cclaw-cli 6.14.4 → 7.0.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 (86) hide show
  1. package/README.md +0 -2
  2. package/dist/artifact-linter/brainstorm.js +1 -1
  3. package/dist/artifact-linter/design.js +2 -2
  4. package/dist/artifact-linter/findings-dedup.js +1 -1
  5. package/dist/artifact-linter/plan.js +6 -6
  6. package/dist/artifact-linter/review-army.d.ts +1 -1
  7. package/dist/artifact-linter/review-army.js +1 -1
  8. package/dist/artifact-linter/scope.js +6 -6
  9. package/dist/artifact-linter/shared.d.ts +37 -73
  10. package/dist/artifact-linter/shared.js +30 -37
  11. package/dist/artifact-linter/spec.js +1 -1
  12. package/dist/artifact-linter/tdd.d.ts +20 -33
  13. package/dist/artifact-linter/tdd.js +89 -639
  14. package/dist/artifact-linter.js +11 -32
  15. package/dist/cli.js +1 -1
  16. package/dist/config.js +1 -1
  17. package/dist/constants.js +1 -1
  18. package/dist/content/core-agents.d.ts +8 -26
  19. package/dist/content/core-agents.js +48 -94
  20. package/dist/content/examples.d.ts +1 -1
  21. package/dist/content/examples.js +4 -4
  22. package/dist/content/hooks.js +62 -149
  23. package/dist/content/idea.js +2 -2
  24. package/dist/content/iron-laws.js +1 -1
  25. package/dist/content/node-hooks.js +2 -2
  26. package/dist/content/skills-elicitation.js +2 -2
  27. package/dist/content/skills.d.ts +4 -6
  28. package/dist/content/skills.js +14 -53
  29. package/dist/content/stage-schema.d.ts +3 -3
  30. package/dist/content/stage-schema.js +8 -46
  31. package/dist/content/stages/brainstorm.js +5 -5
  32. package/dist/content/stages/plan.js +2 -2
  33. package/dist/content/stages/review.js +1 -1
  34. package/dist/content/stages/schema-types.d.ts +1 -1
  35. package/dist/content/stages/scope.js +1 -1
  36. package/dist/content/stages/spec.js +2 -2
  37. package/dist/content/stages/tdd.js +43 -108
  38. package/dist/content/start-command.js +3 -3
  39. package/dist/content/subagent-context-skills.js +5 -3
  40. package/dist/content/subagents.js +13 -74
  41. package/dist/content/templates.d.ts +6 -6
  42. package/dist/content/templates.js +23 -24
  43. package/dist/content/utility-skills.d.ts +1 -1
  44. package/dist/content/utility-skills.js +1 -1
  45. package/dist/delegation.d.ts +79 -139
  46. package/dist/delegation.js +83 -215
  47. package/dist/early-loop.js +1 -1
  48. package/dist/flow-state.d.ts +24 -129
  49. package/dist/flow-state.js +5 -30
  50. package/dist/gate-evidence.d.ts +2 -7
  51. package/dist/gate-evidence.js +2 -59
  52. package/dist/harness-adapters.d.ts +1 -1
  53. package/dist/harness-adapters.js +11 -10
  54. package/dist/install.js +24 -459
  55. package/dist/internal/advance-stage/advance.d.ts +5 -5
  56. package/dist/internal/advance-stage/advance.js +9 -24
  57. package/dist/internal/advance-stage/parsers.d.ts +1 -1
  58. package/dist/internal/advance-stage/review-loop.d.ts +1 -1
  59. package/dist/internal/advance-stage/review-loop.js +3 -3
  60. package/dist/internal/advance-stage/start-flow.js +1 -3
  61. package/dist/internal/advance-stage.js +4 -23
  62. package/dist/internal/cohesion-contract-stub.d.ts +8 -13
  63. package/dist/internal/cohesion-contract-stub.js +18 -24
  64. package/dist/internal/flow-state-repair.d.ts +1 -1
  65. package/dist/internal/plan-split-waves.d.ts +18 -21
  66. package/dist/internal/plan-split-waves.js +16 -19
  67. package/dist/internal/wave-status.d.ts +3 -6
  68. package/dist/internal/wave-status.js +5 -27
  69. package/dist/policy.js +1 -1
  70. package/dist/run-persistence.js +10 -44
  71. package/dist/runtime/run-hook.mjs +3 -3
  72. package/dist/track-heuristics.js +1 -1
  73. package/dist/types.d.ts +2 -2
  74. package/package.json +1 -1
  75. package/dist/integration-fanin.d.ts +0 -44
  76. package/dist/integration-fanin.js +0 -180
  77. package/dist/internal/set-checkpoint-mode.d.ts +0 -16
  78. package/dist/internal/set-checkpoint-mode.js +0 -72
  79. package/dist/internal/set-integration-overseer-mode.d.ts +0 -14
  80. package/dist/internal/set-integration-overseer-mode.js +0 -69
  81. package/dist/internal/set-worktree-mode.d.ts +0 -10
  82. package/dist/internal/set-worktree-mode.js +0 -28
  83. package/dist/worktree-manager.d.ts +0 -50
  84. package/dist/worktree-manager.js +0 -136
  85. package/dist/worktree-types.d.ts +0 -36
  86. package/dist/worktree-types.js +0 -6
@@ -2,7 +2,7 @@ import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { resolveArtifactPath } from "../../artifact-paths.js";
4
4
  import { appendDelegation, checkMandatoryDelegations, readDelegationEvents, readDelegationLedger } from "../../delegation.js";
5
- import { verifyCompletedStagesGateClosure, verifyCurrentStageGateEvidence, verifyTddWorktreeFanInClosure } from "../../gate-evidence.js";
5
+ import { verifyCompletedStagesGateClosure, verifyCurrentStageGateEvidence } from "../../gate-evidence.js";
6
6
  import { extractMarkdownSectionBody, learningsParseFailureHumanSummary, parseLearningsSection } from "../../artifact-linter.js";
7
7
  import { getAvailableTransitions, getTransitionGuards } from "../../flow-state.js";
8
8
  import { appendKnowledge } from "../../knowledge-store.js";
@@ -13,7 +13,6 @@ import { unique } from "./helpers.js";
13
13
  import { AUTO_REVIEW_LOOP_GATE_BY_STAGE, reviewLoopArtifactFixHint, reviewLoopEnvelopeExample, validateGateEvidenceShape } from "./review-loop.js";
14
14
  import { ensureProactiveDelegationTrace } from "./proactive-delegation-trace.js";
15
15
  import { consumeWaiverToken } from "../waiver-grant.js";
16
- import { runTddDeterministicFanInBeforeAdvance } from "../../integration-fanin.js";
17
16
  function resolveSuccessorTransition(stage, track, transitionTargets, satisfiedGuards, selectedTransitionGuards) {
18
17
  const natural = transitionTargets[0] ?? null;
19
18
  const specialTargets = transitionTargets.filter((target) => target !== natural);
@@ -60,16 +59,16 @@ function nextInteractionHints(flowState, args, successor) {
60
59
  return hints;
61
60
  }
62
61
  /**
63
- * Wave 24 entry point — auto-hydrate evidence for an auto-hydratable
62
+ * entry point — auto-hydrate evidence for an auto-hydratable
64
63
  * gate that the agent already included in --passed but for which they
65
64
  * forgot to provide --evidence-json. Returns silently when no
66
65
  * hydration is possible (no auto-hydratable gate, no artifact, no
67
66
  * envelope, etc.).
68
67
  *
69
- * Wave 25 (v6.1.0) layered `tryAutoHydrateAndSelectReviewLoopGate` on
68
+ * layered `tryAutoHydrateAndSelectReviewLoopGate` on
70
69
  * top of this so the gate is also auto-included in selectedGateIds
71
70
  * when the artifact yields a valid envelope. Together the two helpers
72
- * remove the contradiction the user reported in Wave 24:
71
+ * remove the contradiction:
73
72
  * - "omit this gate from --evidence-json so stage-complete can
74
73
  * auto-hydrate it" → "missing --evidence-json entries for passed
75
74
  * gates: design_diagram_freshness".
@@ -105,7 +104,7 @@ export async function hydrateReviewLoopEvidenceFromArtifact(projectRoot, stage,
105
104
  evidenceByGate[gateId] = JSON.stringify(envelope);
106
105
  }
107
106
  /**
108
- * Wave 25 (v6.1.0) — auto-include an auto-hydratable review-loop gate
107
+ * auto-include an auto-hydratable review-loop gate
109
108
  * in `selectedGateIds` when:
110
109
  * - The stage has an auto-hydratable gate registered via
111
110
  * `AUTO_REVIEW_LOOP_GATE_BY_STAGE` (currently `design`).
@@ -162,7 +161,7 @@ export async function tryAutoHydrateAndSelectReviewLoopGate(projectRoot, stage,
162
161
  return [...selectedGateIds, gateId];
163
162
  }
164
163
  export async function buildValidationReport(projectRoot, flowState, options = {}) {
165
- // Wave 24 follow-up (v6.1.1): forward `flowState.taskClass` so the
164
+ // forward `flowState.taskClass` so the
166
165
  // bugfix-skip lights up via the `cclaw advance-stage` path. The
167
166
  // delegation helper now has its own fallback (it reads `flowState`
168
167
  // internally), but threading the value here keeps the call site
@@ -314,11 +313,11 @@ export async function runAdvanceStage(projectRoot, args, io) {
314
313
  let selectedGateIds = args.passedGateIds.length > 0
315
314
  ? args.passedGateIds.filter((gateId) => selectableGateIds.has(gateId))
316
315
  : requiredGateIds;
317
- // Wave 25 (v6.1.0): if the active stage has an auto-hydratable
316
+ // if the active stage has an auto-hydratable
318
317
  // review-loop gate (currently `design.design_architecture_locked`)
319
318
  // and the artifact already contains a valid review-loop envelope,
320
319
  // include the gate in selectedGateIds and hydrate evidence in one
321
- // step. This removes the Wave 24 contradiction between "omit from
320
+ // step. This removes the contradiction between "omit from
322
321
  // --evidence-json so we can auto-hydrate" and "missing
323
322
  // --evidence-json entries for passed gates".
324
323
  selectedGateIds = await tryAutoHydrateAndSelectReviewLoopGate(projectRoot, args.stage, flowState.track, requiredGateIds, selectedGateIds, args.evidenceByGate);
@@ -363,7 +362,7 @@ export async function runAdvanceStage(projectRoot, args, io) {
363
362
  });
364
363
  }
365
364
  }
366
- // Wave 25 (v6.1.0): hydration + auto-select happens earlier via
365
+ // hydration + auto-select happens earlier via
367
366
  // `tryAutoHydrateAndSelectReviewLoopGate`. The previous explicit
368
367
  // call here was redundant (helper already covered both the
369
368
  // already-selected and not-yet-selected paths).
@@ -603,20 +602,6 @@ export async function runAdvanceStage(projectRoot, args, io) {
603
602
  }
604
603
  const satisfiedGuards = new Set([...nextPassed, ...selectedTransitionGuards]);
605
604
  const successor = resolveSuccessorTransition(args.stage, flowState.track, transitionTargets, satisfiedGuards, new Set(selectedTransitionGuards));
606
- if (args.stage === "tdd" && successor !== null && successor !== "tdd") {
607
- const fanIn = await runTddDeterministicFanInBeforeAdvance(projectRoot, flowState);
608
- if (!fanIn.ok) {
609
- io.stderr.write(`cclaw internal advance-stage: deterministic worktree fan-in failed:\n${fanIn.issues
610
- .map((line) => ` - ${line}`)
611
- .join("\n")}\n`);
612
- return 1;
613
- }
614
- const closure = await verifyTddWorktreeFanInClosure(projectRoot, flowState);
615
- if (closure.length > 0) {
616
- io.stderr.write(`cclaw internal advance-stage: ${closure.join(" | ")}\n`);
617
- return 1;
618
- }
619
- }
620
605
  const completedStages = blockedReviewRoute
621
606
  ? flowState.completedStages.filter((finished) => finished !== args.stage)
622
607
  : flowState.completedStages.includes(args.stage)
@@ -49,7 +49,7 @@ export interface StartFlowArgs {
49
49
  reclassify: boolean;
50
50
  quiet: boolean;
51
51
  /**
52
- * Wave 23 (v5.0.0) — `/cc-ideate` handoff carry-forward.
52
+ * `/cc-ideate` handoff carry-forward.
53
53
  * Workspace-relative POSIX path to `.cclaw/ideas/idea-YYYY-MM-DD-<slug>.md`
54
54
  * (or wherever `/cc-ideate` wrote its artifact).
55
55
  */
@@ -1,7 +1,7 @@
1
1
  import type { FlowStage } from "../../types.js";
2
2
  export declare const AUTO_REVIEW_LOOP_GATE_BY_STAGE: Partial<Record<FlowStage, string>>;
3
3
  /**
4
- * Wave 25 (v6.1.0) — exact JSON shape that gate-evidence validators
4
+ * exact JSON shape that gate-evidence validators
5
5
  * accept for a review-loop envelope. The error messages emitted by
6
6
  * `validateReviewLoopGateEvidence` always include this example so the
7
7
  * agent never has to guess where `stage` lives (top-level of the
@@ -12,7 +12,7 @@ const REVIEW_LOOP_STOP_REASONS = new Set([
12
12
  "user_opt_out"
13
13
  ]);
14
14
  /**
15
- * Wave 25 (v6.1.0) — exact JSON shape that gate-evidence validators
15
+ * exact JSON shape that gate-evidence validators
16
16
  * accept for a review-loop envelope. The error messages emitted by
17
17
  * `validateReviewLoopGateEvidence` always include this example so the
18
18
  * agent never has to guess where `stage` lives (top-level of the
@@ -183,9 +183,9 @@ export async function validateGateEvidenceShape(projectRoot, stage, gateId, evid
183
183
  export function reviewLoopArtifactFixHint(stage, gateId) {
184
184
  if (AUTO_REVIEW_LOOP_GATE_BY_STAGE[stage] !== gateId)
185
185
  return "";
186
- // Wave 25 (v6.1.0): the consistent flow is "include the gate in
186
+ // the consistent flow is "include the gate in
187
187
  // --passed AND let stage-complete auto-hydrate evidence from the
188
- // artifact". Wave 24's hint told agents to omit the gate from
188
+ // artifact". An older hint told agents to omit the gate from
189
189
  // --evidence-json, but they then hit
190
190
  // `missing --evidence-json entries for passed gates: <gateId>`
191
191
  // because hydration only runs when --evidence-json is also present
@@ -175,8 +175,7 @@ export async function runStartFlow(projectRoot, args, io) {
175
175
  guardEvidence,
176
176
  stageGateCatalog,
177
177
  rewinds: current.rewinds,
178
- staleStages: current.staleStages,
179
- worktreeExecutionMode: current.worktreeExecutionMode ?? "worktree-first"
178
+ staleStages: current.staleStages
180
179
  };
181
180
  const validation = await buildValidationReport(projectRoot, nextState);
182
181
  const evidenceIssues = completedStageClosureEvidenceIssues(nextState);
@@ -194,7 +193,6 @@ export async function runStartFlow(projectRoot, args, io) {
194
193
  if (nextTaskClass !== undefined) {
195
194
  nextState = { ...nextState, taskClass: nextTaskClass };
196
195
  }
197
- nextState = { ...nextState, worktreeExecutionMode: "worktree-first" };
198
196
  }
199
197
  if (args.fromIdeaArtifact) {
200
198
  const existingHints = nextState.interactionHints ?? {};
@@ -14,11 +14,8 @@ import { parseAdvanceStageArgs, parseCancelRunArgs, parseHookArgs, parseRewindAr
14
14
  import { parseFlowStateRepairArgs, runFlowStateRepair } from "./flow-state-repair.js";
15
15
  import { parseWaiverGrantArgs, runWaiverGrant } from "./waiver-grant.js";
16
16
  import { FlowStateGuardMismatchError, verifyFlowStateGuard } from "../run-persistence.js";
17
- import { DelegationTimestampError, DispatchCapError, DispatchClaimInvalidError, DispatchDuplicateError, DispatchOverlapError } from "../delegation.js";
17
+ import { DelegationTimestampError, DispatchCapError, DispatchDuplicateError, DispatchOverlapError } from "../delegation.js";
18
18
  import { parsePlanSplitWavesArgs, runPlanSplitWaves } from "./plan-split-waves.js";
19
- import { runSetWorktreeMode } from "./set-worktree-mode.js";
20
- import { runSetCheckpointMode } from "./set-checkpoint-mode.js";
21
- import { runSetIntegrationOverseerMode } from "./set-integration-overseer-mode.js";
22
19
  import { runWaveStatusCommand } from "./wave-status.js";
23
20
  import { runCohesionContractCommand } from "./cohesion-contract-stub.js";
24
21
  /**
@@ -33,15 +30,12 @@ const GUARD_ENFORCED_SUBCOMMANDS = new Set([
33
30
  "cancel-run",
34
31
  "rewind",
35
32
  "verify-flow-state-diff",
36
- "verify-current-state",
37
- "set-worktree-mode",
38
- "set-checkpoint-mode",
39
- "set-integration-overseer-mode"
33
+ "verify-current-state"
40
34
  ]);
41
35
  export async function runInternalCommand(projectRoot, argv, io) {
42
36
  const [subcommand, ...tokens] = argv;
43
37
  if (!subcommand) {
44
- 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 | set-worktree-mode | set-checkpoint-mode | set-integration-overseer-mode | wave-status | cohesion-contract\n");
38
+ 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 | wave-status | cohesion-contract\n");
45
39
  return 1;
46
40
  }
47
41
  try {
@@ -96,22 +90,13 @@ export async function runInternalCommand(projectRoot, argv, io) {
96
90
  if (subcommand === "plan-split-waves") {
97
91
  return await runPlanSplitWaves(projectRoot, parsePlanSplitWavesArgs(tokens), io);
98
92
  }
99
- if (subcommand === "set-worktree-mode") {
100
- return await runSetWorktreeMode(projectRoot, tokens, io);
101
- }
102
- if (subcommand === "set-checkpoint-mode") {
103
- return await runSetCheckpointMode(projectRoot, tokens, io);
104
- }
105
- if (subcommand === "set-integration-overseer-mode") {
106
- return await runSetIntegrationOverseerMode(projectRoot, tokens, io);
107
- }
108
93
  if (subcommand === "wave-status") {
109
94
  return await runWaveStatusCommand(projectRoot, tokens, io);
110
95
  }
111
96
  if (subcommand === "cohesion-contract") {
112
97
  return await runCohesionContractCommand(projectRoot, tokens, io);
113
98
  }
114
- 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 | set-worktree-mode | set-checkpoint-mode | set-integration-overseer-mode | wave-status | cohesion-contract\n`);
99
+ 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 | wave-status | cohesion-contract\n`);
115
100
  return 1;
116
101
  }
117
102
  catch (err) {
@@ -135,10 +120,6 @@ export async function runInternalCommand(projectRoot, argv, io) {
135
120
  io.stderr.write(`error: dispatch_cap — ${err.message}\n`);
136
121
  return 2;
137
122
  }
138
- if (err instanceof DispatchClaimInvalidError) {
139
- io.stderr.write(`error: dispatch_claim_invalid — ${err.message}\n`);
140
- return 2;
141
- }
142
123
  io.stderr.write(`cclaw internal ${subcommand} failed: ${err instanceof Error ? err.message : String(err)}\n`);
143
124
  return 1;
144
125
  }
@@ -10,20 +10,15 @@ export interface CohesionContractArgs {
10
10
  }
11
11
  export declare function parseCohesionContractArgs(tokens: string[]): CohesionContractArgs | null;
12
12
  /**
13
- * v6.14.2 — emit a minimal advisory cohesion contract that satisfies
14
- * the linter shape check (`cohesion-contract.{md,json}`) so projects
15
- * with `legacyContinuation: true` and 2 completed slice-implementer
16
- * rows can clear the soft `tdd.cohesion_contract_missing` finding
17
- * without hand-authoring the document.
13
+ * Scaffold a minimal cohesion-contract pair (`cohesion-contract.{md,json}`)
14
+ * so authors have a starting point when a multi-slice wave needs cross-slice
15
+ * cohesion documentation. The stub seeds `sharedTypes`, `touchpoints`, and
16
+ * `slices` from the active run delegation ledger and carries
17
+ * `status.verdict: "scaffold"` so reviewers know to fill in the real content
18
+ * before treating it as authoritative.
18
19
  *
19
- * The stub is intentionally bare `sharedTypes`, `touchpoints`, and
20
- * `slices` are populated from the active run delegation ledger so
21
- * downstream tooling can see which slices the contract acknowledges,
22
- * but the contract carries `status.verdict: "advisory_legacy"` so
23
- * reviewers know not to treat it as authoritative.
24
- *
25
- * Refuses to overwrite an existing contract unless `--force` is
26
- * passed; the existing file is treated as authored work.
20
+ * Refuses to overwrite an existing contract unless `--force` is passed; the
21
+ * existing file is treated as authored work.
27
22
  */
28
23
  export declare function runCohesionContractCommand(projectRoot: string, tokens: string[], io: InternalIo): Promise<number>;
29
24
  export {};
@@ -2,7 +2,7 @@ import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { RUNTIME_ROOT } from "../constants.js";
4
4
  import { writeFileSafe } from "../fs-utils.js";
5
- import { readDelegationLedger } from "../delegation.js";
5
+ import { readDelegationLedger, isParallelTddSliceWorker } from "../delegation.js";
6
6
  export function parseCohesionContractArgs(tokens) {
7
7
  const args = { stub: false, force: false, reason: null };
8
8
  for (const token of tokens) {
@@ -27,20 +27,15 @@ export function parseCohesionContractArgs(tokens) {
27
27
  return args;
28
28
  }
29
29
  /**
30
- * v6.14.2 — emit a minimal advisory cohesion contract that satisfies
31
- * the linter shape check (`cohesion-contract.{md,json}`) so projects
32
- * with `legacyContinuation: true` and 2 completed slice-implementer
33
- * rows can clear the soft `tdd.cohesion_contract_missing` finding
34
- * without hand-authoring the document.
30
+ * Scaffold a minimal cohesion-contract pair (`cohesion-contract.{md,json}`)
31
+ * so authors have a starting point when a multi-slice wave needs cross-slice
32
+ * cohesion documentation. The stub seeds `sharedTypes`, `touchpoints`, and
33
+ * `slices` from the active run delegation ledger and carries
34
+ * `status.verdict: "scaffold"` so reviewers know to fill in the real content
35
+ * before treating it as authoritative.
35
36
  *
36
- * The stub is intentionally bare `sharedTypes`, `touchpoints`, and
37
- * `slices` are populated from the active run delegation ledger so
38
- * downstream tooling can see which slices the contract acknowledges,
39
- * but the contract carries `status.verdict: "advisory_legacy"` so
40
- * reviewers know not to treat it as authoritative.
41
- *
42
- * Refuses to overwrite an existing contract unless `--force` is
43
- * passed; the existing file is treated as authored work.
37
+ * Refuses to overwrite an existing contract unless `--force` is passed; the
38
+ * existing file is treated as authored work.
44
39
  */
45
40
  export async function runCohesionContractCommand(projectRoot, tokens, io) {
46
41
  const parsed = parseCohesionContractArgs(tokens);
@@ -63,13 +58,12 @@ export async function runCohesionContractCommand(projectRoot, tokens, io) {
63
58
  const sliceIds = collectSliceIds(ledger?.entries ?? []);
64
59
  const reasonNote = parsed.reason
65
60
  ? `Reason: ${parsed.reason}`
66
- : "Reason: legacyContinuation auto-stub.";
61
+ : "Reason: scaffold for a multi-slice wave that needs cohesion documentation.";
67
62
  const md = [
68
63
  "# Cohesion Contract",
69
64
  "",
70
- "_Advisory stub generated by `cclaw-cli internal cohesion-contract --stub`._",
71
- "_Status: `advisory_legacy` — populated for legacyContinuation projects so the_",
72
- "_TDD linter does not block stage-complete on `tdd.cohesion_contract_missing`._",
65
+ "_Scaffold generated by `cclaw-cli internal cohesion-contract --stub`._",
66
+ "_Status: `scaffold` — replace placeholders with real cross-slice data before review._",
73
67
  "",
74
68
  `${reasonNote}`,
75
69
  "",
@@ -110,21 +104,21 @@ export async function runCohesionContractCommand(projectRoot, tokens, io) {
110
104
  touchpoints: [],
111
105
  slices: sliceIds.map((sid) => ({
112
106
  sliceId: sid,
113
- description: `Stub entry for ${sid}; advisory under legacyContinuation.`,
107
+ description: `Scaffold entry for ${sid}; replace with real behavior summary.`,
114
108
  implemented: true,
115
109
  testsPass: true,
116
110
  cohesionVerified: false
117
111
  })),
118
112
  status: {
119
- verdict: "advisory_legacy",
113
+ verdict: "scaffold",
120
114
  generatedBy: "cclaw-cli internal cohesion-contract --stub",
121
- reason: parsed.reason ?? "legacyContinuation auto-stub"
115
+ reason: parsed.reason ?? "scaffold for a multi-slice wave"
122
116
  }
123
117
  };
124
118
  await writeFileSafe(mdPath, md);
125
119
  await writeFileSafe(jsonPath, `${JSON.stringify(jsonStub, null, 2)}\n`);
126
- io.stdout.write(`cclaw: cohesion-contract stub written (${sliceIds.length} slice(s) referenced). ` +
127
- "Status: advisory_legacyreview and replace once cross-slice cohesion data is real.\n");
120
+ io.stdout.write(`cclaw: cohesion-contract scaffold written (${sliceIds.length} slice(s) referenced). ` +
121
+ "Status: scaffoldreplace placeholders with real cross-slice data.\n");
128
122
  return 0;
129
123
  }
130
124
  async function fileExists(filePath) {
@@ -139,7 +133,7 @@ async function fileExists(filePath) {
139
133
  function collectSliceIds(entries) {
140
134
  const set = new Set();
141
135
  for (const entry of entries) {
142
- if (entry.agent !== "slice-implementer")
136
+ if (!isParallelTddSliceWorker(entry.agent ?? ""))
143
137
  continue;
144
138
  if (entry.status !== "completed")
145
139
  continue;
@@ -8,7 +8,7 @@ export interface FlowStateRepairArgs {
8
8
  json: boolean;
9
9
  quiet: boolean;
10
10
  /**
11
- * v6.9.0 — when true, normalize `state/early-loop.json` to the canonical
11
+ * when true, normalize `state/early-loop.json` to the canonical
12
12
  * shape derived from `early-loop-log.jsonl`. Lets operators recover from
13
13
  * legacy hand-written `early-loop.json` files that drifted from the
14
14
  * source-of-truth log.
@@ -4,7 +4,7 @@ interface InternalIo {
4
4
  stderr: Writable;
5
5
  }
6
6
  /**
7
- * v6.10.0 (P3) — split a large `05-plan.md` Implementation Units section
7
+ * split a large `05-plan.md` Implementation Units section
8
8
  * into wave-NN.md sub-files so an executor can carry one wave at a time
9
9
  * without re-reading the whole plan.
10
10
  *
@@ -31,7 +31,7 @@ export interface PlanSplitWavesArgs {
31
31
  }
32
32
  export declare const PLAN_SPLIT_DEFAULT_WAVE_SIZE = 5;
33
33
  export declare const PLAN_SPLIT_SMALL_PLAN_THRESHOLD = 50;
34
- /** v6.13.1 — member line in Parallel Execution Plan or wave-NN.md */
34
+ /** Member line in Parallel Execution Plan or wave-NN.md */
35
35
  export interface ParsedParallelWaveMember {
36
36
  sliceId: string;
37
37
  unitId: string;
@@ -57,11 +57,10 @@ export declare function extractParallelExecutionManagedBody(planMarkdown: string
57
57
  */
58
58
  export declare function extractMembersListFromLine(trimmedLine: string): string | null;
59
59
  /**
60
- * v6.14.4 — extract a `(sliceId, unitId)` pair from a markdown table data
61
- * row whose first column is an `S-NN` token. Used by the wave parser to
62
- * recognize the table-format Parallel Execution Plan that hox-shape
63
- * projects emit alongside (or instead of) the legacy `**Members:**`
64
- * bullet line.
60
+ * Extract a `(sliceId, unitId)` pair from a markdown table data row
61
+ * whose first column is an `S-NN` token. Used by the wave parser to
62
+ * recognize the table-format Parallel Execution Plan alongside (or
63
+ * instead of) the `**Members:**` bullet line.
65
64
  *
66
65
  * Rules:
67
66
  * - The line must start with `|` (after trimming).
@@ -70,25 +69,23 @@ export declare function extractMembersListFromLine(trimmedLine: string): string
70
69
  * silently skipped.
71
70
  * - Column 2, when present and non-empty, becomes the `unitId`
72
71
  * verbatim (after stripping whitespace + backticks/quotes/brackets).
73
- * This preserves the hox convention of recording task ids
74
- * (`T-010`, `T-008a`, …) in the `unit` column without forcing a
75
- * `U-NN` derivation.
76
- * - When column 2 is absent or empty, fall back to the legacy
77
- * `S-NN U-NN` derivation so the existing `**Members:**` parser path
78
- * stays bit-identical for non-table plans.
72
+ * This lets authors record task ids (`T-010`, `T-008a`, …) in the
73
+ * `unit` column without forcing a `U-NN` derivation.
74
+ * - When column 2 is absent or empty, fall back to the
75
+ * `S-NN U-NN` derivation so the `**Members:**` parser path stays
76
+ * bit-identical for non-table plans.
79
77
  */
80
78
  export declare function parseTableRowMember(trimmedLine: string): ParsedParallelWaveMember | null;
81
79
  /**
82
80
  * Parse `## Parallel Execution Plan` managed block for wave headings and
83
- * member declarations. Recognizes BOTH the legacy `**Members:**` /
84
- * `Members:` line shape AND the markdown-table shape
85
- * (`| sliceId | unit | dependsOn | …`) used by hox-shape projects and by
86
- * any plan written by `cclaw-cli sync` after v6.13.x.
81
+ * member declarations. Recognizes BOTH the `**Members:**` / `Members:`
82
+ * line shape AND the markdown-table shape
83
+ * (`| sliceId | unit | dependsOn | …`).
87
84
  *
88
85
  * Wave headings accepted (case-insensitive, trailing text allowed):
89
86
  * - `### Wave 04`
90
87
  * - `### Wave W-04`
91
- * - `### Wave W-04 — после успешного fan-in W-03 (5 lanes …)`
88
+ * - `### Wave W-04 — after fan-in W-03 (5 lanes …)`
92
89
  *
93
90
  * Within a single wave the parser dedupes by `sliceId`: if the same
94
91
  * slice appears in both `**Members:**` and a table row, the first
@@ -138,20 +135,20 @@ export interface ImplementationUnitParallelFields {
138
135
  }
139
136
  export interface ParseImplementationUnitParallelOptions {
140
137
  /**
141
- * Legacy continuation (v6.13.0): when the plan predates explicit parallel
138
+ * Continuation: when the plan predates explicit parallel
142
139
  * bullets, units without a `parallelizable:` line default to serial eligibility
143
140
  * in the scheduler (`parallelizable: false`).
144
141
  */
145
142
  legacyParallelDefaultSerial?: boolean;
146
143
  }
147
144
  /**
148
- * Parse v6.13 parallel-metadata bullets from an implementation unit body.
145
+ * Parse parallel-metadata bullets from an implementation unit body.
149
146
  * Missing keys use conservative defaults (`dependsOn: []`, `parallelizable: true`
150
147
  * unless `legacyParallelDefaultSerial` is set).
151
148
  */
152
149
  export declare function parseImplementationUnitParallelFields(unit: ParsedImplementationUnit, options?: ParseImplementationUnitParallelOptions): ImplementationUnitParallelFields;
153
150
  /**
154
- * True when the plan has implementation units but any unit is missing v6.13.0
151
+ * True when the plan has implementation units but any unit is missing
155
152
  * `dependsOn` / `claimedPaths` / `parallelizable` / `riskTier` bullets.
156
153
  */
157
154
  export declare function planArtifactLacksV613ParallelMetadata(planMarkdown: string): boolean;
@@ -61,11 +61,10 @@ export function extractMembersListFromLine(trimmedLine) {
61
61
  return null;
62
62
  }
63
63
  /**
64
- * v6.14.4 — extract a `(sliceId, unitId)` pair from a markdown table data
65
- * row whose first column is an `S-NN` token. Used by the wave parser to
66
- * recognize the table-format Parallel Execution Plan that hox-shape
67
- * projects emit alongside (or instead of) the legacy `**Members:**`
68
- * bullet line.
64
+ * Extract a `(sliceId, unitId)` pair from a markdown table data row
65
+ * whose first column is an `S-NN` token. Used by the wave parser to
66
+ * recognize the table-format Parallel Execution Plan alongside (or
67
+ * instead of) the `**Members:**` bullet line.
69
68
  *
70
69
  * Rules:
71
70
  * - The line must start with `|` (after trimming).
@@ -74,12 +73,11 @@ export function extractMembersListFromLine(trimmedLine) {
74
73
  * silently skipped.
75
74
  * - Column 2, when present and non-empty, becomes the `unitId`
76
75
  * verbatim (after stripping whitespace + backticks/quotes/brackets).
77
- * This preserves the hox convention of recording task ids
78
- * (`T-010`, `T-008a`, …) in the `unit` column without forcing a
79
- * `U-NN` derivation.
80
- * - When column 2 is absent or empty, fall back to the legacy
81
- * `S-NN U-NN` derivation so the existing `**Members:**` parser path
82
- * stays bit-identical for non-table plans.
76
+ * This lets authors record task ids (`T-010`, `T-008a`, …) in the
77
+ * `unit` column without forcing a `U-NN` derivation.
78
+ * - When column 2 is absent or empty, fall back to the
79
+ * `S-NN U-NN` derivation so the `**Members:**` parser path stays
80
+ * bit-identical for non-table plans.
83
81
  */
84
82
  export function parseTableRowMember(trimmedLine) {
85
83
  if (!trimmedLine.startsWith("|"))
@@ -109,15 +107,14 @@ export function parseTableRowMember(trimmedLine) {
109
107
  }
110
108
  /**
111
109
  * Parse `## Parallel Execution Plan` managed block for wave headings and
112
- * member declarations. Recognizes BOTH the legacy `**Members:**` /
113
- * `Members:` line shape AND the markdown-table shape
114
- * (`| sliceId | unit | dependsOn | …`) used by hox-shape projects and by
115
- * any plan written by `cclaw-cli sync` after v6.13.x.
110
+ * member declarations. Recognizes BOTH the `**Members:**` / `Members:`
111
+ * line shape AND the markdown-table shape
112
+ * (`| sliceId | unit | dependsOn | …`).
116
113
  *
117
114
  * Wave headings accepted (case-insensitive, trailing text allowed):
118
115
  * - `### Wave 04`
119
116
  * - `### Wave W-04`
120
- * - `### Wave W-04 — после успешного fan-in W-03 (5 lanes …)`
117
+ * - `### Wave W-04 — after fan-in W-03 (5 lanes …)`
121
118
  *
122
119
  * Within a single wave the parser dedupes by `sliceId`: if the same
123
120
  * slice appears in both `**Members:**` and a table row, the first
@@ -145,7 +142,7 @@ export function parseParallelExecutionPlanWaves(planMarkdown) {
145
142
  };
146
143
  /**
147
144
  * Strict add: throw on duplicates within the same wave OR across waves.
148
- * Used for the `**Members:**` path so v6.13.1's duplicate-detection
145
+ * Used for the `**Members:**` path so the duplicate-detection
149
146
  * contract is preserved bit-identically.
150
147
  */
151
148
  const addMemberStrict = (member) => {
@@ -324,7 +321,7 @@ export function formatNextParallelWaveSyncHint(merged) {
324
321
  return `Parallel Execution Plan: ${candidate.waveId} has ${candidate.members.length} parallel members (${ids}).`;
325
322
  }
326
323
  /**
327
- * Parse v6.13 parallel-metadata bullets from an implementation unit body.
324
+ * Parse parallel-metadata bullets from an implementation unit body.
328
325
  * Missing keys use conservative defaults (`dependsOn: []`, `parallelizable: true`
329
326
  * unless `legacyParallelDefaultSerial` is set).
330
327
  */
@@ -380,7 +377,7 @@ function unitBodyHasV613ParallelBullet(body, label) {
380
377
  });
381
378
  }
382
379
  /**
383
- * True when the plan has implementation units but any unit is missing v6.13.0
380
+ * True when the plan has implementation units but any unit is missing
384
381
  * `dependsOn` / `claimedPaths` / `parallelizable` / `riskTier` bullets.
385
382
  */
386
383
  export function planArtifactLacksV613ParallelMetadata(planMarkdown) {
@@ -21,9 +21,6 @@ export interface WaveStatusNextDispatch {
21
21
  export interface WaveStatusReport {
22
22
  activeRunId: string;
23
23
  currentStage: string;
24
- tddCutoverSliceId: string | null;
25
- tddWorktreeCutoverSliceId: string | null;
26
- legacyContinuation: boolean;
27
24
  waves: WaveStatusWaveSummary[];
28
25
  nextDispatch: WaveStatusNextDispatch;
29
26
  warnings: string[];
@@ -37,11 +34,11 @@ export interface RunWaveStatusOptions {
37
34
  artifactsDir?: string;
38
35
  }
39
36
  /**
40
- * v6.14.2 — deterministic helper for the TDD controller. Reads the
41
- * managed `<!-- parallel-exec-managed-start -->` block from
37
+ * Deterministic helper for the TDD controller. Reads the managed
38
+ * `<!-- parallel-exec-managed-start -->` block from
42
39
  * `<artifacts-dir>/05-plan.md` plus the `wave-plans/` directory and
43
40
  * reports waves + the next dispatchable members so the controller does
44
- * NOT have to page through a 1400-line plan to find the active wave.
41
+ * NOT have to page through a long plan to find the active wave.
45
42
  *
46
43
  * Always exits 0 unless the plan is malformed (no managed block AND no
47
44
  * wave-plans directory), in which case exit 2 with a structured error.
@@ -39,11 +39,11 @@ const TERMINAL_PHASES = new Set([
39
39
  "resolve-conflict"
40
40
  ]);
41
41
  /**
42
- * v6.14.2 — deterministic helper for the TDD controller. Reads the
43
- * managed `<!-- parallel-exec-managed-start -->` block from
42
+ * Deterministic helper for the TDD controller. Reads the managed
43
+ * `<!-- parallel-exec-managed-start -->` block from
44
44
  * `<artifacts-dir>/05-plan.md` plus the `wave-plans/` directory and
45
45
  * reports waves + the next dispatchable members so the controller does
46
- * NOT have to page through a 1400-line plan to find the active wave.
46
+ * NOT have to page through a long plan to find the active wave.
47
47
  *
48
48
  * Always exits 0 unless the plan is malformed (no managed block AND no
49
49
  * wave-plans directory), in which case exit 2 with a structured error.
@@ -53,9 +53,6 @@ export async function runWaveStatus(projectRoot, options = {}) {
53
53
  const flowState = await readFlowState(projectRoot).catch(() => null);
54
54
  const activeRunId = flowState?.activeRunId ?? "unknown-run";
55
55
  const currentStage = flowState?.currentStage ?? "tdd";
56
- const tddCutoverSliceId = flowState?.tddCutoverSliceId ?? null;
57
- const tddWorktreeCutoverSliceId = flowState?.tddWorktreeCutoverSliceId ?? null;
58
- const legacyContinuation = flowState?.legacyContinuation === true;
59
56
  let planRaw = "";
60
57
  try {
61
58
  planRaw = await fs.readFile(path.join(artifactsDir, "05-plan.md"), "utf8");
@@ -71,9 +68,6 @@ export async function runWaveStatus(projectRoot, options = {}) {
71
68
  return {
72
69
  activeRunId,
73
70
  currentStage,
74
- tddCutoverSliceId,
75
- tddWorktreeCutoverSliceId,
76
- legacyContinuation,
77
71
  waves: [],
78
72
  nextDispatch: {
79
73
  waveId: null,
@@ -102,9 +96,6 @@ export async function runWaveStatus(projectRoot, options = {}) {
102
96
  return {
103
97
  activeRunId,
104
98
  currentStage,
105
- tddCutoverSliceId,
106
- tddWorktreeCutoverSliceId,
107
- legacyContinuation,
108
99
  waves: [],
109
100
  nextDispatch: {
110
101
  waveId: null,
@@ -120,8 +111,8 @@ export async function runWaveStatus(projectRoot, options = {}) {
120
111
  // Collect closed slice ids from the active run delegation ledger +
121
112
  // events. A slice is "closed" once it carries a terminal phase
122
113
  // (refactor, refactor-deferred, resolve-conflict) OR a phase=green
123
- // event with refactorOutcome (v6.14.0 fold-inline path). Anything else
124
- // we treat as still open so the helper never falsely advances.
114
+ // event with `refactorOutcome` recorded inline. Anything else we treat
115
+ // as still open so the helper never falsely advances.
125
116
  const closedSlices = new Set();
126
117
  let ledgerEntries = [];
127
118
  try {
@@ -194,9 +185,6 @@ export async function runWaveStatus(projectRoot, options = {}) {
194
185
  });
195
186
  const firstOpenWave = waves.find((w) => w.status === "open" || w.status === "partial") ?? null;
196
187
  const warnings = [];
197
- if (tddCutoverSliceId) {
198
- warnings.push("tddCutoverSliceId is a historical boundary; do not use it to find the active slice.");
199
- }
200
188
  if (merged.length === 0 && planRaw.length === 0) {
201
189
  warnings.push("wave_plan_missing: 05-plan.md not found or empty under <artifacts-dir>.");
202
190
  }
@@ -224,9 +212,6 @@ export async function runWaveStatus(projectRoot, options = {}) {
224
212
  return {
225
213
  activeRunId,
226
214
  currentStage,
227
- tddCutoverSliceId,
228
- tddWorktreeCutoverSliceId,
229
- legacyContinuation,
230
215
  waves,
231
216
  nextDispatch,
232
217
  warnings
@@ -236,13 +221,6 @@ function formatHumanReport(report) {
236
221
  const lines = [];
237
222
  lines.push(`activeRunId: ${report.activeRunId}`);
238
223
  lines.push(`currentStage: ${report.currentStage}`);
239
- if (report.tddCutoverSliceId) {
240
- lines.push(`tddCutoverSliceId: ${report.tddCutoverSliceId} (HISTORICAL)`);
241
- }
242
- if (report.tddWorktreeCutoverSliceId) {
243
- lines.push(`tddWorktreeCutoverSliceId: ${report.tddWorktreeCutoverSliceId}`);
244
- }
245
- lines.push(`legacyContinuation: ${report.legacyContinuation}`);
246
224
  lines.push("waves:");
247
225
  if (report.waves.length === 0) {
248
226
  lines.push(" (no waves discovered)");