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
@@ -74,8 +74,10 @@ export interface CloseoutState {
74
74
  }
75
75
  export declare function createInitialCloseoutState(): CloseoutState;
76
76
  export interface FlowState {
77
- /** Backward-compatible schema marker for future migrations. */
77
+ /** Schema marker for forward compatibility. */
78
78
  schemaVersion: typeof FLOW_STATE_SCHEMA_VERSION;
79
+ /** Workspace marker stamped during sync/upgrade (semver string). */
80
+ packageVersion?: string;
79
81
  activeRunId: string;
80
82
  currentStage: FlowStage;
81
83
  completedStages: FlowStage[];
@@ -86,17 +88,14 @@ export interface FlowState {
86
88
  /** Run-level upstream shaping mode chosen once at start (`lean` / `guided` / `deep`). */
87
89
  discoveryMode: DiscoveryMode;
88
90
  /**
89
- * Wave 25 (v6.1.0) — optional task class for the active run.
91
+ * Optional task class for the active run.
90
92
  *
91
- * Mirrors the `MandatoryDelegationTaskClass` union used by Wave 24's
92
- * `mandatoryAgentsFor` helper. When set to `"software-bugfix"`, the
93
+ * Mirrors the `MandatoryDelegationTaskClass` union used by
94
+ * `mandatoryAgentsFor`. When set to `"software-bugfix"`, the
93
95
  * artifact-validation escape (`shouldDemoteArtifactValidationByTrack`)
94
96
  * collapses lite-tier-only checks (Architecture Diagram async/failure
95
97
  * edges, Interaction Edge Case mandatory rows, Stale Diagram Drift,
96
98
  * Expansion Strategist) from required → advisory.
97
- *
98
- * Persistence is best-effort: existing flow-state.json files written
99
- * before Wave 25 simply omit the field (treated as `null`).
100
99
  */
101
100
  taskClass?: "software-standard" | "software-trivial" | "software-bugfix" | null;
102
101
  /** Stages explicitly skipped for this track (empty for standard; populated for quick). */
@@ -115,137 +114,33 @@ export interface FlowState {
115
114
  repoSignals?: RepoSignals;
116
115
  /**
117
116
  * Best-effort stage completion timestamps (ISO strings) captured as stages
118
- * enter `completedStages`. Missing keys behave like legacy flows with no audit
119
- * clock for post-closure mutation hints.
117
+ * enter `completedStages`. Missing keys behave like older flows with no
118
+ * audit clock for post-closure mutation hints.
120
119
  */
121
120
  completedStageMeta?: Partial<Record<FlowStage, {
122
121
  completedAt: string;
123
122
  }>>;
124
123
  /**
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;
139
- /**
140
- * v6.14.2 — boundary slice id at which worktree-first protocol began
141
- * applying. `cclaw-cli sync` auto-stamps this when
142
- * `legacyContinuation: true` AND `worktreeExecutionMode: "worktree-first"`
143
- * AND the value is not already set.
144
- *
145
- * Detection rule (v6.14.2): the highest `S-N` among slices with at
146
- * least one completed `slice-implementer` row in the active run that
147
- * carries NONE of the worktree-first metadata fields (`claimToken`,
148
- * `ownerLaneId`, `leasedUntil`). When no such slice exists, sync
149
- * falls back to `tddCutoverSliceId` so legacy v6.12 cutover marks
150
- * still confer the exemption.
151
- *
152
- * Effect: closed slices whose numeric id is `<= tddWorktreeCutoverSliceId`
153
- * AND whose `slice-implementer` rows in the active run lack ALL
154
- * three worktree fields are exempt from `tdd_slice_lane_metadata_missing`,
155
- * `tdd_slice_claim_token_missing`, and `tdd_lease_expired_unreclaimed`.
156
- *
157
- * One-shot: subsequent sync runs leave the value untouched. Operators
158
- * may pin it earlier/later by direct edit + `cclaw-cli internal
159
- * flow-state-repair --reason=<slug>`.
160
- */
161
- tddWorktreeCutoverSliceId?: string;
162
- /**
163
- * v6.13.0 — when `worktree-first` (default for newly initialized runs),
164
- * slice-implementer work happens in isolated git worktrees with explicit
165
- * claims/leases and deterministic fan-in integration.
166
- *
167
- * Omitted on legacy `flow-state.json` files: treated as `single-tree` via
168
- * `effectiveWorktreeExecutionMode`.
169
- */
170
- worktreeExecutionMode?: "single-tree" | "worktree-first";
171
- /**
172
- * v6.13.0 — set by `cclaw-cli sync` when the plan predates parallel-metadata
173
- * fields. Relaxes some plan linters for existing implementation units and
174
- * defaults scheduler parallelism to opt-in only for those units.
175
- */
176
- legacyContinuation?: boolean;
177
- /**
178
- * v6.14.0 — TDD wave checkpoint mode (stream-style parallel TDD).
179
- *
180
- * - `per-slice` — default for new projects. Each lane runs RED→GREEN as
181
- * soon as its `dependsOn` closes; the linter enforces RED-before-GREEN
182
- * per slice only (`tdd_slice_red_completed_before_green`). No global
183
- * barrier between Phase A REDs and Phase B GREENs.
184
- * - `global-red` — legacy v6.12/v6.13 behavior. ALL Phase A REDs in a
185
- * wave must complete before ANY Phase B GREEN starts. Auto-applied
186
- * for projects with `legacyContinuation: true` so hox-style runs
187
- * continue to enforce the wave barrier.
188
- *
189
- * Omitted on legacy state files (treated as `"global-red"` for
190
- * `legacyContinuation: true` and `"per-slice"` otherwise via
191
- * `effectiveTddCheckpointMode`).
192
- */
193
- tddCheckpointMode?: "per-slice" | "global-red";
194
- /**
195
- * v6.14.0 — integration-overseer dispatch mode.
196
- *
197
- * - `conditional` — default for new projects. The controller calls
198
- * `integrationCheckRequired(events)` after wave closeout; the
199
- * integration-overseer is dispatched only when (a) two or more
200
- * closed slices share import boundaries (heuristic: shared
201
- * directory in `evidenceRefs`/`claimedPaths`), (b) any slice has
202
- * `riskTier === "high"`, or (c) deterministic fan-in reported a
203
- * `cclaw_fanin_conflict`. Otherwise the linter emits the audit
204
- * row `cclaw_integration_overseer_skipped` and skips dispatch.
205
- * - `always` — legacy v6.13 behavior. Run integration-overseer
206
- * after every multi-slice wave regardless of trigger.
207
- *
208
- * Omitted on legacy state files (treated as `"always"`).
209
- */
210
- integrationOverseerMode?: "conditional" | "always";
211
- /**
212
- * v6.14.2 — minimum elapsed milliseconds between `acknowledged` and
213
- * `completed` for a `slice-implementer --phase green` row. The hook
214
- * helper rejects fast-greens (`completedTs - ackTs < this`) with
215
- * `green_evidence_too_fresh` unless the dispatch carries
216
- * `--allow-fast-green --green-mode=observational`.
124
+ * Minimum elapsed milliseconds between `acknowledged` and `completed`
125
+ * for a `slice-builder --phase green` row. The hook helper rejects
126
+ * fast-greens (`completedTs - ackTs < this`) with `green_evidence_too_fresh`
127
+ * unless the dispatch carries `--allow-fast-green --green-mode=observational`.
217
128
  *
218
129
  * Default 4000ms when omitted (see `effectiveTddGreenMinElapsedMs`).
219
130
  * Operators tuning the floor for very fast suites may set it lower
220
- * (e.g. `1500`) or set it to `0` to disable the check entirely while
221
- * keeping the other Fix 4 contracts (RED test name match, passing
222
- * assertion line) active.
131
+ * (e.g. `1500`) or `0` to disable the check entirely while keeping the
132
+ * other freshness contracts (RED test name match, passing assertion line)
133
+ * active.
223
134
  */
224
135
  tddGreenMinElapsedMs?: number;
225
136
  }
226
- /**
227
- * Effective worktree mode: legacy state files without the field keep
228
- * single-tree scheduling to avoid breaking existing runs on upgrade.
229
- */
230
- export declare function effectiveWorktreeExecutionMode(state: FlowState): "single-tree" | "worktree-first";
231
- /**
232
- * Effective v6.14 TDD checkpoint mode: legacy state files without the
233
- * field default to `global-red` when `legacyContinuation: true` (hox)
234
- * and `per-slice` otherwise. Explicit values always win.
235
- */
236
- export declare function effectiveTddCheckpointMode(state: FlowState): "per-slice" | "global-red";
237
- /**
238
- * Effective v6.14 integration-overseer mode: legacy state files without
239
- * the field default to `always` (matches v6.13 behavior).
240
- */
241
- export declare function effectiveIntegrationOverseerMode(state: FlowState): "conditional" | "always";
242
137
  export declare const DEFAULT_TDD_GREEN_MIN_ELAPSED_MS = 4000;
243
138
  /**
244
- * v6.14.2 — effective minimum GREEN elapsed window in milliseconds.
245
- * Returns the per-project override when present and finite; otherwise
246
- * the documented 4000ms default. Negative values or NaN fall through
247
- * to the default so a hand-edited `flow-state.json` cannot accidentally
248
- * disable the check via `-1` or `"oops"`.
139
+ * Effective minimum GREEN elapsed window in milliseconds. Returns the
140
+ * per-project override when present and finite; otherwise the documented
141
+ * 4000ms default. Negative values or NaN fall through to the default so a
142
+ * hand-edited `flow-state.json` cannot accidentally disable the check via
143
+ * `-1` or `"oops"`.
249
144
  */
250
145
  export declare function effectiveTddGreenMinElapsedMs(state: FlowState): number;
251
146
  export interface StageInteractionHint {
@@ -253,10 +148,10 @@ export interface StageInteractionHint {
253
148
  sourceStage?: FlowStage;
254
149
  recordedAt?: string;
255
150
  /**
256
- * Wave 23 (v5.0.0) — `/cc-ideate` handoff carry-forward.
257
- * When a brainstorm run is started from a `/cc-ideate` recommendation,
258
- * `start-flow` records the originating idea artifact so brainstorm can
259
- * reuse the divergent + critique + rank work instead of re-generating it.
151
+ * `/cc-ideate` handoff carry-forward. When a brainstorm run is started
152
+ * from a `/cc-ideate` recommendation, `start-flow` records the originating
153
+ * idea artifact so brainstorm can reuse the divergent + critique + rank
154
+ * work instead of re-generating it.
260
155
  *
261
156
  * `fromIdeaArtifact` is a workspace-relative POSIX path to
262
157
  * `.cclaw/ideas/idea-YYYY-MM-DD-<slug>.md` (or wherever `/cc-ideate`
@@ -44,38 +44,13 @@ export function createInitialCloseoutState() {
44
44
  compoundPromoted: 0
45
45
  };
46
46
  }
47
- /**
48
- * Effective worktree mode: legacy state files without the field keep
49
- * single-tree scheduling to avoid breaking existing runs on upgrade.
50
- */
51
- export function effectiveWorktreeExecutionMode(state) {
52
- return state.worktreeExecutionMode ?? "single-tree";
53
- }
54
- /**
55
- * Effective v6.14 TDD checkpoint mode: legacy state files without the
56
- * field default to `global-red` when `legacyContinuation: true` (hox)
57
- * and `per-slice` otherwise. Explicit values always win.
58
- */
59
- export function effectiveTddCheckpointMode(state) {
60
- if (state.tddCheckpointMode === "per-slice" || state.tddCheckpointMode === "global-red") {
61
- return state.tddCheckpointMode;
62
- }
63
- return state.legacyContinuation === true ? "global-red" : "per-slice";
64
- }
65
- /**
66
- * Effective v6.14 integration-overseer mode: legacy state files without
67
- * the field default to `always` (matches v6.13 behavior).
68
- */
69
- export function effectiveIntegrationOverseerMode(state) {
70
- return state.integrationOverseerMode === "conditional" ? "conditional" : "always";
71
- }
72
47
  export const DEFAULT_TDD_GREEN_MIN_ELAPSED_MS = 4000;
73
48
  /**
74
- * v6.14.2 — effective minimum GREEN elapsed window in milliseconds.
75
- * Returns the per-project override when present and finite; otherwise
76
- * the documented 4000ms default. Negative values or NaN fall through
77
- * to the default so a hand-edited `flow-state.json` cannot accidentally
78
- * disable the check via `-1` or `"oops"`.
49
+ * Effective minimum GREEN elapsed window in milliseconds. Returns the
50
+ * per-project override when present and finite; otherwise the documented
51
+ * 4000ms default. Negative values or NaN fall through to the default so a
52
+ * hand-edited `flow-state.json` cannot accidentally disable the check via
53
+ * `-1` or `"oops"`.
79
54
  */
80
55
  export function effectiveTddGreenMinElapsedMs(state) {
81
56
  const raw = state.tddGreenMinElapsedMs;
@@ -13,13 +13,13 @@ export interface QaLogFloorSignal {
13
13
  ok: boolean;
14
14
  count: number;
15
15
  /**
16
- * Wave 23 (v5.0.0): always 0. The convergence floor no longer enforces
16
+ * always 0. The convergence floor no longer enforces
17
17
  * a fixed count. Harness UIs may render `questionBudgetHint(track,
18
18
  * stage).recommended` separately as a soft hint.
19
19
  */
20
20
  min: number;
21
21
  hasStopSignal: boolean;
22
- /** Wave 23: always false. See `min` note above. */
22
+ /** Always false; see `min` note above. */
23
23
  liteShortCircuit: boolean;
24
24
  skipQuestionsAdvisory: boolean;
25
25
  blocking: boolean;
@@ -66,11 +66,6 @@ export interface VerifyCurrentStageGateEvidenceOptions {
66
66
  extraStageFlags?: string[];
67
67
  }
68
68
  export declare function verifyCurrentStageGateEvidence(projectRoot: string, flowState: FlowState, options?: VerifyCurrentStageGateEvidenceOptions): Promise<GateEvidenceCheckResult>;
69
- /**
70
- * Validates that every lane-backed slice which reached REFACTOR has a matching
71
- * `cclaw_fanin_applied` audit row for the active run (v6.13.0 worktree-first).
72
- */
73
- export declare function verifyTddWorktreeFanInClosure(projectRoot: string, flowState: FlowState): Promise<string[]>;
74
69
  export declare function verifyCompletedStagesGateClosure(flowState: FlowState): CompletedStagesClosureResult;
75
70
  export interface GateReconciliationResult {
76
71
  stage: FlowStage;
@@ -5,8 +5,7 @@ import { ELICITATION_STAGES, evaluateQaLogFloor } from "./artifact-linter/shared
5
5
  import { resolveArtifactPath } from "./artifact-paths.js";
6
6
  import { RUNTIME_ROOT } from "./constants.js";
7
7
  import { stageSchema } from "./content/stage-schema.js";
8
- import { readDelegationLedger, readDelegationEvents } from "./delegation.js";
9
- import { effectiveWorktreeExecutionMode } from "./flow-state.js";
8
+ import { readDelegationLedger } from "./delegation.js";
10
9
  import { exists } from "./fs-utils.js";
11
10
  import { computeEarlyLoopStatus, isEarlyLoopStage, normalizeEarlyLoopMaxIterations } from "./early-loop.js";
12
11
  import { detectPublicApiChanges } from "./internal/detect-public-api-changes.js";
@@ -463,7 +462,7 @@ export async function verifyCurrentStageGateEvidence(projectRoot, flowState, opt
463
462
  forcingPending: floor.forcingPending,
464
463
  noNewDecisions: floor.noNewDecisions
465
464
  };
466
- // v6.9.0 — when the QA log floor is blocking, mirror that decision into
465
+ // when the QA log floor is blocking, mirror that decision into
467
466
  // `gates.issues` so the harness has a single structured source of truth
468
467
  // for "this stage is blocked". The `qa_log_unconverged` linter rule
469
468
  // remains the verbose detail/fallback channel.
@@ -488,62 +487,6 @@ export async function verifyCurrentStageGateEvidence(projectRoot, flowState, opt
488
487
  qaLogFloor
489
488
  };
490
489
  }
491
- function sliceHasTerminalRefactor(events, runId, sliceId) {
492
- for (const e of events) {
493
- if (e.runId !== runId || e.stage !== "tdd" || e.sliceId !== sliceId)
494
- continue;
495
- if (e.agent !== "slice-implementer" || e.status !== "completed")
496
- continue;
497
- if (e.phase === "refactor" || e.phase === "refactor-deferred")
498
- return true;
499
- }
500
- return false;
501
- }
502
- function closedSlicesWithLane(events, runId) {
503
- const withLane = new Set();
504
- for (const e of events) {
505
- if (e.runId !== runId || e.stage !== "tdd")
506
- continue;
507
- if (e.agent !== "slice-implementer" || e.status !== "completed" || e.phase !== "green")
508
- continue;
509
- if (!e.ownerLaneId?.trim() || !e.sliceId)
510
- continue;
511
- withLane.add(e.sliceId);
512
- }
513
- const out = new Set();
514
- for (const sid of withLane) {
515
- if (sliceHasTerminalRefactor(events, runId, sid))
516
- out.add(sid);
517
- }
518
- return out;
519
- }
520
- /**
521
- * Validates that every lane-backed slice which reached REFACTOR has a matching
522
- * `cclaw_fanin_applied` audit row for the active run (v6.13.0 worktree-first).
523
- */
524
- export async function verifyTddWorktreeFanInClosure(projectRoot, flowState) {
525
- if (effectiveWorktreeExecutionMode(flowState) !== "worktree-first")
526
- return [];
527
- const runId = flowState.activeRunId;
528
- const { events, fanInAudits } = await readDelegationEvents(projectRoot);
529
- const needing = closedSlicesWithLane(events, runId);
530
- if (needing.size === 0)
531
- return [];
532
- const applied = new Set();
533
- for (const a of fanInAudits) {
534
- if (a.runId !== runId || a.event !== "cclaw_fanin_applied")
535
- continue;
536
- for (const s of a.sliceIds ?? [])
537
- applied.add(s);
538
- }
539
- const issues = [];
540
- for (const sid of needing) {
541
- if (!applied.has(sid)) {
542
- issues.push(`tdd worktree fan-in closure: slice ${sid} completed on a lane but cclaw_fanin_applied is missing for run ${runId}.`);
543
- }
544
- }
545
- return issues;
546
- }
547
490
  export function verifyCompletedStagesGateClosure(flowState) {
548
491
  const issues = [];
549
492
  const openStages = [];
@@ -79,7 +79,7 @@ export interface HarnessAdapter {
79
79
  * (`codex-rs/collaboration-mode-templates`). Available to agents running
80
80
  * inside Codex but may be hidden on very old builds.
81
81
  * - `plain-text` — fallback only; used when no native primitive is
82
- * available (no shipping harness uses this in v0.41.0).
82
+ * available (no shipping harness uses this).
83
83
  */
84
84
  structuredAsk: "AskUserQuestion" | "AskQuestion" | "question" | "request_user_input" | "plain-text";
85
85
  /**
@@ -293,7 +293,7 @@ export function harnessesByTier() {
293
293
  });
294
294
  }
295
295
  function ironLawsAgentsMdBlock() {
296
- // v6.9.0: keep this set in sync with `ironLawsSkillMarkdown()` —
296
+ // keep this set in sync with `ironLawsSkillMarkdown()` —
297
297
  // post-Phase A, only `stop-clean-or-handoff` is still hook-enforced
298
298
  // (Stop hook). All other iron laws live in stage HARD-GATE blocks.
299
299
  const enforcedLawIds = new Set([
@@ -351,8 +351,8 @@ Before responding to a coding request:
351
351
 
352
352
  Three rules apply to every cclaw stage in this project, regardless of which skills loaded:
353
353
 
354
- 1. **Q&A convergence before drafting** — for brainstorm / scope / design, walk the stage forcing questions one at a time via the harness-native question tool (Claude \`AskUserQuestion\`, Cursor \`AskQuestion\`, Codex \`request_user_input\`, Gemini \`ask_user\`). The \`qa_log_unconverged\` linter rule will block \`stage-complete\` when convergence has not been reached. Convergence is satisfied when ANY of: (a) every forcing-question topic id is tagged \`[topic:<id>]\` in at least one \`## Q&A Log\` row, (b) the last 2 substantive rows produce no decision-changing impact (Ralph-Loop), or (c) an explicit user stop-signal row is recorded. The fixed count floor (10 for standard) was removed in Wave 23. Wave 24 (v6.0.0) made \`[topic:<id>]\` tagging mandatory (no English keyword fallback) so the gate works in any natural language.
355
- 2. **Subagents run after Q&A approval** — mandatory subagents in brainstorm / scope / design (\`product-discovery\`, \`critic\`, \`planner\`, \`architect\`, \`test-author\`) run only AFTER the user approves the elicitation outcome. See each stage's "Run Phase: post-elicitation" rows in the materialized Automatic Subagent Dispatch table.
354
+ 1. **Q&A convergence before drafting** — for brainstorm / scope / design, walk the stage forcing questions one at a time via the harness-native question tool (Claude \`AskUserQuestion\`, Cursor \`AskQuestion\`, Codex \`request_user_input\`, Gemini \`ask_user\`). The \`qa_log_unconverged\` linter rule will block \`stage-complete\` when convergence has not been reached. Convergence is satisfied when ANY of: (a) every forcing-question topic id is tagged \`[topic:<id>]\` in at least one \`## Q&A Log\` row, (b) the last 2 substantive rows produce no decision-changing impact (Ralph-Loop), or (c) an explicit user stop-signal row is recorded. \`[topic:<id>]\` tagging is mandatory (no English keyword fallback) so the gate works in any natural language.
355
+ 2. **Subagents run after Q&A approval** — mandatory subagents in brainstorm / scope / design (\`product-discovery\`, \`critic\`, \`planner\`, \`architect\`) run only AFTER the user approves the elicitation outcome. See each stage's "Run Phase: post-elicitation" rows in the materialized Automatic Subagent Dispatch table.
356
356
  3. **No command-line echo to chat** — the user does not run cclaw helpers manually. Never paste \`node .cclaw/hooks/...\` invocations, \`--evidence-json '{...}'\` payloads, or shell hash commands (\`shasum\`, \`sha256sum\`, \`Get-FileHash\`, \`certutil\`, etc.) into chat. Run helpers via the tool layer; report only the resulting summary.
357
357
 
358
358
  ${ironLawsAgentsMdBlock()}
@@ -626,15 +626,15 @@ async function writeSkillKindShims(commandDir) {
626
626
  }
627
627
  }
628
628
  /**
629
- * Legacy codex surfaces cclaw wrote before v0.39.0 that Codex CLI never
629
+ * Legacy codex surfaces cclaw wrote before that Codex CLI never
630
630
  * consumed (`.codex/commands/*.md` had no discovery primitive). We keep
631
631
  * removing `.codex/commands/` on every sync so upgrades from those
632
- * installs leave a clean slate, but as of v0.40.0 we DO write
632
+ * installs leave a clean slate, but as of we DO write
633
633
  * `.codex/hooks.json` again — Codex CLI grew a real hooks API in
634
- * v0.114.0 (Mar 2026), and that file is the current, supported target.
634
+ (Mar 2026), and that file is the current, supported target.
635
635
  *
636
636
  * This function also removes skill folders named after the old
637
- * `cclaw-cc*` scheme (v0.39.0 / v0.39.1) now that cclaw installs them
637
+ * `cclaw-cc*` scheme now that cclaw installs them
638
638
  * as plain `cc*`. Leaving them around would make Codex list two skills
639
639
  * for the same entry point.
640
640
  */
@@ -713,22 +713,23 @@ function enhancedAgentInstruction(agentName) {
713
713
  return `## Worker ACK Contract\n\nYou are the cclaw ${agentName} subagent. Follow the parent prompt as the task boundary. ACK first with JSON containing spanId, dispatchId or workerRunId, dispatchSurface, agentDefinitionPath, ackTs, and status: "ACK". Finish with the strict return schema plus the same spanId+dispatchId proof so the parent can append .cclaw/state/delegation-events.jsonl and .cclaw/state/delegation-log.json. Do not let the parent claim isolated completion without matching ACK/result proof. Do not recursively orchestrate other agents unless the parent explicitly asks.`;
714
714
  }
715
715
  async function syncAgentFiles(projectRoot, harnesses) {
716
+ const agents = CCLAW_AGENTS;
716
717
  const agentsDir = path.join(projectRoot, RUNTIME_ROOT, "agents");
717
718
  await ensureDir(agentsDir);
718
- for (const agent of CCLAW_AGENTS) {
719
+ for (const agent of agents) {
719
720
  await writeFileSafe(path.join(agentsDir, `${agent.name}.md`), agentMarkdown(agent));
720
721
  }
721
722
  if (harnesses.includes("opencode")) {
722
723
  const opencodeAgentsDir = path.join(projectRoot, ".opencode/agents");
723
724
  await ensureDir(opencodeAgentsDir);
724
- for (const agent of CCLAW_AGENTS) {
725
+ for (const agent of agents) {
725
726
  await writeFileSafe(path.join(opencodeAgentsDir, `${agent.name}.md`), opencodeAgentMarkdown(agent));
726
727
  }
727
728
  }
728
729
  if (harnesses.includes("codex")) {
729
730
  const codexAgentsDir = path.join(projectRoot, ".codex/agents");
730
731
  await ensureDir(codexAgentsDir);
731
- for (const agent of CCLAW_AGENTS) {
732
+ for (const agent of agents) {
732
733
  await writeFileSafe(path.join(codexAgentsDir, `${agent.name}.toml`), codexAgentToml(agent));
733
734
  }
734
735
  }