cclaw-cli 7.7.1 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/README.md +210 -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 +90 -508
  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/install.d.ts +27 -15
  73. package/dist/install.js +230 -1342
  74. package/dist/knowledge-store.d.ts +19 -163
  75. package/dist/knowledge-store.js +56 -590
  76. package/dist/logger.d.ts +8 -3
  77. package/dist/logger.js +13 -4
  78. package/dist/orchestrator-routing.d.ts +29 -0
  79. package/dist/orchestrator-routing.js +156 -0
  80. package/dist/run-persistence.d.ts +7 -118
  81. package/dist/run-persistence.js +29 -845
  82. package/dist/runtime/run-hook.entry.d.ts +1 -3
  83. package/dist/runtime/run-hook.entry.js +19 -4
  84. package/dist/runtime/run-hook.mjs +13 -1024
  85. package/dist/types.d.ts +25 -261
  86. package/dist/types.js +8 -36
  87. package/package.json +6 -3
  88. package/dist/artifact-linter/brainstorm.d.ts +0 -2
  89. package/dist/artifact-linter/brainstorm.js +0 -353
  90. package/dist/artifact-linter/design.d.ts +0 -18
  91. package/dist/artifact-linter/design.js +0 -444
  92. package/dist/artifact-linter/findings-dedup.d.ts +0 -56
  93. package/dist/artifact-linter/findings-dedup.js +0 -232
  94. package/dist/artifact-linter/plan.d.ts +0 -2
  95. package/dist/artifact-linter/plan.js +0 -826
  96. package/dist/artifact-linter/review-army.d.ts +0 -49
  97. package/dist/artifact-linter/review-army.js +0 -520
  98. package/dist/artifact-linter/review.d.ts +0 -2
  99. package/dist/artifact-linter/review.js +0 -113
  100. package/dist/artifact-linter/scope.d.ts +0 -2
  101. package/dist/artifact-linter/scope.js +0 -158
  102. package/dist/artifact-linter/shared.d.ts +0 -637
  103. package/dist/artifact-linter/shared.js +0 -2163
  104. package/dist/artifact-linter/ship.d.ts +0 -2
  105. package/dist/artifact-linter/ship.js +0 -250
  106. package/dist/artifact-linter/spec.d.ts +0 -2
  107. package/dist/artifact-linter/spec.js +0 -176
  108. package/dist/artifact-linter/tdd.d.ts +0 -118
  109. package/dist/artifact-linter/tdd.js +0 -1404
  110. package/dist/artifact-linter.d.ts +0 -15
  111. package/dist/artifact-linter.js +0 -517
  112. package/dist/codex-feature-flag.d.ts +0 -58
  113. package/dist/codex-feature-flag.js +0 -193
  114. package/dist/content/closeout-guidance.d.ts +0 -14
  115. package/dist/content/closeout-guidance.js +0 -44
  116. package/dist/content/diff-command.d.ts +0 -1
  117. package/dist/content/diff-command.js +0 -43
  118. package/dist/content/harness-doc.d.ts +0 -1
  119. package/dist/content/harness-doc.js +0 -65
  120. package/dist/content/hook-events.d.ts +0 -9
  121. package/dist/content/hook-events.js +0 -23
  122. package/dist/content/hook-manifest.d.ts +0 -81
  123. package/dist/content/hook-manifest.js +0 -156
  124. package/dist/content/hooks.d.ts +0 -11
  125. package/dist/content/hooks.js +0 -1972
  126. package/dist/content/idea.d.ts +0 -60
  127. package/dist/content/idea.js +0 -416
  128. package/dist/content/language-policy.d.ts +0 -2
  129. package/dist/content/language-policy.js +0 -13
  130. package/dist/content/learnings.d.ts +0 -6
  131. package/dist/content/learnings.js +0 -141
  132. package/dist/content/observe.d.ts +0 -19
  133. package/dist/content/observe.js +0 -86
  134. package/dist/content/opencode-plugin.d.ts +0 -1
  135. package/dist/content/opencode-plugin.js +0 -635
  136. package/dist/content/review-prompts.d.ts +0 -1
  137. package/dist/content/review-prompts.js +0 -104
  138. package/dist/content/runtime-shared-snippets.d.ts +0 -8
  139. package/dist/content/runtime-shared-snippets.js +0 -80
  140. package/dist/content/session-hooks.d.ts +0 -7
  141. package/dist/content/session-hooks.js +0 -107
  142. package/dist/content/skills-elicitation.d.ts +0 -1
  143. package/dist/content/skills-elicitation.js +0 -167
  144. package/dist/content/stage-command.d.ts +0 -2
  145. package/dist/content/stage-command.js +0 -17
  146. package/dist/content/stage-schema.d.ts +0 -117
  147. package/dist/content/stage-schema.js +0 -955
  148. package/dist/content/stages/_lint-metadata/index.d.ts +0 -2
  149. package/dist/content/stages/_lint-metadata/index.js +0 -97
  150. package/dist/content/stages/brainstorm.d.ts +0 -2
  151. package/dist/content/stages/brainstorm.js +0 -184
  152. package/dist/content/stages/design.d.ts +0 -2
  153. package/dist/content/stages/design.js +0 -288
  154. package/dist/content/stages/index.d.ts +0 -8
  155. package/dist/content/stages/index.js +0 -11
  156. package/dist/content/stages/plan.d.ts +0 -2
  157. package/dist/content/stages/plan.js +0 -191
  158. package/dist/content/stages/review.d.ts +0 -2
  159. package/dist/content/stages/review.js +0 -240
  160. package/dist/content/stages/schema-types.d.ts +0 -203
  161. package/dist/content/stages/schema-types.js +0 -1
  162. package/dist/content/stages/scope.d.ts +0 -2
  163. package/dist/content/stages/scope.js +0 -254
  164. package/dist/content/stages/ship.d.ts +0 -2
  165. package/dist/content/stages/ship.js +0 -159
  166. package/dist/content/stages/spec.d.ts +0 -2
  167. package/dist/content/stages/spec.js +0 -170
  168. package/dist/content/stages/tdd.d.ts +0 -4
  169. package/dist/content/stages/tdd.js +0 -273
  170. package/dist/content/state-contracts.d.ts +0 -1
  171. package/dist/content/state-contracts.js +0 -63
  172. package/dist/content/status-command.d.ts +0 -4
  173. package/dist/content/status-command.js +0 -109
  174. package/dist/content/subagent-context-skills.d.ts +0 -4
  175. package/dist/content/subagent-context-skills.js +0 -279
  176. package/dist/content/subagents.d.ts +0 -3
  177. package/dist/content/subagents.js +0 -997
  178. package/dist/content/templates.d.ts +0 -26
  179. package/dist/content/templates.js +0 -1692
  180. package/dist/content/track-render-context.d.ts +0 -18
  181. package/dist/content/track-render-context.js +0 -53
  182. package/dist/content/tree-command.d.ts +0 -1
  183. package/dist/content/tree-command.js +0 -64
  184. package/dist/content/utility-skills.d.ts +0 -30
  185. package/dist/content/utility-skills.js +0 -160
  186. package/dist/content/view-command.d.ts +0 -2
  187. package/dist/content/view-command.js +0 -92
  188. package/dist/delegation.d.ts +0 -649
  189. package/dist/delegation.js +0 -1539
  190. package/dist/early-loop.d.ts +0 -70
  191. package/dist/early-loop.js +0 -302
  192. package/dist/execution-topology.d.ts +0 -44
  193. package/dist/execution-topology.js +0 -95
  194. package/dist/gate-evidence.d.ts +0 -85
  195. package/dist/gate-evidence.js +0 -631
  196. package/dist/harness-adapters.d.ts +0 -151
  197. package/dist/harness-adapters.js +0 -756
  198. package/dist/harness-selection.d.ts +0 -31
  199. package/dist/harness-selection.js +0 -214
  200. package/dist/hook-schema.d.ts +0 -6
  201. package/dist/hook-schema.js +0 -114
  202. package/dist/hook-schemas/claude-hooks.v1.json +0 -10
  203. package/dist/hook-schemas/codex-hooks.v1.json +0 -10
  204. package/dist/hook-schemas/cursor-hooks.v1.json +0 -13
  205. package/dist/init-detect.d.ts +0 -2
  206. package/dist/init-detect.js +0 -50
  207. package/dist/internal/advance-stage/advance.d.ts +0 -89
  208. package/dist/internal/advance-stage/advance.js +0 -655
  209. package/dist/internal/advance-stage/cancel-run.d.ts +0 -8
  210. package/dist/internal/advance-stage/cancel-run.js +0 -19
  211. package/dist/internal/advance-stage/flow-state-coercion.d.ts +0 -3
  212. package/dist/internal/advance-stage/flow-state-coercion.js +0 -81
  213. package/dist/internal/advance-stage/helpers.d.ts +0 -14
  214. package/dist/internal/advance-stage/helpers.js +0 -145
  215. package/dist/internal/advance-stage/hook.d.ts +0 -8
  216. package/dist/internal/advance-stage/hook.js +0 -40
  217. package/dist/internal/advance-stage/parsers.d.ts +0 -72
  218. package/dist/internal/advance-stage/parsers.js +0 -357
  219. package/dist/internal/advance-stage/proactive-delegation-trace.d.ts +0 -24
  220. package/dist/internal/advance-stage/proactive-delegation-trace.js +0 -56
  221. package/dist/internal/advance-stage/review-loop.d.ts +0 -16
  222. package/dist/internal/advance-stage/review-loop.js +0 -199
  223. package/dist/internal/advance-stage/rewind.d.ts +0 -14
  224. package/dist/internal/advance-stage/rewind.js +0 -108
  225. package/dist/internal/advance-stage/start-flow.d.ts +0 -13
  226. package/dist/internal/advance-stage/start-flow.js +0 -241
  227. package/dist/internal/advance-stage/verify.d.ts +0 -21
  228. package/dist/internal/advance-stage/verify.js +0 -185
  229. package/dist/internal/advance-stage.d.ts +0 -7
  230. package/dist/internal/advance-stage.js +0 -138
  231. package/dist/internal/cohesion-contract-stub.d.ts +0 -24
  232. package/dist/internal/cohesion-contract-stub.js +0 -148
  233. package/dist/internal/compound-readiness.d.ts +0 -23
  234. package/dist/internal/compound-readiness.js +0 -102
  235. package/dist/internal/detect-public-api-changes.d.ts +0 -5
  236. package/dist/internal/detect-public-api-changes.js +0 -45
  237. package/dist/internal/detect-supply-chain-changes.d.ts +0 -6
  238. package/dist/internal/detect-supply-chain-changes.js +0 -138
  239. package/dist/internal/early-loop-status.d.ts +0 -7
  240. package/dist/internal/early-loop-status.js +0 -93
  241. package/dist/internal/envelope-validate.d.ts +0 -7
  242. package/dist/internal/envelope-validate.js +0 -66
  243. package/dist/internal/flow-state-repair.d.ts +0 -20
  244. package/dist/internal/flow-state-repair.js +0 -104
  245. package/dist/internal/plan-split-waves.d.ts +0 -190
  246. package/dist/internal/plan-split-waves.js +0 -764
  247. package/dist/internal/runtime-integrity.d.ts +0 -7
  248. package/dist/internal/runtime-integrity.js +0 -268
  249. package/dist/internal/slice-commit.d.ts +0 -7
  250. package/dist/internal/slice-commit.js +0 -619
  251. package/dist/internal/tdd-loop-status.d.ts +0 -14
  252. package/dist/internal/tdd-loop-status.js +0 -68
  253. package/dist/internal/tdd-red-evidence.d.ts +0 -7
  254. package/dist/internal/tdd-red-evidence.js +0 -153
  255. package/dist/internal/waiver-grant.d.ts +0 -62
  256. package/dist/internal/waiver-grant.js +0 -294
  257. package/dist/internal/wave-status.d.ts +0 -74
  258. package/dist/internal/wave-status.js +0 -506
  259. package/dist/managed-resources.d.ts +0 -53
  260. package/dist/managed-resources.js +0 -313
  261. package/dist/policy.d.ts +0 -10
  262. package/dist/policy.js +0 -167
  263. package/dist/retro-gate.d.ts +0 -9
  264. package/dist/retro-gate.js +0 -47
  265. package/dist/run-archive.d.ts +0 -61
  266. package/dist/run-archive.js +0 -391
  267. package/dist/runs.d.ts +0 -2
  268. package/dist/runs.js +0 -2
  269. package/dist/stack-detection.d.ts +0 -116
  270. package/dist/stack-detection.js +0 -489
  271. package/dist/streaming/event-stream.d.ts +0 -31
  272. package/dist/streaming/event-stream.js +0 -114
  273. package/dist/tdd-cycle.d.ts +0 -107
  274. package/dist/tdd-cycle.js +0 -289
  275. package/dist/tdd-verification-evidence.d.ts +0 -17
  276. package/dist/tdd-verification-evidence.js +0 -122
  277. package/dist/track-heuristics.d.ts +0 -27
  278. package/dist/track-heuristics.js +0 -154
  279. package/dist/util/slice-id.d.ts +0 -58
  280. package/dist/util/slice-id.js +0 -89
  281. package/dist/worktree-manager.d.ts +0 -20
  282. package/dist/worktree-manager.js +0 -108
package/README.md CHANGED
@@ -1,197 +1,273 @@
1
1
  # cclaw
2
2
 
3
- **cclaw is a file-backed flow runtime for coding agents.** It turns Claude Code, Cursor, OpenCode, and Codex into one repeatable path from idea to shipped change: visible stages, hard gates, real subagent evidence, and resumable closeout in your repo.
3
+ **cclaw is a lightweight harness-first flow toolkit for coding agents.** It installs three slash commands, six on-demand specialists, twelve auto-trigger skills (including TDD cycle and conversation-language), ten artifact templates, four stage runbooks, eight reference patterns, five research playbooks, five recovery playbooks, thirteen worked examples, an antipatterns library, a decision protocol, a meta-skill, and a tiny runtime — together a deep content layer wrapped around a runtime under 1 KLOC — so Claude Code, Cursor, OpenCode, or Codex can move from idea to shipped change with a clear plan, AC traceability, TDD per AC, and almost no ceremony.
4
4
 
5
5
  ```text
6
6
  idea
7
- |
8
- v
9
- +-------------+ +--------+ +--------+ +------+ +------+ +-----+
10
- | brainstorm | ---> | scope | ---> | design | ---> | spec | ---> | plan | ---> | tdd |
11
- +-------------+ +--------+ +--------+ +------+ +------+ +-----+
12
- |
13
- v
14
- +--------+ +------+
15
- | review | ---> | ship |
16
- +--------+ +------+
17
- |
18
- v
19
- post_ship_review -> archive
7
+
8
+
9
+ /cc <task>
10
+
11
+ ┌─────┴─────────────────────────────────────┐
12
+ │ Phase 0 calibration: │
13
+ │ targeted change or multi-component? │
14
+ └─────┬─────────────────┬───────────────────┘
15
+ │trivial │small/medium │large/risky
16
+ ▼ ▼ ▼
17
+ edit + commit plan → build brainstormer →
18
+ per AC → review → ship architect → planner
19
+ (each is optional)
20
+
21
+
22
+ compound (auto, gated)
23
+
24
+
25
+ active artifacts → shipped/<slug>/
20
26
  ```
21
27
 
22
- The promise is simple: at any point you can ask **where are we, what is blocked, what evidence exists, and what should run next?**
28
+ Three slash commands. Four stages (`plan build review → ship`, where **build IS a TDD cycle**: RED GREEN REFACTOR per AC). Six specialists. Eleven skills (including a TDD-cycle skill that's always-on while building). Ten templates. Four runbooks. Eight reference patterns. Five research playbooks. Five recovery playbooks. Thirteen worked examples. Two mandatory gates (AC traceability + TDD phase chain).
23
29
 
24
- ## First 5 Minutes
30
+ ## What changed in v8
25
31
 
26
- Requirements: Node.js 20+ and a git project root.
32
+ cclaw v8.0 is a breaking redesign. We dropped the 7.x stage machine: no more `brainstorm` / `scope` / `design` / `spec` / `tdd` mandatory stages, no more 18 specialists, no more 9 state files, no more 30 stage gates. v7.x runs are not migrated; see [docs/migration-v7-to-v8.md](docs/migration-v7-to-v8.md).
33
+
34
+ What we kept and made deeper:
35
+
36
+ - plans with **acceptance criteria + YAML frontmatter** (`slug`, `stage`, `status`, `ac[]`, `last_specialist`, `refines`, `shipped_at`, `ship_commit`, `review_iterations`, `security_flag`);
37
+ - **build is a TDD stage** — every AC goes through RED → GREEN → REFACTOR; `commit-helper.mjs --phase=red|green|refactor` enforces the cycle (production files in RED are rejected, GREEN without prior RED is rejected, REFACTOR is mandatory);
38
+ - **AC ↔ commit traceability** enforced by `commit-helper.mjs`;
39
+ - **artifact templates** for every stage (`plan`, `build`, `review`, `ship`, `decisions`, `learnings`, `manifest`, `ideas`, `iron-laws`);
40
+ - **twelve auto-trigger skills** — plan-authoring, AC traceability, refinement, parallel-build, security-review, review-loop, commit-message-quality, AC-quality, refactor-safety, breaking-changes, conversation-language (always-on), anti-slop (always-on), plus a meta-skill that ties them together;
41
+ - **stage runbooks** (`.cclaw/lib/runbooks/{plan,build,review,ship}.md`) — strict checklists per stage with common pitfalls;
42
+ - **reference patterns** (`.cclaw/lib/patterns/`) — eight task-type playbooks (api-endpoint, auth-flow, schema-migration, ui-component, perf-fix, refactor, security-hardening, doc-rewrite) the orchestrator opens before authoring AC;
43
+ - **research playbooks** (`.cclaw/lib/research/`) — reading the codebase (files + tests + integration boundaries), time-boxing, using prior shipped slugs;
44
+ - **recovery playbooks** (`.cclaw/lib/recovery/`) — AC traceability break, review hard cap reached, parallel-build slice conflict, frontmatter corruption, schemaVersion mismatch;
45
+ - **examples library** (`.cclaw/lib/examples/`) — eight real-looking plan / build / review / ship / decision / learning / commit-helper artifacts;
46
+ - **antipatterns** (`.cclaw/lib/antipatterns.md`) — twelve known failure modes the reviewer cites as findings;
47
+ - **decision protocol** (`.cclaw/lib/decision-protocol.md`) — short-form digest of "is this even a decision?"; full D-N schema lives in `lib/agents/architect.md`, worked decisions in `lib/examples/`;
48
+ - **resumable refinement** via frontmatter on shipped slugs (`refines: <old-slug>`);
49
+ - durable artifacts your team and graph tools (Graphify, GitNexus, etc.) can index.
50
+
51
+ ## First 5 minutes
52
+
53
+ Requirements: Node.js 20+ and a git project.
27
54
 
28
55
  ```bash
29
56
  cd /path/to/your/repo
30
- npx cclaw-cli
57
+ npx cclaw-cli init # auto-detect harness from project root
58
+ npx cclaw-cli init --harness=claude,cursor,opencode,codex # explicit selection
31
59
  ```
32
60
 
33
- Then work from your coding harness:
34
-
35
- ```text
36
- /cc <idea> start, resume, or continue a tracked flow
37
- /cc-idea generate or refresh an idea backlog
38
- /cc-cancel end the current run cleanly with a reason
39
- ```
61
+ `init` resolves harnesses in this order:
40
62
 
41
- `/cc-idea` is a utility command for backlog discovery. It is distinct from
42
- `.cclaw/artifacts/00-idea.md`, which is the stage artifact created by
43
- `/cc <idea>`.
63
+ 1. `--harness=<id>[,<id>]` flag if passed.
64
+ 2. Existing `.cclaw/config.yaml` (so subsequent `init` / `sync` / `upgrade` are deterministic).
65
+ 3. Auto-detect from project root markers: `.claude/`, `.cursor/`, `.opencode/`, `.codex/`, `.agents/skills/`, `CLAUDE.md`, `opencode.json`, `opencode.jsonc`.
66
+ 4. If nothing detected and no flag passed → exit with an actionable error. cclaw never silently picks a harness for you.
44
67
 
45
- For scripted setup:
68
+ Then work entirely inside your harness:
46
69
 
47
- ```bash
48
- npx cclaw-cli init --harnesses=claude,cursor --no-interactive
70
+ ```text
71
+ /cc <task> plan / build / review / ship — orchestrator routes everything
72
+ /cc-cancel stop the active run cleanly (artifacts move to .cclaw/flows/cancelled/<slug>/)
73
+ /cc-idea drop a half-formed idea into .cclaw/ideas.md (no flow started)
49
74
  ```
50
75
 
51
- If generated files or hooks look stale, run `npx cclaw-cli sync`.
76
+ There is no `cclaw plan`, `cclaw status`, `cclaw ship`, or `cclaw migrate` CLI command. Flow control lives in `/cc` inside the harness.
77
+
78
+ ## Six specialists, all on demand
79
+
80
+ | id | modes | when |
81
+ | --- | --- | --- |
82
+ | `brainstormer` | frame / scope / alternatives | ambiguous request, need a frame and scope |
83
+ | `architect` | architecture / feasibility | structural decisions or feasibility check |
84
+ | `planner` | research / work-breakdown / topology | breaking work into AC and choosing topology |
85
+ | `reviewer` | code / text-review / integration / release / adversarial | reviews of any kind |
86
+ | `security-reviewer` | threat-model / sensitive-change | auth / secrets / supply chain / data exposure |
87
+ | `slice-builder` | build / fix-only | implementing AC and applying scoped fixes |
88
+
89
+ Specialists are proposed only when the task is large, abstract, risky, security-sensitive, or spans multiple components. Trivial and small/medium tasks run inline. Each prompt is 150-280 lines and includes an explicit output schema, two or more worked examples, edge cases, common pitfalls, and hard rules (see `.cclaw/lib/agents/*.md` after install). The orchestrator pulls additional context from runbooks, patterns, examples, and recovery playbooks as needed; see [docs/skills.md](docs/skills.md) for the auto-trigger layer that wraps every invocation.
90
+
91
+ ## Plan artifact, by example
92
+
93
+ ```yaml
94
+ ---
95
+ slug: approval-page
96
+ stage: plan
97
+ status: active
98
+ ac:
99
+ - id: AC-1
100
+ text: "User sees an approval status pill on the dashboard."
101
+ status: pending
102
+ - id: AC-2
103
+ text: "Pending approvals show a tooltip with the approver's name."
104
+ status: pending
105
+ last_specialist: null
106
+ refines: null
107
+ shipped_at: null
108
+ ship_commit: null
109
+ review_iterations: 0
110
+ security_flag: false
111
+ ---
112
+
113
+ # approval-page
114
+
115
+ > One paragraph: what we are doing and why.
116
+
117
+ ## Acceptance Criteria
118
+
119
+ | id | text | status | commit |
120
+ | --- | --- | --- | --- |
121
+ | AC-1 | User sees an approval status pill on the dashboard. | pending | — |
122
+ | AC-2 | Pending approvals show a tooltip with the approver's name. | pending | — |
123
+ ```
52
124
 
53
- ## Why cclaw
125
+ The same shape applies to `build.md` (commit log), `review.md` (findings + Five Failure Modes pass), `ship.md` (release notes + push/PR refs), `decisions.md` (architect output), `learnings.md` (compound output). Templates live in `.cclaw/lib/templates/`.
54
126
 
55
- AI coding sessions fail when decisions live only in chat. cclaw puts the operating truth in files:
127
+ ## Artifact tree
56
128
 
57
- ```text
129
+ ```
58
130
  .cclaw/
59
- artifacts/ active stage docs: 00-idea.md through 09-retro.md
60
- state/flow-state.json current stage, gates, stale markers, closeout.shipSubstate
61
- state/delegation-log.json
62
- subagent dispatches, waivers, evidence refs
63
- knowledge.jsonl reusable lessons harvested from stage artifacts
64
- archive/ archived run snapshots (durable closeout proof)
131
+ config.yaml cclaw config (harness, flow defaults)
132
+ ideas.md append-only idea backlog (/cc-idea)
133
+ knowledge.jsonl cross-feature learnings index, append-only
134
+ state/
135
+ flow-state.json ~500 bytes, schemaVersion: 2
136
+ hooks/
137
+ session-start.mjs rehydrates flow state on harness boot
138
+ stop-handoff.mjs short reminder when stopping mid-flow
139
+ commit-helper.mjs atomic commit per AC + traceability + TDD phase gate
140
+ flows/ everything that comes out of a /cc run
141
+ <slug>/ one folder per active flow
142
+ plan.md current work + AC
143
+ build.md implementation log + TDD evidence
144
+ review.md Concern Ledger + iteration logs
145
+ ship.md preflight + AC↔commit map + rollback + finalization
146
+ decisions.md architect output (optional; only when architect ran)
147
+ learnings.md compound output (optional; only when gated)
148
+ shipped/<slug>/ plan.md, build.md, review.md, ship.md,
149
+ decisions.md, learnings.md, manifest.md
150
+ cancelled/<slug>/ when /cc-cancel is invoked
151
+ lib/ reference content shipped by the installer
152
+ agents/ 6 specialist prompts (each ends with a Composition footer
153
+ locking it to its lane — no nested orchestration)
154
+ skills/ 12 auto-trigger skills (2 always-on: conversation-language,
155
+ anti-slop; 10 stage- or event-gated)
156
+ templates/ 9 templates (plan, build, review, ship, decisions,
157
+ learnings, manifest, ideas, iron-laws)
158
+ runbooks/ 4 stage runbooks (plan, build, review, ship)
159
+ patterns/ 8 task-type playbooks
160
+ research/ 3 research playbooks
161
+ recovery/ 5 recovery playbooks
162
+ examples/ 8 worked examples
163
+ antipatterns.md 12 named failure modes
164
+ decision-protocol.md short-form digest; full schema in lib/agents/architect.md
65
165
  ```
66
166
 
67
- That gives you:
167
+ `.cclaw/state/` and `.cclaw/worktrees/` are appended to `.gitignore` on init (transient per-session data). The rest of `.cclaw/` is committable; graphify, team review, and the next agent all need it.
68
168
 
69
- - **One path** from idea to ship, with one user-chosen discovery mode (`lean`, `guided`, `deep`) and internal `quick` / `medium` / `standard` tracks.
70
- - **Real gates** for evidence, tests, review, delegation, stale-stage recovery, and closeout.
71
- - **Adaptive TDD execution**: feature-atomic slices carry internal 2-5 minute RED/GREEN/REFACTOR steps; cclaw routes them inline, through one builder, through parallel builders, or through strict micro-slices when risk demands it.
72
- - **Subagents with accountability**: controller owns state, workers do bounded implementation units, overseers validate, evidence lands in `delegation-log.json`.
73
- - **Recovery instead of confusion**: `npx cclaw-cli sync` tells you blockers and next fixes.
74
- - **Portable harness behavior** across Claude Code, Cursor, OpenCode, and Codex.
169
+ The split is deliberate. Active and archived flow artifacts go under `flows/` so the orchestrator never confuses them with the read-only library under `lib/`. Runtime (`state/`, `hooks/`) stays at the top so harness hooks can find it without traversal. Active flows are grouped by slug — open `flows/<slug>/` and every artifact for that flow is right there, instead of scattered across six per-stage subdirectories.
75
170
 
76
- ## The Daily Loop
171
+ ## AC traceability gate (mandatory)
77
172
 
78
- ```text
79
- 1. Start or resume
80
- /cc <idea>
173
+ Ship is blocked unless every AC in the active plan is `status: committed` with a real commit SHA. The `commit-helper.mjs` hook is the only supported way to commit during `/cc`:
174
+
175
+ ```bash
176
+ git add path/to/changed/file
177
+ node .cclaw/hooks/commit-helper.mjs --ac=AC-1 --message="implement approval pill"
178
+ ```
81
179
 
82
- 2. Work the current stage
83
- The agent writes/updates per-stage files like .cclaw/artifacts/00-idea.md, 01-brainstorm-<slug>.md, 02-scope-<slug>.md
180
+ The hook checks that `AC-1` is declared in `plan.md`, refuses to run when `flow-state.json` schemaVersion is not `2`, runs `git commit`, captures the new SHA, and writes it back into `flow-state.json`. If you commit by hand, AC traceability breaks and ship will refuse.
84
181
 
85
- 3. Prove the gate
86
- stage-complete records evidence in flow-state.json
182
+ ## Compound learnings (automatic, gated)
87
183
 
88
- 4. Inspect when stuck
89
- npx cclaw-cli sync
184
+ After ship, cclaw automatically checks whether the run produced something worth remembering:
90
185
 
91
- 5. Close out after ship
92
- /cc continues post_ship_review -> archive
93
- ```
186
+ - a non-trivial decision was recorded by `architect` or `planner`, **or**
187
+ - review needed three or more iterations, **or**
188
+ - a security review ran or `security_flag` is true, **or**
189
+ - the user explicitly asked to capture (`/cc <task> --capture-learnings`).
94
190
 
95
- Tracks keep the flow proportional:
191
+ If yes → `flows/<slug>/learnings.md` is written from the template, and one line is appended to `knowledge.jsonl` recording the slug, ship_commit, signals, and `refines` chain. If no → silently skipped, so the index stays signal-rich. Then everything moves to `flows/shipped/<slug>/` with a `manifest.md`.
96
192
 
97
- ```text
98
- quick spec -> tdd -> review -> ship
99
- medium brainstorm -> spec -> plan -> tdd -> review -> ship
100
- standard brainstorm -> scope -> design -> spec -> plan -> tdd -> review -> ship
101
- ```
193
+ ## Parallel-build (cap: 5 slices, git worktree)
102
194
 
103
- At `/cc <idea>`, the user picks **one discovery mode** (`lean`, `guided`, `deep`) for upstream shaping. Track selection remains **model-guided and advisory** during start-up; runtime enforcement begins after state is written: subsequent `/cc` turns follow the selected internal track, persisted `discoveryMode`, required gates, delegation rules, stale-stage markers, and `closeout.shipSubstate`.
195
+ Inline is the default. Parallel-build is opt-in and only when planner declares it. Pre-conditions: ≥4 AC, ≥2 distinct touchSurface clusters, every AC `parallelSafe: true`, no AC depends on outputs of another AC in the same wave.
104
196
 
105
- ## When Blocked
197
+ A **slice = 1+ AC with a shared touchSurface**. If planner produces more than 5 slices, planner must merge thinner slices into fatter ones — never generate "wave 2", "wave 3". The 5-slice cap is the v7-era constraint kept on purpose: orchestration cost grows non-linearly past 5 sub-agents, and 5 fits comfortably under every harness's sub-agent quota.
106
198
 
107
- Start here:
199
+ When the harness supports sub-agent dispatch, each parallel slice runs in its own worktree:
108
200
 
109
- ```text
110
- npx cclaw-cli sync
201
+ ```bash
202
+ git worktree add .cclaw/worktrees/<slug>-slice-1 -b cclaw/<slug>/slice-1
203
+ git worktree add .cclaw/worktrees/<slug>-slice-2 -b cclaw/<slug>/slice-2
204
+ git worktree add .cclaw/worktrees/<slug>-slice-3 -b cclaw/<slug>/slice-3
111
205
  ```
112
206
 
113
- A useful status should read like an operator note, not a raw dump:
207
+ Each slice-builder runs RED GREEN REFACTOR for every AC it owns sequentially inside its worktree. After the wave, `reviewer` in `integration` mode reads from each worktree's branch and the orchestrator merges them in. If the harness does not support sub-agent dispatch (or worktree creation fails), parallel-build degrades silently to inline-sequential — recorded but not an error.
114
208
 
115
- ```text
116
- Current: tdd (standard)
117
- Blocked by: NO_SOURCE_CONTEXT
118
- Next: cclaw internal rewind plan "add bootstrap slice", then /cc
119
- Evidence needed: fresh RED/GREEN/REFACTOR slice and verification output
120
- ```
209
+ For ≤4 AC the orchestrator picks `inline` even when AC look "parallelSafe". Dispatch overhead is not worth saving 1-2 AC of wall-clock.
121
210
 
122
- Common exits:
211
+ ## When sub-agents help (and when they don't)
123
212
 
213
+ Use a sub-agent for:
124
214
 
125
- | Situation | Next action |
126
- | ------------------------------------------------- | ------------------------------------------------------------------------------------ |
127
- | Missing gates | Run `/cc`, finish the stage, then complete with evidence. |
128
- | Mandatory delegation missing evidence | Dispatch the worker/overseer or waive explicitly with rationale. |
129
- | `NO_SOURCE_CONTEXT` or `NO_TEST_SURFACE` | Rewind to `plan`/`spec`, define the source or test surface, then resume TDD. |
130
- | `NO_IMPLEMENTABLE_SLICE` or `RED_NOT_EXPRESSIBLE` | Rework `design`/`spec`/`plan` until one vertical slice is testable. |
131
- | `NO_VCS_MODE` | Restore git, set `vcs: none` with hash evidence, or configure `tdd.verificationRef`. |
132
- | Review blocked | `cclaw internal rewind tdd "review_blocked_by_critical <finding-ids>"`. |
133
- | Stale stage after rewind | Redo the marked stage, then `cclaw internal rewind --ack <stage>`. |
134
- | Broken hooks or generated files | `npx cclaw-cli sync`, then follow the fail-fast error guidance if it still fails. |
215
+ - **Parallel slice dispatch** during `parallel-build` (cap: 5).
216
+ - **Specialist context isolation** for `architect`, `security-reviewer`, integration `reviewer` when the harness supports it. A fresh sub-agent reads a small focused filebag instead of the orchestrator's full history.
135
217
 
218
+ Don't use a sub-agent for:
136
219
 
137
- ## Subagents Without Theater
220
+ - Trivial / small / medium slugs (≤4 AC). Run inline.
221
+ - Sequential work that doesn't actually parallelize.
222
+ - Routine work the orchestrator can finish in 1-2 turns.
138
223
 
139
- ```text
140
- user goal
141
- |
142
- v
143
- controller ---------------> worker: bounded implementation/test/doc task
144
- | |
145
- | v
146
- +----------------------> overseer: read-only validation
147
- |
148
- v
149
- evidence refs + terminal status
150
- |
151
- v
152
- .cclaw/state/delegation-log.json
153
- ```
224
+ ## Five Failure Modes + review Ralph loop
154
225
 
155
- The controller owns `flow-state.json`, sequencing, synthesis, and the final answer. Workers own scoped work. Overseers verify. A waiver means the work was **not** done by a real worker and must say why proceeding is acceptable.
226
+ Reviews check the Five Failure Modes — hallucinated actions, scope creep, cascading errors, context loss, tool misuse every iteration. The Five Failure Modes pass is wrapped by the `review-loop` auto-trigger skill so the agent cannot skip it.
156
227
 
157
- ## What Is Enforced
228
+ Reviews are not single-shot. They are a Ralph loop with an explicit ledger:
158
229
 
159
- Enforced by generated helpers and state checks:
230
+ 1. Iteration 1 lists every finding as F-1, F-2, … in an append-only **Concern Ledger** at the top of `flows/<slug>/review.md`. Each row carries severity (`block` / `warn`), status (`open` / `closed` / `superseded`), and a `file:line` citation.
231
+ 2. Iteration N+1 must reread every open row, mark it `closed | open | superseded by F-K`, and append new findings as F-(max+1). It cannot delete or rewrite earlier rows.
232
+ 3. The loop ends when (a) every row is `closed`, (b) two consecutive iterations record zero new `block` findings AND every open row is `warn`, or (c) the 5-iteration hard cap fires with at least one open block row — at which point `/cc` stops and reports instead of looping forever.
160
233
 
161
- - Stage completion goes through `node .cclaw/hooks/stage-complete.mjs <stage>`.
162
- - Required gates need evidence before advancement.
163
- - Mandatory delegations need terminal evidence or explicit waiver.
164
- - Stale stages block until redone and acknowledged.
165
- - Review criticals route back to TDD.
166
- - Ship continues through `post_ship_review -> archive` with `closeout.shipSubstate`.
234
+ A typical run converges in 1-3 iterations. The hard cap is a circuit breaker, not a target.
167
235
 
168
- Advisory/model-guided:
236
+ ## Conversation language
169
237
 
170
- - Initial track heuristic wording.
171
- - Proactive subagents that are not mandatory for the active stage/tier.
172
- - Reference patterns that shape prompts but do not add runtime states.
238
+ cclaw replies in the user's language for prose. It NEVER translates wire-protocol identifiers slugs, `AC-N`, `D-N`, `F-N`, frontmatter keys, file paths, hook output, specialist names, or commit tags. This is enforced by the always-on `conversation-language` skill so a Russian-speaking user, for example, gets Russian explanations but still sees `flow-state.json` and `AC-1` verbatim.
173
239
 
174
- ## The Deeper Contract
240
+ ## Hooks (default profile: minimal)
175
241
 
176
- The README is the front door. The full operating contract lives here:
242
+ Three hooks ship by default and only `commit-helper.mjs` is mandatory:
177
243
 
178
- - [Scheme of Work](./docs/scheme-of-work.md): stages, gates, recovery, closeout, state files.
179
- - [Configuration](./docs/config.md): strictness, tracks, TDD, compound, language packs, hooks.
180
- - [Harnesses](./docs/harnesses.md): Claude, Cursor, OpenCode, Codex capabilities and fallbacks.
181
- - [Generated Agent Block Example](./docs/agents-block.example.md): what gets injected into harness guidance.
244
+ - `session-start.mjs` rehydrates flow state and prints active slug
245
+ - `stop-handoff.mjs` short reminder when stopping mid-flow
246
+ - `commit-helper.mjs` atomic commit per AC + traceability check
182
247
 
183
- ## CLI Reference
248
+ ## CLI commands
184
249
 
185
250
  ```bash
186
- npx cclaw-cli # interactive setup or installed status hint
187
- npx cclaw-cli init --harnesses=<list> --no-interactive
188
- npx cclaw-cli sync # regenerate managed runtime files
189
- npx cclaw-cli upgrade # refresh generated files while preserving config
190
- npx cclaw-cli archive # explicit archive/reset; normal closeout uses /cc
191
- npx cclaw-cli uninstall # remove .cclaw and generated harness shims
192
- npx cclaw-cli --version
251
+ cclaw init # install assets in the current project
252
+ cclaw sync # reapply assets to match the current code
253
+ cclaw upgrade # sync after upgrading the npm package
254
+ cclaw uninstall # remove cclaw assets from the project
255
+ cclaw version # print version
256
+ cclaw help # short help
193
257
  ```
194
258
 
259
+ Flow-control commands (`plan`, `status`, `ship`, `migrate`, `build`, `review`) are intentionally **not** part of the CLI. They live as `/cc` instructions inside the harness.
260
+
261
+ ## More docs
262
+
263
+ - [docs/v8-vision.md](docs/v8-vision.md) — locked decisions, full kill-list, references review
264
+ - [docs/scheme-of-work.md](docs/scheme-of-work.md) — flow walk-through with all checkpoints
265
+ - [docs/skills.md](docs/skills.md) — six auto-trigger skills and what they enforce
266
+ - [docs/config.md](docs/config.md) — `.cclaw/config.yaml` reference
267
+ - [docs/harnesses.md](docs/harnesses.md) — what each harness installs
268
+ - [docs/quality-gates.md](docs/quality-gates.md) — AC traceability + Five Failure Modes
269
+ - [docs/migration-v7-to-v8.md](docs/migration-v7-to-v8.md) — from cclaw 7.x
270
+
195
271
  ## License
196
272
 
197
- [MIT](./LICENSE)
273
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,51 @@
1
+ import type { AcceptanceCriterionState, FlowStage, DiscoverySpecialistId, ArtifactStatus } from "./types.js";
2
+ export interface ArtifactFrontmatter {
3
+ slug: string;
4
+ stage: FlowStage | "shipped" | "cancelled";
5
+ status: ArtifactStatus | "cancelled";
6
+ ac?: AcceptanceCriterionState[];
7
+ last_specialist?: DiscoverySpecialistId | null;
8
+ refines?: string | null;
9
+ shipped_at?: string | null;
10
+ ship_commit?: string | null;
11
+ review_iterations?: number;
12
+ security_flag?: boolean;
13
+ [key: string]: unknown;
14
+ }
15
+ export interface ParsedArtifact {
16
+ frontmatter: ArtifactFrontmatter;
17
+ body: string;
18
+ raw: string;
19
+ }
20
+ export declare class FrontmatterError extends Error {
21
+ readonly path?: string | undefined;
22
+ constructor(message: string, path?: string | undefined);
23
+ }
24
+ export declare function parseArtifact(raw: string, sourcePath?: string): ParsedArtifact;
25
+ export declare function renderArtifact(parsed: ParsedArtifact): string;
26
+ export declare function readArtifact(filePath: string): Promise<ParsedArtifact>;
27
+ export declare function writeArtifact(filePath: string, parsed: ParsedArtifact): Promise<void>;
28
+ export declare function extractAcceptanceCriteriaFromBody(body: string): Array<{
29
+ id: string;
30
+ text: string;
31
+ commit?: string;
32
+ status: AcceptanceCriterionState["status"];
33
+ }>;
34
+ export declare function mergeAcceptanceCriteria(fromBody: Array<{
35
+ id: string;
36
+ text: string;
37
+ commit?: string;
38
+ status: AcceptanceCriterionState["status"];
39
+ }>, fromFrontmatter: AcceptanceCriterionState[] | undefined): AcceptanceCriterionState[];
40
+ export interface SyncFrontmatterPatch {
41
+ ac?: AcceptanceCriterionState[];
42
+ last_specialist?: ArtifactFrontmatter["last_specialist"];
43
+ review_iterations?: number;
44
+ security_flag?: boolean;
45
+ shipped_at?: string | null;
46
+ ship_commit?: string | null;
47
+ refines?: string | null;
48
+ }
49
+ export declare function syncFrontmatter(projectRoot: string, slug: string, stage: FlowStage, patch: SyncFrontmatterPatch): Promise<ParsedArtifact>;
50
+ export declare function isFrontmatterCancelled(frontmatter: ArtifactFrontmatter): boolean;
51
+ export declare function isFrontmatterShipped(frontmatter: ArtifactFrontmatter): boolean;
@@ -0,0 +1,131 @@
1
+ import fs from "node:fs/promises";
2
+ import YAML from "yaml";
3
+ import { activeArtifactPath } from "./artifact-paths.js";
4
+ import { exists, writeFileSafe } from "./fs-utils.js";
5
+ const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/u;
6
+ const AC_LINE_RE = /^[\s>*+-]*\*{0,2}\s*(AC-\d+)\s*[:\-—)]\s*(.+?)\s*$/iu;
7
+ const AC_COMMIT_RE = /\(?(commit\s*[:=]?\s*([0-9a-f]{7,40})|sha\s*[:=]?\s*([0-9a-f]{7,40})|@([0-9a-f]{7,40}))\)?/iu;
8
+ const AC_PENDING_RE = /\(commit\s*[:=]?\s*pending\)/iu;
9
+ export class FrontmatterError extends Error {
10
+ path;
11
+ constructor(message, path) {
12
+ super(message);
13
+ this.path = path;
14
+ this.name = "FrontmatterError";
15
+ }
16
+ }
17
+ export function parseArtifact(raw, sourcePath) {
18
+ const trimmed = raw.replace(/^\uFEFF/u, "");
19
+ const match = FRONTMATTER_RE.exec(trimmed);
20
+ if (!match) {
21
+ throw new FrontmatterError(`Artifact is missing the required YAML frontmatter block (---).${sourcePath ? ` (${sourcePath})` : ""}`, sourcePath);
22
+ }
23
+ const yamlBody = match[1] ?? "";
24
+ const body = match[2] ?? "";
25
+ let parsed;
26
+ try {
27
+ parsed = YAML.parse(yamlBody);
28
+ }
29
+ catch (err) {
30
+ throw new FrontmatterError(`Invalid YAML frontmatter: ${err.message}`, sourcePath);
31
+ }
32
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
33
+ throw new FrontmatterError("Frontmatter must be a YAML object.", sourcePath);
34
+ }
35
+ const frontmatter = parsed;
36
+ if (typeof frontmatter.slug !== "string" || frontmatter.slug.length === 0) {
37
+ throw new FrontmatterError("Frontmatter must declare a non-empty `slug`.", sourcePath);
38
+ }
39
+ if (typeof frontmatter.stage !== "string") {
40
+ throw new FrontmatterError("Frontmatter must declare a `stage` (plan/build/review/ship/shipped/cancelled).", sourcePath);
41
+ }
42
+ if (typeof frontmatter.status !== "string") {
43
+ throw new FrontmatterError("Frontmatter must declare a `status` (active/shipped/cancelled).", sourcePath);
44
+ }
45
+ if (frontmatter.ac !== undefined && !Array.isArray(frontmatter.ac)) {
46
+ throw new FrontmatterError("Frontmatter `ac` must be an array.", sourcePath);
47
+ }
48
+ return { frontmatter, body, raw };
49
+ }
50
+ export function renderArtifact(parsed) {
51
+ const yaml = YAML.stringify(parsed.frontmatter, { indent: 2 }).trim();
52
+ const body = parsed.body.startsWith("\n") ? parsed.body : `\n${parsed.body}`;
53
+ return `---\n${yaml}\n---\n${body.replace(/^\n/u, "")}\n`;
54
+ }
55
+ export async function readArtifact(filePath) {
56
+ const raw = await fs.readFile(filePath, "utf8");
57
+ return parseArtifact(raw, filePath);
58
+ }
59
+ export async function writeArtifact(filePath, parsed) {
60
+ await writeFileSafe(filePath, renderArtifact(parsed));
61
+ }
62
+ export function extractAcceptanceCriteriaFromBody(body) {
63
+ const results = [];
64
+ const seen = new Set();
65
+ for (const rawLine of body.split(/\r?\n/u)) {
66
+ const line = rawLine.replace(/<[^>]+>/gu, "").trim();
67
+ const match = AC_LINE_RE.exec(line);
68
+ if (!match)
69
+ continue;
70
+ const id = match[1].toUpperCase();
71
+ if (seen.has(id))
72
+ continue;
73
+ seen.add(id);
74
+ let text = match[2].trim();
75
+ let commit;
76
+ let status = "pending";
77
+ const commitMatch = AC_COMMIT_RE.exec(text);
78
+ if (commitMatch && !AC_PENDING_RE.test(text)) {
79
+ commit = commitMatch[2] ?? commitMatch[3] ?? commitMatch[4];
80
+ if (commit)
81
+ status = "committed";
82
+ }
83
+ text = text.replace(AC_COMMIT_RE, "").replace(AC_PENDING_RE, "").replace(/\s{2,}/gu, " ").replace(/[\s\-:—]+$/u, "").trim();
84
+ results.push({ id, text, commit, status });
85
+ }
86
+ return results;
87
+ }
88
+ export function mergeAcceptanceCriteria(fromBody, fromFrontmatter) {
89
+ const fmIndex = new Map();
90
+ for (const ac of fromFrontmatter ?? [])
91
+ fmIndex.set(ac.id, ac);
92
+ const merged = [];
93
+ for (const item of fromBody) {
94
+ const fm = fmIndex.get(item.id);
95
+ const commit = item.commit ?? fm?.commit;
96
+ const status = commit ? "committed" : (fm?.status ?? "pending");
97
+ merged.push({
98
+ id: item.id,
99
+ text: item.text || fm?.text || item.id,
100
+ commit,
101
+ status
102
+ });
103
+ }
104
+ for (const [id, ac] of fmIndex) {
105
+ if (!merged.some((entry) => entry.id === id))
106
+ merged.push(ac);
107
+ }
108
+ return merged;
109
+ }
110
+ export async function syncFrontmatter(projectRoot, slug, stage, patch) {
111
+ const filePath = activeArtifactPath(projectRoot, stage, slug);
112
+ if (!(await exists(filePath))) {
113
+ throw new FrontmatterError(`Artifact flows/${slug}/${stage}.md not found.`, filePath);
114
+ }
115
+ const parsed = await readArtifact(filePath);
116
+ const next = { ...parsed.frontmatter };
117
+ for (const [key, value] of Object.entries(patch)) {
118
+ if (value === undefined)
119
+ continue;
120
+ next[key] = value;
121
+ }
122
+ const updated = { ...parsed, frontmatter: next };
123
+ await writeArtifact(filePath, updated);
124
+ return updated;
125
+ }
126
+ export function isFrontmatterCancelled(frontmatter) {
127
+ return frontmatter.status === "cancelled" || frontmatter.stage === "cancelled";
128
+ }
129
+ export function isFrontmatterShipped(frontmatter) {
130
+ return frontmatter.status === "shipped" || frontmatter.stage === "shipped";
131
+ }
@@ -1,28 +1,8 @@
1
- import type { FlowStage, FlowTrack } from "./types.js";
2
- export type ArtifactPathIntent = "read" | "write";
3
- export interface ResolveArtifactPathContext {
4
- projectRoot: string;
5
- track?: FlowTrack;
6
- /**
7
- * Optional brainstorm topic used for `<slug>` interpolation.
8
- * When omitted, the resolver attempts to infer it from `00-idea.md`.
9
- */
10
- topic?: string;
11
- /**
12
- * - read: locate an existing artifact first (new slug shape, then legacy fallback).
13
- * - write: return a non-colliding writable path for a new artifact.
14
- */
15
- intent?: ArtifactPathIntent;
16
- }
17
- export interface ResolvedArtifactPath {
18
- stage: FlowStage;
19
- fileName: string;
20
- relPath: string;
21
- absPath: string;
22
- source: "existing" | "generated";
23
- legacy: boolean;
24
- }
25
- export declare function isSlugArtifactPattern(filePattern: string): boolean;
26
- export declare function legacyArtifactFileName(filePattern: string): string;
1
+ import type { FlowStage } from "./types.js";
2
+ export type ArtifactStage = FlowStage | "decisions" | "learnings";
3
+ export declare const ARTIFACT_FILE_NAMES: Record<ArtifactStage, string>;
27
4
  export declare function slugifyArtifactTopic(topic: string): string;
28
- export declare function resolveArtifactPath(stage: FlowStage, context: ResolveArtifactPathContext): Promise<ResolvedArtifactPath>;
5
+ export declare function activeArtifactDir(projectRoot: string, slug: string): string;
6
+ export declare function activeArtifactPath(projectRoot: string, stage: ArtifactStage, slug: string): string;
7
+ export declare function shippedArtifactDir(projectRoot: string, slug: string): string;
8
+ export declare function shippedArtifactPath(projectRoot: string, slug: string, stage: ArtifactStage): string;