cclaw-cli 0.51.30 → 0.55.2

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 (142) hide show
  1. package/README.md +22 -16
  2. package/dist/artifact-linter/brainstorm.d.ts +2 -0
  3. package/dist/artifact-linter/brainstorm.js +245 -0
  4. package/dist/artifact-linter/design.d.ts +2 -0
  5. package/dist/artifact-linter/design.js +323 -0
  6. package/dist/artifact-linter/plan.d.ts +2 -0
  7. package/dist/artifact-linter/plan.js +162 -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 +65 -0
  12. package/dist/artifact-linter/scope.d.ts +2 -0
  13. package/dist/artifact-linter/scope.js +115 -0
  14. package/dist/artifact-linter/shared.d.ts +246 -0
  15. package/dist/artifact-linter/shared.js +1488 -0
  16. package/dist/artifact-linter/ship.d.ts +2 -0
  17. package/dist/artifact-linter/ship.js +46 -0
  18. package/dist/artifact-linter/spec.d.ts +2 -0
  19. package/dist/artifact-linter/spec.js +108 -0
  20. package/dist/artifact-linter/tdd.d.ts +2 -0
  21. package/dist/artifact-linter/tdd.js +124 -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 +9 -15
  32. package/dist/content/cancel-command.js +2 -2
  33. package/dist/content/closeout-guidance.js +10 -7
  34. package/dist/content/core-agents.d.ts +18 -0
  35. package/dist/content/core-agents.js +46 -2
  36. package/dist/content/decision-protocol.d.ts +1 -1
  37. package/dist/content/decision-protocol.js +1 -1
  38. package/dist/content/examples.js +6 -6
  39. package/dist/content/harness-doc.js +20 -2
  40. package/dist/content/hook-inline-snippets.d.ts +17 -4
  41. package/dist/content/hook-inline-snippets.js +218 -5
  42. package/dist/content/hook-manifest.d.ts +2 -2
  43. package/dist/content/hook-manifest.js +2 -2
  44. package/dist/content/hooks.d.ts +1 -0
  45. package/dist/content/hooks.js +32 -137
  46. package/dist/content/idea-command.d.ts +8 -0
  47. package/dist/content/{ideate-command.js → idea-command.js} +57 -50
  48. package/dist/content/idea-frames.d.ts +31 -0
  49. package/dist/content/{ideate-frames.js → idea-frames.js} +9 -9
  50. package/dist/content/idea-ranking.d.ts +25 -0
  51. package/dist/content/{ideate-ranking.js → idea-ranking.js} +5 -5
  52. package/dist/content/iron-laws.d.ts +0 -1
  53. package/dist/content/iron-laws.js +31 -16
  54. package/dist/content/learnings.js +1 -1
  55. package/dist/content/meta-skill.js +7 -7
  56. package/dist/content/node-hooks.d.ts +10 -0
  57. package/dist/content/node-hooks.js +43 -9
  58. package/dist/content/opencode-plugin.js +3 -3
  59. package/dist/content/skills.js +19 -7
  60. package/dist/content/stage-schema.js +44 -2
  61. package/dist/content/stages/_lint-metadata/index.js +26 -2
  62. package/dist/content/stages/brainstorm.js +13 -7
  63. package/dist/content/stages/design.js +16 -11
  64. package/dist/content/stages/plan.js +7 -4
  65. package/dist/content/stages/review.js +4 -4
  66. package/dist/content/stages/schema-types.d.ts +1 -1
  67. package/dist/content/stages/scope.js +15 -12
  68. package/dist/content/stages/ship.js +2 -2
  69. package/dist/content/stages/spec.js +9 -3
  70. package/dist/content/stages/tdd.js +14 -4
  71. package/dist/content/start-command.js +11 -10
  72. package/dist/content/status-command.js +3 -3
  73. package/dist/content/subagents.js +60 -6
  74. package/dist/content/templates.d.ts +1 -1
  75. package/dist/content/templates.js +102 -150
  76. package/dist/content/tree-command.js +2 -2
  77. package/dist/content/utility-skills.d.ts +2 -2
  78. package/dist/content/utility-skills.js +2 -2
  79. package/dist/content/view-command.js +4 -2
  80. package/dist/delegation.d.ts +2 -0
  81. package/dist/delegation.js +2 -1
  82. package/dist/early-loop.d.ts +66 -0
  83. package/dist/early-loop.js +275 -0
  84. package/dist/gate-evidence.d.ts +8 -0
  85. package/dist/gate-evidence.js +141 -5
  86. package/dist/harness-adapters.d.ts +2 -2
  87. package/dist/harness-adapters.js +47 -18
  88. package/dist/install.js +153 -29
  89. package/dist/internal/advance-stage/advance.d.ts +50 -0
  90. package/dist/internal/advance-stage/advance.js +480 -0
  91. package/dist/internal/advance-stage/cancel-run.d.ts +8 -0
  92. package/dist/internal/advance-stage/cancel-run.js +19 -0
  93. package/dist/internal/advance-stage/flow-state-coercion.d.ts +3 -0
  94. package/dist/internal/advance-stage/flow-state-coercion.js +81 -0
  95. package/dist/internal/advance-stage/helpers.d.ts +14 -0
  96. package/dist/internal/advance-stage/helpers.js +145 -0
  97. package/dist/internal/advance-stage/hook.d.ts +8 -0
  98. package/dist/internal/advance-stage/hook.js +40 -0
  99. package/dist/internal/advance-stage/parsers.d.ts +54 -0
  100. package/dist/internal/advance-stage/parsers.js +307 -0
  101. package/dist/internal/advance-stage/review-loop.d.ts +7 -0
  102. package/dist/internal/advance-stage/review-loop.js +170 -0
  103. package/dist/internal/advance-stage/rewind.d.ts +14 -0
  104. package/dist/internal/advance-stage/rewind.js +108 -0
  105. package/dist/internal/advance-stage/start-flow.d.ts +11 -0
  106. package/dist/internal/advance-stage/start-flow.js +136 -0
  107. package/dist/internal/advance-stage/verify.d.ts +29 -0
  108. package/dist/internal/advance-stage/verify.js +225 -0
  109. package/dist/internal/advance-stage.js +21 -1470
  110. package/dist/internal/compound-readiness.d.ts +1 -1
  111. package/dist/internal/compound-readiness.js +2 -2
  112. package/dist/internal/early-loop-status.d.ts +7 -0
  113. package/dist/internal/early-loop-status.js +90 -0
  114. package/dist/internal/runtime-integrity.d.ts +7 -0
  115. package/dist/internal/runtime-integrity.js +288 -0
  116. package/dist/internal/tdd-red-evidence.js +1 -1
  117. package/dist/knowledge-store.d.ts +3 -8
  118. package/dist/knowledge-store.js +16 -29
  119. package/dist/managed-resources.js +24 -2
  120. package/dist/policy.js +4 -6
  121. package/dist/run-archive.d.ts +1 -1
  122. package/dist/run-archive.js +12 -12
  123. package/dist/run-persistence.js +111 -11
  124. package/dist/tdd-cycle.d.ts +3 -3
  125. package/dist/tdd-cycle.js +1 -1
  126. package/dist/types.d.ts +18 -10
  127. package/package.json +1 -1
  128. package/dist/content/ideate-command.d.ts +0 -8
  129. package/dist/content/ideate-frames.d.ts +0 -31
  130. package/dist/content/ideate-ranking.d.ts +0 -25
  131. package/dist/content/next-command.d.ts +0 -20
  132. package/dist/content/next-command.js +0 -298
  133. package/dist/content/seed-shelf.d.ts +0 -36
  134. package/dist/content/seed-shelf.js +0 -301
  135. package/dist/content/stage-common-guidance.d.ts +0 -1
  136. package/dist/content/stage-common-guidance.js +0 -106
  137. package/dist/doctor-registry.d.ts +0 -10
  138. package/dist/doctor-registry.js +0 -186
  139. package/dist/doctor.d.ts +0 -17
  140. package/dist/doctor.js +0 -2201
  141. package/dist/internal/hook-manifest.d.ts +0 -16
  142. package/dist/internal/hook-manifest.js +0 -77
@@ -26,7 +26,7 @@ function resolveCliRuntimeForGeneratedHook() {
26
26
  }
27
27
  return { entrypoint: null, argsPrefix: [] };
28
28
  }
29
- function internalHelperScript(helperName, internalSubcommand, usage) {
29
+ function internalHelperScript(helperName, internalSubcommand, usage, options) {
30
30
  const cliRuntime = resolveCliRuntimeForGeneratedHook();
31
31
  return `#!/usr/bin/env node
32
32
  import fs from "node:fs/promises";
@@ -40,6 +40,8 @@ const CCLAW_CLI_ARGS_PREFIX = ${JSON.stringify(cliRuntime.argsPrefix)};
40
40
  const HELPER_NAME = ${JSON.stringify(helperName)};
41
41
  const INTERNAL_SUBCOMMAND = ${JSON.stringify(internalSubcommand)};
42
42
  const USAGE = ${JSON.stringify(usage)};
43
+ const POSITIONAL_ARG_NAME = ${JSON.stringify(options?.positionalArgName ?? null)};
44
+ const POSITIONAL_ARG_REQUIRED = ${JSON.stringify(options?.positionalArgRequired === true)};
43
45
 
44
46
  async function detectRoot() {
45
47
  const candidates = [
@@ -69,11 +71,22 @@ function printUsage() {
69
71
  }
70
72
 
71
73
  async function main() {
72
- const [, , ...flags] = process.argv;
73
- if (flags.includes("--help") || flags.includes("-h")) {
74
+ const [, , ...argvTokens] = process.argv;
75
+ if (argvTokens.includes("--help") || argvTokens.includes("-h")) {
74
76
  printUsage();
75
77
  return;
76
78
  }
79
+ let positionalArg = "";
80
+ let flags = argvTokens;
81
+ if (POSITIONAL_ARG_NAME !== null) {
82
+ positionalArg = (argvTokens[0] ?? "").trim();
83
+ flags = argvTokens.slice(1);
84
+ if (POSITIONAL_ARG_REQUIRED && positionalArg.length === 0) {
85
+ printUsage();
86
+ process.exitCode = 1;
87
+ return;
88
+ }
89
+ }
77
90
 
78
91
  const root = await detectRoot();
79
92
  const runtimePath = path.join(root, RUNTIME_ROOT);
@@ -112,7 +125,12 @@ async function main() {
112
125
  return;
113
126
  }
114
127
 
115
- const child = spawn(process.execPath, [cliEntrypoint, ...cliArgsPrefix, "internal", INTERNAL_SUBCOMMAND, ...flags], {
128
+ const internalArgs =
129
+ POSITIONAL_ARG_NAME !== null
130
+ ? [INTERNAL_SUBCOMMAND, positionalArg, ...flags]
131
+ : [INTERNAL_SUBCOMMAND, ...flags];
132
+
133
+ const child = spawn(process.execPath, [cliEntrypoint, ...cliArgsPrefix, "internal", ...internalArgs], {
116
134
  cwd: root,
117
135
  env: process.env,
118
136
  stdio: "inherit"
@@ -124,7 +142,7 @@ async function main() {
124
142
  const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
125
143
  if (code === "ENOENT") {
126
144
  process.stderr.write(
127
- "[cclaw] " + HELPER_NAME + ": node executable not found while invoking local runtime. Re-run npx cclaw-cli doctor.\\n"
145
+ "[cclaw] " + HELPER_NAME + ": node executable not found while invoking local runtime. Re-run npx cclaw-cli sync.\\n"
128
146
  );
129
147
  } else {
130
148
  process.stderr.write(
@@ -155,137 +173,14 @@ void main();
155
173
  export function startFlowScript() {
156
174
  return internalHelperScript("start-flow", "start-flow", "Usage: node " + RUNTIME_ROOT + "/hooks/start-flow.mjs --track=<standard|medium|quick> [--class=...] [--prompt=...] [--stack=...] [--reason=...] [--reclassify] [--force-reset]");
157
175
  }
158
- export function stageCompleteScript() {
159
- const cliRuntime = resolveCliRuntimeForGeneratedHook();
160
- return `#!/usr/bin/env node
161
- import fs from "node:fs/promises";
162
- import path from "node:path";
163
- import process from "node:process";
164
- import { spawn } from "node:child_process";
165
-
166
- const RUNTIME_ROOT = ${JSON.stringify(RUNTIME_ROOT)};
167
- const CCLAW_CLI_ENTRYPOINT = ${JSON.stringify(cliRuntime.entrypoint)};
168
- const CCLAW_CLI_ARGS_PREFIX = ${JSON.stringify(cliRuntime.argsPrefix)};
169
-
170
- async function detectRoot() {
171
- const candidates = [
172
- process.env.CCLAW_PROJECT_ROOT,
173
- process.env.CLAUDE_PROJECT_DIR,
174
- process.env.CURSOR_PROJECT_DIR,
175
- process.env.CURSOR_PROJECT_ROOT,
176
- process.env.OPENCODE_PROJECT_DIR,
177
- process.env.OPENCODE_PROJECT_ROOT,
178
- process.cwd()
179
- ].filter((value) => typeof value === "string" && value.length > 0);
180
-
181
- for (const candidate of candidates) {
182
- try {
183
- const runtimePath = path.join(candidate, RUNTIME_ROOT);
184
- const stat = await fs.stat(runtimePath);
185
- if (stat.isDirectory()) return candidate;
186
- } catch {
187
- // continue
188
- }
189
- }
190
- return candidates[0] || process.cwd();
176
+ export function cancelRunScript() {
177
+ return internalHelperScript("cancel-run", "cancel-run", "Usage: node " + RUNTIME_ROOT + "/hooks/cancel-run.mjs --reason=<text> [--disposition=<cancelled|abandoned>] [--name=<slug>]");
191
178
  }
192
-
193
- function printUsage() {
194
- process.stderr.write(
195
- "Usage: node " +
196
- RUNTIME_ROOT +
197
- "/hooks/stage-complete.mjs <stage> [--passed=...] [--evidence-json=...] [--waive-delegation=...] [--waiver-reason=...] [--json]\\n"
198
- );
199
- }
200
-
201
- async function main() {
202
- const [, , stage, ...flags] = process.argv;
203
- if (!stage || stage.trim().length === 0) {
204
- printUsage();
205
- process.exitCode = 1;
206
- return;
207
- }
208
-
209
- const root = await detectRoot();
210
- const runtimePath = path.join(root, RUNTIME_ROOT);
211
- try {
212
- const stat = await fs.stat(runtimePath);
213
- if (!stat.isDirectory()) throw new Error("not-dir");
214
- } catch {
215
- process.stderr.write("[cclaw] stage-complete: runtime root not found at " + runtimePath + "\\n");
216
- process.exitCode = 1;
217
- return;
218
- }
219
-
220
- const cliEntrypoint = process.env.CCLAW_CLI_JS || CCLAW_CLI_ENTRYPOINT;
221
- const cliArgsPrefix = process.env.CCLAW_CLI_JS ? [] : CCLAW_CLI_ARGS_PREFIX;
222
- if (!cliEntrypoint || cliEntrypoint.trim().length === 0) {
223
- process.stderr.write(
224
- "[cclaw] stage-complete: local Node runtime entrypoint is missing. Re-run npx cclaw-cli sync, or set CCLAW_CLI_JS=/absolute/path/to/dist/cli.js for this session.\\n"
225
- );
226
- process.exitCode = 1;
227
- return;
228
- }
229
-
230
- try {
231
- const stat = await fs.stat(cliEntrypoint);
232
- if (!stat.isFile()) throw new Error("not-file");
233
- for (const argPath of cliArgsPrefix) {
234
- if (typeof argPath !== "string" || argPath.startsWith("-")) continue;
235
- const argStat = await fs.stat(argPath);
236
- if (!argStat.isFile()) throw new Error("arg-not-file");
237
- }
238
- } catch {
239
- process.stderr.write(
240
- "[cclaw] stage-complete: local Node runtime entrypoint not found at " + cliEntrypoint + ". Re-run npx cclaw-cli sync, or set CCLAW_CLI_JS=/absolute/path/to/dist/cli.js for this session.\\n"
241
- );
242
- process.exitCode = 1;
243
- return;
244
- }
245
-
246
- const child = spawn(
247
- process.execPath,
248
- [cliEntrypoint, ...cliArgsPrefix, "internal", "advance-stage", stage, ...flags],
249
- {
250
- cwd: root,
251
- env: process.env,
252
- stdio: "inherit"
253
- }
254
- );
255
- let spawnErrored = false;
256
-
257
- child.on("error", (error) => {
258
- spawnErrored = true;
259
- const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
260
- if (code === "ENOENT") {
261
- process.stderr.write(
262
- "[cclaw] stage-complete: node executable not found while invoking local runtime. Re-run npx cclaw-cli doctor.\\n"
263
- );
264
- } else {
265
- process.stderr.write(
266
- "[cclaw] stage-complete: failed to invoke local Node advance-stage runtime (" +
267
- (error instanceof Error ? error.message : String(error)) +
268
- ").\\n"
269
- );
270
- }
271
- process.exitCode = 1;
272
- });
273
-
274
- child.on("close", (code, signal) => {
275
- if (spawnErrored) {
276
- process.exitCode = 1;
277
- return;
278
- }
279
- if (signal) {
280
- process.exitCode = 1;
281
- return;
282
- }
283
- process.exitCode = typeof code === "number" && code >= 0 ? code : 1;
284
- });
285
- }
286
-
287
- void main();
288
- `;
179
+ export function stageCompleteScript() {
180
+ return internalHelperScript("stage-complete", "advance-stage", "Usage: node " + RUNTIME_ROOT + "/hooks/stage-complete.mjs <stage> [--passed=...] [--evidence-json=...] [--waive-delegation=...] [--waiver-reason=...] [--accept-proactive-waiver] [--accept-proactive-waiver-reason=...] [--json]", {
181
+ positionalArgName: "stage",
182
+ positionalArgRequired: true
183
+ });
289
184
  }
290
185
  export function delegationRecordScript() {
291
186
  return `#!/usr/bin/env node
@@ -669,7 +564,7 @@ set "RUNTIME=%HOOK_DIR%run-hook.mjs"
669
564
  where node >nul 2>nul
670
565
  if %ERRORLEVEL% neq 0 (
671
566
  REM Best-effort: missing node should not block harness execution loops.
672
- echo [cclaw] run-hook.cmd: node not found; cclaw hook skipped. Run npx cclaw-cli doctor. >&2
567
+ echo [cclaw] run-hook.cmd: node not found; cclaw hook skipped. Run npx cclaw-cli sync. >&2
673
568
  exit /b 0
674
569
  )
675
570
  node "%RUNTIME%" %*
@@ -681,7 +576,7 @@ if [ "$#" -lt 1 ]; then
681
576
  exit 1
682
577
  fi
683
578
  if ! command -v node >/dev/null 2>&1; then
684
- echo "[cclaw] run-hook.cmd: node not found; cclaw hook skipped. Run npx cclaw-cli doctor." >&2
579
+ echo "[cclaw] run-hook.cmd: node not found; cclaw hook skipped. Run npx cclaw-cli sync." >&2
685
580
  exit 0
686
581
  fi
687
582
  exec node "\${SCRIPT_DIR}/run-hook.mjs" "$@"
@@ -0,0 +1,8 @@
1
+ import { type IdeaFrameId } from "./idea-frames.js";
2
+ export interface IdeaCommandOptions {
3
+ frameIds?: readonly IdeaFrameId[];
4
+ mode?: "repo-grounded" | "elsewhere-software" | "elsewhere-non-software" | "narrow";
5
+ }
6
+ export declare function minimumDistinctIdeaFrames(frameCount: number, mode?: IdeaCommandOptions["mode"]): number;
7
+ export declare function ideaCommandContract(options?: IdeaCommandOptions): string;
8
+ export declare function ideaCommandSkillMarkdown(options?: IdeaCommandOptions): string;
@@ -1,43 +1,43 @@
1
1
  import { RUNTIME_ROOT } from "../constants.js";
2
- import { resolveIdeateFrames } from "./ideate-frames.js";
3
- import { ideateStructuredAskToolsWithFallback } from "./decision-protocol.js";
2
+ import { resolveIdeaFrames } from "./idea-frames.js";
3
+ import { ideaStructuredAskToolsWithFallback } from "./decision-protocol.js";
4
4
  import { conversationLanguagePolicyMarkdown } from "./language-policy.js";
5
- const IDEATE_SKILL_FOLDER = "flow-ideate";
6
- const IDEATE_SKILL_NAME = "flow-ideate";
5
+ const IDEA_SKILL_FOLDER = "flow-idea";
6
+ const IDEA_SKILL_NAME = "flow-idea";
7
7
  /**
8
- * Directory + filename convention for ideate artifacts. These are separate
9
- * from stage artifacts (00-..08-*.md) because `/cc-ideate` runs outside the
8
+ * Directory + filename convention for idea artifacts. These are separate
9
+ * from stage artifacts (00-..08-*.md) because `/cc-idea` runs outside the
10
10
  * critical-path flow state machine and must not collide with stage numbering.
11
11
  */
12
- const IDEATE_ARTIFACT_GLOB = ".cclaw/artifacts/ideate-*.md";
13
- const IDEATE_ARTIFACT_PATTERN = ".cclaw/artifacts/ideate-<YYYY-MM-DD-slug>.md";
14
- const IDEATE_RESUME_WINDOW_DAYS = 30;
15
- const STRUCTURED_ASK_TOOLS = ideateStructuredAskToolsWithFallback();
16
- export function minimumDistinctIdeateFrames(frameCount, mode = "repo-grounded") {
12
+ const IDEA_ARTIFACT_GLOB = ".cclaw/artifacts/idea-*.md";
13
+ const IDEA_ARTIFACT_PATTERN = ".cclaw/artifacts/idea-<YYYY-MM-DD-slug>.md";
14
+ const IDEA_RESUME_WINDOW_DAYS = 30;
15
+ const STRUCTURED_ASK_TOOLS = ideaStructuredAskToolsWithFallback();
16
+ export function minimumDistinctIdeaFrames(frameCount, mode = "repo-grounded") {
17
17
  if (frameCount <= 0)
18
18
  return 0;
19
19
  const cap = mode === "repo-grounded" ? 4 : 2;
20
20
  return Math.min(cap, frameCount);
21
21
  }
22
22
  function renderFrameBullets(frameIds) {
23
- return resolveIdeateFrames(frameIds)
23
+ return resolveIdeaFrames(frameIds)
24
24
  .map((frame) => ` - ${frame.label} (\`${frame.id}\`)`)
25
25
  .join("\n");
26
26
  }
27
27
  function renderFrameNames(frameIds) {
28
- return resolveIdeateFrames(frameIds)
28
+ return resolveIdeaFrames(frameIds)
29
29
  .map((frame) => frame.label)
30
30
  .join(", ");
31
31
  }
32
- export function ideateCommandContract(options = {}) {
33
- const frames = resolveIdeateFrames(options.frameIds);
32
+ export function ideaCommandContract(options = {}) {
33
+ const frames = resolveIdeaFrames(options.frameIds);
34
34
  const frameBullets = renderFrameBullets(options.frameIds);
35
- const minimumDistinctFrames = minimumDistinctIdeateFrames(frames.length, options.mode);
36
- return `# /cc-ideate
35
+ const minimumDistinctFrames = minimumDistinctIdeaFrames(frames.length, options.mode);
36
+ return `# /cc-idea
37
37
 
38
38
  ## Purpose
39
39
 
40
- Repository-improvement ideate mode. Generate a ranked backlog of
40
+ Repository-improvement idea mode. Generate a ranked backlog of
41
41
  high-value improvements, persist it as an artifact on disk, and end with
42
42
  an explicit handoff — either launch \`/cc\` on a chosen candidate in the
43
43
  same session, or save/discard the backlog.
@@ -45,18 +45,20 @@ same session, or save/discard the backlog.
45
45
  ## HARD-GATE
46
46
 
47
47
  ${conversationLanguagePolicyMarkdown()}
48
- - Ideate mode only. Never mutate \`.cclaw/state/flow-state.json\`.
48
+ - Idea mode only. Never mutate \`.cclaw/state/flow-state.json\`.
49
49
  - Every recommendation cites evidence from the current repository
50
50
  (file path, command output, or knowledge-store entry id).
51
- - Always write a persisted artifact to
52
- \`${IDEATE_ARTIFACT_PATTERN}\`. Chat-only output is not acceptable
53
- the next session must be able to resume.
54
- - Always end with a structured handoff prompt, not an open question.
51
+ - Whenever you produce ideation output, persist it to
52
+ \`${IDEA_ARTIFACT_PATTERN}\`. Chat-only output is not acceptable.
53
+ The only exception is an explicit user-cancel from the resume prompt —
54
+ in that case, write nothing and exit silently.
55
+ - Always end with a structured handoff prompt, not an open question
56
+ (skipped on explicit cancel).
55
57
 
56
58
  ## Algorithm
57
59
 
58
- 1. **Resume check.** Glob \`${IDEATE_ARTIFACT_GLOB}\`. If any artifact
59
- has been modified within the last ${IDEATE_RESUME_WINDOW_DAYS} days,
60
+ 1. **Resume check.** Glob \`${IDEA_ARTIFACT_GLOB}\`. If any artifact
61
+ has been modified within the last ${IDEA_RESUME_WINDOW_DAYS} days,
60
62
  offer the user: continue that backlog, start fresh, or cancel.
61
63
  2. **Mode classification.** Explicitly classify subject:
62
64
  \`repo-grounded\` / \`elsewhere-software\` / \`elsewhere-non-software\` / \`narrow\`.
@@ -83,7 +85,7 @@ ${frameBullets}
83
85
  \`(impact points / effort cost) * confidence multiplier\` and recommend
84
86
  the top survivor.
85
87
  8. **Write the artifact** at
86
- \`${IDEATE_ARTIFACT_PATTERN}\` using the schema in the skill.
88
+ \`${IDEA_ARTIFACT_PATTERN}\` using the schema in the skill.
87
89
  8.5 **Seed shelf (optional).** For critiqued-out or deferred ideas that still
88
90
  show upside, write seed notes to
89
91
  \`${RUNTIME_ROOT}/seeds/SEED-<YYYY-MM-DD>-<slug>.md\` with
@@ -91,61 +93,66 @@ ${frameBullets}
91
93
  9. **Present the handoff prompt** with four concrete options — not A/B/C
92
94
  letters. Default = "Start /cc on the top recommendation".
93
95
 
94
- ## Headless mode
96
+ ## Headless mode (CI/automation only)
95
97
 
98
+ Headless envelopes are a machine-mode exception for CI/automation orchestration.
99
+ In normal interactive ideation, respond with natural language plus the artifact path.
96
100
  For skill-to-skill invocation, emit exactly one JSON envelope:
97
101
 
98
102
  \`\`\`json
99
- {"version":"1","kind":"stage-output","stage":"non-flow","payload":{"command":"/cc-ideate","artifact":".cclaw/artifacts/ideate-<date>-<slug>.md","recommendation":"I-1"},"emittedAt":"<ISO-8601>"}
103
+ {"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>"}
100
104
  \`\`\`
101
105
 
102
106
  Validate envelopes with:
103
- \`cclaw internal envelope-validate --stdin\`
107
+ \`npx cclaw-cli internal envelope-validate --stdin\`
104
108
 
105
109
  ## Primary skill
106
110
 
107
- **${RUNTIME_ROOT}/skills/${IDEATE_SKILL_FOLDER}/SKILL.md**
111
+ **${RUNTIME_ROOT}/skills/${IDEA_SKILL_FOLDER}/SKILL.md**
108
112
  `;
109
113
  }
110
- export function ideateCommandSkillMarkdown(options = {}) {
111
- const frames = resolveIdeateFrames(options.frameIds);
114
+ export function ideaCommandSkillMarkdown(options = {}) {
115
+ const frames = resolveIdeaFrames(options.frameIds);
112
116
  const frameBullets = renderFrameBullets(options.frameIds);
113
- const minimumDistinctFrames = minimumDistinctIdeateFrames(frames.length, options.mode);
117
+ const minimumDistinctFrames = minimumDistinctIdeaFrames(frames.length, options.mode);
114
118
  const frameNames = renderFrameNames(options.frameIds);
115
119
  return `---
116
- name: ${IDEATE_SKILL_NAME}
117
- description: "Repository ideate mode: detect and rank high-leverage improvements, persist a backlog artifact, and hand off to /cc or save/discard."
120
+ name: ${IDEA_SKILL_NAME}
121
+ description: "Repository idea mode: detect and rank high-leverage improvements, persist a backlog artifact, and hand off to /cc or save/discard."
118
122
  ---
119
123
 
120
- # /cc-ideate
124
+ # /cc-idea
121
125
 
122
126
  ## Announce at start
123
127
 
124
- "Using flow-ideate to identify highest-leverage improvements in this
128
+ "Using flow-idea to identify highest-leverage improvements in this
125
129
  repository. Will persist a ranked backlog to
126
- \`${IDEATE_ARTIFACT_PATTERN}\` and end with an explicit handoff."
130
+ \`${IDEA_ARTIFACT_PATTERN}\` and end with an explicit handoff."
127
131
 
128
132
  ## HARD-GATE
129
133
 
130
134
  ${conversationLanguagePolicyMarkdown()}
131
- - Do not start coding in ideate mode.
132
- - Do not mutate \`.cclaw/state/flow-state.json\` — ideate mode sits outside
135
+ - Do not start coding in idea mode.
136
+ - Do not mutate \`.cclaw/state/flow-state.json\` — idea mode sits outside
133
137
  the critical-path flow.
134
- - Always produce the artifact file on disk before presenting the handoff.
138
+ - Whenever ideation output is produced, persist the artifact file on disk
139
+ before presenting the handoff. The only exception is an explicit user-cancel
140
+ from the resume prompt — in that case, write nothing and exit silently.
135
141
  - Always end with a structured handoff that names the concrete follow-up
136
- command for each option. No A/B/C letters without command context.
142
+ command for each option (skipped on explicit cancel). No A/B/C letters
143
+ without command context.
137
144
 
138
145
  ## Protocol
139
146
 
140
147
  ### Phase 0 — Resume and classify
141
148
 
142
149
  1. Use the harness's file-glob tool (\`Glob\` pattern
143
- \`${IDEATE_ARTIFACT_GLOB}\` or equivalent \`ls\`/\`find\`).
144
- 2. Filter to files modified within the last ${IDEATE_RESUME_WINDOW_DAYS} days.
150
+ \`${IDEA_ARTIFACT_GLOB}\` or equivalent \`ls\`/\`find\`).
151
+ 2. Filter to files modified within the last ${IDEA_RESUME_WINDOW_DAYS} days.
145
152
  3. If one or more match, present **one** structured ask using the
146
153
  harness's native tool (${STRUCTURED_ASK_TOOLS}) with options:
147
154
  - **Continue the existing backlog** — read the most-recent
148
- ideate-*.md and work from its candidate list; skip re-scanning.
155
+ idea-*.md and work from its candidate list; skip re-scanning.
149
156
  - **Start a fresh scan** — proceed to Phase 1; the old artifact stays
150
157
  on disk for history.
151
158
  - **Cancel** — stop; do not scan or write anything.
@@ -218,10 +225,10 @@ Only survivors advance to ranking.
218
225
  and break ties with rationale strength.
219
226
  4. Compute the artifact filename:
220
227
  - \`slug\` = first 3–5 words of the top recommendation, lowercase,
221
- non-alphanumeric collapsed to \`-\`, trimmed. When ideate mode is
228
+ non-alphanumeric collapsed to \`-\`, trimmed. When idea mode is
222
229
  focus-hinted (user passed an argument), use the focus hint instead.
223
230
  - \`date\` = today in \`YYYY-MM-DD\` (local time).
224
- - Path = \`.cclaw/artifacts/ideate-<date>-<slug>.md\`.
231
+ - Path = \`.cclaw/artifacts/idea-<date>-<slug>.md\`.
225
232
  5. Use the harness's write-file tool (\`Write\`, \`apply_patch\`, or shell
226
233
  \`cat <<EOF > path\`) to create the artifact with this schema:
227
234
 
@@ -269,7 +276,7 @@ Only survivors advance to ranking.
269
276
  6. Optional: for promising non-selected ideas, write
270
277
  \`${RUNTIME_ROOT}/seeds/SEED-<YYYY-MM-DD>-<slug>.md\` entries with:
271
278
  \`title\`, \`trigger_when\`, \`hypothesis\`, \`action\`, and
272
- \`source_artifact\` = ideate artifact path.
279
+ \`source_artifact\` = idea artifact path.
273
280
  7. Confirm in chat: "Wrote <path>."
274
281
 
275
282
  ### Phase 5 — Handoff prompt
@@ -286,7 +293,7 @@ Required options, in this order:
286
293
  2. **Pick a different candidate** — the agent asks which ID (I-2, I-3, …)
287
294
  and then invokes \`/cc <that candidate's handoff phrase>\`.
288
295
  3. **Save and close** — leave the artifact on disk, do nothing else.
289
- Next session: \`/cc-ideate\` will offer to resume it.
296
+ Next session: \`/cc-idea\` will offer to resume it.
290
297
  4. **Discard** — delete the just-written artifact. Use only when the
291
298
  scan produced nothing actionable.
292
299
 
@@ -298,7 +305,7 @@ lettered list with the same four labels. Do not invent extra options.
298
305
  - **Start /cc on I-1** or **different candidate:** announce
299
306
  "Handing off to /cc <phrase>" and load the \`using-cclaw\` router
300
307
  skill. From there, the normal \`/cc\` classification and stage flow
301
- takes over. Do not produce a second artifact; the ideate file is
308
+ takes over. Do not produce a second artifact; the idea file is
302
309
  preserved as the origin document for this run.
303
310
  - **Save and close:** reply with the artifact path and stop.
304
311
  - **Discard:** delete the artifact file, confirm deletion, stop.
@@ -0,0 +1,31 @@
1
+ export type IdeaFrameId = "pain-friction" | "inversion" | "assumption-break" | "leverage" | "cross-domain-analogy" | "constraint-flip";
2
+ export interface IdeaFrame {
3
+ id: IdeaFrameId;
4
+ label: string;
5
+ prompt: string;
6
+ examplePatterns: string[];
7
+ }
8
+ export interface IdeaFrameDispatchInput {
9
+ focus: string;
10
+ mode: "repo-grounded" | "elsewhere-software" | "elsewhere-non-software";
11
+ signalSummary: string[];
12
+ }
13
+ export interface IdeaFrameDispatchPlanEntry {
14
+ frameId: IdeaFrameId;
15
+ label: string;
16
+ prompt: string;
17
+ }
18
+ export interface IdeaCandidateDraft {
19
+ title: string;
20
+ evidencePath: string;
21
+ summary: string;
22
+ frameId: IdeaFrameId;
23
+ }
24
+ export interface IdeaCandidateMerged extends Omit<IdeaCandidateDraft, "frameId"> {
25
+ frameIds: IdeaFrameId[];
26
+ }
27
+ export declare const DEFAULT_IDEA_FRAME_IDS: readonly IdeaFrameId[];
28
+ export declare const IDEA_FRAMES: readonly IdeaFrame[];
29
+ export declare function resolveIdeaFrames(frameIds?: readonly IdeaFrameId[]): IdeaFrame[];
30
+ export declare function buildIdeaFrameDispatchPlan(input: IdeaFrameDispatchInput, frameIds?: readonly IdeaFrameId[]): IdeaFrameDispatchPlanEntry[];
31
+ export declare function dedupeIdeaCandidates(drafts: readonly IdeaCandidateDraft[]): IdeaCandidateMerged[];
@@ -60,7 +60,7 @@ const FRAME_REGISTRY = {
60
60
  ]
61
61
  }
62
62
  };
63
- export const DEFAULT_IDEATE_FRAME_IDS = Object.freeze([
63
+ export const DEFAULT_IDEA_FRAME_IDS = Object.freeze([
64
64
  "pain-friction",
65
65
  "inversion",
66
66
  "assumption-break",
@@ -68,16 +68,16 @@ export const DEFAULT_IDEATE_FRAME_IDS = Object.freeze([
68
68
  "cross-domain-analogy",
69
69
  "constraint-flip"
70
70
  ]);
71
- export const IDEATE_FRAMES = Object.freeze(DEFAULT_IDEATE_FRAME_IDS.map((id) => FRAME_REGISTRY[id]));
72
- export function resolveIdeateFrames(frameIds) {
71
+ export const IDEA_FRAMES = Object.freeze(DEFAULT_IDEA_FRAME_IDS.map((id) => FRAME_REGISTRY[id]));
72
+ export function resolveIdeaFrames(frameIds) {
73
73
  if (!frameIds || frameIds.length === 0) {
74
- return [...IDEATE_FRAMES];
74
+ return [...IDEA_FRAMES];
75
75
  }
76
76
  const seen = new Set();
77
77
  const resolved = [];
78
78
  for (const rawId of frameIds) {
79
- if (!DEFAULT_IDEATE_FRAME_IDS.includes(rawId)) {
80
- throw new Error(`Unknown ideate frame id: ${rawId}`);
79
+ if (!DEFAULT_IDEA_FRAME_IDS.includes(rawId)) {
80
+ throw new Error(`Unknown idea frame id: ${rawId}`);
81
81
  }
82
82
  if (seen.has(rawId))
83
83
  continue;
@@ -86,11 +86,11 @@ export function resolveIdeateFrames(frameIds) {
86
86
  }
87
87
  return resolved;
88
88
  }
89
- export function buildIdeateFrameDispatchPlan(input, frameIds) {
89
+ export function buildIdeaFrameDispatchPlan(input, frameIds) {
90
90
  const signalBlock = input.signalSummary.length > 0
91
91
  ? input.signalSummary.map((line) => `- ${line}`).join("\n")
92
92
  : "- no pre-scan signals captured yet";
93
- return resolveIdeateFrames(frameIds).map((frame) => ({
93
+ return resolveIdeaFrames(frameIds).map((frame) => ({
94
94
  frameId: frame.id,
95
95
  label: frame.label,
96
96
  prompt: [
@@ -115,7 +115,7 @@ function normalizeCandidateKey(title, evidencePath) {
115
115
  .replace(/\\/gu, "/");
116
116
  return `${normalizedTitle}::${normalizedEvidence}`;
117
117
  }
118
- export function dedupeIdeateCandidates(drafts) {
118
+ export function dedupeIdeaCandidates(drafts) {
119
119
  const merged = new Map();
120
120
  for (const draft of drafts) {
121
121
  const key = normalizeCandidateKey(draft.title, draft.evidencePath);
@@ -0,0 +1,25 @@
1
+ export type IdeaImpact = "high" | "medium" | "low";
2
+ export type IdeaEffort = "s" | "m" | "l";
3
+ export type IdeaConfidence = "high" | "medium" | "low";
4
+ export interface IdeaCandidateEvaluationInput {
5
+ id: string;
6
+ title: string;
7
+ impact: IdeaImpact;
8
+ effort: IdeaEffort;
9
+ confidence: IdeaConfidence;
10
+ rationaleStrength: number;
11
+ counterArgumentStrength: number;
12
+ }
13
+ export interface IdeaCandidateEvaluation extends IdeaCandidateEvaluationInput {
14
+ disposition: "survivor" | "critiqued-out";
15
+ rankingScore: number;
16
+ }
17
+ export interface IdeaRankingResult {
18
+ survivors: IdeaCandidateEvaluation[];
19
+ critiquedOut: IdeaCandidateEvaluation[];
20
+ recommendationId: string | null;
21
+ }
22
+ export declare function isCritiquedOut(rationaleStrength: number, counterArgumentStrength: number): boolean;
23
+ export declare function scoreIdeaCandidate(impact: IdeaImpact, effort: IdeaEffort, confidence: IdeaConfidence): number;
24
+ export declare function evaluateIdeaCandidate(input: IdeaCandidateEvaluationInput): IdeaCandidateEvaluation;
25
+ export declare function rankIdeaCandidates(inputs: readonly IdeaCandidateEvaluationInput[], maxSurvivors?: number): IdeaRankingResult;
@@ -25,22 +25,22 @@ function clampStrength(value) {
25
25
  export function isCritiquedOut(rationaleStrength, counterArgumentStrength) {
26
26
  return clampStrength(counterArgumentStrength) > clampStrength(rationaleStrength);
27
27
  }
28
- export function scoreIdeateCandidate(impact, effort, confidence) {
28
+ export function scoreIdeaCandidate(impact, effort, confidence) {
29
29
  const raw = (IMPACT_POINTS[impact] / EFFORT_COST[effort]) * CONFIDENCE_MULTIPLIER[confidence];
30
30
  return Number(raw.toFixed(3));
31
31
  }
32
- export function evaluateIdeateCandidate(input) {
32
+ export function evaluateIdeaCandidate(input) {
33
33
  const disposition = isCritiquedOut(input.rationaleStrength, input.counterArgumentStrength)
34
34
  ? "critiqued-out"
35
35
  : "survivor";
36
36
  return {
37
37
  ...input,
38
38
  disposition,
39
- rankingScore: scoreIdeateCandidate(input.impact, input.effort, input.confidence)
39
+ rankingScore: scoreIdeaCandidate(input.impact, input.effort, input.confidence)
40
40
  };
41
41
  }
42
- export function rankIdeateCandidates(inputs, maxSurvivors = 10) {
43
- const evaluated = inputs.map(evaluateIdeateCandidate);
42
+ export function rankIdeaCandidates(inputs, maxSurvivors = 10) {
43
+ const evaluated = inputs.map(evaluateIdeaCandidate);
44
44
  const survivors = evaluated
45
45
  .filter((candidate) => candidate.disposition === "survivor")
46
46
  .sort((left, right) => {
@@ -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;