cclaw-cli 6.1.1 → 6.2.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 +2 -2
- package/dist/artifact-linter/brainstorm.js +13 -13
- package/dist/artifact-linter/design.js +5 -5
- package/dist/artifact-linter/scope.js +3 -3
- package/dist/artifact-linter/shared.d.ts +18 -19
- package/dist/artifact-linter/shared.js +34 -31
- package/dist/artifact-linter.js +4 -0
- package/dist/content/hooks.js +2 -2
- package/dist/content/skills-elicitation.js +8 -19
- package/dist/content/stage-schema.d.ts +3 -3
- package/dist/content/stage-schema.js +27 -4
- package/dist/content/stages/brainstorm.js +5 -5
- package/dist/content/stages/design.js +1 -1
- package/dist/content/stages/scope.js +2 -2
- package/dist/content/start-command.d.ts +2 -2
- package/dist/content/start-command.js +18 -17
- package/dist/content/subagents.js +1 -1
- package/dist/delegation.js +2 -2
- package/dist/flow-state.d.ts +5 -1
- package/dist/flow-state.js +6 -1
- package/dist/gate-evidence.js +4 -3
- package/dist/internal/advance-stage/advance.js +4 -3
- package/dist/internal/advance-stage/parsers.d.ts +2 -1
- package/dist/internal/advance-stage/parsers.js +11 -1
- package/dist/internal/advance-stage/proactive-delegation-trace.d.ts +19 -0
- package/dist/internal/advance-stage/proactive-delegation-trace.js +44 -0
- package/dist/internal/advance-stage/start-flow.js +17 -2
- package/dist/internal/advance-stage/verify.d.ts +0 -8
- package/dist/internal/advance-stage/verify.js +2 -30
- package/dist/run-persistence.js +10 -2
- package/dist/track-heuristics.d.ts +2 -2
- package/dist/track-heuristics.js +11 -6
- package/dist/types.d.ts +2 -0
- package/dist/types.js +1 -0
- package/package.json +1 -1
|
@@ -7,7 +7,7 @@ export const BRAINSTORM = {
|
|
|
7
7
|
complexityTier: "standard",
|
|
8
8
|
skillFolder: "brainstorm",
|
|
9
9
|
skillName: "brainstorm",
|
|
10
|
-
skillDescription: "Problem-discovery stage. Build a concise Problem Decision Record,
|
|
10
|
+
skillDescription: "Problem-discovery stage. Build a concise Problem Decision Record, compare distinct directions under the run's discovery mode (lean / guided / deep), and hand approved decisions to scope.",
|
|
11
11
|
philosophy: {
|
|
12
12
|
hardGate: "Do NOT invoke implementation skills, write code, scaffold projects, or mutate product behavior until a concrete direction is approved by the user.",
|
|
13
13
|
ironLaw: "NO ARTIFACT IS COMPLETE WITHOUT AN EXPLICITLY APPROVED DIRECTION — SILENCE IS NOT APPROVAL.",
|
|
@@ -39,7 +39,7 @@ export const BRAINSTORM = {
|
|
|
39
39
|
"**ADAPTIVE ELICITATION COMES FIRST (no exceptions, no subagent dispatch before).** Load `.cclaw/skills/adaptive-elicitation/SKILL.md`. Walk the brainstorm forcing questions one-at-a-time via the harness-native question tool, append one row to `## Q&A Log` (`Turn | Question | User answer (1-line) | Decision impact`) after each user answer **and stamp the row's `Decision impact` cell with the matching `[topic:<id>]` tag** (e.g. `[topic:pain]`). Continue until every forcing-question topic id is tagged on a row OR Ralph-Loop convergence detector says no new decision-changing rows in last 2 iterations OR user records an explicit stop-signal row. Only then proceed to delegations, drafts, or analysis. The linter `qa_log_unconverged` rule will block `stage-complete` if convergence is not reached.",
|
|
40
40
|
"**Explore project context** — after the elicitation loop converges, inspect existing files/docs/recent activity to refine the Discovered context section; capture matching files/patterns/seeds in `Context > Discovered context` so downstream stages don't redo discovery.",
|
|
41
41
|
"**Brainstorm forcing questions (must be covered or explicitly waived)** — `pain: what pain are we solving`; `direct-path: what is the direct path`; `do-nothing: what happens if we do nothing`; `operator: who is the first operator/user affected`; `no-go: what no-go boundaries are non-negotiable`. Tag the matching `## Q&A Log` row's `Decision impact` cell with `[topic:<id>]` (e.g. `[topic:pain]`) so the linter can verify coverage in any natural language. Tags are MANDATORY for forcing-question rows; un-tagged rows do NOT count toward coverage.",
|
|
42
|
-
"**
|
|
42
|
+
"**Discovery posture (flow-state `discoveryMode`)** — follow `lean` / `guided` / `deep` from the active run. Use lean for smallest safe discovery pass; guided as the default balanced pass; escalate to deep when ambiguity, architecture, external dependency, security/data risk, or explicit think-bigger requests warrant fuller option pressure and mandatory specialist coverage.",
|
|
43
43
|
"**Write the Problem Decision Record** — pick a free-form `Frame type` label that names how this work is framed (examples: product, technical-maintenance, research-spike, ops-incident, infrastructure), then fill the universal Framing fields: affected user/role/operator, current state/failure mode/opportunity, desired observable outcome, evidence/signal, why now, do-nothing consequence, and non-goals.",
|
|
44
44
|
"**Premise check (one pass)** — answer the three gstack-style questions in the artifact body: *Right problem? Direct path? What if we do nothing?* Take a position; do not hedge.",
|
|
45
45
|
"**Reframe with How Might We** — write a single `How Might We …?` line that names the user/operator, the desired outcome, and the constraint. This is the altitude check before approaches.",
|
|
@@ -61,7 +61,7 @@ export const BRAINSTORM = {
|
|
|
61
61
|
interactionProtocol: [
|
|
62
62
|
"\"If something is unclear, stop. Name what's confusing. Ask.\"",
|
|
63
63
|
"Start from observed project context; if the idea is vague, first narrow the project type with **one** structured question, then keep going.",
|
|
64
|
-
"
|
|
64
|
+
"Honor the run's `discoveryMode` (`lean` | `guided` | `deep`) from flow-state: lean stays fastest, guided is the default breadth, deep pulls in fuller critique and mandatory delegations when the run is classified that way.",
|
|
65
65
|
"Lead with the premise check (right problem / direct path / what if nothing) and the `How Might We` reframing before approaches; both go in the artifact, not just the chat.",
|
|
66
66
|
"Ask at most one question per turn, only when decision-changing; if using a structured question tool, send exactly one question object, not a multi-question form.",
|
|
67
67
|
"Run the shared adaptive elicitation cycle from `.cclaw/skills/adaptive-elicitation/SKILL.md`, including stop-signal handling (RU/EN/UA), smart-skip, conditional grilling triggers, and append-only `## Q&A Log` updates.",
|
|
@@ -72,7 +72,7 @@ export const BRAINSTORM = {
|
|
|
72
72
|
"State exactly what is being approved, then **STOP** until the user explicitly approves the artifact."
|
|
73
73
|
],
|
|
74
74
|
process: [
|
|
75
|
-
"Explore project context and
|
|
75
|
+
"Explore project context and align work to the run's discovery mode (lean / guided / deep).",
|
|
76
76
|
"Use compact discovery for simple apps, short-circuit implementation-only asks, or ask one decision-changing question at a time.",
|
|
77
77
|
"Compare 2-3 distinct approaches, including a higher-upside challenger.",
|
|
78
78
|
"Collect reaction, then recommend with rationale tied to that reaction.",
|
|
@@ -145,7 +145,7 @@ export const BRAINSTORM = {
|
|
|
145
145
|
{ section: "Clarity Gate", required: false, validationRule: "Recommended before recommendation lock: include ambiguity score (0.00-1.00), decision boundaries, reaffirmed non-goals, and residual-risk handoff for scope." },
|
|
146
146
|
{ section: "Sharpening Questions", required: false, validationRule: "Recommended only when needed: one decision-changing question per turn with explicit `Decision impact`; compact tasks may record `None - early exit` with rationale." },
|
|
147
147
|
{ section: "Clarifying Questions", required: false, validationRule: "Must capture question, answer, and decision impact for each clarifying question." },
|
|
148
|
-
{ section: "Approach Tier", required: true, validationRule: "Must
|
|
148
|
+
{ section: "Approach Tier", required: true, validationRule: "Must record how much discovery/evidence breadth is warranted in discoveryMode terms (`lean`, `guided`, or `deep`) relative to flow-state—and explain what risk or uncertainty drives that calibration (not merely the label)." },
|
|
149
149
|
{ section: "Short-Circuit Decision", required: false, validationRule: "Must include Status/Why/Scope handoff lines when short-circuit is discussed; compact stubs are valid for concrete asks." },
|
|
150
150
|
{ section: "Reference Pattern Candidates", required: false, validationRule: "Recommended when examples influence direction: list pattern/source, reusable invariant, accept/reject/defer disposition, and reason before approaches are finalized." },
|
|
151
151
|
{ section: "Idea Evidence Carry-forward", required: false, validationRule: "Wave 23 (v5.0.0): when `flow-state.interactionHints.brainstorm.fromIdeaArtifact` is set, this section MUST cite the idea artifact path and the chosen `I-#`, list reused fields (Title, Why-now, Expected impact, Risk, Counter-argument), and explicitly state that only challenger row(s) were newly generated. Honors `/cc-ideate` handoff so divergent + critique + rank work is reused, not redone." },
|
|
@@ -78,7 +78,7 @@ export const DESIGN = {
|
|
|
78
78
|
"Run compact research by default; write `.cclaw/artifacts/02a-research.md` only when deep/high-risk uncertainty requires a separate research artifact.",
|
|
79
79
|
"Run investigator pass plus scope challenge/search-before-building.",
|
|
80
80
|
"Walk review sections interactively and lock boundaries, data flow, state transitions, edge cases, and failure modes.",
|
|
81
|
-
"Cover security, observability, deployment, tests, and performance for
|
|
81
|
+
"Cover security, observability, deployment, tests, and performance for guided/deep-shaped design work; lean slices may omit heavy add-ons only when scope and risk justify the compact path.",
|
|
82
82
|
"Run stale-diagram audit (enabled by default unless explicitly disabled).",
|
|
83
83
|
"Produce required outputs: blast-radius diff (scope owns full repo audit), tier diagrams, failure table, completion dashboard. Out-of-scope is carried from scope via Upstream Handoff — do NOT re-author it.",
|
|
84
84
|
"Plant high-upside deferred ideas when useful and reconcile critic/outside-voice findings.",
|
|
@@ -52,7 +52,7 @@ export const SCOPE = {
|
|
|
52
52
|
"**Premise carry-forward (do NOT re-author)** — brainstorm OWNS the premise check (right problem / direct path / what if nothing). Cite brainstorm's `## Premise Check` section in `## Upstream Handoff > Decisions carried forward`. Add a row to `## Premise Drift` only when the scope-stage Q&A surfaced NEW evidence that materially changes the brainstorm answer (e.g. new constraint, new user signal). Otherwise mark `Premise Drift: None` — do not duplicate the brainstorm premise table.",
|
|
53
53
|
"**Conditional 10-star boundary** — for deep/high-risk/product-strategy work, show what would make the product meaningfully better, then explicitly choose what ships now, what is deferred, and what is excluded without vague `later/for now` placeholders. Skip this for straightforward repair work and record `not needed: compact scope`.",
|
|
54
54
|
"**Pick one operational mode with the user** — HOLD SCOPE preserves focus; SELECTIVE EXPANSION cherry-picks high-leverage reference ideas; SCOPE EXPANSION explores ambitious alternatives; SCOPE REDUCTION cuts to the essential wedge. Recommend one, state why and what signal would change it, then keep elicitation focused until the user either approves or asks to proceed with draft boundaries.",
|
|
55
|
-
"**Run mode-specific analysis only to needed depth** —
|
|
55
|
+
"**Run mode-specific analysis only to needed depth** — lean discovery keeps the selected-mode row compact; guided adds the standard contract rows; deep may add Landscape Check, Taste Calibration, Reference Pattern Registry, Reference Pull, Ambitious Alternatives, and Ruthless Minimum Slice evidence when mode/risk warrants it.",
|
|
56
56
|
"**Decision-driver contract** — list weighted decision drivers (value, risk, reversibility, effort, timeline) and score candidate scope moves so the selected mode and boundaries are evidence-backed, not preference-led.",
|
|
57
57
|
"**Architecture handoff (do NOT pick architecture tier here)** — design OWNS architecture choice (minimum-viable / product-grade / ideal). Scope only picks the SCOPE MODE (HOLD/SELECTIVE/EXPAND/REDUCE) and boundary; record in `## Scope Contract > Design handoff` what design must decide (e.g. `architecture-tier`, `framework`, `data-model`). Do NOT enumerate Implementation Alternatives in scope.",
|
|
58
58
|
"**Constraints (carry-forward from brainstorm/external sources)** — record explicit external/regulatory/system/integration constraints in `## Scope Contract > Constraints`. Spec OWNS testable assumptions (`## Assumptions Before Finalization`); do NOT duplicate constraint material as assumption material.",
|
|
@@ -65,7 +65,7 @@ export const SCOPE = {
|
|
|
65
65
|
"\"Strong success criteria let you loop independently. Weak criteria require constant clarification.\"",
|
|
66
66
|
decisionProtocolInstruction("scope mode selection", "present expand/selective/hold/reduce as labeled options with trade-offs and mark one as (recommended)", "recommend the option that best covers the prime-directive failure modes, four data-flow paths, observability, and deferred handling for the in-scope set with the smallest blast radius. Base your recommendation on default heuristics: greenfield -> expand, enhancement -> selective, bugfix/hotfix/refactor -> hold, broad blast radius -> reduce"),
|
|
67
67
|
"Run the shared adaptive elicitation cycle from `.cclaw/skills/adaptive-elicitation/SKILL.md`, including stop-signal handling (RU/EN/UA), smart-skip, conditional grilling triggers, and append-only `## Q&A Log` updates.",
|
|
68
|
-
"**Lead with adaptive elicitation, not with a proposed contract.** First walk scope forcing questions one-at-a-time per `adaptive-elicitation` skill. Only AFTER the Q&A loop converges (forcing-Qs answered/waived OR user stop-signal row recorded) propose the scope contract draft for approval.
|
|
68
|
+
"**Lead with adaptive elicitation, not with a proposed contract.** First walk scope forcing questions one-at-a-time per `adaptive-elicitation` skill. Only AFTER the Q&A loop converges (forcing-Qs answered/waived OR user stop-signal row recorded) propose the scope contract draft for approval. Lean discovery may compress: ask the smallest forcing-Q set that satisfies the convergence floor, then propose contract.",
|
|
69
69
|
"For low-risk concrete asks, keep the proposal compact but still explicit: recommend (do not auto-select) one mode, show exact in/out/deferred boundaries, and request explicit approval before finalizing the artifact or completing the stage.",
|
|
70
70
|
"Cite brainstorm's premise via `## Upstream Handoff` and take a firm position on whether scope-stage Q&A surfaced any premise drift; do NOT re-author the brainstorm Premise Check table.",
|
|
71
71
|
"Push back on weak framing: vague scope needs a specific user/problem, platform vision needs a narrow wedge, social proof needs behavioral evidence.",
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Command contract for /cc — the unified entry point.
|
|
3
3
|
* No args → reads existing flow state and progresses it when a tracked flow
|
|
4
4
|
* already exists; missing state/fresh placeholder state blocks with
|
|
5
|
-
* init/start guidance. With prompt → classifies the idea,
|
|
6
|
-
* starts the first stage of that track (brainstorm for medium/standard, spec for quick).
|
|
5
|
+
* init/start guidance. With prompt → classifies the idea, asks for one discovery mode,
|
|
6
|
+
* resolves the internal track, and starts the first stage of that track (brainstorm for medium/standard, spec for quick).
|
|
7
7
|
*/
|
|
8
8
|
export declare function startCommandContract(): string;
|
|
9
9
|
/**
|
|
@@ -9,8 +9,8 @@ function flowStatePath() {
|
|
|
9
9
|
* Command contract for /cc — the unified entry point.
|
|
10
10
|
* No args → reads existing flow state and progresses it when a tracked flow
|
|
11
11
|
* already exists; missing state/fresh placeholder state blocks with
|
|
12
|
-
* init/start guidance. With prompt → classifies the idea,
|
|
13
|
-
* starts the first stage of that track (brainstorm for medium/standard, spec for quick).
|
|
12
|
+
* init/start guidance. With prompt → classifies the idea, asks for one discovery mode,
|
|
13
|
+
* resolves the internal track, and starts the first stage of that track (brainstorm for medium/standard, spec for quick).
|
|
14
14
|
*/
|
|
15
15
|
export function startCommandContract() {
|
|
16
16
|
const flowPath = flowStatePath();
|
|
@@ -21,7 +21,7 @@ export function startCommandContract() {
|
|
|
21
21
|
**The unified entry point for the cclaw flow.**
|
|
22
22
|
|
|
23
23
|
- \`/cc\` (no arguments) → reads existing flow state and resumes/progresses the active flow. If flow state is missing or still a fresh init placeholder, stop and guide the user to run \`/cc <prompt>\` or \`npx cclaw-cli init\`; do not silently create a brainstorm run.
|
|
24
|
-
- \`/cc <prompt>\` (with an idea/description) → saves the prompt as idea context and starts the first stage of the resolved track.
|
|
24
|
+
- \`/cc <prompt>\` (with an idea/description) → saves the prompt as idea context, asks for one discovery mode, and starts the first stage of the resolved internal track.
|
|
25
25
|
|
|
26
26
|
This is the **recommended way to start, resume, and continue** working with cclaw.
|
|
27
27
|
|
|
@@ -72,7 +72,7 @@ ${conversationLanguagePolicyMarkdown()}
|
|
|
72
72
|
|
|
73
73
|
5. Read \`${flowPath}\`.
|
|
74
74
|
6. If flow already has completed stages, warn the user that starting a new tracked flow will reset progress. Ask for confirmation before proceeding. A fresh init placeholder state with \`completedStages: []\`, no passed gates, and no \`00-idea.md\` is **not** an active flow; do not ask the user to resume it.
|
|
75
|
-
7. **
|
|
75
|
+
7. **Internal track heuristic** — classify the idea text and compute an internal track recommendation before any state mutation:
|
|
76
76
|
- First, load \`${RUNTIME_ROOT}/config.yaml\`. If \`trackHeuristics\` is defined, apply those per-track vocabulary hints (\`fallback\`, \`tracks.<id>.{triggers,veto}\`) on top of the built-in defaults. Evaluation order is always \`standard -> medium -> quick\` (narrow-to-broad).
|
|
77
77
|
- **quick** (\`spec → tdd → review → ship\`) — single-purpose work where the spec is essentially already known. Quick skips ceremony, not safety: spec approval, TDD evidence, review, and ship gates remain mandatory.
|
|
78
78
|
Triggers (case-insensitive substring or close variant): \`bug\`, \`bugfix\`, \`fix\`, \`hotfix\`, \`patch\`, \`typo\`, \`regression\`, \`copy change\`, \`rename\`, \`bump\`, \`upgrade dep\`, \`config tweak\`, \`docs only\`, \`comment\`, \`lint\`, \`format\`, \`small\`, \`tiny\`, \`one-liner\`, \`revert\`.
|
|
@@ -82,14 +82,14 @@ ${conversationLanguagePolicyMarkdown()}
|
|
|
82
82
|
Triggers: \`new feature\`, \`refactor\`, \`migration\`, \`platform\`, \`architecture\`, \`schema\`, \`integrate\`, \`workflow\`, \`onboarding\`, or any prompt that does not match quick/medium confidently.
|
|
83
83
|
- When triggers conflict, prefer **standard** over **medium**, and **medium** over **quick**.
|
|
84
84
|
- Report **track selection confidence** as high/medium/low with the matched trigger or fallback reason, plus one sentence explaining what the selected track skips and what safety gates remain. Be explicit that this recommendation is advisory until the user accepts and the managed helper writes state; after that, \`/cc\` follows the configured track.
|
|
85
|
-
8. Present one compact **Start framing** summary: class,
|
|
86
|
-
9.
|
|
87
|
-
> \`
|
|
88
|
-
> \`
|
|
89
|
-
>
|
|
85
|
+
8. Present one compact **Start framing** summary: class, internal track recommendation, track selection confidence, stack, origin docs, seed recalls, and the recommended next action. Ask a single confirmation question only when there is a destructive reset, a real contradiction, or ambiguous software/non-software classification.
|
|
86
|
+
9. Ask one explicit **discovery mode** question and make it the only normal start-of-run user choice:
|
|
87
|
+
> \`Choose discovery mode: Lean / Guided / Deep\`.
|
|
88
|
+
> \`Lean\` = compact shaping, \`Guided\` = recommended default with enough questions and key specialists before drafting, \`Deep\` = stronger probing and broader specialist/research passes.
|
|
89
|
+
> Mention the internal track recommendation only as context, not as the primary decision. Offer track override only when reset, contradiction, or reclassification evidence makes the internal recommendation suspect.
|
|
90
90
|
If the harness's native ask tool is available (\`AskUserQuestion\` / \`AskQuestion\` / \`question\` / \`request_user_input\`), send exactly ONE question; on schema error, fall back to a plain-text lettered list.
|
|
91
91
|
10. Start the tracked flow only through the managed helper:
|
|
92
|
-
\`node .cclaw/hooks/start-flow.mjs --track=<quick|medium|standard> --class=<class> --prompt=<prompt> --stack=<stack> --reason=<matched heuristic>\`
|
|
92
|
+
\`node .cclaw/hooks/start-flow.mjs --track=<quick|medium|standard> --discovery-mode=<lean|guided|deep> --class=<class> --prompt=<prompt> --stack=<stack> --reason=<matched heuristic>\`
|
|
93
93
|
If this helper fails, STOP. Report one human-readable failure line from the JSON \`error\` field, include the helper JSON payload in a fenced \`json\` block, and never echo the invoking command line. Do **not** manually edit \`${flowPath}\`.
|
|
94
94
|
11. The helper persists \`${flowPath}\`, computes \`skippedStages\`, sets the first stage for the track, resets the gate catalog, and writes \`.cclaw/artifacts/00-idea.md\`.
|
|
95
95
|
12. Load the **first-stage skill for the chosen track** and its command file:
|
|
@@ -103,9 +103,9 @@ ${conversationLanguagePolicyMarkdown()}
|
|
|
103
103
|
If during any stage the agent discovers evidence that contradicts the initial Phase 0 / track decision (e.g. a supposedly \`trivial\` change turns out to require schema migration, a \`quick\` bug fix turns out to need design discussion, an origin doc reveals scope 3× larger than the prompt), STOP and re-classify:
|
|
104
104
|
|
|
105
105
|
1. Surface the new evidence in plain text.
|
|
106
|
-
2. Propose the updated \`Class
|
|
106
|
+
2. Propose the updated \`Class\`, internal \`Track\`, and (when discovery posture should change) \`Discovery mode\` with a one-line reason.
|
|
107
107
|
3. Use the Decision Protocol to let the user accept, override, or cancel.
|
|
108
|
-
4. On acceptance: run \`node .cclaw/hooks/start-flow.mjs --reclassify --track=<new-track> --class=<new-class> --reason=<why>\`. The helper appends a \`Reclassification:\` entry to \`00-idea.md\` and updates flow state atomically. If it fails, STOP and report one human-readable line plus the helper JSON payload in a fenced \`json\` block; never echo the invoking command line. Do NOT manually edit \`flow-state.json\`.
|
|
108
|
+
4. On acceptance: run \`node .cclaw/hooks/start-flow.mjs --reclassify --track=<new-track> --discovery-mode=<lean|guided|deep> --class=<new-class> --reason=<why>\`. The helper appends a \`Reclassification:\` entry to \`00-idea.md\` and updates flow state atomically. If it fails, STOP and report one human-readable line plus the helper JSON payload in a fenced \`json\` block; never echo the invoking command line. Do NOT manually edit \`flow-state.json\`.
|
|
109
109
|
|
|
110
110
|
### Without prompt (\`/cc\`)
|
|
111
111
|
|
|
@@ -153,7 +153,7 @@ description: "Unified entry point for the cclaw flow. No args = resume/next. Wit
|
|
|
153
153
|
\`/cc\` is the **starting command** for cclaw. It intelligently routes:
|
|
154
154
|
|
|
155
155
|
- **No arguments** → resumes or progresses an existing tracked flow; missing/fresh placeholder state blocks with start guidance
|
|
156
|
-
- **With a prompt** → classifies the task,
|
|
156
|
+
- **With a prompt** → classifies the task, asks for one discovery mode (lean/guided/deep), resolves an internal track (quick/medium/standard), and starts the **first stage of that track** (not always brainstorm — e.g. the \`quick\` track starts at \`spec\`)
|
|
157
157
|
|
|
158
158
|
## HARD-GATE
|
|
159
159
|
|
|
@@ -174,7 +174,7 @@ ${conversationLanguagePolicyMarkdown()}
|
|
|
174
174
|
- Ask: "Continue with reset? (A) Yes, start fresh (B) No, resume current flow"
|
|
175
175
|
- If (B) → switch to Path B behavior.
|
|
176
176
|
If \`completedStages\` is empty, all gate \`passed\` arrays are empty, and \`${RUNTIME_ROOT}/artifacts/00-idea.md\` is missing, treat it as a fresh init placeholder — do **not** ask whether to continue the current flow.
|
|
177
|
-
7. **Classify the idea** using the heuristic below and present one compact Start framing summary (class, track, stack, origin docs, seed recalls, next action). Wait for explicit confirmation or override before mutating any state only when reset/conflict/ambiguity makes it necessary.
|
|
177
|
+
7. **Classify the idea** using the heuristic below and present one compact Start framing summary (class, internal track recommendation, stack, origin docs, seed recalls, next action). Wait for explicit confirmation or override before mutating any state only when reset/conflict/ambiguity makes it necessary.
|
|
178
178
|
- If \`${RUNTIME_ROOT}/config.yaml\` defines \`trackHeuristics\`, apply those vocabulary hints (\`fallback\`, \`tracks.<id>.{triggers,veto}\`) on top of built-in defaults. Evaluation order is fixed: \`standard -> medium -> quick\`. (Honest note: this is advisory prose; the LLM applies it, not a Node-level router.)
|
|
179
179
|
|
|
180
180
|
**Track heuristic** (lowercase substring match against the user prompt):
|
|
@@ -187,12 +187,13 @@ ${conversationLanguagePolicyMarkdown()}
|
|
|
187
187
|
|
|
188
188
|
- On conflict, prefer \`standard\` over \`medium\`, and \`medium\` over \`quick\`.
|
|
189
189
|
- Always state the recommendation as a one-line reason citing matched triggers and a high/medium/low track selection confidence. Clarify that the heuristic is advisory until the managed helper writes state; after that, \`/cc\` follows the selected track. Include override guidance: switch to standard when architecture, schema, migration, security, or unclear scope appears; switch to medium when product framing is needed but architecture is known.
|
|
190
|
-
8.
|
|
190
|
+
8. Ask for the single explicit start choice: \`Lean / Guided / Deep\`. Use \`Guided\` as the recommended default unless the user clearly wants compact shaping or unusually deep probing. Keep track internal unless contradiction/reset/reclassification requires surfacing an override.
|
|
191
|
+
9. Run the managed start helper: \`node .cclaw/hooks/start-flow.mjs --track=<quick|medium|standard> --discovery-mode=<lean|guided|deep> --class=<class> --prompt=<prompt> --stack=<stack> --reason=<matched heuristic>\`. The helper writes \`${flowPath}\`, including \`discoveryMode\`, computes \`skippedStages\`, resets the gate catalog, and writes \`${RUNTIME_ROOT}/artifacts/00-idea.md\`. If it fails, STOP, report one human-readable failure line from the JSON \`error\` field, and include the helper JSON payload in a fenced \`json\` block; do not echo the invoking command line, and do not manually edit flow state.
|
|
191
192
|
9. Load and execute the **first stage skill of the chosen track** (\`brainstorm\` for medium/standard, \`spec\` for quick) plus its matching command file.
|
|
192
193
|
|
|
193
194
|
### Reclassification on discovery
|
|
194
195
|
|
|
195
|
-
If mid-stage evidence contradicts the initial Class/Track decision (the "trivial" change needs a migration, the "quick" bug fix needs architecture work, an origin doc multiplies scope), STOP and re-classify using the Decision Protocol. On acceptance, run \`node .cclaw/hooks/start-flow.mjs --reclassify --track=<new-track> --class=<new-class> --reason=<why>\`; the helper records \`Reclassification:\` in \`00-idea.md\` and updates state atomically. If it fails, report one human-readable line plus the helper JSON payload in a fenced \`json\` block, never echo the invoking command line, and do not rewrite prior artifacts or manually edit flow-state.
|
|
196
|
+
If mid-stage evidence contradicts the initial Class/Track/Discovery decision (the "trivial" change needs a migration, the "quick" bug fix needs architecture work, an origin doc multiplies scope), STOP and re-classify using the Decision Protocol. On acceptance, run \`node .cclaw/hooks/start-flow.mjs --reclassify --track=<new-track> --discovery-mode=<lean|guided|deep> --class=<new-class> --reason=<why>\`; the helper records \`Reclassification:\` in \`00-idea.md\` and updates state atomically. If it fails, report one human-readable line plus the helper JSON payload in a fenced \`json\` block, never echo the invoking command line, and do not rewrite prior artifacts or manually edit flow-state.
|
|
196
197
|
|
|
197
198
|
### Path B: \`/cc\` (no arguments)
|
|
198
199
|
|
|
@@ -217,6 +218,6 @@ Use \`/cc\` for the happy path:
|
|
|
217
218
|
| Progressing after completing a stage | \`/cc\` |
|
|
218
219
|
| Starting with a specific idea | \`/cc <idea>\` |
|
|
219
220
|
|
|
220
|
-
\`/cc <prompt>\` resolves class + track and starts
|
|
221
|
+
\`/cc <prompt>\` resolves class + internal track, asks for one discovery mode, and starts the selected track's first stage; \`/cc\` without a prompt follows the current \`flow-state.json\`.
|
|
221
222
|
`;
|
|
222
223
|
}
|
|
@@ -18,7 +18,7 @@ function automaticStageDelegationTable() {
|
|
|
18
18
|
|---|---|---|
|
|
19
19
|
${rows}
|
|
20
20
|
|
|
21
|
-
> **Track-aware skip (Wave 24, v6.0.0):** mandatory agents are skipped entirely when \`track === "quick"\` OR \`taskClass === "software-bugfix"\`. Use \`mandatoryAgentsFor(stage, track, taskClass)\` from \`src/content/stage-schema.ts\` for the authoritative list at runtime. Proactive agents
|
|
21
|
+
> **Track-aware skip (Wave 24, v6.0.0):** mandatory agents are skipped entirely when \`track === "quick"\` OR \`taskClass === "software-bugfix"\`. Use \`mandatoryAgentsFor(stage, track, taskClass)\` from \`src/content/stage-schema.ts\` for the authoritative list at runtime. Proactive agents are trigger-driven opportunities, not a blanket completion gate, and lean/lightweight early-stage runs may intentionally record none.`;
|
|
22
22
|
}
|
|
23
23
|
function stageSummary(stage) {
|
|
24
24
|
return stageDelegationSummary("standard").find((row) => row.stage === stage)
|
package/dist/delegation.js
CHANGED
|
@@ -481,9 +481,9 @@ export async function checkMandatoryDelegations(projectRoot, stage, options = {}
|
|
|
481
481
|
// via `flow-state.json`. Forward-typed `null` callers still suppress
|
|
482
482
|
// the lookup explicitly; only `undefined` triggers the fallback.
|
|
483
483
|
const resolvedTaskClass = options.taskClass !== undefined ? options.taskClass : flowState.taskClass ?? null;
|
|
484
|
-
const mandatory = mandatoryAgentsFor(stage, flowState.track, resolvedTaskClass);
|
|
484
|
+
const mandatory = mandatoryAgentsFor(stage, flowState.track, resolvedTaskClass, "standard", flowState.discoveryMode);
|
|
485
485
|
const skippedByTrack = mandatory.length === 0 &&
|
|
486
|
-
stageSchema(stage, flowState.track).mandatoryDelegations.length > 0;
|
|
486
|
+
stageSchema(stage, flowState.track, flowState.discoveryMode, resolvedTaskClass).mandatoryDelegations.length > 0;
|
|
487
487
|
if (skippedByTrack) {
|
|
488
488
|
await recordMandatorySkippedByTrack(projectRoot, {
|
|
489
489
|
stage,
|
package/dist/flow-state.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FlowStage, FlowTrack, TransitionRule } from "./types.js";
|
|
1
|
+
import type { DiscoveryMode, FlowStage, FlowTrack, TransitionRule } from "./types.js";
|
|
2
2
|
export declare const TRANSITION_RULES: TransitionRule[];
|
|
3
3
|
export declare const FLOW_STATE_SCHEMA_VERSION = 1;
|
|
4
4
|
export interface StageGateState {
|
|
@@ -76,6 +76,8 @@ export interface FlowState {
|
|
|
76
76
|
stageGateCatalog: Record<FlowStage, StageGateState>;
|
|
77
77
|
/** Active flow track (determines which stages are in the critical path for this run). */
|
|
78
78
|
track: FlowTrack;
|
|
79
|
+
/** Run-level upstream shaping mode chosen once at start (`lean` / `guided` / `deep`). */
|
|
80
|
+
discoveryMode: DiscoveryMode;
|
|
79
81
|
/**
|
|
80
82
|
* Wave 25 (v6.1.0) — optional task class for the active run.
|
|
81
83
|
*
|
|
@@ -123,8 +125,10 @@ export interface StageInteractionHint {
|
|
|
123
125
|
export interface InitialFlowStateOptions {
|
|
124
126
|
activeRunId?: string;
|
|
125
127
|
track?: FlowTrack;
|
|
128
|
+
discoveryMode?: DiscoveryMode;
|
|
126
129
|
}
|
|
127
130
|
export declare function isFlowTrack(value: unknown): value is FlowTrack;
|
|
131
|
+
export declare function isDiscoveryMode(value: unknown): value is DiscoveryMode;
|
|
128
132
|
export declare function trackStages(track: FlowTrack): FlowStage[];
|
|
129
133
|
export declare function skippedStagesForTrack(track: FlowTrack): FlowStage[];
|
|
130
134
|
export declare function firstStageForTrack(track: FlowTrack): FlowStage;
|
package/dist/flow-state.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { buildTransitionRules, orderedStageSchemas, stageGateIds, stageRecommendedGateIds } from "./content/stage-schema.js";
|
|
2
|
-
import { FLOW_STAGES, FLOW_TRACKS, TRACK_STAGES } from "./types.js";
|
|
2
|
+
import { DISCOVERY_MODES, FLOW_STAGES, FLOW_TRACKS, TRACK_STAGES } from "./types.js";
|
|
3
3
|
export const TRANSITION_RULES = buildTransitionRules();
|
|
4
4
|
export const FLOW_STATE_SCHEMA_VERSION = 1;
|
|
5
5
|
/**
|
|
@@ -47,6 +47,9 @@ export function createInitialCloseoutState() {
|
|
|
47
47
|
export function isFlowTrack(value) {
|
|
48
48
|
return typeof value === "string" && FLOW_TRACKS.includes(value);
|
|
49
49
|
}
|
|
50
|
+
export function isDiscoveryMode(value) {
|
|
51
|
+
return typeof value === "string" && DISCOVERY_MODES.includes(value);
|
|
52
|
+
}
|
|
50
53
|
export function trackStages(track) {
|
|
51
54
|
return [...TRACK_STAGES[track]];
|
|
52
55
|
}
|
|
@@ -67,6 +70,7 @@ export function createInitialFlowState(activeRunIdOrOptions = {}, maybeTrack) {
|
|
|
67
70
|
: activeRunIdOrOptions;
|
|
68
71
|
const activeRunId = options.activeRunId ?? createRunId();
|
|
69
72
|
const track = options.track ?? "standard";
|
|
73
|
+
const discoveryMode = options.discoveryMode ?? "guided";
|
|
70
74
|
const skippedStages = skippedStagesForTrack(track);
|
|
71
75
|
const stageGateCatalog = {};
|
|
72
76
|
for (const schema of orderedStageSchemas(track)) {
|
|
@@ -87,6 +91,7 @@ export function createInitialFlowState(activeRunIdOrOptions = {}, maybeTrack) {
|
|
|
87
91
|
guardEvidence: {},
|
|
88
92
|
stageGateCatalog,
|
|
89
93
|
track,
|
|
94
|
+
discoveryMode,
|
|
90
95
|
skippedStages,
|
|
91
96
|
staleStages: {},
|
|
92
97
|
rewinds: [],
|
package/dist/gate-evidence.js
CHANGED
|
@@ -210,7 +210,7 @@ const DESIGN_RESEARCH_REQUIRED_SECTIONS = [
|
|
|
210
210
|
];
|
|
211
211
|
export async function verifyCurrentStageGateEvidence(projectRoot, flowState, options = {}) {
|
|
212
212
|
const stage = flowState.currentStage;
|
|
213
|
-
const schema = stageSchema(stage, flowState.track);
|
|
213
|
+
const schema = stageSchema(stage, flowState.track, flowState.discoveryMode, flowState.taskClass ?? null);
|
|
214
214
|
const catalog = flowState.stageGateCatalog[stage];
|
|
215
215
|
const required = schema.requiredGates
|
|
216
216
|
.filter((gate) => gate.tier === "required")
|
|
@@ -462,6 +462,7 @@ export async function verifyCurrentStageGateEvidence(projectRoot, flowState, opt
|
|
|
462
462
|
const skipQuestionsHint = flowState.interactionHints?.[stage]?.skipQuestions === true ||
|
|
463
463
|
(options.extraStageFlags ?? []).includes("--skip-questions");
|
|
464
464
|
const floor = evaluateQaLogFloor(qaLogBody, flowState.track, stage, {
|
|
465
|
+
discoveryMode: flowState.discoveryMode,
|
|
465
466
|
skipQuestions: skipQuestionsHint
|
|
466
467
|
});
|
|
467
468
|
qaLogFloor = {
|
|
@@ -498,7 +499,7 @@ export function verifyCompletedStagesGateClosure(flowState) {
|
|
|
498
499
|
const issues = [];
|
|
499
500
|
const openStages = [];
|
|
500
501
|
for (const stage of flowState.completedStages) {
|
|
501
|
-
const schema = stageSchema(stage, flowState.track);
|
|
502
|
+
const schema = stageSchema(stage, flowState.track, flowState.discoveryMode, flowState.taskClass ?? null);
|
|
502
503
|
const catalog = flowState.stageGateCatalog[stage];
|
|
503
504
|
const required = schema.requiredGates
|
|
504
505
|
.filter((gate) => gate.tier === "required")
|
|
@@ -526,7 +527,7 @@ export function verifyCompletedStagesGateClosure(flowState) {
|
|
|
526
527
|
}
|
|
527
528
|
export function reconcileCurrentStageGateCatalog(flowState) {
|
|
528
529
|
const stage = flowState.currentStage;
|
|
529
|
-
const schema = stageSchema(stage, flowState.track);
|
|
530
|
+
const schema = stageSchema(stage, flowState.track, flowState.discoveryMode, flowState.taskClass ?? null);
|
|
530
531
|
const required = schema.requiredGates
|
|
531
532
|
.filter((gate) => gate.tier === "required")
|
|
532
533
|
.map((gate) => gate.id);
|
|
@@ -11,7 +11,7 @@ import { stageSchema } from "../../content/stage-schema.js";
|
|
|
11
11
|
import { extractReviewLoopEnvelopeFromArtifact } from "../../content/review-loop.js";
|
|
12
12
|
import { unique } from "./helpers.js";
|
|
13
13
|
import { AUTO_REVIEW_LOOP_GATE_BY_STAGE, reviewLoopArtifactFixHint, reviewLoopEnvelopeExample, validateGateEvidenceShape } from "./review-loop.js";
|
|
14
|
-
import { ensureProactiveDelegationTrace } from "./
|
|
14
|
+
import { ensureProactiveDelegationTrace } from "./proactive-delegation-trace.js";
|
|
15
15
|
function resolveSuccessorTransition(stage, track, transitionTargets, satisfiedGuards, selectedTransitionGuards) {
|
|
16
16
|
const natural = transitionTargets[0] ?? null;
|
|
17
17
|
const specialTargets = transitionTargets.filter((target) => target !== natural);
|
|
@@ -299,7 +299,7 @@ export async function runAdvanceStage(projectRoot, args, io) {
|
|
|
299
299
|
io.stderr.write(`cclaw internal advance-stage: current stage is "${flowState.currentStage}", not "${args.stage}".\n`);
|
|
300
300
|
return 1;
|
|
301
301
|
}
|
|
302
|
-
const schema = stageSchema(args.stage, flowState.track);
|
|
302
|
+
const schema = stageSchema(args.stage, flowState.track, flowState.discoveryMode, flowState.taskClass ?? null);
|
|
303
303
|
const requiredGateIds = schema.requiredGates
|
|
304
304
|
.filter((gate) => gate.tier === "required")
|
|
305
305
|
.map((gate) => gate.id);
|
|
@@ -530,7 +530,8 @@ export async function runAdvanceStage(projectRoot, args, io) {
|
|
|
530
530
|
}
|
|
531
531
|
const proactiveTrace = await ensureProactiveDelegationTrace(projectRoot, args.stage, {
|
|
532
532
|
acceptWaiver: args.acceptProactiveWaiver,
|
|
533
|
-
waiverReason: args.acceptProactiveWaiverReason
|
|
533
|
+
waiverReason: args.acceptProactiveWaiverReason,
|
|
534
|
+
discoveryMode: flowState.discoveryMode
|
|
534
535
|
});
|
|
535
536
|
if (proactiveTrace.missingRules.length > 0) {
|
|
536
537
|
const missingSummary = proactiveTrace.missingRules
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type FlowStage, type FlowTrack } from "../../types.js";
|
|
1
|
+
import { type DiscoveryMode, type FlowStage, type FlowTrack } from "../../types.js";
|
|
2
2
|
import type { ArchiveDisposition } from "../../runs.js";
|
|
3
3
|
export interface AdvanceStageArgs {
|
|
4
4
|
stage: FlowStage;
|
|
@@ -32,6 +32,7 @@ export interface RewindArgs {
|
|
|
32
32
|
}
|
|
33
33
|
export interface StartFlowArgs {
|
|
34
34
|
track: FlowTrack;
|
|
35
|
+
discoveryMode: DiscoveryMode;
|
|
35
36
|
className?: string;
|
|
36
37
|
prompt?: string;
|
|
37
38
|
reason?: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FLOW_STAGES } from "../../types.js";
|
|
2
|
-
import { isFlowTrack } from "../../flow-state.js";
|
|
2
|
+
import { isDiscoveryMode, isFlowTrack } from "../../flow-state.js";
|
|
3
3
|
import { isFlowStageValue, parseCsv, parseEvidenceByGate, unique } from "./helpers.js";
|
|
4
4
|
export function parseAdvanceStageArgs(tokens) {
|
|
5
5
|
const [stageRaw, ...flagTokens] = tokens;
|
|
@@ -204,6 +204,7 @@ export function parseHookArgs(tokens) {
|
|
|
204
204
|
}
|
|
205
205
|
export function parseStartFlowArgs(tokens) {
|
|
206
206
|
let track;
|
|
207
|
+
let discoveryMode = "guided";
|
|
207
208
|
let className;
|
|
208
209
|
let prompt;
|
|
209
210
|
let reason;
|
|
@@ -245,6 +246,14 @@ export function parseStartFlowArgs(tokens) {
|
|
|
245
246
|
track = raw;
|
|
246
247
|
continue;
|
|
247
248
|
}
|
|
249
|
+
if (token === "--discovery-mode" || token.startsWith("--discovery-mode=")) {
|
|
250
|
+
const raw = readValue("--discovery-mode").trim();
|
|
251
|
+
if (!isDiscoveryMode(raw)) {
|
|
252
|
+
throw new Error(`--discovery-mode must be one of: lean, guided, deep.`);
|
|
253
|
+
}
|
|
254
|
+
discoveryMode = raw;
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
248
257
|
if (token === "--class" || token.startsWith("--class=")) {
|
|
249
258
|
className = readValue("--class").trim();
|
|
250
259
|
continue;
|
|
@@ -281,6 +290,7 @@ export function parseStartFlowArgs(tokens) {
|
|
|
281
290
|
}
|
|
282
291
|
return {
|
|
283
292
|
track,
|
|
293
|
+
discoveryMode,
|
|
284
294
|
className,
|
|
285
295
|
prompt,
|
|
286
296
|
reason,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type StageAutoSubagentDispatch } from "../../content/stage-schema.js";
|
|
2
|
+
import type { DiscoveryMode, FlowStage } from "../../types.js";
|
|
3
|
+
export interface ProactiveDelegationTraceResult {
|
|
4
|
+
missingRules: StageAutoSubagentDispatch[];
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Ensure every proactive dispatch rule for the stage has a ledger row for the
|
|
8
|
+
* active run, or an explicit user-flag waiver.
|
|
9
|
+
*
|
|
10
|
+
* Lean/guided discovery on early elicitation stages intentionally does not
|
|
11
|
+
* require a full proactive trace: specialists run only when triggers warrant
|
|
12
|
+
* them. Deep discovery keeps the blanket trace so mandatory + proactive
|
|
13
|
+
* coverage stays auditably complete before advance.
|
|
14
|
+
*/
|
|
15
|
+
export declare function ensureProactiveDelegationTrace(projectRoot: string, stage: FlowStage, options: {
|
|
16
|
+
acceptWaiver: boolean;
|
|
17
|
+
waiverReason?: string;
|
|
18
|
+
discoveryMode: DiscoveryMode;
|
|
19
|
+
}): Promise<ProactiveDelegationTraceResult>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { appendDelegation, readDelegationLedger } from "../../delegation.js";
|
|
2
|
+
import { stageAutoSubagentDispatch } from "../../content/stage-schema.js";
|
|
3
|
+
function isEarlyElicitationStage(stage) {
|
|
4
|
+
return stage === "brainstorm" || stage === "scope" || stage === "design";
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Ensure every proactive dispatch rule for the stage has a ledger row for the
|
|
8
|
+
* active run, or an explicit user-flag waiver.
|
|
9
|
+
*
|
|
10
|
+
* Lean/guided discovery on early elicitation stages intentionally does not
|
|
11
|
+
* require a full proactive trace: specialists run only when triggers warrant
|
|
12
|
+
* them. Deep discovery keeps the blanket trace so mandatory + proactive
|
|
13
|
+
* coverage stays auditably complete before advance.
|
|
14
|
+
*/
|
|
15
|
+
export async function ensureProactiveDelegationTrace(projectRoot, stage, options) {
|
|
16
|
+
if (isEarlyElicitationStage(stage) && (options.discoveryMode === "lean" || options.discoveryMode === "guided")) {
|
|
17
|
+
return { missingRules: [] };
|
|
18
|
+
}
|
|
19
|
+
const proactiveRules = stageAutoSubagentDispatch(stage).filter((rule) => rule.mode === "proactive");
|
|
20
|
+
if (proactiveRules.length === 0)
|
|
21
|
+
return { missingRules: [] };
|
|
22
|
+
const ledger = await readDelegationLedger(projectRoot);
|
|
23
|
+
const currentRunEntries = ledger.entries.filter((entry) => entry.runId === ledger.runId);
|
|
24
|
+
const missingRules = proactiveRules.filter((rule) => !currentRunEntries.some((entry) => entry.stage === stage && entry.agent === rule.agent && entry.mode === "proactive"));
|
|
25
|
+
if (missingRules.length === 0)
|
|
26
|
+
return { missingRules: [] };
|
|
27
|
+
if (!options.acceptWaiver)
|
|
28
|
+
return { missingRules };
|
|
29
|
+
const waiverReason = options.waiverReason?.trim() || "accepted via --accept-proactive-waiver";
|
|
30
|
+
for (const rule of missingRules) {
|
|
31
|
+
await appendDelegation(projectRoot, {
|
|
32
|
+
stage,
|
|
33
|
+
agent: rule.agent,
|
|
34
|
+
mode: "proactive",
|
|
35
|
+
status: "waived",
|
|
36
|
+
waiverReason,
|
|
37
|
+
acceptedBy: "user-flag",
|
|
38
|
+
conditionTrigger: rule.when,
|
|
39
|
+
skill: rule.skill,
|
|
40
|
+
ts: new Date().toISOString()
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return { missingRules: [] };
|
|
44
|
+
}
|
|
@@ -7,6 +7,12 @@ import { listExistingFiles, listFilesUnder, pathExists } from "./helpers.js";
|
|
|
7
7
|
import { TRACK_STAGES } from "../../types.js";
|
|
8
8
|
import { buildValidationReport } from "./advance.js";
|
|
9
9
|
import { carriedCompletedStageCatalog, completedStageClosureEvidenceIssues, firstIncompleteStageForTrack } from "./verify.js";
|
|
10
|
+
function resolveTaskClass(className, fallback) {
|
|
11
|
+
if (className === "software-standard" || className === "software-trivial" || className === "software-bugfix") {
|
|
12
|
+
return className;
|
|
13
|
+
}
|
|
14
|
+
return fallback;
|
|
15
|
+
}
|
|
10
16
|
export async function discoverStartFlowContext(projectRoot) {
|
|
11
17
|
const lines = [];
|
|
12
18
|
const seedFiles = (await listFilesUnder(projectRoot, path.join(RUNTIME_ROOT, "seeds"), 10))
|
|
@@ -58,6 +64,7 @@ export async function appendIdeaArtifact(projectRoot, args, previous) {
|
|
|
58
64
|
`- From: ${previous?.track ?? "unknown"}`,
|
|
59
65
|
`- To: ${args.track}`,
|
|
60
66
|
`- Class: ${args.className || "unspecified"}`,
|
|
67
|
+
`- Discovery mode: ${args.discoveryMode}`,
|
|
61
68
|
`- Reason: ${args.reason || "unspecified"}`
|
|
62
69
|
].join("\n") + "\n";
|
|
63
70
|
await fs.appendFile(artifactPath, entry, "utf8");
|
|
@@ -68,6 +75,7 @@ export async function appendIdeaArtifact(projectRoot, args, previous) {
|
|
|
68
75
|
"# Idea",
|
|
69
76
|
`Class: ${args.className || "unspecified"}`,
|
|
70
77
|
`Track: ${args.track}${args.reason ? ` (${args.reason})` : ""}`,
|
|
78
|
+
`Discovery mode: ${args.discoveryMode}`,
|
|
71
79
|
`Stack: ${args.stack || "unknown"}`,
|
|
72
80
|
"",
|
|
73
81
|
"## User prompt",
|
|
@@ -85,10 +93,11 @@ export async function runStartFlow(projectRoot, args, io) {
|
|
|
85
93
|
io.stderr.write("cclaw internal start-flow: refusing to reset an active flow with completed stages without --force-reset. Ask the user before resetting.\n");
|
|
86
94
|
return 1;
|
|
87
95
|
}
|
|
96
|
+
const nextTaskClass = resolveTaskClass(args.className, current.taskClass);
|
|
88
97
|
let nextState;
|
|
89
98
|
if (args.reclassify) {
|
|
90
99
|
const completedInNewTrack = current.completedStages.filter((stage) => TRACK_STAGES[args.track].includes(stage));
|
|
91
|
-
const fresh = createInitialFlowState({ activeRunId: current.activeRunId, track: args.track });
|
|
100
|
+
const fresh = createInitialFlowState({ activeRunId: current.activeRunId, track: args.track, discoveryMode: args.discoveryMode });
|
|
92
101
|
const stageGateCatalog = { ...fresh.stageGateCatalog };
|
|
93
102
|
const guardEvidence = {};
|
|
94
103
|
for (const stage of completedInNewTrack) {
|
|
@@ -98,6 +107,7 @@ export async function runStartFlow(projectRoot, args, io) {
|
|
|
98
107
|
}
|
|
99
108
|
nextState = {
|
|
100
109
|
...fresh,
|
|
110
|
+
...(nextTaskClass !== undefined ? { taskClass: nextTaskClass } : {}),
|
|
101
111
|
completedStages: completedInNewTrack,
|
|
102
112
|
currentStage: firstIncompleteStageForTrack(args.track, completedInNewTrack),
|
|
103
113
|
guardEvidence,
|
|
@@ -117,7 +127,10 @@ export async function runStartFlow(projectRoot, args, io) {
|
|
|
117
127
|
}
|
|
118
128
|
}
|
|
119
129
|
else {
|
|
120
|
-
nextState = createInitialFlowState({ track: args.track });
|
|
130
|
+
nextState = createInitialFlowState({ track: args.track, discoveryMode: args.discoveryMode });
|
|
131
|
+
if (nextTaskClass !== undefined) {
|
|
132
|
+
nextState = { ...nextState, taskClass: nextTaskClass };
|
|
133
|
+
}
|
|
121
134
|
}
|
|
122
135
|
if (args.fromIdeaArtifact) {
|
|
123
136
|
const existingHints = nextState.interactionHints ?? {};
|
|
@@ -140,6 +153,8 @@ export async function runStartFlow(projectRoot, args, io) {
|
|
|
140
153
|
command: "start-flow",
|
|
141
154
|
reclassify: args.reclassify,
|
|
142
155
|
track: nextState.track,
|
|
156
|
+
discoveryMode: nextState.discoveryMode,
|
|
157
|
+
taskClass: nextState.taskClass ?? null,
|
|
143
158
|
currentStage: nextState.currentStage,
|
|
144
159
|
skippedStages: nextState.skippedStages,
|
|
145
160
|
activeRunId: nextState.activeRunId
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type StageAutoSubagentDispatch } from "../../content/stage-schema.js";
|
|
2
1
|
import { type FlowState, type StageGateState } from "../../flow-state.js";
|
|
3
2
|
import { type FlowStage, type FlowTrack } from "../../types.js";
|
|
4
3
|
import type { VerifyCurrentStateArgs, VerifyFlowStateDiffArgs } from "./parsers.js";
|
|
@@ -7,9 +6,6 @@ interface InternalIo {
|
|
|
7
6
|
stdout: Writable;
|
|
8
7
|
stderr: Writable;
|
|
9
8
|
}
|
|
10
|
-
interface ProactiveDelegationTraceResult {
|
|
11
|
-
missingRules: StageAutoSubagentDispatch[];
|
|
12
|
-
}
|
|
13
9
|
export declare function runVerifyFlowStateDiff(projectRoot: string, args: VerifyFlowStateDiffArgs, io: InternalIo): Promise<number>;
|
|
14
10
|
export declare function runVerifyCurrentState(projectRoot: string, args: VerifyCurrentStateArgs, io: InternalIo): Promise<number>;
|
|
15
11
|
export declare function firstIncompleteStageForTrack(track: FlowTrack, completedStages: FlowStage[]): FlowStage;
|
|
@@ -18,10 +14,6 @@ export declare function carriedCompletedStageCatalog(current: FlowState, fresh:
|
|
|
18
14
|
evidence: Record<string, string>;
|
|
19
15
|
};
|
|
20
16
|
export declare function completedStageClosureEvidenceIssues(flowState: FlowState): string[];
|
|
21
|
-
export declare function ensureProactiveDelegationTrace(projectRoot: string, stage: FlowStage, options: {
|
|
22
|
-
acceptWaiver: boolean;
|
|
23
|
-
waiverReason?: string;
|
|
24
|
-
}): Promise<ProactiveDelegationTraceResult>;
|
|
25
17
|
export declare function pathExists(projectRoot: string, relPath: string): Promise<boolean>;
|
|
26
18
|
export declare function listExistingFiles(projectRoot: string, relPaths: string[]): Promise<string[]>;
|
|
27
19
|
export declare function listFilesUnder(projectRoot: string, relDir: string, limit?: number): Promise<string[]>;
|