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.
- package/README.md +0 -2
- package/dist/artifact-linter/brainstorm.js +1 -1
- package/dist/artifact-linter/design.js +2 -2
- package/dist/artifact-linter/findings-dedup.js +1 -1
- package/dist/artifact-linter/plan.js +6 -6
- package/dist/artifact-linter/review-army.d.ts +1 -1
- package/dist/artifact-linter/review-army.js +1 -1
- package/dist/artifact-linter/scope.js +6 -6
- package/dist/artifact-linter/shared.d.ts +37 -73
- package/dist/artifact-linter/shared.js +30 -37
- package/dist/artifact-linter/spec.js +1 -1
- package/dist/artifact-linter/tdd.d.ts +20 -33
- package/dist/artifact-linter/tdd.js +89 -639
- package/dist/artifact-linter.js +11 -32
- package/dist/cli.js +1 -1
- package/dist/config.js +1 -1
- package/dist/constants.js +1 -1
- package/dist/content/core-agents.d.ts +8 -26
- package/dist/content/core-agents.js +48 -94
- package/dist/content/examples.d.ts +1 -1
- package/dist/content/examples.js +4 -4
- package/dist/content/hooks.js +62 -149
- package/dist/content/idea.js +2 -2
- package/dist/content/iron-laws.js +1 -1
- package/dist/content/node-hooks.js +2 -2
- package/dist/content/skills-elicitation.js +2 -2
- package/dist/content/skills.d.ts +4 -6
- package/dist/content/skills.js +14 -53
- package/dist/content/stage-schema.d.ts +3 -3
- package/dist/content/stage-schema.js +8 -46
- package/dist/content/stages/brainstorm.js +5 -5
- package/dist/content/stages/plan.js +2 -2
- package/dist/content/stages/review.js +1 -1
- package/dist/content/stages/schema-types.d.ts +1 -1
- package/dist/content/stages/scope.js +1 -1
- package/dist/content/stages/spec.js +2 -2
- package/dist/content/stages/tdd.js +43 -108
- package/dist/content/start-command.js +3 -3
- package/dist/content/subagent-context-skills.js +5 -3
- package/dist/content/subagents.js +13 -74
- package/dist/content/templates.d.ts +6 -6
- package/dist/content/templates.js +23 -24
- package/dist/content/utility-skills.d.ts +1 -1
- package/dist/content/utility-skills.js +1 -1
- package/dist/delegation.d.ts +79 -139
- package/dist/delegation.js +83 -215
- package/dist/early-loop.js +1 -1
- package/dist/flow-state.d.ts +24 -129
- package/dist/flow-state.js +5 -30
- package/dist/gate-evidence.d.ts +2 -7
- package/dist/gate-evidence.js +2 -59
- package/dist/harness-adapters.d.ts +1 -1
- package/dist/harness-adapters.js +11 -10
- package/dist/install.js +24 -459
- package/dist/internal/advance-stage/advance.d.ts +5 -5
- package/dist/internal/advance-stage/advance.js +9 -24
- package/dist/internal/advance-stage/parsers.d.ts +1 -1
- package/dist/internal/advance-stage/review-loop.d.ts +1 -1
- package/dist/internal/advance-stage/review-loop.js +3 -3
- package/dist/internal/advance-stage/start-flow.js +1 -3
- package/dist/internal/advance-stage.js +4 -23
- package/dist/internal/cohesion-contract-stub.d.ts +8 -13
- package/dist/internal/cohesion-contract-stub.js +18 -24
- package/dist/internal/flow-state-repair.d.ts +1 -1
- package/dist/internal/plan-split-waves.d.ts +18 -21
- package/dist/internal/plan-split-waves.js +16 -19
- package/dist/internal/wave-status.d.ts +3 -6
- package/dist/internal/wave-status.js +5 -27
- package/dist/policy.js +1 -1
- package/dist/run-persistence.js +10 -44
- package/dist/runtime/run-hook.mjs +3 -3
- package/dist/track-heuristics.js +1 -1
- package/dist/types.d.ts +2 -2
- package/package.json +1 -1
- package/dist/integration-fanin.d.ts +0 -44
- package/dist/integration-fanin.js +0 -180
- package/dist/internal/set-checkpoint-mode.d.ts +0 -16
- package/dist/internal/set-checkpoint-mode.js +0 -72
- package/dist/internal/set-integration-overseer-mode.d.ts +0 -14
- package/dist/internal/set-integration-overseer-mode.js +0 -69
- package/dist/internal/set-worktree-mode.d.ts +0 -10
- package/dist/internal/set-worktree-mode.js +0 -28
- package/dist/worktree-manager.d.ts +0 -50
- package/dist/worktree-manager.js +0 -136
- package/dist/worktree-types.d.ts +0 -36
- package/dist/worktree-types.js +0 -6
package/dist/flow-state.d.ts
CHANGED
|
@@ -74,8 +74,10 @@ export interface CloseoutState {
|
|
|
74
74
|
}
|
|
75
75
|
export declare function createInitialCloseoutState(): CloseoutState;
|
|
76
76
|
export interface FlowState {
|
|
77
|
-
/**
|
|
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
|
-
*
|
|
91
|
+
* Optional task class for the active run.
|
|
90
92
|
*
|
|
91
|
-
* Mirrors the `MandatoryDelegationTaskClass` union used by
|
|
92
|
-
* `mandatoryAgentsFor
|
|
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
|
|
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
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
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
|
|
221
|
-
*
|
|
222
|
-
*
|
|
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
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
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
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
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`
|
package/dist/flow-state.js
CHANGED
|
@@ -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
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
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;
|
package/dist/gate-evidence.d.ts
CHANGED
|
@@ -13,13 +13,13 @@ export interface QaLogFloorSignal {
|
|
|
13
13
|
ok: boolean;
|
|
14
14
|
count: number;
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
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
|
-
/**
|
|
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;
|
package/dist/gate-evidence.js
CHANGED
|
@@ -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
|
|
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
|
-
//
|
|
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
|
|
82
|
+
* available (no shipping harness uses this).
|
|
83
83
|
*/
|
|
84
84
|
structuredAsk: "AskUserQuestion" | "AskQuestion" | "question" | "request_user_input" | "plain-text";
|
|
85
85
|
/**
|
package/dist/harness-adapters.js
CHANGED
|
@@ -293,7 +293,7 @@ export function harnessesByTier() {
|
|
|
293
293
|
});
|
|
294
294
|
}
|
|
295
295
|
function ironLawsAgentsMdBlock() {
|
|
296
|
-
//
|
|
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.
|
|
355
|
-
2. **Subagents run after Q&A approval** — mandatory subagents in brainstorm / scope / design (\`product-discovery\`, \`critic\`, \`planner\`, \`architect
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
732
|
+
for (const agent of agents) {
|
|
732
733
|
await writeFileSafe(path.join(codexAgentsDir, `${agent.name}.toml`), codexAgentToml(agent));
|
|
733
734
|
}
|
|
734
735
|
}
|