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,444 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- import { resolveArtifactPath as resolveStageArtifactPath } from "../artifact-paths.js";
4
- import { exists } from "../fs-utils.js";
5
- import { CONFIDENCE_FINDING_REGEX_SOURCE } from "../content/skills.js";
6
- import { checkCriticPredictionsContract, evaluateInvestigationTrace, evaluateLayeredDocumentReviewStatus, evaluateQaLogFloor, extractMarkdownSectionBody, getMarkdownTableRows, meaningfulLineCount, sectionBodyByName, markdownFieldRegex } from "./shared.js";
7
- const DESIGN_DIAGRAM_REQUIREMENTS = {
8
- lightweight: [
9
- {
10
- section: "Architecture Diagram",
11
- markers: ["architecture"],
12
- note: "Architecture diagram is required for all tiers."
13
- }
14
- ],
15
- standard: [
16
- {
17
- section: "Architecture Diagram",
18
- markers: ["architecture"],
19
- note: "Architecture diagram is required for all tiers."
20
- },
21
- {
22
- section: "Data-Flow Shadow Paths",
23
- markers: ["data-flow-shadow-paths"],
24
- note: "Standard+ requires data-flow shadow path coverage."
25
- },
26
- {
27
- section: "Error Flow Diagram",
28
- markers: ["error-flow"],
29
- note: "Standard+ requires explicit error-flow rescue mapping."
30
- }
31
- ],
32
- deep: [
33
- {
34
- section: "Architecture Diagram",
35
- markers: ["architecture"],
36
- note: "Architecture diagram is required for all tiers."
37
- },
38
- {
39
- section: "Data-Flow Shadow Paths",
40
- markers: ["data-flow-shadow-paths"],
41
- note: "Standard+ requires data-flow shadow path coverage."
42
- },
43
- {
44
- section: "Error Flow Diagram",
45
- markers: ["error-flow"],
46
- note: "Standard+ requires explicit error-flow rescue mapping."
47
- },
48
- {
49
- section: "Deep Diagram Add-on",
50
- markers: ["state-machine", "rollback-flowchart", "deployment-sequence"],
51
- note: "Deep tier requires one add-on deep diagram (state machine, rollback flowchart, or deployment sequence)."
52
- }
53
- ]
54
- };
55
- function normalizeDesignDiagramTier(value) {
56
- if (!value)
57
- return null;
58
- const normalized = value.trim().toLowerCase();
59
- if (/^(?:lite|light|lightweight)$/u.test(normalized))
60
- return "lightweight";
61
- if (/^standard$/u.test(normalized))
62
- return "standard";
63
- if (/^deep$/u.test(normalized))
64
- return "deep";
65
- return null;
66
- }
67
- function parseApproachTierSection(sectionBody) {
68
- if (!sectionBody)
69
- return null;
70
- for (const line of sectionBody.split(/\r?\n/u)) {
71
- const cleaned = line.replace(/[*_`]/gu, "").trim();
72
- const directMatch = /(?:^|\b)tier\s*:\s*(lite|lightweight|light|standard|deep)\b/iu.exec(cleaned);
73
- if (directMatch) {
74
- const captured = directMatch[1] ?? "";
75
- const remainder = cleaned.slice(cleaned.toLowerCase().indexOf("tier") + 4);
76
- const tierTokens = remainder.match(/\b(?:lite|lightweight|light|standard|deep)\b/giu) ?? [];
77
- const distinct = new Set(tierTokens.map((token) => token.toLowerCase()));
78
- if (distinct.size >= 2) {
79
- // Multi-token line is the unfilled template placeholder
80
- // (`Tier: lite | standard | deep`); treat as no decision.
81
- continue;
82
- }
83
- return normalizeDesignDiagramTier(captured);
84
- }
85
- }
86
- const token = /\b(lite|lightweight|light|standard|deep)\b/iu.exec(sectionBody)?.[1] ?? null;
87
- return normalizeDesignDiagramTier(token);
88
- }
89
- async function resolveDesignDiagramTier(projectRoot, track, designRaw) {
90
- const fromDesign = parseApproachTierSection(extractMarkdownSectionBody(designRaw, "Approach Tier"));
91
- if (fromDesign) {
92
- return { tier: fromDesign, source: "design-artifact:Approach Tier" };
93
- }
94
- try {
95
- const brainstormArtifact = await resolveStageArtifactPath("brainstorm", {
96
- projectRoot,
97
- track,
98
- intent: "read"
99
- });
100
- if (await exists(brainstormArtifact.absPath)) {
101
- const brainstormRaw = await fs.readFile(brainstormArtifact.absPath, "utf8");
102
- const fromBrainstorm = parseApproachTierSection(extractMarkdownSectionBody(brainstormRaw, "Approach Tier"));
103
- if (fromBrainstorm) {
104
- return { tier: fromBrainstorm, source: "brainstorm-artifact:Approach Tier" };
105
- }
106
- }
107
- }
108
- catch {
109
- // Ignore read/resolve errors and fall back to default tier.
110
- }
111
- return { tier: "standard", source: "default:standard" };
112
- }
113
- /**
114
- * parenthetical suffixes that the audit strips
115
- * from a Codebase Investigation filename cell BEFORE attempting
116
- * `fs.stat`. The user's quick-tier test wrote `index.html (new)` in
117
- * the table, and the linter then tried to stat the literal string
118
- * `index.html (new)` (with the suffix) and failed with "could not
119
- * read blast-radius file(s): index.html (new)". Authors used these
120
- * markers as informational labels, not as part of the filename.
121
- *
122
- * Stripping happens for ANY parenthetical suffix on the same line as
123
- * the filename cell so we don't have to enumerate every author
124
- * convention. For new files (suffix "new"), the audit records
125
- * "new file, no stale diagrams to detect" instead of trying to stat.
126
- */
127
- const STALE_DIAGRAM_NEW_FILE_SUFFIX_PATTERN = /\(\s*new(?:[\s-]?file)?\s*\)/iu;
128
- const STALE_DIAGRAM_SKIP_FILE_SUFFIX_PATTERN = /\(\s*(?:n\/a|skip|skipped|deleted|removed|stub|placeholder|tbd)\s*\)/iu;
129
- export function normalizeCodebaseInvestigationFileRef(value, notesCell) {
130
- const cleanedFull = value
131
- .replace(/`/gu, "")
132
- .replace(/^\s*[-*]\s*/u, "")
133
- .trim();
134
- if (!cleanedFull)
135
- return null;
136
- if (/^#/u.test(cleanedFull)) {
137
- return { filename: cleanedFull.replace(/^#\s*/u, ""), raw: cleanedFull, newFile: false, skip: true };
138
- }
139
- // Strip ANY trailing parenthetical suffix(es) so the audit operates
140
- // on the raw filename. We loop because authors sometimes stack
141
- // multiple suffixes (`index.html (new) (stub)`).
142
- let stripped = cleanedFull;
143
- let newFile = false;
144
- let skip = false;
145
- for (let safety = 0; safety < 4; safety += 1) {
146
- const trailingParen = /\s*\([^)]*\)\s*$/u.exec(stripped);
147
- if (!trailingParen)
148
- break;
149
- const parenText = trailingParen[0];
150
- if (STALE_DIAGRAM_NEW_FILE_SUFFIX_PATTERN.test(parenText))
151
- newFile = true;
152
- if (STALE_DIAGRAM_SKIP_FILE_SUFFIX_PATTERN.test(parenText))
153
- skip = true;
154
- stripped = stripped.slice(0, trailingParen.index).trim();
155
- }
156
- if (!stripped)
157
- return null;
158
- if (/^(?:file|n\/a|none|\(none\)|tbd|\?)$/iu.test(stripped))
159
- return null;
160
- // Notes column may carry an explicit `skip:` marker.
161
- if (/(?:^|\s|\|)skip\s*:/iu.test(notesCell))
162
- skip = true;
163
- return { filename: stripped, raw: cleanedFull, newFile, skip };
164
- }
165
- export function collectCodebaseInvestigationFiles(sectionBody) {
166
- const refs = [];
167
- const seen = new Set();
168
- for (const row of getMarkdownTableRows(sectionBody)) {
169
- const notesCell = row[row.length - 1] ?? "";
170
- const fileCell = normalizeCodebaseInvestigationFileRef(row[0] ?? "", notesCell);
171
- if (!fileCell)
172
- continue;
173
- const key = `${fileCell.filename}|${fileCell.skip}|${fileCell.newFile}`;
174
- if (seen.has(key))
175
- continue;
176
- seen.add(key);
177
- refs.push(fileCell);
178
- }
179
- return refs;
180
- }
181
- async function runStaleDiagramAudit(projectRoot, artifactPath, artifactRaw, codebaseInvestigationBody) {
182
- const markerCount = (artifactRaw.match(/<!--\s*diagram:\s*[a-z0-9-]+\s*-->/giu) ?? []).length;
183
- if (markerCount === 0) {
184
- return {
185
- ok: false,
186
- details: "No diagram markers found in design artifact; stale-diagram baseline cannot be computed."
187
- };
188
- }
189
- let artifactStat;
190
- try {
191
- artifactStat = await fs.stat(artifactPath);
192
- }
193
- catch {
194
- return {
195
- ok: false,
196
- details: "Cannot stat design artifact to compute diagram marker baseline."
197
- };
198
- }
199
- const refs = collectCodebaseInvestigationFiles(codebaseInvestigationBody);
200
- if (refs.length === 0) {
201
- return {
202
- ok: false,
203
- details: "Codebase Investigation must list at least one blast-radius file for stale-diagram audit."
204
- };
205
- }
206
- const stale = [];
207
- const missing = [];
208
- const newFiles = [];
209
- const skipped = [];
210
- let scanned = 0;
211
- for (const ref of refs) {
212
- if (ref.skip) {
213
- skipped.push(ref.filename);
214
- continue;
215
- }
216
- if (ref.newFile) {
217
- newFiles.push(ref.filename);
218
- continue;
219
- }
220
- const absPath = path.isAbsolute(ref.filename) ? ref.filename : path.join(projectRoot, ref.filename);
221
- if (!(await exists(absPath))) {
222
- missing.push(ref.filename);
223
- continue;
224
- }
225
- let fileStat;
226
- try {
227
- fileStat = await fs.stat(absPath);
228
- }
229
- catch {
230
- missing.push(ref.filename);
231
- continue;
232
- }
233
- if (!fileStat.isFile())
234
- continue;
235
- scanned += 1;
236
- if (fileStat.mtimeMs > artifactStat.mtimeMs) {
237
- stale.push(ref.filename);
238
- }
239
- }
240
- if (missing.length > 0) {
241
- return {
242
- ok: false,
243
- details: `Stale Diagram Audit could not read blast-radius file(s): ${missing.join(", ")}. Strip parenthetical suffixes like \` (new)\`, \` (deleted)\`, \` (stub)\` from the filename column, mark new files as \`<path> (new)\`, or add a leading \`#\` to the filename to skip the row.`
244
- };
245
- }
246
- const noteParts = [];
247
- if (skipped.length > 0)
248
- noteParts.push(`${skipped.length} skipped (${skipped.join(", ")})`);
249
- if (newFiles.length > 0)
250
- noteParts.push(`${newFiles.length} new file(s) with no stale diagrams to detect (${newFiles.join(", ")})`);
251
- const notes = noteParts.length > 0 ? `; ${noteParts.join("; ")}` : "";
252
- if (scanned === 0 && newFiles.length === 0 && skipped.length === 0) {
253
- return {
254
- ok: false,
255
- details: "Stale Diagram Audit found no readable blast-radius files in Codebase Investigation."
256
- };
257
- }
258
- if (stale.length > 0) {
259
- return {
260
- ok: false,
261
- details: `Stale Diagram Audit flagged stale file(s) newer than diagram baseline: ${stale.join(", ")}${notes}.`
262
- };
263
- }
264
- return {
265
- ok: true,
266
- details: `Stale Diagram Audit clear: ${scanned} blast-radius file(s) are not newer than diagram baseline${notes}.`
267
- };
268
- }
269
- export async function lintDesignStage(ctx) {
270
- const { projectRoot, track, raw, absFile, sections, findings, parsedFrontmatter, brainstormShortCircuitBody, brainstormShortCircuitActivated, staleDiagramAuditEnabled, isTrivialOverride, activeStageFlags } = ctx;
271
- evaluateInvestigationTrace(ctx, "Codebase Investigation");
272
- const qaLogBody = sectionBodyByName(sections, "Q&A Log");
273
- const qaLogRows = qaLogBody ? getMarkdownTableRows(qaLogBody) : [];
274
- const qaLogOk = qaLogBody !== null && qaLogRows.length > 0;
275
- findings.push({
276
- section: "qa_log_missing",
277
- required: false,
278
- rule: "[P2] qa_log_missing — Q&A Log empty — confirm you actually had a dialogue with the user, not a draft from memory.",
279
- found: qaLogOk,
280
- details: qaLogOk
281
- ? `Q&A Log contains ${qaLogRows.length} data row(s).`
282
- : qaLogBody === null
283
- ? "Missing `## Q&A Log` section."
284
- : "Q&A Log is present but has zero data rows."
285
- });
286
- {
287
- const skipQuestions = activeStageFlags.includes("--skip-questions");
288
- const floor = evaluateQaLogFloor(qaLogBody, track, "design", { discoveryMode: ctx.discoveryMode, skipQuestions });
289
- findings.push({
290
- section: "qa_log_unconverged",
291
- required: !floor.skipQuestionsAdvisory,
292
- 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.",
293
- found: floor.ok,
294
- details: floor.details
295
- });
296
- }
297
- const criticPredictions = checkCriticPredictionsContract(sections);
298
- if (criticPredictions !== null) {
299
- findings.push({
300
- section: "critic.predictions_missing",
301
- required: false,
302
- rule: "[P2] critic.predictions_missing — pre-commitment predictions block missing or empty",
303
- found: criticPredictions.found,
304
- details: criticPredictions.details
305
- });
306
- }
307
- const tierResolution = await resolveDesignDiagramTier(projectRoot, track, raw);
308
- const diagramTier = isTrivialOverride
309
- ? "lightweight"
310
- : tierResolution.tier;
311
- const tierSource = isTrivialOverride
312
- ? `${tierResolution.source}; trivial override forced lightweight`
313
- : tierResolution.source;
314
- const hasDiagramMarkers = /<!--\s*diagram:\s*[a-z0-9-]+\s*-->/iu.test(raw);
315
- const skipDiagramRequirements = isTrivialOverride && !hasDiagramMarkers;
316
- if (skipDiagramRequirements) {
317
- findings.push({
318
- section: "Diagram Requirement: Architecture Diagram",
319
- required: true,
320
- rule: "Compact trivial-override slices may omit architecture diagram markers when they intentionally skip diagram work.",
321
- found: true,
322
- details: "Diagram requirement skipped: compact trivial-override slice without diagram markers."
323
- });
324
- }
325
- else {
326
- for (const requirement of DESIGN_DIAGRAM_REQUIREMENTS[diagramTier]) {
327
- const sectionBody = sectionBodyByName(sections, requirement.section);
328
- const hasSection = sectionBody !== null;
329
- const matchedMarker = requirement.markers.find((marker) => {
330
- const escapedMarker = marker.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
331
- const markerRegex = new RegExp(`<!--\\s*diagram:\\s*${escapedMarker}\\s*-->`, "iu");
332
- return sectionBody !== null && markerRegex.test(sectionBody);
333
- });
334
- const hasMarker = matchedMarker !== undefined;
335
- const hasContent = sectionBody !== null && meaningfulLineCount(sectionBody) > 0;
336
- const found = hasSection && hasMarker && hasContent;
337
- const markerList = requirement.markers.map((marker) => `<!-- diagram: ${marker} -->`).join(" or ");
338
- findings.push({
339
- section: `Diagram Requirement: ${requirement.section}`,
340
- required: true,
341
- rule: `Design tier "${diagramTier}" requires "${requirement.section}" with marker ${markerList}. ${requirement.note}`,
342
- found,
343
- details: found
344
- ? `Satisfied (${tierSource}).`
345
- : !hasSection
346
- ? `Missing section "${requirement.section}" (${tierSource}).`
347
- : !hasMarker
348
- ? `Missing marker (${markerList}) in section "${requirement.section}" (${tierSource}).`
349
- : `Section "${requirement.section}" has marker but no meaningful content (${tierSource}).`
350
- });
351
- }
352
- }
353
- if (staleDiagramAuditEnabled) {
354
- if (isTrivialOverride && !hasDiagramMarkers) {
355
- findings.push({
356
- section: "Stale Diagram Drift Check",
357
- required: true,
358
- rule: "When stale-diagram audit is enabled, compact trivial-override slices may skip the drift check only if no design diagram markers are present.",
359
- found: true,
360
- details: "Stale Diagram Audit skipped: artifact has no diagram markers (compact trivial-override slice)."
361
- });
362
- }
363
- else {
364
- const codebaseInvestigation = sectionBodyByName(sections, "Codebase Investigation");
365
- if (codebaseInvestigation === null) {
366
- findings.push({
367
- section: "Stale Diagram Drift Check",
368
- required: true,
369
- rule: "When stale-diagram audit is enabled, stale diagram audit requires Codebase Investigation blast-radius files.",
370
- found: false,
371
- details: "No ## heading matching required section \"Codebase Investigation\"."
372
- });
373
- }
374
- else {
375
- const staleAudit = await runStaleDiagramAudit(projectRoot, absFile, raw, codebaseInvestigation);
376
- findings.push({
377
- section: "Stale Diagram Drift Check",
378
- required: true,
379
- rule: "When stale-diagram audit is enabled, blast-radius files must not be newer than current design diagram baseline.",
380
- found: staleAudit.ok,
381
- details: staleAudit.details
382
- });
383
- }
384
- }
385
- }
386
- // Universal Layer 2.3 structural checks (gstack plan-eng-review). All
387
- // present-only. Validates regression iron-rule acknowledgment and
388
- // confidence-calibrated finding format.
389
- const regressionBody = sectionBodyByName(sections, "Regression Iron Rule");
390
- if (regressionBody !== null) {
391
- const ack = markdownFieldRegex("Iron rule acknowledged", "yes|true|y").test(regressionBody);
392
- findings.push({
393
- section: "Regression Iron Rule Acknowledgement",
394
- required: false,
395
- rule: "Regression Iron Rule section must affirm `Iron rule acknowledged: yes`.",
396
- found: ack,
397
- details: ack
398
- ? "Regression iron rule acknowledged."
399
- : "Regression Iron Rule is missing explicit `Iron rule acknowledged: yes`."
400
- });
401
- }
402
- const findingsBody = sectionBodyByName(sections, "Calibrated Findings");
403
- if (findingsBody !== null) {
404
- const isEmpty = /(^|\n)\s*-\s*None this stage\b/iu.test(findingsBody);
405
- const findingRegex = new RegExp(CONFIDENCE_FINDING_REGEX_SOURCE, "u");
406
- const validRows = findingsBody
407
- .split("\n")
408
- .filter((line) => /^[-*]\s+\[/u.test(line.trim()))
409
- .filter((line) => findingRegex.test(line));
410
- const ok = isEmpty || validRows.length >= 1;
411
- findings.push({
412
- section: "Calibrated Finding Format",
413
- required: false,
414
- rule: "Calibrated Findings must either declare `None this stage` or contain at least one finding in the form `[P1|P2|P3] (confidence: <n>/10) <path>[:<line>] — <description>`.",
415
- found: ok,
416
- details: isEmpty
417
- ? "No findings recorded for this stage."
418
- : ok
419
- ? `Detected ${validRows.length} calibrated finding(s).`
420
- : "No calibrated findings detected. Use `[P1|P2|P3] (confidence: <n>/10) <repo-path>[:<line>] — <description>`."
421
- });
422
- }
423
- const layeredDocumentReview = evaluateLayeredDocumentReviewStatus(sections, CONFIDENCE_FINDING_REGEX_SOURCE);
424
- if (layeredDocumentReview !== null) {
425
- findings.push({
426
- section: "Document Reviewer Structured Findings",
427
- required: true,
428
- rule: "When Layered review references coherence-reviewer/scope-guardian-reviewer/feasibility-reviewer, include explicit reviewer status plus calibrated finding lines.",
429
- found: layeredDocumentReview.missingStructured.length === 0,
430
- details: layeredDocumentReview.missingStructured.length === 0
431
- ? `Structured findings present for reviewers: ${layeredDocumentReview.triggeredReviewers.join(", ")}.`
432
- : `Missing status or calibrated findings for: ${layeredDocumentReview.missingStructured.join(", ")}.`
433
- });
434
- findings.push({
435
- section: "document-review.fail_without_waiver",
436
- required: true,
437
- rule: "[P1] document-review.fail_without_waiver — reviewer FAIL/PARTIAL requires fix evidence or explicit waiver.",
438
- found: layeredDocumentReview.failOrPartialWithoutWaiver.length === 0,
439
- details: layeredDocumentReview.failOrPartialWithoutWaiver.length === 0
440
- ? "No unwaived FAIL/PARTIAL reviewer statuses detected."
441
- : `Unwaived FAIL/PARTIAL statuses: ${layeredDocumentReview.failOrPartialWithoutWaiver.join(", ")}.`
442
- });
443
- }
444
- }
@@ -1,56 +0,0 @@
1
- import type { FlowStage } from "../types.js";
2
- import type { LintFinding } from "./shared.js";
3
- export declare const FINDINGS_CACHE_SCHEMA_VERSION = 1;
4
- export type FindingStatus = {
5
- kind: "new";
6
- } | {
7
- kind: "repeat";
8
- count: number;
9
- } | {
10
- kind: "resolved";
11
- };
12
- export interface ClassifiedFinding {
13
- finding: LintFinding;
14
- fingerprint: string;
15
- status: FindingStatus;
16
- }
17
- export interface ResolvedFinding {
18
- fingerprint: string;
19
- rule: string;
20
- lastSeenAt: string;
21
- }
22
- export interface FindingsDedupSummary {
23
- newCount: number;
24
- repeatCount: number;
25
- resolvedCount: number;
26
- resolved: ResolvedFinding[];
27
- }
28
- export interface LintRunDedupResult {
29
- classified: ClassifiedFinding[];
30
- summary: FindingsDedupSummary;
31
- header: string;
32
- }
33
- /**
34
- * Normalize a finding detail string so volatile tokens (run IDs,
35
- * timestamps, counts, hex hashes, temp paths) don't cause a finding
36
- * to appear "new" on every invocation.
37
- */
38
- export declare function normalizeFindingDetail(detail: string): string;
39
- export declare function fingerprintFinding(stage: FlowStage, finding: LintFinding): string;
40
- /**
41
- * Classify each emitted finding as `new`, `repeat:N`, or `resolved`
42
- * relative to the cached sidecar for this stage. Persists the updated
43
- * fingerprint set under a directory lock so concurrent lint runs for
44
- * the same project don't clobber each other.
45
- *
46
- * The returned `header` is a short human string intended for inclusion
47
- * above the linter output; it's stable across runs when findings
48
- * repeat. Empty string when there is nothing meaningful to report
49
- * (no findings and no carry-over state).
50
- */
51
- export declare function classifyAndPersistFindings(projectRoot: string, stage: FlowStage, findings: LintFinding[], options?: {
52
- now?: Date;
53
- }): Promise<LintRunDedupResult>;
54
- export declare function buildDedupHeader(stage: FlowStage, summary: FindingsDedupSummary): string;
55
- export declare function formatFindingStatusTag(status: FindingStatus): string;
56
- export declare function findingsDedupCachePathFor(projectRoot: string): string;