Task Plan: Validate and Fix orchestrator-discipline Plugin
Context
The orchestrator-discipline plugin enforces delegation discipline via two PreToolUse hooks and a
rules file. It currently fails claude plugin validate due to an unrecognized rules field in
plugin.json. Three additional gaps exist: directory-targeted Grep bypasses the read-warning
hook, rules/CLAUDE.md loading is unverified, and SKILL.md is missing user-invocable: true.
Source documents:
plan/feature-context-validate-orchestrator-discipline.mdplan/codebase/orchestrator-discipline-patterns.md
Plugin root: plugins/orchestrator-discipline/
Context Manifest
Key Decisions Already Made (Do Not Re-Investigate)
The architecture spec (plan/architect-validate-orchestrator-discipline.md) resolved all four open questions from the feature context doc. These decisions are final — do not reopen them.
Decision 1 — rules/CLAUDE.md delivery mechanism: Move content verbatim to a new file at plugins/orchestrator-discipline/CLAUDE.md (plugin root). This is the same pattern used by plugins/development-harness/CLAUDE.md and plugins/plugin-creator/CLAUDE.md. The rules/ directory and rules/CLAUDE.md are to be deleted after content is confirmed moved. Option B (merge into SKILL.md body) was rejected because SKILL.md content loads on demand rather than passively. Option C (references file) was also rejected.
Decision 2 — Grep directory path coverage: Add isDirectory() + looksLikeDirectory() to the Grep branch in pre-tool-orchestrator-read-warning.cjs. Fire the warning for ALL directory-targeted Grep calls — no allowlist, no pattern heuristic. The hook is non-blocking so the noise cost is acceptable.
Decision 3 — SKILL.md user-invocable field: Add user-invocable: true to SKILL.md frontmatter. Do NOT add a name: field. The absence of name: is intentional and correct — adding it would suppress slash command registration due to a confirmed Claude Code v2.1.23 bug (documented in plugins/plugin-creator/CLAUDE.md, "CRITICAL: Skill Name Field Bug" section).
Decision 4 — Remove commands field from plugin.json: The commands field is the legacy registration path. Both skills and commands currently point to ./skills/orchestrator-discipline. Remove commands; keep only skills. After T1 completes, plugin.json should contain exactly: name, skills, hooks.
Current State of Each File to Be Modified
plugins/orchestrator-discipline/.claude-plugin/plugin.json — current contents (13 lines):
{
"name": "orchestrator-discipline",
"description": "Enforces orchestrator context window discipline...",
"version": "1.3.2",
"author": { "name": "Jamie Nelson", "url": "https://github.com/bitflight-devops" },
"skills": ["./skills/orchestrator-discipline"],
"hooks": "./hooks.json",
"rules": ["./rules"],
"commands": ["./skills/orchestrator-discipline"]
}
Target state after T1: remove "rules" and "commands" lines. Do NOT touch version — auto_sync_manifests.py pre-commit hook handles versioning automatically.
plugins/orchestrator-discipline/rules/CLAUDE.md — 143-line behavioral constraints file. Content covers: Context Window Read Constraints (permitted/prohibited), Delegation Constraints, Investigation Escalation Anti-Pattern (with mermaid diagram), Agent Output Polling Anti-Pattern (with mermaid diagram), Diagnostic Commands list, Epistemic Identity Scope. Key string that must survive in destination: "no exemption categories" (used in T1 and T4 verification).
plugins/orchestrator-discipline/CLAUDE.md — does NOT exist yet. T1 creates it by copying rules/CLAUDE.md content verbatim.
plugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjs — 86-line CommonJS Node.js hook. Current structure:
- Lines 15-16:
SOURCE_FILE_EXTENSIONSregex andTEST_PATH_PATTERNregex constants. - Lines 23-26:
isSourceOrConfigFile(filePath)function — returns true if path matches extension regex OR test path pattern. - Lines 28-58: stdin read loop, JSON parse, tool name dispatch. For
Read, readstoolInput.file_path. ForGrep, readstoolInput.path. Falls through toisSourceOrConfigFile(targetPath)check — this is the gap (directory paths like"src/"return false). - Lines 60-84: Produces
{ hookSpecificOutput: { hookEventName: "PreToolUse", additionalContext: "<orchestrator-read-warning>...</orchestrator-read-warning>" } }and exits 0. - No
require('node:fs')import exists — must be added in T2. - Uses CommonJS (
require()), not ESM (import). Must stay CommonJS.
plugins/orchestrator-discipline/skills/orchestrator-discipline/SKILL.md — 83-line skill. Current frontmatter (lines 1-3):
---
description: Orchestrator context window discipline enforcement. Prevents...
---
Target state after T3: add user-invocable: true on line 3, before closing ---. No name: field. Body content unchanged.
plugins/orchestrator-discipline/hooks.json — does NOT need modification. It wires two PreToolUse hooks: Read|Grep matcher to pre-tool-orchestrator-read-warning.cjs and Bash matcher to pre-tool-diagnostic-command-gate.cjs, both invoked as node "${CLAUDE_PLUGIN_ROOT}/hooks/...".
Hook Architecture — How the Read Warning Hook Works
When Claude Code fires a PreToolUse event for Read or Grep, it pipes a JSON object to the hook's stdin in the form:
{ "tool_name": "Grep", "tool_input": { "path": "src/", "pattern": "foo" } }
The hook reads all stdin, parses the JSON, checks tool_name, extracts targetPath (from tool_input.file_path for Read, from tool_input.path for Grep), then calls isSourceOrConfigFile(targetPath). If that returns true, the hook writes a hookSpecificOutput.additionalContext JSON block. If false, it writes {}. Both paths call process.exit(0) — the hook is strictly non-blocking.
The gap: isSourceOrConfigFile("src/") returns false because neither the extension regex nor the test-path pattern match a bare directory string. The fix adds two new functions (isDirectory and looksLikeDirectory) and OR-extends the shouldWarn condition in the Grep branch only.
The exact logic change to implement (from architect spec):
// Add at top of file alongside existing requires:
const fs = require('node:fs');
// Add two new helper functions after isSourceOrConfigFile():
function isDirectory(targetPath) {
try { return fs.statSync(targetPath).isDirectory(); } catch { return false; }
}
function looksLikeDirectory(targetPath) {
if (!targetPath) return false;
if (targetPath.endsWith('/') || targetPath.endsWith('')) return true;
const lastSegment = targetPath.split(/[\\/]/).filter(Boolean).pop() || '';
return !lastSegment.includes('.');
}
// Change Grep branch from:
shouldWarn = isSourceOrConfigFile(targetPath) || isTestPath(targetPath)
// To:
shouldWarn = isSourceOrConfigFile(targetPath)
|| isTestPath(targetPath)
|| isDirectory(targetPath)
|| looksLikeDirectory(targetPath)
Note: BACKLOG.md has a .md extension — it does NOT match SOURCE_FILE_EXTENSIONS, is NOT a test path, fs.statSync("BACKLOG.md").isDirectory() returns false, and it does NOT pass looksLikeDirectory (it has . in the last segment). So BACKLOG.md will correctly produce {} output.
user-invocable: true Syntax — Confirmed Pattern
From plugins/plugin-creator/skills/skill-creator/SKILL.md lines 1-5 (read directly):
---
description: Guide for creating effective skills...
license: Complete terms in LICENSE.txt
user-invocable: true
---
The field name is user-invocable (hyphenated), value is YAML boolean true (not the string "true"). Place after description:, before the closing ---.
Plugin.json Schema — What Is and Is Not Allowed
Per plugins/plugin-creator/skills/claude-plugins-reference-2026/SKILL.md:32-52 and confirmed in plugins/plugin-creator/CLAUDE.md "Plugin.json Requirements" section:
Valid component path fields: commands, agents, skills, hooks, mcpServers, outputStyles, lspServers.
The field rules is NOT in the schema — this is the direct cause of the Unrecognized key: "rules" validation error.
The commands field is the legacy registration path. Per the CLAUDE.md: "Skills and slash commands are now unified — they are the same system." The canonical registration after the fix is skills in plugin.json plus user-invocable: true in SKILL.md frontmatter.
Plugin Root CLAUDE.md Pattern — Confirmed
Two existing plugins use root-level CLAUDE.md as the mechanism for delivering session-level behavioral context:
plugins/development-harness/CLAUDE.md— confirmed present (directory listing shows it)plugins/plugin-creator/CLAUDE.md— confirmed present (read in full above)
plugins/orchestrator-discipline/ currently has NO root-level CLAUDE.md. The rules/CLAUDE.md at plugins/orchestrator-discipline/rules/CLAUDE.md is the content to be moved.
Validation Tools
Two validators are used in T4:
claude plugin validate plugins/orchestrator-discipline/— official Claude Code CLI validator. Checks: plugin.json schema compliance,namefield present and kebab-case, all paths start with./, referenced files exist. Current failure:✘ Found 1 error: root: Unrecognized key: "rules"../plugins/plugin-creator/scripts/plugin_validator.py plugins/orchestrator-discipline/— repo-internal validator. Invoked asuv run plugins/plugin-creator/scripts/plugin_validator.py plugins/orchestrator-discipline/. Validates frontmatter, skill complexity (token-based), internal links, cross-references. Use--verbosefor detail;--fixfor auto-remediation of known issues (removesname:fields from plugin skills automatically).
Linting tool: uv run prek run --files <path> — runs all configured pre-commit hooks against specific files. Used to confirm markdown formatting compliance.
Critical Constraints for All Tasks
- Do NOT manually edit
versionfields inplugin.jsonor.claude-plugin/marketplace.json—auto_sync_manifests.pypre-commit hook handles versioning on commit. - Do NOT run
git commitorgit add— leave staging for human review. - Do NOT use ESM
importsyntax in the JS hook — file uses CommonJSrequire(). - Do NOT add external npm dependencies to the hook — use only
node:stdlib modules. - Do NOT add a
name:field to SKILL.md — doing so suppresses slash command registration. - Do NOT change the
additionalContextXML content or tag name in the hook. - Conventional commit scope for this plugin:
fix(orchestrator-discipline): ...
File Paths for Implementation
| File | Task | Action |
|---|---|---|
plugins/orchestrator-discipline/.claude-plugin/plugin.json |
T1 | Remove rules and commands fields |
plugins/orchestrator-discipline/CLAUDE.md |
T1 | Create — copy verbatim content from rules/CLAUDE.md |
plugins/orchestrator-discipline/rules/CLAUDE.md |
T1 | Document for deletion (do not delete in T1 — leave for human) |
plugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjs |
T2 | Add fs require + two helper functions + extend Grep shouldWarn |
plugins/orchestrator-discipline/skills/orchestrator-discipline/SKILL.md |
T3 | Add user-invocable: true to frontmatter only |
Reference files (read-only):
plugins/plugin-creator/skills/claude-plugins-reference-2026/SKILL.md— lines 32-52 (schema), lines 148-153 (auto-loading table)plugins/plugin-creator/CLAUDE.md— skill name field bug, plugin.json requirementsplugins/orchestrator-discipline/hooks/pre-tool-diagnostic-command-gate.cjs— do NOT modify (out of scope)plugins/orchestrator-discipline/skills/orchestrator-discipline/references/investigation-escalation.md— do NOT modify (out of scope)
What NOT to Re-Investigate
The following questions were resolved by the architect doc and do NOT need re-investigation:
- Whether
rulesis a valid plugin.json field — it is NOT (confirmed schema gap). - Which delivery mechanism for rules content — plugin root
CLAUDE.mdis chosen (Decision 1). - Whether to keep
commandsfield — remove it (Decision 4). - Whether
user-invocable: trueis needed — yes (Decision 3). - Whether
name:should be added — NO, confirmed bug means omittingname:is correct. - Whether
fs.statSyncis safe in CommonJS Node.js hooks — yes, with try/catch (confirmed pattern). - Whether
BACKLOG.mdwould trigger the new directory detection — confirmed NO (has.mdextension,isDirectory()returns false,looksLikeDirectoryreturns false).
Dependency Graph
T1 (plugin.json fix) ─┐
T2 (Grep dir coverage) ─┼─→ T4 (Full validation suite)
T3 (SKILL.md frontmatter)┘
T1, T2, and T3 are independent and can execute in parallel. T4 depends on T1, T2, and T3 all completing successfully.
Priority Ordering
| Task | Priority | Complexity | Depends On | Parallelize With |
|---|---|---|---|---|
| T1 | High | Low | None | T2, T3 |
| T2 | High | Medium | None | T1, T3 |
| T3 | Medium | Low | None | T1, T2 |
| T4 | High | Medium | T1 + T2 + T3 | None |
Tasks
T1: Fix plugin.json Validation Failure
---
task: T1
title: Fix plugin.json validation failure (BLOCKER)
status: not-started
agent: general-purpose
dependencies: []
priority: 1
complexity: low
accuracy-risk: medium
parallelize-with: [T2, T3]
reason: T1, T2, T3 touch different files — plugin.json, a JS hook, and SKILL.md respectively. No file conflicts.
handoff: "Report: final plugin.json contents, output of `claude plugin validate`, disposition of rules/CLAUDE.md content (merged/moved/kept), and whether `commands` field was removed."
---
Context
plugins/orchestrator-discipline/.claude-plugin/plugin.json currently contains a "rules" key
that is not in the Claude Code plugin.json schema. This causes:
✘ Found 1 error: root: Unrecognized key: "rules"
The schema (per plugins/plugin-creator/skills/claude-plugins-reference-2026/SKILL.md:32-52)
allows only: commands, agents, skills, hooks, mcpServers, outputStyles, lspServers.
The rules field points to ./rules, which contains
plugins/orchestrator-discipline/rules/CLAUDE.md — a 143-line behavioral constraints file. The
plugin also declares both "skills" and "commands" pointing to the same
./skills/orchestrator-discipline path, which may cause a double-registration issue surfaced after
the rules field is removed.
No other plugin in this repository uses a rules field. Alternate patterns for surfacing rules
content: plugin root CLAUDE.md, inline in SKILL.md, or skills/.../references/ file.
Objective
Remove the invalid rules field from plugin.json, preserve rules/CLAUDE.md content via a
verified loading mechanism, and make claude plugin validate plugins/orchestrator-discipline/ exit
0 with no errors.
Required Inputs
plugins/orchestrator-discipline/.claude-plugin/plugin.json— current manifestplugins/plugin-creator/skills/claude-plugins-reference-2026/SKILL.md— authoritative schema reference (lines 32-52 for component path fields, lines 148-153 for auto-loading table)plugins/orchestrator-discipline/rules/CLAUDE.md— content to be preservedplugins/orchestrator-discipline/skills/orchestrator-discipline/SKILL.md— may need update if content is merged hereplugins/plugin-creator/CLAUDE.md— skill name field bug notes (affects whethercommandsfield is needed)- Assumption:
claudeCLI is available on PATH. Confirm withwhich claude.
Requirements
- Remove
"rules": ["./rules"]fromplugin.json. - Move the content of
./rules/CLAUDE.mdtoplugins/orchestrator-discipline/CLAUDE.md(plugin root). This is the confirmed pattern used byplugins/development-harness/andplugins/plugin-creator/— root-levelCLAUDE.mdis auto-loaded as plugin documentation context. Do not choose option B (SKILL.md body) or option C (references/rules.md); the architecture spec (Decision 1) has already evaluated and rejected those options. - Implement whichever option from requirement 2 is chosen. Do NOT delete
rules/CLAUDE.mdcontent without confirming it exists in the destination. - Assess whether
"commands": ["./skills/orchestrator-discipline"]should be removed. Readplugins/plugin-creator/CLAUDE.mdto confirm whethercommands+skillspointing to the same path causes double-registration. Removecommandsif it is redundant and the schema recommendsskillsalone. - Run
claude plugin validate plugins/orchestrator-discipline/and verify exit code is 0.
Constraints
- Do NOT change the behavioral semantics of the hooks (what they warn about, what they allow).
- Do NOT modify
hooks/pre-tool-orchestrator-read-warning.cjsorhooks/pre-tool-diagnostic-command-gate.cjs— those are T2's scope. - Do NOT modify
skills/orchestrator-discipline/SKILL.mdfrontmatter fields — that is T3's scope. You may append content to the body if merging rules, but do not touch frontmatter. - Do NOT manually bump the version in
plugin.json— theauto_sync_manifests.pypre-commit hook handles versioning automatically on commit. - Do NOT run
git commit— leave staging for the human to review.
Expected Outputs
plugins/orchestrator-discipline/.claude-plugin/plugin.json— modified (norulesfield, and possibly nocommandsfield if determined redundant)- One of:
plugins/orchestrator-discipline/CLAUDE.mdcreated (if option A chosen), ORplugins/orchestrator-discipline/skills/orchestrator-discipline/SKILL.mdbody updated (if option B chosen), ORplugins/orchestrator-discipline/skills/orchestrator-discipline/references/rules.mdcreated (if option C chosen)
- If
rules/CLAUDE.mdis superseded, document that it can be removed (but do NOT delete it in this task — leave deletion decision to human review).
Acceptance Criteria
claude plugin validate plugins/orchestrator-discipline/exits 0 with no errors printed.plugins/orchestrator-discipline/.claude-plugin/plugin.jsoncontains noruleskey when inspected withcat.- The full text of the original
rules/CLAUDE.mdis reachable via one of the approved mechanisms (plugin root CLAUDE.md, SKILL.md body, or references/rules.md). Verify by reading the destination file and confirming the "no exemption categories" and "falsifiable test" language is present. - If
commandsfield was removed:plugin.jsoncontains nocommandskey. If kept: document why in handoff. node -e "JSON.parse(require('fs').readFileSync('plugins/orchestrator-discipline/.claude-plugin/plugin.json','utf8'))"exits 0 (valid JSON).
Verification Steps
claude plugin validate plugins/orchestrator-discipline/— confirm output shows no errors and exit code is 0.cat plugins/orchestrator-discipline/.claude-plugin/plugin.json— visually confirm noruleskey present.- Read the destination file for
rules/CLAUDE.mdcontent. Grep for the string "no exemption categories" to confirm content survived. node -e "JSON.parse(require('fs').readFileSync('plugins/orchestrator-discipline/.claude-plugin/plugin.json','utf8'))"— confirm valid JSON.
CoVe Checks
Key claims to verify:
- Claim:
rulesis not in the plugin.json schema. - Claim: Plugin root
CLAUDE.mdis auto-loaded as plugin documentation context (per how other plugins deliver rule content). - Claim:
commandsandskillspointing to the same path may cause double-registration.
Verification questions:
- Does
plugins/plugin-creator/skills/claude-plugins-reference-2026/SKILL.mdlines 32-52 listrulesas a valid component path field? (Expected: No.) - Does
plugins/plugin-creator/skills/claude-plugins-reference-2026/SKILL.mdlines 148-153 (default directory auto-loading table) include arules/or rootCLAUDE.mdrow? (Determines which delivery mechanism is verified.) - Does
plugins/plugin-creator/CLAUDE.mddocument whethercommands+skillsboth pointing to the same directory path causes a schema error or harmless redundancy?
Evidence to collect:
- Read lines 32-52 and 148-153 of
plugins/plugin-creator/skills/claude-plugins-reference-2026/SKILL.md. - Read
plugins/plugin-creator/CLAUDE.mdfor the skill name field bug andcommandsvsskillsguidance. - Read
plugins/development-harness/CLAUDE.mdorplugins/agent-orchestration/CLAUDE.mdas an example of plugin rootCLAUDE.mdusage (confirm the pattern exists).
Revision rule:
If any CoVe check reveals the schema allows rules, or that root CLAUDE.md is NOT auto-loaded,
revise the delivery mechanism choice and state what changed in the handoff.
T2: Fix Grep Directory Path Coverage in Hook
---
task: T2
title: Fix Grep directory path coverage in pre-tool-orchestrator-read-warning.cjs
status: not-started
agent: general-purpose
dependencies: []
priority: 1
complexity: medium
accuracy-risk: medium
parallelize-with: [T1, T3]
reason: T2 modifies only the JS hook file. T1 touches plugin.json and potentially rules/CLAUDE.md. T3 touches SKILL.md. No overlap.
handoff: "Report: the exact code change made (diff or before/after), output of `node --check`, test evidence for all four Grep scenarios in acceptance criteria, and whether BACKLOG.md Grep calls were determined to trigger or not (with rationale documented)."
---
Context
plugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjs (86 lines) fires a
<orchestrator-read-warning> advisory for Read and Grep tool calls when the target path has a
source file extension. The current gate function:
const SOURCE_FILE_EXTENSIONS =
/\.(py|toml|yaml|yml|js|ts|jsx|tsx|json|cfg|ini|env|sh|bash|go|rs|rb|java|c|cpp|h|hpp)$/i;
function isSourceOrConfigFile(filePath) {
return SOURCE_FILE_EXTENSIONS.test(filePath) || TEST_PATH_PATTERN.test(filePath);
}
When an orchestrator calls Grep(pattern="class.*Service", path="src/"), targetPath is "src/".
isSourceOrConfigFile("src/") returns false — no extension match, no test path match — and the
hook silently passes. This is the primary failure mode: directory-targeted Grep by an orchestrator
escapes the warning.
The codebase patterns doc (plan/codebase/orchestrator-discipline-patterns.md, section 5.2)
provides two detection approaches: fs.statSync (filesystem check) and pattern heuristics
(trailing slash or no dot in last segment).
The hook must NOT crash when path is absent from tool_input (current code already guards with
toolInput.path || '').
Objective
Extend the hook so that Grep calls where path is a directory (detected via heuristic or
fs.statSync) also trigger the <orchestrator-read-warning> advisory, without introducing
crashes or false-positive noise on legitimate markdown/plan-file searches.
Required Inputs
plugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjs— full file to read before editingplan/codebase/orchestrator-discipline-patterns.mdsections 4 and 5 — gap analysis and detection optionsplan/feature-context-validate-orchestrator-discipline.mdQ3 (lines 183-194) — options A–D for directory detection scope
Requirements
- Read the full current hook file before making any changes.
- Add directory detection to the
Greppath-checking logic. Implement Option A from Q3 (fire for any directory path) combined with a heuristic guard: treat a path as a directory iffs.statSync(path).isDirectory()returns true, OR if the path ends with/, OR if the last segment of the path contains no.character. Wrapfs.statSyncin a try/catch that returns false on any error (path does not exist or is inaccessible). BACKLOG.mdis a legitimate orchestrator read target (tracking file, not source code). Grep calls withpath: "BACKLOG.md"must NOT trigger the hook. Confirm thatBACKLOG.mddoes not match the new directory detection logic (it will not — it has a.mdextension andisDirectory()will return false). Document in a code comment that.mdfiles are excluded by the extension check already.- Do not alter the existing behavior for
Readcalls or forGrepcalls with source file extension paths — only extend theGrepdirectory detection branch. - Preserve the existing error-safety pattern: if
pathis absent or empty, the hook passes through silently (return{}).
Constraints
- Do NOT change the
additionalContextmessage content or XML tag name — only the trigger logic. - Do NOT change how the hook handles
Readtool calls. - Do NOT add any
console.errororconsole.warncalls — the hook writes only to stdout. - Do NOT use ES module syntax (
import) — the file uses CommonJSrequire(). - Do NOT add external npm dependencies — use only
node:stdlib modules (node:fs,node:path). - The hook must still exit via
process.exit(0)in all code paths. node --checkmust pass on the modified file.
Expected Outputs
plugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjs— modified with directory detection logic added to the Grep branch
Acceptance Criteria
node --check plugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjsexits 0 (no syntax errors).- A test script that simulates
Grep({ pattern: "foo", path: "src/" })via stdin produces JSON output containing"additionalContext". (Simulate by piping JSON to the script viaecho '{"tool_name":"Grep","tool_input":{"path":"src/","pattern":"foo"}}' | node plugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjs.) - A test with
path: "plugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjs"(an existing.jsfile) produces"additionalContext"(existing behavior preserved). - A test with
path: "BACKLOG.md"produces{}(no warning — markdown file excluded by extension check; not a source file extension, not a directory). - A test with
path: ""(empty string) produces{}without crashing.
Verification Steps
node --check plugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjsecho '{"tool_name":"Grep","tool_input":{"path":"src/","pattern":"foo"}}' | node plugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjs— output must containadditionalContext.echo '{"tool_name":"Grep","tool_input":{"path":"plugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjs","pattern":"foo"}}' | node plugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjs— output must containadditionalContext.echo '{"tool_name":"Grep","tool_input":{"path":"BACKLOG.md","pattern":"foo"}}' | node plugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjs— output must be{}.echo '{"tool_name":"Grep","tool_input":{"path":"","pattern":"foo"}}' | node plugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjs— output must be{}and script must not throw.
CoVe Checks
Key claims to verify:
- Claim:
tool_input.pathis the correct field name for the Grep path argument in the hook's stdin JSON. - Claim:
fs.statSync(path).isDirectory()with a try/catch is safe to call from a Node.js hook in the repo's CommonJS +node:fsconvention. - Claim:
BACKLOG.mdwill not trigger the new directory detection logic.
Verification questions:
- Does the current hook file read Grep path as
toolInput.path(nottoolInput.file_pathor another field)? Readplugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjslines 48-51 to confirm. - Does
BACKLOG.mdend with/? Does it have no.in the last segment? (Both are false — it ends in.md.) Confirm that neither heuristic matches it andfs.statSync("BACKLOG.md").isDirectory()returns false (it is a file). - Does any other hook in this repo use
fs.statSyncfromnode:fs? If not, is there a documented reason to avoid it? Checkplugins/*/hooks/*.jsfor filesystem access patterns.
Evidence to collect:
- Read lines 42-60 of
plugins/orchestrator-discipline/hooks/pre-tool-orchestrator-read-warning.cjsto confirm field names. - Run verification step 4 (BACKLOG.md test) and record the output.
- Search
plugins/*/hooks/*.jsforstatSyncto confirm or deny prior usage.
Revision rule:
If tool_input.path is not the correct field name, correct the field access in the implementation
and state the actual field name in the handoff. If fs.statSync is found to be inappropriate
(e.g., hook runs before the path exists on disk), fall back to the heuristic-only approach (Option
B from section 5.2) and document why.
T3: Fix SKILL.md Frontmatter and Linting
---
task: T3
title: Fix SKILL.md frontmatter user-invocable field and run linting
status: not-started
agent: general-purpose
dependencies: []
priority: 2
complexity: low
accuracy-risk: medium
parallelize-with: [T1, T2]
reason: T3 touches only SKILL.md frontmatter. T1 touches plugin.json and rules/CLAUDE.md. T2 touches the JS hook. No overlap.
handoff: "Report: final frontmatter of SKILL.md (full YAML block), output of `uv run prek run --files`, and rationale for the user-invocable value chosen."
---
Context
plugins/orchestrator-discipline/skills/orchestrator-discipline/SKILL.md (83 lines) has minimal
frontmatter:
---
description: "..."
---
Two questions are unresolved per the feature context doc:
- Q2: Should
user-invocable: truebe added? (Thecommandsfield inplugin.jsonpoints to this skills directory, which may register it as a slash command. Theplugin-creatorCLAUDE.md notes that aname:field causes skills NOT to appear as slash commands — the current SKILL.md has noname:field, which is correct.) - Q4: The
commandsfield inplugin.jsondeclares the same path asskills. After T1 resolves thecommandsredundancy question, T3 must ensure SKILL.md frontmatter is correct for whichever registration mechanism remains.
Per plugins/plugin-creator/CLAUDE.md (skill name field bug section, per feature context doc line
282): user-invocable: true must be set for the skill to appear in the slash command menu.
Objective
Determine the correct value for user-invocable in the SKILL.md frontmatter, add the field, and
confirm the file passes uv run prek run --files.
Required Inputs
plugins/orchestrator-discipline/skills/orchestrator-discipline/SKILL.md— full file to read before editingplugins/plugin-creator/CLAUDE.md— skill name field bug section (determines whetheruser-invocable: trueis needed and whethername:field must be absent)plugins/plugin-creator/skills/claude-plugins-reference-2026/SKILL.md— SKILL.md frontmatter field reference (what fields are valid)- One working example SKILL.md from another plugin that uses
user-invocable: true— confirm the field name and value format (true vs "true" vs boolean) - T1 handoff (if available): whether
commandsfield was removed fromplugin.json. Ifcommandswas removed,user-invocable: trueis the only registration mechanism — it becomes required, not optional.
Requirements
- Read the full current SKILL.md before editing.
- Read
plugins/plugin-creator/CLAUDE.mdto find the definitive answer on whetheruser-invocable: trueis required for slash command registration whenname:is absent. - Find one existing SKILL.md in this repo that uses
user-invocable: trueand confirm the exact YAML syntax (field name, value format). - Add
user-invocable: trueto the frontmatter if confirmed required. Place it afterdescription:and before any other fields, consistent with the example found in requirement 3. - Do NOT add a
name:field — the feature context doc (line 282) explicitly states the absence ofname:is correct. - Run
uv run prek run --files plugins/orchestrator-discipline/skills/orchestrator-discipline/SKILL.mdand resolve any linting findings.
Constraints
- Do NOT change the body content of SKILL.md — only frontmatter.
- Do NOT add
name:to the frontmatter. - Do NOT change the
description:value. - If T1 has not completed, proceed with
user-invocable: trueas the default choice (the feature context doc states manual invocation is a desired use case per scenario 6, line 136-139). - Do NOT run
git commit.
Expected Outputs
plugins/orchestrator-discipline/skills/orchestrator-discipline/SKILL.md— modified frontmatter withuser-invocable: trueadded (and any linting fixes applied)
Acceptance Criteria
- SKILL.md frontmatter contains
user-invocable: true(exact YAML boolean, not string"true"). - SKILL.md frontmatter does NOT contain a
name:field. uv run prek run --files plugins/orchestrator-discipline/skills/orchestrator-discipline/SKILL.mdexits 0 with no errors.- SKILL.md body content (lines after the closing
---) is unchanged from the original.
Verification Steps
- Read the modified SKILL.md and print the frontmatter block (lines 1 to closing
---). Confirmuser-invocable: trueis present andname:is absent. uv run prek run --files plugins/orchestrator-discipline/skills/orchestrator-discipline/SKILL.md— record full output; confirm exit 0.grep -n "user-invocable" plugins/orchestrator-discipline/skills/orchestrator-discipline/SKILL.md— confirm line number and value.grep -n "^name:" plugins/orchestrator-discipline/skills/orchestrator-discipline/SKILL.md— confirm no output (field absent).
CoVe Checks
Key claims to verify:
- Claim:
user-invocable: true(YAML boolean) is the correct field name and value format for slash command registration in plugin SKILL.md files. - Claim: The absence of a
name:field is intentional and correct (not a missing required field).
Verification questions:
- Does any existing SKILL.md in
plugins/*/skills/useuser-invocable: true? Find one and read its frontmatter to confirm exact syntax. (Grep(pattern="user-invocable", path="plugins/")) - Does
plugins/plugin-creator/CLAUDE.mdor the plugin-creator skill reference explicitly state thatname:in SKILL.md frontmatter prevents slash command registration? - Does
plugins/plugin-creator/skills/claude-plugins-reference-2026/SKILL.mdlistuser-invocableas a valid frontmatter field for skills?
Evidence to collect:
- Run
Grep(pattern="user-invocable", path="plugins/")and read one matching file to confirm field syntax. - Read the relevant section of
plugins/plugin-creator/CLAUDE.mdand cite the exact line.
Revision rule:
If user-invocable is not found in any existing SKILL.md, the field name may be wrong. Check the
plugin-creator reference for the correct field name before writing. State the finding and actual
field name in the handoff.
SYNC CHECKPOINT 1: T1 + T2 + T3 Convergence
Convergence point: All three of T1, T2, T3 must complete before T4 starts.
Quality gates:
- T1:
claude plugin validate plugins/orchestrator-discipline/exits 0 - T1:
plugin.jsoncontains noruleskey;rules/CLAUDE.mdcontent preserved in verified destination - T2: All 5 verification step commands for T2 produce expected outputs
- T2:
node --checkpasses on the modified hook file - T3:
user-invocable: truepresent in SKILL.md frontmatter,name:absent - T3:
uv run prek run --filespasses on SKILL.md
Reflection questions:
- Did T1 remove the
commandsfield? If so, does T3's frontmatter still correctly register the skill? - Did T2 introduce any new import (
require) statements? If so, does T1's updatedplugin.jsonneed any adjustment? - Are there any emergent conflicts between the three parallel fixes?
Proceed to T4 only after all T1 + T2 + T3 acceptance criteria are confirmed met.
T4: Full Validation Suite
---
task: T4
title: Full validation suite — end-to-end verification of all orchestrator-discipline fixes
status: not-started
agent: general-purpose
dependencies: [T1, T2, T3]
priority: 1
complexity: medium
accuracy-risk: low
parallelize-with: []
reason: T4 is the convergence task; it depends on all three prior tasks completing. No parallelism possible.
handoff: "Report: output of each validation command (copy-pasted, not summarized), pass/fail status for each acceptance criterion, any pre-existing issues found in plugin_validator.py output, and the documented test procedure for hook behavior."
---
Context
T1, T2, and T3 have each addressed one gap in the orchestrator-discipline plugin:
- T1: Removed invalid
rulesfield fromplugin.json - T2: Extended Grep directory detection in
pre-tool-orchestrator-read-warning.cjs - T3: Added
user-invocable: trueto SKILL.md frontmatter
T4 runs the complete validation suite across all plugin files to confirm the fixes integrate correctly and no regressions exist.
Two validators exist for this repo:
claude plugin validate plugins/orchestrator-discipline/— official Claude Code CLI validator./plugins/plugin-creator/scripts/plugin_validator.py plugins/orchestrator-discipline/— repo internal validator script
Both must be run. Failures in plugin_validator.py must be documented; pre-existing failures
(present before T1/T2/T3 changes) should be noted as pre-existing and added to the backlog if not
fixed.
Objective
Confirm that all fixes from T1, T2, and T3 integrate correctly, both validators pass (or known
pre-existing failures are documented), all modified files pass prek linting, and the hook
behavior is verified end-to-end via the five test commands defined in T2's verification steps.
Required Inputs
- All modified plugin files (outputs from T1, T2, T3)
- T1, T2, T3 handoff reports (review before starting)
plugins/plugin-creator/scripts/plugin_validator.py— internal validatoruv run prek run— linting tool
Requirements
- Verify T1, T2, and T3 handoff reports confirm all their acceptance criteria are met before proceeding.
- Run
claude plugin validate plugins/orchestrator-discipline/and capture full output. - Run
./plugins/plugin-creator/scripts/plugin_validator.py plugins/orchestrator-discipline/and capture full output. - Collect the list of all files modified across T1, T2, T3 and run
uv run prek run --files <each-modified-file>on each one. - Re-run the five hook behavior test commands from T2's verification steps to confirm hook behavior end-to-end (not just the modified logic in isolation).
- Document the test procedure for hook behavior as a short code block that can be re-run by a human reviewer.
- If
plugin_validator.pyreports errors not related to the T1/T2/T3 changes (pre-existing issues), document each one with file and line reference, and add a backlog item for each.
Constraints
- Do NOT fix issues discovered in step 7 in this task — document them only. Scope boundaries apply.
- Do NOT run
git commitorgit add. - Do NOT modify any files unless a T1/T2/T3 fix was not correctly applied (in which case, apply only the missing part of the fix with a note in the handoff).
Expected Outputs
- A validation report (written to stdout / handoff) containing:
- Full output of
claude plugin validate(copy-pasted verbatim)
- Full output of
…(truncated)