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,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;