cclaw-cli 7.7.1 → 8.1.1

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 (284) hide show
  1. package/README.md +211 -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 +107 -511
  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 -768
  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 -134
  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/harness-prompt.d.ts +26 -0
  73. package/dist/harness-prompt.js +142 -0
  74. package/dist/install.d.ts +35 -15
  75. package/dist/install.js +238 -1347
  76. package/dist/knowledge-store.d.ts +19 -163
  77. package/dist/knowledge-store.js +56 -590
  78. package/dist/logger.d.ts +8 -3
  79. package/dist/logger.js +13 -4
  80. package/dist/orchestrator-routing.d.ts +29 -0
  81. package/dist/orchestrator-routing.js +156 -0
  82. package/dist/run-persistence.d.ts +7 -118
  83. package/dist/run-persistence.js +29 -845
  84. package/dist/runtime/run-hook.entry.d.ts +1 -3
  85. package/dist/runtime/run-hook.entry.js +19 -4
  86. package/dist/runtime/run-hook.mjs +13 -1024
  87. package/dist/types.d.ts +25 -261
  88. package/dist/types.js +8 -36
  89. package/package.json +6 -3
  90. package/dist/artifact-linter/brainstorm.d.ts +0 -2
  91. package/dist/artifact-linter/brainstorm.js +0 -353
  92. package/dist/artifact-linter/design.d.ts +0 -18
  93. package/dist/artifact-linter/design.js +0 -444
  94. package/dist/artifact-linter/findings-dedup.d.ts +0 -56
  95. package/dist/artifact-linter/findings-dedup.js +0 -232
  96. package/dist/artifact-linter/plan.d.ts +0 -2
  97. package/dist/artifact-linter/plan.js +0 -826
  98. package/dist/artifact-linter/review-army.d.ts +0 -49
  99. package/dist/artifact-linter/review-army.js +0 -520
  100. package/dist/artifact-linter/review.d.ts +0 -2
  101. package/dist/artifact-linter/review.js +0 -113
  102. package/dist/artifact-linter/scope.d.ts +0 -2
  103. package/dist/artifact-linter/scope.js +0 -158
  104. package/dist/artifact-linter/shared.d.ts +0 -637
  105. package/dist/artifact-linter/shared.js +0 -2163
  106. package/dist/artifact-linter/ship.d.ts +0 -2
  107. package/dist/artifact-linter/ship.js +0 -250
  108. package/dist/artifact-linter/spec.d.ts +0 -2
  109. package/dist/artifact-linter/spec.js +0 -176
  110. package/dist/artifact-linter/tdd.d.ts +0 -118
  111. package/dist/artifact-linter/tdd.js +0 -1404
  112. package/dist/artifact-linter.d.ts +0 -15
  113. package/dist/artifact-linter.js +0 -517
  114. package/dist/codex-feature-flag.d.ts +0 -58
  115. package/dist/codex-feature-flag.js +0 -193
  116. package/dist/content/closeout-guidance.d.ts +0 -14
  117. package/dist/content/closeout-guidance.js +0 -44
  118. package/dist/content/diff-command.d.ts +0 -1
  119. package/dist/content/diff-command.js +0 -43
  120. package/dist/content/harness-doc.d.ts +0 -1
  121. package/dist/content/harness-doc.js +0 -65
  122. package/dist/content/hook-events.d.ts +0 -9
  123. package/dist/content/hook-events.js +0 -23
  124. package/dist/content/hook-manifest.d.ts +0 -81
  125. package/dist/content/hook-manifest.js +0 -156
  126. package/dist/content/hooks.d.ts +0 -11
  127. package/dist/content/hooks.js +0 -1972
  128. package/dist/content/idea.d.ts +0 -60
  129. package/dist/content/idea.js +0 -416
  130. package/dist/content/language-policy.d.ts +0 -2
  131. package/dist/content/language-policy.js +0 -13
  132. package/dist/content/learnings.d.ts +0 -6
  133. package/dist/content/learnings.js +0 -141
  134. package/dist/content/observe.d.ts +0 -19
  135. package/dist/content/observe.js +0 -86
  136. package/dist/content/opencode-plugin.d.ts +0 -1
  137. package/dist/content/opencode-plugin.js +0 -635
  138. package/dist/content/review-prompts.d.ts +0 -1
  139. package/dist/content/review-prompts.js +0 -104
  140. package/dist/content/runtime-shared-snippets.d.ts +0 -8
  141. package/dist/content/runtime-shared-snippets.js +0 -80
  142. package/dist/content/session-hooks.d.ts +0 -7
  143. package/dist/content/session-hooks.js +0 -107
  144. package/dist/content/skills-elicitation.d.ts +0 -1
  145. package/dist/content/skills-elicitation.js +0 -167
  146. package/dist/content/stage-command.d.ts +0 -2
  147. package/dist/content/stage-command.js +0 -17
  148. package/dist/content/stage-schema.d.ts +0 -117
  149. package/dist/content/stage-schema.js +0 -955
  150. package/dist/content/stages/_lint-metadata/index.d.ts +0 -2
  151. package/dist/content/stages/_lint-metadata/index.js +0 -97
  152. package/dist/content/stages/brainstorm.d.ts +0 -2
  153. package/dist/content/stages/brainstorm.js +0 -184
  154. package/dist/content/stages/design.d.ts +0 -2
  155. package/dist/content/stages/design.js +0 -288
  156. package/dist/content/stages/index.d.ts +0 -8
  157. package/dist/content/stages/index.js +0 -11
  158. package/dist/content/stages/plan.d.ts +0 -2
  159. package/dist/content/stages/plan.js +0 -191
  160. package/dist/content/stages/review.d.ts +0 -2
  161. package/dist/content/stages/review.js +0 -240
  162. package/dist/content/stages/schema-types.d.ts +0 -203
  163. package/dist/content/stages/schema-types.js +0 -1
  164. package/dist/content/stages/scope.d.ts +0 -2
  165. package/dist/content/stages/scope.js +0 -254
  166. package/dist/content/stages/ship.d.ts +0 -2
  167. package/dist/content/stages/ship.js +0 -159
  168. package/dist/content/stages/spec.d.ts +0 -2
  169. package/dist/content/stages/spec.js +0 -170
  170. package/dist/content/stages/tdd.d.ts +0 -4
  171. package/dist/content/stages/tdd.js +0 -273
  172. package/dist/content/state-contracts.d.ts +0 -1
  173. package/dist/content/state-contracts.js +0 -63
  174. package/dist/content/status-command.d.ts +0 -4
  175. package/dist/content/status-command.js +0 -109
  176. package/dist/content/subagent-context-skills.d.ts +0 -4
  177. package/dist/content/subagent-context-skills.js +0 -279
  178. package/dist/content/subagents.d.ts +0 -3
  179. package/dist/content/subagents.js +0 -997
  180. package/dist/content/templates.d.ts +0 -26
  181. package/dist/content/templates.js +0 -1692
  182. package/dist/content/track-render-context.d.ts +0 -18
  183. package/dist/content/track-render-context.js +0 -53
  184. package/dist/content/tree-command.d.ts +0 -1
  185. package/dist/content/tree-command.js +0 -64
  186. package/dist/content/utility-skills.d.ts +0 -30
  187. package/dist/content/utility-skills.js +0 -160
  188. package/dist/content/view-command.d.ts +0 -2
  189. package/dist/content/view-command.js +0 -92
  190. package/dist/delegation.d.ts +0 -649
  191. package/dist/delegation.js +0 -1539
  192. package/dist/early-loop.d.ts +0 -70
  193. package/dist/early-loop.js +0 -302
  194. package/dist/execution-topology.d.ts +0 -44
  195. package/dist/execution-topology.js +0 -95
  196. package/dist/gate-evidence.d.ts +0 -85
  197. package/dist/gate-evidence.js +0 -631
  198. package/dist/harness-adapters.d.ts +0 -151
  199. package/dist/harness-adapters.js +0 -756
  200. package/dist/harness-selection.d.ts +0 -31
  201. package/dist/harness-selection.js +0 -214
  202. package/dist/hook-schema.d.ts +0 -6
  203. package/dist/hook-schema.js +0 -114
  204. package/dist/hook-schemas/claude-hooks.v1.json +0 -10
  205. package/dist/hook-schemas/codex-hooks.v1.json +0 -10
  206. package/dist/hook-schemas/cursor-hooks.v1.json +0 -13
  207. package/dist/init-detect.d.ts +0 -2
  208. package/dist/init-detect.js +0 -50
  209. package/dist/internal/advance-stage/advance.d.ts +0 -89
  210. package/dist/internal/advance-stage/advance.js +0 -655
  211. package/dist/internal/advance-stage/cancel-run.d.ts +0 -8
  212. package/dist/internal/advance-stage/cancel-run.js +0 -19
  213. package/dist/internal/advance-stage/flow-state-coercion.d.ts +0 -3
  214. package/dist/internal/advance-stage/flow-state-coercion.js +0 -81
  215. package/dist/internal/advance-stage/helpers.d.ts +0 -14
  216. package/dist/internal/advance-stage/helpers.js +0 -145
  217. package/dist/internal/advance-stage/hook.d.ts +0 -8
  218. package/dist/internal/advance-stage/hook.js +0 -40
  219. package/dist/internal/advance-stage/parsers.d.ts +0 -72
  220. package/dist/internal/advance-stage/parsers.js +0 -357
  221. package/dist/internal/advance-stage/proactive-delegation-trace.d.ts +0 -24
  222. package/dist/internal/advance-stage/proactive-delegation-trace.js +0 -56
  223. package/dist/internal/advance-stage/review-loop.d.ts +0 -16
  224. package/dist/internal/advance-stage/review-loop.js +0 -199
  225. package/dist/internal/advance-stage/rewind.d.ts +0 -14
  226. package/dist/internal/advance-stage/rewind.js +0 -108
  227. package/dist/internal/advance-stage/start-flow.d.ts +0 -13
  228. package/dist/internal/advance-stage/start-flow.js +0 -241
  229. package/dist/internal/advance-stage/verify.d.ts +0 -21
  230. package/dist/internal/advance-stage/verify.js +0 -185
  231. package/dist/internal/advance-stage.d.ts +0 -7
  232. package/dist/internal/advance-stage.js +0 -138
  233. package/dist/internal/cohesion-contract-stub.d.ts +0 -24
  234. package/dist/internal/cohesion-contract-stub.js +0 -148
  235. package/dist/internal/compound-readiness.d.ts +0 -23
  236. package/dist/internal/compound-readiness.js +0 -102
  237. package/dist/internal/detect-public-api-changes.d.ts +0 -5
  238. package/dist/internal/detect-public-api-changes.js +0 -45
  239. package/dist/internal/detect-supply-chain-changes.d.ts +0 -6
  240. package/dist/internal/detect-supply-chain-changes.js +0 -138
  241. package/dist/internal/early-loop-status.d.ts +0 -7
  242. package/dist/internal/early-loop-status.js +0 -93
  243. package/dist/internal/envelope-validate.d.ts +0 -7
  244. package/dist/internal/envelope-validate.js +0 -66
  245. package/dist/internal/flow-state-repair.d.ts +0 -20
  246. package/dist/internal/flow-state-repair.js +0 -104
  247. package/dist/internal/plan-split-waves.d.ts +0 -190
  248. package/dist/internal/plan-split-waves.js +0 -764
  249. package/dist/internal/runtime-integrity.d.ts +0 -7
  250. package/dist/internal/runtime-integrity.js +0 -268
  251. package/dist/internal/slice-commit.d.ts +0 -7
  252. package/dist/internal/slice-commit.js +0 -619
  253. package/dist/internal/tdd-loop-status.d.ts +0 -14
  254. package/dist/internal/tdd-loop-status.js +0 -68
  255. package/dist/internal/tdd-red-evidence.d.ts +0 -7
  256. package/dist/internal/tdd-red-evidence.js +0 -153
  257. package/dist/internal/waiver-grant.d.ts +0 -62
  258. package/dist/internal/waiver-grant.js +0 -294
  259. package/dist/internal/wave-status.d.ts +0 -74
  260. package/dist/internal/wave-status.js +0 -506
  261. package/dist/managed-resources.d.ts +0 -53
  262. package/dist/managed-resources.js +0 -313
  263. package/dist/policy.d.ts +0 -10
  264. package/dist/policy.js +0 -167
  265. package/dist/retro-gate.d.ts +0 -9
  266. package/dist/retro-gate.js +0 -47
  267. package/dist/run-archive.d.ts +0 -61
  268. package/dist/run-archive.js +0 -391
  269. package/dist/runs.d.ts +0 -2
  270. package/dist/runs.js +0 -2
  271. package/dist/stack-detection.d.ts +0 -116
  272. package/dist/stack-detection.js +0 -489
  273. package/dist/streaming/event-stream.d.ts +0 -31
  274. package/dist/streaming/event-stream.js +0 -114
  275. package/dist/tdd-cycle.d.ts +0 -107
  276. package/dist/tdd-cycle.js +0 -289
  277. package/dist/tdd-verification-evidence.d.ts +0 -17
  278. package/dist/tdd-verification-evidence.js +0 -122
  279. package/dist/track-heuristics.d.ts +0 -27
  280. package/dist/track-heuristics.js +0 -154
  281. package/dist/util/slice-id.d.ts +0 -58
  282. package/dist/util/slice-id.js +0 -89
  283. package/dist/worktree-manager.d.ts +0 -20
  284. 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>;