cclaw-cli 0.55.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +3 -3
  2. package/dist/artifact-linter/brainstorm.js +59 -1
  3. package/dist/artifact-linter/design.js +46 -1
  4. package/dist/artifact-linter/plan.js +22 -1
  5. package/dist/artifact-linter/review.js +35 -1
  6. package/dist/artifact-linter/scope.js +33 -9
  7. package/dist/artifact-linter/shared.d.ts +12 -10
  8. package/dist/artifact-linter/shared.js +102 -41
  9. package/dist/artifact-linter/ship.js +36 -0
  10. package/dist/artifact-linter/spec.js +23 -1
  11. package/dist/artifact-linter/tdd.js +74 -0
  12. package/dist/artifact-linter.d.ts +1 -1
  13. package/dist/artifact-linter.js +11 -1
  14. package/dist/constants.d.ts +1 -1
  15. package/dist/constants.js +1 -0
  16. package/dist/content/closeout-guidance.d.ts +1 -1
  17. package/dist/content/closeout-guidance.js +10 -11
  18. package/dist/content/core-agents.d.ts +35 -36
  19. package/dist/content/core-agents.js +189 -99
  20. package/dist/content/diff-command.js +1 -1
  21. package/dist/content/examples.d.ts +0 -3
  22. package/dist/content/examples.js +197 -752
  23. package/dist/content/hook-events.js +1 -2
  24. package/dist/content/hook-manifest.d.ts +3 -4
  25. package/dist/content/hook-manifest.js +22 -25
  26. package/dist/content/hooks.js +54 -14
  27. package/dist/content/idea.d.ts +60 -0
  28. package/dist/content/idea.js +404 -0
  29. package/dist/content/learnings.d.ts +2 -4
  30. package/dist/content/learnings.js +10 -26
  31. package/dist/content/meta-skill.js +4 -3
  32. package/dist/content/node-hooks.js +368 -164
  33. package/dist/content/observe.js +3 -3
  34. package/dist/content/opencode-plugin.js +12 -32
  35. package/dist/content/reference-patterns.js +2 -2
  36. package/dist/content/runtime-shared-snippets.d.ts +8 -0
  37. package/dist/content/runtime-shared-snippets.js +80 -0
  38. package/dist/content/session-hooks.js +1 -1
  39. package/dist/content/skills-elicitation.d.ts +1 -0
  40. package/dist/content/skills-elicitation.js +123 -0
  41. package/dist/content/skills.d.ts +1 -0
  42. package/dist/content/skills.js +54 -2
  43. package/dist/content/stage-schema.js +107 -63
  44. package/dist/content/stages/brainstorm.js +7 -3
  45. package/dist/content/stages/design.js +4 -0
  46. package/dist/content/stages/review.js +8 -8
  47. package/dist/content/stages/schema-types.d.ts +2 -2
  48. package/dist/content/stages/scope.js +7 -3
  49. package/dist/content/stages/ship.js +1 -1
  50. package/dist/content/start-command.js +4 -4
  51. package/dist/content/status-command.js +3 -3
  52. package/dist/content/subagent-context-skills.js +156 -1
  53. package/dist/content/subagents.d.ts +0 -5
  54. package/dist/content/subagents.js +12 -82
  55. package/dist/content/templates.js +108 -6
  56. package/dist/content/utility-skills.js +26 -97
  57. package/dist/flow-state.d.ts +12 -6
  58. package/dist/flow-state.js +5 -6
  59. package/dist/gate-evidence.d.ts +0 -31
  60. package/dist/gate-evidence.js +3 -181
  61. package/dist/harness-adapters.js +1 -1
  62. package/dist/hook-schemas/claude-hooks.v1.json +2 -3
  63. package/dist/hook-schemas/codex-hooks.v1.json +1 -1
  64. package/dist/hook-schemas/cursor-hooks.v1.json +1 -1
  65. package/dist/install.js +50 -7
  66. package/dist/internal/advance-stage/advance.js +22 -2
  67. package/dist/internal/advance-stage/parsers.d.ts +1 -0
  68. package/dist/internal/advance-stage/parsers.js +6 -0
  69. package/dist/internal/advance-stage/review-loop.js +1 -10
  70. package/dist/knowledge-store.d.ts +2 -20
  71. package/dist/knowledge-store.js +43 -57
  72. package/dist/policy.js +3 -3
  73. package/dist/retro-gate.js +8 -90
  74. package/dist/run-archive.js +1 -4
  75. package/dist/run-persistence.d.ts +1 -1
  76. package/dist/run-persistence.js +43 -111
  77. package/dist/runtime/run-hook.entry.d.ts +3 -0
  78. package/dist/runtime/run-hook.entry.js +5 -0
  79. package/dist/runtime/run-hook.mjs +9647 -0
  80. package/dist/track-heuristics.d.ts +7 -1
  81. package/dist/track-heuristics.js +12 -0
  82. package/package.json +4 -2
  83. package/dist/content/hook-inline-snippets.d.ts +0 -96
  84. package/dist/content/hook-inline-snippets.js +0 -515
  85. package/dist/content/idea-command.d.ts +0 -8
  86. package/dist/content/idea-command.js +0 -322
  87. package/dist/content/idea-frames.d.ts +0 -31
  88. package/dist/content/idea-frames.js +0 -140
  89. package/dist/content/idea-ranking.d.ts +0 -25
  90. package/dist/content/idea-ranking.js +0 -65
  91. package/dist/trace-matrix.d.ts +0 -27
  92. package/dist/trace-matrix.js +0 -226
@@ -56,20 +56,20 @@ function buildCursorEvents() {
56
56
  }
57
57
  export function claudeHooksJsonWithObservation() {
58
58
  return JSON.stringify({
59
- cclawHookSchemaVersion: 1,
59
+ cclawHookSchemaVersion: 2,
60
60
  hooks: buildClaudeLikeEvents("claude")
61
61
  }, null, 2);
62
62
  }
63
63
  export function cursorHooksJsonWithObservation() {
64
64
  return JSON.stringify({
65
- cclawHookSchemaVersion: 1,
65
+ cclawHookSchemaVersion: 2,
66
66
  version: 1,
67
67
  hooks: buildCursorEvents()
68
68
  }, null, 2);
69
69
  }
70
70
  export function codexHooksJsonWithObservation() {
71
71
  return JSON.stringify({
72
- cclawHookSchemaVersion: 1,
72
+ cclawHookSchemaVersion: 2,
73
73
  hooks: buildClaudeLikeEvents("codex")
74
74
  }, null, 2);
75
75
  }
@@ -1,5 +1,6 @@
1
1
  import { RUNTIME_ROOT } from "../constants.js";
2
2
  import { META_SKILL_NAME } from "./meta-skill.js";
3
+ import { SHARED_FLOW_AND_KNOWLEDGE_SNIPPETS, SHARED_STAGE_SUPPORT_SNIPPETS } from "./runtime-shared-snippets.js";
3
4
  export function opencodePluginJs(_options = {}) {
4
5
  return `// cclaw OpenCode plugin — generated by npx cclaw-cli sync
5
6
  import { appendFileSync, existsSync, mkdirSync } from "node:fs";
@@ -16,13 +17,8 @@ export default function cclawPlugin(ctx) {
16
17
  const flowStatePath = join(stateDir, "flow-state.json");
17
18
  const knowledgePath = join(runtimeDir, "knowledge.jsonl");
18
19
  const metaSkillPath = join(runtimeDir, "skills/${META_SKILL_NAME}/SKILL.md");
19
- const STAGE_IDS = ["brainstorm", "scope", "design", "spec", "plan", "tdd", "review", "ship"];
20
- const REVIEW_PROMPT_BY_STAGE = {
21
- brainstorm: "brainstorm-self-review.md",
22
- scope: "scope-ceo-review.md",
23
- design: "design-eng-review.md"
24
- };
25
- const REVIEW_PROMPT_FILES = Object.values(REVIEW_PROMPT_BY_STAGE);
20
+ ${SHARED_FLOW_AND_KNOWLEDGE_SNIPPETS}
21
+ ${SHARED_STAGE_SUPPORT_SNIPPETS}
26
22
 
27
23
  function ensureRuntimeDirs() {
28
24
  try {
@@ -61,14 +57,9 @@ export default function cclawPlugin(ctx) {
61
57
  async function readFlowState() {
62
58
  try {
63
59
  const raw = await readFile(flowStatePath, "utf8");
64
- const state = JSON.parse(raw);
65
- return {
66
- stage: typeof state.currentStage === "string" ? state.currentStage : "none",
67
- completed: Array.isArray(state.completedStages) ? state.completedStages.length : 0,
68
- activeRunId: typeof state.activeRunId === "string" ? state.activeRunId : "none"
69
- };
60
+ return summarizeFlowState(JSON.parse(raw));
70
61
  } catch {
71
- return { stage: "none", completed: 0, activeRunId: "none" };
62
+ return summarizeFlowState({});
72
63
  }
73
64
  }
74
65
 
@@ -80,18 +71,13 @@ export default function cclawPlugin(ctx) {
80
71
  }
81
72
  }
82
73
 
83
- async function readTailLines(filePath, maxLines) {
84
- const text = (await readFileText(filePath)).trim();
85
- if (!text) return [];
86
- return text.split(/\\r?\\n/).slice(-maxLines);
87
- }
88
-
89
- async function readKnowledgeDigest() {
90
- return readTailLines(knowledgePath, 12);
74
+ async function readKnowledgeDigest(stage) {
75
+ const raw = await readFileText(knowledgePath);
76
+ return parseKnowledgeDigest(raw, stage, 6).lines;
91
77
  }
92
78
 
93
79
  async function readStageSupportContext(stage) {
94
- if (typeof stage !== "string" || !STAGE_IDS.includes(stage)) return [];
80
+ if (!isKnownStageId(stage)) return [];
95
81
  const parts = [];
96
82
  const contract = (await readFileText(join(runtimeDir, "templates/state-contracts", stage + ".json"))).trim();
97
83
  if (contract.length > 0) {
@@ -100,7 +86,7 @@ export default function cclawPlugin(ctx) {
100
86
  contract
101
87
  );
102
88
  }
103
- const reviewPromptName = REVIEW_PROMPT_BY_STAGE[stage];
89
+ const reviewPromptName = reviewPromptFileName(stage);
104
90
  if (reviewPromptName) {
105
91
  const prompt = (await readFileText(join(runtimeDir, "skills/review-prompts", reviewPromptName))).trim();
106
92
  if (prompt.length > 0) {
@@ -119,12 +105,12 @@ export default function cclawPlugin(ctx) {
119
105
  const flow = await readFlowState();
120
106
  const parts = [
121
107
  BOOTSTRAP_MARKER,
122
- \`cclaw loaded. Flow: stage=\${flow.stage} (\${flow.completed}/8 completed, run=\${flow.activeRunId}). Active artifacts: ${RUNTIME_ROOT}/artifacts/\`
108
+ \`cclaw loaded. Flow: stage=\${flow.stage} (\${flow.completed}/8 completed, run=\${flow.activeRunId}). Active artifacts: \${activeArtifactsPathLabel("${RUNTIME_ROOT}")}\`
123
109
  ];
124
110
 
125
111
 
126
112
 
127
- const knowledge = await readKnowledgeDigest();
113
+ const knowledge = await readKnowledgeDigest(flow.stage);
128
114
  if (knowledge.length > 0) parts.push("Knowledge digest (top relevant entries):", ...knowledge);
129
115
 
130
116
  const stageSupport = await readStageSupportContext(flow.stage);
@@ -621,12 +607,6 @@ export default function cclawPlugin(ctx) {
621
607
  eventType === "session.compacted" ||
622
608
  eventType === "session.cleared" ||
623
609
  eventType === "session.updated";
624
- // session.compacted must run pre-compact BEFORE canonical rehydration,
625
- // otherwise the injected system prompt can show the pre-compact
626
- // digest/state until the next lifecycle event.
627
- if (eventType === "session.compacted") {
628
- await runHookScript("pre-compact", eventData ?? {});
629
- }
630
610
  if (isSessionLifecycle) {
631
611
  // Keep OpenCode aligned with Claude/Cursor/Codex: session-start is
632
612
  // the canonical rehydrate path that refreshes derived state such as
@@ -201,7 +201,7 @@ export const REFERENCE_PATTERNS = [
201
201
  "Review source-item coverage by vertical slice, not by file count alone.",
202
202
  "A slice is review-ready only when RED, GREEN, REFACTOR, and verification evidence all line up."
203
203
  ],
204
- artifactSections: ["Completeness Snapshot", "Trace Matrix Check"]
204
+ artifactSections: ["Completeness Snapshot", "Coverage Check"]
205
205
  }
206
206
  ]
207
207
  },
@@ -348,7 +348,7 @@ export const REFERENCE_PATTERNS = [
348
348
  {
349
349
  stage: "review",
350
350
  guidance: [
351
- "Victory Detector: Layer 1, Layer 2, security sweep, structured findings, and trace evidence are complete with no unresolved criticals unless verdict is BLOCKED.",
351
+ "Victory Detector: Layer 1, Layer 2, security sweep, structured findings, and acceptance/reproduction coverage evidence are complete with no unresolved criticals unless verdict is BLOCKED.",
352
352
  "If the detector fails, iterate findings or route back to TDD; do not say LGTM."
353
353
  ],
354
354
  artifactSections: ["Review Readiness Snapshot", "Final Verdict"]
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Shared runtime snippets interpolated into generated hook/plugin scripts.
3
+ *
4
+ * Keep these string helpers minimal and dependency-free so both runtimes
5
+ * (node hooks and OpenCode plugin) stay in sync without duplicating constants.
6
+ */
7
+ export declare const SHARED_FLOW_AND_KNOWLEDGE_SNIPPETS = "\nfunction summarizeFlowState(rawState) {\n const state =\n rawState && typeof rawState === \"object\" && !Array.isArray(rawState)\n ? rawState\n : {};\n return {\n stage: typeof state.currentStage === \"string\" ? state.currentStage : \"none\",\n completed: Array.isArray(state.completedStages) ? state.completedStages.length : 0,\n activeRunId: typeof state.activeRunId === \"string\" ? state.activeRunId : \"none\"\n };\n}\n\nfunction parseKnowledgeDigest(rawKnowledge, currentStage, maxRows = 6) {\n const text = typeof rawKnowledge === \"string\" ? rawKnowledge : \"\";\n if (text.trim().length === 0) {\n return { learningsCount: 0, lines: [] };\n }\n const rows = text\n .split(/\\r?\\n/gu)\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n let learningsCount = 0;\n const parsedRows = [];\n for (const line of rows) {\n if (line.startsWith(\"{\")) learningsCount += 1;\n try {\n const parsed = JSON.parse(line);\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) continue;\n parsedRows.push(parsed);\n } catch {\n // ignore malformed knowledge line in digest\n }\n }\n const lines = parsedRows\n .filter((row) => {\n const stage = typeof row.stage === \"string\" ? row.stage : null;\n return stage === null || stage === currentStage;\n })\n .slice(-maxRows)\n .reverse()\n .map((row) => {\n const confidence = typeof row.confidence === \"string\" ? row.confidence : \"unknown\";\n const stage = typeof row.stage === \"string\" ? row.stage : \"global\";\n const trigger = typeof row.trigger === \"string\" ? row.trigger : \"trigger\";\n const action = typeof row.action === \"string\" ? row.action : \"action\";\n return \"- [\" + confidence + \" \u2022 \" + stage + \"] \" + trigger + \" -> \" + action;\n });\n return { learningsCount, lines };\n}\n\nfunction activeArtifactsPathLabel(runtimeRoot) {\n return String(runtimeRoot || \".cclaw\") + \"/artifacts/\";\n}\n";
8
+ export declare const SHARED_STAGE_SUPPORT_SNIPPETS = "\nconst STAGE_IDS = [\"brainstorm\", \"scope\", \"design\", \"spec\", \"plan\", \"tdd\", \"review\", \"ship\"];\nconst REVIEW_PROMPT_BY_STAGE = {\n brainstorm: \"brainstorm-self-review.md\",\n scope: \"scope-ceo-review.md\",\n design: \"design-eng-review.md\"\n};\nconst REVIEW_PROMPT_FILES = Object.values(REVIEW_PROMPT_BY_STAGE);\n\nfunction isKnownStageId(stage) {\n return typeof stage === \"string\" && STAGE_IDS.includes(stage);\n}\n\nfunction reviewPromptFileName(stage) {\n if (!isKnownStageId(stage)) return null;\n const name = REVIEW_PROMPT_BY_STAGE[stage];\n return typeof name === \"string\" ? name : null;\n}\n";
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Shared runtime snippets interpolated into generated hook/plugin scripts.
3
+ *
4
+ * Keep these string helpers minimal and dependency-free so both runtimes
5
+ * (node hooks and OpenCode plugin) stay in sync without duplicating constants.
6
+ */
7
+ export const SHARED_FLOW_AND_KNOWLEDGE_SNIPPETS = `
8
+ function summarizeFlowState(rawState) {
9
+ const state =
10
+ rawState && typeof rawState === "object" && !Array.isArray(rawState)
11
+ ? rawState
12
+ : {};
13
+ return {
14
+ stage: typeof state.currentStage === "string" ? state.currentStage : "none",
15
+ completed: Array.isArray(state.completedStages) ? state.completedStages.length : 0,
16
+ activeRunId: typeof state.activeRunId === "string" ? state.activeRunId : "none"
17
+ };
18
+ }
19
+
20
+ function parseKnowledgeDigest(rawKnowledge, currentStage, maxRows = 6) {
21
+ const text = typeof rawKnowledge === "string" ? rawKnowledge : "";
22
+ if (text.trim().length === 0) {
23
+ return { learningsCount: 0, lines: [] };
24
+ }
25
+ const rows = text
26
+ .split(/\\r?\\n/gu)
27
+ .map((line) => line.trim())
28
+ .filter((line) => line.length > 0);
29
+ let learningsCount = 0;
30
+ const parsedRows = [];
31
+ for (const line of rows) {
32
+ if (line.startsWith("{")) learningsCount += 1;
33
+ try {
34
+ const parsed = JSON.parse(line);
35
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) continue;
36
+ parsedRows.push(parsed);
37
+ } catch {
38
+ // ignore malformed knowledge line in digest
39
+ }
40
+ }
41
+ const lines = parsedRows
42
+ .filter((row) => {
43
+ const stage = typeof row.stage === "string" ? row.stage : null;
44
+ return stage === null || stage === currentStage;
45
+ })
46
+ .slice(-maxRows)
47
+ .reverse()
48
+ .map((row) => {
49
+ const confidence = typeof row.confidence === "string" ? row.confidence : "unknown";
50
+ const stage = typeof row.stage === "string" ? row.stage : "global";
51
+ const trigger = typeof row.trigger === "string" ? row.trigger : "trigger";
52
+ const action = typeof row.action === "string" ? row.action : "action";
53
+ return "- [" + confidence + " • " + stage + "] " + trigger + " -> " + action;
54
+ });
55
+ return { learningsCount, lines };
56
+ }
57
+
58
+ function activeArtifactsPathLabel(runtimeRoot) {
59
+ return String(runtimeRoot || ".cclaw") + "/artifacts/";
60
+ }
61
+ `;
62
+ export const SHARED_STAGE_SUPPORT_SNIPPETS = `
63
+ const STAGE_IDS = ["brainstorm", "scope", "design", "spec", "plan", "tdd", "review", "ship"];
64
+ const REVIEW_PROMPT_BY_STAGE = {
65
+ brainstorm: "brainstorm-self-review.md",
66
+ scope: "scope-ceo-review.md",
67
+ design: "design-eng-review.md"
68
+ };
69
+ const REVIEW_PROMPT_FILES = Object.values(REVIEW_PROMPT_BY_STAGE);
70
+
71
+ function isKnownStageId(stage) {
72
+ return typeof stage === "string" && STAGE_IDS.includes(stage);
73
+ }
74
+
75
+ function reviewPromptFileName(stage) {
76
+ if (!isKnownStageId(stage)) return null;
77
+ const name = REVIEW_PROMPT_BY_STAGE[stage];
78
+ return typeof name === "string" ? name : null;
79
+ }
80
+ `;
@@ -66,7 +66,7 @@ When resuming work after a break:
66
66
 
67
67
  ### Optional session-history scan for compound
68
68
 
69
- During post-ship \`compound_review\`, ask before scanning external session history. If the user opts in, inspect only relevant Cursor/Claude/Codex transcripts for repeated failures or process lessons, summarize matches, and then apply the same overlap/refresh/supersede rules before touching \`.cclaw/knowledge.jsonl\`.
69
+ During post-ship \`post_ship_review\`, ask before scanning external session history. If the user opts in, inspect only relevant Cursor/Claude/Codex transcripts for repeated failures or process lessons, summarize matches, and then apply the same overlap/refresh/supersede rules before touching \`.cclaw/knowledge.jsonl\`.
70
70
 
71
71
  ## Context Management
72
72
 
@@ -0,0 +1 @@
1
+ export declare function adaptiveElicitationSkillMarkdown(): string;
@@ -0,0 +1,123 @@
1
+ import { RUNTIME_ROOT } from "../constants.js";
2
+ import { questionBudgetHint } from "../track-heuristics.js";
3
+ import { FLOW_TRACKS } from "../types.js";
4
+ const ELICITATION_STAGES = ["brainstorm", "scope", "design"];
5
+ function renderQuestionBudgetHintTable() {
6
+ const rows = [];
7
+ for (const track of FLOW_TRACKS) {
8
+ for (const stage of ELICITATION_STAGES) {
9
+ const hint = questionBudgetHint(track, stage);
10
+ rows.push(`| \`${track}\` | \`${stage}\` | ${hint.min} | ${hint.recommended} | ${hint.hardCapWarning} |`);
11
+ }
12
+ }
13
+ return `| Track | Stage | Min | Recommended | Hard cap warning |
14
+ |---|---|---|---|---|
15
+ ${rows.join("\n")}`;
16
+ }
17
+ export function adaptiveElicitationSkillMarkdown() {
18
+ const budgetTable = renderQuestionBudgetHintTable();
19
+ return `---
20
+ name: adaptive-elicitation
21
+ description: "Harness-native one-question-at-a-time dialogue for brainstorm/scope/design with stop signals, smart-skip, and append-only Q&A logging."
22
+ ---
23
+
24
+ # Adaptive Elicitation
25
+
26
+ Pinned anchor: "Don't tell it what to do, give it success criteria and watch it go."
27
+
28
+ ## HARD-GATE
29
+ - User does not run cclaw manually. Do not tell the user to run CLI commands for answers.
30
+ - Ask exactly one question per turn and wait for the answer before asking the next one.
31
+ - Use harness-native question tools first; prose fallback is allowed only when the tool is unavailable.
32
+ - Keep a running Q&A trace in the active artifact under \`## Q&A Log\` in \`${RUNTIME_ROOT}/artifacts/\` as append-only rows.
33
+
34
+ ## Harness Question Surface
35
+
36
+ Preferred native tool names:
37
+ - Claude Code: \`AskUserQuestion\`
38
+ - Codex: \`request_user_input\`
39
+ - Gemini: \`ask_user\`
40
+ - Cursor: \`AskQuestion\`
41
+
42
+ If unavailable, ask one concise prose question and explicitly wait for chat answer.
43
+
44
+ ## Core Protocol
45
+
46
+ 1. Ask one decision-changing question.
47
+ 2. Wait for the answer.
48
+ 3. Append one row to \`## Q&A Log\`: \`Turn | Question | User answer (1-line) | Decision impact\`.
49
+ 4. Self-evaluate:
50
+ - What did I learn?
51
+ - Is context enough to draft now? (yes/no + reason)
52
+ - If no, what is the next most decision-changing question?
53
+ 5. Repeat until context is clear OR user asks to proceed.
54
+
55
+ ## Question Shape Rules
56
+
57
+ - Prefer single-select multiple choice when one direction/priority/next step must be chosen.
58
+ - Use multi-select only for compatible sets (goals, constraints, non-goals).
59
+ - Smart-skip questions already answered earlier (directly or implicitly) and log "skipped (already covered)" when relevant.
60
+
61
+ ## Stop Signals (Natural Language)
62
+
63
+ Treat these as stop-and-draft signals:
64
+ - RU: "достаточно", "хватит", "давай драфт"
65
+ - EN: "enough", "skip", "just draft it", "stop asking", "move on"
66
+ - UA: "досить", "вистачить", "давай драфт", "рухаємось далі"
67
+
68
+ When detected:
69
+ - Do not ask another question in this stage loop.
70
+ - Move to drafting with available context.
71
+ - For internal agent calls only, pass \`--skip-questions\` on the next advance helper call.
72
+
73
+ ## Conditional Grilling (Only On Risk Triggers)
74
+
75
+ Ask an extra 3-5 sharp questions only when one of these triggers appears:
76
+ - Irreversibility (data deletion, schema migration, breaking API/contract)
77
+ - Security/auth boundary changes
78
+ - Domain-model ambiguity with multiple plausible invariants
79
+
80
+ Do not ask extra questions "for theater" on simple low-risk work.
81
+
82
+ ## Question Budget Hint (Soft Guidance)
83
+
84
+ Use as orientation, never as a hard stop. Source of truth is \`questionBudgetHint(track, stage)\`:
85
+
86
+ ${budgetTable}
87
+
88
+ Track mapping note: \`quick\` ~= lightweight, \`medium\` ~= standard, \`standard\` ~= deep.
89
+ Stop based on clarity/user signal, not raw count.
90
+
91
+ ## Stage Forcing Questions
92
+
93
+ Always keep at least one unresolved forcing question in play until answered or explicitly waived:
94
+
95
+ - Brainstorm:
96
+ - What pain are we solving?
97
+ - What is the most direct path?
98
+ - What happens if we do nothing?
99
+ - Who is the operator/user impacted first?
100
+ - What are non-negotiable no-go boundaries?
101
+ - Scope:
102
+ - What is definitely in and definitely out?
103
+ - Which decisions are already locked upstream?
104
+ - What is the rollback path if this fails?
105
+ - What are the top failure modes we must design for?
106
+ - Design:
107
+ - What is the data flow end-to-end?
108
+ - Where are the seams/interfaces and ownership boundaries?
109
+ - Which invariants must always hold?
110
+ - What will we explicitly NOT refactor now?
111
+
112
+ ## One-Way Override (Irreversible Decisions)
113
+
114
+ For irreversible moves (deletion, schema migration, breaking API):
115
+ - Ask for explicit confirmation even if user asked to stop questions.
116
+ - Proceed only after explicit override ("I understand the irreversible risk; proceed").
117
+ - Record the override in \`## Q&A Log\` and in the stage artifact decision section.
118
+
119
+ ## Completion Rule
120
+
121
+ "Continue until clear OR user wants to proceed."
122
+ Never force a fixed N-question script.`;
123
+ }
@@ -10,3 +10,4 @@ export declare function noPlaceholdersBlock(): string;
10
10
  export declare function watchedFailProofBlock(): string;
11
11
  export declare function stageSkillFolder(stage: FlowStage): string;
12
12
  export declare function stageSkillMarkdown(stage: FlowStage, track?: FlowTrack): string;
13
+ export declare function executingWavesSkillMarkdown(): string;
@@ -148,11 +148,12 @@ function contextLoadingBlock(stage, trace, executionModel) {
148
148
 
149
149
  Before execution:
150
150
  1. Read \`.cclaw/state/flow-state.json\`.
151
+ - If the file is missing, do **not** invent an active run — this is normal for fresh init. Route to \`/cc <idea>\` first.
151
152
  2. Load active artifacts from \`.cclaw/artifacts/\`.
152
153
  3. Load upstream artifacts required by this stage:
153
154
  ${readLines}
154
155
  4. Read the state contract from \`.cclaw/templates/state-contracts/<stage>.json\` for required fields, taxonomies, and derived markdown path.
155
- 5. Read the canonical artifact template at \`${artifactTemplatePath}\` and reuse its exact section layout — per-row tables with stable column order, calibrated review block; do not invent layouts.
156
+ 5. Read the canonical artifact template at \`${artifactTemplatePath}\` to preserve heading/per-row tables contracts (stable section names and column order) plus calibrated review block scaffolding. Preserve existing substantive bullets/rows already in the artifact; never overwrite the artifact wholesale from the template — patch only sections you author this turn.
156
157
  6. Extract upstream decisions, constraints, and open questions into the current artifact's \`Upstream Handoff\` section when present.
157
158
  7. Confirm context readiness: upstream artifact freshness, required context, canonical template shape, relevant in-repo/reference patterns, and unresolved blockers are known. If any item is missing, load it or stop before drafting.
158
159
  8. Before doing stage work, give a compact user-facing drift preamble: "Carrying forward: <1-3 bullets>. Drift since upstream: None / <specific drift>. Recommendation: continue / re-scope."
@@ -376,7 +377,7 @@ function completionParametersBlock(schema, track) {
376
377
  - \`delegation lifecycle proof\`: use the delegation helper recipe in this section with explicit lifecycle rows: \`--status=scheduled\` -> \`--status=launched\` -> \`--status=acknowledged\` -> \`--status=completed\` (completed isolated/generic requires prior ACK for the same span or \`--ack-ts=<iso>\`).
377
378
  - Fill \`## Learnings\` before closeout: either \`- None this stage.\` or JSON bullets with required keys \`type\`, \`trigger\`, \`action\`, \`confidence\` (knowledge-schema compatible).
378
379
  - Record mandatory delegation lifecycle in \`${RUNTIME_ROOT}/state/delegation-log.json\` and append proof events to \`${RUNTIME_ROOT}/state/delegation-events.jsonl\`; the ledger is current state, the event log is audit proof.${mandatoryAgents.length > 0 ? ` If a mandatory delegation cannot run in this harness, use \`--waive-delegation=${mandatoryAgents.join(",")} --waiver-reason="<why safe>"\` on the completion helper.` : ""} If proactive delegations were intentionally skipped, rerun only with \`--accept-proactive-waiver\` (optionally \`--accept-proactive-waiver-reason="<why safe>"\`) after explicit user approval.
379
- - Never edit raw \`flow-state.json\` to complete a stage, even in advisory mode; that bypasses validation, gate evidence, and Learnings harvest. If the helper fails, stop and report the exact command/output instead of applying a manual state workaround.
380
+ - Never edit raw \`flow-state.json\` to complete a stage, even in advisory mode; that bypasses validation, gate evidence, and Learnings harvest. If a helper fails, report a one-line human-readable failure plus fenced JSON diagnostics; never echo the invoking command line or apply a manual state workaround.
380
381
  - Completion protocol: verify required gates, update the artifact, then use the completion helper with \`--evidence-json\` and \`--passed\` for every satisfied gate.
381
382
  `;
382
383
  }
@@ -607,3 +608,54 @@ ${reviewSectionsBlock(reviewLens.reviewSections)}
607
608
  - Keep decisions explicit: context, options, chosen option, rationale, risk, and rollback.
608
609
  `;
609
610
  }
611
+ export function executingWavesSkillMarkdown() {
612
+ return `---
613
+ name: executing-waves
614
+ description: "Execute multi-wave work using existing cclaw run resume + verify-current-state — no new CLI needed."
615
+ ---
616
+
617
+ # Executing Waves (Persistent Multi-Wave Work)
618
+
619
+ ## Overview
620
+
621
+ Long-form work (large refactors, multi-stage uplifts) often spans many waves.
622
+ This skill documents how the controller persists work across waves WITHOUT new
623
+ CLI commands, using existing \`cclaw run resume\` and \`internal verify-current-state\`.
624
+
625
+ ## When to Use
626
+
627
+ - Work spans 2+ commits / waves with cohesion concerns between waves.
628
+ - Each wave has its own stage cycle (brainstorm -> scope -> design -> spec -> plan -> tdd -> review -> ship).
629
+ - User wants explicit per-wave verification before the next wave starts.
630
+ - Risk of cross-wave drift exists.
631
+
632
+ ## Anti-Pattern
633
+
634
+ - Running many waves linearly without verification between them, accumulating drift.
635
+ - Treating a wave as only a commit boundary without re-verifying upstream decisions.
636
+
637
+ ## Process
638
+
639
+ 1. **Wave Start**: author wave plan as \`.cclaw/wave-plans/<wave-n>.md\` referencing previous wave's ship artifact.
640
+ 2. **Carry-forward Audit**: at brainstorm of the next wave, re-read previous wave ship artifact and explicitly record in the existing \`## Wave Carry-forward\` section:
641
+ - Carrying forward: <scope LD# hash references still valid>
642
+ - Drift detected: <decisions no longer valid + reason>
643
+ - Re-scope needed: <yes/no>
644
+ - Never create a second \`## Locked Decisions\` heading in brainstorm; reference prior LD# hashes inline.
645
+ 3. **Resume Path**: if a wave was interrupted mid-stage, \`cclaw run resume\` restores state. Run \`internal verify-current-state\` before continuing.
646
+ 4. **Wave End**: at ship, architect cross-stage verification runs from dispatch matrix. If \`DRIFT_DETECTED\`, fix before ship.
647
+ 5. **Next Wave Trigger**: launch new \`/cc <topic>\` for next wave and reference previous wave ship artifact in upstream handoff.
648
+
649
+ ## Status Markers
650
+
651
+ - \`wave-status: in-progress\` — current stage incomplete.
652
+ - \`wave-status: blocked-by-prev\` — waiting on previous wave verification.
653
+ - \`wave-status: shipped\` — wave shipped, next wave can start.
654
+ - \`wave-status: rolled-back\` — previous wave invalidated, current wave needs rebase.
655
+
656
+ ## Linter Hooks
657
+
658
+ - If multi-wave work is detected (>1 wave-plan files in \`.cclaw/wave-plans/\`), current brainstorm artifact MUST contain \`## Wave Carry-forward\` section with drift audit.
659
+ - If carry-forward drift is missing in multi-wave context, emit \`[P1] wave.drift_unaddressed\`.
660
+ `;
661
+ }