cclaw-cli 6.11.0 → 6.13.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 (41) hide show
  1. package/dist/artifact-linter/plan.js +60 -2
  2. package/dist/artifact-linter/shared.d.ts +9 -0
  3. package/dist/artifact-linter/spec.js +14 -0
  4. package/dist/artifact-linter/tdd.d.ts +29 -0
  5. package/dist/artifact-linter/tdd.js +398 -11
  6. package/dist/artifact-linter.js +10 -1
  7. package/dist/content/core-agents.d.ts +2 -2
  8. package/dist/content/core-agents.js +3 -3
  9. package/dist/content/examples.js +4 -4
  10. package/dist/content/hooks.js +48 -1
  11. package/dist/content/skills.d.ts +10 -0
  12. package/dist/content/skills.js +64 -2
  13. package/dist/content/stage-schema.js +13 -4
  14. package/dist/content/stages/plan.js +2 -1
  15. package/dist/content/stages/schema-types.d.ts +1 -1
  16. package/dist/content/stages/spec.js +2 -2
  17. package/dist/content/stages/tdd.js +8 -7
  18. package/dist/content/templates.js +10 -4
  19. package/dist/delegation.d.ts +73 -3
  20. package/dist/delegation.js +196 -6
  21. package/dist/flow-state.d.ts +35 -0
  22. package/dist/flow-state.js +7 -0
  23. package/dist/gate-evidence.d.ts +5 -0
  24. package/dist/gate-evidence.js +58 -1
  25. package/dist/install.js +173 -1
  26. package/dist/integration-fanin.d.ts +44 -0
  27. package/dist/integration-fanin.js +180 -0
  28. package/dist/internal/advance-stage/advance.js +16 -1
  29. package/dist/internal/advance-stage/start-flow.js +3 -1
  30. package/dist/internal/advance-stage.js +13 -4
  31. package/dist/internal/plan-split-waves.d.ts +39 -1
  32. package/dist/internal/plan-split-waves.js +190 -6
  33. package/dist/internal/set-worktree-mode.d.ts +10 -0
  34. package/dist/internal/set-worktree-mode.js +28 -0
  35. package/dist/managed-resources.js +2 -0
  36. package/dist/run-persistence.js +22 -0
  37. package/dist/worktree-manager.d.ts +50 -0
  38. package/dist/worktree-manager.js +136 -0
  39. package/dist/worktree-types.d.ts +36 -0
  40. package/dist/worktree-types.js +6 -0
  41. package/package.json +1 -1
@@ -36,10 +36,10 @@ export const BEHAVIOR_ANCHORS = [
36
36
  },
37
37
  {
38
38
  stage: "tdd",
39
- section: "Watched-RED Proof",
40
- bad: "Hand-edit Watched-RED Proof rows directly in the TDD artifact; the next lint overwrites the auto-rendered region and the slice still lacks a provable RED in delegation events.",
41
- good: "Dispatch `test-author --slice S-1 --phase red`, then `slice-implementer --slice S-1 --phase green`. The linter auto-renders the slice cycle from `delegation-events.jsonl`.",
42
- ruleHint: "RED/GREEN/REFACTOR transitions are recorded as `delegation-events.jsonl` rows via slice-tagged dispatches; the markdown tables are auto-rendered between `auto-start: tdd-slice-summary` markers from v6.11.0 onward."
39
+ section: "Vertical Slice Cycle",
40
+ bad: "Controller writes the failing test, the GREEN fix, AND per-slice prose into `06-tdd.md` itself, then hand-edits Watched-RED / Vertical Slice Cycle tables. `phase=red`/`green`/`doc` events missing; `tdd_slice_implementer_missing` and `tdd_slice_documenter_missing` block the gate.",
41
+ good: "Per slice: (1) `Task(\"test-author --slice S-1 --phase red\")`. Verify the event. (2) ONE message, TWO Tasks — `slice-implementer --phase green` AND `slice-documenter --phase doc`. (3) `slice-implementer --phase refactor` (or `refactor-deferred`). Linter auto-renders Vertical Slice Cycle from events.",
42
+ ruleHint: "Per-Slice Ritual (v6.12.0+): RED verify GREEN+DOC fan-out (one message, two Tasks) REFACTOR. Controller never writes GREEN code or per-slice prose. Mandatory regardless of `discoveryMode`."
43
43
  },
44
44
  {
45
45
  stage: "review",
@@ -350,6 +350,11 @@ function usage() {
350
350
  " --slice=<id> TDD slice identifier (e.g. S-1) used by the linter to auto-derive the Watched-RED + Vertical Slice Cycle tables.",
351
351
  " --phase=<phase> one of " + VALID_DELEGATION_PHASES.join(", ") + ". Pair with --slice to record a TDD slice phase event.",
352
352
  " --refactor-rationale=<t> required when --phase=refactor-deferred unless --evidence-ref carries the rationale text.",
353
+ " --claim-token=<opaque> v6.13 — required for worktree-first slice-implementer schedules with --slice (echo on all terminal rows for the span).",
354
+ " --lane-id=<id> v6.13 — worktree lane id (ownerLaneId metadata).",
355
+ " --lease-until=<iso> v6.13 — ISO8601 lease expiry for reclaim tooling.",
356
+ " --depends-on=<a,b> v6.13 — comma-separated plan unit ids for scheduler diagnostics.",
357
+ " --integration-state=<s> v6.13 — one of pending|applied|conflict|resolved|abandoned.",
353
358
  ""
354
359
  ].join("\\n") + "\\n");
355
360
  }
@@ -484,6 +489,42 @@ function buildRow(args, status, runId, now, options) {
484
489
  resolvedEvidenceRefs = [rationale, ...resolvedEvidenceRefs];
485
490
  }
486
491
  }
492
+ const integrationStateRaw =
493
+ typeof args["integration-state"] === "string" ? args["integration-state"].trim() : "";
494
+ const integrationStateAllowed = new Set([
495
+ "pending",
496
+ "applied",
497
+ "conflict",
498
+ "resolved",
499
+ "abandoned"
500
+ ]);
501
+ const integrationState =
502
+ integrationStateRaw.length > 0 && integrationStateAllowed.has(integrationStateRaw)
503
+ ? integrationStateRaw
504
+ : undefined;
505
+ const claimToken =
506
+ typeof args["claim-token"] === "string" && args["claim-token"].trim().length > 0
507
+ ? args["claim-token"].trim()
508
+ : undefined;
509
+ const ownerLaneId =
510
+ typeof args["lane-id"] === "string" && args["lane-id"].trim().length > 0
511
+ ? args["lane-id"].trim()
512
+ : undefined;
513
+ const leasedUntil =
514
+ typeof args["lease-until"] === "string" && args["lease-until"].trim().length > 0
515
+ ? args["lease-until"].trim()
516
+ : undefined;
517
+ const dependsOnRaw =
518
+ typeof args["depends-on"] === "string" ? args["depends-on"].trim() : "";
519
+ const dependsOn =
520
+ dependsOnRaw.length > 0
521
+ ? dependsOnRaw
522
+ .split(",")
523
+ .map((value) => value.trim())
524
+ .filter((value) => value.length > 0)
525
+ : undefined;
526
+ const leaseState =
527
+ leasedUntil && status === "scheduled" ? "claimed" : undefined;
487
528
  return {
488
529
  stage: args.stage,
489
530
  agent: args.agent,
@@ -508,7 +549,13 @@ function buildRow(args, status, runId, now, options) {
508
549
  allowParallel: args["allow-parallel"] === true ? true : undefined,
509
550
  claimedPaths: claimedPaths.length > 0 ? claimedPaths : undefined,
510
551
  sliceId,
511
- phase
552
+ phase,
553
+ claimToken,
554
+ ownerLaneId,
555
+ leasedUntil,
556
+ leaseState,
557
+ dependsOn,
558
+ integrationState
512
559
  };
513
560
  }
514
561
 
@@ -18,6 +18,16 @@ export declare function watchedFailProofBlock(): string;
18
18
  export declare const INVESTIGATION_DISCIPLINE_STAGES: ReadonlySet<FlowStage>;
19
19
  export declare function investigationDisciplineBlock(): string;
20
20
  export declare function behaviorAnchorBlock(stage: FlowStage): string;
21
+ /**
22
+ * v6.12.0 Phase Ritual + Phase W — TDD-only top-of-skill sections that
23
+ * sit immediately after the `<EXTREMELY-IMPORTANT>` Iron Law block and
24
+ * before `## Quick Start`. They establish the per-slice three-dispatch
25
+ * ritual + wave batch mode in imperative voice with literal commands so
26
+ * pattern-matching on read works in our favor.
27
+ *
28
+ * Empty for non-TDD stages.
29
+ */
30
+ export declare function tddTopOfSkillBlock(stage: FlowStage): string;
21
31
  export declare function stageSkillFolder(stage: FlowStage): string;
22
32
  export declare function stageSkillMarkdown(stage: FlowStage, track?: FlowTrack): string;
23
33
  export declare function executingWavesSkillMarkdown(): string;
@@ -102,7 +102,7 @@ Any "the failure is real" claim (failing test, broken build, regression catch, d
102
102
 
103
103
  \`proof: <iso-ts> | <observed snippet — first 200 chars> | source: <command or log path>\`
104
104
 
105
- For TDD specifically, this is the watched-RED proof and is required per new test before \`stage-complete\` accepts the stage. From v6.11.0 onward, the controller dispatches \`test-author --slice S-<id> --phase red\` (and later \`slice-implementer --phase green\`, \`--phase refactor\` or \`--phase refactor-deferred --refactor-rationale "<why>"\`) and the linter auto-derives the \`Watched-RED Proof\` and \`Vertical Slice Cycle\` tables in \`06-tdd.md\` from \`.cclaw/state/delegation-events.jsonl\`. Do NOT hand-edit those tables. v6.10.0 sidecar (\`06-tdd-slices.jsonl\`) is removed; \`cclaw-cli sync\` cleans the file from existing installs.
105
+ For TDD specifically, this is the watched-RED proof and is required per new test before \`stage-complete\` accepts the stage. From v6.12.0 onward, every slice on every TDD run dispatches three roles in this exact order: (1) \`test-author --slice S-<id> --phase red\`, (2) ONE message with TWO concurrent Task calls — \`slice-implementer --slice S-<id> --phase green --paths <production paths>\` AND \`slice-documenter --slice S-<id> --phase doc --paths <artifacts-dir>/tdd-slices/S-<id>.md\`, (3) \`slice-implementer --phase refactor\` or \`--phase refactor-deferred --refactor-rationale "<why>"\`. The linter auto-derives the \`Watched-RED Proof\` and \`Vertical Slice Cycle\` tables in \`06-tdd.md\` from \`.cclaw/state/delegation-events.jsonl\`. Do NOT hand-edit those tables. \`slice-implementer\` and \`slice-documenter\` are mandatory regardless of \`discoveryMode\` (v6.12.0 Phase R/M); the controller MUST NOT write GREEN production code or per-slice prose itself. v6.10.0 sidecar (\`06-tdd-slices.jsonl\`) is removed; \`cclaw-cli sync\` cleans the file from existing installs.
106
106
  `;
107
107
  }
108
108
  /**
@@ -168,6 +168,68 @@ function whenNotToUseBlock(items) {
168
168
  return `## When Not to Use
169
169
  ${items.map((item) => `- ${item}`).join("\n")}
170
170
 
171
+ `;
172
+ }
173
+ /**
174
+ * v6.12.0 Phase Ritual + Phase W — TDD-only top-of-skill sections that
175
+ * sit immediately after the `<EXTREMELY-IMPORTANT>` Iron Law block and
176
+ * before `## Quick Start`. They establish the per-slice three-dispatch
177
+ * ritual + wave batch mode in imperative voice with literal commands so
178
+ * pattern-matching on read works in our favor.
179
+ *
180
+ * Empty for non-TDD stages.
181
+ */
182
+ export function tddTopOfSkillBlock(stage) {
183
+ if (stage !== "tdd")
184
+ return "";
185
+ return `## Per-Slice Ritual (v6.12.0+)
186
+
187
+ ONE slice = THREE dispatches, in this order. Do not skip, do not collapse.
188
+
189
+ 1. **RED** — \`Task("test-author --slice S-<id> --phase red")\`.
190
+ 2. **Verify RED** — wait for the \`phase=red\` event in \`.cclaw/state/delegation-events.jsonl\` with non-empty \`evidenceRefs\`. No production edits.
191
+ 3. **GREEN+DOC fan-out** — ONE message, TWO concurrent Tasks:
192
+ \`\`\`
193
+ Task("slice-implementer --slice S-<id> --phase green --paths <prod paths>")
194
+ Task("slice-documenter --slice S-<id> --phase doc --paths <artifacts-dir>/tdd-slices/S-<id>.md")
195
+ \`\`\`
196
+ The file-overlap scheduler auto-allows parallel dispatch because \`claimedPaths\` are disjoint. Fire BOTH calls in the same message — never serialize independent work.
197
+ 4. **REFACTOR** — \`Task("slice-implementer --slice S-<id> --phase refactor")\` OR \`--phase refactor-deferred --refactor-rationale '<why>'\`.
198
+
199
+ **FORBIDDEN:**
200
+ - Controller writing GREEN production code. ALL GREEN goes through \`slice-implementer\` — linter rule \`tdd_slice_implementer_missing\` blocks the gate.
201
+ - Controller writing per-slice prose into legacy \`06-tdd.md\` sections (Test Discovery / RED Evidence / GREEN Evidence / Watched-RED Proof / Vertical Slice Cycle / Per-Slice Review / Failure Analysis / Acceptance Mapping). \`slice-documenter\` owns \`tdd-slices/S-<id>.md\` — \`tdd_slice_documenter_missing\` blocks the gate.
202
+ - Hand-editing auto-render blocks between \`auto-start: tdd-slice-summary\` / \`auto-start: slices-index\` markers — overwritten every lint.
203
+
204
+ Delegation-record signature: \`node .cclaw/hooks/delegation-record.mjs --stage=tdd --agent=<agent> --mode=mandatory --status=<...> --span-id=<id> --dispatch-id=<id> --dispatch-surface=<surface> --agent-definition-path=<path> --slice=S-<id> --phase=<red|green|refactor|refactor-deferred|doc> [--paths=<csv>] [--refactor-rationale=<why>] [--ack-ts=<iso>] [--evidence-ref=<ref>] --json\`.
205
+
206
+ ## Wave Batch Mode (v6.12.0+)
207
+
208
+ Trigger: any \`<artifacts-dir>/wave-plans/wave-NN.md\` exists, OR 2+ slices have disjoint \`claimedPaths\`. Cap = 5 \`slice-implementer\` lanes (10 subagents incl. paired documenters) via \`MAX_PARALLEL_SLICE_IMPLEMENTERS\`.
209
+
210
+ **Phase A — RED checkpoint** — ONE message, all test-authors:
211
+ \`\`\`
212
+ Task("test-author --slice S-1 --phase red")
213
+ Task("test-author --slice S-2 --phase red")
214
+ Task("test-author --slice S-3 --phase red")
215
+ \`\`\`
216
+ Wait for ALL Phase A REDs to land with non-empty \`evidenceRefs\` before Phase B. Linter \`tdd_red_checkpoint_violation\` (required: true) blocks any wave where a \`phase=green\` \`completedTs\` precedes the wave's last \`phase=red\` \`completedTs\`.
217
+
218
+ **Phase B — GREEN+DOC fan-out** — ONE message, paired implementer+documenter Tasks per slice:
219
+ \`\`\`
220
+ Task("slice-implementer --slice S-1 --phase green --paths <S-1 prod>")
221
+ Task("slice-documenter --slice S-1 --phase doc --paths <artifacts-dir>/tdd-slices/S-1.md")
222
+ Task("slice-implementer --slice S-2 --phase green --paths <S-2 prod>")
223
+ Task("slice-documenter --slice S-2 --phase doc --paths <artifacts-dir>/tdd-slices/S-2.md")
224
+ \`\`\`
225
+ Launch ALL Phase B pairs in ONE message. **Never serialize independent work.**
226
+
227
+ **Phase C — REFACTOR per slice** — after GREEN+DOC evidence is recorded, dispatch \`slice-implementer --phase refactor\` or \`--phase refactor-deferred\` per slice (may be parallelized when lanes stay disjoint).
228
+
229
+ **Fan-in (v6.13.0+, worktree-first default)** — each \`slice-implementer\` GREEN row should record \`--claim-token\`, \`--lane-id\`, and \`--lease-until\` per the delegation hook. On successful TDD stage-complete, the runtime performs deterministic \`git apply --3way\` fan-in from each lane worktree onto the current integration branch (no \`-X ours/theirs\`). Conflicts emit \`cclaw_fanin_conflict\` audit rows; resolve with \`slice-implementer --phase resolve-conflict\` then re-run stage-complete. When 2+ parallel lanes finish a wave, still dispatch \`integration-overseer\` so cohesion-contract evidence exists before review.
230
+
231
+ **slice-documenter** may mark prose \`provisional\` until GREEN is proven; finalize \`tdd-slices/S-<id>.md\` after GREEN evidence is recorded.
232
+
171
233
  `;
172
234
  }
173
235
  function artifactTemplatePathForStage(stage) {
@@ -593,7 +655,7 @@ If you are about to violate the Iron Law, STOP. No amount of urgency, partial pr
593
655
 
594
656
  </EXTREMELY-IMPORTANT>
595
657
 
596
- ${quickStartBlock(stage, track)}
658
+ ${tddTopOfSkillBlock(stage)}${quickStartBlock(stage, track)}
597
659
 
598
660
  ${STAGE_LANGUAGE_POLICY_POINTER}
599
661
  ## Philosophy
@@ -117,6 +117,7 @@ function defaultReturnSchemaForAgent(agent) {
117
117
  case "feasibility-reviewer":
118
118
  return "review-return";
119
119
  case "slice-implementer":
120
+ case "slice-documenter":
120
121
  return "worker-return";
121
122
  case "release-reviewer":
122
123
  return "release-return";
@@ -143,7 +144,7 @@ function defaultReturnSchemaForAgent(agent) {
143
144
  function dispatchClassForRow(row) {
144
145
  if (row.dispatchClass)
145
146
  return row.dispatchClass;
146
- if (row.agent === "fixer" || row.agent === "slice-implementer")
147
+ if (row.agent === "fixer" || row.agent === "slice-implementer" || row.agent === "slice-documenter")
147
148
  return "worker";
148
149
  return row.skill?.includes("review") || row.agent === "reviewer" || row.agent === "security-reviewer" || row.agent.endsWith("-reviewer")
149
150
  ? "review-lens"
@@ -721,10 +722,18 @@ const STAGE_AUTO_SUBAGENT_DISPATCH = {
721
722
  },
722
723
  {
723
724
  agent: "slice-implementer",
724
- mode: "proactive",
725
+ mode: "mandatory",
726
+ requiredAtTier: "lightweight",
727
+ when: "Always for GREEN and REFACTOR phases. Controller MUST NOT write production code itself.",
728
+ purpose: "Implement the minimal passing slice inside explicit file boundaries and return strict worker evidence. v6.12.0 Phase M makes this dispatch mandatory; the linter rule `tdd_slice_implementer_missing` blocks the gate when GREEN was authored by anyone other than `slice-implementer`.",
729
+ requiresUserGate: false
730
+ },
731
+ {
732
+ agent: "slice-documenter",
733
+ mode: "mandatory",
725
734
  requiredAtTier: "lightweight",
726
- when: "When a bounded GREEN/REFACTOR slice has non-overlapping file ownership and a clear RED failure.",
727
- purpose: "Implement the minimal passing slice inside explicit file boundaries and return strict worker evidence.",
735
+ when: "Always in PARALLEL with `slice-implementer --phase green` for the same slice.",
736
+ purpose: "Write per-slice prose into `<artifacts-dir>/tdd-slices/S-<id>.md` while production code is being implemented. v6.12.0 Phase R makes this mandatory regardless of `discoveryMode`; the linter rule `tdd_slice_documenter_missing` blocks the gate when a `phase=doc` event is missing.",
728
737
  requiresUserGate: false
729
738
  },
730
739
  {
@@ -46,6 +46,7 @@ export const PLAN = {
46
46
  "Slice into vertical tasks — each task targets 2-5 minutes, produces one testable outcome, and touches one coherent area.",
47
47
  "Task Contract — every task has one coherent outcome, AC mapping, exact verification command/manual step, and expected evidence snippet or pass condition. Avoid vague `run tests` wording.",
48
48
  "Annotate slice-review metadata — task rows may carry `touchCount` (rough number of files expected to change), `touchPaths` (glob hints, e.g. `migrations/**`, `src/auth/**`), and optional `highRisk: true` to force a review pass. These fields feed the TDD stage's Per-Slice Review point.",
49
+ "For every `### Implementation Unit U-<n>`, declare v6.13.0 parallel metadata bullets: `id`, `dependsOn` (unit ids or `none`), `claimedPaths` (repo-relative), `parallelizable` (true|false), `riskTier` (low|standard|high), optional `lane` — used for conflict-aware wave plans and schedulers.",
49
50
  "Map scope Locked Decisions — every D-XX ID from scope is referenced by at least one plan task (or explicitly marked deferred with reason).",
50
51
  "Run anti-placeholder + anti-scope-reduction scans — block `TODO/TBD/...` and phrasing like `v1`, `for now`, `later` for locked boundaries.",
51
52
  "Define validation points — mark where progress must be checked before continuing, with concrete command and expected evidence.",
@@ -135,7 +136,7 @@ export const PLAN = {
135
136
  { section: "Locked Decision Coverage", required: false, validationRule: "Every locked decision ID (D-XX) from scope is listed with linked task IDs or explicit defer rationale." },
136
137
  { section: "Risk Assessment", required: false, validationRule: "If present: per-task or per-batch risk identification with likelihood, impact, and mitigation strategy." },
137
138
  { section: "Boundary Map", required: false, validationRule: "If present: per-batch or per-task interface contracts listing what each task produces (exports) and consumes (imports) from other tasks." },
138
- { section: "Implementation Units", required: false, validationRule: "If present: each `### Implementation Unit U-<n>` includes Goal, Files, Approach, Test scenarios, and Verification fields." },
139
+ { section: "Implementation Units", required: false, validationRule: "If present: each `### Implementation Unit U-<n>` includes Goal, Files, Approach, Test scenarios, Verification fields, plus v6.13.0 bullets (`id`, `dependsOn`, `claimedPaths`, `parallelizable`, `riskTier`, optional `lane`)." },
139
140
  { section: "Calibrated Findings", required: false, validationRule: "If present: either `None this stage` or one or more lines in `[P1|P2|P3] (confidence: <n>/10) <path>[:<line>] — <description>` format." },
140
141
  { section: "Regression Iron Rule", required: false, validationRule: "If present: includes `Iron rule acknowledged: yes`." },
141
142
  { section: "WAIT_FOR_CONFIRM", required: true, validationRule: "Explicit marker present. Status: pending until user approves." },
@@ -20,7 +20,7 @@ export interface ArtifactValidation {
20
20
  tier?: "required" | "recommended";
21
21
  validationRule: string;
22
22
  }
23
- export type StageSubagentName = "researcher" | "architect" | "spec-validator" | "spec-document-reviewer" | "coherence-reviewer" | "scope-guardian-reviewer" | "feasibility-reviewer" | "slice-implementer" | "release-reviewer" | "planner" | "product-discovery" | "divergent-thinker" | "critic" | "reviewer" | "security-reviewer" | "integration-overseer" | "test-author" | "doc-updater" | "fixer";
23
+ export type StageSubagentName = "researcher" | "architect" | "spec-validator" | "spec-document-reviewer" | "coherence-reviewer" | "scope-guardian-reviewer" | "feasibility-reviewer" | "slice-implementer" | "slice-documenter" | "release-reviewer" | "planner" | "product-discovery" | "divergent-thinker" | "critic" | "reviewer" | "security-reviewer" | "integration-overseer" | "test-author" | "doc-updater" | "fixer";
24
24
  export type StageSubagentDispatchClass = "stage-specialist" | "worker" | "review-lens";
25
25
  export type StageSubagentReturnSchema = "planning-return" | "product-return" | "critic-return" | "review-return" | "security-return" | "tdd-return" | "docs-return" | "worker-return" | "fixer-return" | "research-return" | "architecture-return" | "spec-validation-return" | "release-return";
26
26
  export interface StageAutoSubagentDispatch {
@@ -62,7 +62,7 @@ export const SPEC = {
62
62
  "Define measurable acceptance criteria.",
63
63
  "Capture constraints, assumptions, and edge cases.",
64
64
  "Review assumptions before finalization: source/confidence, validation path, and accepted/rejected/open disposition.",
65
- "Build Acceptance Mapping: AC -> design decision -> observable evidence -> verification method -> likely test level.",
65
+ "Annotate parallel-slice metadata on each acceptance criterion: `parallelSafe` (true|false) and `touchSurface` (repo-relative paths/modules expected to change) so downstream plan units and TDD lanes stay conflict-aware (v6.13.0).",
66
66
  "Confirm every verification method is concrete enough for plan/TDD to use later.",
67
67
  "Present acceptance criteria to the user in 3-5-item batches, pausing for explicit ACK between batches (see Interaction Protocol).",
68
68
  "Write spec artifact and request approval."
@@ -118,7 +118,7 @@ export const SPEC = {
118
118
  },
119
119
  artifactValidation: [
120
120
  { section: "Upstream Handoff", required: false, validationRule: "Summarizes scope/design decisions, constraints, open questions, and explicit drift before acceptance criteria." },
121
- { section: "Acceptance Criteria", required: true, validationRule: "Each criterion is observable, measurable, and falsifiable. Standard track should include Requirement Ref and Design Decision Ref columns; quick track may instead link each AC to the reproduction contract or bug slice. AC IDs (AC-1, AC-2…) are stable across revisions — dropped ACs stay with Priority `DROPPED`." },
121
+ { section: "Acceptance Criteria", required: true, validationRule: "Each criterion is observable, measurable, and falsifiable. Standard track should include Requirement Ref and Design Decision Ref columns; quick track may instead link each AC to the reproduction contract or bug slice. AC IDs (AC-1, AC-2…) are stable across revisions — dropped ACs stay with Priority `DROPPED`. v6.13.0: each AC declares `parallelSafe` (true|false) and `touchSurface` (paths/modules) for parallel slice planning." },
122
122
  { section: "Quick Reproduction Contract", required: false, validationRule: "Quick bug-fix specs own the reproduction contract: symptom, repro steps, expected RED test behavior, and acceptance criterion." },
123
123
  { section: "Edge Cases", required: true, validationRule: "At least one boundary and one error condition per criterion." },
124
124
  { section: "Constraints and Assumptions", required: false, validationRule: "Constraints are CARRIED FORWARD from scope's `## Scope Contract > Constraints` (cite with `See scope: <ref>` or copy with attribution). New spec-stage constraints (rare) get a citation to the spec-stage Q&A row that surfaced them. Assumptions are owned by `## Assumptions Before Finalization` — do NOT duplicate them here. Section may be `- See scope: 02-scope.md#constraints.` for the common case." },
@@ -49,8 +49,9 @@ export const TDD = {
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
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): when `discoveryMode === \"deep\"` is active, dispatch `slice-documenter --slice S-<id> --phase doc` IN PARALLEL with `slice-implementer` for the same slice. The documenter only writes `<artifacts-dir>/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.",
53
- "Record evidencecapture 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.",
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 paths 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`). v6.13.0: documenter output may remain `provisional` until GREEN evidence exists; finalize the slice file after GREEN is recorded.",
53
+ "## Wave Batch Mode (v6.13+) (A) RED checkpoint across all wave members before any GREEN in that wave. (B) Parallel implementer+documenter fan-out across multiple slices when paths are disjoint and claims/leases are valid (`--claim-token`, `--lane-id`, `--lease-until`). (C) Per-lane REFACTOR or refactor-deferred. (D) Deterministic git fan-in at TDD stage-complete merges lane diffs with `git apply --3way`; unresolved conflicts block advance until `--phase resolve-conflict` succeeds.",
54
+ "**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
55
  "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
56
  "**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
57
  "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).",
@@ -62,7 +63,7 @@ export const TDD = {
62
63
  "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
64
  "Before writing RED tests, discover relevant existing tests and commands so the new test extends the suite instead of fighting it.",
64
65
  "Before implementation, perform a system-wide impact check across callbacks, state, interfaces, schemas, and external contracts touched by the slice.",
65
- "Slice-documenter (Phase C, opt-in / mandatory on discoveryMode=deep): 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.",
66
+ "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`).",
66
67
  "Run source/test preflight using configured TDD path patterns where feasible; if path classification is impossible (generated files, non-file side effect), record why.",
67
68
  "Write behavior-focused tests before changing implementation (RED).",
68
69
  "Capture and store failing output as RED evidence.",
@@ -109,16 +110,16 @@ export const TDD = {
109
110
  "Relevant existing test files, helpers, fixtures, and exact commands identified before RED.",
110
111
  "Callbacks, state transitions, interfaces, schemas, and contracts checked for impact before implementation.",
111
112
  "Execution posture and vertical-slice RED/GREEN/REFACTOR checkpoint plan recorded, including commit boundaries when the repo workflow supports them.",
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). Legacy `## Watched-RED Proof` / `## RED Evidence` markdown tables remain valid as a fallback.",
113
- "GREEN observability: a `phase=green` event in `delegation-events.jsonl` per slice whose `completedTs` >= the matching `phase=red` `completedTs` and whose evidenceRefs name the failing-now-passing test. Legacy `## GREEN Evidence` block remains valid as a fallback.",
113
+ "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.",
114
+ "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
115
  "REFACTOR observability: per slice, a `phase=refactor` event OR a `phase=refactor-deferred` event whose evidenceRefs / refactor rationale captures why refactor was deferred.",
116
+ "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.",
115
117
  "Fresh verification evidence recorded with command, PASS/FAIL status, and commit SHA or no-VCS reason plus content/artifact hash before completion.",
116
118
  "Iron Law Acknowledgement section explicitly states `Acknowledged: yes`.",
117
119
  "Acceptance mapping documented.",
118
120
  "Failure reason analysis recorded.",
119
121
  "Refactor rationale captured.",
120
- "Traceability to task identifier is documented.",
121
- "On discoveryMode=deep: per slice, a `phase=doc` event from `slice-documenter` whose evidenceRefs name `<artifacts-dir>/tdd-slices/S-<id>.md`. On other discovery modes the documenter event is advisory."
122
+ "Traceability to task identifier is documented."
122
123
  ],
123
124
  inputs: ["approved plan slice", "spec acceptance criterion", "test harness configuration", "coding standards and constraints"],
124
125
  requiredContext: ["plan artifact", "spec artifact", "existing test patterns", "affected contracts and state boundaries"],
@@ -739,11 +739,11 @@ ${renderBehaviorAnchorTemplateLine("spec")}
739
739
  - Drift from upstream (or \`None\`):
740
740
 
741
741
  ## Acceptance Criteria
742
- | ID | Requirement Ref (R#) | Criterion (observable/measurable/falsifiable) | Design Decision Ref (D-XX) |
743
- |---|---|---|---|
744
- | AC-1 | R1 | | |
742
+ | ID | Requirement Ref (R#) | Criterion (observable/measurable/falsifiable) | Design Decision Ref (D-XX) | parallelSafe (true/false) | touchSurface (paths/modules) |
743
+ |---|---|---|---|---|---|
744
+ | AC-1 | R1 | | | false | |
745
745
 
746
- > Standard ACs reference at least one \`R#\` from \`02-scope.md\`. Quick-track ACs may instead put \`Quick Reproduction Contract\` / bug-slice refs in the Requirement Ref column and \`N/A\` for Design Decision Ref. ACs are stable (never renumber): dropped ACs stay with Priority \`DROPPED\`; new ones append with the next free \`AC-#\`.
746
+ > Standard ACs reference at least one \`R#\` from \`02-scope.md\`. Quick-track ACs may instead put \`Quick Reproduction Contract\` / bug-slice refs in the Requirement Ref column and \`N/A\` for Design Decision Ref. ACs are stable (never renumber): dropped ACs stay with Priority \`DROPPED\`; new ones append with the next free \`AC-#\`. **v6.13.0:** \`parallelSafe\` states whether this AC can be proven in parallel with others; \`touchSurface\` lists repo-relative globs or modules this AC is expected to touch (scheduler + slice planning).
747
747
 
748
748
  ## Quick Reproduction Contract
749
749
  > Required for quick bug-fix specs; use \`N/A\` for non-bugfix or standard/medium tracks. TDD turns this contract into the RED reproduction test.
@@ -907,6 +907,12 @@ Execution rule: complete and verify each batch before starting the next batch.
907
907
  > Required structural form per implementation unit. Use ≥1 unit; bite-sized 2-5 minute steps inside each. The linter validates shape, not topic.
908
908
 
909
909
  ### Implementation Unit U-1
910
+ - **id:** U-1
911
+ - **dependsOn:** none
912
+ - **claimedPaths:** (repo-relative, comma-separated globs or files this unit expects to own)
913
+ - **parallelizable:** true
914
+ - **riskTier:** standard
915
+ - **lane:** (optional advisory lane tag for human-readable batching)
910
916
  - **Goal:**
911
917
  - **Requirements (from Spec):**
912
918
  - **Dependencies (other units):**
@@ -1,7 +1,7 @@
1
1
  import { type SubagentFallback } from "./harness-adapters.js";
2
2
  import { type MandatoryDelegationTaskClass } from "./content/stage-schema.js";
3
3
  import type { FlowStage } from "./types.js";
4
- import type { FlowState } from "./flow-state.js";
4
+ import { type FlowState } from "./flow-state.js";
5
5
  export type DelegationMode = "mandatory" | "proactive";
6
6
  export type DelegationStatus = "scheduled" | "launched" | "acknowledged" | "completed" | "failed" | "waived" | "stale";
7
7
  export declare const DELEGATION_DISPATCH_SURFACES: readonly ["claude-task", "cursor-task", "opencode-agent", "codex-agent", "generic-task", "role-switch", "manual"];
@@ -164,9 +164,26 @@ export type DelegationEntry = {
164
164
  * keep in sync with the inline copy in
165
165
  * `src/content/hooks.ts::delegationRecordScript`.
166
166
  */
167
- phase?: "red" | "green" | "refactor" | "refactor-deferred" | "doc";
167
+ phase?: "red" | "green" | "refactor" | "refactor-deferred" | "doc" | "resolve-conflict";
168
+ /**
169
+ * v6.13.0 — opaque token tying scheduled work to terminal lifecycle rows
170
+ * under worktree-first execution (mandatory on new schedules).
171
+ */
172
+ claimToken?: string;
173
+ /** v6.13.0 — lane / worktree id owning the slice checkout. */
174
+ ownerLaneId?: string;
175
+ /** v6.13.0 — ISO lease expiry for reclaim sweeps. */
176
+ leasedUntil?: string;
177
+ /** v6.13.0 — lease bookkeeping for audit + reclaim tooling. */
178
+ leaseState?: "claimed" | "expired" | "released" | "reclaimed";
179
+ /** v6.13.0 — plan unit dependency ids echoed for scheduler diagnostics. */
180
+ dependsOn?: string[];
181
+ /**
182
+ * v6.13.0 — integration branch merge status after deterministic fan-in.
183
+ */
184
+ integrationState?: "pending" | "applied" | "conflict" | "resolved" | "abandoned";
168
185
  };
169
- export declare const DELEGATION_PHASES: readonly ["red", "green", "refactor", "refactor-deferred", "doc"];
186
+ export declare const DELEGATION_PHASES: readonly ["red", "green", "refactor", "refactor-deferred", "doc", "resolve-conflict"];
170
187
  export type DelegationPhase = (typeof DELEGATION_PHASES)[number];
171
188
  export declare const DELEGATION_LEDGER_SCHEMA_VERSION: 3;
172
189
  export type DelegationLedger = {
@@ -191,9 +208,31 @@ export type DelegationEvent = DelegationEntry & {
191
208
  */
192
209
  export declare function isTrustBoundaryPath(filePath: string): boolean;
193
210
  export declare function readDelegationLedger(projectRoot: string): Promise<DelegationLedger>;
211
+ /** Parsed `cclaw_fanin_*` audit rows from `delegation-events.jsonl`. */
212
+ export interface FanInAuditRecord {
213
+ event: "cclaw_fanin_applied" | "cclaw_fanin_conflict" | "cclaw_fanin_resolved" | "cclaw_fanin_abandoned";
214
+ runId?: string;
215
+ laneId?: string;
216
+ sliceIds?: string[];
217
+ integrationBranch?: string;
218
+ details?: string;
219
+ ts: string;
220
+ }
221
+ /**
222
+ * Append a deterministic fan-in audit row (not a delegation lifecycle event).
223
+ */
224
+ export declare function recordCclawFanInAudit(projectRoot: string, params: {
225
+ kind: FanInAuditRecord["event"];
226
+ runId: string;
227
+ laneId: string;
228
+ sliceIds: string[];
229
+ integrationBranch: string;
230
+ details?: string;
231
+ }): Promise<void>;
194
232
  export declare function readDelegationEvents(projectRoot: string): Promise<{
195
233
  events: DelegationEvent[];
196
234
  corruptLines: number[];
235
+ fanInAudits: FanInAuditRecord[];
197
236
  }>;
198
237
  /**
199
238
  * Fold ledger entries to the latest row per `spanId` and keep only spans
@@ -319,12 +358,38 @@ export declare class DispatchCapError extends Error {
319
358
  };
320
359
  });
321
360
  }
361
+ /**
362
+ * v6.13.0 — claim / lease contract violation for worktree-first TDD rows.
363
+ */
364
+ export declare class DispatchClaimInvalidError extends Error {
365
+ constructor(message: string);
366
+ }
322
367
  /**
323
368
  * v6.10.0 (P2) — default cap on active `slice-implementer` spans in a
324
369
  * single TDD run. Aligned with evanflow's parallel cap. Override via
325
370
  * `CCLAW_MAX_PARALLEL_SLICE_IMPLEMENTERS=<int>` (validated `>=1`).
326
371
  */
327
372
  export declare const MAX_PARALLEL_SLICE_IMPLEMENTERS: 5;
373
+ export interface ReadySliceUnit {
374
+ unitId: string;
375
+ sliceId: string;
376
+ dependsOn: string[];
377
+ claimedPaths: string[];
378
+ parallelizable: boolean;
379
+ }
380
+ export interface SelectReadySlicesOptions {
381
+ cap: number;
382
+ completedUnitIds: ReadonlySet<string>;
383
+ activePathHolders: ReadonlyArray<{
384
+ paths: string[];
385
+ }>;
386
+ legacyContinuation: boolean;
387
+ }
388
+ /**
389
+ * Return up to `cap` slice units whose dependsOn are satisfied, avoiding
390
+ * `claimedPaths` intersections with already-selected units and active holders.
391
+ */
392
+ export declare function selectReadySlices(units: ReadySliceUnit[], opts: SelectReadySlicesOptions): ReadySliceUnit[];
328
393
  /**
329
394
  * v6.10.0 (P1) — when scheduling a `slice-implementer` on a TDD stage,
330
395
  * compare `claimedPaths` against every currently active span on the
@@ -369,6 +434,11 @@ export declare function validateFanOutCap(stamped: DelegationEntry, activeEntrie
369
434
  */
370
435
  export declare function findActiveSpanForPair(stage: string, agent: string, runId: string, ledger: DelegationLedger): DelegationEntry | null;
371
436
  export declare function appendDelegation(projectRoot: string, entry: DelegationEntry): Promise<void>;
437
+ /**
438
+ * Scan delegation events for expired `leasedUntil` timestamps and append
439
+ * best-effort `cclaw_slice_lease_expired` audit rows (one per span/slice key).
440
+ */
441
+ export declare function reclaimExpiredDelegationClaims(projectRoot: string, now?: Date): Promise<number>;
372
442
  /**
373
443
  * Aggregate the fulfillment mode cclaw expects for the active harness set.
374
444
  * Priority native > generic-dispatch > role-switch > waiver — the best