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.
- package/dist/content/agents.d.ts +9 -0
- package/dist/content/agents.js +177 -6
- package/dist/content/examples.d.ts +17 -0
- package/dist/content/examples.js +275 -4
- package/dist/content/harness-tool-refs.d.ts +20 -0
- package/dist/content/harness-tool-refs.js +240 -0
- package/dist/content/meta-skill.js +203 -33
- package/dist/content/skills.js +106 -49
- package/dist/content/stage-schema.js +63 -11
- package/dist/content/start-command.js +63 -17
- package/dist/content/subagents.js +169 -0
- package/dist/content/templates.js +44 -6
- package/dist/content/utility-skills.d.ts +2 -1
- package/dist/content/utility-skills.js +141 -2
- package/dist/doctor.js +77 -0
- package/dist/harness-adapters.js +55 -16
- package/dist/install.js +19 -0
- package/package.json +1 -1
|
@@ -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
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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),
|
package/dist/harness-adapters.js
CHANGED
|
@@ -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
|
|
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
|
|
61
|
-
const agentsPath = path.join(projectRoot, "AGENTS.md");
|
|
90
|
+
async function syncRoutingFile(filePath, title) {
|
|
62
91
|
const block = agentsMdBlock();
|
|
63
|
-
if (!(await exists(
|
|
64
|
-
await writeFileSafe(
|
|
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(
|
|
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(
|
|
100
|
+
await writeFileSafe(filePath, updated);
|
|
72
101
|
}
|
|
73
102
|
else {
|
|
74
|
-
await writeFileSafe(
|
|
103
|
+
await writeFileSafe(filePath, `${content.trimEnd()}\n\n${block}\n`);
|
|
75
104
|
}
|
|
76
105
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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(
|
|
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(
|
|
121
|
+
await fs.rm(filePath, { force: true });
|
|
87
122
|
}
|
|
88
123
|
else {
|
|
89
|
-
await writeFileSafe(
|
|
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 `---
|