all-for-claudecode 2.8.0 → 2.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Automated pipeline for Claude Code — spec → plan → implement → review → clean",
9
- "version": "2.8.0"
9
+ "version": "2.8.2"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "afc",
14
14
  "source": "./",
15
15
  "description": "Automated pipeline for Claude Code. Automates the full development cycle: spec → plan → implement → review → clean.",
16
- "version": "2.8.0",
16
+ "version": "2.8.2",
17
17
  "category": "automation",
18
18
  "tags": ["pipeline", "automation", "spec", "plan", "implement", "review", "critic-loop"]
19
19
  }
@@ -1,12 +1,11 @@
1
1
  {
2
2
  "name": "afc",
3
- "version": "2.8.0",
3
+ "version": "2.8.2",
4
4
  "description": "Automated pipeline for Claude Code. Automates the full development cycle: spec → plan → implement → review → clean.",
5
5
  "author": { "name": "jhlee0409", "email": "relee6203@gmail.com" },
6
6
  "homepage": "https://github.com/jhlee0409/all-for-claudecode",
7
7
  "repository": "https://github.com/jhlee0409/all-for-claudecode",
8
8
  "license": "MIT",
9
9
  "keywords": ["pipeline", "automation", "spec", "plan", "implement", "review", "critic-loop"],
10
- "commands": "./commands/",
11
- "hooks": "./hooks/hooks.json"
10
+ "commands": "./commands/"
12
11
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: afc:doctor
3
- description: "Diagnose project health and plugin setup — use when the user asks for a health check, wants to diagnose project issues, or verify plugin installation"
3
+ description: "Diagnose afc plugin setup and configuration — use when the user asks for a health check, wants to verify plugin installation, or check if afc is properly configured"
4
4
  argument-hint: "[--verbose]"
5
5
  allowed-tools:
6
6
  - Read
@@ -10,10 +10,13 @@ allowed-tools:
10
10
  model: haiku
11
11
  ---
12
12
 
13
- # /afc:doctor — Project Health Diagnosis
13
+ # /afc:doctor — Plugin Setup Diagnosis
14
14
 
15
- > Runs a comprehensive health check on the all-for-claudecode setup for the current project.
15
+ > Checks whether the all-for-claudecode plugin is correctly installed and configured in the current project.
16
+ > Like `brew doctor` or `flutter doctor` — verifies the **tool's setup**, NOT the project's code quality.
16
17
  > Read-only — never modifies files. Reports issues with actionable fix commands.
18
+ >
19
+ > **IMPORTANT: Do NOT analyze project source code, architecture, or code quality. Only check afc plugin configuration, hooks, state, and environment as defined in the check tables below.**
17
20
 
18
21
  ## Arguments
19
22
 
@@ -32,136 +35,21 @@ Each failing check includes a **Fix:** line with the exact command to resolve it
32
35
 
33
36
  ---
34
37
 
35
- ## Checks
36
-
37
- Run ALL checks regardless of earlier failures. Do not short-circuit.
38
-
39
- ### Category 1: Environment
40
-
41
- | Check | How | Pass | Fail |
42
- |-------|-----|------|------|
43
- | git installed | `which git` | git found in PATH | Fix: install git |
44
- | jq installed | `which jq` | jq found in PATH | ⚠ Warning: jq not found. Hook scripts will use grep/sed fallback (slower, less reliable). Fix: `brew install jq` or `apt install jq` |
45
-
46
- ### Category 2: Project Config
47
-
48
- | Check | How | Pass | Fail |
49
- |-------|-----|------|------|
50
- | Config file exists | Read `.claude/afc.config.md` | File exists | Fix: run `/afc:init` |
51
- | Required sections present | Grep for `## CI Commands`, `## Architecture`, `## Code Style` | All 3 sections found | Fix: add missing section to `.claude/afc.config.md` or re-run `/afc:init` |
52
- | Gate command defined | Grep for `gate:` inside `## CI Commands` section | `gate:` field found | Fix: add `gate:` field to `## CI Commands` section |
53
- | CI command runnable | Extract CI command from config, run it | Exits 0 | ⚠ Warning: CI command failed. Check `{config.ci}` in afc.config.md |
54
- | Gate command runnable | Extract gate command from config, run it | Exits 0 | ⚠ Warning: gate command failed. Check `{config.gate}` in afc.config.md |
55
-
56
- ### Category 3: CLAUDE.md Integration
57
-
58
- | Check | How | Pass | Fail |
59
- |-------|-----|------|------|
60
- | Global CLAUDE.md exists | Read `~/.claude/CLAUDE.md` | File exists | ⚠ Warning: no global CLAUDE.md. all-for-claudecode skills won't auto-trigger from intent. Fix: run `/afc:init` |
61
- | all-for-claudecode block present | Grep for `<!-- AFC:START -->` and `<!-- AFC:END -->` in `~/.claude/CLAUDE.md` | Both markers found | Fix: run `/afc:init` to inject all-for-claudecode block |
62
- | all-for-claudecode block version | Extract version from `<!-- AFC:VERSION:X.Y.Z -->` in CLAUDE.md. Read `${CLAUDE_PLUGIN_ROOT}/package.json` (`.version`) to get the actual plugin version. Compare the two. | Block version = plugin version | ⚠ Warning: all-for-claudecode block is outdated (found {block_version}, current {plugin_version}). Fix: run `/afc:init` to update |
63
- | No conflicting routing | Grep for conflicting agent patterns (`executor`, `deep-executor`, `debugger`, `code-reviewer`) outside all-for-claudecode block that could intercept afc intents | No conflicts or conflicts are inside other tool blocks | ⚠ Warning: found agent routing that may conflict with afc skills. Review `~/.claude/CLAUDE.md` |
64
-
65
- ### Category 4: Legacy Migration (v1.x → v2.0)
66
-
67
- > Detects leftover artifacts from the old `selfish-pipeline` (v1.x) plugin. If none found, print `✓ No legacy artifacts` and skip this category.
68
-
69
- | Check | How | Pass | Fail |
70
- |-------|-----|------|------|
71
- | No legacy CLAUDE.md block | Grep `~/.claude/CLAUDE.md` for `<!-- SELFISH:START -->` | Marker not found | ⚠ Warning: legacy `SELFISH:START` block found in `~/.claude/CLAUDE.md`. Fix: run `/afc:init` (will replace with all-for-claudecode block) |
72
- | No legacy config file | Check `.claude/selfish.config.md` | File does not exist | ⚠ Warning: legacy config `.claude/selfish.config.md` found. Fix: `mv .claude/selfish.config.md .claude/afc.config.md` |
73
- | No legacy state files | Glob `.claude/.selfish-*` | No files found | ⚠ Warning: legacy state files `.claude/.selfish-*` found. Fix: `cd .claude && for f in .selfish-*; do mv "$f" "${f/.selfish-/.afc-}"; done` |
74
- | No legacy artifact dir | Check `.claude/selfish/` directory | Directory does not exist | ⚠ Warning: legacy artifact directory `.claude/selfish/` found. Fix: `mv .claude/selfish .claude/afc` |
75
- | No legacy git tags | `git tag -l 'selfish/pre-*' 'selfish/phase-*'` | No tags found | ⚠ Warning: legacy git tags found. Fix: `git tag -l 'selfish/*' \| xargs git tag -d` |
76
- | No legacy plugin installed | Check if `selfish@selfish-pipeline` appears in installed plugins (grep settings.json for `selfish-pipeline`) | Not found | ⚠ Warning: old `selfish-pipeline` plugin still installed. Fix: `claude plugin uninstall selfish@selfish-pipeline && claude plugin marketplace remove jhlee0409/selfish-pipeline` |
77
-
78
- ### Category 5: Pipeline State
79
-
80
- | Check | How | Pass | Fail |
81
- |-------|-----|------|------|
82
- | No stale pipeline state | Check `.claude/.afc-state.json` via `afc-pipeline-manage.sh status` | File does not exist (no active pipeline) | ⚠ Warning: stale pipeline state found (feature: {name}, phase: {phase}). This may block normal operations. Fix: `"${CLAUDE_PLUGIN_ROOT}/scripts/afc-pipeline-manage.sh" end --force` or run `/afc:resume` |
83
- | No orphaned artifacts | Glob `.claude/afc/specs/*/spec.md` | No specs directories, or all are from active pipeline | ⚠ Warning: orphaned `.claude/afc/specs/{name}/` found. Left over from a previous pipeline. Fix: `rm -rf .claude/afc/specs/{name}/` |
84
- | No lingering safety tags | `git tag -l 'afc/pre-*'` | No tags, or tags match active pipeline | ⚠ Warning: lingering safety tag `afc/pre-{x}` found. Fix: `git tag -d afc/pre-{x}` |
85
- | Checkpoint state | Read `.claude/afc/memory/checkpoint.md` if exists | No checkpoint (clean), or checkpoint is from current session | ⚠ Warning: stale checkpoint from {date}. Fix: run `/afc:resume` to continue or delete `.claude/afc/memory/checkpoint.md` |
86
-
87
- ### Category 6: Memory Health
88
-
89
- > Checks `.claude/afc/memory/` subdirectory sizes and agent memory file sizes. If memory directory does not exist, print `✓ No memory directory` and skip this category.
90
-
91
- | Check | How | Pass | Fail |
92
- |-------|-----|------|------|
93
- | quality-history count | Count files in `.claude/afc/memory/quality-history/` | ≤ 30 files | ⚠ Warning: {N} files in quality-history/ (threshold: 30). Oldest files should be pruned. Fix: run a pipeline with `/afc:auto` (Clean phase auto-prunes) or manually delete oldest files |
94
- | reviews count | Count files in `.claude/afc/memory/reviews/` | ≤ 40 files | ⚠ Warning: {N} files in reviews/ (threshold: 40). Fix: run a pipeline or manually delete oldest files |
95
- | retrospectives count | Count files in `.claude/afc/memory/retrospectives/` | ≤ 30 files | ⚠ Warning: {N} files in retrospectives/ (threshold: 30). Fix: run a pipeline or manually delete oldest files |
96
- | research count | Count files in `.claude/afc/memory/research/` | ≤ 50 files | ⚠ Warning: {N} files in research/ (threshold: 50). Fix: run a pipeline or manually delete oldest files |
97
- | decisions count | Count files in `.claude/afc/memory/decisions/` | ≤ 60 files | ⚠ Warning: {N} files in decisions/ (threshold: 60). Fix: run a pipeline or manually delete oldest files |
98
- | afc-architect MEMORY.md size | Count lines in `.claude/agent-memory/afc-architect/MEMORY.md` (if exists) | ≤ 100 lines | ⚠ Warning: afc-architect MEMORY.md is {N} lines (limit: 100). Fix: invoke `/afc:architect` to trigger self-pruning, or manually edit the file |
99
- | afc-security MEMORY.md size | Count lines in `.claude/agent-memory/afc-security/MEMORY.md` (if exists) | ≤ 100 lines | ⚠ Warning: afc-security MEMORY.md is {N} lines (limit: 100). Fix: invoke `/afc:security` to trigger self-pruning, or manually edit the file |
100
-
101
- ### Category 7: Hook Health
102
-
103
- | Check | How | Pass | Fail |
104
- |-------|-----|------|------|
105
- | hooks.json valid | Parse plugin's hooks.json with jq (or manual validation) | Valid JSON with `hooks` key | ✗ Fix: reinstall plugin — `claude plugin install afc@all-for-claudecode` |
106
- | All scripts exist | For each script referenced in hooks.json, check file exists | All scripts found | ✗ Fix: reinstall plugin |
107
- | Scripts executable | Check execute permission on each script in plugin's scripts/ | All have +x | Fix: `chmod +x` on the missing scripts, or reinstall plugin |
108
-
109
- ### Category 8: Version Sync (development only)
110
-
111
- > Only run if current directory is the all-for-claudecode source repo (check for `package.json` with `"name": "all-for-claudecode"`).
112
-
113
- | Check | How | Pass | Fail |
114
- |-------|-----|------|------|
115
- | Version triple match | Compare versions in `package.json` (`.version`), `.claude-plugin/plugin.json` (`.version`), `.claude-plugin/marketplace.json` (`.metadata.version` and `.plugins[0].version`) | All identical | ✗ Fix: update mismatched files to the same version |
116
- | Cache in sync | Compare `commands/auto.md` content between source and `~/.claude/plugins/cache/all-for-claudecode/afc/{version}/commands/auto.md` | Content matches | ⚠ Warning: plugin cache is stale. Fix: copy source files to cache directory |
117
-
118
- ### Category 9: Command Definitions (development only)
119
-
120
- > Only run if current directory is the all-for-claudecode source repo (same condition as Category 8).
121
-
122
- | Check | How | Pass | Fail |
123
- |-------|-----|------|------|
124
- | Frontmatter exists | Each `commands/*.md` file has opening and closing `---` block | All files have frontmatter | ✗ Fix: add YAML frontmatter block to `commands/{file}.md` |
125
- | Required fields | Each command frontmatter contains `name:` and `description:` | All files have both fields | ✗ Fix: add missing `name:` or `description:` to `commands/{file}.md` |
126
- | Name-filename match | `name:` value follows `afc:{filename}` pattern (e.g. `auto.md` → `name: afc:auto`) | All names match filenames | ✗ Fix: rename `name:` field in `commands/{file}.md` to `afc:{filename}` |
127
- | Fork-agent reference | Commands with `context: fork` and `agent:` field reference a file that exists in `agents/` (e.g. `agent: afc-architect` → `agents/afc-architect.md` exists) | All agent references resolve | ✗ Fix: create missing agent file `agents/{name}.md` or fix `agent:` field in `commands/{file}.md` |
128
-
129
- ### Category 10: Agent Definitions (development only)
130
-
131
- > Only run if current directory is the all-for-claudecode source repo (same condition as Category 8).
132
-
133
- | Check | How | Pass | Fail |
134
- |-------|-----|------|------|
135
- | Frontmatter exists | Each `agents/*.md` file has opening and closing `---` block | All files have frontmatter | ✗ Fix: add YAML frontmatter block to `agents/{file}.md` |
136
- | Required fields | Each agent frontmatter contains `name:`, `description:`, and `model:` | All files have all 3 fields | ✗ Fix: add missing field to `agents/{file}.md` |
137
- | Name-filename match | `name:` value equals the filename without extension (e.g. `afc-architect.md` → `name: afc-architect`) | All names match filenames | ✗ Fix: rename `name:` field in `agents/{file}.md` to match filename |
138
- | Expert memory | All 8 expert consultation agents (`afc-backend-expert`, `afc-infra-expert`, `afc-pm-expert`, `afc-design-expert`, `afc-marketing-expert`, `afc-legal-expert`, `afc-appsec-expert`, `afc-tech-advisor`) have `memory: project` | All experts have memory field | ✗ Fix: add `memory: project` to `agents/{name}.md` frontmatter |
139
- | Worker maxTurns | `afc-impl-worker` and `afc-pr-analyst` have `maxTurns:` field | Both workers have maxTurns | ✗ Fix: add `maxTurns:` to `agents/{name}.md` frontmatter |
140
-
141
- ### Category 11: Doc References (development only)
142
-
143
- > Only run if current directory is the all-for-claudecode source repo (same condition as Category 8).
144
-
145
- | Check | How | Pass | Fail |
146
- |-------|-----|------|------|
147
- | Referenced docs exist | Scan commands and agents for file references to `docs/` (e.g. `docs/critic-loop-rules.md`, `docs/phase-gate-protocol.md`). Each referenced file must exist. | All referenced docs found | ✗ Fix: create missing `docs/{file}.md` or fix the reference |
148
- | Domain adapters exist | `docs/domain-adapters/` directory contains at least one `.md` file | ≥ 1 adapter file found | ✗ Fix: add domain adapter files to `docs/domain-adapters/` |
149
-
150
- ---
151
-
152
38
  ## Execution
153
39
 
154
- 1. Run the automated health check script:
40
+ 1. Run the health check script (covers ALL categories — no manual checks needed):
155
41
  ```
156
42
  "${CLAUDE_PLUGIN_ROOT}/scripts/afc-doctor.sh" $ARGUMENTS
157
43
  ```
158
- This covers Categories 1-8 automatically.
159
44
 
160
- 2. Print the script's stdout output as-is (already formatted with pass/warn/fail markers).
45
+ 2. Print the script's stdout output as-is. Do not reformat, summarize, or interpret.
161
46
 
162
- 3. If in the source repo (package.json `name` = `"all-for-claudecode"`), continue with Categories 9-11 manually using the check tables above.
47
+ 3. **Stop.** Output nothing after the script output. No analysis, no suggestions, no follow-up actions.
163
48
 
164
- 4. Print combined summary (script summary + any additional findings from Categories 9-11).
49
+ **Rules:**
50
+ - The ONLY Bash command you may run is the `afc-doctor.sh` script above. No other Bash calls.
51
+ - Do NOT execute Fix commands. They are for the user to run manually.
52
+ - Do NOT analyze project source code, git history, branches, or architecture.
165
53
 
166
54
  ## Example Output
167
55
 
@@ -226,7 +114,8 @@ Results: 28 passed, 2 warnings, 0 failures
226
114
 
227
115
  ## Notes
228
116
 
229
- - **Read-only**: this command never modifies any files. It only reads and reports.
117
+ - **Read-only**: this command NEVER modifies any files, deletes tags, changes permissions, or executes fix commands. It only reads and reports. The `Fix:` lines are instructions for the USER to run manually — do NOT execute them.
118
+ - **No project analysis**: after printing the summary, STOP. Do not analyze project source code, git history, branches, or suggest next steps about the project. Doctor's scope ends at the summary line.
230
119
  - **Always run all checks**: do not stop on first failure. The full picture is the value.
231
120
  - **Actionable fixes**: every non-pass result must include a Fix line. Never report a problem without a solution.
232
121
  - **Fast execution**: skip CI/gate command checks if `--fast` is in arguments (these are the slowest checks).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "all-for-claudecode",
3
- "version": "2.8.0",
3
+ "version": "2.8.2",
4
4
  "description": "Claude Code plugin that automates the full dev cycle — spec, plan, implement, review, clean.",
5
5
  "bin": {
6
6
  "all-for-claudecode": "bin/cli.mjs"
@@ -2,7 +2,7 @@
2
2
  set -euo pipefail
3
3
 
4
4
  # afc-doctor.sh — Automated health check for all-for-claudecode plugin
5
- # Runs categories 1-9 deterministically. Categories 10-12 require LLM analysis.
5
+ # Runs ALL categories deterministically. No LLM judgment required.
6
6
  # Output: human-readable text (no JSON), directly printable.
7
7
  # Read-only: never modifies files.
8
8
 
@@ -459,6 +459,224 @@ if [ "$IS_DEV" = true ]; then
459
459
  else
460
460
  warn "Plugin cache directory not found" "install plugin first, then npm run sync:cache"
461
461
  fi
462
+
463
+ # --- Category 10: Command Definitions (dev only) ---
464
+ section "Command Definitions (dev)"
465
+
466
+ CMD_DIR="$PROJECT_DIR/commands"
467
+ if [ -d "$CMD_DIR" ]; then
468
+ CMD_COUNT=0
469
+ CMD_FM_MISSING=""
470
+ CMD_FIELD_MISSING=""
471
+ CMD_NAME_MISMATCH=""
472
+ CMD_AGENT_MISSING=""
473
+
474
+ for cmd_file in "$CMD_DIR"/*.md; do
475
+ [ -f "$cmd_file" ] || continue
476
+ CMD_COUNT=$((CMD_COUNT + 1))
477
+ BASENAME=$(basename "$cmd_file" .md)
478
+
479
+ # Check frontmatter exists (--- ... ---)
480
+ if ! head -1 "$cmd_file" | grep -q '^---' 2>/dev/null; then
481
+ CMD_FM_MISSING="${CMD_FM_MISSING:+$CMD_FM_MISSING, }$BASENAME"
482
+ continue
483
+ fi
484
+
485
+ # Extract frontmatter (between first and second ---)
486
+ FM=$(sed -n '2,/^---$/p' "$cmd_file" 2>/dev/null | sed '$d')
487
+
488
+ # Check required fields: name and description
489
+ if ! printf '%s\n' "$FM" | grep -q '^name:' 2>/dev/null || ! printf '%s\n' "$FM" | grep -q '^description:' 2>/dev/null; then
490
+ CMD_FIELD_MISSING="${CMD_FIELD_MISSING:+$CMD_FIELD_MISSING, }$BASENAME"
491
+ fi
492
+
493
+ # Check name-filename match (afc:{basename})
494
+ FM_NAME=$(printf '%s\n' "$FM" | grep '^name:' | head -1 | sed 's/name:[[:space:]]*//' | tr -d '"' | tr -d "'" | tr -d ' ')
495
+ EXPECTED_NAME="afc:$BASENAME"
496
+ if [ -n "$FM_NAME" ] && [ "$FM_NAME" != "$EXPECTED_NAME" ]; then
497
+ CMD_NAME_MISMATCH="${CMD_NAME_MISMATCH:+$CMD_NAME_MISMATCH, }$BASENAME (got $FM_NAME)"
498
+ fi
499
+
500
+ # Check fork-agent reference
501
+ if printf '%s\n' "$FM" | grep -q 'context:.*fork' 2>/dev/null; then
502
+ AGENT_NAME=$(printf '%s\n' "$FM" | grep '^agent:' | head -1 | sed 's/agent:[[:space:]]*//' | tr -d '"' | tr -d "'" | tr -d ' ' || true)
503
+ if [ -n "$AGENT_NAME" ] && [ ! -f "$PROJECT_DIR/agents/$AGENT_NAME.md" ]; then
504
+ CMD_AGENT_MISSING="${CMD_AGENT_MISSING:+$CMD_AGENT_MISSING, }$BASENAME → $AGENT_NAME"
505
+ fi
506
+ fi
507
+ done
508
+
509
+ if [ -z "$CMD_FM_MISSING" ]; then
510
+ pass "Frontmatter exists ($CMD_COUNT files)"
511
+ else
512
+ fail "Missing frontmatter: $CMD_FM_MISSING" "add YAML frontmatter block"
513
+ fi
514
+
515
+ if [ -z "$CMD_FIELD_MISSING" ]; then
516
+ pass "Required fields present"
517
+ else
518
+ fail "Missing name/description: $CMD_FIELD_MISSING" "add missing fields"
519
+ fi
520
+
521
+ if [ -z "$CMD_NAME_MISMATCH" ]; then
522
+ pass "Name-filename match"
523
+ else
524
+ fail "Name mismatch: $CMD_NAME_MISMATCH" "rename name: field to afc:{filename}"
525
+ fi
526
+
527
+ if [ -z "$CMD_AGENT_MISSING" ]; then
528
+ pass "Fork-agent references valid"
529
+ else
530
+ fail "Missing agent: $CMD_AGENT_MISSING" "create missing agent file or fix agent: field"
531
+ fi
532
+ fi
533
+
534
+ # --- Category 11: Agent Definitions (dev only) ---
535
+ section "Agent Definitions (dev)"
536
+
537
+ AGENT_DIR="$PROJECT_DIR/agents"
538
+ if [ -d "$AGENT_DIR" ]; then
539
+ AGENT_COUNT=0
540
+ AGENT_FM_MISSING=""
541
+ AGENT_FIELD_MISSING=""
542
+ AGENT_NAME_MISMATCH=""
543
+ EXPERT_MEMORY_MISSING=""
544
+ WORKER_TURNS_MISSING=""
545
+
546
+ EXPERT_AGENTS="afc-backend-expert afc-infra-expert afc-pm-expert afc-design-expert afc-marketing-expert afc-legal-expert afc-appsec-expert afc-tech-advisor"
547
+ WORKER_AGENTS="afc-impl-worker afc-pr-analyst"
548
+
549
+ for agent_file in "$AGENT_DIR"/*.md; do
550
+ [ -f "$agent_file" ] || continue
551
+ AGENT_COUNT=$((AGENT_COUNT + 1))
552
+ BASENAME=$(basename "$agent_file" .md)
553
+
554
+ # Check frontmatter exists
555
+ if ! head -1 "$agent_file" | grep -q '^---' 2>/dev/null; then
556
+ AGENT_FM_MISSING="${AGENT_FM_MISSING:+$AGENT_FM_MISSING, }$BASENAME"
557
+ continue
558
+ fi
559
+
560
+ FM=$(sed -n '2,/^---$/p' "$agent_file" 2>/dev/null | sed '$d')
561
+
562
+ # Check required fields: name, description, model
563
+ if ! printf '%s\n' "$FM" | grep -q '^name:' 2>/dev/null || ! printf '%s\n' "$FM" | grep -q '^description:' 2>/dev/null || ! printf '%s\n' "$FM" | grep -q '^model:' 2>/dev/null; then
564
+ AGENT_FIELD_MISSING="${AGENT_FIELD_MISSING:+$AGENT_FIELD_MISSING, }$BASENAME"
565
+ fi
566
+
567
+ # Check name-filename match
568
+ FM_NAME=$(printf '%s\n' "$FM" | grep '^name:' | head -1 | sed 's/name:[[:space:]]*//' | tr -d '"' | tr -d "'" | tr -d ' ')
569
+ if [ -n "$FM_NAME" ] && [ "$FM_NAME" != "$BASENAME" ]; then
570
+ AGENT_NAME_MISMATCH="${AGENT_NAME_MISMATCH:+$AGENT_NAME_MISMATCH, }$BASENAME (got $FM_NAME)"
571
+ fi
572
+
573
+ # Expert memory check
574
+ for expert in $EXPERT_AGENTS; do
575
+ if [ "$BASENAME" = "$expert" ]; then
576
+ if ! printf '%s\n' "$FM" | grep -q '^memory:' 2>/dev/null; then
577
+ EXPERT_MEMORY_MISSING="${EXPERT_MEMORY_MISSING:+$EXPERT_MEMORY_MISSING, }$BASENAME"
578
+ fi
579
+ fi
580
+ done
581
+
582
+ # Worker maxTurns check
583
+ for worker in $WORKER_AGENTS; do
584
+ if [ "$BASENAME" = "$worker" ]; then
585
+ if ! printf '%s\n' "$FM" | grep -q '^maxTurns:' 2>/dev/null; then
586
+ WORKER_TURNS_MISSING="${WORKER_TURNS_MISSING:+$WORKER_TURNS_MISSING, }$BASENAME"
587
+ fi
588
+ fi
589
+ done
590
+ done
591
+
592
+ if [ -z "$AGENT_FM_MISSING" ]; then
593
+ pass "Frontmatter exists ($AGENT_COUNT files)"
594
+ else
595
+ fail "Missing frontmatter: $AGENT_FM_MISSING" "add YAML frontmatter block"
596
+ fi
597
+
598
+ if [ -z "$AGENT_FIELD_MISSING" ]; then
599
+ pass "Required fields present"
600
+ else
601
+ fail "Missing name/description/model: $AGENT_FIELD_MISSING" "add missing fields"
602
+ fi
603
+
604
+ if [ -z "$AGENT_NAME_MISMATCH" ]; then
605
+ pass "Name-filename match"
606
+ else
607
+ fail "Name mismatch: $AGENT_NAME_MISMATCH" "rename name: field to match filename"
608
+ fi
609
+
610
+ # Count experts found
611
+ EXPERT_TOTAL=0
612
+ EXPERT_WITH_MEM=0
613
+ for expert in $EXPERT_AGENTS; do
614
+ if [ -f "$AGENT_DIR/$expert.md" ]; then
615
+ EXPERT_TOTAL=$((EXPERT_TOTAL + 1))
616
+ FM=$(sed -n '2,/^---$/p' "$AGENT_DIR/$expert.md" 2>/dev/null | sed '$d')
617
+ if printf '%s\n' "$FM" | grep -q '^memory:' 2>/dev/null; then
618
+ EXPERT_WITH_MEM=$((EXPERT_WITH_MEM + 1))
619
+ fi
620
+ fi
621
+ done
622
+ if [ -z "$EXPERT_MEMORY_MISSING" ]; then
623
+ pass "Expert memory configured ($EXPERT_WITH_MEM/$EXPERT_TOTAL)"
624
+ else
625
+ fail "Missing memory: field: $EXPERT_MEMORY_MISSING" "add memory: project to agent frontmatter"
626
+ fi
627
+
628
+ WORKER_TOTAL=0
629
+ WORKER_WITH_TURNS=0
630
+ for worker in $WORKER_AGENTS; do
631
+ if [ -f "$AGENT_DIR/$worker.md" ]; then
632
+ WORKER_TOTAL=$((WORKER_TOTAL + 1))
633
+ FM=$(sed -n '2,/^---$/p' "$AGENT_DIR/$worker.md" 2>/dev/null | sed '$d')
634
+ if printf '%s\n' "$FM" | grep -q '^maxTurns:' 2>/dev/null; then
635
+ WORKER_WITH_TURNS=$((WORKER_WITH_TURNS + 1))
636
+ fi
637
+ fi
638
+ done
639
+ if [ -z "$WORKER_TURNS_MISSING" ]; then
640
+ pass "Worker maxTurns configured ($WORKER_WITH_TURNS/$WORKER_TOTAL)"
641
+ else
642
+ fail "Missing maxTurns: $WORKER_TURNS_MISSING" "add maxTurns: to agent frontmatter"
643
+ fi
644
+ fi
645
+
646
+ # --- Category 12: Doc References (dev only) ---
647
+ section "Doc References (dev)"
648
+
649
+ # Scan commands and agents for docs/ references
650
+ DOC_REFS_MISSING=""
651
+ for src_file in "$CMD_DIR"/*.md "$AGENT_DIR"/*.md; do
652
+ [ -f "$src_file" ] || continue
653
+ while IFS= read -r ref; do
654
+ [ -z "$ref" ] && continue
655
+ DOC_PATH="$PROJECT_DIR/$ref"
656
+ if [ ! -f "$DOC_PATH" ]; then
657
+ DOC_REFS_MISSING="${DOC_REFS_MISSING:+$DOC_REFS_MISSING, }$ref (in $(basename "$src_file"))"
658
+ fi
659
+ done < <(grep -oE 'docs/[a-zA-Z0-9_/-]+\.md' "$src_file" 2>/dev/null | sort -u)
660
+ done
661
+
662
+ if [ -z "$DOC_REFS_MISSING" ]; then
663
+ pass "Referenced docs exist"
664
+ else
665
+ fail "Missing docs: $DOC_REFS_MISSING" "create missing doc files or fix references"
666
+ fi
667
+
668
+ # Domain adapters
669
+ ADAPTER_DIR="$PROJECT_DIR/docs/domain-adapters"
670
+ if [ -d "$ADAPTER_DIR" ]; then
671
+ ADAPTER_COUNT=$(find "$ADAPTER_DIR" -maxdepth 1 -name '*.md' -type f 2>/dev/null | wc -l | tr -d ' ')
672
+ if [ "$ADAPTER_COUNT" -ge 1 ]; then
673
+ pass "Domain adapters exist ($ADAPTER_COUNT files)"
674
+ else
675
+ fail "No domain adapter files" "add .md files to docs/domain-adapters/"
676
+ fi
677
+ else
678
+ fail "docs/domain-adapters/ directory missing" "create docs/domain-adapters/ with at least one .md file"
679
+ fi
462
680
  fi
463
681
 
464
682
  # --- Summary ---
@@ -474,9 +692,5 @@ else
474
692
  printf '%d issues need attention. Run the Fix commands above.\n' "$FAIL"
475
693
  fi
476
694
 
477
- # Signal dev-only categories to caller
478
- if [ "$IS_DEV" = true ]; then
479
- printf '\nNote: Categories 10-12 (Command/Agent/Doc validation) require LLM analysis.\n'
480
- fi
481
695
 
482
696
  exit 0
@@ -19,14 +19,14 @@ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
19
19
  LEARNER_CONFIG="$PROJECT_DIR/.claude/afc/learner.json"
20
20
  QUEUE_FILE="$PROJECT_DIR/.claude/.afc-learner-queue.jsonl"
21
21
 
22
- # Gate: exit immediately if learner is not enabled
22
+ # Read stdin (must consume before any exit to prevent pipe break)
23
+ INPUT=$(cat)
24
+
25
+ # Gate: exit if learner is not enabled
23
26
  if [ ! -f "$LEARNER_CONFIG" ]; then
24
27
  exit 0
25
28
  fi
26
29
 
27
- # Read stdin (contains user prompt JSON)
28
- INPUT=$(cat)
29
-
30
30
  # Extract prompt text
31
31
  USER_TEXT=""
32
32
  if command -v jq >/dev/null 2>&1; then