cclaw-cli 7.7.1 → 8.1.1

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.
Files changed (284) hide show
  1. package/README.md +211 -134
  2. package/dist/artifact-frontmatter.d.ts +51 -0
  3. package/dist/artifact-frontmatter.js +131 -0
  4. package/dist/artifact-paths.d.ts +7 -27
  5. package/dist/artifact-paths.js +20 -249
  6. package/dist/cancel.d.ts +16 -0
  7. package/dist/cancel.js +66 -0
  8. package/dist/cli.d.ts +2 -27
  9. package/dist/cli.js +107 -511
  10. package/dist/compound.d.ts +26 -0
  11. package/dist/compound.js +96 -0
  12. package/dist/config.d.ts +14 -51
  13. package/dist/config.js +23 -359
  14. package/dist/constants.d.ts +11 -18
  15. package/dist/constants.js +19 -106
  16. package/dist/content/antipatterns.d.ts +1 -0
  17. package/dist/content/antipatterns.js +109 -0
  18. package/dist/content/artifact-templates.d.ts +10 -0
  19. package/dist/content/artifact-templates.js +550 -0
  20. package/dist/content/cancel-command.d.ts +2 -2
  21. package/dist/content/cancel-command.js +25 -17
  22. package/dist/content/core-agents.d.ts +9 -233
  23. package/dist/content/core-agents.js +39 -768
  24. package/dist/content/decision-protocol.d.ts +1 -12
  25. package/dist/content/decision-protocol.js +27 -20
  26. package/dist/content/examples.d.ts +8 -42
  27. package/dist/content/examples.js +293 -425
  28. package/dist/content/idea-command.d.ts +2 -0
  29. package/dist/content/idea-command.js +38 -0
  30. package/dist/content/iron-laws.d.ts +4 -138
  31. package/dist/content/iron-laws.js +18 -197
  32. package/dist/content/meta-skill.d.ts +1 -3
  33. package/dist/content/meta-skill.js +57 -134
  34. package/dist/content/node-hooks.d.ts +12 -8
  35. package/dist/content/node-hooks.js +188 -838
  36. package/dist/content/recovery.d.ts +8 -0
  37. package/dist/content/recovery.js +179 -0
  38. package/dist/content/reference-patterns.d.ts +4 -13
  39. package/dist/content/reference-patterns.js +260 -389
  40. package/dist/content/research-playbooks.d.ts +8 -8
  41. package/dist/content/research-playbooks.js +108 -121
  42. package/dist/content/review-loop.d.ts +6 -192
  43. package/dist/content/review-loop.js +29 -731
  44. package/dist/content/skills.d.ts +8 -38
  45. package/dist/content/skills.js +681 -732
  46. package/dist/content/specialist-prompts/architect.d.ts +1 -0
  47. package/dist/content/specialist-prompts/architect.js +225 -0
  48. package/dist/content/specialist-prompts/brainstormer.d.ts +1 -0
  49. package/dist/content/specialist-prompts/brainstormer.js +168 -0
  50. package/dist/content/specialist-prompts/index.d.ts +2 -0
  51. package/dist/content/specialist-prompts/index.js +14 -0
  52. package/dist/content/specialist-prompts/planner.d.ts +1 -0
  53. package/dist/content/specialist-prompts/planner.js +182 -0
  54. package/dist/content/specialist-prompts/reviewer.d.ts +1 -0
  55. package/dist/content/specialist-prompts/reviewer.js +193 -0
  56. package/dist/content/specialist-prompts/security-reviewer.d.ts +1 -0
  57. package/dist/content/specialist-prompts/security-reviewer.js +133 -0
  58. package/dist/content/specialist-prompts/slice-builder.d.ts +1 -0
  59. package/dist/content/specialist-prompts/slice-builder.js +232 -0
  60. package/dist/content/stage-playbooks.d.ts +8 -0
  61. package/dist/content/stage-playbooks.js +404 -0
  62. package/dist/content/start-command.d.ts +2 -12
  63. package/dist/content/start-command.js +221 -207
  64. package/dist/flow-state.d.ts +21 -178
  65. package/dist/flow-state.js +67 -170
  66. package/dist/fs-utils.d.ts +6 -26
  67. package/dist/fs-utils.js +29 -162
  68. package/dist/gitignore.d.ts +2 -1
  69. package/dist/gitignore.js +51 -34
  70. package/dist/harness-detect.d.ts +10 -0
  71. package/dist/harness-detect.js +29 -0
  72. package/dist/harness-prompt.d.ts +26 -0
  73. package/dist/harness-prompt.js +142 -0
  74. package/dist/install.d.ts +35 -15
  75. package/dist/install.js +238 -1347
  76. package/dist/knowledge-store.d.ts +19 -163
  77. package/dist/knowledge-store.js +56 -590
  78. package/dist/logger.d.ts +8 -3
  79. package/dist/logger.js +13 -4
  80. package/dist/orchestrator-routing.d.ts +29 -0
  81. package/dist/orchestrator-routing.js +156 -0
  82. package/dist/run-persistence.d.ts +7 -118
  83. package/dist/run-persistence.js +29 -845
  84. package/dist/runtime/run-hook.entry.d.ts +1 -3
  85. package/dist/runtime/run-hook.entry.js +19 -4
  86. package/dist/runtime/run-hook.mjs +13 -1024
  87. package/dist/types.d.ts +25 -261
  88. package/dist/types.js +8 -36
  89. package/package.json +6 -3
  90. package/dist/artifact-linter/brainstorm.d.ts +0 -2
  91. package/dist/artifact-linter/brainstorm.js +0 -353
  92. package/dist/artifact-linter/design.d.ts +0 -18
  93. package/dist/artifact-linter/design.js +0 -444
  94. package/dist/artifact-linter/findings-dedup.d.ts +0 -56
  95. package/dist/artifact-linter/findings-dedup.js +0 -232
  96. package/dist/artifact-linter/plan.d.ts +0 -2
  97. package/dist/artifact-linter/plan.js +0 -826
  98. package/dist/artifact-linter/review-army.d.ts +0 -49
  99. package/dist/artifact-linter/review-army.js +0 -520
  100. package/dist/artifact-linter/review.d.ts +0 -2
  101. package/dist/artifact-linter/review.js +0 -113
  102. package/dist/artifact-linter/scope.d.ts +0 -2
  103. package/dist/artifact-linter/scope.js +0 -158
  104. package/dist/artifact-linter/shared.d.ts +0 -637
  105. package/dist/artifact-linter/shared.js +0 -2163
  106. package/dist/artifact-linter/ship.d.ts +0 -2
  107. package/dist/artifact-linter/ship.js +0 -250
  108. package/dist/artifact-linter/spec.d.ts +0 -2
  109. package/dist/artifact-linter/spec.js +0 -176
  110. package/dist/artifact-linter/tdd.d.ts +0 -118
  111. package/dist/artifact-linter/tdd.js +0 -1404
  112. package/dist/artifact-linter.d.ts +0 -15
  113. package/dist/artifact-linter.js +0 -517
  114. package/dist/codex-feature-flag.d.ts +0 -58
  115. package/dist/codex-feature-flag.js +0 -193
  116. package/dist/content/closeout-guidance.d.ts +0 -14
  117. package/dist/content/closeout-guidance.js +0 -44
  118. package/dist/content/diff-command.d.ts +0 -1
  119. package/dist/content/diff-command.js +0 -43
  120. package/dist/content/harness-doc.d.ts +0 -1
  121. package/dist/content/harness-doc.js +0 -65
  122. package/dist/content/hook-events.d.ts +0 -9
  123. package/dist/content/hook-events.js +0 -23
  124. package/dist/content/hook-manifest.d.ts +0 -81
  125. package/dist/content/hook-manifest.js +0 -156
  126. package/dist/content/hooks.d.ts +0 -11
  127. package/dist/content/hooks.js +0 -1972
  128. package/dist/content/idea.d.ts +0 -60
  129. package/dist/content/idea.js +0 -416
  130. package/dist/content/language-policy.d.ts +0 -2
  131. package/dist/content/language-policy.js +0 -13
  132. package/dist/content/learnings.d.ts +0 -6
  133. package/dist/content/learnings.js +0 -141
  134. package/dist/content/observe.d.ts +0 -19
  135. package/dist/content/observe.js +0 -86
  136. package/dist/content/opencode-plugin.d.ts +0 -1
  137. package/dist/content/opencode-plugin.js +0 -635
  138. package/dist/content/review-prompts.d.ts +0 -1
  139. package/dist/content/review-prompts.js +0 -104
  140. package/dist/content/runtime-shared-snippets.d.ts +0 -8
  141. package/dist/content/runtime-shared-snippets.js +0 -80
  142. package/dist/content/session-hooks.d.ts +0 -7
  143. package/dist/content/session-hooks.js +0 -107
  144. package/dist/content/skills-elicitation.d.ts +0 -1
  145. package/dist/content/skills-elicitation.js +0 -167
  146. package/dist/content/stage-command.d.ts +0 -2
  147. package/dist/content/stage-command.js +0 -17
  148. package/dist/content/stage-schema.d.ts +0 -117
  149. package/dist/content/stage-schema.js +0 -955
  150. package/dist/content/stages/_lint-metadata/index.d.ts +0 -2
  151. package/dist/content/stages/_lint-metadata/index.js +0 -97
  152. package/dist/content/stages/brainstorm.d.ts +0 -2
  153. package/dist/content/stages/brainstorm.js +0 -184
  154. package/dist/content/stages/design.d.ts +0 -2
  155. package/dist/content/stages/design.js +0 -288
  156. package/dist/content/stages/index.d.ts +0 -8
  157. package/dist/content/stages/index.js +0 -11
  158. package/dist/content/stages/plan.d.ts +0 -2
  159. package/dist/content/stages/plan.js +0 -191
  160. package/dist/content/stages/review.d.ts +0 -2
  161. package/dist/content/stages/review.js +0 -240
  162. package/dist/content/stages/schema-types.d.ts +0 -203
  163. package/dist/content/stages/schema-types.js +0 -1
  164. package/dist/content/stages/scope.d.ts +0 -2
  165. package/dist/content/stages/scope.js +0 -254
  166. package/dist/content/stages/ship.d.ts +0 -2
  167. package/dist/content/stages/ship.js +0 -159
  168. package/dist/content/stages/spec.d.ts +0 -2
  169. package/dist/content/stages/spec.js +0 -170
  170. package/dist/content/stages/tdd.d.ts +0 -4
  171. package/dist/content/stages/tdd.js +0 -273
  172. package/dist/content/state-contracts.d.ts +0 -1
  173. package/dist/content/state-contracts.js +0 -63
  174. package/dist/content/status-command.d.ts +0 -4
  175. package/dist/content/status-command.js +0 -109
  176. package/dist/content/subagent-context-skills.d.ts +0 -4
  177. package/dist/content/subagent-context-skills.js +0 -279
  178. package/dist/content/subagents.d.ts +0 -3
  179. package/dist/content/subagents.js +0 -997
  180. package/dist/content/templates.d.ts +0 -26
  181. package/dist/content/templates.js +0 -1692
  182. package/dist/content/track-render-context.d.ts +0 -18
  183. package/dist/content/track-render-context.js +0 -53
  184. package/dist/content/tree-command.d.ts +0 -1
  185. package/dist/content/tree-command.js +0 -64
  186. package/dist/content/utility-skills.d.ts +0 -30
  187. package/dist/content/utility-skills.js +0 -160
  188. package/dist/content/view-command.d.ts +0 -2
  189. package/dist/content/view-command.js +0 -92
  190. package/dist/delegation.d.ts +0 -649
  191. package/dist/delegation.js +0 -1539
  192. package/dist/early-loop.d.ts +0 -70
  193. package/dist/early-loop.js +0 -302
  194. package/dist/execution-topology.d.ts +0 -44
  195. package/dist/execution-topology.js +0 -95
  196. package/dist/gate-evidence.d.ts +0 -85
  197. package/dist/gate-evidence.js +0 -631
  198. package/dist/harness-adapters.d.ts +0 -151
  199. package/dist/harness-adapters.js +0 -756
  200. package/dist/harness-selection.d.ts +0 -31
  201. package/dist/harness-selection.js +0 -214
  202. package/dist/hook-schema.d.ts +0 -6
  203. package/dist/hook-schema.js +0 -114
  204. package/dist/hook-schemas/claude-hooks.v1.json +0 -10
  205. package/dist/hook-schemas/codex-hooks.v1.json +0 -10
  206. package/dist/hook-schemas/cursor-hooks.v1.json +0 -13
  207. package/dist/init-detect.d.ts +0 -2
  208. package/dist/init-detect.js +0 -50
  209. package/dist/internal/advance-stage/advance.d.ts +0 -89
  210. package/dist/internal/advance-stage/advance.js +0 -655
  211. package/dist/internal/advance-stage/cancel-run.d.ts +0 -8
  212. package/dist/internal/advance-stage/cancel-run.js +0 -19
  213. package/dist/internal/advance-stage/flow-state-coercion.d.ts +0 -3
  214. package/dist/internal/advance-stage/flow-state-coercion.js +0 -81
  215. package/dist/internal/advance-stage/helpers.d.ts +0 -14
  216. package/dist/internal/advance-stage/helpers.js +0 -145
  217. package/dist/internal/advance-stage/hook.d.ts +0 -8
  218. package/dist/internal/advance-stage/hook.js +0 -40
  219. package/dist/internal/advance-stage/parsers.d.ts +0 -72
  220. package/dist/internal/advance-stage/parsers.js +0 -357
  221. package/dist/internal/advance-stage/proactive-delegation-trace.d.ts +0 -24
  222. package/dist/internal/advance-stage/proactive-delegation-trace.js +0 -56
  223. package/dist/internal/advance-stage/review-loop.d.ts +0 -16
  224. package/dist/internal/advance-stage/review-loop.js +0 -199
  225. package/dist/internal/advance-stage/rewind.d.ts +0 -14
  226. package/dist/internal/advance-stage/rewind.js +0 -108
  227. package/dist/internal/advance-stage/start-flow.d.ts +0 -13
  228. package/dist/internal/advance-stage/start-flow.js +0 -241
  229. package/dist/internal/advance-stage/verify.d.ts +0 -21
  230. package/dist/internal/advance-stage/verify.js +0 -185
  231. package/dist/internal/advance-stage.d.ts +0 -7
  232. package/dist/internal/advance-stage.js +0 -138
  233. package/dist/internal/cohesion-contract-stub.d.ts +0 -24
  234. package/dist/internal/cohesion-contract-stub.js +0 -148
  235. package/dist/internal/compound-readiness.d.ts +0 -23
  236. package/dist/internal/compound-readiness.js +0 -102
  237. package/dist/internal/detect-public-api-changes.d.ts +0 -5
  238. package/dist/internal/detect-public-api-changes.js +0 -45
  239. package/dist/internal/detect-supply-chain-changes.d.ts +0 -6
  240. package/dist/internal/detect-supply-chain-changes.js +0 -138
  241. package/dist/internal/early-loop-status.d.ts +0 -7
  242. package/dist/internal/early-loop-status.js +0 -93
  243. package/dist/internal/envelope-validate.d.ts +0 -7
  244. package/dist/internal/envelope-validate.js +0 -66
  245. package/dist/internal/flow-state-repair.d.ts +0 -20
  246. package/dist/internal/flow-state-repair.js +0 -104
  247. package/dist/internal/plan-split-waves.d.ts +0 -190
  248. package/dist/internal/plan-split-waves.js +0 -764
  249. package/dist/internal/runtime-integrity.d.ts +0 -7
  250. package/dist/internal/runtime-integrity.js +0 -268
  251. package/dist/internal/slice-commit.d.ts +0 -7
  252. package/dist/internal/slice-commit.js +0 -619
  253. package/dist/internal/tdd-loop-status.d.ts +0 -14
  254. package/dist/internal/tdd-loop-status.js +0 -68
  255. package/dist/internal/tdd-red-evidence.d.ts +0 -7
  256. package/dist/internal/tdd-red-evidence.js +0 -153
  257. package/dist/internal/waiver-grant.d.ts +0 -62
  258. package/dist/internal/waiver-grant.js +0 -294
  259. package/dist/internal/wave-status.d.ts +0 -74
  260. package/dist/internal/wave-status.js +0 -506
  261. package/dist/managed-resources.d.ts +0 -53
  262. package/dist/managed-resources.js +0 -313
  263. package/dist/policy.d.ts +0 -10
  264. package/dist/policy.js +0 -167
  265. package/dist/retro-gate.d.ts +0 -9
  266. package/dist/retro-gate.js +0 -47
  267. package/dist/run-archive.d.ts +0 -61
  268. package/dist/run-archive.js +0 -391
  269. package/dist/runs.d.ts +0 -2
  270. package/dist/runs.js +0 -2
  271. package/dist/stack-detection.d.ts +0 -116
  272. package/dist/stack-detection.js +0 -489
  273. package/dist/streaming/event-stream.d.ts +0 -31
  274. package/dist/streaming/event-stream.js +0 -114
  275. package/dist/tdd-cycle.d.ts +0 -107
  276. package/dist/tdd-cycle.js +0 -289
  277. package/dist/tdd-verification-evidence.d.ts +0 -17
  278. package/dist/tdd-verification-evidence.js +0 -122
  279. package/dist/track-heuristics.d.ts +0 -27
  280. package/dist/track-heuristics.js +0 -154
  281. package/dist/util/slice-id.d.ts +0 -58
  282. package/dist/util/slice-id.js +0 -89
  283. package/dist/worktree-manager.d.ts +0 -20
  284. package/dist/worktree-manager.js +0 -108
@@ -1,827 +1,776 @@
1
- import { RUNTIME_ROOT, STAGE_TO_SKILL_FOLDER } from "../constants.js";
2
- import { nextStage as nextStageForTrack } from "../flow-state.js";
3
- import { FLOW_STAGES } from "../types.js";
4
- import { behaviorAnchorFor, stageExamples } from "./examples.js";
5
- import { INVESTIGATION_DISCIPLINE_BLOCK } from "./templates.js";
6
- import { reviewStackAwareRoutes, reviewStackAwareRoutingSummary, stageAutoSubagentDispatch, stageSchema, stageTrackRenderContext } from "./stage-schema.js";
7
- import { renderTrackTerminology } from "./track-render-context.js";
8
- import { referencePatternsForStage } from "./reference-patterns.js";
9
- import { harnessDelegationRecipes } from "../harness-adapters.js";
10
- const VERIFICATION_STAGES = ["tdd", "review", "ship"];
11
- const STAGE_LANGUAGE_POLICY_POINTER = "> Language policy: see `using-cclaw` section `Conversation Language Policy`.";
12
- // ---------- Cross-cutting universal mechanics (Layer 2 building blocks) ----------
13
- //
14
- // These are shared, structural blocks that get injected into every stage skill.
15
- // They check structural shape, not domain content. Each has a matching linter
16
- // rule in `src/artifact-linter.ts` so artifacts can fail when shape is missing.
17
- export const FORBIDDEN_SYCOPHANCY_PHRASES = [
18
- "you're absolutely right",
19
- "great point",
20
- "absolutely!",
21
- "thanks for catching",
22
- "thanks for the great",
23
- "good catch",
24
- "love this",
25
- "nailed it"
26
- ];
27
- export const FORBIDDEN_PLACEHOLDER_TOKENS = [
28
- "TBD",
29
- "TODO",
30
- "FIXME",
31
- "implement later",
32
- "similar to Task",
33
- "add appropriate error handling",
34
- "add proper logging",
35
- "fill this in",
36
- "<placeholder>"
37
- ];
38
- export const CONFIDENCE_FINDING_REGEX_SOURCE = "\\[P[123]\\]\\s*\\(confidence:\\s*\\d{1,2}/10\\)\\s+[^\\s]+(?::\\d+)?\\s+—";
39
- export function stopPerIssueBlock() {
40
- return `## STOP-per-issue Protocol
1
+ const PLAN_AUTHORING = `---
2
+ name: plan-authoring
3
+ trigger: when writing or updating .cclaw/flows/<slug>/plan.md
4
+ ---
41
5
 
42
- After each critical section (premise / alternatives / mode pick / each review finding), STOP and record one decision marker before continuing:
6
+ # Skill: plan-authoring
43
7
 
44
- - \`Q<n>:\` issue or open question
45
- - \`decision:\` — \`accept\` / \`reject\` / \`defer\` / \`skip — no issues\`
46
- - \`rationale:\` — one line, evidence-backed
8
+ Use this skill whenever you create or modify any \`.cclaw/flows/<slug>/plan.md\`.
47
9
 
48
- Do not batch decisions. Do not silently move on. The artifact MUST contain at least one \`decision:\` marker per critical section.
49
- `;
50
- }
51
- export function confidenceCalibrationBlock() {
52
- return `## Confidence Calibration
10
+ ## Rules
11
+
12
+ 1. **Frontmatter is mandatory.** Every plan starts with the YAML block from \`.cclaw/lib/templates/plan.md\`. Required keys: \`slug\`, \`stage\`, \`status\`, \`ac\`, \`last_specialist\`, \`refines\`, \`shipped_at\`, \`ship_commit\`, \`review_iterations\`, \`security_flag\`.
13
+ 2. **AC ids are sequential** starting at \`AC-1\`. They must match the AC table inside the body.
14
+ 3. **Each AC is observable.** Verification line is mandatory. If you cannot write the verification, the AC is not real.
15
+ 4. **The traceability block at the end** is rebuilt by \`commit-helper.mjs\`. Do not edit it by hand once a commit was recorded.
16
+ 5. **Out-of-scope items** stay in the body. Do not let them leak into AC.
17
+
18
+ ## When refining a shipped slug
53
19
 
54
- Findings, recommendations, and review notes use the calibrated finding format:
20
+ - Quote at most one paragraph from \`.cclaw/flows/shipped/<old-slug>/plan.md\`.
21
+ - Set \`refines: <old-slug>\` in the new plan's frontmatter.
22
+ - Do not copy the shipped AC verbatim — write fresh AC for the refinement.
55
23
 
56
- \`[P1|P2|P3] (confidence: <n>/10) <repo-relative-path>[:<line>] — <one-line description>\`
24
+ ## What to refuse
57
25
 
58
- - \`P1\` blocks merge; \`P2\` should be addressed; \`P3\` is nice-to-have.
59
- - Confidence \`< 7\` suppress unless severity is \`P1\`.
60
- - "What evidence would change this?" every finding must answer it inline or in the next bullet.
61
- - Never assert "this is fine" without confidence; never assert confidence above \`8\` without a cited artifact, line, or test.
26
+ - Plans without AC.
27
+ - Plans whose AC count exceeds 12 (split first).
28
+ - Plans that change scope between brainstormer and planner without going back to brainstormer.
62
29
  `;
63
- }
64
- export function outsideVoiceSlotBlock() {
65
- return `## Outside Voice Slot (optional)
30
+ const AC_TRACEABILITY = `---
31
+ name: ac-traceability
32
+ trigger: when committing changes for an active cclaw run
33
+ ---
34
+
35
+ # Skill: ac-traceability
36
+
37
+ cclaw has one mandatory gate: every commit produced inside \`/cc\` references exactly one AC, and the AC ↔ commit chain is recorded in \`flow-state.json\`.
66
38
 
67
- Reserve a section titled \`## Outside Voice\` (or \`## Outside Voice — <model/critic>\`) for a second-model or fresh-context critic perspective when used. Required shape when present:
39
+ ## Rules
68
40
 
69
- - \`source:\` model id, critic agent name, or human reviewer handle
70
- - \`prompt:\` exact frame sent (or reference to \`docs/quality-gates.md\` recipe)
71
- - \`tension:\` at least one disagreement with the main draft, or \`none — converged\`
72
- - \`resolution:\` accepted / rejected / merged / deferred + one-line rationale
41
+ 1. Use \`node .cclaw/hooks/commit-helper.mjs --ac=AC-N --message="..."\` for every AC commit. Do not call \`git commit\` directly.
42
+ 2. Stage only AC-related changes before invoking the hook.
43
+ 3. The hook will refuse the commit if:
44
+ - \`AC-N\` is not declared in the active plan;
45
+ - \`flow-state.json\` schemaVersion is not \`2\`;
46
+ - nothing is staged.
47
+ 4. After the commit succeeds, the hook records the SHA in \`flow-state.json\` under the matching AC and re-renders the traceability block in \`plans/<slug>.md\`.
48
+ 5. \`runCompoundAndShip\` refuses to ship a slug with any pending AC. There is no override.
73
49
 
74
- Empty when not used; do not fabricate an outside voice.
50
+ ## When you accidentally committed without the hook
51
+
52
+ - \`flow-state.json\` is now out of sync with the working tree.
53
+ - Run the hook manually for the affected AC: \`node .cclaw/hooks/commit-helper.mjs --ac=AC-N --message="resync"\` while staging an empty change is not allowed; instead, edit \`.cclaw/state/flow-state.json\` to add the SHA to the AC entry by hand and verify with the orchestrator before continuing.
75
54
  `;
76
- }
77
- export function antiSycophancyBlock() {
78
- const phrases = FORBIDDEN_SYCOPHANCY_PHRASES.map((p) => `\`${p}\``).join(", ");
79
- return `## Anti-sycophancy
55
+ const REFINEMENT = `---
56
+ name: refinement
57
+ trigger: when /cc detects an existing plan (active or shipped) for the new task
58
+ ---
80
59
 
81
- Forbidden response openers when receiving review, critic output, or user feedback: ${phrases}.
60
+ # Skill: refinement
82
61
 
83
- Replace agreement theater with one of:
62
+ \`/cc\` performs existing-plan detection at the start of every invocation. When it finds a fuzzy match, the user is asked to choose one of:
84
63
 
85
- - \`Verified<evidence>\` (you actually checked)
86
- - \`Disagree<reason>\` (you push back with substance)
87
- - \`Investigating — <next step>\` (you do not yet know)
64
+ - **amend**keep the active plan, add new AC, leave already-committed AC intact;
65
+ - **rewrite**replace the active plan body and AC entirely (commits remain in git, but AC ids restart);
66
+ - **refine shipped** create a new plan with \`refines: <old-slug>\` linking to the shipped slug;
67
+ - **new** — start an unrelated plan.
88
68
 
89
- Never agree before reading the cited evidence. Never apologize for asking a clarifying question.
90
- `;
91
- }
92
- export function noPlaceholdersBlock() {
93
- const tokens = FORBIDDEN_PLACEHOLDER_TOKENS.map((p) => `\`${p}\``).join(", ");
94
- return `## NO PLACEHOLDERS Rule
69
+ ## Rules for refinement
70
+
71
+ 1. \`refines: <old-slug>\` is set in the new plan's frontmatter and must match a real shipped slug.
72
+ 2. Do not move artifacts out of \`.cclaw/flows/shipped/\`. The shipped slug stays read-only.
73
+ 3. The new plan can quote up to one paragraph from the shipped plan but must restate the full Context for the refinement.
74
+ 4. AC ids restart at AC-1 in the new plan. Do not number "AC-13" because the shipped slug had 12 AC.
75
+ 5. \`knowledge.jsonl\` will record the new entry with \`refines: <old-slug>\` so the index forms a chain.
76
+
77
+ ## What the orchestrator surfaces
95
78
 
96
- Plans, specs, designs, and review artifacts MUST NOT contain placeholder tokens: ${tokens}. Use repo-relative paths and concrete commands; if a value is genuinely unknown, write the open question explicitly with a \`Q<n>:\` marker and a \`decision: defer — <reason>\` row instead of inserting a placeholder token.
79
+ - last_specialist of the active plan, so the user can see "stopped at architect" or "review iteration 3 in progress".
80
+ - The AC table with their statuses (\`pending\` / \`committed\`).
81
+ - Whether \`security_flag\` was set.
82
+ - A direct link to \`.cclaw/flows/shipped/<slug>/manifest.md\` if the match is a shipped slug.
97
83
  `;
98
- }
99
- export function watchedFailProofBlock() {
100
- return `## Watched-fail Proof
84
+ const PARALLEL_BUILD = `---
85
+ name: parallel-build
86
+ trigger: when planner topology = parallel-build
87
+ ---
101
88
 
102
- Any "the failure is real" claim (failing test, broken build, regression catch, deployment fail) MUST include a watched-fail proof line in the artifact:
89
+ # Skill: parallel-build
103
90
 
104
- \`proof: <iso-ts> | <observed snippet first 200 chars> | source: <command or log path>\`
91
+ \`parallel-build\` is the only parallelism allowed during build. It is opt-in. The orchestrator never picks it without planner naming it explicitly in \`plans/<slug>.md\` Topology section.
105
92
 
106
- For TDD, watched-RED proof is mandatory before \`stage-complete\` accepts the slice. Dispatch \`slice-builder\` end-to-end: it owns RED/GREEN evidence rows, refactor coverage per the hook flags, \`<artifacts-dir>/tdd-slices/S-<id>.md\`, and (when wired) \`slice-completed\`. The linter mirrors phase history into auto-render markers in \`06-tdd.md\` — never hand-fill those fragments.
107
- `;
108
- }
109
- /**
110
- * Stages that perform real investigation work. The shared
111
- * `INVESTIGATION_DISCIPLINE_BLOCK` is rendered once per stage skill in this
112
- * set so the search → graph → narrow-read → draft ladder appears verbatim
113
- * across the elicitation/spec/plan/tdd/review pipeline. `ship` is excluded:
114
- * it consumes the upstream trace rather than producing one.
115
- */
116
- export const INVESTIGATION_DISCIPLINE_STAGES = new Set([
117
- "brainstorm",
118
- "scope",
119
- "design",
120
- "spec",
121
- "plan",
122
- "tdd",
123
- "review"
124
- ]);
125
- export function investigationDisciplineBlock() {
126
- return INVESTIGATION_DISCIPLINE_BLOCK;
127
- }
128
- export function behaviorAnchorBlock(stage) {
129
- const anchor = behaviorAnchorFor(stage);
130
- if (!anchor)
131
- return "";
132
- const ruleHint = anchor.ruleHint && anchor.ruleHint.trim().length > 0
133
- ? `\n\nRule hint: ${anchor.ruleHint.trim()}`
134
- : "";
135
- return `## Behavior anchor
136
-
137
- Anchored to artifact section: \`${anchor.section}\`.
138
-
139
- - Bad: ${anchor.bad}
140
- - Good: ${anchor.good}${ruleHint}
141
- `;
142
- }
143
- function crossCuttingMechanicsBlock(stage) {
144
- // All stages share the universal mechanics, but each stage's matching
145
- // linter rules decide what is mandatory vs. structural-only.
146
- const blocks = [
147
- stopPerIssueBlock(),
148
- confidenceCalibrationBlock(),
149
- outsideVoiceSlotBlock(),
150
- antiSycophancyBlock(),
151
- noPlaceholdersBlock()
152
- ];
153
- if (stage === "tdd" || stage === "review" || stage === "ship") {
154
- blocks.push(watchedFailProofBlock());
155
- }
156
- if (INVESTIGATION_DISCIPLINE_STAGES.has(stage)) {
157
- blocks.push(investigationDisciplineBlock());
158
- }
159
- const anchor = behaviorAnchorBlock(stage);
160
- if (anchor.length > 0) {
161
- blocks.push(anchor);
162
- }
163
- return blocks.join("\n");
164
- }
165
- function whenNotToUseBlock(items) {
166
- if (items.length === 0) {
167
- return "";
168
- }
169
- return `## When Not to Use
170
- ${items.map((item) => `- ${item}`).join("\n")}
93
+ ## Pre-conditions (all must hold)
171
94
 
172
- `;
173
- }
174
- /**
175
- * TDD-only prelude after `<EXTREMELY-IMPORTANT>`: wave routing + canonical
176
- * `slice-builder` dispatch. Uses literal commands so pattern-matching on read
177
- * matches operator scripts.
178
- *
179
- * Empty for non-TDD stages.
180
- */
181
- export function tddTopOfSkillBlock(stage) {
182
- if (stage !== "tdd")
183
- return "";
184
- return `## TDD orchestration primer
95
+ 1. **≥4 AC** in the plan.
96
+ 2. **≥2 distinct touchSurface clusters** — there is at least one pair of AC whose \`touchSurface\` arrays are completely disjoint.
97
+ 3. Every AC in a parallel wave carries \`parallelSafe: true\`.
98
+ 4. No AC depends on outputs of another AC in the same wave.
185
99
 
186
- **MANDATE controller preserves TDD evidence.** In TDD the controller routes, dispatches when needed, and reconciles. Default topology is \`auto\` + \`balanced\`: feature-atomic units contain internal 2-5 minute RED/GREEN/REFACTOR steps. Inline execution is allowed only when \`wave-status\`/the plan selects \`inline\`; it still must satisfy RED-before-GREEN, AC traceability, path containment, verification, managed commit/worktree, lockfile twin, and orphan-change gates. \`single-builder\` and \`parallel-builders\` use \`slice-builder\`; \`strict-micro\` preserves one tiny task per schedulable slice for high-risk work.
100
+ For ≤4 AC the orchestrator picks \`inline\` even when AC look "parallelSafe". The git-worktree + sub-agent dispatch overhead is not worth saving 1-2 AC of wall-clock.
187
101
 
188
- **Step 1 Wave status (always first):**
189
- \`node .cclaw/cli.mjs internal wave-status --json\`
102
+ ## Slice = 1+ AC with shared touchSurface
190
103
 
191
- The output names: \`waves[]\` (closed/open), \`nextDispatch.waveId\`, \`nextDispatch.mode\` (\`wave-fanout\`, \`single-slice\`, or \`blocked\`), \`nextDispatch.topology\` (\`inline\`, \`single-builder\`, \`parallel-builders\`, or \`strict-micro\`), \`nextDispatch.readyToDispatch\` (slice ids), and \`nextDispatch.pathConflicts\` (overlapping \`claimedPaths\` between members).
104
+ A **slice** is one or more AC whose \`touchSurface\` arrays intersect. AC with disjoint touchSurfaces go into different slices; AC with overlapping touchSurfaces stay in the **same** slice (run sequentially inside it). Each slice is owned by exactly one slice-builder sub-agent.
192
105
 
193
- **Step 2 Decide automatically (no user question when paths disjoint):**
106
+ ## Hard cap: 5 parallel slices per wave
194
107
 
195
- | \`topology\` | \`pathConflicts\` | Action |
196
- |---------------------------|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
197
- | \`parallel-builders\` | \`[]\` | **Fan out independent substantial units in one tool batch.** Emit one \`Task\` per routed ready builder in a single controller message. Do NOT ask. |
198
- | \`single-builder\` | any/none | Dispatch one \`slice-builder\` for the next feature-atomic unit; serialize remaining ready units. |
199
- | \`inline\` | \`[]\` | Execute inline only for low-risk inline-safe units; record equivalent RED/GREEN/REFACTOR evidence before completion. |
200
- | \`strict-micro\` | any/none | Preserve micro-slice sequencing: one tiny task/slice at a time unless the strict plan explicitly proves safe fan-out. |
201
- | \`blocked\`/mode blocked | non-empty | Issue exactly one AskQuestion (resolve overlap, split/serialize, or adjust claimedPaths), then re-run \`wave-status\`. |
108
+ If the slug produces more than 5 slices, **merge the thinner slices into fatter ones** (group AC by adjacent files / shared module) until you have ≤5. **Do not generate "wave 2", "wave 3", etc.** If after merging you still have >5 slices, the slug is too large — split it into multiple slugs.
202
109
 
203
- **Step 3 — Dispatch protocol per delegated slice:** for \`single-builder\`, \`parallel-builders\`, and delegated \`strict-micro\`, in the SAME controller message that issues the \`Task\` call:
110
+ This 5-slice cap is the v7-era constraint we kept on purpose:
204
111
 
205
- 1. Append \`delegation-record --status=scheduled\` for the \`slice-builder\` span (one row per slice; reuse the same \`spanId\` across the entire RED → GREEN → REFACTOR → DOC lifecycle).
206
- 2. Append \`delegation-record --status=launched\` immediately after.
207
- 3. Issue the harness Task call: \`Task(subagent_type=<harness slice-builder mapping>, description="slice-builder <slice-id>", prompt="<full slice context, claimedPaths, plan-row, AC ids, paths to source/tests, slice-card path>")\`.
208
- 4. The slice-builder span ACKs locally (\`delegation-record --status=acknowledged\`) and runs the **complete** RED → GREEN → REFACTOR → DOC cycle inside the span — including writing \`tdd-slices/S-<id>.md\` and emitting \`--phase=red\`, \`--phase=green\`, \`--phase=refactor\` (or \`--phase=refactor-deferred\` with rationale), and \`--phase=doc\` rows on its own.
209
- 5. The controller waits for ALL parallel spans to terminate before reconciling. Do not page back into the controller chat between spans.
112
+ - orchestration cost grows non-linearly past 5 sub-agents (context shuffling, integration review, conflict surface);
113
+ - 5 fits comfortably under the harness sub-agent quota everywhere we tested (Claude Code, Cursor, OpenCode, Codex);
114
+ - larger fan-outs reliably produce more integration findings than wall-clock saved.
210
115
 
211
- For \`inline\`, skip the Task call but do not skip evidence: write the same per-slice card/evidence refs, run RED before GREEN, verify before completion, and keep all path/commit/worktree gates satisfied.
116
+ ## Execution
212
117
 
213
- **Step 4 Wave closeout:** after all in-flight slices report \`completed\`:
118
+ 1. Orchestrator reads \`plans/<slug>.md\` Topology section, extracts the slice list (max 5).
119
+ 2. For each slice, dispatch one \`slice-builder\` sub-agent. Pass:
120
+ - the slice id,
121
+ - the AC ids it owns,
122
+ - the slice's \`touchSurface\` (the only paths the slice may modify),
123
+ - the worktree path (see below).
124
+ 3. Each slice-builder runs the full TDD cycle (RED → GREEN → REFACTOR) for every AC it owns, sequentially inside the slice, in its own working tree.
125
+ 4. After all slice-builders return, the orchestrator invokes \`reviewer\` in mode \`integration\` (separate sub-agent if the harness supports it; inline otherwise). Integration reviewer checks path conflicts, double-edits, the AC↔commit chain across all slices, and integration tests covering the slice boundary.
126
+ 5. If integration finds problems, the orchestrator dispatches \`slice-builder\` in \`fix-only\` mode against the cited file:line refs.
214
127
 
215
- 1. Re-run \`wave-status --json\`. Confirm the wave is \`closed\` and the next dispatch is the following wave (or \`closeout\`).
216
- 2. If \`integrationCheckRequired\` is true, dispatch \`integration-overseer\` (proactive) and append the \`cclaw_integration_overseer_skipped\` audit kind only when the contract waives it.
217
- 3. If \`wave-status\` reports another \`wave-fanout\` next dispatch with disjoint paths, **immediately repeat Step 2 — do not pause for \"continue\"**.
218
- 4. When all waves are closed and no more slices remain ready, run \`stage-complete tdd\`.
128
+ ## Git-worktree pattern (when harness supports sub-agent dispatch)
219
129
 
220
- **Step 5 Auto-advance after stage-complete:** when \`stage-complete\` returns \`ok\` with a new \`currentStage\`, immediately load the next stage skill and continue. The user does NOT need to retype \`/cc\`. Announce \"Stage tdd complete → entering <next>. Continuing.\" and proceed.
130
+ Each parallel slice runs in its own \`git worktree\` rooted at \`.cclaw/worktrees/<slug>-<slice-id>/\`:
221
131
 
222
- Wave resume: reuse \`wave-status\` outputs and parallelize unfinished members instead of restarting finished slices.
132
+ \`\`\`bash
133
+ $ git worktree add .cclaw/worktrees/<slug>-slice-1 -b cclaw/<slug>/slice-1
134
+ $ git worktree add .cclaw/worktrees/<slug>-slice-2 -b cclaw/<slug>/slice-2
135
+ $ git worktree add .cclaw/worktrees/<slug>-slice-3 -b cclaw/<slug>/slice-3
136
+ \`\`\`
223
137
 
224
- ---
225
- `;
226
- }
227
- /**
228
- * Review-only prelude: mandates parallel reviewer / security-reviewer dispatch
229
- * via harness Task and forbids inline authoring of findings.
230
- *
231
- * Empty for non-review stages.
232
- */
233
- export function reviewTopOfSkillBlock(stage) {
234
- if (stage !== "review")
235
- return "";
236
- return `## Review orchestration primer
237
-
238
- **MANDATE — controller never authors findings inline.** In review the controller orchestrates; \`reviewer\` (functional/spec/correctness/architecture/perf/observability) and \`security-reviewer\` (security sweep + dependency/version audit) are the **mandatory delegated workers** that produce findings, lens coverage, and the verdict input. Typing \`## Layer 1 Findings\`, \`## Layer 2 Findings\`, \`## Lens Coverage\`, or \`## Final Verdict\` content directly into \`07-review.md\` in the controller chat is a protocol violation. The controller writes ONLY the reconciled multi-specialist verdict block AFTER all reviewer Tasks return.
239
-
240
- **Step 1 — Diff scope (always first):**
241
- \`git diff --stat <base>...HEAD\` and \`git diff --name-only <base>...HEAD\`.
242
- If the diff is empty, exit early with APPROVED (no changes to review).
243
-
244
- **Step 2 — Dispatch the review army in PARALLEL (single controller message):**
245
-
246
- | Lens | Worker | Mandatory? |
247
- |--------------------------|-----------------------|------------|
248
- | Spec compliance / Layer 1 | \`reviewer\` | yes |
249
- | Layer 2 cross-slice / correctness / observability | \`reviewer\` | yes |
250
- | Security sweep + dep/version audit | \`security-reviewer\` | yes (or \`NO_SECURITY_IMPACT\` attestation) |
251
- | Adversarial second opinion | \`reviewer\` (adversarial framing) | only if trust boundaries moved OR diff is large+high-risk |
252
-
253
- Emit ONE \`Task\` per lens in a single controller message. For each lens:
254
-
255
- 1. Append \`delegation-record --status=scheduled\` for the lens span (one row per lens; reuse the same \`spanId\` for the lens lifecycle).
256
- 2. Append \`delegation-record --status=launched\` immediately after.
257
- 3. Issue the harness Task call: \`Task(subagent_type=<harness reviewer/security-reviewer mapping>, description="<lens> review", prompt="<diff range, files, AC ids, upstream artifacts (spec, design, tdd Per-Slice Reviews), expected output schema for 07-review-army.json>")\`.
258
- 4. The reviewer span ACKs locally and writes its findings/lens coverage to \`07-review-army.json\` (and the structured findings table in \`07-review.md\`) on its own — including \`NO_SECURITY_IMPACT\` rationale if a security pass yields zero findings.
259
- 5. The controller waits for ALL lens spans to return before reconciling.
260
-
261
- **Step 3 — Reconcile and verdict:** after all lens spans complete:
262
-
263
- 1. Run \`validateReviewArmy\` (helper or linter) on \`07-review-army.json\`.
264
- 2. Dedup by fingerprint, mark multi-specialist confirmations.
265
- 3. Confirm acceptance criteria coverage and Pre-Critic / Lens Coverage / Anti-sycophancy fields are present (linter requires them).
266
- 4. Compute the final verdict: APPROVED, APPROVED_WITH_CONCERNS, or BLOCKED.
267
- 5. If BLOCKED, emit \`ROUTE_BACK_TO_TDD\` with the blocking finding ids and the managed \`npx cclaw-cli internal rewind tdd\` command. Do NOT silently stop.
268
-
269
- **Step 4 — Auto-advance after stage-complete:** when \`stage-complete review\` returns \`ok\` with a new \`currentStage\` (typically \`ship\`), immediately load the next stage skill and continue. Announce \"Stage review complete → entering <next>. Continuing.\" and proceed without waiting for the user to retype \`/cc\`.
138
+ Each slice-builder sub-agent runs with its worktree path as cwd. After all slices finish:
270
139
 
271
- ---
272
- `;
273
- }
274
- function artifactTemplatePathForStage(stage) {
275
- const stageIndex = FLOW_STAGES.indexOf(stage) + 1;
276
- const stageNumber = String(stageIndex).padStart(2, "0");
277
- return `${RUNTIME_ROOT}/templates/${stageNumber}-${stage}.md`;
278
- }
279
- function contextLoadingBlock(stage, trace, executionModel) {
280
- const readLines = trace.readsFrom.length > 0
281
- ? trace.readsFrom.map((value) => `- \`${value}\``).join("\n")
282
- : "- (first stage — no upstream artifacts)";
283
- const inputs = executionModel.inputs.length > 0
284
- ? executionModel.inputs.map((item) => `- ${item}`).join("\n")
285
- : "- (first stage — no required inputs)";
286
- const requiredContext = executionModel.requiredContext.length > 0
287
- ? executionModel.requiredContext.map((item) => `- ${item}`).join("\n")
288
- : "- None beyond this skill";
289
- const artifactTemplatePath = artifactTemplatePathForStage(stage);
290
- return `## Context Loading
291
-
292
- Before execution:
293
- 1. Read \`.cclaw/state/flow-state.json\`.
294
- - If the file is missing, do **not** invent an active run — this is normal for fresh init. Route to \`/cc <idea>\` first.
295
- 2. Load active artifacts from \`.cclaw/artifacts/\`.
296
- 3. Load upstream artifacts required by this stage:
297
- ${readLines}
298
- 4. Read the state contract from \`.cclaw/templates/state-contracts/<stage>.json\` for required fields, taxonomies, and derived markdown path.
299
- 5. Read the canonical artifact template at \`${artifactTemplatePath}\` to preserve heading/per-row tables contracts (stable section names and column order) plus calibrated review block scaffolding. Preserve existing substantive bullets/rows already in the artifact; never overwrite the artifact wholesale from the template — patch only sections you author this turn.
300
- 6. Extract upstream decisions, constraints, and open questions into the current artifact's \`Upstream Handoff\` section when present.
301
- 7. Confirm context readiness: upstream artifact freshness, required context, canonical template shape, relevant in-repo/reference patterns, and unresolved blockers are known. If any item is missing, load it or stop before drafting.
302
- 8. Before doing stage work, give a compact user-facing drift preamble: "Carrying forward: <1-3 bullets>. Drift since upstream: None / <specific drift>. Recommendation: continue / re-scope."
303
- 9. If you change an upstream decision, record an explicit drift reason in the current artifact before continuing.
304
- 10. Confirm stage inputs:
305
- ${inputs}
306
- 11. Confirm required context:
307
- ${requiredContext}
308
- 12. Use the injected knowledge digest; only fall back to full \`.cclaw/knowledge.jsonl\` when insufficient.
309
- `;
310
- }
311
- function autoSubagentDispatchBlock(stage, track) {
312
- const rules = stageAutoSubagentDispatch(stage);
313
- if (rules.length === 0)
314
- return "";
315
- const schema = stageSchema(stage, track);
316
- const rows = rules
317
- .map((rule) => {
318
- const userGate = rule.requiresUserGate ? "required" : "not required";
319
- const dispatchClass = rule.dispatchClass ?? "stage-specialist";
320
- const returnSchema = rule.returnSchema ?? "agent-default";
321
- const runPhase = rule.runPhase ?? "any";
322
- return `| ${rule.agent} | ${rule.mode} | ${runPhase} | ${dispatchClass} | ${returnSchema} | ${userGate} | ${rule.when} | ${rule.purpose} |`;
323
- })
324
- .join("\n");
325
- const mandatory = schema.mandatoryDelegations;
326
- const mandatoryList = mandatory.length > 0 ? mandatory.map((a) => `\`${a}\``).join(", ") : "none";
327
- const delegationLogRel = `${RUNTIME_ROOT}/state/delegation-log.json`;
328
- const delegationEventsRel = `${RUNTIME_ROOT}/state/delegation-events.jsonl`;
329
- const hasPostElicitation = rules.some((rule) => rule.runPhase === "post-elicitation");
330
- const runPhaseLegend = hasPostElicitation
331
- ? `\nRun Phase legend: \`post-elicitation\` = run only AFTER the adaptive elicitation Q&A loop converges (forcing questions answered/skipped/waived OR user stop-signal recorded). \`pre-elicitation\` = run before any user dialogue (rare). \`any\` = no ordering constraint.`
332
- : "";
333
- return `## Automatic Subagent Dispatch
334
- | Agent | Mode | Run Phase | Class | Return Schema | User Gate | Trigger | Purpose |
335
- |---|---|---|---|---|---|---|---|
336
- ${rows}
337
- Mandatory: ${mandatoryList}. Record lifecycle rows in \`${delegationLogRel}\` and append-only \`${delegationEventsRel}\` before completion.${runPhaseLegend}
338
- ### Harness Dispatch Contract — use true harness dispatch: Claude Task, Cursor generic dispatch, OpenCode \`.opencode/agents/<agent>.md\` via Task/@agent, Codex \`.codex/agents/<agent>.toml\`. Do not collapse OpenCode or Codex to role-switch by default. Worker ACK Contract: ACK must include \`spanId\`, \`dispatchId\`, \`dispatchSurface\`, \`agentDefinitionPath\`, and \`ackTs\`; never claim \`fulfillmentMode: "isolated"\` without matching lifecycle proof. Canonical helper (same flags as \`delegation-record.mjs --help\`): \`node .cclaw/hooks/delegation-record.mjs --stage=<stage> --agent=<agent> --mode=<mandatory|proactive> --status=<scheduled|launched|acknowledged|completed|...> --span-id=<id> --dispatch-id=<id> --dispatch-surface=<surface> --agent-definition-path=<path> [--ack-ts=<iso>] [--evidence-ref=<ref>] --json\`. Lifecycle order: \`scheduled → launched → acknowledged → completed\` on one span (reuse the same span id); completed isolated/generic rows require a prior ACK event for that span or \`--ack-ts=<iso>\`. For a partial audit trail, \`--repair --span-id=<id> --repair-reason="<why>"\` appends missing phases (see \`--help\`) instead of inventing shortcuts.
339
-
340
- If you must re-dispatch the same agent in the same stage before the previous span has a terminal row, pass \`--supersede=<prevSpanId>\` (closes the previous span as \`stale\` with \`supersededBy=<newSpanId>\`) or \`--allow-parallel\` (records both spans as concurrently active and tags the new row with \`allowParallel: true\`). Without one of those flags, a duplicate scheduled write on the same \`(stage, agent)\` pair fails with \`exit 2\` and \`{ ok: false, error: "dispatch_duplicate" }\`. Lifecycle timestamps are also validated: \`startTs ≤ launchedTs ≤ ackTs ≤ completedTs\` and per-span \`ts\` is non-decreasing — non-monotonic values fail with \`exit 2\` and \`{ ok: false, error: "delegation_timestamp_non_monotonic" }\`.
341
-
342
- ${perHarnessLifecycleRecipeBlock()}`;
343
- }
344
- function perHarnessLifecycleRecipeBlock() {
345
- const recipes = harnessDelegationRecipes();
346
- const rows = recipes
347
- .map((recipe) => `| \`${recipe.harnessId}\` | \`${recipe.dispatchSurface}\` | \`${recipe.agentDefinitionExample}\` | \`${recipe.fulfillmentMode}\` |`)
348
- .join("\n");
349
- return `### Per-Harness Lifecycle Recipe — placeholders only
350
- Reuse the same \`<span-id>\` and \`<dispatch-id>\` across scheduled -> launched -> acknowledged -> completed; substitute neutral tokens \`<agent-name>\`, \`<stage>\`, \`<iso-ts>\`, \`<artifact-anchor>\`. Full command sequences live in \`docs/harnesses.md\`.
351
- | Harness | Dispatch surface | Agent definition path | fulfillmentMode |
352
- |---|---|---|---|
353
- ${rows}
354
- `;
355
- }
356
- function researchPlaybooksBlock(playbooks) {
357
- if (playbooks.length === 0)
358
- return "";
359
- const rows = playbooks
360
- .map((playbook) => `\`${RUNTIME_ROOT}/skills/${playbook}\``)
361
- .join("; ");
362
- return `## Research Playbooks
363
- Execute in primary agent context before locking the stage; record outcomes in the artifact when relevant: ${rows}.
364
- `;
365
- }
366
- function referencePatternsBlock(stage) {
367
- const patterns = referencePatternsForStage(stage);
368
- if (patterns.length === 0)
369
- return "";
370
- const summaries = patterns
371
- .map((pattern) => {
372
- const contract = pattern.contracts.find((item) => item.stage === stage);
373
- const sections = contract ? contract.artifactSections.join(", ") : "n/a";
374
- return `${pattern.title} (sections: ${sections})`;
375
- })
376
- .join("; ");
377
- return `## Reference Patterns
378
- Prompt-only; no runtime/delegation changes. These compact pattern titles come from the internal registry; use the behavior and artifact sections, not the source project history. Use: ${summaries}.
379
- `;
380
- }
381
- function reviewSectionsBlock(sectionsInput) {
382
- if (sectionsInput.length === 0)
383
- return "";
384
- const sections = sectionsInput
385
- .map((sec) => {
386
- const points = sec.evaluationPoints.map((p) => `- ${p}`).join("\n");
387
- const title = sec.stopGate ? `${sec.title} (STOP gate)` : sec.title;
388
- return `### ${title}\n${points}`;
389
- })
390
- .join("\n\n");
391
- return `## Review Sections
392
-
393
- ${sections}
394
- `;
395
- }
396
- function stackAwareReviewRoutingBlock(stage) {
397
- if (stage !== "review")
398
- return "";
399
- const routes = reviewStackAwareRoutes()
400
- .map((route) => `- ${route.stack}: ${route.signals.map((signal) => `\`${signal}\``).join(", ")} -> ${route.agent} lens for ${route.focus}.`)
401
- .join("\n");
402
- return `## Stack-Aware Review Routing
403
- ${reviewStackAwareRoutingSummary()}
404
-
405
- Default general review still runs. Add only the matching stack lens when repo signals or changed files justify it.
406
-
407
- ${routes}
408
- `;
409
- }
410
- function reviewLoopBlock(reviewLoop) {
411
- if (!reviewLoop)
412
- return "";
413
- const checklist = reviewLoop.checklist.map((item) => `- \`${item}\``).join("\n");
414
- return `## Outside Voice Review Loop
415
- - Stage: \`${reviewLoop.stage}\`
416
- - Target score: \`${reviewLoop.targetScore}\`
417
- - Max iterations: \`${reviewLoop.maxIterations}\`
418
- - Checklist dimensions:
419
- ${checklist}
420
- `;
421
- }
422
- function verificationBlock(stage) {
423
- if (!VERIFICATION_STAGES.includes(stage))
424
- return "";
425
- return `## Verification Before Completion
426
-
427
- This is the gate function for completion claims. No "done", "all good", or
428
- "tests pass" unless fresh evidence from this turn proves it.
429
-
430
- - Run verification commands (tests/build/lint/type-check) for the changed scope.
431
- - Before \`tdd -> review\` and \`review -> ship\`, discover the real test command
432
- from repo config (package scripts, pytest/go/cargo/maven/gradle signals) and
433
- cite that exact command in the gate evidence.
434
- - Confirm output directly; do not infer success from prior runs or green memories.
435
- - If this is a bug fix, capture RED -> GREEN evidence for the regression path.
436
- - If a command fails, report the failure as diagnostic evidence and stop before completion.
437
- - If you only inspected files or reasoned about the change, say so; that is not verification.
438
-
439
- Keep this verification evidence in the artifact before completion.
440
- `;
441
- }
442
- function batchExecutionModeBlock(stage, track) {
443
- const schema = stageSchema(stage, track);
444
- if (!schema.batchExecutionAllowed)
445
- return "";
446
- const orderingGuidance = track === "quick"
447
- ? "Use spec acceptance items / bug reproduction slices for ordering."
448
- : "Use plan slices for ordering.";
449
- return `## Batch Execution Mode
450
-
451
- Execute the current dependency batch task-by-task (RED -> GREEN -> REFACTOR).
452
- Stop on BLOCKED status or when user input is required.
453
- Apply concise turn announces: one announce per batch boundary (or when risk/source
454
- changes materially), then execute tasks without repetitive boilerplate.
455
-
456
- Detailed walkthrough:
457
- ${orderingGuidance} Keep RED -> GREEN -> REFACTOR evidence in the TDD artifact.
458
- `;
459
- }
460
- function crossStageTraceBlock(trace) {
461
- const reads = trace.readsFrom.length > 0
462
- ? trace.readsFrom.map((r) => `- ${r}`).join("\n")
463
- : "- (first stage — no upstream artifacts)";
464
- const writes = trace.writesTo.length > 0
465
- ? trace.writesTo.map((w) => `- ${w}`).join("\n")
466
- : "- (terminal stage)";
467
- return `## Cross-Stage Traceability
468
-
469
- Reads from:
470
- ${reads}
471
-
472
- Writes to:
473
- ${writes}
474
-
475
- Rule: ${trace.traceabilityRule}
140
+ 1. Integration reviewer reads from each worktree's branch.
141
+ 2. The orchestrator merges \`cclaw/<slug>/slice-N\` into the main branch one slice at a time (or fast-forward if the wave was clean).
142
+ 3. \`git worktree remove .cclaw/worktrees/<slug>-slice-N\` per slice; the cclaw branches stay until ship.
143
+
144
+ ## Fallback: inline-sequential when sub-agent dispatch is unavailable
145
+
146
+ If the harness does not support sub-agent dispatch (or worktree creation fails — non-git repo, permission denied, etc.), \`parallel-build\` **degrades silently to \`inline\`** and runs all slices sequentially in the main working tree. The orchestrator records the fallback in \`builds/<slug>.md\`:
147
+
148
+ \`\`\`markdown
149
+ > Topology was \`parallel-build\` but the harness does not support sub-agent dispatch (or worktree creation failed). Slices ran sequentially in the main working tree.
150
+ \`\`\`
151
+
152
+ This degradation is not an error and does not reduce review depth.
153
+
154
+ ## Hard rules
155
+
156
+ - \`integration\` mode reviewer is mandatory after every parallel wave. No shortcut.
157
+ - Slice-builders never read each other's worktrees mid-flight.
158
+ - A slice-builder that detects a conflict with another slice stops and raises an integration finding instead of hand-merging.
159
+ - More than 5 parallel slices is forbidden. Merge or split.
476
160
  `;
477
- }
478
- function artifactValidationBlock(validations) {
479
- if (validations.length === 0)
480
- return "";
481
- const rows = validations
482
- .map((v) => {
483
- const req = v.required ? "REQUIRED" : "recommended";
484
- return `| ${v.section} | ${req} | ${v.validationRule} |`;
485
- })
486
- .join("\n");
487
- return `## Artifact Validation
488
-
489
- | Section | Tier | Validation rule |
490
- |---|---|---|
491
- ${rows}
161
+ const SECURITY_REVIEW = `---
162
+ name: security-review
163
+ trigger: when the diff touches authn / authz / secrets / supply chain / data exposure
164
+ ---
165
+
166
+ # Skill: security-review
167
+
168
+ The orchestrator dispatches \`security-reviewer\` automatically when the active task or diff touches sensitive surfaces. You can also invoke it explicitly with \`/cc <task> --security-review\`.
169
+
170
+ ## Rules
171
+
172
+ 1. \`security-reviewer\` is a separate specialist from \`reviewer\`. They can run in parallel against the same diff.
173
+ 2. \`security-reviewer\` decisions of severity \`security\` are block-level: ship is blocked until they are resolved by slice-builder mode=fix-only and the security review reruns clear.
174
+ 3. \`security_flag: true\` in plan frontmatter triggers the compound learning gate even if no other quality signal is present.
175
+
176
+ ## Threat-model checklist (mandatory)
177
+
178
+ For every \`threat-model\` invocation, write \`ok\` / \`flag\` / \`n/a\` for each:
179
+
180
+ 1. Authentication
181
+ 2. Authorization
182
+ 3. Secrets (committed credentials, env, signing keys)
183
+ 4. Supply chain (new third-party deps, version pinning, provenance)
184
+ 5. Data exposure (logging, transmission, storage of user data)
185
+
186
+ ## Pure UI / docs diffs
187
+
188
+ State explicitly that all five items are \`n/a\` and write a one-line justification per item. Do not skip the checklist.
492
189
  `;
493
- }
494
- function mergedAntiPatterns(philosophy, execution) {
495
- const merged = [];
496
- const seen = new Set();
497
- for (const item of [...philosophy.commonRationalizations, ...execution.blockers]) {
498
- const key = item.trim().toLowerCase();
499
- if (seen.has(key))
500
- continue;
501
- seen.add(key);
502
- merged.push(item);
503
- }
504
- return merged.map((item) => `- ${item}`).join("\n");
505
- }
506
- function completionParametersBlock(schema, track) {
507
- const gateList = schema.executionModel.requiredGates.map((g) => `\`${g.id}\``).join(", ");
508
- // Mandatory agents are dropped on `quick` track. Surface
509
- // the empty list so the rendered SKILL.md doesn't tell quick-track runs to
510
- // dispatch agents the linter is going to skip.
511
- const trackAwareMandatoryAgents = track === "quick" ? [] : schema.reviewLens.mandatoryDelegations;
512
- const mandatoryAgents = trackAwareMandatoryAgents;
513
- const mandatory = trackAwareMandatoryAgents.length > 0
514
- ? trackAwareMandatoryAgents.map((a) => `\`${a}\``).join(", ")
515
- : track === "quick" && schema.reviewLens.mandatoryDelegations.length > 0
516
- ? "none (skipped: quick track)"
517
- : "none";
518
- const resolvedNextStage = nextStageForTrack(schema.stage, track);
519
- const nextStage = resolvedNextStage ?? "done";
520
- const nextDescription = nextStage === "done"
521
- ? "flow complete"
522
- : stageSchema(nextStage, track).skillDescription;
523
- return `### Completion Parameters
524
-
525
- - \`stage\`: \`${schema.stage}\`
526
- - \`next\`: \`${nextStage}\` (${nextDescription})
527
- - \`gates\`: ${gateList}
528
- - \`artifact\`: \`${RUNTIME_ROOT}/artifacts/${schema.artifactRules.artifactFile}\`
529
- - \`mandatory delegations\`: ${mandatory}
530
- - \`completion helper\`: \`node .cclaw/hooks/stage-complete.mjs ${schema.stage}\`
531
- - \`completion helper with evidence\`: \`node .cclaw/hooks/stage-complete.mjs ${schema.stage} --evidence-json '{"<gate_id>":"<evidence note>"}' --passed=<gate_id>[,<gate_id>]\`
532
- - \`completion helper JSON diagnostics\`: append \`--json\` to receive a machine-readable validation failure summary.
533
- - \`delegation lifecycle proof\`: use the delegation helper recipe in this section with explicit lifecycle rows: \`--status=scheduled\` -> \`--status=launched\` -> \`--status=acknowledged\` -> \`--status=completed\` (completed isolated/generic requires prior ACK for the same span or \`--ack-ts=<iso>\`).
534
- - Fill \`## Learnings\` before closeout: either \`- None this stage.\` or JSON bullets with required keys \`type\`, \`trigger\`, \`action\`, \`confidence\` (knowledge-schema compatible).
535
- - If you edit any completed-stage artifact after it shipped (\`completedStageMeta\` timestamps exist), append a short \`## Amendments\` section with dated bullets (timestamp + reason) instead of overwriting the archived narrative silently — advisory linter rule \`stage_artifact_post_closure_mutation\` enforces visibility when this trail is missing.
536
- - Record mandatory delegation lifecycle in \`${RUNTIME_ROOT}/state/delegation-log.json\` and append proof events to \`${RUNTIME_ROOT}/state/delegation-events.jsonl\`; the ledger is current state, the event log is audit proof.${mandatoryAgents.length > 0 ? ` If a mandatory delegation cannot run in this harness, use \`--waive-delegation=${mandatoryAgents.join(",")} --waiver-reason="<why safe>"\` on the completion helper.` : ""} If proactive delegations were intentionally skipped, first issue a short-lived waiver token with \`cclaw-cli internal waiver-grant --stage <stage> --reason "<short-slug>"\`, then rerun the completion helper with \`--accept-proactive-waiver=<token> --accept-proactive-waiver-reason="<why safe>"\` after explicit user approval. Tokens expire in 30 minutes and are single-use; bare \`--accept-proactive-waiver\` is no longer accepted.
537
- - Never edit raw \`flow-state.json\` to complete a stage, even in advisory mode; that bypasses validation, gate evidence, and Learnings harvest. If a helper fails, report a one-line human-readable failure plus fenced JSON diagnostics; never echo the invoking command line or apply a manual state workaround.
538
- - Stage completion claim requires \`stage-complete\` exit 0 in the current turn. Quote the single-line success JSON exactly as printed to stdout (for example \`{"ok":true,"command":"stage-complete",...}\` including \`completedStages\` / \`currentStage\` / \`runId\`); do not paraphrase. Do not infer success from empty stdout or from skipped retries (quiet mode always emits one JSON line on success).
539
- - Completion protocol: verify required gates, update the artifact, then use the completion helper with \`--evidence-json\` and \`--passed\` for every satisfied gate.
190
+ const REVIEW_LOOP = `---
191
+ name: review-loop
192
+ trigger: when reviewer or security-reviewer is invoked
193
+ ---
194
+
195
+ # Skill: review-loop
196
+
197
+ Review is a producer ↔ critic loop, not a single pass. Iteration N proposes findings; \`slice-builder\` (in \`fix-only\` mode) closes them; iteration N+1 re-checks. The loop ends only when one of three convergence signals fires (see "Convergence detector" below). This is the cclaw analogue of the Karpathy "Ralph loop": short cycles, an explicit ledger, and hard rules for when to stop.
198
+
199
+ Every iteration runs the **Five Failure Modes** checklist:
200
+
201
+ 1. Hallucinated actions
202
+ 2. Scope creep
203
+ 3. Cascading errors
204
+ 4. Context loss
205
+ 5. Tool misuse
206
+
207
+ For each mode the reviewer answers yes/no with a citation when "yes". A "yes" without a citation is itself a finding (you cited nothing, that is the finding).
208
+
209
+ ## Concern Ledger
210
+
211
+ Every \`reviews/<slug>.md\` carries an append-only ledger. Each row is a single finding; rows are never edited or deleted, only appended.
212
+
213
+ \`\`\`markdown
214
+ ## Concern Ledger
215
+
216
+ | ID | Opened in | Mode | Severity | Status | Closed in | Citation |
217
+ | --- | --- | --- | --- | --- | --- | --- |
218
+ | F-1 | 1 | code | block | closed | 2 | \`src/api/list.ts:14\` |
219
+ | F-2 | 2 | code | warn | open | – | \`tests/integration/list.test.ts:31\` |
220
+ \`\`\`
221
+
222
+ Rules:
223
+
224
+ - **F-N** ids are stable and global per slug — never renumber. If a finding is superseded, append \`F-K supersedes F-J\` instead.
225
+ - **Severity** is \`block\` | \`warn\`. \`block\` rows must close before ship; \`warn\` rows may ship with a recorded note in \`ships/<slug>.md\`.
226
+ - **Status** is \`open\` | \`closed\`. A closed row records the iteration that closed it.
227
+ - **Citation** is a real \`file:line\` (or test id, or commit SHA). No prose-only findings — if you cannot cite, you do not have a finding yet.
228
+
229
+ When iteration N+1 runs, the reviewer reads the ledger first, re-validates each open row (still open? closed by a fix? superseded?), then appends new findings as F-(max+1). Closing a row requires a citation to the fix evidence (commit SHA, test name, or new file:line).
230
+
231
+ ## Convergence detector
232
+
233
+ The loop ends when ANY of these fires:
234
+
235
+ 1. **All ledger rows closed.** Decision: \`clear\`. Ship may proceed.
236
+ 2. **Two consecutive iterations append zero new \`block\` findings AND every open row is \`warn\`.** Decision: \`clear\` with warn carry-over recorded in \`ships/<slug>.md\` and \`learnings/<slug>.md\`.
237
+ 3. **Hard cap reached** (5 iterations) with at least one open \`block\` row remaining. Decision: \`cap-reached\`. Stop; surface to user.
238
+
239
+ Tie-breaker: if iteration 5 closes the last \`block\` row, return \`clear\` (signal #1) even though the cap was hit. The cap exists to bound runaway loops, not to punish a slug that converges on the last attempt.
240
+
241
+ ## Hard cap
242
+
243
+ - 5 review iterations per slug. After the 5th, the reviewer writes \`status: cap-reached\` and stops.
244
+ - The orchestrator surfaces every remaining open ledger row and recommends \`/cc-cancel\` (split into a fresh slug) or \`accept warns and ship\` (only valid if every remaining open row has severity=warn).
245
+
246
+ ## Decision values
247
+
248
+ - \`block\` — at least one ledger row is severity=block + status=open. \`slice-builder\` (mode=fix-only) must run next; then re-review.
249
+ - \`warn\` — open rows exist, all severity=warn, convergence detector signal #2 has fired. Ship may proceed; warns carry over.
250
+ - \`clear\` — convergence detector signal #1 fired (all rows closed) OR signal #2 (warn-only convergence). Ready for ship.
251
+ - \`cap-reached\` — signal #3 fired with at least one open block row remaining. Stop; surface to user.
252
+
253
+ ## Worked example — three-iteration convergence
254
+
255
+ \`\`\`markdown
256
+ ## Iteration 1 — code — 2026-04-18T10:14Z
257
+
258
+ Findings:
259
+ - F-1 block — \`src/api/list.ts:14\` — missing pagination cursor.
260
+ - F-2 warn — \`tests/integration/list.test.ts:31\` — no negative test for empty page.
261
+
262
+ Decision: block. slice-builder (mode=fix-only) invoked next.
263
+
264
+ ## Iteration 2 — code — 2026-04-18T10:39Z
265
+
266
+ Ledger reread:
267
+ - F-1: closed — fix at \`src/api/list.ts:18\` (commit 7a91ab2). Citation matches.
268
+ - F-2: open — no fix attempted (warn carry-over).
269
+
270
+ New findings: none.
271
+
272
+ Decision: warn. Convergence signal #2 needs another zero-block iteration.
273
+
274
+ ## Iteration 3 — code — 2026-04-18T11:02Z
275
+
276
+ Ledger reread:
277
+ - F-1: closed (sticky).
278
+ - F-2: open (warn carry-over).
279
+
280
+ New findings: none. Two consecutive zero-block iterations recorded.
281
+
282
+ Decision: clear (signal #2). F-2 carries to ships/<slug>.md and learnings/<slug>.md.
283
+ \`\`\`
284
+
285
+ ## Common pitfalls
286
+
287
+ - Adding "implicit" findings without citations because "the reviewer can see it". The reviewer cannot. Cite \`file:line\` or do not record the finding.
288
+ - Renumbering F-N ids when an old finding is superseded. Append a new row \`F-K supersedes F-J\`; never rewrite history.
289
+ - Closing a row without a fix citation. Closing is itself a claim — record the SHA / test name / file:line that proves the fix.
290
+ - Treating "no new findings" as instant clear. The convergence detector requires *two* consecutive zero-block iterations; one is not enough.
291
+ - Skipping the convergence check and looping until cap. The detector exists so easy slugs ship fast; do not waste budget.
292
+ - Mixing \`code\` and \`text-review\` modes within one iteration. Each iteration declares one mode in its header.
540
293
  `;
541
- }
542
- function delegationAndCompletionBlock(schema, track) {
543
- const dispatchBlock = autoSubagentDispatchBlock(schema.stage, track).trim();
544
- const completionBlock = completionParametersBlock(schema, track).trim();
545
- const normalizedDispatch = dispatchBlock.length > 0
546
- ? dispatchBlock.replace(/^## Automatic Subagent Dispatch/mu, "### Automatic Subagent Dispatch")
547
- : "### Automatic Subagent Dispatch\nNo automatic subagent dispatch rules for this stage.";
548
- return `## Delegation & Completion
294
+ const COMMIT_MESSAGE_QUALITY = `---
295
+ name: commit-message-quality
296
+ trigger: before every commit-helper.mjs invocation
297
+ ---
549
298
 
550
- ${normalizedDispatch}
299
+ # Skill: commit-message-quality
551
300
 
552
- ${completionBlock}
301
+ \`commit-helper.mjs\` accepts any non-empty message, but the AC traceability chain only stays useful if the messages stay readable.
553
302
 
554
- ### Stage Closure (harness-only UX)
303
+ ## Rules
555
304
 
556
- - **NEVER paste the \`stage-complete.mjs\` command line into chat.** The user does not run cclaw manually; seeing \`node .cclaw/hooks/stage-complete.mjs ... --evidence-json '{...}' --waive-delegation=...\` is noise. Run the helper via the tool layer; report only the resulting summary.
557
- - **NEVER paste the \`--evidence-json\` payload into chat.** It is structured data for the helper, not for the user. The same evidence already lives in the artifact section.
558
- - On failure, report a compact human-readable summary based on the helper's JSON \`findings\` array list failing section names only (one line each), include the full helper JSON in a single fenced \`json\` block. Do not echo the invoking command.
559
- - **NEVER run shell hash commands** (\`shasum\`, \`sha256sum\`, \`md5sum\`, \`Get-FileHash\`, \`certutil\`, etc.) for hash compute. If the linter ever asks for a hash, that is a linter bug report failure and stop, do not auto-fix in bash.
560
- - The helper defaults to quiet (\`CCLAW_STAGE_COMPLETE_QUIET=1\`): no pretty-printed chatter, but **stdout still prints exactly one line** of machine-readable success JSON (same contract as \`start-flow\` in quiet mode).
305
+ 1. **Imperative voice** "Add StatusPill component", not "Added" or "Adding".
306
+ 2. **Subject ≤72 characters** long subjects truncate in \`git log --oneline\` and CI signals.
307
+ 3. **Subject does not repeat the AC id** — the hook already appends \`refs: AC-N\`.
308
+ 4. **Body when needed** second-line blank, then a short rationale paragraph and any non-obvious context. Use \`--message\` for the subject; if the message must be multi-line, write it to a file and pass \`--file\`.
309
+ 5. **Cite finding ids in fix commits** \`fix: F-2 separate rejected token\`.
310
+
311
+ ## Anti-patterns
312
+
313
+ - "WIP", "fixes", "stuff", "more". The reviewer rejects these as F-1 \`block\`.
314
+ - Subject lines that paraphrase the diff. Diff is the diff; the message is the why.
315
+ - Co-author trailers in solo commits.
316
+
317
+ ## When to amend
318
+
319
+ Never amend a commit produced by \`commit-helper.mjs\` after the SHA is recorded in \`flow-state.json\`. Amend changes the SHA and breaks the AC chain. If the message is wrong, write a short note in \`builds/<slug>.md\` and move on; it is recoverable in review.
561
320
  `;
562
- }
563
- function quickStartBlock(stage, track) {
564
- const schema = stageSchema(stage, track);
565
- const gatePreview = schema.executionModel.requiredGates.slice(0, 3).map((g) => `\`${g.id}\``).join(", ");
566
- return `## Quick Start
567
-
568
- 1. Announce at start: "Using \`${schema.skillName}\` to ${schema.philosophy.purpose}".
569
- 2. Obey HARD-GATE and Iron Law.
570
- 3. Execute checklist in order and persist \`${RUNTIME_ROOT}/artifacts/${schema.artifactRules.artifactFile}\`.
571
- 4. Satisfy gates (${gatePreview}${schema.executionModel.requiredGates.length > 3 ? ` +${schema.executionModel.requiredGates.length - 3}` : ""}).
321
+ const AC_QUALITY = `---
322
+ name: ac-quality
323
+ trigger: when authoring or reviewing AC entries
324
+ ---
325
+
326
+ # Skill: ac-quality
327
+
328
+ Three checks per AC:
329
+
330
+ 1. **Observable** a user, test, or operator can tell whether it is satisfied without reading the diff.
331
+ 2. **Independently committable** — a single commit covering only this AC is meaningful.
332
+ 3. **Verifiable** — there is an explicit verification line (test name, manual step, or command).
333
+
334
+ ## Smell check
335
+
336
+ | smell | example | rewrite |
337
+ | --- | --- | --- |
338
+ | sub-task | "implement the helper" | "search returns BM25-ranked results for queries with multiple terms" |
339
+ | vague verification | "tests pass" | "verified by tests/unit/search.test.ts: 'returns BM25-ranked hits'" |
340
+ | internal detail | "refactor the cache" | "cache hit rate >90% on the dashboard repaint scenario" |
341
+ | compound AC | "build the page and add analytics" | split into two AC |
342
+
343
+ ## Numbering
344
+
345
+ - AC ids start at \`AC-1\` and are sequential.
346
+ - Refinement slugs restart at \`AC-1\` even when they refine a slug that had AC-1..AC-12.
347
+ - Do not reuse an AC id within the same slug; if you delete an AC, the remaining ids stay sequential after compaction.
348
+
349
+ ## When to add an AC mid-flight
350
+
351
+ You don't. Adding AC during build is scope creep. Either the new work fits an existing AC (no new id), or it should be a follow-up (\`/cc-idea\`) or a fresh slug.
572
352
  `;
573
- }
574
- export function stageSkillFolder(stage) {
575
- return STAGE_TO_SKILL_FOLDER[stage];
576
- }
577
- function normalizedGuidanceKey(value) {
578
- return value
579
- .replace(/`[^`]+`/gu, " ")
580
- .replace(/[*_]/gu, " ")
581
- .replace(/[^a-z0-9]+/giu, " ")
582
- .replace(/\s+/gu, " ")
583
- .trim()
584
- .toLowerCase();
585
- }
586
- function mermaidNodeLabel(raw, index) {
587
- const stripped = raw
588
- .replace(/`[^`]+`/gu, "")
589
- .replace(/\*\*/gu, "")
590
- .replace(/[*_]/gu, "")
591
- .replace(/\[[^\]]*\]\([^)]*\)/gu, "")
592
- .split(/[—:.;]/u)[0]
593
- ?.trim() ?? "";
594
- const words = stripped.split(/\s+/u).filter((word) => word.length > 0);
595
- const short = words.slice(0, 4).join(" ");
596
- const label = short.length === 0
597
- ? `Step ${index + 1}`
598
- : short.replace(/["`]/gu, "");
599
- return label.length > 48 ? `${label.slice(0, 45)}...` : label;
600
- }
601
- const MERMAID_PROCESS_MAX_NODES = 10;
602
- function renderProcessFlowMermaid(executionModel) {
603
- if (executionModel.processFlow && executionModel.processFlow.trim().length > 0) {
604
- return `\`\`\`mermaid\n${executionModel.processFlow.trim()}\n\`\`\``;
605
- }
606
- const source = executionModel.process.length > 0
607
- ? executionModel.process
608
- : executionModel.checklist;
609
- if (source.length === 0) {
610
- return "";
611
- }
612
- const limited = source.slice(0, MERMAID_PROCESS_MAX_NODES);
613
- const nodes = limited.map((item, index) => ({
614
- id: `S${index + 1}`,
615
- label: mermaidNodeLabel(item, index)
616
- }));
617
- const lines = ["flowchart TD"];
618
- for (const node of nodes) {
619
- lines.push(` ${node.id}["${node.label}"]`);
620
- }
621
- for (let i = 0; i < nodes.length - 1; i += 1) {
622
- lines.push(` ${nodes[i].id} --> ${nodes[i + 1].id}`);
623
- }
624
- if (source.length > MERMAID_PROCESS_MAX_NODES) {
625
- lines.push(` S${nodes.length} --> More["...see full Checklist"]`);
626
- }
627
- return `\`\`\`mermaid\n${lines.join("\n")}\n\`\`\``;
628
- }
629
- function renderPlatformNotesBlock(notes) {
630
- if (!notes || notes.length === 0) {
631
- return "";
632
- }
633
- const body = notes.map((item) => `- ${item}`).join("\n");
634
- return `## Platform Notes
635
- ${body}
353
+ const REFACTOR_SAFETY = `---
354
+ name: refactor-safety
355
+ trigger: when the slug is identified as a pure refactor
356
+ ---
357
+
358
+ # Skill: refactor-safety
359
+
360
+ Refactors must be **behaviour-preserving**. The harness enforces this with three structural rules.
361
+
362
+ ## Pin behaviour first
363
+
364
+ Before any rewrite, identify the pin:
365
+
366
+ - existing tests that should pass with the same expected output;
367
+ - a snapshot or fixture set that should not change;
368
+ - a manual repro the user accepts as the contract.
369
+
370
+ If no pin exists, "add a pin" is AC-1 of the refactor.
371
+
372
+ ## One refactor at a time
636
373
 
374
+ A refactor slug must contain refactor changes only. A bug fix that would have been "while we're here" is a separate slug. The pin from the refactor slug is then valid input for the fix slug.
375
+
376
+ ## Public API discipline
377
+
378
+ If the refactor renames or restructures public exports:
379
+
380
+ - add a deprecation alias so external consumers still compile;
381
+ - mark the old name with a \`@deprecated\` JSDoc / equivalent;
382
+ - record the deprecation deadline in \`ships/<slug>.md\`.
383
+
384
+ If the project policy forbids deprecation aliases (some libraries), the refactor is breaking; \`security_flag\` does not apply but breaking-change handling does (see breaking-changes skill).
385
+
386
+ ## Verification
387
+
388
+ Refactor AC verification is "no behavioural diff": tests pass, snapshots unchanged, fixtures unchanged. If anything changes, the refactor leaked behaviour and must be split.
637
389
  `;
638
- }
639
- function dedupeGuidance(items, blockedBy) {
640
- const blocked = new Set(blockedBy
641
- .map((item) => normalizedGuidanceKey(item))
642
- .filter((item) => item.length > 0));
643
- const seen = new Set();
644
- const result = [];
645
- for (const item of items) {
646
- const key = normalizedGuidanceKey(item);
647
- if (key.length === 0)
648
- continue;
649
- if (blocked.has(key))
650
- continue;
651
- if (seen.has(key))
652
- continue;
653
- seen.add(key);
654
- result.push(item);
655
- }
656
- return result;
657
- }
658
- export function stageSkillMarkdown(stage, track = "standard", _packageVersion) {
659
- const schema = stageSchema(stage, track);
660
- const trackContext = stageTrackRenderContext(track);
661
- const philosophy = schema.philosophy;
662
- const executionModel = schema.executionModel;
663
- const artifactRules = schema.artifactRules;
664
- const reviewLens = schema.reviewLens;
665
- const mandatoryDelegations = reviewLens.mandatoryDelegations;
666
- const gateList = executionModel.requiredGates
667
- .map((g) => `- \`${g.id}\` — ${g.description}`)
668
- .join("\n");
669
- const evidenceList = executionModel.requiredEvidence
670
- .map((e) => `- [ ] ${e}`)
671
- .join("\n");
672
- const checklistItems = executionModel.checklist
673
- .map((item, i) => `${i + 1}. ${item}`)
674
- .join("\n");
675
- const interactionFocus = dedupeGuidance(executionModel.interactionProtocol, [...executionModel.checklist, ...executionModel.process]).slice(0, 5);
676
- const processFlowMermaid = renderProcessFlowMermaid(executionModel);
677
- const platformNotesBlock = renderPlatformNotesBlock(executionModel.platformNotes);
678
- const reviewLoopSection = reviewLoopBlock(reviewLens.reviewLoop);
679
- const mandatoryDelegationSummary = mandatoryDelegations.length > 0
680
- ? mandatoryDelegations.map((name) => `\`${name}\``).join(", ")
681
- : "none";
682
- return `---
683
- name: ${schema.skillName}
684
- description: "${schema.skillDescription}"
390
+ const TDD_CYCLE = `---
391
+ name: tdd-cycle
392
+ trigger: always-on whenever stage=build (mandatory; build IS the TDD stage)
685
393
  ---
686
394
 
687
- # ${schema.skillName}
395
+ # Skill: tdd-cycle (RED → GREEN → REFACTOR)
396
+
397
+ build is a TDD stage. Every AC goes through the cycle. There is no other build mode.
688
398
 
689
- <EXTREMELY-IMPORTANT>
399
+ > **Iron Law:** NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST. The RED failure is the spec.
690
400
 
691
- **IRON LAW ${stage.toUpperCase()}:** ${philosophy.ironLaw}
401
+ ## The three phases
692
402
 
693
- If you are about to violate the Iron Law, STOP. No amount of urgency, partial progress, or clever reinterpretation overrides it. Escalate via the Decision Protocol or abandon the stage.
403
+ ### RED write a failing test
694
404
 
695
- </EXTREMELY-IMPORTANT>
405
+ - Touch test files **only**. No production edits in the RED commit.
406
+ - The test must encode the AC verification line authored by planner.
407
+ - The test must fail for the **right reason** — the assertion that encodes the AC, not a syntax / import / fixture error.
408
+ - Capture the runner output that proves the failure (command + 1-3 line excerpt). This is the **watched-RED proof**.
409
+ - **Test files are named by the unit under test, NOT by the AC id.** Mirror the production module path: \`src/lib/permissions.ts\` → \`tests/unit/permissions.test.ts\` (or whatever the project's convention is — \`*.spec.ts\`, \`__tests__/*.ts\`, \`*_test.go\`, \`test_*.py\`). \`AC-1.test.ts\`, \`tests/AC-2.test.ts\`, \`spec/ac3.spec.ts\` are anti-patterns. The AC id lives **inside** the test name (\`it('AC-1: tooltip shows email …', …)\`), in the commit message (\`red(AC-1): …\`), and in the build log — never in the filename.
410
+ - Commit: \`commit-helper.mjs --ac=AC-N --phase=red --message="red(AC-N): …"\`.
696
411
 
697
- ${renderTrackTerminology(tddTopOfSkillBlock(stage) + reviewTopOfSkillBlock(stage), trackContext)}${quickStartBlock(stage, track)}
412
+ ### GREEN minimal production change
698
413
 
699
- ${STAGE_LANGUAGE_POLICY_POINTER}
700
- ## Philosophy
701
- ${philosophy.purpose}
414
+ - Smallest possible production diff that turns RED into PASS.
415
+ - Run the **full relevant suite**, not the single test. A passing single test with the suite broken elsewhere is a regression, not GREEN.
416
+ - Capture the suite command + PASS/FAIL summary. This is the **GREEN evidence**.
417
+ - Touch only files declared in the plan. If a file outside the plan is required, **stop** and surface the conflict.
418
+ - Commit: \`commit-helper.mjs --ac=AC-N --phase=green --message="green(AC-N): …"\`.
702
419
 
703
- ## Complexity Tier
704
- - Active tier: \`${schema.complexityTier}\`; mandatory delegations: ${mandatoryDelegationSummary}
705
- - Scale-to-complexity: execute required gates/sections; keep optional/deep sections compact unless risk, novelty, or config triggers them.
706
- - Track render context: \`${trackContext.track}\` (${trackContext.usesPlanTerminology ? "plan-first wording" : "acceptance-first wording"})
420
+ ### REFACTOR — mandatory pass
707
421
 
708
- ## When to Use
709
- ${philosophy.whenToUse.map((item) => `- ${item}`).join("\n")}
422
+ REFACTOR is **not optional**. Even when the GREEN diff feels minimal, you must consider rename / extract / inline / type-narrow / dedup / dead-code-removal. Run the same suite again; it must pass with **identical** expected output.
710
423
 
711
- ${whenNotToUseBlock(philosophy.whenNotToUse)}
712
- ## HARD-GATE
713
- ${philosophy.hardGate}
424
+ If a refactor is warranted, apply it and commit:
714
425
 
715
- ## Anti-Patterns & Red Flags
716
- ${mergedAntiPatterns(philosophy, executionModel)}
426
+ \`commit-helper.mjs --ac=AC-N --phase=refactor --message="refactor(AC-N): …"\`.
717
427
 
718
- ## Process
428
+ If no refactor is warranted, say so **explicitly**:
719
429
 
720
- Stage state machine (map only; Checklist is authoritative):
721
- ${processFlowMermaid.length > 0 ? processFlowMermaid : "```mermaid\nflowchart TD\n S1[\"Execute Checklist\"] --> S2[\"Satisfy required gates\"] --> S3[\"Verify before closeout\"]\n```"}
430
+ \`commit-helper.mjs --ac=AC-N --phase=refactor --skipped --message="refactor(AC-N) skipped: <reason>"\`.
722
431
 
723
- ${platformNotesBlock}${contextLoadingBlock(stage, artifactRules.crossStageTrace, executionModel)}
724
- ${delegationAndCompletionBlock(schema, track)}
725
- ${stackAwareReviewRoutingBlock(stage)}
726
- ${researchPlaybooksBlock(executionModel.researchPlaybooks ?? [])}
727
- ${referencePatternsBlock(stage)}
432
+ Silence fails the gate.
728
433
 
729
- ## Checklist
434
+ ## Mandatory gates per AC
730
435
 
731
- You MUST complete these steps in order:
436
+ \`commit-helper\` enforces (a) (e) mechanically. The reviewer checks (b), (d), (f), (g) on iteration 1.
732
437
 
733
- ${checklistItems}
438
+ (a) **discovery_complete** — relevant tests / fixtures / helpers / commands cited.\n(b) **impact_check_complete** — affected callbacks / state / interfaces / contracts named.\n(c) **red_test_recorded** — failing test exists, watched-RED proof attached.\n(d) **red_fails_for_right_reason** — RED captured a real assertion failure.\n(e) **green_full_suite** — full relevant suite green after GREEN.\n(f) **refactor_run_or_skipped_with_reason** — REFACTOR ran, or explicitly skipped with reason.\n(g) **traceable_to_plan** — commits reference plan AC ids and the plan's file set.\n(h) **commit_chain_intact** — RED + GREEN + REFACTOR SHAs (or skipped sentinel) recorded in flow-state.
734
439
 
735
- ${stageExamples(stage)}
440
+ ## Anti-patterns
736
441
 
737
- ## Interaction Protocol
442
+ - "The implementation is obvious, skipping RED." A-13 — gate fails immediately.
443
+ - "Single test green, didn't run the suite." A-14 — that's not GREEN; it's a regression.
444
+ - "Nothing to refactor, skipping silently." A-15 — emit the explicit \`--skipped\` commit with reason.
445
+ - "Stage everything with \`git add -A\`." A-16 — staged unrelated edits leak into the AC commit.
446
+ - "Production code in the RED commit." A-17 — RED is test files only.
447
+ - **"Test file named after the AC id" — \`AC-1.test.ts\`, \`tests/AC-2.spec.ts\`, etc.** The reviewer flags this as \`block\`. Mirror the unit under test in the filename; carry the AC id inside the test name and commit message only.
738
448
 
739
- These are **rules for HOW you interact with the user** during this stage — tone, question shape, decision gating. Ordered steps of *what to do* live in the Checklist; do not treat these as an alternative sequence.
449
+ ## Fix-only flow
740
450
 
741
- ${interactionFocus.length > 0 ? interactionFocus.map((item, i) => `${i + 1}. ${item}`).join("\n") : "- Keep communication concise and decision-focused; rely on the Checklist for execution order."}
451
+ When reviewer returns \`block\`, the same TDD cycle applies to the fix:
742
452
 
743
- Decision protocol: ask only decision-changing questions, record the chosen option, rationale, risk, and rollback when the stage makes a non-trivial call.
453
+ - F-N changes observable behaviour new RED test that encodes the corrected behaviour, then GREEN, then REFACTOR.
454
+ - F-N is purely a refactor → commit under \`--phase=refactor\`.
455
+ - F-N is a docs / log / config nit → commit under \`--phase=refactor\` or \`--phase=refactor --skipped\`.
744
456
 
745
- ${batchExecutionModeBlock(stage, track)}
746
- ${crossCuttingMechanicsBlock(stage)}
747
- ## Required Gates
748
- ${gateList}
457
+ The AC id stays the same; commit messages cite \`F-N\`.
749
458
 
750
- ## Required Evidence
751
- ${evidenceList}
459
+ ## When TDD does not apply
460
+
461
+ The single exception is **bootstrap of the test framework itself** — a slug whose AC-1 is "test framework installed and one passing example test exists". In that case the orchestrator must mark the slug as \`build_profile: bootstrap\` in plan frontmatter, and \`commit-helper\` accepts the GREEN commit without a prior RED for AC-1 only. Every subsequent AC and every other slug uses the full cycle.
462
+ `;
463
+ const BREAKING_CHANGES = `---
464
+ name: breaking-changes
465
+ trigger: when the diff modifies public API surface or persisted contracts
466
+ ---
752
467
 
753
- ${verificationBlock(stage)}
468
+ # Skill: breaking-changes
754
469
 
755
- ## Exit Criteria
756
- ${executionModel.exitCriteria.map((item) => `- [ ] ${item}`).join("\n")}
470
+ A change is breaking when:
757
471
 
758
- ## Artifact Rules
759
- - Artifact target: \`${RUNTIME_ROOT}/artifacts/${artifactRules.artifactFile}\`
472
+ - a public export is renamed, removed, or changes signature;
473
+ - a CLI flag is renamed or removed;
474
+ - a wire format (HTTP, RPC, queue payload) changes shape or required fields;
475
+ - a persisted contract (DB schema, file format, env var) changes in a way that requires migration.
760
476
 
761
- ${crossStageTraceBlock(artifactRules.crossStageTrace)}
762
- ${artifactValidationBlock(artifactRules.artifactValidation)}
477
+ ## Rules
763
478
 
764
- ## Review Lens
765
- ${reviewLoopSection ? `${reviewLoopSection}\n` : ""}## Outputs
766
- ${reviewLens.outputs.map((item) => `- ${item}`).join("\n")}
479
+ 1. **Plan must declare it.** Set \`breaking_change: true\` (or note it explicitly in the plan body).
480
+ 2. **Migration must exist.** \`ships/<slug>.md\` carries a migration section: who is affected, what they need to do, when the old path stops working.
481
+ 3. **Deprecation window.** Public libraries — at least one minor version. Internal services — at least one deploy cycle and one alert.
482
+ 4. **Release notes.** The CHANGELOG line must start with \`BREAKING:\` and link to the migration section.
767
483
 
768
- ${reviewSectionsBlock(reviewLens.reviewSections)}
484
+ ## Coexistence
769
485
 
770
- ## Shared Stage Guidance
771
- - At STOP/closeout points, offer the shared handoff choices only when a user decision is needed.
772
- - Carry upstream decisions forward explicitly; record drift instead of silently changing direction.
773
- - Before closeout, fill \`## Learnings\` with \`- None this stage.\` or 1-3 strict JSON bullets.
774
- - Keep decisions explicit: context, options, chosen option, rationale, risk, and rollback.
486
+ When possible, ship the new path alongside the old. Examples:
487
+
488
+ - new endpoint path next to the old one;
489
+ - new column added before the old one is dropped;
490
+ - new env var name accepted along with the old (with a deprecation log line);
491
+ - new function exported with the new name; old name aliased to it.
492
+
493
+ Coexistence is not always possible (e.g. wire-format changes for older clients you cannot upgrade). When it is not possible, surface this back to architect; the decision must be recorded in \`decisions/<slug>.md\`.
494
+
495
+ ## Common pitfalls
496
+
497
+ - "Internal API, not breaking." If the change crosses a service boundary, treat it as breaking.
498
+ - Renaming a CLI flag without an alias. Aliases for CLI flags are nearly always free; add them.
499
+ - Skipping the CHANGELOG line because "everyone knows". They do not.
500
+ - Forgetting the alert window for internal services. The deploy cycle is not enough; users need a heads-up.
775
501
  `;
776
- }
777
- export function executingWavesSkillMarkdown() {
778
- return `---
779
- name: executing-waves
780
- description: "Execute multi-wave work using existing cclaw run resume + verify-current-state — no new CLI needed."
502
+ const CONVERSATION_LANGUAGE = `---
503
+ name: conversation-language
504
+ trigger: always-on
781
505
  ---
782
506
 
783
- # Executing Waves (Persistent Multi-Wave Work)
507
+ # Skill: conversation-language
508
+
509
+ cclaw is a harness tool. The harness has one user; the user has one language. Your conversational output must be in that language. Detect it from the user's most recent message and stay in it for the remainder of the turn.
510
+
511
+ ## What MUST stay in the user's language
784
512
 
785
- ## Overview
513
+ Everything that the user reads as prose:
786
514
 
787
- Long-form work (large refactors, multi-stage uplifts) often spans many waves.
788
- This skill documents how the controller persists work across waves WITHOUT new
789
- CLI commands, using existing \`cclaw run resume\` and \`internal verify-current-state\`.
515
+ - Status updates ("starting plan", "RED for AC-2 looks good").
516
+ - Questions you ask the user.
517
+ - Clarifications, recommendations, summaries, recaps.
518
+ - Error explanations and recovery suggestions.
519
+ - Diff explanations during review iterations.
790
520
 
791
- ## When to Use
521
+ If the user wrote to you in Russian, your status updates are in Russian. If the user wrote in Ukrainian, your status updates are in Ukrainian. If the user mixed languages, follow their dominant language; if there is no dominant language, mirror the language of their final paragraph.
792
522
 
793
- - Work spans 2+ commits / waves with cohesion concerns between waves.
794
- - Each wave has its own stage cycle (brainstorm -> scope -> design -> spec -> plan -> tdd -> review -> ship).
795
- - User wants explicit per-wave verification before the next wave starts.
796
- - Risk of cross-wave drift exists.
523
+ Do NOT translate during the same conversation. The user has already chosen their language; restating the same point in English is noise.
797
524
 
798
- ## Anti-Pattern
525
+ ## What MUST NOT be translated
799
526
 
800
- - Running many waves linearly without verification between them, accumulating drift.
801
- - Treating a wave as only a commit boundary without re-verifying upstream decisions.
527
+ Mechanical tokens stay in their original form regardless of conversation language:
802
528
 
803
- ## Process
529
+ - File paths (\`.cclaw/flows/<slug>/plan.md\`).
530
+ - AC ids (\`AC-1\`, \`AC-2\`).
531
+ - Decision ids (\`D-1\`, \`D-2\`).
532
+ - Slugs (\`add-approval-page\`, never "добавить-страницу-одобрения").
533
+ - Commands and CLI flags (\`/cc\`, \`--phase=red\`, \`commit-helper.mjs\`).
534
+ - Hook output and machine-readable JSON.
535
+ - Specialist names (\`brainstormer\`, \`architect\`, \`planner\`, \`reviewer\`, \`security-reviewer\`, \`slice-builder\`).
536
+ - Mode names (\`code\`, \`text-review\`, \`integration\`, \`release\`, \`adversarial\`, \`fix-only\`).
537
+ - Frontmatter keys (\`slug\`, \`stage\`, \`status\`, \`ac\`, \`phases\`).
538
+ - Stage names (\`plan\`, \`build\`, \`review\`, \`ship\`).
539
+ - TDD phase names (\`red\`, \`green\`, \`refactor\`).
804
540
 
805
- 1. **Wave Start**: author wave plan as \`.cclaw/wave-plans/<wave-n>.md\` referencing previous wave's ship artifact.
806
- 2. **Carry-forward Audit**: at brainstorm of the next wave, re-read previous wave ship artifact and explicitly record in the existing \`## Wave Carry-forward\` section:
807
- - Carrying forward: <scope D-XX decision references still valid>
808
- - Drift detected: <decisions no longer valid + reason>
809
- - Re-scope needed: <yes/no>
810
- - Never create a second \`## Locked Decisions\` heading in brainstorm; reference prior D-XX IDs inline.
811
- 3. **Resume Path**: if a wave was interrupted mid-stage, \`cclaw run resume\` restores state. Run \`internal verify-current-state\` before continuing.
812
- 4. **Wave End**: at ship, architect cross-stage verification runs from dispatch matrix. If \`DRIFT_DETECTED\`, fix before ship.
813
- 5. **Next Wave Trigger**: launch new \`/cc <topic>\` for next wave and reference previous wave ship artifact in upstream handoff.
541
+ These tokens are the wire protocol of cclaw. Translating them breaks tool calls, AC matching, frontmatter parsing, and the commit-helper hook. They are identifiers, not vocabulary.
814
542
 
815
- ## Status Markers
543
+ ## What MAY be in either language
816
544
 
817
- - \`wave-status: in-progress\` current stage incomplete.
818
- - \`wave-status: blocked-by-prev\` — waiting on previous wave verification.
819
- - \`wave-status: shipped\` — wave shipped, next wave can start.
820
- - \`wave-status: rolled-back\` — previous wave invalidated, current wave needs rebase.
545
+ Artifact bodies (the prose inside \`plans/<slug>.md\`, \`builds/<slug>.md\`, \`reviews/<slug>.md\`, \`ships/<slug>.md\`, \`decisions/<slug>.md\`, \`learnings/<slug>.md\`).
821
546
 
822
- ## Linter Hooks
547
+ Default rule: write the artifact body in the same language as the user's conversation, because the artifact is for them and for the next agent who reads their notes. The frontmatter stays English (it is the wire protocol).
823
548
 
824
- - If multi-wave work is detected (>1 wave-plan files in \`.cclaw/wave-plans/\`), current brainstorm artifact MUST contain \`## Wave Carry-forward\` section with drift audit.
825
- - If carry-forward drift is missing in multi-wave context, emit \`[P1] wave.drift_unaddressed\`.
549
+ If the user explicitly asks for English-only artifacts ("write the plan in English so the rest of the team can read it"), honour the request. Otherwise stay in their language.
550
+
551
+ Commit messages: the AC line stays English (\`AC-N: …\`); the rest of the message body may follow the artifact-body language.
552
+
553
+ ## Worked example — Russian conversation
554
+
555
+ User: "сделай мне CLI клиент для нашего REST API"
556
+
557
+ You (status): "Стартую план \`api-cli\`. Подтягиваю pattern \`api-endpoint.md\`. Пять AC: list, get, create, update, delete. Подтверждаешь?"
558
+
559
+ You (artifact \`flows/api-cli/plan.md\`):
560
+
561
+ \`\`\`markdown
562
+ ---
563
+ slug: api-cli
564
+ stage: plan
565
+ status: active
566
+ ac:
567
+ - id: AC-1
568
+ text: list команда вызывает GET /resources и печатает таблицу.
569
+ status: pending
570
+ ---
571
+
572
+ # api-cli
573
+
574
+
575
+ \`\`\`
576
+
577
+ Note: slug stays \`api-cli\` (English, kebab-case); AC ids stay \`AC-1\` (English); frontmatter keys stay English; the AC body is in Russian.
578
+
579
+ You (commit message): \`AC-1: добавлен list-команд via fetch\`. The \`AC-1:\` prefix is English (commit-helper requires it); the message body is Russian.
580
+
581
+ ## Common pitfalls
582
+
583
+ - Translating slugs ("добавить-cli" instead of "add-cli"). Slugs are filenames; keep them ASCII kebab-case.
584
+ - Translating frontmatter keys (\`статус: активен\`). Frontmatter is parsed by code; keys must be English.
585
+ - Restating the same status update twice ("Старт. — Starting."). Pick one. Match the user.
586
+ - Switching to English when the answer is "complicated". The user's complexity tolerance is not your language tolerance.
587
+ - Translating commit-helper output (\`[ошибка]\`). Hook output is read by the harness; leave it in English. Your own commentary on top of the hook output may be in the user's language.
588
+
589
+ ## How to detect language
590
+
591
+ 1. Read the user's last message. If it has at least one full sentence in language X, X is the language.
592
+ 2. If the user mixed languages within one message, count tokens; pick the language with the most non-stopword tokens.
593
+ 3. If still tied, default to the language of their previous-but-one message.
594
+ 4. If there is no usable history (first turn, terse prompt), default to English. Do not guess from one ambiguous word.
826
595
  `;
596
+ const ANTI_SLOP = `---
597
+ name: anti-slop
598
+ trigger: always-on for any code-modifying step (slice-builder, fix-only, recovery)
599
+ ---
600
+
601
+ # Skill: anti-slop
602
+
603
+ cclaw takes its lean ethos seriously: **no busywork, no fake fixes, no fake progress.** This skill applies whenever you are writing code, modifying tests, debugging a build/lint/test failure, or running verification commands.
604
+
605
+ ## Two iron rules
606
+
607
+ ### 1. No redundant verification
608
+
609
+ Do not re-run the same build, test, or lint command twice in a row without a code or input change in between. The result will not change. If a check failed, change something — or stop and report the failure as a finding.
610
+
611
+ **What counts as a "change":**
612
+
613
+ - modified production source
614
+ - modified test file
615
+ - modified config / fixture / lockfile
616
+ - different argument set passed to the same tool (\`npm test\` → \`npm test -- --reporter=verbose --testNamePattern="AC-1"\` is OK; the same \`npm test\` twice is not)
617
+
618
+ **Red flags (do NOT do these):**
619
+
620
+ - "let me try the test again" without any edit
621
+ - "let me re-build" without any edit
622
+ - "let me re-lint" without any edit
623
+ - "let me check if the issue is still there" without any edit
624
+
625
+ If a tool succeeded once, do not run it a second time to "make sure". If it failed once, the second identical run will fail too.
626
+
627
+ ### 2. No environment shims, no fake fixes
628
+
629
+ When a build / test / lint fails, **fix the root cause** or **surface the failure as a finding**. The following are anti-patterns; reviewer flags them as \`block\`:
630
+
631
+ - wrapping a real failure in \`try / catch\` and ignoring the error
632
+ - skipping a test (\`.skip\`, \`xit\`, \`@pytest.mark.skip\`, \`#[ignore]\`) "until later" without a follow-up issue or AC
633
+ - adding \`process.env.NODE_ENV === "test"\` (or equivalent) branches just to make tests pass
634
+ - adding \`// @ts-ignore\`, \`// eslint-disable\`, \`# noqa\`, \`# type: ignore\` to silence the failure rather than fix it
635
+ - short-circuiting a function with a hardcoded fixture value when "in test"
636
+ - mocking a function inline inside production code "just to get past this"
637
+ - writing a fallback that hides a real error path (\`return data ?? STUB_DATA\` where STUB_DATA exists only to dodge an upstream failure)
638
+ - copy-pasting a stack-trace into a try/catch as the "fix"
639
+
640
+ If the real fix is out of scope for the current AC, **stop**. Surface the failure and let the orchestrator hand the slug back to planner. Do not "make it work" with a shim and commit. Reviewer will catch the shim, the slug will fail review, and you will redo the work properly. Save the round-trip.
641
+
642
+ ## When you are tempted to add a fallback
643
+
644
+ Ask yourself: *"what real failure is this fallback hiding?"* If the answer is "I don't know" or "the test was flaky", the fallback is slop. Find the real failure first.
645
+
646
+ ## Worked example — slop vs root-cause
647
+
648
+ ❌ slop:
649
+
650
+ \`\`\`ts
651
+ function getUser(id: string) {
652
+ try {
653
+ return db.users.find(id);
654
+ } catch (e) {
655
+ if (process.env.NODE_ENV === "test") return { id, name: "test-user" }; // makes the test pass
656
+ throw e;
657
+ }
827
658
  }
659
+ \`\`\`
660
+
661
+ ✅ root-cause:
662
+
663
+ \`\`\`ts
664
+ // (test fixture seeds a user before calling getUser; production code untouched)
665
+ beforeEach(async () => { await db.users.insert({ id: "u-1", name: "Anna" }); });
666
+ \`\`\`
667
+
668
+ ## What to surface as a finding (and stop)
669
+
670
+ - **Root cause is in someone else's slug.** Surface as \`block\`: "AC-N depends on \`<file>\` which is owned by \`<other slug>\`. Cannot complete without the other slug shipping first."
671
+ - **Test framework is broken.** Surface as \`block\`: "test runner exits with \`<exact-error>\` independent of the test under change."
672
+ - **Plan is wrong.** Surface as \`info\`: "AC-N as written cannot be implemented without touching \`<file>\`, but the plan rules out that file."
673
+ - **Dependency upgrade required.** Surface as \`info\`: "AC-N requires \`<lib>@>=X\`, current is \`<Y>\`. Recommend separate dep-bump slug."
674
+
675
+ In all four cases: stop, return the summary JSON, do **not** push code that "works around it".
676
+
677
+ ## What this skill does NOT prevent
678
+
679
+ - Re-running a build / test after you actually changed code. That is normal TDD GREEN-cycle behaviour.
680
+ - Adding a real test fixture or mock library at the test boundary (\`vi.mock("./db")\` in the *test file*, not in production). The boundary matters.
681
+ - Documented \`// eslint-disable\` lines with a one-line justification AND a follow-up issue id. The justification is what makes it not slop.
682
+ - Running \`tsc --noEmit\` after \`npm test\` — that is a different tool, not a re-run of the same one.
683
+ `;
684
+ export const AUTO_TRIGGER_SKILLS = [
685
+ {
686
+ id: "plan-authoring",
687
+ fileName: "plan-authoring.md",
688
+ description: "Auto-applies whenever the agent edits .cclaw/flows/<slug>/plan.md.",
689
+ triggers: ["edit:.cclaw/flows/*/plan.md", "create:.cclaw/flows/*/plan.md"],
690
+ body: PLAN_AUTHORING
691
+ },
692
+ {
693
+ id: "ac-traceability",
694
+ fileName: "ac-traceability.md",
695
+ description: "Enforces commit-helper invocation and AC↔commit chain.",
696
+ triggers: ["before:git-commit", "before:git-push"],
697
+ body: AC_TRACEABILITY
698
+ },
699
+ {
700
+ id: "refinement",
701
+ fileName: "refinement.md",
702
+ description: "Activates when /cc detects an existing plan match.",
703
+ triggers: ["existing-plan-detected"],
704
+ body: REFINEMENT
705
+ },
706
+ {
707
+ id: "parallel-build",
708
+ fileName: "parallel-build.md",
709
+ description: "Rules and execution playbook for the parallel-build topology.",
710
+ triggers: ["topology:parallel-build"],
711
+ body: PARALLEL_BUILD
712
+ },
713
+ {
714
+ id: "security-review",
715
+ fileName: "security-review.md",
716
+ description: "Activates when the diff touches sensitive surfaces.",
717
+ triggers: ["security-flag:true", "diff:auth|secrets|supply-chain|pii"],
718
+ body: SECURITY_REVIEW
719
+ },
720
+ {
721
+ id: "review-loop",
722
+ fileName: "review-loop.md",
723
+ description: "Wraps every reviewer / security-reviewer invocation.",
724
+ triggers: ["specialist:reviewer", "specialist:security-reviewer"],
725
+ body: REVIEW_LOOP
726
+ },
727
+ {
728
+ id: "tdd-cycle",
729
+ fileName: "tdd-cycle.md",
730
+ description: "Mandatory always-on skill while stage=build. Enforces RED → GREEN → REFACTOR per AC, with watched-RED proof and full-suite GREEN evidence.",
731
+ triggers: ["stage:build", "specialist:slice-builder"],
732
+ body: TDD_CYCLE
733
+ },
734
+ {
735
+ id: "commit-message-quality",
736
+ fileName: "commit-message-quality.md",
737
+ description: "Enforces commit-message conventions for commit-helper.mjs.",
738
+ triggers: ["before:commit-helper"],
739
+ body: COMMIT_MESSAGE_QUALITY
740
+ },
741
+ {
742
+ id: "ac-quality",
743
+ fileName: "ac-quality.md",
744
+ description: "Three-check rubric for every AC entry; smell tests + numbering rules.",
745
+ triggers: ["edit:.cclaw/flows/*/plan.md", "specialist:planner", "specialist:reviewer:text-review"],
746
+ body: AC_QUALITY
747
+ },
748
+ {
749
+ id: "refactor-safety",
750
+ fileName: "refactor-safety.md",
751
+ description: "Behaviour-preservation rules for pure-refactor slugs.",
752
+ triggers: ["task:refactor", "pattern:refactor"],
753
+ body: REFACTOR_SAFETY
754
+ },
755
+ {
756
+ id: "breaking-changes",
757
+ fileName: "breaking-changes.md",
758
+ description: "Detect and document breaking changes; coexistence rules and CHANGELOG template.",
759
+ triggers: ["diff:public-api", "frontmatter:breaking_change=true"],
760
+ body: BREAKING_CHANGES
761
+ },
762
+ {
763
+ id: "conversation-language",
764
+ fileName: "conversation-language.md",
765
+ description: "Always-on policy: reply in the user's language; never translate paths, AC ids, slugs, hook output, or frontmatter keys.",
766
+ triggers: ["always-on"],
767
+ body: CONVERSATION_LANGUAGE
768
+ },
769
+ {
770
+ id: "anti-slop",
771
+ fileName: "anti-slop.md",
772
+ description: "Always-on guard against redundant verification, env-specific shims, and silent skip-and-pass fixes.",
773
+ triggers: ["always-on", "task:build", "task:fix-only", "task:recovery"],
774
+ body: ANTI_SLOP
775
+ }
776
+ ];