cclaw-cli 0.51.30 → 1.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 (160) hide show
  1. package/README.md +24 -18
  2. package/dist/artifact-linter/brainstorm.d.ts +2 -0
  3. package/dist/artifact-linter/brainstorm.js +289 -0
  4. package/dist/artifact-linter/design.d.ts +2 -0
  5. package/dist/artifact-linter/design.js +354 -0
  6. package/dist/artifact-linter/plan.d.ts +2 -0
  7. package/dist/artifact-linter/plan.js +183 -0
  8. package/dist/artifact-linter/review-army.d.ts +24 -0
  9. package/dist/artifact-linter/review-army.js +365 -0
  10. package/dist/artifact-linter/review.d.ts +2 -0
  11. package/dist/artifact-linter/review.js +99 -0
  12. package/dist/artifact-linter/scope.d.ts +2 -0
  13. package/dist/artifact-linter/scope.js +125 -0
  14. package/dist/artifact-linter/shared.d.ts +247 -0
  15. package/dist/artifact-linter/shared.js +1517 -0
  16. package/dist/artifact-linter/ship.d.ts +2 -0
  17. package/dist/artifact-linter/ship.js +82 -0
  18. package/dist/artifact-linter/spec.d.ts +2 -0
  19. package/dist/artifact-linter/spec.js +130 -0
  20. package/dist/artifact-linter/tdd.d.ts +2 -0
  21. package/dist/artifact-linter/tdd.js +198 -0
  22. package/dist/artifact-linter.d.ts +4 -76
  23. package/dist/artifact-linter.js +56 -2949
  24. package/dist/cli.d.ts +1 -6
  25. package/dist/cli.js +4 -159
  26. package/dist/codex-feature-flag.d.ts +1 -1
  27. package/dist/codex-feature-flag.js +1 -1
  28. package/dist/config.d.ts +3 -2
  29. package/dist/config.js +67 -3
  30. package/dist/constants.d.ts +1 -7
  31. package/dist/constants.js +10 -15
  32. package/dist/content/cancel-command.js +2 -2
  33. package/dist/content/closeout-guidance.d.ts +1 -1
  34. package/dist/content/closeout-guidance.js +15 -13
  35. package/dist/content/core-agents.d.ts +46 -29
  36. package/dist/content/core-agents.js +216 -82
  37. package/dist/content/decision-protocol.d.ts +1 -1
  38. package/dist/content/decision-protocol.js +1 -1
  39. package/dist/content/diff-command.js +1 -1
  40. package/dist/content/examples.d.ts +0 -3
  41. package/dist/content/examples.js +197 -752
  42. package/dist/content/harness-doc.js +20 -2
  43. package/dist/content/hook-manifest.d.ts +2 -2
  44. package/dist/content/hook-manifest.js +2 -2
  45. package/dist/content/hooks.d.ts +1 -0
  46. package/dist/content/hooks.js +32 -137
  47. package/dist/content/idea.d.ts +60 -0
  48. package/dist/content/idea.js +404 -0
  49. package/dist/content/iron-laws.d.ts +0 -1
  50. package/dist/content/iron-laws.js +31 -16
  51. package/dist/content/learnings.d.ts +2 -4
  52. package/dist/content/learnings.js +11 -27
  53. package/dist/content/meta-skill.js +7 -7
  54. package/dist/content/node-hooks.d.ts +10 -0
  55. package/dist/content/node-hooks.js +163 -95
  56. package/dist/content/opencode-plugin.js +15 -29
  57. package/dist/content/reference-patterns.js +2 -2
  58. package/dist/content/runtime-shared-snippets.d.ts +8 -0
  59. package/dist/content/runtime-shared-snippets.js +80 -0
  60. package/dist/content/session-hooks.js +1 -1
  61. package/dist/content/skills.d.ts +1 -0
  62. package/dist/content/skills.js +69 -7
  63. package/dist/content/stage-schema.js +147 -61
  64. package/dist/content/stages/_lint-metadata/index.js +26 -2
  65. package/dist/content/stages/brainstorm.js +13 -7
  66. package/dist/content/stages/design.js +16 -11
  67. package/dist/content/stages/plan.js +7 -4
  68. package/dist/content/stages/review.js +12 -12
  69. package/dist/content/stages/schema-types.d.ts +2 -2
  70. package/dist/content/stages/scope.js +15 -12
  71. package/dist/content/stages/ship.js +3 -3
  72. package/dist/content/stages/spec.js +9 -3
  73. package/dist/content/stages/tdd.js +14 -4
  74. package/dist/content/start-command.js +11 -10
  75. package/dist/content/status-command.js +5 -5
  76. package/dist/content/subagent-context-skills.js +156 -1
  77. package/dist/content/subagents.d.ts +0 -5
  78. package/dist/content/subagents.js +65 -81
  79. package/dist/content/templates.d.ts +1 -1
  80. package/dist/content/templates.js +187 -154
  81. package/dist/content/tree-command.js +2 -2
  82. package/dist/content/utility-skills.d.ts +2 -2
  83. package/dist/content/utility-skills.js +28 -99
  84. package/dist/content/view-command.js +4 -2
  85. package/dist/delegation.d.ts +2 -0
  86. package/dist/delegation.js +2 -1
  87. package/dist/early-loop.d.ts +66 -0
  88. package/dist/early-loop.js +275 -0
  89. package/dist/flow-state.d.ts +5 -6
  90. package/dist/flow-state.js +4 -6
  91. package/dist/gate-evidence.d.ts +0 -23
  92. package/dist/gate-evidence.js +111 -153
  93. package/dist/harness-adapters.d.ts +2 -2
  94. package/dist/harness-adapters.js +48 -19
  95. package/dist/install.js +190 -32
  96. package/dist/internal/advance-stage/advance.d.ts +50 -0
  97. package/dist/internal/advance-stage/advance.js +479 -0
  98. package/dist/internal/advance-stage/cancel-run.d.ts +8 -0
  99. package/dist/internal/advance-stage/cancel-run.js +19 -0
  100. package/dist/internal/advance-stage/flow-state-coercion.d.ts +3 -0
  101. package/dist/internal/advance-stage/flow-state-coercion.js +81 -0
  102. package/dist/internal/advance-stage/helpers.d.ts +14 -0
  103. package/dist/internal/advance-stage/helpers.js +145 -0
  104. package/dist/internal/advance-stage/hook.d.ts +8 -0
  105. package/dist/internal/advance-stage/hook.js +40 -0
  106. package/dist/internal/advance-stage/parsers.d.ts +54 -0
  107. package/dist/internal/advance-stage/parsers.js +307 -0
  108. package/dist/internal/advance-stage/review-loop.d.ts +7 -0
  109. package/dist/internal/advance-stage/review-loop.js +161 -0
  110. package/dist/internal/advance-stage/rewind.d.ts +14 -0
  111. package/dist/internal/advance-stage/rewind.js +108 -0
  112. package/dist/internal/advance-stage/start-flow.d.ts +11 -0
  113. package/dist/internal/advance-stage/start-flow.js +136 -0
  114. package/dist/internal/advance-stage/verify.d.ts +29 -0
  115. package/dist/internal/advance-stage/verify.js +225 -0
  116. package/dist/internal/advance-stage.js +21 -1470
  117. package/dist/internal/compound-readiness.d.ts +1 -1
  118. package/dist/internal/compound-readiness.js +2 -2
  119. package/dist/internal/early-loop-status.d.ts +7 -0
  120. package/dist/internal/early-loop-status.js +90 -0
  121. package/dist/internal/runtime-integrity.d.ts +7 -0
  122. package/dist/internal/runtime-integrity.js +288 -0
  123. package/dist/internal/tdd-red-evidence.js +1 -1
  124. package/dist/knowledge-store.d.ts +5 -28
  125. package/dist/knowledge-store.js +57 -84
  126. package/dist/managed-resources.js +24 -2
  127. package/dist/policy.js +7 -9
  128. package/dist/retro-gate.js +8 -90
  129. package/dist/run-archive.d.ts +1 -1
  130. package/dist/run-archive.js +13 -16
  131. package/dist/run-persistence.js +20 -15
  132. package/dist/runtime/run-hook.entry.d.ts +3 -0
  133. package/dist/runtime/run-hook.entry.js +5 -0
  134. package/dist/runtime/run-hook.mjs +9477 -0
  135. package/dist/tdd-cycle.d.ts +3 -3
  136. package/dist/tdd-cycle.js +1 -1
  137. package/dist/types.d.ts +18 -10
  138. package/package.json +4 -2
  139. package/dist/content/hook-inline-snippets.d.ts +0 -83
  140. package/dist/content/hook-inline-snippets.js +0 -302
  141. package/dist/content/ideate-command.d.ts +0 -8
  142. package/dist/content/ideate-command.js +0 -315
  143. package/dist/content/ideate-frames.d.ts +0 -31
  144. package/dist/content/ideate-frames.js +0 -140
  145. package/dist/content/ideate-ranking.d.ts +0 -25
  146. package/dist/content/ideate-ranking.js +0 -65
  147. package/dist/content/next-command.d.ts +0 -20
  148. package/dist/content/next-command.js +0 -298
  149. package/dist/content/seed-shelf.d.ts +0 -36
  150. package/dist/content/seed-shelf.js +0 -301
  151. package/dist/content/stage-common-guidance.d.ts +0 -1
  152. package/dist/content/stage-common-guidance.js +0 -106
  153. package/dist/doctor-registry.d.ts +0 -10
  154. package/dist/doctor-registry.js +0 -186
  155. package/dist/doctor.d.ts +0 -17
  156. package/dist/doctor.js +0 -2201
  157. package/dist/internal/hook-manifest.d.ts +0 -16
  158. package/dist/internal/hook-manifest.js +0 -77
  159. package/dist/trace-matrix.d.ts +0 -27
  160. package/dist/trace-matrix.js +0 -226
@@ -0,0 +1,404 @@
1
+ import { RUNTIME_ROOT } from "../constants.js";
2
+ import { ideaStructuredAskToolsWithFallback } from "./decision-protocol.js";
3
+ import { conversationLanguagePolicyMarkdown } from "./language-policy.js";
4
+ const FRAME_REGISTRY = {
5
+ "pain-friction": {
6
+ id: "pain-friction",
7
+ label: "pain/friction",
8
+ prompt: "Find repeated friction in the repo workflow. Prioritize changes that eliminate recurring toil, fragile handoffs, or repeated manual recovery.",
9
+ examplePatterns: [
10
+ "Repeated TODO/FIXME hotspots in one subsystem",
11
+ "Flows that require manual retries or ad-hoc scripts",
12
+ "Developer loops slowed by avoidable boilerplate"
13
+ ]
14
+ },
15
+ "assumption-break": {
16
+ id: "assumption-break",
17
+ label: "assumption-break",
18
+ prompt: "List the top assumptions behind the current approach and break one: what if that assumption is wrong, incomplete, or expensive to maintain?",
19
+ examplePatterns: [
20
+ "An approval gate currently assumed to be always manual can be automated safely",
21
+ "A broad required section can be optional with measurable trigger conditions",
22
+ "A long checklist step can be replaced by a deterministic verifier"
23
+ ]
24
+ },
25
+ "cross-domain-analogy": {
26
+ id: "cross-domain-analogy",
27
+ label: "cross-domain-analogy",
28
+ prompt: "Borrow one proven pattern from an adjacent domain and map it to this repository's constraints.",
29
+ examplePatterns: [
30
+ "Treat post-ship closeout like incident-response runbooks with explicit ownership",
31
+ "Apply API compatibility techniques to artifact schema evolution",
32
+ "Use observability SLO-style thresholds for process-quality gates"
33
+ ]
34
+ }
35
+ };
36
+ export const DEFAULT_IDEA_FRAME_IDS = Object.freeze([
37
+ "pain-friction",
38
+ "assumption-break",
39
+ "cross-domain-analogy"
40
+ ]);
41
+ export const IDEA_FRAMES = Object.freeze(DEFAULT_IDEA_FRAME_IDS.map((id) => FRAME_REGISTRY[id]));
42
+ export function resolveIdeaFrames(frameIds) {
43
+ if (!frameIds || frameIds.length === 0) {
44
+ return [...IDEA_FRAMES];
45
+ }
46
+ const seen = new Set();
47
+ const resolved = [];
48
+ for (const rawId of frameIds) {
49
+ if (!DEFAULT_IDEA_FRAME_IDS.includes(rawId)) {
50
+ throw new Error(`Unknown idea frame id: ${rawId}`);
51
+ }
52
+ if (seen.has(rawId))
53
+ continue;
54
+ seen.add(rawId);
55
+ resolved.push(FRAME_REGISTRY[rawId]);
56
+ }
57
+ return resolved;
58
+ }
59
+ export function buildIdeaFrameDispatchPlan(input, frameIds) {
60
+ const signalBlock = input.signalSummary.length > 0
61
+ ? input.signalSummary.map((line) => `- ${line}`).join("\n")
62
+ : "- no pre-scan signals captured yet";
63
+ return resolveIdeaFrames(frameIds).map((frame) => ({
64
+ frameId: frame.id,
65
+ label: frame.label,
66
+ prompt: [
67
+ `Frame: ${frame.label} (${frame.id})`,
68
+ `Mode: ${input.mode}`,
69
+ `Focus: ${input.focus || "open-ended scan"}`,
70
+ "",
71
+ "Signal summary:",
72
+ signalBlock,
73
+ "",
74
+ `Frame prompt: ${frame.prompt}`,
75
+ "",
76
+ "Generate 3-5 concrete candidates with repo-grounded evidence."
77
+ ].join("\n")
78
+ }));
79
+ }
80
+ function normalizeCandidateKey(title, evidencePath) {
81
+ const normalizedTitle = title.trim().toLowerCase().replace(/[^a-z0-9]+/gu, " ").trim();
82
+ const normalizedEvidence = evidencePath
83
+ .trim()
84
+ .toLowerCase()
85
+ .replace(/\\/gu, "/");
86
+ return `${normalizedTitle}::${normalizedEvidence}`;
87
+ }
88
+ export function dedupeIdeaCandidates(drafts) {
89
+ const merged = new Map();
90
+ for (const draft of drafts) {
91
+ const key = normalizeCandidateKey(draft.title, draft.evidencePath);
92
+ const existing = merged.get(key);
93
+ if (!existing) {
94
+ merged.set(key, {
95
+ title: draft.title,
96
+ evidencePath: draft.evidencePath,
97
+ summary: draft.summary,
98
+ frameIds: [draft.frameId]
99
+ });
100
+ continue;
101
+ }
102
+ if (!existing.frameIds.includes(draft.frameId)) {
103
+ existing.frameIds.push(draft.frameId);
104
+ }
105
+ if (draft.summary.length > existing.summary.length) {
106
+ existing.summary = draft.summary;
107
+ }
108
+ }
109
+ return [...merged.values()];
110
+ }
111
+ const IMPACT_PRIORITY = {
112
+ high: 3,
113
+ medium: 2,
114
+ low: 1
115
+ };
116
+ const EFFORT_PRIORITY = {
117
+ s: 0,
118
+ m: 1,
119
+ l: 2
120
+ };
121
+ const CONFIDENCE_PRIORITY = {
122
+ high: 2,
123
+ medium: 1,
124
+ low: 0
125
+ };
126
+ function isRejectedIdea(input) {
127
+ if (input.confidence === "low")
128
+ return true;
129
+ if (input.impact === "low" && input.effort === "l")
130
+ return true;
131
+ return false;
132
+ }
133
+ export function scoreIdeaCandidate(impact, effort, confidence) {
134
+ // Keep the scoring intentionally simple and monotonic.
135
+ return IMPACT_PRIORITY[impact] + CONFIDENCE_PRIORITY[confidence] - EFFORT_PRIORITY[effort];
136
+ }
137
+ export function evaluateIdeaCandidate(input) {
138
+ const disposition = isRejectedIdea(input) ? "rejected" : "survivor";
139
+ return {
140
+ ...input,
141
+ disposition,
142
+ rankingScore: scoreIdeaCandidate(input.impact, input.effort, input.confidence)
143
+ };
144
+ }
145
+ export function rankIdeaCandidates(inputs, maxSurvivors = 10) {
146
+ const evaluated = inputs.map(evaluateIdeaCandidate);
147
+ const survivors = evaluated
148
+ .filter((candidate) => candidate.disposition === "survivor")
149
+ .sort((left, right) => {
150
+ // Deterministic ordering: impact > effort > confidence > id.
151
+ const impactDelta = IMPACT_PRIORITY[right.impact] - IMPACT_PRIORITY[left.impact];
152
+ if (impactDelta !== 0)
153
+ return impactDelta;
154
+ const effortDelta = EFFORT_PRIORITY[left.effort] - EFFORT_PRIORITY[right.effort];
155
+ if (effortDelta !== 0)
156
+ return effortDelta;
157
+ const confidenceDelta = CONFIDENCE_PRIORITY[right.confidence] - CONFIDENCE_PRIORITY[left.confidence];
158
+ if (confidenceDelta !== 0)
159
+ return confidenceDelta;
160
+ return left.id.localeCompare(right.id);
161
+ })
162
+ .slice(0, Math.max(0, maxSurvivors));
163
+ const survivorIds = new Set(survivors.map((candidate) => candidate.id));
164
+ const rejected = evaluated
165
+ .filter((candidate) => candidate.disposition === "rejected" || !survivorIds.has(candidate.id))
166
+ .sort((left, right) => left.id.localeCompare(right.id));
167
+ return {
168
+ survivors,
169
+ rejected,
170
+ recommendationId: survivors[0]?.id ?? null
171
+ };
172
+ }
173
+ const IDEA_SKILL_FOLDER = "flow-idea";
174
+ const IDEA_SKILL_NAME = "flow-idea";
175
+ const IDEA_ARTIFACT_GLOB = ".cclaw/artifacts/idea-*.md";
176
+ const IDEA_ARTIFACT_PATTERN = ".cclaw/artifacts/idea-<YYYY-MM-DD-slug>.md";
177
+ const IDEA_RESUME_WINDOW_DAYS = 30;
178
+ const STRUCTURED_ASK_TOOLS = ideaStructuredAskToolsWithFallback();
179
+ export function minimumDistinctIdeaFrames(frameCount, mode = "repo-grounded") {
180
+ if (frameCount <= 0)
181
+ return 0;
182
+ const cap = mode === "repo-grounded" ? 3 : 2;
183
+ return Math.min(cap, frameCount);
184
+ }
185
+ function renderFrameBullets(frameIds) {
186
+ return resolveIdeaFrames(frameIds)
187
+ .map((frame) => ` - ${frame.label} (\`${frame.id}\`)`)
188
+ .join("\n");
189
+ }
190
+ function renderFrameNames(frameIds) {
191
+ return resolveIdeaFrames(frameIds)
192
+ .map((frame) => frame.label)
193
+ .join(", ");
194
+ }
195
+ export function ideaCommandContract(options = {}) {
196
+ const frames = resolveIdeaFrames(options.frameIds);
197
+ const frameBullets = renderFrameBullets(options.frameIds);
198
+ const minimumDistinctFrames = minimumDistinctIdeaFrames(frames.length, options.mode);
199
+ return `# /cc-idea
200
+
201
+ ## Purpose
202
+
203
+ Repository-improvement idea mode. Generate a ranked backlog of
204
+ high-value improvements, persist it as an artifact on disk, and end with
205
+ an explicit handoff - either launch \`/cc\` on a chosen candidate in the
206
+ same session, or save/discard the backlog.
207
+
208
+ ## HARD-GATE
209
+
210
+ ${conversationLanguagePolicyMarkdown()}
211
+ - Idea mode only. Never mutate \`.cclaw/state/flow-state.json\`.
212
+ - Every recommendation cites evidence from the current repository
213
+ (file path, command output, or knowledge-store entry id).
214
+ - Whenever you produce ideation output, persist it to
215
+ \`${IDEA_ARTIFACT_PATTERN}\`. Chat-only output is not acceptable.
216
+ The only exception is an explicit user-cancel from the resume prompt -
217
+ in that case, write nothing and exit silently.
218
+ - Always end with a structured handoff prompt, not an open question
219
+ (skipped on explicit cancel).
220
+
221
+ ## Algorithm
222
+
223
+ 1. **Resume check.** Glob \`${IDEA_ARTIFACT_GLOB}\`. If any artifact
224
+ has been modified within the last ${IDEA_RESUME_WINDOW_DAYS} days,
225
+ offer the user: continue that backlog, start fresh, or cancel.
226
+ 2. **Mode classification.** Explicitly classify subject:
227
+ \`repo-grounded\` / \`elsewhere-software\` / \`elsewhere-non-software\` / \`narrow\`.
228
+ 3. **Mode-aware grounding (parallel).**
229
+ - Repo-grounded: repo signal scan + \`${RUNTIME_ROOT}/knowledge.jsonl\`
230
+ repetition scan.
231
+ - Elsewhere-software: docs-first grounding (Context7 and official docs).
232
+ - Elsewhere-non-software: constraints and objective grounding.
233
+ 4. **Divergent ideation frames (parallel).** Generate candidates with
234
+ configured frames (${frames.length} total):
235
+ ${frameBullets}
236
+ Keep at least ${minimumDistinctFrames} distinct frame outputs in this rendered mode.
237
+ Deterministic minimum: repo-grounded = 3, narrow/non-repo = 2, always capped
238
+ by configured frame count.
239
+ 5. **Adversarial critique pass.** For each candidate, write the strongest
240
+ counter-argument, kill weak ideas, and keep survivors only.
241
+ 6. **Produce 5-10 survivors** with impact (High/Medium/Low),
242
+ effort (S/M/L), confidence (High/Medium/Low), **why now**, expected user impact, risk, and one evidence path per
243
+ survivor.
244
+ 7. **Rank by simple triage order**: impact first, then effort, then confidence.
245
+ Reject low-confidence ideas and obvious low-impact/high-effort outliers.
246
+ Recommend the top survivor.
247
+ 8. **Write the artifact** at
248
+ \`${IDEA_ARTIFACT_PATTERN}\` using the schema in the skill.
249
+ 9. **Present the handoff prompt** with four concrete options - not A/B/C
250
+ letters. Default = "Start /cc on the top recommendation".
251
+
252
+ ## Headless mode (CI/automation only)
253
+
254
+ Headless envelopes are a machine-mode exception for CI/automation orchestration.
255
+ In normal interactive ideation, respond with natural language plus the artifact path.
256
+ For skill-to-skill invocation, emit exactly one JSON envelope:
257
+
258
+ \`\`\`json
259
+ {"version":"1","kind":"stage-output","stage":"non-flow","payload":{"command":"/cc-idea","artifact":".cclaw/artifacts/idea-<date>-<slug>.md","recommendation":"I-1"},"emittedAt":"<ISO-8601>"}
260
+ \`\`\`
261
+
262
+ Validate envelopes with:
263
+ \`npx cclaw-cli internal envelope-validate --stdin\`
264
+
265
+ ## Primary skill
266
+
267
+ **${RUNTIME_ROOT}/skills/${IDEA_SKILL_FOLDER}/SKILL.md**
268
+ `;
269
+ }
270
+ export function ideaCommandSkillMarkdown(options = {}) {
271
+ const frames = resolveIdeaFrames(options.frameIds);
272
+ const frameBullets = renderFrameBullets(options.frameIds);
273
+ const minimumDistinctFrames = minimumDistinctIdeaFrames(frames.length, options.mode);
274
+ const frameNames = renderFrameNames(options.frameIds);
275
+ return `---
276
+ name: ${IDEA_SKILL_NAME}
277
+ description: "Repository idea mode: detect and rank high-leverage improvements, persist a backlog artifact, and hand off to /cc or save/discard."
278
+ ---
279
+
280
+ # /cc-idea
281
+
282
+ ## Announce at start
283
+
284
+ "Using flow-idea to identify highest-leverage improvements in this
285
+ repository. Will persist a ranked backlog to
286
+ \`${IDEA_ARTIFACT_PATTERN}\` and end with an explicit handoff."
287
+
288
+ ## HARD-GATE
289
+
290
+ ${conversationLanguagePolicyMarkdown()}
291
+ - Do not start coding in idea mode.
292
+ - Do not mutate \`.cclaw/state/flow-state.json\` - idea mode sits outside
293
+ the critical-path flow.
294
+ - Whenever ideation output is produced, persist the artifact file on disk
295
+ before presenting the handoff. The only exception is an explicit user-cancel
296
+ from the resume prompt - in that case, write nothing and exit silently.
297
+ - Always end with a structured handoff that names the concrete follow-up
298
+ command for each option (skipped on explicit cancel). No A/B/C letters
299
+ without command context.
300
+
301
+ ## Protocol
302
+
303
+ ### Phase 0 - Resume and classify
304
+
305
+ 1. Use the harness's file-glob tool (\`Glob\` pattern
306
+ \`${IDEA_ARTIFACT_GLOB}\` or equivalent \`ls\`).
307
+ 2. Filter to files modified within the last ${IDEA_RESUME_WINDOW_DAYS} days.
308
+ 3. If one or more match, present **one** structured ask using the
309
+ harness's native tool (${STRUCTURED_ASK_TOOLS}) with options:
310
+ - **Continue the existing backlog**.
311
+ - **Start a fresh scan**.
312
+ - **Cancel**.
313
+ 4. If no recent artifact exists, proceed to Phase 1 silently.
314
+ 5. Classify the ideation mode before grounding:
315
+ - \`repo-grounded\`
316
+ - \`elsewhere-software\`
317
+ - \`elsewhere-non-software\`
318
+ - \`narrow\`
319
+ 6. Record the chosen mode in the artifact.
320
+
321
+ ### Phase 1 - Mode-aware grounding
322
+
323
+ Run grounding in parallel where available:
324
+
325
+ - For \`repo-grounded\`:
326
+ - \`rg -n 'TODO|FIXME|XXX|HACK|TBD'\` grouped by file.
327
+ - Test-runner output (\`npm test\`, \`pytest\`, \`go test ./...\`) - note
328
+ failures, timeouts, deprecation warnings.
329
+ - Module size outliers with weak direct test coverage.
330
+ - Docs drift checks for stale references.
331
+ - \`${RUNTIME_ROOT}/knowledge.jsonl\` entries where \`type\` is
332
+ \`rule | pattern | lesson | compound\`, with repeated \`trigger/action\`
333
+ pairs and stable high-confidence patterns.
334
+ - For \`elsewhere-software\`:
335
+ - Gather current framework/library docs first.
336
+ - Add one comparison scan for established solutions.
337
+ - For \`elsewhere-non-software\`:
338
+ - Capture objective, constraints, and measured friction before proposing fixes.
339
+
340
+ Record each finding with exact evidence (path, command, or doc source).
341
+
342
+ ### Phase 2 - Divergent ideation
343
+
344
+ Generate candidate ideas by frame, in parallel when possible:
345
+
346
+ ${frameBullets}
347
+
348
+ Require at least ${minimumDistinctFrames} distinct frames in this rendered mode. The
349
+ runtime rule is deterministic: repo-grounded scans require 3 distinct frames;
350
+ narrow, elsewhere-software, and elsewhere-non-software runs require 2; all modes
351
+ are capped by the configured frame count.
352
+
353
+ ### Phase 3 - Critique all, keep survivors
354
+
355
+ For each raw candidate:
356
+ - Write strongest argument **against** this idea.
357
+ - Identify disqualifiers (duplicate, weak evidence, poor ROI, wrong timing).
358
+ - Mark as \`survivor\` or \`rejected\`.
359
+
360
+ Only survivors advance to ranking.
361
+
362
+ ### Phase 4 - Rank and write the artifact
363
+
364
+ 1. Keep 5-10 survivors.
365
+ 2. For each survivor, include:
366
+ - **ID** - \`I-1\`, \`I-2\`, ...
367
+ - **Title**
368
+ - **Impact** - High / Medium / Low
369
+ - **Effort** - S / M / L
370
+ - **Confidence** - High / Medium / Low
371
+ - **Evidence**
372
+ - **Why now**
373
+ - **Expected impact**
374
+ - **Risk**
375
+ - **Counter-argument**
376
+ - **Next /cc prompt**
377
+ 3. Sort survivors by impact, then effort, then confidence.
378
+ 4. Write \`.cclaw/artifacts/idea-<date>-<slug>.md\`.
379
+ 5. Confirm in chat: "Wrote <path>".
380
+
381
+ ### Phase 5 - Handoff prompt
382
+
383
+ Present one structured ask with exactly these options (no bare A/B/C):
384
+ Required options, in this order:
385
+ 1. **Start /cc on the top recommendation** (default)
386
+ 2. **Pick a different candidate**
387
+ 3. **Save and close**
388
+ 4. **Discard**
389
+
390
+ ### Phase 6 - Execute the choice
391
+
392
+ - Start /cc: load \`${RUNTIME_ROOT}/skills/using-cclaw/SKILL.md\` and run
393
+ \`/cc <phrase>\`.
394
+ - Save and close: reply with artifact path and stop.
395
+ - Discard: delete the artifact and stop.
396
+
397
+ ## Do not
398
+
399
+ - Do not write into \`.cclaw/artifacts/0X-*.md\` (stage artifacts).
400
+ - Do not mutate \`.cclaw/state/flow-state.json\`.
401
+ - Do not collapse all ideas into one frame; distribute across:
402
+ ${frameNames}.
403
+ `;
404
+ }
@@ -138,5 +138,4 @@ export declare function ironLawRuntimeDocument(options?: {
138
138
  strictLaws?: string[];
139
139
  nowIso?: string;
140
140
  }): IronLawRuntimeDocument;
141
- export declare function ironLawsAgentsMdBlock(): string;
142
141
  export declare function ironLawsSkillMarkdown(): string;
@@ -146,31 +146,37 @@ export function ironLawRuntimeDocument(options = {}) {
146
146
  laws
147
147
  };
148
148
  }
149
- export function ironLawsAgentsMdBlock() {
150
- const rows = IRON_LAWS.map((law) => {
151
- return `| \`${law.id}\` | ${law.rule} | ${law.enforcement} | ${law.severity} |`;
152
- }).join("\n");
153
- return `### Iron Laws
154
-
155
- These rules are always-on. Hook-enforced laws can block actions in strict mode.
156
-
157
- | ID | Rule | Enforced by | Level |
158
- |---|---|---|---|
159
- ${rows}
160
- `;
149
+ function appliesToLabel(law) {
150
+ return law.appliesTo === "all" ? "all stages" : law.appliesTo.join(", ");
151
+ }
152
+ function hardGateReference(law) {
153
+ if (law.appliesTo === "all") {
154
+ return "the active stage `HARD-GATE` block in `.cclaw/skills/<stage>/SKILL.md`";
155
+ }
156
+ return law.appliesTo
157
+ .map((stage) => `\`${RUNTIME_ROOT}/skills/${stage}/SKILL.md\` (${stage} HARD-GATE)`)
158
+ .join(", ");
161
159
  }
162
160
  export function ironLawsSkillMarkdown() {
163
- const list = IRON_LAWS.map((law, index) => {
164
- const applies = law.appliesTo === "all" ? "all stages" : law.appliesTo.join(", ");
161
+ const enforcedLawIds = new Set([
162
+ "stop-clean-or-handoff",
163
+ "review-coverage-complete-before-ship"
164
+ ]);
165
+ const enforced = IRON_LAWS.filter((law) => enforcedLawIds.has(law.id));
166
+ const advisory = IRON_LAWS.filter((law) => !enforcedLawIds.has(law.id));
167
+ const enforcedSections = enforced.map((law, index) => {
165
168
  return `### ${index + 1}. ${law.title}
166
169
 
167
170
  - **ID:** \`${law.id}\`
168
171
  - **Rule:** ${law.rule}
169
172
  - **Why:** ${law.rationale}
170
- - **Applies to:** ${applies}
173
+ - **Applies to:** ${appliesToLabel(law)}
171
174
  - **Enforced by:** ${law.enforcement} (${law.severity})
172
175
  `;
173
176
  }).join("\n");
177
+ const advisoryList = advisory
178
+ .map((law) => `- \`${law.id}\` — applies to ${appliesToLabel(law)}; see ${hardGateReference(law)}.`)
179
+ .join("\n");
174
180
  return `---
175
181
  name: iron-laws
176
182
  description: "Non-negotiable workflow constraints enforced by cclaw hooks and routing."
@@ -181,7 +187,16 @@ description: "Non-negotiable workflow constraints enforced by cclaw hooks and ro
181
187
  These are cclaw's non-negotiable constraints for harness sessions.
182
188
  Use them as the final arbitration layer when local instructions conflict.
183
189
 
184
- ${list}
190
+ ## Hook-Enforced Runtime Laws
191
+
192
+ ${enforcedSections}
193
+
194
+ ## Advisory Laws (Stage-Owned)
195
+
196
+ The following laws remain active guidance, but their canonical enforcement surface
197
+ is each stage's \`HARD-GATE\` contract:
198
+
199
+ ${advisoryList}
185
200
 
186
201
  ## Practical rule
187
202
 
@@ -1,8 +1,6 @@
1
1
  /**
2
2
  * Canonical required JSONL field order (matches strict validator keys).
3
- * Optional keys (`source`, `severity`, `supersedes`, `superseded_by`) may
4
- * be appended after these required fields.
5
- * Exported for tests and any programmatic writer that wants a stable base shape.
3
+ * Optional keys (`source`, `severity`) may be appended after these required fields.
6
4
  */
7
- export declare const KNOWLEDGE_JSONL_FIELDS: readonly ["type", "trigger", "action", "confidence", "domain", "stage", "origin_stage", "origin_run", "frequency", "universality", "maturity", "created", "first_seen_ts", "last_seen_ts", "project"];
5
+ export declare const KNOWLEDGE_JSONL_FIELDS: readonly ["type", "trigger", "action", "confidence", "stage", "origin_stage", "frequency", "created", "first_seen_ts", "last_seen_ts", "project"];
8
6
  export declare function learnSkillMarkdown(): string;
@@ -11,22 +11,16 @@ const LEARN_SKILL_NAME = "learnings";
11
11
  const LEARN_SKILL_DESCRIPTION = "Project-scoped knowledge store: append and query rule/pattern/lesson/compound entries in the canonical JSONL file at .cclaw/knowledge.jsonl. Strict schema, append-only, machine-queryable.";
12
12
  /**
13
13
  * Canonical required JSONL field order (matches strict validator keys).
14
- * Optional keys (`source`, `severity`, `supersedes`, `superseded_by`) may
15
- * be appended after these required fields.
16
- * Exported for tests and any programmatic writer that wants a stable base shape.
14
+ * Optional keys (`source`, `severity`) may be appended after these required fields.
17
15
  */
18
16
  export const KNOWLEDGE_JSONL_FIELDS = [
19
17
  "type",
20
18
  "trigger",
21
19
  "action",
22
20
  "confidence",
23
- "domain",
24
21
  "stage",
25
22
  "origin_stage",
26
- "origin_run",
27
23
  "frequency",
28
- "universality",
29
- "maturity",
30
24
  "created",
31
25
  "first_seen_ts",
32
26
  "last_seen_ts",
@@ -74,14 +68,14 @@ During manual knowledge operations, only modify \`${KNOWLEDGE_PATH}\`, \`${KNOWL
74
68
  or an explicitly user-approved summary file. Do not modify application code here.
75
69
  Do not invent alternate stores (no markdown mirror, no SQLite, no per-stage files).
76
70
 
77
- ## Entry format strict JSONL schema
71
+ ## Entry format - strict JSONL schema
78
72
 
79
73
  Exactly one JSON object per line. Required fields must appear in the order:
80
- \`type, trigger, action, confidence, domain, stage, origin_stage, origin_run, frequency, universality, maturity, created, first_seen_ts, last_seen_ts, project\`.
81
- Optional fields \`source\`, \`severity\`, \`supersedes\`, and \`superseded_by\` may be appended after \`project\`.
74
+ \`type, trigger, action, confidence, stage, origin_stage, frequency, created, first_seen_ts, last_seen_ts, project\`.
75
+ Optional fields \`source\` and \`severity\` may be appended after \`project\`.
82
76
 
83
77
  \`\`\`json
84
- {"type":"pattern","trigger":"when reviewing external payloads","action":"parse through zod before touching service layer","confidence":"high","domain":"api","stage":"review","origin_stage":"review","origin_run":"payload-hardening","frequency":1,"universality":"project","maturity":"raw","created":"2026-04-14T12:00:00Z","first_seen_ts":"2026-04-14T12:00:00Z","last_seen_ts":"2026-04-14T12:00:00Z","project":"cclaw"}
78
+ {"type":"pattern","trigger":"when reviewing external payloads","action":"parse through zod before touching service layer","confidence":"high","stage":"review","origin_stage":"review","frequency":1,"created":"2026-04-14T12:00:00Z","first_seen_ts":"2026-04-14T12:00:00Z","last_seen_ts":"2026-04-14T12:00:00Z","project":"cclaw"}
85
79
  \`\`\`
86
80
 
87
81
  | field | type | required | notes |
@@ -90,28 +84,19 @@ Optional fields \`source\`, \`severity\`, \`supersedes\`, and \`superseded_by\`
90
84
  | \`trigger\` | string | yes | The concrete situation that must be recognized. Start with a verb or \`when …\`. |
91
85
  | \`action\` | string | yes | The concrete move to take when the trigger fires. One sentence. |
92
86
  | \`confidence\` | \`"high" \\| "medium" \\| "low"\` | yes | Write \`medium\` when unsure; do not omit. |
93
- | \`domain\` | string \\| null | yes | Free-form taxonomy (\`api\`, \`infra\`, \`ui\`, \`security\`, \`testing\`, …). Use \`null\` when cross-cutting. |
94
87
  | \`stage\` | \`FlowStage\` \\| null | yes | One of brainstorm / scope / design / spec / plan / tdd / review / ship, or \`null\` when cross-stage. |
95
88
  | \`origin_stage\` | \`FlowStage\` \\| null | yes | Stage where this learning was first observed. |
96
- | \`origin_run\` | string \\| null | yes | Optional run, branch, or topic label where it was observed first. |
97
89
  | \`frequency\` | integer >= 1 | yes | Number of times this same trigger/action pair has been observed. |
98
- | \`universality\` | \`"project" \\| "personal" \\| "universal"\` | yes | Scope of applicability. |
99
- | \`maturity\` | \`"raw" \\| "lifted-to-rule" \\| "lifted-to-enforcement"\` | yes | Lifecycle state of the learning. |
100
90
  | \`created\` | ISO 8601 UTC string | yes | \`date -u +%Y-%m-%dT%H:%M:%SZ\`. |
101
91
  | \`first_seen_ts\` | ISO 8601 UTC string | yes | First observed timestamp (usually equals \`created\`). |
102
92
  | \`last_seen_ts\` | ISO 8601 UTC string | yes | Last re-confirmed timestamp. |
103
93
  | \`project\` | string \\| null | yes | Repo or scope name. Use \`null\` when the entry crosses projects. |
104
- | \`source\` | \`"stage" \\| "retro" \\| "compound" \\| "ideate" \\| "manual" \\| null\` | no | Origin channel for the entry when known. |
94
+ | \`source\` | \`"stage" \\| "retro" \\| "compound" \\| "idea" \\| "manual" \\| null\` | no | Origin channel for the entry when known. |
105
95
  | \`severity\` | \`"critical" \\| "important" \\| "suggestion"\` | no | Priority signal for compound lifts; \`critical\` enables single-hit override in compound readiness analysis. |
106
- | \`supersedes\` | string[] | no | Non-empty IDs/slugs of older entries this entry refreshes. Use only for clear replacements discovered during compound closeout or curation. |
107
- | \`superseded_by\` | string | no | Non-empty ID/slug of the newer entry that refreshes this one. Use only when marking stale guidance as replaced. |
108
96
 
109
97
  Rules:
110
98
  - No other fields beyond the table above. Extra keys are forbidden and MUST be rejected by any writer.
111
- - Every required-null field must be emitted explicitly as \`null\` (not omitted). This keeps the file grep-friendly.
112
- - Append-only: never rewrite or delete a historical line. Corrections are new
113
- entries whose \`trigger\` clearly supersedes the earlier one; add \`supersedes\` /
114
- \`superseded_by\` only when the replacement relationship is clear.
99
+ - Append-only: never rewrite or delete a historical line.
115
100
  - Keep each entry one line. No pretty-printing. No trailing commas.
116
101
 
117
102
  ## Curation policy (target: ≤ 50 active entries)
@@ -133,17 +118,16 @@ Rules:
133
118
 
134
119
  ### Search \`<query>\`
135
120
  - Stream \`${KNOWLEDGE_PATH}\`, JSON.parse each line, filter where any of
136
- \`trigger\`, \`action\`, \`domain\`, \`project\` contains \`<query>\` (case-insensitive).
121
+ \`trigger\`, \`action\`, \`project\` contains \`<query>\` (case-insensitive).
137
122
  - Return the matched lines pretty-printed (do not mutate the file).
138
123
 
139
124
  ### Add
140
- - Ask for required user-facing fields in order: \`type\`, \`trigger\`, \`action\`, \`confidence\`, \`domain\`, \`stage\`, \`universality\`, \`project\`.
125
+ - Ask for required user-facing fields in order: \`type\`, \`trigger\`, \`action\`, \`confidence\`, \`stage\`, \`project\`.
141
126
  - \`confidence\` must be one of \`high\`, \`medium\`, \`low\`. Default to \`medium\` if the user declines to set it.
142
- - \`domain\`, \`stage\`, and \`project\` may be explicitly \`null\`.
127
+ - \`stage\` and \`project\` may be explicitly \`null\`.
143
128
  - Prefer stage-native \`## Learnings\` capture for new flow work; use \`add\` mainly for backfilling historical lessons or ad-hoc entries outside a stage closeout.
144
- - \`origin_stage\` defaults to \`stage\`; \`origin_run\` defaults to the current run, branch, or topic label (or \`null\` if unknown).
129
+ - \`origin_stage\` defaults to \`stage\`.
145
130
  - \`frequency\` starts at \`1\`.
146
- - \`maturity\` starts at \`raw\`.
147
131
  - \`created\`, \`first_seen_ts\`, and \`last_seen_ts\` are set automatically to current UTC ISO timestamp.
148
132
  - Append exactly one JSON line to \`${KNOWLEDGE_PATH}\` with the field order from the schema table above.
149
133
  - Re-read the file tail to confirm the new line is valid JSON and parses back to the same object.
@@ -13,7 +13,7 @@ function generatedHelperSkillList() {
13
13
  export function usingCclawSkillMarkdown() {
14
14
  return `---
15
15
  name: using-cclaw
16
- description: "Routing brain for cclaw. Decide whether to start/resume a stage, answer directly, or use visible commands like /cc, /cc-ideate, and /cc-cancel."
16
+ description: "Routing brain for cclaw. Decide whether to start/resume a stage, answer directly, or use visible commands like /cc, /cc-idea, and /cc-cancel."
17
17
  ---
18
18
 
19
19
  # Using Cclaw
@@ -64,7 +64,7 @@ Task arrives
64
64
  ├─ Running as spawned subagent? -> obey parent prompt only; do not run cclaw routing
65
65
  ├─ Pure question / non-software ask? -> answer directly (no stage)
66
66
  ├─ New software work? -> /cc <idea>
67
- ├─ Repo-improvement discovery? -> /cc-ideate
67
+ ├─ Repo-improvement discovery? -> /cc-idea
68
68
  ├─ Resume existing flow? -> /cc
69
69
  ├─ Knowledge operation? -> load the learnings skill
70
70
  ├─ Normal post-ship closeout? -> /cc drives ${closeoutChainInline()}
@@ -92,18 +92,18 @@ Before stage work:
92
92
  ## Platform reliability notes
93
93
 
94
94
  - Managed hook dispatch uses \`.cclaw/hooks/run-hook.cmd\` (cross-platform wrapper).
95
- - If hooks fail due missing runtime deps (for example \`node\` not on \`PATH\`), run \`npx cclaw-cli doctor\` before continuing.
95
+ - If hooks fail due missing runtime deps (for example \`node\` not on \`PATH\`), run \`npx cclaw-cli sync\` before continuing.
96
96
  - Prefer cross-platform commands in artifacts/examples (\`npm test\`, \`pnpm test\`, \`python -m pytest\`, etc.) over shell-specific aliases whenever possible.
97
97
 
98
98
  ## Stage quick map
99
99
 
100
- Use \`/cc <idea>\` for new work, \`/cc\` for progression and closeout, \`/cc-ideate\` for backlog discovery, and \`/cc-cancel\` for cancellation/abandonment.
100
+ Use \`/cc <idea>\` for new work, \`/cc\` for progression and closeout, \`/cc-idea\` for backlog discovery, and \`/cc-cancel\` for cancellation/abandonment.
101
101
 
102
102
  ## Main vs Operator Surfaces
103
103
 
104
- - **Main workflow:** \`/cc\`, \`/cc-ideate\`, and \`/cc-cancel\` inside the installed harness runtime.
105
- - **Installer/support surface:** \`npx cclaw-cli init\`, \`npx cclaw-cli sync\`, \`npx cclaw-cli upgrade\`, \`npx cclaw-cli doctor\`, and explicit support/archive actions. Do not ask users to install or run a \`cclaw\` binary during normal stage flow.
106
- - Use operator/support surfaces only for install/runtime diagnosis, explicit archival, or deeper inspection. Do not make them part of the happy path.
104
+ - **Main workflow:** \`/cc\`, \`/cc-idea\`, and \`/cc-cancel\` inside the installed harness runtime.
105
+ - **Installer/support surface:** \`npx cclaw-cli init\`, \`npx cclaw-cli sync\`, \`npx cclaw-cli upgrade\`, \`npx cclaw-cli sync\`, and \`npx cclaw-cli uninstall\`.
106
+ - Use operator/support surfaces only for install/runtime diagnosis or lifecycle maintenance. Do not make them part of the happy path.
107
107
 
108
108
  ## Whole flow map
109
109
 
@@ -15,6 +15,16 @@ export interface NodeHookRuntimeOptions {
15
15
  * `cclaw sync` after changing the config value so hook and CLI agree.
16
16
  */
17
17
  compoundRecurrenceThreshold?: number;
18
+ /**
19
+ * Enables early-stage producer/critic loop diagnostics in session-start.
20
+ * Defaults to true.
21
+ */
22
+ earlyLoopEnabled?: boolean;
23
+ /**
24
+ * Baked-in max iterations for brainstorm/scope/design early-loop status.
25
+ * Derived from `config.earlyLoop.maxIterations`.
26
+ */
27
+ earlyLoopMaxIterations?: number;
18
28
  }
19
29
  /**
20
30
  * Node-only hook runtime (single entrypoint).