cclaw-cli 7.7.0 → 8.1.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 (282) hide show
  1. package/README.md +210 -134
  2. package/dist/artifact-frontmatter.d.ts +51 -0
  3. package/dist/artifact-frontmatter.js +131 -0
  4. package/dist/artifact-paths.d.ts +7 -27
  5. package/dist/artifact-paths.js +20 -249
  6. package/dist/cancel.d.ts +16 -0
  7. package/dist/cancel.js +66 -0
  8. package/dist/cli.d.ts +2 -27
  9. package/dist/cli.js +90 -508
  10. package/dist/compound.d.ts +26 -0
  11. package/dist/compound.js +96 -0
  12. package/dist/config.d.ts +14 -51
  13. package/dist/config.js +23 -359
  14. package/dist/constants.d.ts +11 -18
  15. package/dist/constants.js +19 -106
  16. package/dist/content/antipatterns.d.ts +1 -0
  17. package/dist/content/antipatterns.js +109 -0
  18. package/dist/content/artifact-templates.d.ts +10 -0
  19. package/dist/content/artifact-templates.js +550 -0
  20. package/dist/content/cancel-command.d.ts +2 -2
  21. package/dist/content/cancel-command.js +25 -17
  22. package/dist/content/core-agents.d.ts +9 -233
  23. package/dist/content/core-agents.js +39 -766
  24. package/dist/content/decision-protocol.d.ts +1 -12
  25. package/dist/content/decision-protocol.js +27 -20
  26. package/dist/content/examples.d.ts +8 -42
  27. package/dist/content/examples.js +293 -425
  28. package/dist/content/idea-command.d.ts +2 -0
  29. package/dist/content/idea-command.js +38 -0
  30. package/dist/content/iron-laws.d.ts +4 -138
  31. package/dist/content/iron-laws.js +18 -197
  32. package/dist/content/meta-skill.d.ts +1 -3
  33. package/dist/content/meta-skill.js +57 -132
  34. package/dist/content/node-hooks.d.ts +12 -8
  35. package/dist/content/node-hooks.js +188 -838
  36. package/dist/content/recovery.d.ts +8 -0
  37. package/dist/content/recovery.js +179 -0
  38. package/dist/content/reference-patterns.d.ts +4 -13
  39. package/dist/content/reference-patterns.js +260 -389
  40. package/dist/content/research-playbooks.d.ts +8 -8
  41. package/dist/content/research-playbooks.js +108 -121
  42. package/dist/content/review-loop.d.ts +6 -192
  43. package/dist/content/review-loop.js +29 -731
  44. package/dist/content/skills.d.ts +8 -38
  45. package/dist/content/skills.js +681 -732
  46. package/dist/content/specialist-prompts/architect.d.ts +1 -0
  47. package/dist/content/specialist-prompts/architect.js +225 -0
  48. package/dist/content/specialist-prompts/brainstormer.d.ts +1 -0
  49. package/dist/content/specialist-prompts/brainstormer.js +168 -0
  50. package/dist/content/specialist-prompts/index.d.ts +2 -0
  51. package/dist/content/specialist-prompts/index.js +14 -0
  52. package/dist/content/specialist-prompts/planner.d.ts +1 -0
  53. package/dist/content/specialist-prompts/planner.js +182 -0
  54. package/dist/content/specialist-prompts/reviewer.d.ts +1 -0
  55. package/dist/content/specialist-prompts/reviewer.js +193 -0
  56. package/dist/content/specialist-prompts/security-reviewer.d.ts +1 -0
  57. package/dist/content/specialist-prompts/security-reviewer.js +133 -0
  58. package/dist/content/specialist-prompts/slice-builder.d.ts +1 -0
  59. package/dist/content/specialist-prompts/slice-builder.js +232 -0
  60. package/dist/content/stage-playbooks.d.ts +8 -0
  61. package/dist/content/stage-playbooks.js +404 -0
  62. package/dist/content/start-command.d.ts +2 -12
  63. package/dist/content/start-command.js +221 -207
  64. package/dist/flow-state.d.ts +21 -178
  65. package/dist/flow-state.js +67 -170
  66. package/dist/fs-utils.d.ts +6 -26
  67. package/dist/fs-utils.js +29 -162
  68. package/dist/gitignore.d.ts +2 -1
  69. package/dist/gitignore.js +51 -34
  70. package/dist/harness-detect.d.ts +10 -0
  71. package/dist/harness-detect.js +29 -0
  72. package/dist/install.d.ts +27 -15
  73. package/dist/install.js +230 -1342
  74. package/dist/knowledge-store.d.ts +19 -163
  75. package/dist/knowledge-store.js +56 -590
  76. package/dist/logger.d.ts +8 -3
  77. package/dist/logger.js +13 -4
  78. package/dist/orchestrator-routing.d.ts +29 -0
  79. package/dist/orchestrator-routing.js +156 -0
  80. package/dist/run-persistence.d.ts +7 -118
  81. package/dist/run-persistence.js +29 -845
  82. package/dist/runtime/run-hook.entry.d.ts +1 -3
  83. package/dist/runtime/run-hook.entry.js +19 -4
  84. package/dist/runtime/run-hook.mjs +13 -1024
  85. package/dist/types.d.ts +25 -261
  86. package/dist/types.js +8 -36
  87. package/package.json +6 -3
  88. package/dist/artifact-linter/brainstorm.d.ts +0 -2
  89. package/dist/artifact-linter/brainstorm.js +0 -353
  90. package/dist/artifact-linter/design.d.ts +0 -18
  91. package/dist/artifact-linter/design.js +0 -444
  92. package/dist/artifact-linter/findings-dedup.d.ts +0 -56
  93. package/dist/artifact-linter/findings-dedup.js +0 -232
  94. package/dist/artifact-linter/plan.d.ts +0 -2
  95. package/dist/artifact-linter/plan.js +0 -826
  96. package/dist/artifact-linter/review-army.d.ts +0 -49
  97. package/dist/artifact-linter/review-army.js +0 -520
  98. package/dist/artifact-linter/review.d.ts +0 -2
  99. package/dist/artifact-linter/review.js +0 -113
  100. package/dist/artifact-linter/scope.d.ts +0 -2
  101. package/dist/artifact-linter/scope.js +0 -158
  102. package/dist/artifact-linter/shared.d.ts +0 -637
  103. package/dist/artifact-linter/shared.js +0 -2163
  104. package/dist/artifact-linter/ship.d.ts +0 -2
  105. package/dist/artifact-linter/ship.js +0 -250
  106. package/dist/artifact-linter/spec.d.ts +0 -2
  107. package/dist/artifact-linter/spec.js +0 -176
  108. package/dist/artifact-linter/tdd.d.ts +0 -118
  109. package/dist/artifact-linter/tdd.js +0 -1404
  110. package/dist/artifact-linter.d.ts +0 -15
  111. package/dist/artifact-linter.js +0 -517
  112. package/dist/codex-feature-flag.d.ts +0 -58
  113. package/dist/codex-feature-flag.js +0 -193
  114. package/dist/content/closeout-guidance.d.ts +0 -14
  115. package/dist/content/closeout-guidance.js +0 -44
  116. package/dist/content/diff-command.d.ts +0 -1
  117. package/dist/content/diff-command.js +0 -43
  118. package/dist/content/harness-doc.d.ts +0 -1
  119. package/dist/content/harness-doc.js +0 -65
  120. package/dist/content/hook-events.d.ts +0 -9
  121. package/dist/content/hook-events.js +0 -23
  122. package/dist/content/hook-manifest.d.ts +0 -81
  123. package/dist/content/hook-manifest.js +0 -156
  124. package/dist/content/hooks.d.ts +0 -11
  125. package/dist/content/hooks.js +0 -1972
  126. package/dist/content/idea.d.ts +0 -60
  127. package/dist/content/idea.js +0 -416
  128. package/dist/content/language-policy.d.ts +0 -2
  129. package/dist/content/language-policy.js +0 -13
  130. package/dist/content/learnings.d.ts +0 -6
  131. package/dist/content/learnings.js +0 -141
  132. package/dist/content/observe.d.ts +0 -19
  133. package/dist/content/observe.js +0 -86
  134. package/dist/content/opencode-plugin.d.ts +0 -1
  135. package/dist/content/opencode-plugin.js +0 -635
  136. package/dist/content/review-prompts.d.ts +0 -1
  137. package/dist/content/review-prompts.js +0 -104
  138. package/dist/content/runtime-shared-snippets.d.ts +0 -8
  139. package/dist/content/runtime-shared-snippets.js +0 -80
  140. package/dist/content/session-hooks.d.ts +0 -7
  141. package/dist/content/session-hooks.js +0 -107
  142. package/dist/content/skills-elicitation.d.ts +0 -1
  143. package/dist/content/skills-elicitation.js +0 -167
  144. package/dist/content/stage-command.d.ts +0 -2
  145. package/dist/content/stage-command.js +0 -17
  146. package/dist/content/stage-schema.d.ts +0 -117
  147. package/dist/content/stage-schema.js +0 -955
  148. package/dist/content/stages/_lint-metadata/index.d.ts +0 -2
  149. package/dist/content/stages/_lint-metadata/index.js +0 -97
  150. package/dist/content/stages/brainstorm.d.ts +0 -2
  151. package/dist/content/stages/brainstorm.js +0 -184
  152. package/dist/content/stages/design.d.ts +0 -2
  153. package/dist/content/stages/design.js +0 -288
  154. package/dist/content/stages/index.d.ts +0 -8
  155. package/dist/content/stages/index.js +0 -11
  156. package/dist/content/stages/plan.d.ts +0 -2
  157. package/dist/content/stages/plan.js +0 -191
  158. package/dist/content/stages/review.d.ts +0 -2
  159. package/dist/content/stages/review.js +0 -240
  160. package/dist/content/stages/schema-types.d.ts +0 -203
  161. package/dist/content/stages/schema-types.js +0 -1
  162. package/dist/content/stages/scope.d.ts +0 -2
  163. package/dist/content/stages/scope.js +0 -254
  164. package/dist/content/stages/ship.d.ts +0 -2
  165. package/dist/content/stages/ship.js +0 -159
  166. package/dist/content/stages/spec.d.ts +0 -2
  167. package/dist/content/stages/spec.js +0 -170
  168. package/dist/content/stages/tdd.d.ts +0 -4
  169. package/dist/content/stages/tdd.js +0 -273
  170. package/dist/content/state-contracts.d.ts +0 -1
  171. package/dist/content/state-contracts.js +0 -63
  172. package/dist/content/status-command.d.ts +0 -4
  173. package/dist/content/status-command.js +0 -109
  174. package/dist/content/subagent-context-skills.d.ts +0 -4
  175. package/dist/content/subagent-context-skills.js +0 -279
  176. package/dist/content/subagents.d.ts +0 -3
  177. package/dist/content/subagents.js +0 -997
  178. package/dist/content/templates.d.ts +0 -26
  179. package/dist/content/templates.js +0 -1692
  180. package/dist/content/track-render-context.d.ts +0 -18
  181. package/dist/content/track-render-context.js +0 -53
  182. package/dist/content/tree-command.d.ts +0 -1
  183. package/dist/content/tree-command.js +0 -64
  184. package/dist/content/utility-skills.d.ts +0 -30
  185. package/dist/content/utility-skills.js +0 -160
  186. package/dist/content/view-command.d.ts +0 -2
  187. package/dist/content/view-command.js +0 -92
  188. package/dist/delegation.d.ts +0 -649
  189. package/dist/delegation.js +0 -1539
  190. package/dist/early-loop.d.ts +0 -70
  191. package/dist/early-loop.js +0 -302
  192. package/dist/execution-topology.d.ts +0 -36
  193. package/dist/execution-topology.js +0 -73
  194. package/dist/gate-evidence.d.ts +0 -85
  195. package/dist/gate-evidence.js +0 -631
  196. package/dist/harness-adapters.d.ts +0 -151
  197. package/dist/harness-adapters.js +0 -756
  198. package/dist/harness-selection.d.ts +0 -31
  199. package/dist/harness-selection.js +0 -214
  200. package/dist/hook-schema.d.ts +0 -6
  201. package/dist/hook-schema.js +0 -114
  202. package/dist/hook-schemas/claude-hooks.v1.json +0 -10
  203. package/dist/hook-schemas/codex-hooks.v1.json +0 -10
  204. package/dist/hook-schemas/cursor-hooks.v1.json +0 -13
  205. package/dist/init-detect.d.ts +0 -2
  206. package/dist/init-detect.js +0 -50
  207. package/dist/internal/advance-stage/advance.d.ts +0 -89
  208. package/dist/internal/advance-stage/advance.js +0 -655
  209. package/dist/internal/advance-stage/cancel-run.d.ts +0 -8
  210. package/dist/internal/advance-stage/cancel-run.js +0 -19
  211. package/dist/internal/advance-stage/flow-state-coercion.d.ts +0 -3
  212. package/dist/internal/advance-stage/flow-state-coercion.js +0 -81
  213. package/dist/internal/advance-stage/helpers.d.ts +0 -14
  214. package/dist/internal/advance-stage/helpers.js +0 -145
  215. package/dist/internal/advance-stage/hook.d.ts +0 -8
  216. package/dist/internal/advance-stage/hook.js +0 -40
  217. package/dist/internal/advance-stage/parsers.d.ts +0 -72
  218. package/dist/internal/advance-stage/parsers.js +0 -357
  219. package/dist/internal/advance-stage/proactive-delegation-trace.d.ts +0 -24
  220. package/dist/internal/advance-stage/proactive-delegation-trace.js +0 -56
  221. package/dist/internal/advance-stage/review-loop.d.ts +0 -16
  222. package/dist/internal/advance-stage/review-loop.js +0 -199
  223. package/dist/internal/advance-stage/rewind.d.ts +0 -14
  224. package/dist/internal/advance-stage/rewind.js +0 -108
  225. package/dist/internal/advance-stage/start-flow.d.ts +0 -13
  226. package/dist/internal/advance-stage/start-flow.js +0 -241
  227. package/dist/internal/advance-stage/verify.d.ts +0 -21
  228. package/dist/internal/advance-stage/verify.js +0 -185
  229. package/dist/internal/advance-stage.d.ts +0 -7
  230. package/dist/internal/advance-stage.js +0 -138
  231. package/dist/internal/cohesion-contract-stub.d.ts +0 -24
  232. package/dist/internal/cohesion-contract-stub.js +0 -148
  233. package/dist/internal/compound-readiness.d.ts +0 -23
  234. package/dist/internal/compound-readiness.js +0 -102
  235. package/dist/internal/detect-public-api-changes.d.ts +0 -5
  236. package/dist/internal/detect-public-api-changes.js +0 -45
  237. package/dist/internal/detect-supply-chain-changes.d.ts +0 -6
  238. package/dist/internal/detect-supply-chain-changes.js +0 -138
  239. package/dist/internal/early-loop-status.d.ts +0 -7
  240. package/dist/internal/early-loop-status.js +0 -93
  241. package/dist/internal/envelope-validate.d.ts +0 -7
  242. package/dist/internal/envelope-validate.js +0 -66
  243. package/dist/internal/flow-state-repair.d.ts +0 -20
  244. package/dist/internal/flow-state-repair.js +0 -104
  245. package/dist/internal/plan-split-waves.d.ts +0 -190
  246. package/dist/internal/plan-split-waves.js +0 -764
  247. package/dist/internal/runtime-integrity.d.ts +0 -7
  248. package/dist/internal/runtime-integrity.js +0 -268
  249. package/dist/internal/slice-commit.d.ts +0 -7
  250. package/dist/internal/slice-commit.js +0 -619
  251. package/dist/internal/tdd-loop-status.d.ts +0 -14
  252. package/dist/internal/tdd-loop-status.js +0 -68
  253. package/dist/internal/tdd-red-evidence.d.ts +0 -7
  254. package/dist/internal/tdd-red-evidence.js +0 -153
  255. package/dist/internal/waiver-grant.d.ts +0 -62
  256. package/dist/internal/waiver-grant.js +0 -294
  257. package/dist/internal/wave-status.d.ts +0 -63
  258. package/dist/internal/wave-status.js +0 -450
  259. package/dist/managed-resources.d.ts +0 -53
  260. package/dist/managed-resources.js +0 -313
  261. package/dist/policy.d.ts +0 -10
  262. package/dist/policy.js +0 -167
  263. package/dist/retro-gate.d.ts +0 -9
  264. package/dist/retro-gate.js +0 -47
  265. package/dist/run-archive.d.ts +0 -61
  266. package/dist/run-archive.js +0 -391
  267. package/dist/runs.d.ts +0 -2
  268. package/dist/runs.js +0 -2
  269. package/dist/stack-detection.d.ts +0 -116
  270. package/dist/stack-detection.js +0 -489
  271. package/dist/streaming/event-stream.d.ts +0 -31
  272. package/dist/streaming/event-stream.js +0 -114
  273. package/dist/tdd-cycle.d.ts +0 -107
  274. package/dist/tdd-cycle.js +0 -289
  275. package/dist/tdd-verification-evidence.d.ts +0 -17
  276. package/dist/tdd-verification-evidence.js +0 -122
  277. package/dist/track-heuristics.d.ts +0 -27
  278. package/dist/track-heuristics.js +0 -154
  279. package/dist/util/slice-id.d.ts +0 -58
  280. package/dist/util/slice-id.js +0 -89
  281. package/dist/worktree-manager.d.ts +0 -20
  282. package/dist/worktree-manager.js +0 -108
@@ -1,353 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- import { checkCriticPredictionsContract, evaluateInvestigationTrace, evaluateQaLogFloor, sectionBodyByName, validateApproachesTaxonomy, headingLineIndex, meaningfulLineCount, getMarkdownTableRows, parseShortCircuitStatus, validateCalibratedSelfReview, markdownFieldRegex } from "./shared.js";
4
- import { readFlowState } from "../run-persistence.js";
5
- export async function lintBrainstormStage(ctx) {
6
- const { projectRoot, track, raw, absFile, sections, findings, parsedFrontmatter, brainstormShortCircuitBody, brainstormShortCircuitActivated, staleDiagramAuditEnabled, isTrivialOverride } = ctx;
7
- evaluateInvestigationTrace(ctx, "Q&A Log");
8
- const qaLogBody = sectionBodyByName(sections, "Q&A Log");
9
- const qaLogRows = qaLogBody ? getMarkdownTableRows(qaLogBody) : [];
10
- const qaLogOk = qaLogBody !== null && qaLogRows.length > 0;
11
- findings.push({
12
- section: "qa_log_missing",
13
- required: false,
14
- rule: "[P2] qa_log_missing — Q&A Log empty — confirm you actually had a dialogue with the user, not a draft from memory.",
15
- found: qaLogOk,
16
- details: qaLogOk
17
- ? `Q&A Log contains ${qaLogRows.length} data row(s).`
18
- : qaLogBody === null
19
- ? "Missing `## Q&A Log` section."
20
- : "Q&A Log is present but has zero data rows."
21
- });
22
- if (!brainstormShortCircuitActivated) {
23
- const skipQuestions = ctx.activeStageFlags.includes("--skip-questions");
24
- const floor = evaluateQaLogFloor(qaLogBody, track, "brainstorm", { discoveryMode: ctx.discoveryMode, skipQuestions });
25
- findings.push({
26
- section: "qa_log_unconverged",
27
- required: !floor.skipQuestionsAdvisory,
28
- rule: "[P1] qa_log_unconverged — Q&A Log has not converged for this stage. Continue elicitation until every forcing-question topic id is tagged with `[topic:<id>]` on at least one row, the last 2 rows produce no decision-changing impact (Ralph-Loop), or an explicit user stop-signal row is appended.",
29
- found: floor.ok,
30
- details: floor.details
31
- });
32
- }
33
- // Brainstorm Iron Law: "NO ARTIFACT IS COMPLETE WITHOUT AN EXPLICITLY
34
- // APPROVED DIRECTION — SILENCE IS NOT APPROVAL." Previously this was
35
- // prose-only — nothing failed when the Selected Direction section
36
- // omitted an approval marker, or when the Approaches table collapsed
37
- // to a single row (defeating the "2-3 distinct approaches" gate).
38
- const tierBody = sectionBodyByName(sections, "Approach Tier");
39
- if (tierBody !== null) {
40
- // Token vocabulary covers `lite`, `Lightweight`, `Standard`, and
41
- // `Deep` (case-insensitive). A line that lists ≥2 distinct tokens is
42
- // the unfilled template placeholder (`Tier: lite | standard | deep`)
43
- // and must not silently pass; we look for at least one decision line
44
- // with exactly one token, while ignoring placeholder lines.
45
- const cleanedLines = tierBody
46
- .split("\n")
47
- .map((line) => line.replace(/[*_`]/gu, ""));
48
- const lineTokenCounts = cleanedLines.map((line) => {
49
- const tokens = line.match(/\b(?:lite|lightweight|light|standard|deep)\b/giu) ?? [];
50
- return new Set(tokens.map((token) => token.toLowerCase())).size;
51
- });
52
- const hasDecisionLine = lineTokenCounts.some((count) => count === 1);
53
- const hasPlaceholderLine = lineTokenCounts.some((count) => count >= 2);
54
- const ok = hasDecisionLine;
55
- findings.push({
56
- section: "Approach Tier Classification",
57
- required: false,
58
- rule: "Approach Tier must explicitly classify depth as one of `lite` (a.k.a. `Lightweight`), `Standard`, or `Deep`.",
59
- found: ok,
60
- details: ok
61
- ? "Approach Tier includes a single recognized depth token."
62
- : hasPlaceholderLine
63
- ? "Approach Tier still lists multiple tier tokens (template placeholder); pick exactly one of `lite`/`Lightweight`, `Standard`, or `Deep`."
64
- : "Approach Tier is missing a recognized depth token (`lite`/`Lightweight`, `Standard`, or `Deep`)."
65
- });
66
- }
67
- const approachesBody = sectionBodyByName(sections, "Approaches");
68
- if (approachesBody !== null) {
69
- const approachesTaxonomy = validateApproachesTaxonomy(approachesBody);
70
- findings.push({
71
- section: "Distinct Approaches Enforcement",
72
- required: true,
73
- rule: "Approaches section must document at least 2 distinct approaches so the Iron Law comparison is meaningful.",
74
- found: approachesTaxonomy.rowCount >= 2,
75
- details: approachesTaxonomy.rowCount >= 2
76
- ? `Detected ${approachesTaxonomy.rowCount} approach row(s).`
77
- : `Detected ${approachesTaxonomy.rowCount} approach row(s); at least 2 required.`
78
- });
79
- findings.push({
80
- section: "Approaches Role/Upside Taxonomy",
81
- required: false,
82
- rule: "Approaches table must use canonical Role and Upside enum values.",
83
- found: approachesTaxonomy.roleUpsideOk,
84
- details: approachesTaxonomy.details
85
- });
86
- findings.push({
87
- section: "Challenger Alternative Enforcement",
88
- required: false,
89
- rule: "Approaches must include one challenger option with explicit high/higher upside.",
90
- found: approachesTaxonomy.challengerOk,
91
- details: approachesTaxonomy.details
92
- });
93
- }
94
- const reactionIndex = headingLineIndex(raw, "Approach Reaction");
95
- const directionIndex = headingLineIndex(raw, "Selected Direction");
96
- if (directionIndex >= 0 && !brainstormShortCircuitActivated) {
97
- const orderOk = reactionIndex >= 0 && reactionIndex < directionIndex;
98
- findings.push({
99
- section: "Approach Reaction Ordering",
100
- required: false,
101
- rule: "Approach Reaction must appear before Selected Direction (propose -> react -> recommend).",
102
- found: orderOk,
103
- details: orderOk
104
- ? "Approach Reaction appears before Selected Direction."
105
- : "Approach Reaction must be present before Selected Direction."
106
- });
107
- }
108
- const directionBody = sectionBodyByName(sections, "Selected Direction");
109
- if (directionBody !== null) {
110
- const approvalMarker = /\bapprov(?:ed|al)\b/iu.test(directionBody);
111
- findings.push({
112
- section: "Direction Approval Marker",
113
- required: true,
114
- rule: "Selected Direction section must state an explicit approval marker (for example `Approval: approved` or `Approved by: user`).",
115
- found: approvalMarker,
116
- details: approvalMarker
117
- ? "Approval marker present in Selected Direction."
118
- : "No explicit `approved`/`approval` marker found in Selected Direction."
119
- });
120
- if (!brainstormShortCircuitActivated) {
121
- const reactionBody = sectionBodyByName(sections, "Approach Reaction");
122
- const reactionTrace = /\b(?:reaction|feedback|concern(?:s)?)\b/iu.test(directionBody) ||
123
- (reactionIndex >= 0 && reactionIndex < directionIndex && meaningfulLineCount(reactionBody ?? "") > 0);
124
- findings.push({
125
- section: "Direction Reaction Trace",
126
- required: true,
127
- rule: "Selected Direction must be traceable to a prior Approach Reaction section or explicitly reference user reaction/feedback/concerns.",
128
- found: reactionTrace,
129
- details: reactionTrace
130
- ? "Selected Direction is traceable to prior user reaction."
131
- : "Selected Direction is not traceable to user reaction. Add `## Approach Reaction` before it, or mention the user's reaction/concerns in the rationale."
132
- });
133
- // Track-aware handoff: standard track goes to `scope`; medium track
134
- // goes directly to `spec`; the quick track skips brainstorm entirely.
135
- // We accept either canonical successor token plus a generic
136
- // `next-stage` / `handoff` phrase to preserve i18n flexibility.
137
- const handoffTrace = /(?:`(?:scope|spec)`|\bscope\b|\bspec\b|next[-\s_]stage|next stage|\bhandoff\b|hand[-\s]off)/iu.test(directionBody);
138
- findings.push({
139
- section: "Direction Next-Stage Handoff",
140
- required: true,
141
- rule: "Selected Direction must record the track-aware next-stage handoff (mention `scope` for standard, `spec` for medium, or include a `Next-stage handoff:` line).",
142
- found: handoffTrace,
143
- details: handoffTrace
144
- ? "Selected Direction names the next-stage handoff."
145
- : "Selected Direction is missing a next-stage handoff token. Mention `scope` (standard) or `spec` (medium), or add a `Next-stage handoff:` line so downstream stages can trace the contract."
146
- });
147
- }
148
- }
149
- const shortCircuitBody = brainstormShortCircuitBody;
150
- if (shortCircuitBody !== null) {
151
- const statusValue = parseShortCircuitStatus(shortCircuitBody);
152
- const hasStatus = statusValue.length > 0;
153
- findings.push({
154
- section: "Short-Circuit Status",
155
- required: false,
156
- rule: "Short-Circuit Decision must include a `Status:` line (`activated` or `bypassed`).",
157
- found: hasStatus,
158
- details: hasStatus
159
- ? `Short-circuit status declared as "${statusValue}".`
160
- : "Short-Circuit Decision is missing a `Status:` line."
161
- });
162
- if (brainstormShortCircuitActivated) {
163
- const artifactLines = meaningfulLineCount(raw);
164
- const withinStubLimit = artifactLines <= 30;
165
- const hasScopeHandoff = /\bscope\b/iu.test(shortCircuitBody);
166
- findings.push({
167
- section: "Short-Circuit Stub Size",
168
- required: true,
169
- rule: "When short-circuit is activated, brainstorm artifact must remain a <=30 meaningful-line stub.",
170
- found: withinStubLimit,
171
- details: withinStubLimit
172
- ? `Short-circuit stub size within limit (${artifactLines} meaningful lines).`
173
- : `Short-circuit stub too large (${artifactLines} meaningful lines); expected <= 30.`
174
- });
175
- findings.push({
176
- section: "Short-Circuit Scope Handoff",
177
- required: true,
178
- rule: "When short-circuit is activated, the section must explicitly hand off to scope.",
179
- found: hasScopeHandoff,
180
- details: hasScopeHandoff
181
- ? "Short-circuit section includes explicit scope handoff."
182
- : "Short-circuit section is missing explicit scope handoff guidance."
183
- });
184
- }
185
- }
186
- const selfReviewBody = sectionBodyByName(sections, "Self-Review Notes");
187
- if (selfReviewBody !== null) {
188
- const selfReview = validateCalibratedSelfReview(selfReviewBody);
189
- findings.push({
190
- section: "Calibrated Self-Review Format",
191
- required: false,
192
- rule: "When Self-Review Notes are present, they must use the calibrated review prompt output shape.",
193
- found: selfReview.ok,
194
- details: selfReview.details
195
- });
196
- }
197
- const criticPredictions = checkCriticPredictionsContract(sections);
198
- if (criticPredictions !== null) {
199
- findings.push({
200
- section: "critic.predictions_missing",
201
- required: false,
202
- rule: "[P2] critic.predictions_missing — pre-commitment predictions block missing or empty",
203
- found: criticPredictions.found,
204
- details: criticPredictions.details
205
- });
206
- }
207
- // Universal structural checks (Layer 2.1). Each fires only when the
208
- // matching section is present so legacy fixtures keep their current
209
- // shape, while artifacts emitted from the v3 template have to satisfy
210
- // them. Content is never inspected — only the shape required by the
211
- // reference patterns (gstack mode, forcing questions, premise list,
212
- // approach detail cards, anti-sycophancy stamp).
213
- const modeBody = sectionBodyByName(sections, "Mode Block");
214
- if (modeBody !== null) {
215
- const modeTokens = ["STARTUP", "BUILDER", "ENGINEERING", "OPS", "RESEARCH"];
216
- const modeRegex = markdownFieldRegex("Mode", modeTokens.join("|"), "u");
217
- const tokenMatches = new Set();
218
- const lineRegex = new RegExp(modeRegex.source, "gu");
219
- for (const match of modeBody.matchAll(lineRegex)) {
220
- const token = (match[0].match(/STARTUP|BUILDER|ENGINEERING|OPS|RESEARCH/u) ?? [""])[0];
221
- if (token)
222
- tokenMatches.add(token);
223
- }
224
- const placeholderLine = modeBody
225
- .split("\n")
226
- .find((line) => /\bMode\b\s*[*_]{0,2}\s*:/iu.test(line) && (line.match(/STARTUP|BUILDER|ENGINEERING|OPS|RESEARCH/giu) ?? []).length >= 2);
227
- const isPlaceholder = Boolean(placeholderLine);
228
- const ok = tokenMatches.size === 1 && !isPlaceholder;
229
- findings.push({
230
- section: "Mode Block Token",
231
- required: false,
232
- rule: "Mode Block must declare exactly one mode token: STARTUP, BUILDER, ENGINEERING, OPS, or RESEARCH.",
233
- found: ok,
234
- details: ok
235
- ? `Recognized mode token detected: ${[...tokenMatches][0] ?? ""}.`
236
- : isPlaceholder
237
- ? "Mode Block still lists multiple mode tokens (template placeholder); pick exactly one of STARTUP/BUILDER/ENGINEERING/OPS/RESEARCH."
238
- : "Mode Block is missing a recognized mode token (STARTUP/BUILDER/ENGINEERING/OPS/RESEARCH)."
239
- });
240
- }
241
- // Approach Detail Cards: structural sub-section under Approaches, one
242
- // bullet block per approach with the canonical fields.
243
- const approachCardsRegex = /####\s+APPROACH\s+[A-Z]\b[\s\S]*?(?:^-\s*Summary:[\s\S]*?^-\s*Effort:[\s\S]*?^-\s*Risk:[\s\S]*?^-\s*Pros:[\s\S]*?^-\s*Cons:[\s\S]*?^-\s*Reuses:)/gimu;
244
- const matches = raw.match(approachCardsRegex);
245
- const cardCount = matches ? matches.length : 0;
246
- if (/####\s+APPROACH\s+[A-Z]\b/iu.test(raw) ||
247
- /^RECOMMENDATION:/imu.test(raw)) {
248
- findings.push({
249
- section: "Approach Detail Cards",
250
- required: false,
251
- rule: "Approach Detail Cards must include ≥2 `#### APPROACH <letter>` blocks each with Summary/Effort/Risk/Pros/Cons/Reuses.",
252
- found: cardCount >= 2,
253
- details: cardCount >= 2
254
- ? `Detected ${cardCount} valid approach detail card(s).`
255
- : `Detected ${cardCount} valid approach detail card(s); at least 2 required with all fields present.`
256
- });
257
- const recommendationLine = raw.match(/^RECOMMENDATION:\s*(.+)$/imu);
258
- const hasRecommendation = recommendationLine !== null && recommendationLine[1] !== undefined && recommendationLine[1].trim().length > 0;
259
- findings.push({
260
- section: "Approach Recommendation Marker",
261
- required: false,
262
- rule: "Approach Detail Cards must conclude with a single `RECOMMENDATION:` line citing the chosen letter and rationale.",
263
- found: hasRecommendation,
264
- details: hasRecommendation
265
- ? "Recommendation marker present."
266
- : "Missing or empty `RECOMMENDATION:` line after approach detail cards."
267
- });
268
- }
269
- const outsideVoiceBody = sectionBodyByName(sections, "Outside Voice");
270
- if (outsideVoiceBody !== null) {
271
- const required = ["source:", "prompt:", "tension:", "resolution:"];
272
- const missing = required.filter((key) => !new RegExp(`(?:^|\\n)\\s*-?\\s*${key.replace(":", "\\s*:")}`, "iu").test(outsideVoiceBody));
273
- const optedOut = /\bnot used\b|\bn\/a\b|\bnone\b/iu.test(outsideVoiceBody);
274
- findings.push({
275
- section: "Outside Voice Slot Shape",
276
- required: false,
277
- rule: "Outside Voice section must either declare opt-out (`not used`/`none`) or include `source:`, `prompt:`, `tension:`, `resolution:`.",
278
- found: optedOut || missing.length === 0,
279
- details: optedOut || missing.length === 0
280
- ? "Outside Voice slot is well-formed."
281
- : `Outside Voice section is missing field(s): ${missing.join(", ")}.`
282
- });
283
- }
284
- let ideaHint = {};
285
- try {
286
- const flowState = await readFlowState(projectRoot);
287
- const hint = flowState.interactionHints?.brainstorm;
288
- if (hint) {
289
- ideaHint = {
290
- fromIdeaArtifact: hint.fromIdeaArtifact,
291
- fromIdeaCandidateId: hint.fromIdeaCandidateId
292
- };
293
- }
294
- }
295
- catch {
296
- ideaHint = {};
297
- }
298
- if (ideaHint.fromIdeaArtifact) {
299
- const carryBody = sectionBodyByName(sections, "Idea Evidence Carry-forward");
300
- const hasSection = carryBody !== null && meaningfulLineCount(carryBody) > 0;
301
- const sourceCited = hasSection &&
302
- carryBody.includes(ideaHint.fromIdeaArtifact);
303
- const candidateCited = ideaHint.fromIdeaCandidateId
304
- ? hasSection && carryBody.toUpperCase().includes(ideaHint.fromIdeaCandidateId.toUpperCase())
305
- : true;
306
- const ok = hasSection && sourceCited && candidateCited;
307
- findings.push({
308
- section: "brainstorm.idea_evidence_carry_forward",
309
- required: true,
310
- rule: "[P1] brainstorm.idea_evidence_carry_forward — when `flow-state.interactionHints.brainstorm.fromIdeaArtifact` is set, the brainstorm artifact MUST include `## Idea Evidence Carry-forward` citing the idea artifact path and chosen `I-#`. Reuse divergent + critique + rank work from `/cc-ideate` as the `baseline` Approach; only newly generate the higher-upside challenger row(s).",
311
- found: ok,
312
- details: ok
313
- ? `Idea Evidence Carry-forward cites ${ideaHint.fromIdeaArtifact}${ideaHint.fromIdeaCandidateId ? ` (${ideaHint.fromIdeaCandidateId})` : ""}.`
314
- : !hasSection
315
- ? `Brainstorm started from /cc-ideate (artifact ${ideaHint.fromIdeaArtifact}${ideaHint.fromIdeaCandidateId ? `, candidate ${ideaHint.fromIdeaCandidateId}` : ""}) but \`## Idea Evidence Carry-forward\` is missing or empty.`
316
- : !sourceCited
317
- ? `\`## Idea Evidence Carry-forward\` does not cite the source idea artifact path \`${ideaHint.fromIdeaArtifact}\`.`
318
- : `\`## Idea Evidence Carry-forward\` does not cite the chosen candidate id \`${ideaHint.fromIdeaCandidateId ?? ""}\`.`
319
- });
320
- }
321
- const wavePlansDir = path.join(projectRoot, ".cclaw", "wave-plans");
322
- let wavePlanEntries = [];
323
- try {
324
- wavePlanEntries = (await fs.readdir(wavePlansDir))
325
- .filter((entry) => entry !== ".gitkeep" && !entry.startsWith("."));
326
- }
327
- catch {
328
- wavePlanEntries = [];
329
- }
330
- const multiWaveDetected = wavePlanEntries.length >= 2;
331
- if (multiWaveDetected) {
332
- const carryForwardBody = sectionBodyByName(sections, "Wave Carry-forward");
333
- const hasCarryForwardSection = carryForwardBody !== null;
334
- const hasCarryForwardContent = carryForwardBody !== null && meaningfulLineCount(carryForwardBody) > 0;
335
- const hasDriftAuditMarkers = carryForwardBody !== null &&
336
- /\bcarrying\s+forward\b/iu.test(carryForwardBody) &&
337
- /\bdrift\s+detected\b/iu.test(carryForwardBody);
338
- const waveDriftAddressed = hasCarryForwardSection && hasCarryForwardContent && hasDriftAuditMarkers;
339
- findings.push({
340
- section: "wave.drift_unaddressed",
341
- required: false,
342
- rule: "[P1] wave.drift_unaddressed — when `.cclaw/wave-plans/` has >=2 entries, brainstorm must include `## Wave Carry-forward` with carry-forward and drift audit markers.",
343
- found: waveDriftAddressed,
344
- details: waveDriftAddressed
345
- ? `Multi-wave context detected (${wavePlanEntries.length} wave-plan entries); Wave Carry-forward audit is present.`
346
- : !hasCarryForwardSection
347
- ? "Multi-wave context detected but `## Wave Carry-forward` section is missing."
348
- : !hasCarryForwardContent
349
- ? "`## Wave Carry-forward` exists but has no meaningful content."
350
- : "Wave Carry-forward section must include both `Carrying forward` and `Drift detected` markers."
351
- });
352
- }
353
- }
@@ -1,18 +0,0 @@
1
- import { type StageLintContext } from "./shared.js";
2
- export interface CodebaseInvestigationFileRef {
3
- /** Filename to stat (parenthetical suffix already stripped). */
4
- filename: string;
5
- /** Raw cell content, useful for diagnostic messages. */
6
- raw: string;
7
- /** When true, the audit treats this row as a "new file, no baseline". */
8
- newFile: boolean;
9
- /**
10
- * When true, the audit skips this row entirely (suffix `(skip)`,
11
- * `(deleted)`, `(stub)`, leading `#`, or a `skip:` token in the
12
- * Notes column).
13
- */
14
- skip: boolean;
15
- }
16
- export declare function normalizeCodebaseInvestigationFileRef(value: string, notesCell: string): CodebaseInvestigationFileRef | null;
17
- export declare function collectCodebaseInvestigationFiles(sectionBody: string): CodebaseInvestigationFileRef[];
18
- export declare function lintDesignStage(ctx: StageLintContext): Promise<void>;