cclaw-cli 0.7.1 → 0.9.0

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.
@@ -10,6 +10,11 @@ const SUBAGENT_AGENT_NAMES = [
10
10
  "security-reviewer",
11
11
  "test-author",
12
12
  "doc-updater",
13
+ "repo-research-analyst",
14
+ "learnings-researcher",
15
+ "framework-docs-researcher",
16
+ "best-practices-researcher",
17
+ "git-history-analyzer",
13
18
  ];
14
19
  export function subagentDrivenDevSkill() {
15
20
  return `---
@@ -59,6 +64,20 @@ If delegation tooling is unavailable in the active harness, run the same control
59
64
  - **Use a more capable model** for high-ambiguity or high-risk analysis (security review, architecture conflicts, spec contradiction resolution).
60
65
  - During review-heavy stages, prefer **mixed routing**: faster first-pass triage + escalate only high-severity/low-confidence findings.
61
66
 
67
+ ### Cost-aware routing (tier table)
68
+
69
+ | Tier | Use for | Example agents |
70
+ |---|---|---|
71
+ | \`deep\` | one heavy reasoning pass per stage (planner, final reconciliation) | planner |
72
+ | \`balanced\` | spec compliance + code/security review with enough context | spec-reviewer, code-reviewer, security-reviewer, test-author |
73
+ | \`fast\` | read-only research / narrow machine checks / docs updates — safe to fan out | repo-research-analyst, learnings-researcher, framework-docs-researcher, best-practices-researcher, git-history-analyzer, doc-updater |
74
+
75
+ **Routing rules:**
76
+ - At most ONE \`deep\` agent per stage (planner OR final reconciliation, not both).
77
+ - \`balanced\` agents are default for review-stage specialists.
78
+ - \`fast\` agents are the only tier you should fan out in parallel (3-5 at a time is fine).
79
+ - Never escalate a \`fast\` agent's output directly to ship decisions — always have a \`balanced\` reviewer consume the evidence first.
80
+
62
81
  ## HARD-GATE
63
82
 
64
83
  **Never dispatch a subagent without a concrete, self-contained task description pasted into the prompt. Do not pass file references the subagent must read to understand its task.**
@@ -556,6 +575,146 @@ Process (mandatory):
556
575
  - Report: FILES_EDITED, GREEN_COMMAND_RUN, REFACTOR_NOTES, STATUS: DONE|BLOCKED.
557
576
  \`\`\`
558
577
 
578
+ `;
579
+ }
580
+ function repoResearchAnalystEnhancedBody() {
581
+ return `
582
+
583
+ ## Task Tool Delegation
584
+
585
+ Launch **read-only repo exploration** at the start of brainstorm/scope/design so the primary agent plans on a grounded map, not guesses. Run as a \`fast\` tier agent — cheap to fan out alongside learnings-researcher and best-practices-researcher.
586
+
587
+ \`\`\`
588
+ You are a repo research analyst subagent.
589
+
590
+ TASK DOMAIN: {1-sentence description of the feature/fix/refactor being planned}
591
+ REPO HINTS: {known directories, module names, patterns the primary agent already knows}
592
+ OUT OF SCOPE: {paths not to read (large vendor dirs, generated code)}
593
+
594
+ Deliverables:
595
+ - Relevant modules: list of \`path — purpose\` (cite file:line on ambiguous claims).
596
+ - Reuse candidates: list of \`file:line — why this absorbs the change\`.
597
+ - Ownership hints: CODEOWNERS / README / comment signals.
598
+ - Gaps: capabilities NOT yet present that the task would need.
599
+
600
+ Rules:
601
+ - Read-only. Do NOT edit files.
602
+ - Cite file:line for every claim; never invent paths.
603
+ - If the scope is too large to fully explore, say so and bound your search.
604
+ \`\`\`
605
+
606
+ `;
607
+ }
608
+ function learningsResearcherEnhancedBody() {
609
+ return `
610
+
611
+ ## Task Tool Delegation
612
+
613
+ Dispatch before any non-trivial stage to stream \`.cclaw/knowledge.jsonl\` and surface prior learnings. Cheap \`fast\` tier — fan out with other research agents.
614
+
615
+ \`\`\`
616
+ You are a learnings researcher subagent.
617
+
618
+ TASK DESCRIPTION: {verbatim prompt + current stage}
619
+ DOMAIN HINTS: {keywords from Task Classification / Origin Docs}
620
+
621
+ Deliverables:
622
+ - Matched rules: list of \`trigger → action (confidence)\`.
623
+ - Matched patterns: list of \`trigger → action (confidence)\`.
624
+ - Matched lessons: list of \`trigger → action (confidence)\`.
625
+ - Matched compounds: list of \`trigger → action (confidence)\`.
626
+ - No-match note (if nothing relevant exists).
627
+
628
+ Rules:
629
+ - Read-only; NEVER rewrite or delete entries.
630
+ - Return at most 10 entries, ranked by confidence then recency.
631
+ - Quote the entries verbatim — do NOT paraphrase.
632
+ \`\`\`
633
+
634
+ `;
635
+ }
636
+ function frameworkDocsResearcherEnhancedBody() {
637
+ return `
638
+
639
+ ## Task Tool Delegation
640
+
641
+ Use for any task that depends on a specific framework/library/SDK/CLI. Prefer context7 MCP when available for version-accurate docs; otherwise WebSearch/WebFetch official sources.
642
+
643
+ \`\`\`
644
+ You are a framework documentation researcher subagent.
645
+
646
+ LIBRARY + VERSION: {name + resolved version from lockfile / pyproject / go.mod / Cargo.toml / pom.xml / build.gradle}
647
+ TASK USAGE: {which APIs the task will actually call}
648
+ CONTEXT7: {"available" | "not available"}
649
+
650
+ Deliverables:
651
+ - Key APIs: list of signatures the task will touch.
652
+ - Breaking changes since the last major release relevant to the task.
653
+ - Gotchas: deprecated paths, version-gated flags, platform caveats.
654
+ - Source: URL(s) or MCP reference used.
655
+
656
+ Rules:
657
+ - Never invent APIs. Prefer silence + UNKNOWN over speculation.
658
+ - Tie every statement to an authoritative source; avoid blog posts when official docs exist.
659
+ \`\`\`
660
+
661
+ `;
662
+ }
663
+ function bestPracticesResearcherEnhancedBody() {
664
+ return `
665
+
666
+ ## Task Tool Delegation
667
+
668
+ Use when the task touches a well-known domain (auth, caching, rate limiting, observability, accessibility, etc.) and the primary agent needs a short, citable best-practice summary.
669
+
670
+ \`\`\`
671
+ You are a best-practices researcher subagent.
672
+
673
+ DOMAIN: {one word, e.g. auth, caching, rate-limiting, a11y, observability, retries}
674
+ SUB-PROBLEM: {narrow one-sentence statement of what the task is actually deciding}
675
+
676
+ Deliverables:
677
+ - Recommended practices: 5-8 entries of \`practice — rationale — source\`.
678
+ - Common traps / anti-patterns: list of \`trap — why it fails — source\`.
679
+ - Decision hooks: 1-3 explicit questions the primary agent must answer.
680
+
681
+ Rules:
682
+ - Cite 3-5 authoritative sources (official docs, IETF/W3C/OWASP, well-known standards).
683
+ - If the domain has no authoritative answer, say so; do NOT substitute opinion.
684
+ \`\`\`
685
+
686
+ `;
687
+ }
688
+ function gitHistoryAnalyzerEnhancedBody() {
689
+ return `
690
+
691
+ ## Task Tool Delegation
692
+
693
+ Use when the task touches existing code, so the primary agent can see prior attempts, reverts, and owners before proposing changes.
694
+
695
+ \`\`\`
696
+ You are a git history analyzer subagent.
697
+
698
+ IMPACTED PATHS: {list of files/directories the task plans to touch}
699
+ WINDOW: {default 90 days; adjust only if explicitly needed}
700
+
701
+ Commands to run (read-only):
702
+ - git log --follow -n 20 -- <path>
703
+ - git blame <path>
704
+ - git log --since="<window>" --grep="revert|regression" -- <path>
705
+ - git log --since="<window>" --format="%an" -- <path> | sort | uniq -c | sort -nr
706
+
707
+ Deliverables:
708
+ - Recent themes: 3-5 bullets on what changed lately per path.
709
+ - Revert/regression signals: list with commit SHAs.
710
+ - Owners: best-guess from blame + committer frequency.
711
+ - Collision risks: in-flight refactors/migrations visible in log.
712
+
713
+ Rules:
714
+ - Read-only. Never amend history, never git push.
715
+ - If a path is new (no history), say so explicitly rather than fabricating context.
716
+ \`\`\`
717
+
559
718
  `;
560
719
  }
561
720
  function docUpdaterEnhancedBody() {
@@ -597,6 +756,16 @@ export function enhancedAgentBody(agentName) {
597
756
  return testAuthorEnhancedBody();
598
757
  case "doc-updater":
599
758
  return docUpdaterEnhancedBody();
759
+ case "repo-research-analyst":
760
+ return repoResearchAnalystEnhancedBody();
761
+ case "learnings-researcher":
762
+ return learningsResearcherEnhancedBody();
763
+ case "framework-docs-researcher":
764
+ return frameworkDocsResearcherEnhancedBody();
765
+ case "best-practices-researcher":
766
+ return bestPracticesResearcherEnhancedBody();
767
+ case "git-history-analyzer":
768
+ return gitHistoryAnalyzerEnhancedBody();
600
769
  default:
601
770
  return `
602
771
 
@@ -84,6 +84,16 @@ export const ARTIFACT_TEMPLATES = {
84
84
  - (HOLD: minimum-change-set hardening)
85
85
  - (REDUCE: ruthless cuts, follow-up split)
86
86
 
87
+ ## Requirements (stable IDs)
88
+ | ID | Requirement (observable outcome) | Priority | Source (origin doc / prompt line) |
89
+ |---|---|---|---|
90
+ | R1 | | P0 | |
91
+
92
+ > Assign \`R1\`, \`R2\`, \`R3\`… once and never renumber. Downstream artifacts
93
+ > (design, spec, plan, review) reference these IDs verbatim. If a requirement
94
+ > is later dropped, keep the row and mark Priority \`DROPPED\`; if a new one is
95
+ > added mid-flow, append with the next free R-number — do NOT reuse numbers.
96
+
87
97
  ## In Scope / Out of Scope
88
98
 
89
99
  ### In Scope
@@ -203,9 +213,13 @@ export const ARTIFACT_TEMPLATES = {
203
213
  "04-spec.md": `# Specification Artifact
204
214
 
205
215
  ## Acceptance Criteria
206
- | ID | Criterion (observable/measurable/falsifiable) | Design Decision Ref |
207
- |---|---|---|
208
- | AC-1 | | |
216
+ | ID | Requirement Ref (R#) | Criterion (observable/measurable/falsifiable) | Design Decision Ref |
217
+ |---|---|---|---|
218
+ | AC-1 | R1 | | |
219
+
220
+ > Every AC must reference at least one \`R#\` from \`02-scope.md\`. ACs are
221
+ > stable (never renumber): dropped ACs stay with Priority \`DROPPED\`; new
222
+ > ones append with the next free \`AC-#\`.
209
223
 
210
224
  ## Edge Cases
211
225
  | Criterion ID | Boundary case | Error case |
@@ -264,9 +278,15 @@ export const ARTIFACT_TEMPLATES = {
264
278
  Execution rule: complete and verify each wave before starting the next wave.
265
279
 
266
280
  ## Task List
267
- | Task ID | Description | Acceptance criterion | Verification command | Effort |
268
- |---|---|---|---|---|
269
- | T-1 | | | | |
281
+
282
+ **Rules (apply before writing rows):**
283
+ - Every task fits the **2-5 minute budget**. If \`[~Nm]\` is >5, split the task.
284
+ - **No placeholders.** Forbidden tokens anywhere in this table: \`TODO\`, \`TBD\`, \`FIXME\`, \`<fill-in>\`, \`<your-*-here>\`, \`xxx\`, bare ellipsis. Every file path, test, and verification command must be copy-pasteable as written.
285
+ - If an estimate is genuinely uncertain (new library, unfamiliar subsystem), add a **spike task in wave 0** to de-risk — do NOT hide the uncertainty inside a large estimate.
286
+
287
+ | Task ID | Description | Acceptance criterion | Verification command | Effort (S/M/L) | Minutes |
288
+ |---|---|---|---|---|---|
289
+ | T-1 | | | | | [~3m] |
270
290
 
271
291
  ## Acceptance Mapping
272
292
  | Criterion ID | Task IDs |
@@ -283,6 +303,10 @@ Execution rule: complete and verify each wave before starting the next wave.
283
303
  |---|---|---|
284
304
  | | | |
285
305
 
306
+ ## No-Placeholder Scan
307
+ - Scanned tokens: \`TODO\`, \`TBD\`, \`FIXME\`, \`<fill-in>\`, \`<your-*-here>\`, \`xxx\`, bare ellipsis in task rows.
308
+ - Hits: 0 (required for WAIT_FOR_CONFIRM to resolve).
309
+
286
310
  ## WAIT_FOR_CONFIRM
287
311
  - Status: pending
288
312
  - Confirmed by:
@@ -327,6 +351,20 @@ Execution rule: complete and verify each wave before starting the next wave.
327
351
  | Code type | Target | Current | Command |
328
352
  |---|---|---|---|
329
353
  | | | | |
354
+
355
+ ## Test Pyramid Shape
356
+ > Fill in per slice. Size classes: **Small** = pure logic, no I/O, <50ms; **Medium** = single process boundary (fs, in-memory DB, in-process service); **Large** = multi-process / network / real external service. Default to Small; escalate only when a real boundary must be exercised.
357
+
358
+ | Slice | # Small | # Medium | # Large | Justification for any Medium/Large |
359
+ |---|---|---|---|---|
360
+ | S-1 | | | | |
361
+
362
+ ## Prove-It Reproduction (bug-fix slices only)
363
+ > Required whenever the slice is classified as a **bug fix** (task class = \`software-bugfix\`). Must demonstrate the test fails without the fix, passes with the fix, and would fail again if the fix were reverted. Skip this table entirely for non-bugfix slices.
364
+
365
+ | Slice | Reproduction test | RED-without-fix evidence | GREEN-with-fix evidence | Revert-guard note |
366
+ |---|---|---|---|---|
367
+ | S-1 | | | | |
330
368
  `,
331
369
  "07-review.md": `# Review Artifact
332
370
 
@@ -16,6 +16,7 @@ export declare function landscapeCheckSkill(): string;
16
16
  export declare function knowledgeCurationSkill(): string;
17
17
  export declare function securityAuditSkill(): string;
18
18
  export declare function adversarialReviewSkill(): string;
19
+ export declare function documentReviewSkill(): string;
19
20
  export declare function retrospectiveSkill(): string;
20
21
  export declare function languageTypescriptSkill(): string;
21
22
  export declare function languagePythonSkill(): string;
@@ -43,5 +44,5 @@ export declare const LANGUAGE_RULE_PACK_GENERATORS: Record<string, () => string>
43
44
  * clean them up after the move to `.cclaw/rules/lang/`.
44
45
  */
45
46
  export declare const LEGACY_LANGUAGE_RULE_PACK_FOLDERS: readonly ["language-typescript", "language-python", "language-go"];
46
- export declare const UTILITY_SKILL_FOLDERS: readonly ["security", "debugging", "performance", "ci-cd", "docs", "executing-plans", "context-engineering", "source-driven-development", "frontend-accessibility", "landscape-check", "adversarial-review", "security-audit", "knowledge-curation", "retrospective"];
47
+ export declare const UTILITY_SKILL_FOLDERS: readonly ["security", "debugging", "performance", "ci-cd", "docs", "executing-plans", "context-engineering", "source-driven-development", "frontend-accessibility", "landscape-check", "adversarial-review", "security-audit", "knowledge-curation", "retrospective", "document-review"];
47
48
  export declare const UTILITY_SKILL_MAP: Record<string, () => string>;
@@ -1069,6 +1069,143 @@ Escalate to the main review-army under the matching severity (Critical / Importa
1069
1069
  - Only playing the hostile-user role and skipping operator + maintainer.
1070
1070
  `;
1071
1071
  }
1072
+ export function documentReviewSkill() {
1073
+ return `---
1074
+ name: document-review
1075
+ description: "Post-artifact scrub pass. Use after writing any cclaw artifact (brainstorm, scope, design, spec, plan, review, ship) and before asking the user for approval — catches placeholders, internal inconsistencies, dangling references, and vague language."
1076
+ ---
1077
+
1078
+ # Document Review
1079
+
1080
+ ## Quick Start
1081
+
1082
+ > 1. Run against the **just-written artifact** before you ask the user to approve it.
1083
+ > 2. Walk the five lenses below. For each, produce either a concrete fix or the explicit string "no issues".
1084
+ > 3. Apply all fixes yourself in the same artifact — this skill is a scrub, not a checklist for the user.
1085
+
1086
+ ## HARD-GATE
1087
+
1088
+ Do NOT surface an artifact to the user for approval while **any** of the
1089
+ following are still present:
1090
+
1091
+ - Unresolved placeholders (\`TBD\`, \`TODO\`, \`<fill me>\`, empty table rows
1092
+ that the schema requires).
1093
+ - Broken cross-references (e.g. \`AC-12\` in spec when spec table only goes
1094
+ up to \`AC-8\`; \`R3\` referenced in a design decision when scope stops at \`R2\`).
1095
+ - Contradictions between sections of the same artifact (e.g. \`In Scope\`
1096
+ says X but \`Acceptance Criteria\` never mentions X).
1097
+ - Vague language where the stage requires observable / measurable
1098
+ statements (e.g. "fast", "simple", "seamless", "robust" without a metric).
1099
+ - Missing required sections declared by the stage's \`artifactValidation\`.
1100
+
1101
+ If any of these remain, fix them first, then re-run this skill; only then
1102
+ ask for approval.
1103
+
1104
+ ## When to Use
1105
+
1106
+ - Immediately after writing \`.cclaw/artifacts/01-brainstorm.md\`
1107
+ - Immediately after writing \`.cclaw/artifacts/02-scope.md\`
1108
+ - Immediately after writing \`.cclaw/artifacts/03-design.md\`
1109
+ - Immediately after writing \`.cclaw/artifacts/04-spec.md\`
1110
+ - Immediately after writing \`.cclaw/artifacts/05-plan.md\`
1111
+ - Immediately after writing \`.cclaw/artifacts/07-review.md\`
1112
+ - Immediately after writing \`.cclaw/artifacts/08-ship.md\`
1113
+ - Whenever you regenerate an artifact after a Reclassification pass
1114
+
1115
+ Do NOT run during \`06-tdd.md\` — the TDD artifact is append-only evidence;
1116
+ scrubbing risks destroying RED/GREEN history. Use \`Verification Before
1117
+ Completion\` in the TDD skill instead.
1118
+
1119
+ ## Five Lenses
1120
+
1121
+ ### 1. Placeholder Scrub
1122
+
1123
+ Grep the artifact for: \`TBD\`, \`TODO\`, \`FIXME\`, \`<fill me>\`,
1124
+ \`<describe>\`, \`<owner>\`, \`N/A\` inside cells the schema marks as required,
1125
+ and empty first-row table cells that the template left blank.
1126
+
1127
+ **Output:** each placeholder replaced with real content, or a line added
1128
+ explicitly stating "None — <reason>". Never leave a placeholder in a
1129
+ required section.
1130
+
1131
+ ### 2. Cross-Reference Integrity
1132
+
1133
+ - Every \`R#\` referenced in this artifact must exist in \`02-scope.md\`.
1134
+ - Every \`AC-#\` referenced must exist in \`04-spec.md\`.
1135
+ - Every task ID referenced must exist in \`05-plan.md\`.
1136
+ - Every file path cited must be the canonical casing used elsewhere.
1137
+ - Every ADR / decision reference must resolve to an existing record.
1138
+
1139
+ **Output:** broken refs fixed, or flagged with the exact upstream artifact
1140
+ that needs updating first.
1141
+
1142
+ ### 3. Internal Consistency
1143
+
1144
+ - \`In Scope\` / \`Out of Scope\` lists do not overlap.
1145
+ - Acceptance Criteria match the requirements they claim to verify.
1146
+ - Plan tasks cover every AC (no AC left without at least one task).
1147
+ - Failure modes listed in design appear in the spec's edge cases.
1148
+ - Review verdict matches the evidence (no "Ship" with open Criticals).
1149
+
1150
+ **Output:** contradictions resolved by amending whichever side is wrong,
1151
+ with a one-line rationale.
1152
+
1153
+ ### 4. Ambiguity Scan
1154
+
1155
+ Flag words that masquerade as decisions:
1156
+
1157
+ - "fast", "simple", "robust", "intuitive", "seamless", "scalable",
1158
+ "production-ready", "high quality" — each must be replaced with an
1159
+ observable metric or dropped.
1160
+ - "etc.", "and so on", "similar to X" in requirements — enumerate or drop.
1161
+ - Passive voice that hides the actor ("will be validated") — name the
1162
+ actor ("the API gateway validates the payload").
1163
+
1164
+ **Output:** every flagged term rewritten as observable, or escalated as a
1165
+ Decision Protocol question before approval.
1166
+
1167
+ ### 5. Schema Conformance
1168
+
1169
+ Re-verify the artifact against the stage's \`artifactValidation\`:
1170
+
1171
+ - Every required section is present with a non-empty body.
1172
+ - Tables have the columns the template specifies (no dropped columns).
1173
+ - Any "N/A" in a required section carries an inline reason.
1174
+ - Required evidence links (test output, diff excerpts) resolve.
1175
+
1176
+ **Output:** missing sections added, or escalated as a BLOCKED signal if
1177
+ the artifact cannot honestly be completed without more work.
1178
+
1179
+ ## Output Protocol
1180
+
1181
+ After running all five lenses, emit a single one-line summary **before
1182
+ asking the user for approval**:
1183
+
1184
+ > Document review: 5/5 lenses clean; <N> fixes applied.
1185
+
1186
+ If fixes were blocked (e.g. upstream artifact drift), do NOT claim
1187
+ "clean" — surface the blocker explicitly and stop.
1188
+
1189
+ ## Anti-Patterns
1190
+
1191
+ - Running this skill as a "polish pass" after the user already approved
1192
+ the artifact — by then it is too late.
1193
+ - Treating placeholders as "documentation" ("TBD on rollback — we'll
1194
+ figure it out"). Either decide now or mark it as an explicit BLOCKED.
1195
+ - Silently rewriting user-approved content under the guise of "scrubbing".
1196
+ - Using this skill as a substitute for the stage's own review sections —
1197
+ it is a **last-mile check**, not a replacement for the stage review.
1198
+
1199
+ ## Red Flags
1200
+
1201
+ - "No issues" on an artifact that still has empty table rows.
1202
+ - Cross-reference lens passes but the artifact cites IDs from a stage
1203
+ that has not yet been written.
1204
+ - Ambiguity scan finds nothing in a brainstorm / scope artifact (this is
1205
+ implausible — those stages produce narrative by design, and narrative
1206
+ always contains at least one vague phrase worth tightening).
1207
+ `;
1208
+ }
1072
1209
  export function retrospectiveSkill() {
1073
1210
  return `---
1074
1211
  name: retrospective
@@ -1394,7 +1531,8 @@ export const UTILITY_SKILL_FOLDERS = [
1394
1531
  "adversarial-review",
1395
1532
  "security-audit",
1396
1533
  "knowledge-curation",
1397
- "retrospective"
1534
+ "retrospective",
1535
+ "document-review"
1398
1536
  ];
1399
1537
  export const UTILITY_SKILL_MAP = {
1400
1538
  security: securityReviewSkill,
@@ -1410,5 +1548,6 @@ export const UTILITY_SKILL_MAP = {
1410
1548
  "adversarial-review": adversarialReviewSkill,
1411
1549
  "security-audit": securityAuditSkill,
1412
1550
  "knowledge-curation": knowledgeCurationSkill,
1413
- retrospective: retrospectiveSkill
1551
+ retrospective: retrospectiveSkill,
1552
+ "document-review": documentReviewSkill
1414
1553
  };
package/dist/doctor.js CHANGED
@@ -258,13 +258,90 @@ export async function doctorChecks(projectRoot, options = {}) {
258
258
  const skillContent = await fs.readFile(skillPath, "utf8");
259
259
  const lineCount = skillContent.split("\n").length;
260
260
  const MIN_SKILL_LINES = 110;
261
+ const MAX_SKILL_LINES = 650;
261
262
  checks.push({
262
263
  name: `skill:${stage}:min_lines`,
263
264
  ok: lineCount >= MIN_SKILL_LINES,
264
265
  details: `${skillPath} has ${lineCount} lines (minimum ${MIN_SKILL_LINES})`
265
266
  });
267
+ checks.push({
268
+ name: `skill:${stage}:max_lines`,
269
+ ok: lineCount <= MAX_SKILL_LINES,
270
+ details: `${skillPath} has ${lineCount} lines (soft max ${MAX_SKILL_LINES}; stage skills beyond this drift into unread bloat)`
271
+ });
272
+ const canonicalSections = [
273
+ { id: "frontmatter", pattern: /^---\nname: [\w-]+\ndescription: /m, label: "YAML frontmatter (name + description)" },
274
+ { id: "hard_gate", pattern: /^## HARD-GATE$/m, label: "## HARD-GATE" },
275
+ { id: "checklist", pattern: /^## Checklist$/m, label: "## Checklist" },
276
+ { id: "completion_protocol", pattern: /^## Stage Completion Protocol$/m, label: "## Stage Completion Protocol" },
277
+ { id: "handoff_menu", pattern: /^### Handoff Menu$/m, label: "### Handoff Menu" },
278
+ { id: "good_vs_bad", pattern: /Good vs Bad/i, label: "Good vs Bad examples" },
279
+ { id: "anti_patterns", pattern: /^## Anti-Patterns$/m, label: "## Anti-Patterns" }
280
+ ];
281
+ const missingSections = canonicalSections
282
+ .filter((section) => !section.pattern.test(skillContent))
283
+ .map((section) => section.label);
284
+ checks.push({
285
+ name: `skill:${stage}:canonical_sections`,
286
+ ok: missingSections.length === 0,
287
+ details: missingSections.length === 0
288
+ ? `${skillPath} contains all canonical sections`
289
+ : `${skillPath} missing sections: ${missingSections.join(", ")}`
290
+ });
266
291
  }
267
292
  }
293
+ // Meta-skill health — the using-cclaw routing brain must always contain the
294
+ // signals that stage skills reference. When one of these drifts, every stage
295
+ // citation breaks silently.
296
+ const metaSkillPath = path.join(projectRoot, RUNTIME_ROOT, "skills", "using-cclaw", "SKILL.md");
297
+ if (await exists(metaSkillPath)) {
298
+ const metaContent = await fs.readFile(metaSkillPath, "utf8");
299
+ const requiredSignals = [
300
+ { id: "instruction_priority", pattern: /Instruction Priority/i, label: "Instruction Priority" },
301
+ { id: "spawned_detection", pattern: /Spawned Subagent Detection/i, label: "Spawned Subagent Detection" },
302
+ { id: "shared_decision", pattern: /Shared Decision \+ Tool-Use Protocol/i, label: "Shared Decision + Tool-Use Protocol" },
303
+ { id: "shared_completion", pattern: /Shared Stage Completion Protocol/i, label: "Shared Stage Completion Protocol" },
304
+ { id: "escalation_rule", pattern: /Escalation Rule \(3 attempts\)/i, label: "Escalation Rule (3 attempts)" },
305
+ { id: "invocation_preamble", pattern: /Invocation Preamble/i, label: "Invocation Preamble" },
306
+ { id: "operational_self_improvement", pattern: /Operational Self-Improvement/i, label: "Operational Self-Improvement" },
307
+ { id: "engineering_ethos", pattern: /Engineering Ethos/i, label: "Engineering Ethos" },
308
+ { id: "task_classification", pattern: /Task Classification/i, label: "Task Classification" }
309
+ ];
310
+ const missingMeta = requiredSignals
311
+ .filter((signal) => !signal.pattern.test(metaContent))
312
+ .map((signal) => signal.label);
313
+ checks.push({
314
+ name: "skill:meta:signals",
315
+ ok: missingMeta.length === 0,
316
+ details: missingMeta.length === 0
317
+ ? `${metaSkillPath} contains all required routing signals`
318
+ : `${metaSkillPath} missing signals: ${missingMeta.join(", ")}`
319
+ });
320
+ }
321
+ // Harness tool-map references (A.1#4) must always be present — stage skills
322
+ // cite the paths by name.
323
+ const harnessRefDir = path.join(projectRoot, RUNTIME_ROOT, "references", "harness-tools");
324
+ const harnessRefFiles = ["README.md", "claude.md", "cursor.md", "opencode.md", "codex.md"];
325
+ for (const fileName of harnessRefFiles) {
326
+ const refPath = path.join(harnessRefDir, fileName);
327
+ checks.push({
328
+ name: `harness_tool_ref:${fileName.replace(/\.md$/, "")}`,
329
+ ok: await exists(refPath),
330
+ details: refPath
331
+ });
332
+ }
333
+ // Per-stage example references (A.2#8, progressive disclosure). Each stage
334
+ // skill's Examples section points here; the file MUST exist or the pointer
335
+ // is a dangling link.
336
+ const stageRefDir = path.join(projectRoot, RUNTIME_ROOT, "references", "stages");
337
+ for (const stage of COMMAND_FILE_ORDER) {
338
+ const refPath = path.join(stageRefDir, `${stage}-examples.md`);
339
+ checks.push({
340
+ name: `stage_examples_ref:${stage}`,
341
+ ok: await exists(refPath),
342
+ details: refPath
343
+ });
344
+ }
268
345
  checks.push({
269
346
  name: "gitignore:required_patterns",
270
347
  ok: await gitignoreHasRequiredPatterns(projectRoot),
@@ -31,25 +31,55 @@ Before responding to a coding request:
31
31
  2. Use \`/cc\` to start or \`/cc-next\` to continue the flow.
32
32
  3. If no stage applies, respond normally.
33
33
 
34
+ ### Task Classification (before \`/cc\`)
35
+
36
+ | Class | Examples | Route |
37
+ |---|---|---|
38
+ | Software — non-trivial | feature, refactor, migration, integration | \`/cc <idea>\` → stage flow (standard track) |
39
+ | Software — trivial | typo, one-liner, rename, config tweak | \`/cc <idea>\` → quick track |
40
+ | Software — bug fix | regression with repro | \`/cc <idea>\` → quick track, RED reproduces bug first |
41
+ | Pure question | "how does X work?" | Answer directly; no stage |
42
+ | Non-software | legal text, meeting notes | Answer directly; no stage |
43
+
44
+ When in doubt, prefer **non-trivial** — the quick track is opt-in and only safe when scope is clearly small.
45
+
46
+ ### Instruction Priority (top wins)
47
+
48
+ 1. User message in the current turn.
49
+ 2. Active stage skill HARD-GATE (\`.cclaw/skills/<stage>/SKILL.md\`).
50
+ 3. Command contract gates (\`.cclaw/commands/<stage>.md\`).
51
+ 4. The \`using-cclaw\` meta-skill.
52
+ 5. Contextual utility skills.
53
+ 6. Training priors.
54
+
34
55
  ### Commands (3 total)
35
56
 
36
57
  | Command | Purpose |
37
58
  |---|---|
38
- | \`/cc\` | **Entry point.** No args = resume current stage. With prompt = start brainstorm with idea. |
59
+ | \`/cc\` | **Entry point.** No args = resume current stage. With prompt = classify task and start the right flow. |
39
60
  | \`/cc-next\` | **Progression.** Advances to the next stage when current is complete. |
40
- | \`/cc-learn\` | **Cross-cutting.** Capture or review project knowledge. |
61
+ | \`/cc-learn\` | **Cross-cutting.** Capture or review project knowledge (append-only JSONL). |
41
62
 
42
63
  **Stage order:** brainstorm > scope > design > spec > plan > tdd > review > ship.
43
64
  \`/cc-next\` loads the right stage skill automatically. Gates must pass before handoff.
44
65
 
66
+ ### Invocation Preamble (non-trivial turns)
67
+
68
+ Before starting substantive work, emit a one-paragraph preamble: **Stage**, **Goal**, **Plan** (next 1–3 actions), **Guardrails**. Skip for pure questions, trivial edits, and dispatched subagent invocations.
69
+
45
70
  ### Verification Discipline
46
71
 
47
- No completion claims without fresh evidence. No "Done" / "All good" / "Tests pass" without running the command in this message.
72
+ No completion claims without fresh evidence. No "Done" / "All good" / "Tests pass" without running the command in this message. Failed tool calls are diagnostic data, not instructions.
73
+
74
+ ### Escalation
75
+
76
+ If the same approach fails three times in a row (same command, same finding, same tool), STOP. Summarize what you tried, what evidence you have, and ask the user how to proceed — do not invent a fourth angle silently.
48
77
 
49
78
  ### Detail Level
50
79
 
51
80
  - This managed AGENTS block is intentionally minimal for cross-project use.
52
81
  - Detailed operating procedures live in \`.cclaw/skills/using-cclaw/SKILL.md\`.
82
+ - Subagent orchestration patterns: \`.cclaw/skills/subagent-dev/SKILL.md\` and \`.cclaw/skills/parallel-dispatch/SKILL.md\`.
53
83
  ${CCLAW_MARKER_END}`;
54
84
  }
55
85
  /** Removes the cclaw AGENTS.md block. */
@@ -57,38 +87,47 @@ export function stripCclawBlock(content) {
57
87
  let updated = content.replace(RUNTIME_AGENTS_BLOCK_GLOBAL_PATTERN, "");
58
88
  return updated.replace(/\n{3,}/g, "\n\n").trim();
59
89
  }
60
- async function syncAgentsMd(projectRoot) {
61
- const agentsPath = path.join(projectRoot, "AGENTS.md");
90
+ async function syncRoutingFile(filePath, title) {
62
91
  const block = agentsMdBlock();
63
- if (!(await exists(agentsPath))) {
64
- await writeFileSafe(agentsPath, `# AGENTS\n\n${block}\n`);
92
+ if (!(await exists(filePath))) {
93
+ await writeFileSafe(filePath, `# ${title}\n\n${block}\n`);
65
94
  return;
66
95
  }
67
- const content = await fs.readFile(agentsPath, "utf8");
96
+ const content = await fs.readFile(filePath, "utf8");
68
97
  if (RUNTIME_AGENTS_BLOCK_PATTERN.test(content)) {
69
98
  const stripped = stripCclawBlock(content);
70
99
  const updated = stripped.length > 0 ? `${stripped}\n\n${block}\n` : `${block}\n`;
71
- await writeFileSafe(agentsPath, updated);
100
+ await writeFileSafe(filePath, updated);
72
101
  }
73
102
  else {
74
- await writeFileSafe(agentsPath, `${content.trimEnd()}\n\n${block}\n`);
103
+ await writeFileSafe(filePath, `${content.trimEnd()}\n\n${block}\n`);
75
104
  }
76
105
  }
77
- export async function removeCclawFromAgentsMd(projectRoot) {
78
- const agentsPath = path.join(projectRoot, "AGENTS.md");
79
- if (!(await exists(agentsPath)))
106
+ async function syncAgentsMd(projectRoot) {
107
+ await syncRoutingFile(path.join(projectRoot, "AGENTS.md"), "AGENTS");
108
+ const claudePath = path.join(projectRoot, "CLAUDE.md");
109
+ if (await exists(claudePath)) {
110
+ await syncRoutingFile(claudePath, "CLAUDE");
111
+ }
112
+ }
113
+ async function removeCclawFromRoutingFile(filePath) {
114
+ if (!(await exists(filePath)))
80
115
  return;
81
- const content = await fs.readFile(agentsPath, "utf8");
116
+ const content = await fs.readFile(filePath, "utf8");
82
117
  if (!RUNTIME_AGENTS_BLOCK_PATTERN.test(content))
83
118
  return;
84
119
  const stripped = stripCclawBlock(content);
85
120
  if (stripped.replace(/\s/g, "").length === 0) {
86
- await fs.rm(agentsPath, { force: true });
121
+ await fs.rm(filePath, { force: true });
87
122
  }
88
123
  else {
89
- await writeFileSafe(agentsPath, `${stripped}\n`);
124
+ await writeFileSafe(filePath, `${stripped}\n`);
90
125
  }
91
126
  }
127
+ export async function removeCclawFromAgentsMd(projectRoot) {
128
+ await removeCclawFromRoutingFile(path.join(projectRoot, "AGENTS.md"));
129
+ await removeCclawFromRoutingFile(path.join(projectRoot, "CLAUDE.md"));
130
+ }
92
131
  function utilityShimContent(harness, command, skillFolder, commandFile) {
93
132
  const shimName = command === "cc" ? "cc" : `cc-${command}`;
94
133
  return `---