cclaw-cli 6.10.0 → 6.12.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.
@@ -42,15 +42,15 @@ export const TDD = {
42
42
  "Discover the test surface — inspect existing tests, fixtures, helpers, test commands, and nearby assertions before authoring RED. Reuse the local test style unless the slice genuinely needs a new pattern.",
43
43
  "Run a system-wide impact check — name callbacks, state transitions, interfaces, schemas, CLI/config/API contracts, persistence, or event boundaries that this slice can affect. Add RED coverage for each affected public contract or record why it is out of scope.",
44
44
  "Source/test preflight — before production edits, classify planned paths using test-path patterns; verify the RED touches a test path and the GREEN touches only source paths needed for the failing behavior.",
45
- "Use the mandatory `test-author` delegation for RED — after discovery and impact check, produce failing behavior tests and RED evidence only (no production edits). Set `CCLAW_ACTIVE_AGENT=tdd-red` when the harness supports phase labels.",
46
- "RED: Capture failure output copy the exact failure output as RED evidence. Record the slice in `.cclaw/artifacts/06-tdd-slices.jsonl` via `cclaw-cli internal tdd-slice-record --slice <id> --status red --test-file <path> --command <cmd> --paths <comma-separated>` (the markdown `Watched-RED Proof` table is now auto-derived from this sidecar).",
47
- "Continue the same `test-author` delegation intent for GREEN minimal implementation plus full-suite GREEN evidence. Set `CCLAW_ACTIVE_AGENT=tdd-green` when the harness supports phase labels.",
45
+ "Use the mandatory `test-author` delegation for RED — after discovery and impact check, dispatch with `--slice S-<id> --phase red`. Produce failing behavior tests only (no production edits) and let the harness record the dispatch via the generated `delegation-record` hook. Set `CCLAW_ACTIVE_AGENT=tdd-red` when the harness supports phase labels.",
46
+ "RED: do NOT hand-edit `## Watched-RED Proof`, `## Vertical Slice Cycle`, or `## RED Evidence` markdown tables. The linter auto-renders them from `delegation-events.jsonl` slice phase rows; manual edits inside the auto-render markers are overwritten on the next lint.",
47
+ "Dispatch the `slice-implementer` for GREEN with `--slice S-<id> --phase green` and explicit `--paths` so the file-overlap scheduler can auto-allow parallel slices. Attach an evidence ref (test path, span ref, or pasted-output pointer) so the Vertical Slice Cycle row is well-formed. Set `CCLAW_ACTIVE_AGENT=tdd-green` when the harness supports phase labels.",
48
48
  "GREEN: Run full suite — execute ALL tests, not just the ones you wrote. The full suite must be GREEN.",
49
49
  "GREEN: Verify no regressions — if any existing test breaks, fix the regression before proceeding.",
50
50
  "Run verification-before-completion discipline for the slice — capture a fresh test command, explicit PASS/FAIL status, and a config-aware ref (commit SHA when VCS is present/required, or no-vcs attestation when allowed).",
51
- "GREEN: append a `green` row to `.cclaw/artifacts/06-tdd-slices.jsonl` via `cclaw-cli internal tdd-slice-record --slice <id> --status green [--green-output-ref <path|spanId:...>]` so the Vertical Slice Cycle linter validates the sidecar instead of a hand-edited table.",
52
- "REFACTOR: continue the `test-author` evidence cycle (or a dedicated refactor mode when available) to improve code quality without behavior changes, then record `--status refactor-done` (or `--status refactor-deferred --refactor-rationale \"<why>\"`) via the same `tdd-slice-record` CLI. Set `CCLAW_ACTIVE_AGENT=tdd-refactor` when the harness supports phase labels.",
53
- "Record evidence capture test discovery, system-wide impact check, RED failure, GREEN output, and REFACTOR notes in the TDD artifact. When logging a `green` row, attach the closed acceptance-criterion IDs in `acIds` so Ralph Loop status counts them.",
51
+ "REFACTOR: re-dispatch the `slice-implementer` (or `test-author`) with `--phase refactor` once GREEN holds, OR `--phase refactor-deferred --refactor-rationale \"<why>\"` to close the slice without a refactor pass. Both options are recorded as a delegation event; the linter accepts either as REFACTOR coverage. Set `CCLAW_ACTIVE_AGENT=tdd-refactor` when the harness supports phase labels.",
52
+ "DOC (parallel, mandatory v6.12.0): dispatch `slice-documenter --slice S-<id> --phase doc --paths <artifacts-dir>/tdd-slices/S-<id>.md` IN PARALLEL with `slice-implementer --phase green` for the same slice ONE message with TWO concurrent Task calls. The documenter only writes `tdd-slices/S-<id>.md`, so its `--paths` are disjoint from the implementer's production code and the file-overlap scheduler auto-allows the parallel dispatch. Linter rule `tdd_slice_documenter_missing` blocks the gate when the `phase=doc` event is absent (regardless of `discoveryMode`).",
53
+ "**slice-documenter writes per-slice prose** (test discovery, system-wide impact check, RED/GREEN/REFACTOR notes, acceptance mapping, failure analysis) into `tdd-slices/S-<id>.md`. Controller does NOT touch this content. When logging a `green` row, attach the closed acceptance-criterion IDs in `acIds` so Ralph Loop status counts them.",
54
54
  "Annotate traceability — link to the active track's source: plan task ID + spec criterion on standard/medium, or spec acceptance item / bug reproduction slice on quick.",
55
55
  "**Boundary with review (do NOT escalate single-slice findings to whole-diff review).** `tdd.Per-Slice Review` OWNS severity-classified findings WITHIN one slice (correctness, edge cases, regression). `review` OWNS whole-diff Layer 1 (spec compliance) plus Layer 2 (cross-slice integration, security sweep, dependency/version audit, observability). When a single-slice finding genuinely needs whole-diff escalation, surface it in `06-tdd.md > Per-Slice Review` first; review will cite it (not re-classify) and the cross-artifact-duplication linter requires matching severity/disposition.",
56
56
  "Per-Slice Review (conditional) — if the slice meets any trigger (touchCount >= filesChangedThreshold, touchPaths match touchTriggers, or highRisk=true), append a `## Per-Slice Review` entry for this slice before moving on (see the dedicated section below).",
@@ -58,10 +58,11 @@ export const TDD = {
58
58
  ],
59
59
  interactionProtocol: [
60
60
  "Pick one vertical slice at a time: source item, RED test, GREEN implementation, REFACTOR, and verification evidence move together.",
61
- "Slice implementers are sequential by default. Parallel implementers are allowed only when (a) lanes touch non-overlapping files, (b) the controller passes `--allow-parallel` on each ledger row, and (c) an `integration-overseer` is dispatched after the parallel lanes and writes cohesion-evidence into the artifact before the gate is marked passed.",
62
- "Controller owns orchestration; one mandatory `test-author` delegation carries phase-specific RED -> GREEN -> REFACTOR evidence instead of spawning separate workers by default.",
61
+ "Slice implementers are sequential by default. Parallel implementers are allowed only when (a) lanes touch non-overlapping files (the file-overlap scheduler auto-allows parallel when `--paths` are disjoint), and (b) an `integration-overseer` is dispatched after the parallel lanes and writes cohesion-evidence into the artifact before the gate is marked passed.",
62
+ "Controller owns orchestration. For each slice S-<id>, dispatch in this order: (1) `test-author --slice S-<id> --phase red` (RED-only, no production edits), (2) `slice-implementer --slice S-<id> --phase green --paths <comma-separated>` for GREEN, (3) re-dispatch `--phase refactor` or `--phase refactor-deferred --refactor-rationale \"<why>\"` to close REFACTOR. Each dispatch records a row in `delegation-events.jsonl` and the linter auto-derives the Watched-RED + Vertical Slice Cycle tables from those rows. Do NOT hand-edit those tables.",
63
63
  "Before writing RED tests, discover relevant existing tests and commands so the new test extends the suite instead of fighting it.",
64
64
  "Before implementation, perform a system-wide impact check across callbacks, state, interfaces, schemas, and external contracts touched by the slice.",
65
+ "Slice-documenter (mandatory v6.12.0, regardless of `discoveryMode`): in PARALLEL with `slice-implementer --phase green`, dispatch `slice-documenter --slice S-<id> --phase doc` whose only `claimedPaths` is `<artifacts-dir>/tdd-slices/S-<id>.md`. The two dispatches run concurrently because their paths are disjoint. The documenter writes per-slice prose so the main `06-tdd.md` stays thin. Controller MUST NOT author per-slice prose; controller MUST NOT author GREEN production code (use `slice-implementer`).",
65
66
  "Run source/test preflight using configured TDD path patterns where feasible; if path classification is impossible (generated files, non-file side effect), record why.",
66
67
  "Write behavior-focused tests before changing implementation (RED).",
67
68
  "Capture and store failing output as RED evidence.",
@@ -104,16 +105,16 @@ export const TDD = {
104
105
  { id: "tdd_docs_drift_check", description: "When public API/config/CLI surfaces change, docs drift is addressed via a completed doc-updater pass." }
105
106
  ],
106
107
  requiredEvidence: [
107
- "Artifact updated at `.cclaw/artifacts/06-tdd.md` with Test Discovery, System-Wide Impact Check, RED, GREEN, and REFACTOR sections.",
108
+ "Artifact updated at `.cclaw/artifacts/06-tdd.md` with System-Wide Impact Check, Acceptance & Failure Map, REFACTOR Notes, Iron Law Acknowledgement, Verification Ladder, and Learnings.",
108
109
  "Relevant existing test files, helpers, fixtures, and exact commands identified before RED.",
109
110
  "Callbacks, state transitions, interfaces, schemas, and contracts checked for impact before implementation.",
110
111
  "Execution posture and vertical-slice RED/GREEN/REFACTOR checkpoint plan recorded, including commit boundaries when the repo workflow supports them.",
111
- "Failing command output captured (RED).",
112
- "Full test/build output recorded (GREEN).",
112
+ "RED observability: a `phase=red` event in `delegation-events.jsonl` for each slice with non-empty evidenceRefs (test path, span ref, or pasted-output pointer). Slices created **before the v6.12.0 cutover marker** in `flow-state.json::tddCutoverSliceId` may retain legacy `## Watched-RED Proof` / `## RED Evidence` markdown tables; slices created **after the cutover marker** MUST use phase events + slice-documenter doc, and legacy table writes are surfaced by the advisory `tdd_legacy_section_writes_after_cutover` rule.",
113
+ "GREEN observability: a `phase=green` event in `delegation-events.jsonl` per slice whose `completedTs` >= the matching `phase=red` `completedTs`, authored by `slice-implementer` (linter rule `tdd_slice_implementer_missing` blocks the gate otherwise), and whose evidenceRefs name the failing-now-passing test. Pre-cutover slices may keep legacy `## GREEN Evidence` markdown.",
114
+ "REFACTOR observability: per slice, a `phase=refactor` event OR a `phase=refactor-deferred` event whose evidenceRefs / refactor rationale captures why refactor was deferred.",
115
+ "Per slice, a `phase=doc` event from `slice-documenter` whose evidenceRefs name `<artifacts-dir>/tdd-slices/S-<id>.md`. Mandatory regardless of `discoveryMode` (v6.12.0 Phase R). Linter rule `tdd_slice_documenter_missing` blocks the gate when missing.",
113
116
  "Fresh verification evidence recorded with command, PASS/FAIL status, and commit SHA or no-VCS reason plus content/artifact hash before completion.",
114
117
  "Iron Law Acknowledgement section explicitly states `Acknowledged: yes`.",
115
- "Watched-RED Proof includes at least one populated row with an ISO timestamp.",
116
- "Vertical Slice Cycle records RED, GREEN, and REFACTOR per active slice.",
117
118
  "Acceptance mapping documented.",
118
119
  "Failure reason analysis recorded.",
119
120
  "Refactor rationale captured.",
@@ -156,16 +157,16 @@ export const TDD = {
156
157
  },
157
158
  artifactValidation: [
158
159
  { section: "Upstream Handoff", required: false, validationRule: "Summarizes plan/spec/design decisions, constraints, open questions, and explicit drift before RED work." },
159
- { section: "Test Discovery", required: true, validationRule: "Before RED: lists existing tests, fixtures/helpers, exact commands, and the chosen local pattern to extend." },
160
+ { section: "Test Discovery", required: false, validationRule: "Overall narrative for how the stage discovered the existing test surface. Per-slice details live under `tdd-slices/S-<id>.md` from v6.11.0; the `## Test Discovery` heading is optional/advisory." },
160
161
  { section: "System-Wide Impact Check", required: true, validationRule: "Before implementation: names affected callbacks, state transitions, interfaces, schemas, public APIs/config/CLI, persistence, or event contracts, with coverage or explicit out-of-scope notes." },
161
- { section: "RED Evidence", required: true, validationRule: "Failing test output captured per slice." },
162
- { section: "Acceptance & Failure Map", required: false, validationRule: "Each slice row carries Source ID, AC ID, expected behavior, and a RED-link (delegation spanId, evidence path, or sidecar redOutputRef)." },
163
- { section: "GREEN Evidence", required: true, validationRule: "Full suite pass output captured." },
162
+ { section: "RED Evidence", required: true, validationRule: "Failing test output per slice. From v6.11.0 this section is auto-satisfied by a `phase=red` event in `delegation-events.jsonl` with non-empty evidenceRefs; the markdown block remains required as a legacy fallback when phase events are absent." },
163
+ { section: "Acceptance & Failure Map", required: false, validationRule: "Each slice row carries Source ID, AC ID, expected behavior, and a RED-link (delegation spanId or evidence path). From v6.11.0 the column is auto-derivable from `phase=red` events." },
164
+ { section: "GREEN Evidence", required: true, validationRule: "Full suite pass output. From v6.11.0 this section is auto-satisfied by a `phase=green` event in `delegation-events.jsonl` with non-empty evidenceRefs; the markdown block remains required as a legacy fallback when phase events are absent." },
164
165
  { section: "REFACTOR Notes", required: true, validationRule: "What changed, why, behavior preservation confirmed." },
165
166
  { section: "Traceability", required: true, validationRule: "Plan task ID and spec criterion linked." },
166
167
  { section: "Iron Law Acknowledgement", required: true, validationRule: "Must include `Acknowledged: yes` and list exceptions (or `None`)." },
167
- { section: "Watched-RED Proof", required: true, validationRule: "At least one populated row with ISO timestamp proving RED was observed before production edits." },
168
- { section: "Vertical Slice Cycle", required: true, validationRule: "Per active slice records RED, GREEN, and REFACTOR timestamps (refactor may be deferred only with explicit rationale)." },
168
+ { section: "Watched-RED Proof", required: false, validationRule: "From v6.11.0 the Watched-RED summary is auto-rendered from `delegation-events.jsonl` slice phase events (see auto-start: tdd-slice-summary marker). Legacy markdown tables continue to validate via the fallback path." },
169
+ { section: "Vertical Slice Cycle", required: false, validationRule: "From v6.11.0 the Vertical Slice Cycle table is auto-rendered between `auto-start: tdd-slice-summary` markers. Legacy markdown tables continue to validate via the fallback path." },
169
170
  { section: "Verification Ladder", required: true, validationRule: "Per-slice verification tier (static, command, behavioral, human) with evidence captured for the highest tier reached this turn. Must include command + PASS/FAIL + commit SHA when VCS is present, or explicit no-vcs reason plus content/artifact hash/config override." },
170
171
  { section: "TDD Blocker Taxonomy", required: false, validationRule: "When blocked, classify as NO_SOURCE_CONTEXT, NO_TEST_SURFACE, NO_IMPLEMENTABLE_SLICE, RED_NOT_EXPRESSIBLE, or NO_VCS_MODE; include blockedBecause, missingInputs, recommendedRoute, nextCommand, and resumeCriteria." },
171
172
  { section: "Coverage Targets", required: false, validationRule: "If present: per-module or per-code-type coverage thresholds with current values and measurement commands." },
@@ -304,7 +305,7 @@ function tddStageVariantForTrack(track) {
304
305
  return {
305
306
  ...row,
306
307
  required: true,
307
- validationRule: "Each slice row carries Source ID, AC ID (spec acceptance criterion ID, for example AC-1), expected behavior, and a RED-link (delegation spanId, evidence path, or sidecar redOutputRef)."
308
+ validationRule: "Each slice row carries Source ID, AC ID (spec acceptance criterion ID, for example AC-1), expected behavior, and a RED-link (delegation spanId or evidence path). From v6.11.0 a `phase=red` event in `delegation-events.jsonl` with non-empty evidenceRefs satisfies the row."
308
309
  };
309
310
  }
310
311
  if (row.section === "Traceability") {
@@ -676,7 +676,7 @@ function sliceImplementerEnhancedBody() {
676
676
  ${MARKDOWN_CODE_FENCE}
677
677
  You are a slice-implementer subagent.
678
678
 
679
- SLICE: {single vertical slice}
679
+ SLICE: {single vertical slice — controller MUST dispatch you with --slice S-<id> --phase green --paths <comma-separated>}
680
680
  RED_EVIDENCE: {failing test and expected failure}
681
681
  ALLOWED_FILES: {explicit file boundaries — surfaced to scheduler as Files: <paths>}
682
682
  FORBIDDEN_CHANGES: {scope/compatibility limits}
@@ -687,11 +687,11 @@ Rules:
687
687
  - Keep REFACTOR behavior-preserving.
688
688
  - Return the strict worker JSON schema first.
689
689
 
690
- Slice ledger contract (v6.10.0):
691
- - After observing the failing test, run \`cclaw-cli internal tdd-slice-record --slice <id> --status red --test-file <path> --command <cmd> --paths <comma-separated> [--ac <id>] [--plan-unit <id>]\`. The command appends to \`.cclaw/artifacts/06-tdd-slices.jsonl\`.
692
- - After the same test passes, run \`cclaw-cli internal tdd-slice-record --slice <id> --status green [--green-output-ref <path|spanId:...>]\`.
693
- - After REFACTOR, run \`cclaw-cli internal tdd-slice-record --slice <id> --status refactor-done\` or \`--status refactor-deferred --refactor-rationale "<why>"\`.
694
- - Do NOT hand-edit the Watched-RED Proof or Vertical Slice Cycle markdown tables; the linter reads the JSONL sidecar when present and the markdown becomes an auto-derived view.
690
+ Slice phase-event contract (v6.11.0):
691
+ - Do NOT hand-edit \`## Watched-RED Proof\`, \`## Vertical Slice Cycle\`, \`## RED Evidence\`, or \`## GREEN Evidence\` markdown tables in 06-tdd.md. The linter auto-renders them between \`<!-- auto-start: tdd-slice-summary -->\` markers from \`delegation-events.jsonl\` slice phase rows.
692
+ - Your dispatch row IS the evidence: the harness-generated delegation-record hook stamps \`sliceId=S-<id>\`, \`phase=green\`, and \`completedTs\` automatically. Attach evidenceRefs (test path, span ref, or pasted-output pointer) so the linter validates the row.
693
+ - After REFACTOR, ask the controller to re-dispatch you with \`--phase refactor\` (or \`--phase refactor-deferred --refactor-rationale "<why>"\`); each call appends a new ledger row.
694
+ - Per-slice prose summary lives in \`<artifacts-dir>/tdd-slices/S-<id>.md\` and is owned by the parallel \`slice-documenter\` (or the controller). You do NOT touch that file.
695
695
  ${MARKDOWN_CODE_FENCE}
696
696
 
697
697
  `;
@@ -935,14 +935,15 @@ FIXTURES / PATTERNS: {links to helper modules by path + naming conventions}
935
935
 
936
936
  Process (mandatory):
937
937
  1) If STAGE_MODE=TEST_RED_ONLY:
938
- - RED only add failing tests proving the gap (show failing output excerpt).
938
+ - Controller dispatched you with \`--slice S-<id> --phase red\`. Add failing tests proving the gap (show failing output excerpt).
939
939
  - Do NOT edit production code.
940
- - Append the slice to the sidecar via \`cclaw-cli internal tdd-slice-record --slice <id> --status red --test-file <path> --command <cmd> --paths <comma-separated>\` instead of editing the Watched-RED Proof markdown table.
940
+ - Do NOT hand-edit \`## Watched-RED Proof\` / \`## RED Evidence\` markdown tables in 06-tdd.md the linter auto-renders them from your dispatch row in \`delegation-events.jsonl\`. Just ensure your worker return includes evidenceRefs (test path, span ref, or pasted-output pointer) so the harness can stamp them on the ledger row.
941
941
  - Report: TESTS_ADDED, RED_COMMAND_RUN, RED_EVIDENCE, STATUS: DONE|BLOCKED.
942
942
  2) If STAGE_MODE=BUILD_GREEN_REFACTOR:
943
+ - Controller dispatched you with \`--slice S-<id> --phase green\` (and later \`--phase refactor\` or \`--phase refactor-deferred --refactor-rationale "<why>"\`).
943
944
  - GREEN — minimal production code to satisfy existing RED tests, rerun full suite.
944
945
  - REFACTOR — only after full suite is green; preserve behavior.
945
- - Append \`--status green\` (and \`--status refactor-done\` or \`--status refactor-deferred --refactor-rationale "<why>"\` after refactor) via \`cclaw-cli internal tdd-slice-record\`. The Vertical Slice Cycle markdown stays auto-derived from this sidecar.
946
+ - Do NOT hand-edit \`## Vertical Slice Cycle\` / \`## GREEN Evidence\` markdown tables auto-rendered from your dispatch row.
946
947
  - Report: FILES_EDITED, GREEN_COMMAND_RUN, REFACTOR_NOTES, STATUS: DONE|BLOCKED.
947
948
  ${MARKDOWN_CODE_FENCE}
948
949
 
@@ -17,4 +17,10 @@ export declare const RULEBOOK_MARKDOWN = "# Cclaw Rulebook\n\n## MUST_ALWAYS\n-
17
17
  */
18
18
  export declare const CURSOR_GUIDELINES_RULE_MDC = "---\ndescription: cclaw zero-install behavior baseline (always-on)\nglobs:\n - \"**/*\"\nalwaysApply: true\n---\n\n<!-- cclaw-managed-cursor-guidelines-rule -->\n\n# Cclaw Baseline Guidelines\n\nThese three rules apply to every Cursor agent session in this project,\nregardless of whether stage skills loaded.\n\n## 1. Q&A floor before drafting (brainstorm/scope/design)\n\nBefore drafting any `.cclaw/artifacts/01-brainstorm-*.md`,\n`02-scope-*.md`, or `03-design-*.md`, verify that the artifact's\n`## Q&A Log` table demonstrates Ralph-Loop convergence: every\nforcing-question topic id is tagged `[topic:<id>]` on at least one row\n(see the stage's forcing-questions checklist for the id list), the last\n2 turns produce no new decision-changing impact, OR an explicit user\nstop-signal row is recorded. Walk the stage forcing questions one at a\ntime via the `AskQuestion` tool. If you find yourself proposing a\ndraft after 1-2 questions while forcing topic ids remain untagged, STOP\nand continue the loop.\n\nThe `qa_log_unconverged` linter rule will block `stage-complete` when\nconvergence has not been reached. Wave 24 (v6.0.0) made `[topic:<id>]`\ntagging mandatory; the English keyword fallback was removed because it\nmis-reported convergence on RU/UA Q&A logs.\n\n## 2. Mandatory subagents run after Q&A approval\n\nFor brainstorm / scope / design, mandatory subagents (\n`product-discovery`, `critic`, `planner`, `architect`,\n`test-author`) run **only AFTER the user approves the elicitation\noutcome**, never before the Q&A loop converges. Dispatching them early\npreempts the user dialogue and violates the elicitation contract \u2014 the\nlinter will block stage-complete.\n\nSee each stage's \"Run Phase: post-elicitation\" rows in the materialized\nAutomatic Subagent Dispatch table.\n\n## 3. Never echo cclaw command lines to chat\n\nThe user does not run cclaw helpers (`node .cclaw/hooks/...`) manually.\nNEVER paste full command lines, `--evidence-json '{...}'` payloads,\n`--waive-delegation=...`, or shell hash commands (`shasum`,\n`sha256sum`, `Get-FileHash`, `certutil`, etc.) into chat. Run the\nhelper via the tool layer and report only the resulting summary. On\nfailure, report a compact human-readable summary plus the helper JSON in\na single fenced `json` block.\n";
19
19
  export declare const CURSOR_WORKFLOW_RULE_MDC = "---\ndescription: cclaw workflow guardrails for Cursor agent sessions\nglobs:\n - \"**/*\"\nalwaysApply: true\n---\n\n<!-- cclaw-managed-cursor-workflow-rule -->\n\n# Cclaw Workflow Guardrails\n\n## Activation Rule\n\nBefore responding to coding work:\n1. Read `.cclaw/state/flow-state.json`.\n2. Start with `/cc` or continue with `/cc`.\n3. If no software-stage flow applies, respond normally.\n\n## Stage Order\n\n`brainstorm -> scope -> design -> spec -> plan -> tdd -> review -> ship`\n\nTrack-specific skips are allowed only when `flow-state.track` + `skippedStages` explicitly say so.\n\n## Task Classification\n\n| Class | Route |\n|---|---|\n| non-trivial software work | `/cc <idea>` |\n| trivial software fix | `/cc <idea>` (quick track) |\n| bugfix with repro | `/cc <idea>` and enforce RED-first in tdd |\n| pure question / non-software | direct answer (no stage flow) |\n\n## Command Surface\n\n- `/cc` = entry and resume.\n- `/cc` = only progression path.\n- Knowledge capture and recall use the `learnings` skill when requested.\n\n## Verification Discipline\n\n- No completion claim without fresh command evidence in this turn.\n- Stage completion claim requires `stage-complete` exit 0 in the current turn. Quote the single-line success JSON printed to stdout (e.g. `{\"ok\":true,\"command\":\"stage-complete\",...}`); do not paraphrase, do not infer success from empty stdout or from skipped retries.\n\n## Protocol label hygiene\n\n`skip` wording means different things depending on phase: brainstorm/scope/design Q&A stop-signals may still literal **skip**/enough/move-on wording; structured ship closeout retros and compound clustering prompts should expose **no changes** (or accept-as-is language) rather than labeling the passive path as skip. Keep the verbs aligned with the harness question copy you present to the human.\n- Do not mark gates passed from memory.\n- Keep evidence in `.cclaw/artifacts/`; archive through closeout via `/cc` or cancel early via `node .cclaw/hooks/cancel-run.mjs`.\n\n## Delegation And Approvals\n\n- Machine-only checks in design/plan/tdd/review/ship should auto-dispatch when tooling supports it.\n- **For brainstorm / scope / design stages**: ask user input continuously via adaptive elicitation (one question per turn through the harness-native question tool \u2014 `AskQuestion` in Cursor). Walk the stage forcing-questions list one-by-one. **Tag each Q&A Log row's `Decision impact` cell with `[topic:<id>]`** (the id is given in the stage's forcing-questions checklist) so the linter can verify coverage in any natural language. Do NOT batch and do NOT defer to a single approval gate at the end. The `qa_log_unconverged` linter rule will block `stage-complete` when convergence is not reached (forcing topic ids untagged AND last 2 turns still produce decision-changing rows AND no stop-signal).\n- **For other stages** (spec/plan/tdd/build/review/ship): ask user input only at explicit approval gates (scope mode, plan approval, challenge resolution, ship finalization), not for routine progress updates.\n- If you find yourself proposing a draft after 1-2 questions in brainstorm/scope/design, STOP \u2014 go back to the forcing-questions list and continue.\n- Mandatory subagents in brainstorm/scope/design run only AFTER the user approves the elicitation outcome (see each stage's \"Run Phase: post-elicitation\" rows). Dispatching them before the Q&A loop converges violates the contract.\n- Never echo cclaw command lines (`node .cclaw/hooks/...`, `--evidence-json '{...}'`) to chat \u2014 the user does not run cclaw manually. Run helpers via the tool layer; report only the resulting summary.\n- If harness capabilities are partial, record waiver reasons in delegation logs.\n\n## Routing Source Of Truth\n\n- Primary router: `.cclaw/skills/using-cclaw/SKILL.md`.\n- Stage behavior: current stage skill plus `.cclaw/state/flow-state.json`.\n- Preamble budget: keep role/status announcements brief and avoid repeating\n them unless the stage or role changes.\n";
20
+ /**
21
+ * v6.11.0 (S2) — per-slice prose file written by `slice-documenter`
22
+ * (or the controller) to `<artifacts-dir>/tdd-slices/S-<id>.md`. The
23
+ * main `06-tdd.md` is auto-indexed via `## Slices Index`.
24
+ */
25
+ export declare function tddSliceFileTemplate(sliceId: string): string;
20
26
  export declare function buildRulesJson(): Record<string, unknown>;
@@ -976,10 +976,14 @@ ${renderBehaviorAnchorTemplateLine("tdd")}
976
976
  - Open questions:
977
977
  - Drift from upstream (or \`None\`):
978
978
 
979
+ <!-- auto-start: slices-index -->
980
+ ## Slices Index
981
+
982
+ _Auto-rendered from \`tdd-slices/S-*.md\` once slice-documenter or controller writes per-slice files. Do not edit by hand._
983
+ <!-- auto-end: slices-index -->
984
+
979
985
  ## Test Discovery
980
- | Slice | Existing tests / helpers / fixtures | Exact command(s) | Pattern to extend |
981
- |---|---|---|---|
982
- | S-1 | | | |
986
+ > Overall narrative for how this stage discovered the existing test surface. Per-slice details live in \`tdd-slices/S-<id>.md\`.
983
987
 
984
988
  ## System-Wide Impact Check
985
989
  | Slice | Callbacks/state/interfaces/contracts affected | Coverage decision |
@@ -987,20 +991,17 @@ ${renderBehaviorAnchorTemplateLine("tdd")}
987
991
  | S-1 | | covered/out-of-scope because |
988
992
 
989
993
  ## RED Evidence
990
- | Slice | Test name | Command | Failure output summary |
991
- |---|---|---|---|
992
- | S-1 | | | |
994
+ > From v6.11.0 the per-slice RED rows are auto-satisfied by \`phase=red\` events in \`delegation-events.jsonl\` (controller dispatches \`test-author --slice S-<id> --phase red\`). Legacy hand-filled tables continue to validate as a fallback. Use \`Evidence: <path>\` or \`Evidence: spanId:<id>\` pointers if you prefer a manual reference.
993
995
 
994
996
  ## Acceptance & Failure Map
995
997
  | Slice | Source ID | AC ID | Expected behavior | RED-link |
996
998
  |---|---|---|---|---|
997
999
  | S-1 | SRC-1 | AC-1 | | |
998
1000
 
999
- > Each slice maps to the active track's source item (plan slice on standard/medium, or the \`Quick Reproduction Contract\` bug slice / spec acceptance item on quick) and to a spec criterion. The RED-link column is satisfied by either a \`spanId:<id>\` from the delegation ledger, an \`<artifacts-dir>/<file>\` evidence pointer, or a \`redOutputRef\` recorded via \`cclaw-cli internal tdd-slice-record\` in the sidecar ledger.
1001
+ > Each slice maps to the active track's source item (plan slice on standard/medium, or the \`Quick Reproduction Contract\` bug slice / spec acceptance item on quick) and to a spec criterion. The RED-link column is satisfied by either a \`spanId:<id>\` from the delegation ledger or an \`<artifacts-dir>/<file>\` evidence pointer. From v6.11.0 the column is auto-derivable: a \`phase=red\` event in \`delegation-events.jsonl\` with non-empty evidenceRefs auto-satisfies the row.
1000
1002
 
1001
1003
  ## GREEN Evidence
1002
- - Full suite command:
1003
- - Full suite result:
1004
+ > From v6.11.0 GREEN rows are auto-satisfied by \`phase=green\` events in \`delegation-events.jsonl\` (controller dispatches \`slice-implementer --slice S-<id> --phase green\`). Legacy hand-filled tables continue to validate as a fallback. Use \`Evidence: <path>\` or \`Evidence: spanId:<id>\` pointers if you prefer a manual reference.
1004
1005
 
1005
1006
  ## REFACTOR Notes
1006
1007
  - What changed:
@@ -1017,19 +1018,11 @@ ${renderBehaviorAnchorTemplateLine("tdd")}
1017
1018
  - Acknowledged: yes — code that landed before its test will be deleted and rewritten from the test.
1018
1019
  - Exceptions invoked (or \`- None.\`):
1019
1020
 
1020
- ## Watched-RED Proof
1021
- > Required for every new test in this stage. Each row proves the test was *observed* failing before any production code was written.
1022
-
1023
- | Slice | Test name | Observed at (ISO ts) | Failure reason snippet | Source command/log |
1024
- |---|---|---|---|---|
1025
- | S-1 | | | | |
1026
-
1021
+ <!-- auto-start: tdd-slice-summary -->
1027
1022
  ## Vertical Slice Cycle
1028
- > Per slice: RED -> GREEN -> REFACTOR within the same cycle (refactor not deferred). The linter checks structural presence of all three phases.
1029
1023
 
1030
- | Slice | RED ts | GREEN ts | REFACTOR ts (or \`deferred because <reason>\`) |
1031
- |---|---|---|---|
1032
- | S-1 | | | |
1024
+ _Auto-rendered from \`delegation-events.jsonl\` once \`test-author\` and \`slice-implementer\` are dispatched with \`--slice <id> --phase red|green|refactor|refactor-deferred\`. Do not edit by hand._
1025
+ <!-- auto-end: tdd-slice-summary -->
1033
1026
 
1034
1027
  ## Assertion Correctness Notes
1035
1028
  > For each new test assertion, name a *plausible subtle bug* that would still pass it (mental mutation test). If you cannot, the assertion is too coarse — strengthen it.
@@ -1623,6 +1616,31 @@ Track-specific skips are allowed only when \`flow-state.track\` + \`skippedStage
1623
1616
  - Preamble budget: keep role/status announcements brief and avoid repeating
1624
1617
  them unless the stage or role changes.
1625
1618
  `;
1619
+ /**
1620
+ * v6.11.0 (S2) — per-slice prose file written by `slice-documenter`
1621
+ * (or the controller) to `<artifacts-dir>/tdd-slices/S-<id>.md`. The
1622
+ * main `06-tdd.md` is auto-indexed via `## Slices Index`.
1623
+ */
1624
+ export function tddSliceFileTemplate(sliceId) {
1625
+ return `# Slice ${sliceId}
1626
+
1627
+ ## Plan unit
1628
+ T-...
1629
+
1630
+ ## Acceptance criteria
1631
+ AC-...
1632
+
1633
+ ## Why this slice
1634
+
1635
+ ## What was tested
1636
+
1637
+ ## What was implemented
1638
+
1639
+ ## REFACTOR notes
1640
+
1641
+ ## Learnings
1642
+ `;
1643
+ }
1626
1644
  export function buildRulesJson() {
1627
1645
  return {
1628
1646
  version: 1,
@@ -140,7 +140,34 @@ export type DelegationEntry = {
140
140
  * `src/content/hooks.ts::delegationRecordScript`.
141
141
  */
142
142
  claimedPaths?: string[];
143
+ /**
144
+ * v6.11.0 (D1) — TDD slice identifier, e.g. `"S-1"`. Recorded by the
145
+ * controller when dispatching `test-author` / `slice-implementer` /
146
+ * `slice-documenter` so the artifact linter can auto-derive the
147
+ * Watched-RED Proof + Vertical Slice Cycle tables from
148
+ * `delegation-events.jsonl` instead of requiring agents to maintain
149
+ * the markdown by hand. Optional: legacy and non-TDD rows omit it.
150
+ *
151
+ * keep in sync with the inline copy in
152
+ * `src/content/hooks.ts::delegationRecordScript`.
153
+ */
154
+ sliceId?: string;
155
+ /**
156
+ * v6.11.0 (D1) — explicit phase tag for TDD slice events. Combined
157
+ * with `sliceId`, the linter validates RED -> GREEN -> REFACTOR
158
+ * monotonicity per slice. `refactor-deferred` requires a rationale
159
+ * either via `--refactor-rationale` (recorded into evidenceRefs[0])
160
+ * or an `evidenceRefs` entry that contains the rationale text.
161
+ * `doc` is reserved for the parallel `slice-documenter` subagent
162
+ * (Phase C). Optional: legacy and non-TDD rows omit it.
163
+ *
164
+ * keep in sync with the inline copy in
165
+ * `src/content/hooks.ts::delegationRecordScript`.
166
+ */
167
+ phase?: "red" | "green" | "refactor" | "refactor-deferred" | "doc";
143
168
  };
169
+ export declare const DELEGATION_PHASES: readonly ["red", "green", "refactor", "refactor-deferred", "doc"];
170
+ export type DelegationPhase = (typeof DELEGATION_PHASES)[number];
144
171
  export declare const DELEGATION_LEDGER_SCHEMA_VERSION: 3;
145
172
  export type DelegationLedger = {
146
173
  runId: string;
@@ -38,6 +38,13 @@ export const DELEGATION_DISPATCH_SURFACE_PATH_PREFIXES = {
38
38
  "role-switch": [],
39
39
  "manual": []
40
40
  };
41
+ export const DELEGATION_PHASES = [
42
+ "red",
43
+ "green",
44
+ "refactor",
45
+ "refactor-deferred",
46
+ "doc"
47
+ ];
41
48
  export const DELEGATION_LEDGER_SCHEMA_VERSION = 3;
42
49
  function delegationLogPath(projectRoot) {
43
50
  return path.join(projectRoot, RUNTIME_ROOT, "state", "delegation-log.json");
@@ -226,7 +233,12 @@ function isDelegationEntry(value) {
226
233
  (o.allowParallel === undefined || typeof o.allowParallel === "boolean") &&
227
234
  (o.supersededBy === undefined || typeof o.supersededBy === "string") &&
228
235
  (o.claimedPaths === undefined ||
229
- (Array.isArray(o.claimedPaths) && o.claimedPaths.every((item) => typeof item === "string"))));
236
+ (Array.isArray(o.claimedPaths) && o.claimedPaths.every((item) => typeof item === "string"))) &&
237
+ (o.sliceId === undefined ||
238
+ (typeof o.sliceId === "string" && o.sliceId.length > 0)) &&
239
+ (o.phase === undefined ||
240
+ (typeof o.phase === "string" &&
241
+ DELEGATION_PHASES.includes(o.phase))));
230
242
  }
231
243
  function isDelegationDispatchSurface(value) {
232
244
  return typeof value === "string" && DELEGATION_DISPATCH_SURFACES.includes(value);
@@ -121,6 +121,21 @@ export interface FlowState {
121
121
  completedStageMeta?: Partial<Record<FlowStage, {
122
122
  completedAt: string;
123
123
  }>>;
124
+ /**
125
+ * v6.12.0 — TDD migration cutover marker. When `cclaw-cli sync` detects an
126
+ * existing `06-tdd.md` with legacy per-slice tables but no auto-render
127
+ * markers, it inserts the markers and records the highest legacy slice id
128
+ * here (e.g. `"S-10"`). The TDD linter uses this value to:
129
+ * - exempt slices `<= cutoverSliceId` from new mandatory rules (legacy
130
+ * slices keep their markdown tables);
131
+ * - emit `tdd_legacy_section_writes_after_cutover` advisory when a slice
132
+ * id `> cutoverSliceId` appears in legacy per-slice sections of
133
+ * `06-tdd.md` (post-cutover prose belongs in `tdd-slices/S-<id>.md`).
134
+ *
135
+ * Optional + best-effort: omitted on fresh installs and on legacy files
136
+ * sync hasn't visited yet.
137
+ */
138
+ tddCutoverSliceId?: string;
124
139
  }
125
140
  export interface StageInteractionHint {
126
141
  skipQuestions?: boolean;
package/dist/install.js CHANGED
@@ -168,6 +168,14 @@ const DEPRECATED_STATE_FILES = [
168
168
  // now reads cycle phase progression directly from the artifact table.
169
169
  "tdd-cycle-log.jsonl"
170
170
  ];
171
+ // v6.11.0 (R5): files under `<runtime>/artifacts/` that previous releases
172
+ // generated and v6.11.0 removed. `cclaw-cli sync` deletes each so existing
173
+ // installs lose the obsolete sidecar without requiring manual cleanup.
174
+ const DEPRECATED_ARTIFACT_FILES = [
175
+ // v6.10.0 sidecar — replaced in v6.11.0 by phase events in
176
+ // delegation-events.jsonl + auto-rendered tables in 06-tdd.md.
177
+ "06-tdd-slices.jsonl"
178
+ ];
171
179
  const DEPRECATED_HOOK_FILES = [
172
180
  "observe.sh",
173
181
  "summarize-observations.sh",
@@ -827,6 +835,112 @@ async function writeState(projectRoot, config, forceReset = false) {
827
835
  const state = createInitialFlowState({ track: "standard" });
828
836
  await writeFileSafe(statePath, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 });
829
837
  }
838
+ /**
839
+ * v6.12.0 — TDD auto-cutover sync. When sync detects a legacy `06-tdd.md`
840
+ * (no auto-render markers) carrying observable slice activity (e.g. `S-N`
841
+ * referenced ≥3 times in slice-section bodies), insert the v6.11.0 marker
842
+ * skeleton + a one-line cutover banner and stamp the highest legacy slice
843
+ * id into `flow-state.json::tddCutoverSliceId`. Idempotent: re-running sync
844
+ * is byte-stable once markers are present.
845
+ *
846
+ * Design notes:
847
+ * - Best-effort: read failures, missing flow-state, or unparseable JSON
848
+ * all short-circuit silently. We never throw inside sync for migration
849
+ * bookkeeping.
850
+ * - We use `writeFlowState({ allowReset: true })` so we don't trip
851
+ * `validateFlowTransition` (the only field we mutate is the new
852
+ * additive `tddCutoverSliceId`; transition rules don't apply).
853
+ * - The banner mirrors the language in the `## Per-Slice Ritual`
854
+ * skill section so a reader of `06-tdd.md` who hasn't seen v6.12.0
855
+ * understands the contract change.
856
+ */
857
+ async function applyTddCutoverIfNeeded(projectRoot) {
858
+ const tddArtifactPath = runtimePath(projectRoot, "artifacts", "06-tdd.md");
859
+ let existing;
860
+ try {
861
+ existing = await fs.readFile(tddArtifactPath, "utf8");
862
+ }
863
+ catch {
864
+ return;
865
+ }
866
+ if (existing.includes("<!-- auto-start: tdd-slice-summary -->")) {
867
+ return;
868
+ }
869
+ const sliceMatches = [...existing.matchAll(/\bS-(\d+)\b/gu)];
870
+ if (sliceMatches.length < 3) {
871
+ return;
872
+ }
873
+ let maxSliceNum = 0;
874
+ for (const match of sliceMatches) {
875
+ const n = Number.parseInt(match[1], 10);
876
+ if (Number.isFinite(n) && n > maxSliceNum) {
877
+ maxSliceNum = n;
878
+ }
879
+ }
880
+ if (maxSliceNum <= 0) {
881
+ return;
882
+ }
883
+ const cutoverSliceId = `S-${maxSliceNum}`;
884
+ const banner = [
885
+ `<!-- v6.12.0 cutover: slices S-1..${cutoverSliceId} use legacy per-slice tables.`,
886
+ ` New slices (S-${maxSliceNum + 1}+) use phase events + tdd-slices/<id>.md.`,
887
+ " Controller MUST NOT add new rows to legacy sections. -->"
888
+ ].join("\n");
889
+ const slicesIndexBlock = [
890
+ "<!-- auto-start: slices-index -->",
891
+ "## Slices Index",
892
+ "",
893
+ "_Auto-rendered from `tdd-slices/S-*.md` once slice-documenter or controller writes per-slice files. Do not edit by hand._",
894
+ "<!-- auto-end: slices-index -->"
895
+ ].join("\n");
896
+ const summaryBlock = [
897
+ "<!-- auto-start: tdd-slice-summary -->",
898
+ "<!-- auto-end: tdd-slice-summary -->"
899
+ ].join("\n");
900
+ let nextRaw;
901
+ if (existing.startsWith("---\n")) {
902
+ const fmEnd = existing.indexOf("\n---", 4);
903
+ if (fmEnd >= 0) {
904
+ const fmClose = fmEnd + 4;
905
+ const head = existing.slice(0, fmClose);
906
+ const tail = existing.slice(fmClose);
907
+ nextRaw = `${head}\n\n${banner}\n\n${slicesIndexBlock}\n\n${summaryBlock}\n${tail}`;
908
+ }
909
+ else {
910
+ nextRaw = `${banner}\n\n${slicesIndexBlock}\n\n${summaryBlock}\n\n${existing}`;
911
+ }
912
+ }
913
+ else {
914
+ nextRaw = `${banner}\n\n${slicesIndexBlock}\n\n${summaryBlock}\n\n${existing}`;
915
+ }
916
+ await writeFileSafe(tddArtifactPath, nextRaw);
917
+ const slicesDir = runtimePath(projectRoot, "artifacts", "tdd-slices");
918
+ await ensureDir(slicesDir);
919
+ const flowStatePath = runtimePath(projectRoot, "state", "flow-state.json");
920
+ let flowStateRaw;
921
+ try {
922
+ flowStateRaw = await fs.readFile(flowStatePath, "utf8");
923
+ }
924
+ catch {
925
+ return;
926
+ }
927
+ let parsed;
928
+ try {
929
+ parsed = JSON.parse(flowStateRaw);
930
+ }
931
+ catch {
932
+ return;
933
+ }
934
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
935
+ return;
936
+ }
937
+ const obj = parsed;
938
+ if (typeof obj.tddCutoverSliceId === "string" && obj.tddCutoverSliceId.length > 0) {
939
+ return;
940
+ }
941
+ obj.tddCutoverSliceId = cutoverSliceId;
942
+ await writeFileSafe(flowStatePath, `${JSON.stringify(obj, null, 2)}\n`, { mode: 0o600 });
943
+ }
830
944
  async function cleanLegacyArtifacts(projectRoot) {
831
945
  for (const legacyFolder of DEPRECATED_UTILITY_SKILL_FOLDERS) {
832
946
  await removeBestEffort(runtimePath(projectRoot, "skills", legacyFolder), true);
@@ -851,6 +965,7 @@ async function cleanLegacyArtifacts(projectRoot) {
851
965
  ...DEPRECATED_COMMAND_FILES.map((file) => runtimePath(projectRoot, "commands", file)),
852
966
  ...DEPRECATED_SKILL_FILES.map((segments) => runtimePath(projectRoot, "skills", ...segments)),
853
967
  ...DEPRECATED_STATE_FILES.map((file) => runtimePath(projectRoot, "state", file)),
968
+ ...DEPRECATED_ARTIFACT_FILES.map((file) => runtimePath(projectRoot, "artifacts", file)),
854
969
  ...DEPRECATED_RUNTIME_ROOT_FILES.map((file) => runtimePath(projectRoot, file)),
855
970
  ...DEPRECATED_HOOK_FILES.map((file) => runtimePath(projectRoot, "hooks", file))
856
971
  ]) {
@@ -976,6 +1091,9 @@ async function materializeRuntime(projectRoot, config, forceStateReset, operatio
976
1091
  writeRulebook(projectRoot)
977
1092
  ]);
978
1093
  await writeState(projectRoot, config, forceStateReset);
1094
+ if (operation === "sync" || operation === "upgrade") {
1095
+ await applyTddCutoverIfNeeded(projectRoot);
1096
+ }
979
1097
  try {
980
1098
  await ensureRunSystem(projectRoot, { createIfMissing: false });
981
1099
  }
@@ -15,7 +15,6 @@ import { parseFlowStateRepairArgs, runFlowStateRepair } from "./flow-state-repai
15
15
  import { parseWaiverGrantArgs, runWaiverGrant } from "./waiver-grant.js";
16
16
  import { FlowStateGuardMismatchError, verifyFlowStateGuard } from "../run-persistence.js";
17
17
  import { DelegationTimestampError, DispatchCapError, DispatchDuplicateError, DispatchOverlapError } from "../delegation.js";
18
- import { parseTddSliceRecordArgs, runTddSliceRecord } from "../tdd-slices.js";
19
18
  import { parsePlanSplitWavesArgs, runPlanSplitWaves } from "./plan-split-waves.js";
20
19
  /**
21
20
  * Subcommands that mutate or consult flow-state.json via the CLI runtime.
@@ -34,7 +33,7 @@ const GUARD_ENFORCED_SUBCOMMANDS = new Set([
34
33
  export async function runInternalCommand(projectRoot, argv, io) {
35
34
  const [subcommand, ...tokens] = argv;
36
35
  if (!subcommand) {
37
- io.stderr.write("cclaw internal requires a subcommand: advance-stage | start-flow | cancel-run | rewind | verify-flow-state-diff | verify-current-state | envelope-validate | tdd-red-evidence | tdd-loop-status | tdd-slice-record | early-loop-status | compound-readiness | runtime-integrity | hook | flow-state-repair | waiver-grant | plan-split-waves\n");
36
+ io.stderr.write("cclaw internal requires a subcommand: advance-stage | start-flow | cancel-run | rewind | verify-flow-state-diff | verify-current-state | envelope-validate | tdd-red-evidence | tdd-loop-status | early-loop-status | compound-readiness | runtime-integrity | hook | flow-state-repair | waiver-grant | plan-split-waves\n");
38
37
  return 1;
39
38
  }
40
39
  try {
@@ -86,13 +85,10 @@ export async function runInternalCommand(projectRoot, argv, io) {
86
85
  if (subcommand === "waiver-grant") {
87
86
  return await runWaiverGrant(projectRoot, parseWaiverGrantArgs(tokens), io);
88
87
  }
89
- if (subcommand === "tdd-slice-record") {
90
- return await runTddSliceRecord(projectRoot, parseTddSliceRecordArgs(tokens), io);
91
- }
92
88
  if (subcommand === "plan-split-waves") {
93
89
  return await runPlanSplitWaves(projectRoot, parsePlanSplitWavesArgs(tokens), io);
94
90
  }
95
- io.stderr.write(`Unknown internal subcommand: ${subcommand}. Expected advance-stage | start-flow | cancel-run | rewind | verify-flow-state-diff | verify-current-state | envelope-validate | tdd-red-evidence | tdd-loop-status | tdd-slice-record | early-loop-status | compound-readiness | runtime-integrity | hook | flow-state-repair | waiver-grant | plan-split-waves\n`);
91
+ io.stderr.write(`Unknown internal subcommand: ${subcommand}. Expected advance-stage | start-flow | cancel-run | rewind | verify-flow-state-diff | verify-current-state | envelope-validate | tdd-red-evidence | tdd-loop-status | early-loop-status | compound-readiness | runtime-integrity | hook | flow-state-repair | waiver-grant | plan-split-waves\n`);
96
92
  return 1;
97
93
  }
98
94
  catch (err) {
@@ -471,6 +471,7 @@ function coerceFlowState(parsed) {
471
471
  const taskClass = coerceTaskClass(parsed.taskClass);
472
472
  const repoSignals = coerceRepoSignals(parsed.repoSignals);
473
473
  const completedStageMeta = sanitizeCompletedStageMeta(parsed.completedStageMeta);
474
+ const tddCutoverSliceId = coerceTddCutoverSliceId(parsed.tddCutoverSliceId);
474
475
  const state = {
475
476
  schemaVersion: FLOW_STATE_SCHEMA_VERSION,
476
477
  activeRunId,
@@ -483,6 +484,7 @@ function coerceFlowState(parsed) {
483
484
  ...(taskClass !== undefined ? { taskClass } : {}),
484
485
  ...(repoSignals ? { repoSignals } : {}),
485
486
  ...(completedStageMeta ? { completedStageMeta } : {}),
487
+ ...(tddCutoverSliceId ? { tddCutoverSliceId } : {}),
486
488
  skippedStages: sanitizeSkippedStages(parsed.skippedStages, track),
487
489
  staleStages: sanitizeStaleStages(parsed.staleStages),
488
490
  rewinds: sanitizeRewinds(parsed.rewinds),
@@ -492,6 +494,17 @@ function coerceFlowState(parsed) {
492
494
  };
493
495
  return { state };
494
496
  }
497
+ /**
498
+ * v6.12.0 — best-effort coercion for `tddCutoverSliceId`. Returns the value
499
+ * only when it matches the canonical slice id shape `S-<digits>`; otherwise
500
+ * returns null so the field is omitted from the rehydrated state.
501
+ */
502
+ function coerceTddCutoverSliceId(value) {
503
+ if (typeof value !== "string")
504
+ return null;
505
+ const trimmed = value.trim();
506
+ return /^S-\d+$/u.test(trimmed) ? trimmed : null;
507
+ }
495
508
  export class CorruptFlowStateError extends Error {
496
509
  statePath;
497
510
  quarantinedPath;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cclaw-cli",
3
- "version": "6.10.0",
3
+ "version": "6.12.0",
4
4
  "description": "Installer-first flow toolkit for coding agents",
5
5
  "type": "module",
6
6
  "bin": {