cclaw-cli 4.0.0 → 6.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/dist/artifact-linter/brainstorm.js +40 -2
- package/dist/artifact-linter/design.js +2 -2
- package/dist/artifact-linter/review-army.d.ts +25 -0
- package/dist/artifact-linter/review-army.js +155 -0
- package/dist/artifact-linter/review.js +13 -0
- package/dist/artifact-linter/scope.js +9 -17
- package/dist/artifact-linter/shared.d.ts +93 -19
- package/dist/artifact-linter/shared.js +214 -96
- package/dist/artifact-linter.d.ts +1 -1
- package/dist/artifact-linter.js +1 -1
- package/dist/content/core-agents.js +6 -1
- package/dist/content/idea.js +14 -2
- package/dist/content/skills-elicitation.js +35 -18
- package/dist/content/skills.js +10 -4
- package/dist/content/stage-schema.d.ts +29 -0
- package/dist/content/stage-schema.js +17 -0
- package/dist/content/stages/_lint-metadata/index.js +1 -2
- package/dist/content/stages/brainstorm.js +5 -2
- package/dist/content/stages/design.js +13 -12
- package/dist/content/stages/review.js +21 -21
- package/dist/content/stages/scope.js +20 -18
- package/dist/content/stages/spec.js +3 -3
- package/dist/content/stages/tdd.js +1 -0
- package/dist/content/subagents.js +3 -1
- package/dist/content/templates.d.ts +2 -2
- package/dist/content/templates.js +52 -36
- package/dist/delegation.d.ts +16 -0
- package/dist/delegation.js +64 -3
- package/dist/flow-state.d.ts +12 -0
- package/dist/gate-evidence.d.ts +12 -0
- package/dist/gate-evidence.js +4 -1
- package/dist/harness-adapters.js +1 -1
- package/dist/internal/advance-stage/advance.d.ts +2 -0
- package/dist/internal/advance-stage/advance.js +2 -1
- package/dist/internal/advance-stage/parsers.d.ts +8 -0
- package/dist/internal/advance-stage/parsers.js +27 -1
- package/dist/internal/advance-stage/start-flow.js +13 -0
- package/dist/run-persistence.js +14 -2
- package/package.json +1 -1
|
@@ -38,6 +38,13 @@ export const ARTIFACT_TEMPLATES = {
|
|
|
38
38
|
|---|---|---|---|
|
|
39
39
|
| | | | |
|
|
40
40
|
|
|
41
|
+
## Idea Evidence Carry-forward
|
|
42
|
+
> Required only when this brainstorm started from \`/cc-ideate\` (\`flow-state.interactionHints.brainstorm.fromIdeaArtifact\` is set). Skip the section entirely otherwise.
|
|
43
|
+
- Source: \`<.cclaw/ideas/idea-YYYY-MM-DD-slug.md>\`
|
|
44
|
+
- Candidate: \`I-#\`
|
|
45
|
+
- Reused fields: Title, Why-now, Expected impact, Risk, Counter-argument
|
|
46
|
+
- Newly generated: challenger row(s) only — the idea candidate becomes the \`baseline\` row of \`## Approaches\` and the seed of \`## Selected Direction\`; do NOT regenerate divergent + critique + rank work that \`/cc-ideate\` already produced.
|
|
47
|
+
|
|
41
48
|
## Problem Decision Record
|
|
42
49
|
- **Depth:** lite | standard | deep
|
|
43
50
|
- **Frame type:** \`<free-form-label>\` (one short token that names how this work is framed; pick whatever fits — examples in commentary only: \`product\`, \`technical-maintenance\`, \`research-spike\`, \`ops-incident\`, \`infrastructure\`, \`library-extraction\`. Do NOT treat the examples as an enum.)
|
|
@@ -79,9 +86,10 @@ export const ARTIFACT_TEMPLATES = {
|
|
|
79
86
|
## Q&A Log
|
|
80
87
|
| Turn | Question | User answer (1-line) | Decision impact |
|
|
81
88
|
|---|---|---|---|
|
|
82
|
-
| 1 | | |
|
|
89
|
+
| 1 | | | scope-shaping [topic:pain] |
|
|
83
90
|
|
|
84
91
|
> Append-only by turn. Add one row after each user answer; do not rewrite prior rows.
|
|
92
|
+
> **Topic tag is MANDATORY for forcing-question rows.** Stamp \`[topic:<id>]\` in the \`Decision impact\` cell so the linter can verify coverage in any natural language (RU/EN/UA/etc.). Brainstorm IDs: \`pain\`, \`direct-path\`, \`do-nothing\`, \`operator\`, \`no-go\`. Multiple tags allowed when one answer covers several topics. Stop-signal rows do NOT need a tag. Wave 24 (v6.0.0) removed the English keyword fallback.
|
|
85
93
|
|
|
86
94
|
## Approach Tier
|
|
87
95
|
- Tier: lite | standard | deep
|
|
@@ -202,9 +210,10 @@ ${MARKDOWN_CODE_FENCE}
|
|
|
202
210
|
## Q&A Log
|
|
203
211
|
| Turn | Question | User answer (1-line) | Decision impact |
|
|
204
212
|
|---|---|---|---|
|
|
205
|
-
| 1 | | |
|
|
213
|
+
| 1 | | | scope-shaping [topic:in-out] |
|
|
206
214
|
|
|
207
215
|
> Append-only by turn. Add one row after each user answer; do not rewrite prior rows.
|
|
216
|
+
> **Topic tag is MANDATORY for forcing-question rows.** Stamp \`[topic:<id>]\` in the \`Decision impact\` cell so the linter can verify coverage in any natural language (RU/EN/UA/etc.). Scope IDs: \`in-out\`, \`locked-upstream\`, \`rollback\`, \`failure-modes\`. Multiple tags allowed when one answer covers several topics. Stop-signal rows do NOT need a tag. Wave 24 (v6.0.0) removed the English keyword fallback.
|
|
208
217
|
|
|
209
218
|
## Pre-Scope System Audit
|
|
210
219
|
| Check | Command | Findings |
|
|
@@ -219,23 +228,14 @@ ${MARKDOWN_CODE_FENCE}
|
|
|
219
228
|
- Every error has a name:
|
|
220
229
|
- Four paths per data flow:
|
|
221
230
|
|
|
222
|
-
## Premise
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
|
226
|
-
|
|
227
|
-
|
|
|
228
|
-
| Existing-code leverage? | | |
|
|
229
|
-
| Reversibility cost? | | |
|
|
230
|
-
|
|
231
|
-
## Implementation Alternatives
|
|
232
|
-
| Option | Summary | Effort (S/M/L/XL) | Risk (Low/Med/High) | Pros | Cons | Reuses |
|
|
233
|
-
|---|---|---|---|---|---|---|
|
|
234
|
-
| A (minimum viable) | | | | | | |
|
|
235
|
-
| B (ideal architecture) | | | | | | |
|
|
236
|
-
| C (optional) | | | | | | |
|
|
231
|
+
## Premise Drift
|
|
232
|
+
> Optional. Brainstorm OWNS the premise check. Record \`None\` unless scope-stage Q&A surfaced new evidence (constraint, user signal, regulatory change) that materially changes brainstorm's \`## Premise Check\` answer.
|
|
233
|
+
|
|
234
|
+
| Brainstorm question | New evidence (scope-stage) | Drift verdict (no-change / shift / reverse) | Action |
|
|
235
|
+
|---|---|---|---|
|
|
236
|
+
| (cite brainstorm Q) | | | |
|
|
237
237
|
|
|
238
|
-
|
|
238
|
+
- Default: \`Drift: None — brainstorm Premise Check stands.\`
|
|
239
239
|
|
|
240
240
|
## Scope Contract
|
|
241
241
|
- **Selected mode:** HOLD SCOPE | SELECTIVE EXPANSION | SCOPE EXPANSION | SCOPE REDUCTION
|
|
@@ -247,8 +247,9 @@ RECOMMENDATION: <option letter — one-line rationale tying back to premise chal
|
|
|
247
247
|
- **Deferred ideas:**
|
|
248
248
|
- **Accepted reference ideas:**
|
|
249
249
|
- **Rejected reference ideas:**
|
|
250
|
+
- **Constraints (external/regulatory/system/integration):** (spec carries these forward — do NOT restate as assumptions)
|
|
250
251
|
- **Success definition:**
|
|
251
|
-
- **Design handoff:**
|
|
252
|
+
- **Design handoff:** (name what design must decide: architecture-tier, framework, data-model, etc. — design OWNS the architecture choice)
|
|
252
253
|
|
|
253
254
|
## Decision Drivers
|
|
254
255
|
| Driver | Weight (1-5) | Option A | Option B | Option C | Notes |
|
|
@@ -448,9 +449,10 @@ ${MARKDOWN_CODE_FENCE}
|
|
|
448
449
|
## Q&A Log
|
|
449
450
|
| Turn | Question | User answer (1-line) | Decision impact |
|
|
450
451
|
|---|---|---|---|
|
|
451
|
-
| 1 | | |
|
|
452
|
+
| 1 | | | architecture-shaping [topic:data-flow] |
|
|
452
453
|
|
|
453
454
|
> Append-only by turn. Add one row after each user answer; do not rewrite prior rows.
|
|
455
|
+
> **Topic tag is MANDATORY for forcing-question rows.** Stamp \`[topic:<id>]\` in the \`Decision impact\` cell so the linter can verify coverage in any natural language (RU/EN/UA/etc.). Design IDs: \`data-flow\`, \`seams\`, \`invariants\`, \`not-refactor\`. Multiple tags allowed when one answer covers several topics. Stop-signal rows do NOT need a tag. Wave 24 (v6.0.0) removed the English keyword fallback.
|
|
454
456
|
|
|
455
457
|
## Codebase Investigation
|
|
456
458
|
| File | Current responsibility | Patterns discovered | Existing fit / reuse candidate |
|
|
@@ -528,8 +530,12 @@ ${MARKDOWN_CODE_FENCE}
|
|
|
528
530
|
|---|---|---|---|---|
|
|
529
531
|
| | | | clear/stale | |
|
|
530
532
|
|
|
531
|
-
##
|
|
532
|
-
|
|
533
|
+
## Blast-radius Diff
|
|
534
|
+
> Diff since scope artifact baseline. Scope OWNS the full repo audit (\`## Pre-Scope System Audit\`); design only diffs touched paths.
|
|
535
|
+
>
|
|
536
|
+
> Suggested command: \`git diff <scope-artifact-head-sha>..HEAD -- <touched-paths>\`
|
|
537
|
+
|
|
538
|
+
| File | Change since scope (\`git diff\` summary) | Current responsibility | Reuse candidate / existing pattern |
|
|
533
539
|
|---|---|---|---|
|
|
534
540
|
| | | | |
|
|
535
541
|
|
|
@@ -624,9 +630,6 @@ ${MARKDOWN_CODE_FENCE}
|
|
|
624
630
|
- Max iterations: 3
|
|
625
631
|
- Unresolved concerns:
|
|
626
632
|
|
|
627
|
-
## NOT in scope
|
|
628
|
-
-
|
|
629
|
-
|
|
630
633
|
## Parallelization Strategy
|
|
631
634
|
- Standard/Deep add-on when multi-module; omit for compact sequential work.
|
|
632
635
|
- Parallel lanes:
|
|
@@ -722,8 +725,10 @@ ${MARKDOWN_CODE_FENCE}
|
|
|
722
725
|
| AC-1 | | |
|
|
723
726
|
|
|
724
727
|
## Constraints and Assumptions
|
|
725
|
-
-
|
|
726
|
-
|
|
728
|
+
> Constraints are CARRIED FORWARD from scope's \`## Scope Contract > Constraints\`. Cite or copy with attribution; do NOT re-author. Spec OWNS testable assumptions in \`## Assumptions Before Finalization\` below.
|
|
729
|
+
|
|
730
|
+
- **Constraints (carry-forward):** See scope: \`02-scope-<slug>.md#scope-contract\` (or list new spec-stage constraints with citation to the Q&A row that surfaced them).
|
|
731
|
+
- **Assumptions:** See \`## Assumptions Before Finalization\` (spec-only owner).
|
|
727
732
|
|
|
728
733
|
## Assumptions Before Finalization
|
|
729
734
|
| Assumption | Source / confidence | Validation path | Disposition |
|
|
@@ -1184,9 +1189,14 @@ Execution rule: complete and verify each batch before starting the next batch.
|
|
|
1184
1189
|
| AC-1 | PASS/FAIL | |
|
|
1185
1190
|
|
|
1186
1191
|
## Layer 2 Findings
|
|
1192
|
+
> Wave 23 (v5.0.0): Layer 2 categories OWNED by review = cross-slice correctness, security, dependency/version, observability, external-safety. Performance + architecture findings are CARRY-FORWARD from \`03-design-<slug>.md\` (Performance Budget, ADR) — cite, do NOT re-derive. Single-slice findings stay in \`06-tdd.md > Per-Slice Review\`; review may cite their IDs (severity/disposition must match — cross-artifact-duplication linter blocks otherwise).
|
|
1193
|
+
|
|
1187
1194
|
| ID | Severity | Category | File:line / no-line reason | Description | Status |
|
|
1188
1195
|
|---|---|---|---|---|---|
|
|
1189
|
-
| R-1 | Critical/Important/Suggestion | correctness/security/
|
|
1196
|
+
| R-1 | Critical/Important/Suggestion | cross-slice-correctness/security/dependency-version/observability/external-safety | path:line | | open/resolved |
|
|
1197
|
+
| R-2 | from-design | performance | cite \`03-design-<slug>.md > Performance Budget\` | | carry-forward |
|
|
1198
|
+
| R-3 | from-design | architecture | cite \`03-design-<slug>.md > ADR\` | | carry-forward |
|
|
1199
|
+
| R-4 | from-tdd | from-tdd | cite \`06-tdd.md > Per-Slice Review > F-<n>\` | | carry-forward |
|
|
1190
1200
|
- NO_FINDINGS_ATTESTATION: <required when no findings are reported; cite inspected coverage>
|
|
1191
1201
|
|
|
1192
1202
|
## Lens Coverage
|
|
@@ -1477,13 +1487,19 @@ regardless of whether stage skills loaded.
|
|
|
1477
1487
|
|
|
1478
1488
|
Before drafting any \`.cclaw/artifacts/01-brainstorm-*.md\`,
|
|
1479
1489
|
\`02-scope-*.md\`, or \`03-design-*.md\`, verify that the artifact's
|
|
1480
|
-
\`## Q&A Log\` table
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1490
|
+
\`## Q&A Log\` table demonstrates Ralph-Loop convergence: every
|
|
1491
|
+
forcing-question topic id is tagged \`[topic:<id>]\` on at least one row
|
|
1492
|
+
(see the stage's forcing-questions checklist for the id list), the last
|
|
1493
|
+
2 turns produce no new decision-changing impact, OR an explicit user
|
|
1494
|
+
stop-signal row is recorded. Walk the stage forcing questions one at a
|
|
1495
|
+
time via the \`AskQuestion\` tool. If you find yourself proposing a
|
|
1496
|
+
draft after 1-2 questions while forcing topic ids remain untagged, STOP
|
|
1497
|
+
and continue the loop.
|
|
1498
|
+
|
|
1499
|
+
The \`qa_log_unconverged\` linter rule will block \`stage-complete\` when
|
|
1500
|
+
convergence has not been reached. Wave 24 (v6.0.0) made \`[topic:<id>]\`
|
|
1501
|
+
tagging mandatory; the English keyword fallback was removed because it
|
|
1502
|
+
mis-reported convergence on RU/UA Q&A logs.
|
|
1487
1503
|
|
|
1488
1504
|
## 2. Mandatory subagents run after Q&A approval
|
|
1489
1505
|
|
|
@@ -1555,7 +1571,7 @@ Track-specific skips are allowed only when \`flow-state.track\` + \`skippedStage
|
|
|
1555
1571
|
## Delegation And Approvals
|
|
1556
1572
|
|
|
1557
1573
|
- Machine-only checks in design/plan/tdd/review/ship should auto-dispatch when tooling supports it.
|
|
1558
|
-
- **For brainstorm / scope / design stages**: ask user input continuously via adaptive elicitation (one question per turn through the harness-native question tool — \`AskQuestion\` in Cursor). Walk the stage forcing-questions list one-by-one. Do NOT batch and do NOT defer to a single approval gate at the end. The \`
|
|
1574
|
+
- **For brainstorm / scope / design stages**: ask user input continuously via adaptive elicitation (one question per turn through the harness-native question tool — \`AskQuestion\` in Cursor). Walk the stage forcing-questions list one-by-one. **Tag each Q&A Log row's \`Decision impact\` cell with \`[topic:<id>]\`** (the id is given in the stage's forcing-questions checklist) so the linter can verify coverage in any natural language. Do NOT batch and do NOT defer to a single approval gate at the end. The \`qa_log_unconverged\` linter rule will block \`stage-complete\` when convergence is not reached (forcing topic ids untagged AND last 2 turns still produce decision-changing rows AND no stop-signal).
|
|
1559
1575
|
- **For other stages** (spec/plan/tdd/build/review/ship): ask user input only at explicit approval gates (scope mode, plan approval, challenge resolution, ship finalization), not for routine progress updates.
|
|
1560
1576
|
- If you find yourself proposing a draft after 1-2 questions in brainstorm/scope/design, STOP — go back to the forcing-questions list and continue.
|
|
1561
1577
|
- Mandatory subagents in brainstorm/scope/design run only AFTER the user approves the elicitation outcome (see each stage's "Run Phase: post-elicitation" rows). Dispatching them before the Q&A loop converges violates the contract.
|
package/dist/delegation.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type SubagentFallback } from "./harness-adapters.js";
|
|
2
|
+
import { type MandatoryDelegationTaskClass } from "./content/stage-schema.js";
|
|
2
3
|
import type { FlowStage } from "./types.js";
|
|
3
4
|
export type DelegationMode = "mandatory" | "proactive";
|
|
4
5
|
export type DelegationStatus = "scheduled" | "launched" | "acknowledged" | "completed" | "failed" | "waived" | "stale";
|
|
@@ -143,6 +144,13 @@ export declare function appendDelegation(projectRoot: string, entry: DelegationE
|
|
|
143
144
|
export declare function expectedFulfillmentMode(fallbacks: SubagentFallback[]): DelegationFulfillmentMode;
|
|
144
145
|
export declare function checkMandatoryDelegations(projectRoot: string, stage: FlowStage, options?: {
|
|
145
146
|
repairFeatureSystem?: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Optional task class for the active run. When set to
|
|
149
|
+
* `"software-bugfix"`, the mandatory delegation gate is skipped
|
|
150
|
+
* entirely (Wave 24). Callers that don't classify the run leave
|
|
151
|
+
* this undefined and rely on the track-based skip.
|
|
152
|
+
*/
|
|
153
|
+
taskClass?: MandatoryDelegationTaskClass | null;
|
|
146
154
|
}): Promise<{
|
|
147
155
|
satisfied: boolean;
|
|
148
156
|
missing: string[];
|
|
@@ -160,4 +168,12 @@ export declare function checkMandatoryDelegations(projectRoot: string, stage: Fl
|
|
|
160
168
|
staleWorkers: string[];
|
|
161
169
|
/** Expected fulfillment mode for the active harness set. */
|
|
162
170
|
expectedMode: DelegationFulfillmentMode;
|
|
171
|
+
/**
|
|
172
|
+
* Wave 24 (v6.0.0): true when `mandatoryAgentsFor` returned [] for
|
|
173
|
+
* this (track, taskClass) combination — i.e. the gate was skipped
|
|
174
|
+
* entirely on quick track or software-bugfix runs. The skip is also
|
|
175
|
+
* recorded as a `mandatory_delegations_skipped_by_track` event in
|
|
176
|
+
* `delegation-events.jsonl` for audit traceability.
|
|
177
|
+
*/
|
|
178
|
+
skippedByTrack: boolean;
|
|
163
179
|
}>;
|
package/dist/delegation.js
CHANGED
|
@@ -7,7 +7,7 @@ import { readConfig } from "./config.js";
|
|
|
7
7
|
import { exists, withDirectoryLock, writeFileSafe } from "./fs-utils.js";
|
|
8
8
|
import { HARNESS_ADAPTERS } from "./harness-adapters.js";
|
|
9
9
|
import { readFlowState } from "./runs.js";
|
|
10
|
-
import { stageSchema } from "./content/stage-schema.js";
|
|
10
|
+
import { mandatoryAgentsFor, stageSchema } from "./content/stage-schema.js";
|
|
11
11
|
const execFileAsync = promisify(execFile);
|
|
12
12
|
const TERMINAL_DELEGATION_STATUSES = new Set(["completed", "failed", "waived", "stale"]);
|
|
13
13
|
export const DELEGATION_DISPATCH_SURFACES = [
|
|
@@ -320,6 +320,21 @@ export async function readDelegationLedger(projectRoot) {
|
|
|
320
320
|
return { runId: activeRunId, entries: [] };
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
|
+
/**
|
|
324
|
+
* Wave 24 (v6.0.0) audit-only event types that live in
|
|
325
|
+
* `delegation-events.jsonl` but do NOT carry a delegation lifecycle
|
|
326
|
+
* payload (no agent/spanId). The parser must accept them so they
|
|
327
|
+
* don't show up as corrupt lines.
|
|
328
|
+
*/
|
|
329
|
+
const NON_DELEGATION_AUDIT_EVENTS = new Set([
|
|
330
|
+
"mandatory_delegations_skipped_by_track"
|
|
331
|
+
]);
|
|
332
|
+
function isAuditEventLine(parsed) {
|
|
333
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
334
|
+
return false;
|
|
335
|
+
const evt = parsed.event;
|
|
336
|
+
return typeof evt === "string" && NON_DELEGATION_AUDIT_EVENTS.has(evt);
|
|
337
|
+
}
|
|
323
338
|
export async function readDelegationEvents(projectRoot) {
|
|
324
339
|
const filePath = delegationEventsPath(projectRoot);
|
|
325
340
|
if (!(await exists(filePath))) {
|
|
@@ -338,6 +353,11 @@ export async function readDelegationEvents(projectRoot) {
|
|
|
338
353
|
if (isDelegationEvent(parsed)) {
|
|
339
354
|
events.push(parsed);
|
|
340
355
|
}
|
|
356
|
+
else if (isAuditEventLine(parsed)) {
|
|
357
|
+
// Wave 24 audit-only row (e.g. mandatory_delegations_skipped_by_track).
|
|
358
|
+
// Not a delegation lifecycle event but valid audit content.
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
341
361
|
else {
|
|
342
362
|
corruptLines.push(index + 1);
|
|
343
363
|
}
|
|
@@ -451,7 +471,17 @@ export async function checkMandatoryDelegations(projectRoot, stage, options = {}
|
|
|
451
471
|
const flowState = await readFlowState(projectRoot, {
|
|
452
472
|
repairFeatureSystem: options.repairFeatureSystem
|
|
453
473
|
});
|
|
454
|
-
const mandatory =
|
|
474
|
+
const mandatory = mandatoryAgentsFor(stage, flowState.track, options.taskClass ?? null);
|
|
475
|
+
const skippedByTrack = mandatory.length === 0 &&
|
|
476
|
+
stageSchema(stage, flowState.track).mandatoryDelegations.length > 0;
|
|
477
|
+
if (skippedByTrack) {
|
|
478
|
+
await recordMandatorySkippedByTrack(projectRoot, {
|
|
479
|
+
stage,
|
|
480
|
+
track: flowState.track,
|
|
481
|
+
taskClass: options.taskClass ?? null,
|
|
482
|
+
runId: flowState.activeRunId
|
|
483
|
+
});
|
|
484
|
+
}
|
|
455
485
|
const { activeRunId } = flowState;
|
|
456
486
|
const ledger = await readDelegationLedger(projectRoot);
|
|
457
487
|
const events = await readDelegationEvents(projectRoot);
|
|
@@ -553,6 +583,37 @@ export async function checkMandatoryDelegations(projectRoot, stage, options = {}
|
|
|
553
583
|
legacyInferredCompletions,
|
|
554
584
|
corruptEventLines: events.corruptLines,
|
|
555
585
|
staleWorkers,
|
|
556
|
-
expectedMode
|
|
586
|
+
expectedMode,
|
|
587
|
+
skippedByTrack
|
|
557
588
|
};
|
|
558
589
|
}
|
|
590
|
+
/**
|
|
591
|
+
* Wave 24 (v6.0.0) — append a non-delegation audit event to
|
|
592
|
+
* `delegation-events.jsonl` recording that the mandatory delegation
|
|
593
|
+
* gate was skipped because of the active track / task class. Plays the
|
|
594
|
+
* same audit role as a `waived` row but does NOT carry an agent —
|
|
595
|
+
* downstream tooling treats `event === "mandatory_delegations_skipped_by_track"`
|
|
596
|
+
* lines as informational.
|
|
597
|
+
*
|
|
598
|
+
* Failures are swallowed: the audit log is best-effort. Missing the
|
|
599
|
+
* event must never block stage advance because the gate skip itself is
|
|
600
|
+
* authoritative.
|
|
601
|
+
*/
|
|
602
|
+
async function recordMandatorySkippedByTrack(projectRoot, params) {
|
|
603
|
+
const eventsPath = delegationEventsPath(projectRoot);
|
|
604
|
+
const payload = {
|
|
605
|
+
event: "mandatory_delegations_skipped_by_track",
|
|
606
|
+
stage: params.stage,
|
|
607
|
+
track: params.track,
|
|
608
|
+
taskClass: params.taskClass,
|
|
609
|
+
runId: params.runId,
|
|
610
|
+
ts: new Date().toISOString()
|
|
611
|
+
};
|
|
612
|
+
try {
|
|
613
|
+
await fs.mkdir(path.dirname(eventsPath), { recursive: true });
|
|
614
|
+
await fs.appendFile(eventsPath, `${JSON.stringify(payload)}\n`, "utf8");
|
|
615
|
+
}
|
|
616
|
+
catch {
|
|
617
|
+
// best-effort audit; never block stage advance.
|
|
618
|
+
}
|
|
619
|
+
}
|
package/dist/flow-state.d.ts
CHANGED
|
@@ -93,6 +93,18 @@ export interface StageInteractionHint {
|
|
|
93
93
|
skipQuestions?: boolean;
|
|
94
94
|
sourceStage?: FlowStage;
|
|
95
95
|
recordedAt?: string;
|
|
96
|
+
/**
|
|
97
|
+
* Wave 23 (v5.0.0) — `/cc-ideate` handoff carry-forward.
|
|
98
|
+
* When a brainstorm run is started from a `/cc-ideate` recommendation,
|
|
99
|
+
* `start-flow` records the originating idea artifact so brainstorm can
|
|
100
|
+
* reuse the divergent + critique + rank work instead of re-generating it.
|
|
101
|
+
*
|
|
102
|
+
* `fromIdeaArtifact` is a workspace-relative POSIX path to
|
|
103
|
+
* `.cclaw/ideas/idea-YYYY-MM-DD-<slug>.md` (or wherever `/cc-ideate`
|
|
104
|
+
* wrote its artifact). `fromIdeaCandidateId` is the chosen `I-#` row.
|
|
105
|
+
*/
|
|
106
|
+
fromIdeaArtifact?: string;
|
|
107
|
+
fromIdeaCandidateId?: string;
|
|
96
108
|
}
|
|
97
109
|
export interface InitialFlowStateOptions {
|
|
98
110
|
activeRunId?: string;
|
package/dist/gate-evidence.d.ts
CHANGED
|
@@ -12,11 +12,23 @@ import { type FlowStage } from "./types.js";
|
|
|
12
12
|
export interface QaLogFloorSignal {
|
|
13
13
|
ok: boolean;
|
|
14
14
|
count: number;
|
|
15
|
+
/**
|
|
16
|
+
* Wave 23 (v5.0.0): always 0. The convergence floor no longer enforces
|
|
17
|
+
* a fixed count. Harness UIs may render `questionBudgetHint(track,
|
|
18
|
+
* stage).recommended` separately as a soft hint.
|
|
19
|
+
*/
|
|
15
20
|
min: number;
|
|
16
21
|
hasStopSignal: boolean;
|
|
22
|
+
/** Wave 23: always false. See `min` note above. */
|
|
17
23
|
liteShortCircuit: boolean;
|
|
18
24
|
skipQuestionsAdvisory: boolean;
|
|
19
25
|
blocking: boolean;
|
|
26
|
+
/** Forcing-question topics deemed addressed in `## Q&A Log`. */
|
|
27
|
+
forcingCovered: string[];
|
|
28
|
+
/** Forcing-question topics still pending (no Q&A row matched). */
|
|
29
|
+
forcingPending: string[];
|
|
30
|
+
/** Ralph-Loop convergence detector verdict for the last 2 rows. */
|
|
31
|
+
noNewDecisions: boolean;
|
|
20
32
|
}
|
|
21
33
|
export interface GateEvidenceCheckResult {
|
|
22
34
|
ok: boolean;
|
package/dist/gate-evidence.js
CHANGED
|
@@ -471,7 +471,10 @@ export async function verifyCurrentStageGateEvidence(projectRoot, flowState, opt
|
|
|
471
471
|
hasStopSignal: floor.hasStopSignal,
|
|
472
472
|
liteShortCircuit: floor.liteShortCircuit,
|
|
473
473
|
skipQuestionsAdvisory: floor.skipQuestionsAdvisory,
|
|
474
|
-
blocking: !floor.ok && !floor.skipQuestionsAdvisory
|
|
474
|
+
blocking: !floor.ok && !floor.skipQuestionsAdvisory,
|
|
475
|
+
forcingCovered: floor.forcingCovered,
|
|
476
|
+
forcingPending: floor.forcingPending,
|
|
477
|
+
noNewDecisions: floor.noNewDecisions
|
|
475
478
|
};
|
|
476
479
|
}
|
|
477
480
|
return {
|
package/dist/harness-adapters.js
CHANGED
|
@@ -349,7 +349,7 @@ Before responding to a coding request:
|
|
|
349
349
|
|
|
350
350
|
Three rules apply to every cclaw stage in this project, regardless of which skills loaded:
|
|
351
351
|
|
|
352
|
-
1. **Q&A
|
|
352
|
+
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.
|
|
353
353
|
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
354
|
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.
|
|
355
355
|
|
|
@@ -19,6 +19,8 @@ interface InternalValidationReport {
|
|
|
19
19
|
corruptEventLines: number[];
|
|
20
20
|
staleWorkers: string[];
|
|
21
21
|
expectedMode: string;
|
|
22
|
+
/** Wave 24: true when mandatoryAgentsFor returned [] for the run's track / taskClass. */
|
|
23
|
+
skippedByTrack: boolean;
|
|
22
24
|
};
|
|
23
25
|
gates: {
|
|
24
26
|
ok: boolean;
|
|
@@ -111,7 +111,8 @@ export async function buildValidationReport(projectRoot, flowState, options = {}
|
|
|
111
111
|
legacyInferredCompletions: delegation.legacyInferredCompletions,
|
|
112
112
|
corruptEventLines: delegation.corruptEventLines,
|
|
113
113
|
staleWorkers: delegation.staleWorkers,
|
|
114
|
-
expectedMode: delegation.expectedMode
|
|
114
|
+
expectedMode: delegation.expectedMode,
|
|
115
|
+
skippedByTrack: delegation.skippedByTrack
|
|
115
116
|
},
|
|
116
117
|
gates: {
|
|
117
118
|
ok: gates.ok,
|
|
@@ -39,6 +39,14 @@ export interface StartFlowArgs {
|
|
|
39
39
|
forceReset: boolean;
|
|
40
40
|
reclassify: boolean;
|
|
41
41
|
quiet: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Wave 23 (v5.0.0) — `/cc-ideate` handoff carry-forward.
|
|
44
|
+
* Workspace-relative POSIX path to `.cclaw/ideas/idea-YYYY-MM-DD-<slug>.md`
|
|
45
|
+
* (or wherever `/cc-ideate` wrote its artifact).
|
|
46
|
+
*/
|
|
47
|
+
fromIdeaArtifact?: string;
|
|
48
|
+
/** Optional `I-#` row id chosen from the idea artifact's ranked list. */
|
|
49
|
+
fromIdeaCandidateId?: string;
|
|
42
50
|
}
|
|
43
51
|
export interface CancelRunArgs {
|
|
44
52
|
reason: string;
|
|
@@ -211,6 +211,8 @@ export function parseStartFlowArgs(tokens) {
|
|
|
211
211
|
let forceReset = false;
|
|
212
212
|
let reclassify = false;
|
|
213
213
|
let quiet = false;
|
|
214
|
+
let fromIdeaArtifact;
|
|
215
|
+
let fromIdeaCandidateId;
|
|
214
216
|
for (let i = 0; i < tokens.length; i += 1) {
|
|
215
217
|
const token = tokens[i];
|
|
216
218
|
const nextToken = tokens[i + 1];
|
|
@@ -259,12 +261,36 @@ export function parseStartFlowArgs(tokens) {
|
|
|
259
261
|
stack = readValue("--stack").trim();
|
|
260
262
|
continue;
|
|
261
263
|
}
|
|
264
|
+
if (token === "--from-idea-artifact" || token.startsWith("--from-idea-artifact=")) {
|
|
265
|
+
const raw = readValue("--from-idea-artifact").trim();
|
|
266
|
+
fromIdeaArtifact = raw.length > 0 ? raw : undefined;
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
if (token === "--from-idea-candidate" || token.startsWith("--from-idea-candidate=")) {
|
|
270
|
+
const raw = readValue("--from-idea-candidate").trim();
|
|
271
|
+
fromIdeaCandidateId = raw.length > 0 ? raw : undefined;
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
262
274
|
throw new Error(`Unknown flag for internal start-flow: ${token}`);
|
|
263
275
|
}
|
|
264
276
|
if (!track) {
|
|
265
277
|
throw new Error("internal start-flow requires --track=<standard|medium|quick>.");
|
|
266
278
|
}
|
|
267
|
-
|
|
279
|
+
if (fromIdeaCandidateId && !fromIdeaArtifact) {
|
|
280
|
+
throw new Error("--from-idea-candidate requires --from-idea-artifact=<path> to be set as well.");
|
|
281
|
+
}
|
|
282
|
+
return {
|
|
283
|
+
track,
|
|
284
|
+
className,
|
|
285
|
+
prompt,
|
|
286
|
+
reason,
|
|
287
|
+
stack,
|
|
288
|
+
forceReset,
|
|
289
|
+
reclassify,
|
|
290
|
+
quiet,
|
|
291
|
+
fromIdeaArtifact,
|
|
292
|
+
fromIdeaCandidateId
|
|
293
|
+
};
|
|
268
294
|
}
|
|
269
295
|
export function parseCancelRunArgs(tokens) {
|
|
270
296
|
let reason;
|
|
@@ -119,6 +119,19 @@ export async function runStartFlow(projectRoot, args, io) {
|
|
|
119
119
|
else {
|
|
120
120
|
nextState = createInitialFlowState({ track: args.track });
|
|
121
121
|
}
|
|
122
|
+
if (args.fromIdeaArtifact) {
|
|
123
|
+
const existingHints = nextState.interactionHints ?? {};
|
|
124
|
+
const existingBrainstorm = existingHints.brainstorm ?? {};
|
|
125
|
+
nextState.interactionHints = {
|
|
126
|
+
...existingHints,
|
|
127
|
+
brainstorm: {
|
|
128
|
+
...existingBrainstorm,
|
|
129
|
+
fromIdeaArtifact: args.fromIdeaArtifact,
|
|
130
|
+
...(args.fromIdeaCandidateId ? { fromIdeaCandidateId: args.fromIdeaCandidateId } : {}),
|
|
131
|
+
recordedAt: new Date().toISOString()
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
122
135
|
await writeFlowState(projectRoot, nextState, { allowReset: true });
|
|
123
136
|
await appendIdeaArtifact(projectRoot, args, current);
|
|
124
137
|
if (!args.quiet) {
|
package/dist/run-persistence.js
CHANGED
|
@@ -246,13 +246,25 @@ function sanitizeInteractionHints(value) {
|
|
|
246
246
|
const skipQuestions = typed.skipQuestions === true ? true : undefined;
|
|
247
247
|
const sourceStage = isFlowStage(typed.sourceStage) ? typed.sourceStage : undefined;
|
|
248
248
|
const recordedAt = typeof typed.recordedAt === "string" ? typed.recordedAt : undefined;
|
|
249
|
-
|
|
249
|
+
const fromIdeaArtifact = typeof typed.fromIdeaArtifact === "string" && typed.fromIdeaArtifact.trim().length > 0
|
|
250
|
+
? typed.fromIdeaArtifact.trim()
|
|
251
|
+
: undefined;
|
|
252
|
+
const fromIdeaCandidateId = typeof typed.fromIdeaCandidateId === "string" && typed.fromIdeaCandidateId.trim().length > 0
|
|
253
|
+
? typed.fromIdeaCandidateId.trim()
|
|
254
|
+
: undefined;
|
|
255
|
+
if (skipQuestions !== true &&
|
|
256
|
+
!sourceStage &&
|
|
257
|
+
!recordedAt &&
|
|
258
|
+
!fromIdeaArtifact &&
|
|
259
|
+
!fromIdeaCandidateId) {
|
|
250
260
|
continue;
|
|
251
261
|
}
|
|
252
262
|
out[stage] = {
|
|
253
263
|
...(skipQuestions ? { skipQuestions } : {}),
|
|
254
264
|
...(sourceStage ? { sourceStage } : {}),
|
|
255
|
-
...(recordedAt ? { recordedAt } : {})
|
|
265
|
+
...(recordedAt ? { recordedAt } : {}),
|
|
266
|
+
...(fromIdeaArtifact ? { fromIdeaArtifact } : {}),
|
|
267
|
+
...(fromIdeaCandidateId ? { fromIdeaCandidateId } : {})
|
|
256
268
|
};
|
|
257
269
|
}
|
|
258
270
|
return out;
|