mandrel 2.60.0 → 2.61.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 (661) hide show
  1. package/.agents/README.md +10 -10
  2. package/.agents/agents/story-worker.md +1 -1
  3. package/.agents/docs/agentrc-reference.json +4 -82
  4. package/.agents/docs/configuration.md +20 -87
  5. package/.agents/docs/workflows.md +1 -1
  6. package/.agents/instructions.md +1 -3
  7. package/.agents/rules/gherkin-standards.md +4 -0
  8. package/.agents/schemas/agentrc.schema.json +11 -486
  9. package/.agents/schemas/story-deliver-terminal.schema.json +10 -0
  10. package/.agents/schemas/validation-evidence.schema.json +2 -1
  11. package/.agents/scripts/README.md +14 -14
  12. package/.agents/scripts/acceptance-eval.js +32 -164
  13. package/.agents/scripts/agents-bootstrap-github.js +27 -129
  14. package/.agents/scripts/apply-quality-bootstrap.js +4 -40
  15. package/.agents/scripts/audit-baselines.js +6 -27
  16. package/.agents/scripts/audit-labels-bootstrap.js +5 -29
  17. package/.agents/scripts/audit-to-stories.js +91 -361
  18. package/.agents/scripts/boot-sweep.js +19 -72
  19. package/.agents/scripts/bootstrap.js +74 -395
  20. package/.agents/scripts/ceremony-derive.js +9 -45
  21. package/.agents/scripts/check-arch-cycles.js +14 -64
  22. package/.agents/scripts/check-baselines.js +8 -48
  23. package/.agents/scripts/check-context-budget.js +46 -172
  24. package/.agents/scripts/check-cyclomatic.js +12 -44
  25. package/.agents/scripts/check-dead-exports.js +13 -64
  26. package/.agents/scripts/check-doc-links.js +38 -186
  27. package/.agents/scripts/check-gherkin-corpus.js +24 -127
  28. package/.agents/scripts/check-test-temp-hygiene.js +28 -169
  29. package/.agents/scripts/coverage-capture.js +32 -99
  30. package/.agents/scripts/deliver-light.js +14 -101
  31. package/.agents/scripts/deliver-recover.js +6 -42
  32. package/.agents/scripts/deliver-run.js +36 -133
  33. package/.agents/scripts/diagnose-friction.js +24 -116
  34. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  35. package/.agents/scripts/evidence-gate.js +23 -85
  36. package/.agents/scripts/file-ci-gap.js +10 -50
  37. package/.agents/scripts/generate-config-docs.js +30 -170
  38. package/.agents/scripts/generate-lens-checklists.js +8 -52
  39. package/.agents/scripts/generate-skills-index.js +14 -112
  40. package/.agents/scripts/generate-workflows-doc.js +10 -70
  41. package/.agents/scripts/git-cleanup.js +2 -34
  42. package/.agents/scripts/lib/Graph.js +24 -81
  43. package/.agents/scripts/lib/ITicketingProvider.js +47 -143
  44. package/.agents/scripts/lib/Logger.js +14 -76
  45. package/.agents/scripts/lib/audit-baselines/engine.js +11 -31
  46. package/.agents/scripts/lib/audit-baselines/gate-surface.js +3 -17
  47. package/.agents/scripts/lib/audit-baselines/headroom.js +4 -20
  48. package/.agents/scripts/lib/audit-baselines/hotspots.js +3 -15
  49. package/.agents/scripts/lib/audit-baselines/kinds.js +23 -89
  50. package/.agents/scripts/lib/audit-baselines/outliers.js +6 -23
  51. package/.agents/scripts/lib/audit-baselines/read.js +3 -16
  52. package/.agents/scripts/lib/audit-baselines/staleness.js +7 -26
  53. package/.agents/scripts/lib/audit-baselines/surface-entry.js +7 -28
  54. package/.agents/scripts/lib/audit-baselines/trend.js +7 -20
  55. package/.agents/scripts/lib/audit-baselines/weights.js +9 -37
  56. package/.agents/scripts/lib/audit-suite/audit-rules-reader.js +3 -18
  57. package/.agents/scripts/lib/audit-suite/checklist-threading.js +26 -124
  58. package/.agents/scripts/lib/audit-suite/dispatch-checklist.js +14 -45
  59. package/.agents/scripts/lib/audit-suite/findings.js +12 -52
  60. package/.agents/scripts/lib/audit-suite/frontmatter.js +5 -29
  61. package/.agents/scripts/lib/audit-suite/index.js +1 -15
  62. package/.agents/scripts/lib/audit-suite/lens-checklist.js +10 -45
  63. package/.agents/scripts/lib/audit-suite/lens-diff-floor.js +11 -76
  64. package/.agents/scripts/lib/audit-suite/runner.js +13 -43
  65. package/.agents/scripts/lib/audit-suite/selector.js +49 -349
  66. package/.agents/scripts/lib/audit-suite/substitutions.js +12 -40
  67. package/.agents/scripts/lib/audit-suite/workflow-loader.js +3 -15
  68. package/.agents/scripts/lib/audit-to-stories/audit-label-taxonomy.js +11 -73
  69. package/.agents/scripts/lib/audit-to-stories/audit-lenses.js +8 -37
  70. package/.agents/scripts/lib/audit-to-stories/build-story-body.js +25 -143
  71. package/.agents/scripts/lib/audit-to-stories/dedupe-against-github.js +14 -80
  72. package/.agents/scripts/lib/audit-to-stories/epic-grouping-directive.js +4 -18
  73. package/.agents/scripts/lib/audit-to-stories/finding-adapter.js +7 -40
  74. package/.agents/scripts/lib/audit-to-stories/group-findings.js +9 -39
  75. package/.agents/scripts/lib/audit-to-stories/issue-corpus.js +10 -66
  76. package/.agents/scripts/lib/audit-to-stories/issue-index.js +6 -30
  77. package/.agents/scripts/lib/audit-to-stories/issues-file.js +6 -36
  78. package/.agents/scripts/lib/audit-to-stories/ledger-commit.js +17 -69
  79. package/.agents/scripts/lib/audit-to-stories/ledger-pr.js +17 -85
  80. package/.agents/scripts/lib/audit-to-stories/ledger-record.js +10 -48
  81. package/.agents/scripts/lib/audit-to-stories/parse-audit-md.js +38 -146
  82. package/.agents/scripts/lib/audit-to-stories/seed-from-findings.js +7 -42
  83. package/.agents/scripts/lib/audit-to-stories/wire-dependencies.js +10 -57
  84. package/.agents/scripts/lib/baseline-loader.js +12 -51
  85. package/.agents/scripts/lib/baseline-schema-registry.js +5 -22
  86. package/.agents/scripts/lib/baselines/component-matcher.js +3 -12
  87. package/.agents/scripts/lib/baselines/components.js +10 -61
  88. package/.agents/scripts/lib/baselines/coverage-updater-cli.js +7 -36
  89. package/.agents/scripts/lib/baselines/crap-preview-incremental.js +5 -21
  90. package/.agents/scripts/lib/baselines/crap-preview-scan.js +19 -45
  91. package/.agents/scripts/lib/baselines/crap-updater-cli.js +16 -65
  92. package/.agents/scripts/lib/baselines/diff-scope-cli.js +5 -33
  93. package/.agents/scripts/lib/baselines/duplication-scanner.js +11 -60
  94. package/.agents/scripts/lib/baselines/env-overrides.js +12 -67
  95. package/.agents/scripts/lib/baselines/envelope.js +13 -129
  96. package/.agents/scripts/lib/baselines/exit-codes.js +6 -49
  97. package/.agents/scripts/lib/baselines/git-base.js +23 -142
  98. package/.agents/scripts/lib/baselines/kernel.js +11 -111
  99. package/.agents/scripts/lib/baselines/kinds/_crap-new-method-gate.js +9 -47
  100. package/.agents/scripts/lib/baselines/kinds/_crap-read.js +8 -51
  101. package/.agents/scripts/lib/baselines/kinds/_shared-metric.js +7 -62
  102. package/.agents/scripts/lib/baselines/kinds/bundle-size.js +8 -29
  103. package/.agents/scripts/lib/baselines/kinds/coverage.js +3 -15
  104. package/.agents/scripts/lib/baselines/kinds/crap.js +94 -415
  105. package/.agents/scripts/lib/baselines/kinds/duplication.js +4 -30
  106. package/.agents/scripts/lib/baselines/kinds/kind-factory.js +7 -53
  107. package/.agents/scripts/lib/baselines/kinds/maintainability.js +15 -80
  108. package/.agents/scripts/lib/baselines/kinds/mutation.js +12 -72
  109. package/.agents/scripts/lib/baselines/maintainability-baseline-io.js +4 -11
  110. package/.agents/scripts/lib/baselines/merge-envelopes.js +30 -146
  111. package/.agents/scripts/lib/baselines/path-canon.js +19 -128
  112. package/.agents/scripts/lib/baselines/preview-gates.js +8 -37
  113. package/.agents/scripts/lib/baselines/reader.js +14 -107
  114. package/.agents/scripts/lib/baselines/refresh-service.js +35 -252
  115. package/.agents/scripts/lib/baselines/scope.js +11 -135
  116. package/.agents/scripts/lib/baselines/writer.js +16 -149
  117. package/.agents/scripts/lib/bdd-runner-detect.js +18 -113
  118. package/.agents/scripts/lib/bdd-scenario-budget.js +9 -36
  119. package/.agents/scripts/lib/bdd-scenario-scanner.js +11 -73
  120. package/.agents/scripts/lib/bdd-step-index.js +26 -100
  121. package/.agents/scripts/lib/bootstrap/baseline-merge-driver.js +23 -103
  122. package/.agents/scripts/lib/bootstrap/branch-protection.js +2 -5
  123. package/.agents/scripts/lib/bootstrap/commit-push.js +12 -50
  124. package/.agents/scripts/lib/bootstrap/gh-preflight.js +14 -101
  125. package/.agents/scripts/lib/bootstrap/hitl-confirm.js +5 -30
  126. package/.agents/scripts/lib/bootstrap/install-ledger.js +17 -73
  127. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +17 -121
  128. package/.agents/scripts/lib/bootstrap/manifest.js +15 -86
  129. package/.agents/scripts/lib/bootstrap/merge-methods.js +4 -33
  130. package/.agents/scripts/lib/bootstrap/preflight.js +12 -61
  131. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +34 -235
  132. package/.agents/scripts/lib/bootstrap/prompt.js +21 -129
  133. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +27 -141
  134. package/.agents/scripts/lib/bootstrap/summary.js +1 -8
  135. package/.agents/scripts/lib/bootstrap/workflow-audit.js +11 -84
  136. package/.agents/scripts/lib/branch-name-guard.js +4 -23
  137. package/.agents/scripts/lib/changed-files.js +31 -143
  138. package/.agents/scripts/lib/checks/core-bare-clean.js +4 -24
  139. package/.agents/scripts/lib/checks/index.js +18 -101
  140. package/.agents/scripts/lib/checks/loop-health.js +11 -53
  141. package/.agents/scripts/lib/checks/state.js +16 -91
  142. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +10 -61
  143. package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +14 -83
  144. package/.agents/scripts/lib/child-exec.js +39 -108
  145. package/.agents/scripts/lib/cli/standard-args.js +9 -116
  146. package/.agents/scripts/lib/cli-args.js +31 -146
  147. package/.agents/scripts/lib/cli-usage.js +5 -27
  148. package/.agents/scripts/lib/cli-utils.js +2 -12
  149. package/.agents/scripts/lib/close-validation/commands.js +13 -76
  150. package/.agents/scripts/lib/close-validation/gates.js +92 -331
  151. package/.agents/scripts/lib/close-validation/process.js +121 -151
  152. package/.agents/scripts/lib/close-validation/projections/advisories.js +5 -31
  153. package/.agents/scripts/lib/close-validation/projections/crap.js +19 -67
  154. package/.agents/scripts/lib/close-validation/projections/head-sha.js +1 -17
  155. package/.agents/scripts/lib/close-validation/projections/inputs.js +4 -34
  156. package/.agents/scripts/lib/close-validation/projections/maintainability.js +11 -58
  157. package/.agents/scripts/lib/close-validation/runner.js +53 -110
  158. package/.agents/scripts/lib/command-header.js +6 -28
  159. package/.agents/scripts/lib/config/acceptance-eval.js +4 -30
  160. package/.agents/scripts/lib/config/baselines.js +3 -14
  161. package/.agents/scripts/lib/config/ci.js +8 -38
  162. package/.agents/scripts/lib/config/commands.js +1 -15
  163. package/.agents/scripts/lib/config/defaults.js +4 -33
  164. package/.agents/scripts/lib/config/delivery-routing.js +6 -35
  165. package/.agents/scripts/lib/config/explain.js +9 -80
  166. package/.agents/scripts/lib/config/gates/coverage.schema.js +0 -12
  167. package/.agents/scripts/lib/config/gates/crap-incremental-coverage.schema.js +2 -30
  168. package/.agents/scripts/lib/config/gates/crap.schema.js +1 -34
  169. package/.agents/scripts/lib/config/gates/duplication.schema.js +1 -8
  170. package/.agents/scripts/lib/config/gates/index.js +2 -17
  171. package/.agents/scripts/lib/config/gates/maintainability.schema.js +1 -20
  172. package/.agents/scripts/lib/config/gates/mutation.schema.js +1 -7
  173. package/.agents/scripts/lib/config/gates/shared.js +4 -64
  174. package/.agents/scripts/lib/config/github.js +4 -22
  175. package/.agents/scripts/lib/config/limits.js +4 -57
  176. package/.agents/scripts/lib/config/paths.js +2 -21
  177. package/.agents/scripts/lib/config/qa.js +4 -38
  178. package/.agents/scripts/lib/config/quality.js +76 -432
  179. package/.agents/scripts/lib/config/runners.js +12 -56
  180. package/.agents/scripts/lib/config/runtime.js +13 -57
  181. package/.agents/scripts/lib/config/shared.js +2 -16
  182. package/.agents/scripts/lib/config/sync-agentrc.js +9 -50
  183. package/.agents/scripts/lib/config/temp-paths.js +40 -280
  184. package/.agents/scripts/lib/config/validate-orchestration.js +5 -17
  185. package/.agents/scripts/lib/config/worktree-isolation.js +9 -28
  186. package/.agents/scripts/lib/config-resolver.js +10 -52
  187. package/.agents/scripts/lib/config-schema-shared.js +1 -4
  188. package/.agents/scripts/lib/config-settings-schema-delivery.js +12 -294
  189. package/.agents/scripts/lib/config-settings-schema-quality.js +7 -219
  190. package/.agents/scripts/lib/config-settings-schema.js +37 -274
  191. package/.agents/scripts/lib/coverage-baseline.js +20 -110
  192. package/.agents/scripts/lib/coverage-capture-fullscope.js +12 -37
  193. package/.agents/scripts/lib/coverage-capture-incremental.js +12 -43
  194. package/.agents/scripts/lib/coverage-capture-usage.js +4 -24
  195. package/.agents/scripts/lib/coverage-capture.js +99 -224
  196. package/.agents/scripts/lib/coverage-utils.js +14 -79
  197. package/.agents/scripts/lib/cpu-pool.js +17 -123
  198. package/.agents/scripts/lib/crap-baseline-join.js +16 -88
  199. package/.agents/scripts/lib/crap-coordinates.js +6 -25
  200. package/.agents/scripts/lib/crap-engine.js +40 -153
  201. package/.agents/scripts/lib/crap-method-identity.js +16 -78
  202. package/.agents/scripts/lib/crap-utils.js +31 -155
  203. package/.agents/scripts/lib/cyclomatic-ceiling.js +14 -87
  204. package/.agents/scripts/lib/cyclomatic-scope.js +10 -50
  205. package/.agents/scripts/lib/dead-exports-knip.js +18 -56
  206. package/.agents/scripts/lib/dead-exports-mode.js +5 -24
  207. package/.agents/scripts/lib/degraded-mode.js +3 -26
  208. package/.agents/scripts/lib/dependency-parser.js +8 -40
  209. package/.agents/scripts/lib/dependency-version.js +13 -35
  210. package/.agents/scripts/lib/detect-package-manager.js +6 -36
  211. package/.agents/scripts/lib/doc-tiers.js +22 -126
  212. package/.agents/scripts/lib/duplicate-search.js +8 -72
  213. package/.agents/scripts/lib/env-loader.js +5 -27
  214. package/.agents/scripts/lib/error-redactor.js +6 -31
  215. package/.agents/scripts/lib/errors/index.js +2 -22
  216. package/.agents/scripts/lib/escomplex-ast-compat.js +22 -163
  217. package/.agents/scripts/lib/escomplex-kernel.js +21 -123
  218. package/.agents/scripts/lib/feedback-loop/graduator-core.js +93 -419
  219. package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +20 -98
  220. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +27 -151
  221. package/.agents/scripts/lib/findings/audit-ledger.js +23 -97
  222. package/.agents/scripts/lib/findings/classify-finding.js +14 -69
  223. package/.agents/scripts/lib/findings/promote-finding.js +14 -112
  224. package/.agents/scripts/lib/findings/provenance-field.js +11 -52
  225. package/.agents/scripts/lib/findings/route-finding.js +37 -255
  226. package/.agents/scripts/lib/findings/semantic-issue-search.js +14 -59
  227. package/.agents/scripts/lib/findings/severity.js +18 -104
  228. package/.agents/scripts/lib/format-generated-json.js +12 -44
  229. package/.agents/scripts/lib/full-suite-lock.js +160 -429
  230. package/.agents/scripts/lib/full-suite-queue.js +213 -0
  231. package/.agents/scripts/lib/gates/baseline-store.js +5 -9
  232. package/.agents/scripts/lib/gates/friction.js +1 -3
  233. package/.agents/scripts/lib/generated/agentrc-validator.js +2 -2
  234. package/.agents/scripts/lib/gh-exec.js +31 -259
  235. package/.agents/scripts/lib/git/cached-fetch.js +9 -52
  236. package/.agents/scripts/lib/git/sync-from-base.js +15 -107
  237. package/.agents/scripts/lib/git-branch-cleanup.js +14 -61
  238. package/.agents/scripts/lib/git-branch-lifecycle.js +16 -87
  239. package/.agents/scripts/lib/git-utils.js +37 -161
  240. package/.agents/scripts/lib/github/framework-repo.js +8 -71
  241. package/.agents/scripts/lib/github-url.js +2 -17
  242. package/.agents/scripts/lib/import-graph.js +11 -38
  243. package/.agents/scripts/lib/install-cmd-parser.js +4 -13
  244. package/.agents/scripts/lib/json-utils.js +3 -18
  245. package/.agents/scripts/lib/label-constants.js +16 -111
  246. package/.agents/scripts/lib/label-taxonomy.js +4 -30
  247. package/.agents/scripts/lib/maintainability-engine.js +12 -80
  248. package/.agents/scripts/lib/maintainability-unscorable.js +5 -25
  249. package/.agents/scripts/lib/maintainability-utils.js +16 -92
  250. package/.agents/scripts/lib/mandrel-catalog.js +12 -70
  251. package/.agents/scripts/lib/notifications/notifier.js +13 -38
  252. package/.agents/scripts/lib/npm-scripts.js +4 -23
  253. package/.agents/scripts/lib/observability/metrics-ledger.js +16 -76
  254. package/.agents/scripts/lib/observability/runtime-friction.js +44 -286
  255. package/.agents/scripts/lib/observability/signal-validator.js +5 -37
  256. package/.agents/scripts/lib/observability/signals-writer.js +11 -121
  257. package/.agents/scripts/lib/observability/source-classifier.js +21 -203
  258. package/.agents/scripts/lib/observability/terse-result.js +14 -47
  259. package/.agents/scripts/lib/onboard/init-tail.js +13 -74
  260. package/.agents/scripts/lib/onboard/scaffold-docs.js +11 -34
  261. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +25 -139
  262. package/.agents/scripts/lib/orchestration/auto-merge-cwd.js +11 -66
  263. package/.agents/scripts/lib/orchestration/behind-recovery.js +10 -55
  264. package/.agents/scripts/lib/orchestration/ceremony-routing.js +5 -75
  265. package/.agents/scripts/lib/orchestration/change-set.js +7 -36
  266. package/.agents/scripts/lib/orchestration/check-baselines/phases/compare.js +9 -46
  267. package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +11 -44
  268. package/.agents/scripts/lib/orchestration/check-baselines/phases/floors.js +5 -24
  269. package/.agents/scripts/lib/orchestration/check-baselines/phases/friction.js +3 -12
  270. package/.agents/scripts/lib/orchestration/check-baselines/phases/parse-args.js +5 -38
  271. package/.agents/scripts/lib/orchestration/check-baselines/phases/pipeline.js +3 -8
  272. package/.agents/scripts/lib/orchestration/check-baselines/phases/refresh-ack.js +28 -136
  273. package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +3 -13
  274. package/.agents/scripts/lib/orchestration/check-state.js +92 -0
  275. package/.agents/scripts/lib/orchestration/ci-gap-intake.js +37 -144
  276. package/.agents/scripts/lib/orchestration/ci-rerun-guard.js +42 -189
  277. package/.agents/scripts/lib/orchestration/code-review.js +24 -128
  278. package/.agents/scripts/lib/orchestration/column-sync.js +23 -111
  279. package/.agents/scripts/lib/orchestration/complexity-gate.js +42 -214
  280. package/.agents/scripts/lib/orchestration/deliver-recover.js +36 -168
  281. package/.agents/scripts/lib/orchestration/dependency-analyzer.js +4 -35
  282. package/.agents/scripts/lib/orchestration/dependency-candidates.js +9 -41
  283. package/.agents/scripts/lib/orchestration/diff-magnitude.js +25 -115
  284. package/.agents/scripts/lib/orchestration/doc-reader.js +2 -6
  285. package/.agents/scripts/lib/orchestration/docs-digest.js +13 -51
  286. package/.agents/scripts/lib/orchestration/epic-candidates.js +13 -53
  287. package/.agents/scripts/lib/orchestration/epic-checklist.js +9 -33
  288. package/.agents/scripts/lib/orchestration/epic-container.js +41 -167
  289. package/.agents/scripts/lib/orchestration/epic-expansion.js +10 -40
  290. package/.agents/scripts/lib/orchestration/epic-rollup.js +55 -207
  291. package/.agents/scripts/lib/orchestration/file-assumption-enum.js +2 -22
  292. package/.agents/scripts/lib/orchestration/file-assumptions.js +45 -253
  293. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-detect.js +9 -46
  294. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-reap.js +7 -57
  295. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches.js +21 -126
  296. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +2 -6
  297. package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +1 -4
  298. package/.agents/scripts/lib/orchestration/git-cleanup/phases/filters.js +1 -5
  299. package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes-ff.js +9 -34
  300. package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes.js +41 -190
  301. package/.agents/scripts/lib/orchestration/git-cleanup/phases/merged-tip.js +9 -45
  302. package/.agents/scripts/lib/orchestration/git-cleanup/phases/parse-args.js +1 -4
  303. package/.agents/scripts/lib/orchestration/git-cleanup/phases/phase-drivers.js +19 -85
  304. package/.agents/scripts/lib/orchestration/git-cleanup/phases/prompts.js +3 -17
  305. package/.agents/scripts/lib/orchestration/git-cleanup/phases/prune.js +1 -5
  306. package/.agents/scripts/lib/orchestration/git-cleanup/phases/render.js +16 -100
  307. package/.agents/scripts/lib/orchestration/git-cleanup/phases/stashes.js +1 -4
  308. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +16 -67
  309. package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +9 -33
  310. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +8 -29
  311. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +15 -68
  312. package/.agents/scripts/lib/orchestration/light-backstop.js +11 -49
  313. package/.agents/scripts/lib/orchestration/light-escalation.js +21 -89
  314. package/.agents/scripts/lib/orchestration/light-suitability.js +26 -231
  315. package/.agents/scripts/lib/orchestration/merge-block-class.js +39 -216
  316. package/.agents/scripts/lib/orchestration/merge-poll.js +104 -377
  317. package/.agents/scripts/lib/orchestration/pinned-identifier-lint.js +17 -57
  318. package/.agents/scripts/lib/orchestration/plan-context.js +52 -303
  319. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +22 -79
  320. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +5 -31
  321. package/.agents/scripts/lib/orchestration/plan-metrics.js +29 -108
  322. package/.agents/scripts/lib/orchestration/plan-navigation.js +8 -27
  323. package/.agents/scripts/lib/orchestration/plan-persist/acceptance-handle-repair.js +12 -49
  324. package/.agents/scripts/lib/orchestration/plan-persist/audit-provenance.js +18 -73
  325. package/.agents/scripts/lib/orchestration/plan-persist/changes-repair.js +14 -78
  326. package/.agents/scripts/lib/orchestration/plan-persist/cross-plan-links.js +6 -30
  327. package/.agents/scripts/lib/orchestration/plan-persist/epic-adoption.js +14 -65
  328. package/.agents/scripts/lib/orchestration/plan-persist/epic-ops.js +21 -76
  329. package/.agents/scripts/lib/orchestration/plan-persist/external-deps.js +6 -43
  330. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +14 -68
  331. package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +9 -41
  332. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +49 -248
  333. package/.agents/scripts/lib/orchestration/plan-persist/soft-findings.js +2 -12
  334. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +85 -368
  335. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +8 -38
  336. package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +30 -190
  337. package/.agents/scripts/lib/orchestration/plan-persist/wave-collision-gate.js +9 -49
  338. package/.agents/scripts/lib/orchestration/plan-persist/wave-serialisation.js +7 -28
  339. package/.agents/scripts/lib/orchestration/plan-reachability.js +13 -42
  340. package/.agents/scripts/lib/orchestration/plan-run-labels/reap.js +16 -91
  341. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +16 -54
  342. package/.agents/scripts/lib/orchestration/plan-text-hygiene.js +10 -52
  343. package/.agents/scripts/lib/orchestration/planning/authoring-context.js +14 -109
  344. package/.agents/scripts/lib/orchestration/planning/memory-pool-advisory.js +11 -83
  345. package/.agents/scripts/lib/orchestration/pr-watch.js +48 -306
  346. package/.agents/scripts/lib/orchestration/project-meta-cache.js +15 -80
  347. package/.agents/scripts/lib/orchestration/project-meta-resolver.js +10 -51
  348. package/.agents/scripts/lib/orchestration/reassert-status-column.js +12 -76
  349. package/.agents/scripts/lib/orchestration/remote-verifier.js +12 -36
  350. package/.agents/scripts/lib/orchestration/resolve-stories.js +33 -164
  351. package/.agents/scripts/lib/orchestration/retro-proposals.js +66 -361
  352. package/.agents/scripts/lib/orchestration/review-base-ref.js +9 -43
  353. package/.agents/scripts/lib/orchestration/review-depth.js +12 -94
  354. package/.agents/scripts/lib/orchestration/review-providers/codex.js +10 -111
  355. package/.agents/scripts/lib/orchestration/review-providers/degraded-gates.js +13 -71
  356. package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +7 -51
  357. package/.agents/scripts/lib/orchestration/review-providers/mi-exemptions.js +8 -53
  358. package/.agents/scripts/lib/orchestration/review-providers/native.js +30 -214
  359. package/.agents/scripts/lib/orchestration/review-providers/parse-findings.js +7 -52
  360. package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +4 -33
  361. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +11 -71
  362. package/.agents/scripts/lib/orchestration/review-providers/scoped-lint.js +19 -131
  363. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +6 -89
  364. package/.agents/scripts/lib/orchestration/review-providers/types.js +26 -56
  365. package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +3 -46
  366. package/.agents/scripts/lib/orchestration/run-epilogue.js +40 -199
  367. package/.agents/scripts/lib/orchestration/run-scoped-config.js +13 -81
  368. package/.agents/scripts/lib/orchestration/single-story-close/close-note.js +7 -34
  369. package/.agents/scripts/lib/orchestration/single-story-close/failed-terminal.js +16 -89
  370. package/.agents/scripts/lib/orchestration/single-story-close/gate-log.js +18 -109
  371. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +83 -239
  372. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +18 -80
  373. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +103 -97
  374. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +8 -64
  375. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +136 -486
  376. package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +30 -134
  377. package/.agents/scripts/lib/orchestration/single-story-close/phases/graphql-preflight.js +9 -50
  378. package/.agents/scripts/lib/orchestration/single-story-close/phases/lock-wait-pending.js +49 -0
  379. package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +13 -86
  380. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +20 -95
  381. package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +46 -203
  382. package/.agents/scripts/lib/orchestration/single-story-close/phases/pre-gate-steps.js +8 -50
  383. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +12 -83
  384. package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +6 -39
  385. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +1 -6
  386. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-outcome.js +4 -28
  387. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-override.js +6 -51
  388. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +6 -34
  389. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +23 -121
  390. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +110 -290
  391. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +15 -69
  392. package/.agents/scripts/lib/orchestration/story-body-gate.js +4 -23
  393. package/.agents/scripts/lib/orchestration/story-close/baseline-upward-writeback.js +50 -179
  394. package/.agents/scripts/lib/orchestration/story-close/context-budget-writeback.js +11 -41
  395. package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +23 -311
  396. package/.agents/scripts/lib/orchestration/story-close/phases/local-lens-review.js +22 -147
  397. package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +16 -67
  398. package/.agents/scripts/lib/orchestration/story-deliver-terminal-schema.js +12 -68
  399. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +42 -201
  400. package/.agents/scripts/lib/orchestration/story-follow-ups.js +43 -245
  401. package/.agents/scripts/lib/orchestration/story-init-envelope.js +4 -23
  402. package/.agents/scripts/lib/orchestration/story-init-remote.js +2 -6
  403. package/.agents/scripts/lib/orchestration/story-reachability.js +3 -23
  404. package/.agents/scripts/lib/orchestration/task-body-validator.js +12 -126
  405. package/.agents/scripts/lib/orchestration/ticket-lease.js +28 -131
  406. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +15 -149
  407. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +5 -33
  408. package/.agents/scripts/lib/orchestration/ticket-validator.js +39 -181
  409. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +51 -244
  410. package/.agents/scripts/lib/orchestration/ticketing/reads.js +39 -250
  411. package/.agents/scripts/lib/orchestration/ticketing/state.js +14 -68
  412. package/.agents/scripts/lib/orchestration/ticketing/transition.js +46 -263
  413. package/.agents/scripts/lib/orchestration/ticketing.js +2 -26
  414. package/.agents/scripts/lib/orchestration/verify-credit.js +18 -79
  415. package/.agents/scripts/lib/orchestration/worktree-dirty.js +5 -30
  416. package/.agents/scripts/lib/path-security.js +3 -6
  417. package/.agents/scripts/lib/plan-phase-cleanup.js +9 -49
  418. package/.agents/scripts/lib/preflight-runner.js +13 -69
  419. package/.agents/scripts/lib/process-group.js +143 -0
  420. package/.agents/scripts/lib/project-root.js +2 -8
  421. package/.agents/scripts/lib/provider-factory.js +2 -25
  422. package/.agents/scripts/lib/qa/console-allowlist.js +10 -59
  423. package/.agents/scripts/lib/qa/qa-session.js +15 -69
  424. package/.agents/scripts/lib/qa/redact-evidence.js +18 -129
  425. package/.agents/scripts/lib/qa/resolve-qa-contract.js +26 -135
  426. package/.agents/scripts/lib/qa/resolve-selection.js +16 -84
  427. package/.agents/scripts/lib/reserved-test-ids.js +9 -47
  428. package/.agents/scripts/lib/runtime-deps/dep-resolution.js +13 -53
  429. package/.agents/scripts/lib/runtime-deps/ensure-installed.js +10 -44
  430. package/.agents/scripts/lib/runtime-deps/manifest.js +10 -30
  431. package/.agents/scripts/lib/runtime-deps/parser-major.js +15 -51
  432. package/.agents/scripts/lib/runtime-deps/preflight.js +4 -22
  433. package/.agents/scripts/lib/runtime-deps/scan-imports.js +11 -55
  434. package/.agents/scripts/lib/signals/detectors/common.js +12 -38
  435. package/.agents/scripts/lib/signals/index.js +2 -19
  436. package/.agents/scripts/lib/signals/schema.js +14 -109
  437. package/.agents/scripts/lib/signals/write.js +2 -11
  438. package/.agents/scripts/lib/single-story/confirm-merge.js +31 -72
  439. package/.agents/scripts/lib/single-story/story-merged-notify.js +8 -49
  440. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +4 -26
  441. package/.agents/scripts/lib/single-story-sweep/protection.js +13 -100
  442. package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +60 -258
  443. package/.agents/scripts/lib/single-story-sweep.js +14 -97
  444. package/.agents/scripts/lib/skills/parse-skill.js +13 -59
  445. package/.agents/scripts/lib/skills/skills-index.js +8 -29
  446. package/.agents/scripts/lib/skills/walk-skill-files.js +17 -78
  447. package/.agents/scripts/lib/source-extensions.js +11 -42
  448. package/.agents/scripts/lib/source-text/strip-js-comments.js +8 -41
  449. package/.agents/scripts/lib/stdio-flush.js +9 -36
  450. package/.agents/scripts/lib/story-adjacency.js +8 -40
  451. package/.agents/scripts/lib/story-body/body-format-lints.js +22 -83
  452. package/.agents/scripts/lib/story-body/footer-block.js +11 -44
  453. package/.agents/scripts/lib/story-body/story-body.js +83 -358
  454. package/.agents/scripts/lib/temp-retention.js +42 -143
  455. package/.agents/scripts/lib/templates/decomposer-prompts.js +11 -65
  456. package/.agents/scripts/lib/test-env.js +12 -65
  457. package/.agents/scripts/lib/test-run-credit.js +10 -65
  458. package/.agents/scripts/lib/test-runner-contract.js +19 -74
  459. package/.agents/scripts/lib/test-temp.js +38 -184
  460. package/.agents/scripts/lib/test-tiers.js +12 -96
  461. package/.agents/scripts/lib/ticket-body-sections.js +21 -96
  462. package/.agents/scripts/lib/transpile.js +15 -74
  463. package/.agents/scripts/lib/util/concurrent-map.js +6 -25
  464. package/.agents/scripts/lib/util/parse-id-list.js +8 -34
  465. package/.agents/scripts/lib/util/poll-loop.js +8 -28
  466. package/.agents/scripts/lib/util/with-timeout.js +2 -11
  467. package/.agents/scripts/lib/validation-evidence.js +21 -96
  468. package/.agents/scripts/lib/wave-runner/footprint.js +17 -70
  469. package/.agents/scripts/lib/wave-runner/live-probe.js +53 -221
  470. package/.agents/scripts/lib/wave-runner/ready-set.js +72 -301
  471. package/.agents/scripts/lib/workers/crap-worker.js +11 -64
  472. package/.agents/scripts/lib/workers/maintainability-report-worker.js +8 -45
  473. package/.agents/scripts/lib/workers/maintainability-worker.js +5 -21
  474. package/.agents/scripts/lib/workers/serve-worker-messages.js +2 -18
  475. package/.agents/scripts/lib/workflow-closure.js +22 -105
  476. package/.agents/scripts/lib/workspace-provisioner.js +16 -54
  477. package/.agents/scripts/lib/worktree/git-hooks.js +15 -60
  478. package/.agents/scripts/lib/worktree/lifecycle/force-drain.js +20 -60
  479. package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +10 -62
  480. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +22 -86
  481. package/.agents/scripts/lib/worktree/lifecycle/reap.js +24 -126
  482. package/.agents/scripts/lib/worktree/lifecycle-manager.js +2 -20
  483. package/.agents/scripts/lib/worktree/node-modules-strategy.js +46 -180
  484. package/.agents/scripts/lib/worktree-manager.js +15 -40
  485. package/.agents/scripts/lint-issue-body.js +12 -68
  486. package/.agents/scripts/mandrel-update-preflight.js +10 -70
  487. package/.agents/scripts/merge-baseline.js +30 -104
  488. package/.agents/scripts/nav-registry-diff.js +22 -108
  489. package/.agents/scripts/notify.js +12 -69
  490. package/.agents/scripts/plan-context.js +27 -111
  491. package/.agents/scripts/plan-critics.js +12 -66
  492. package/.agents/scripts/plan-persist.js +31 -148
  493. package/.agents/scripts/plan-run-epilogue.js +11 -37
  494. package/.agents/scripts/pr-watch-with-update.js +76 -267
  495. package/.agents/scripts/providers/github/auth.js +3 -8
  496. package/.agents/scripts/providers/github/blocked-by-add.js +14 -61
  497. package/.agents/scripts/providers/github/board-add.js +5 -21
  498. package/.agents/scripts/providers/github/branch-protection.js +11 -43
  499. package/.agents/scripts/providers/github/cache.js +2 -14
  500. package/.agents/scripts/providers/github/comments.js +7 -40
  501. package/.agents/scripts/providers/github/compose.js +3 -19
  502. package/.agents/scripts/providers/github/errors.js +22 -125
  503. package/.agents/scripts/providers/github/issues.js +31 -123
  504. package/.agents/scripts/providers/github/labels.js +24 -124
  505. package/.agents/scripts/providers/github/mappers.js +5 -27
  506. package/.agents/scripts/providers/github/merge-methods.js +3 -22
  507. package/.agents/scripts/providers/github/project-board.js +2 -17
  508. package/.agents/scripts/providers/github/projects-v2-graphql.js +3 -6
  509. package/.agents/scripts/providers/github/request-helpers.js +5 -32
  510. package/.agents/scripts/providers/github/search-budget.js +9 -39
  511. package/.agents/scripts/providers/github/search-query.js +5 -26
  512. package/.agents/scripts/providers/github/sub-issue-add.js +15 -65
  513. package/.agents/scripts/providers/github/sub-issues.js +7 -36
  514. package/.agents/scripts/providers/github/tickets.js +32 -134
  515. package/.agents/scripts/providers/github.js +18 -59
  516. package/.agents/scripts/prune-plan-run-labels.js +12 -46
  517. package/.agents/scripts/quality-preview.js +35 -220
  518. package/.agents/scripts/resolve-doc-tiers.js +3 -26
  519. package/.agents/scripts/resolve-stories.js +16 -67
  520. package/.agents/scripts/resync-status-column.js +6 -25
  521. package/.agents/scripts/run-tests.js +29 -104
  522. package/.agents/scripts/single-story-close.js +23 -135
  523. package/.agents/scripts/single-story-confirm-merge.js +32 -139
  524. package/.agents/scripts/single-story-init.js +47 -209
  525. package/.agents/scripts/stories-wave-tick.js +102 -472
  526. package/.agents/scripts/sync-agentrc.js +3 -21
  527. package/.agents/scripts/sync-claude-agents.js +9 -55
  528. package/.agents/scripts/sync-claude-commands.js +20 -110
  529. package/.agents/scripts/test-wrapper.js +6 -43
  530. package/.agents/scripts/update-coverage-baseline.js +5 -22
  531. package/.agents/scripts/update-crap-baseline.js +7 -30
  532. package/.agents/scripts/update-duplication-baseline.js +16 -92
  533. package/.agents/scripts/update-maintainability-baseline.js +8 -62
  534. package/.agents/scripts/update-ticket-state.js +1 -7
  535. package/.agents/scripts/validate-skills.js +6 -26
  536. package/.agents/templates/agent-protocol.md +2 -2
  537. package/.agents/templates/docs/audit-sweep-runbook.md +3 -4
  538. package/.agents/workflows/audit-accessibility.md +4 -7
  539. package/.agents/workflows/audit-adrs.md +3 -6
  540. package/.agents/workflows/audit-architecture.md +3 -11
  541. package/.agents/workflows/audit-baselines.md +6 -9
  542. package/.agents/workflows/audit-clean-code.md +8 -12
  543. package/.agents/workflows/audit-data-model.md +3 -7
  544. package/.agents/workflows/audit-dependencies.md +4 -7
  545. package/.agents/workflows/audit-devops.md +4 -8
  546. package/.agents/workflows/audit-documentation.md +1 -4
  547. package/.agents/workflows/audit-mobile.md +4 -7
  548. package/.agents/workflows/audit-navigability.md +3 -6
  549. package/.agents/workflows/audit-performance.md +2 -4
  550. package/.agents/workflows/audit-privacy.md +4 -7
  551. package/.agents/workflows/audit-quality.md +4 -7
  552. package/.agents/workflows/audit-security.md +4 -7
  553. package/.agents/workflows/audit-seo.md +4 -7
  554. package/.agents/workflows/audit-sre.md +4 -7
  555. package/.agents/workflows/audit-to-stories.md +17 -30
  556. package/.agents/workflows/audit-ux-ui.md +4 -7
  557. package/.agents/workflows/helpers/audit-lens-core.md +1 -1
  558. package/.agents/workflows/helpers/code-quality-guardrails.md +12 -15
  559. package/.agents/workflows/helpers/deliver-digest.md +6 -4
  560. package/.agents/workflows/helpers/deliver-reference.md +114 -188
  561. package/.agents/workflows/helpers/deliver-story-reference.md +189 -533
  562. package/.agents/workflows/helpers/plan-reference.md +86 -139
  563. package/.agents/workflows/helpers/qa-core.md +12 -0
  564. package/.agents/workflows/memory-consolidate.md +1 -1
  565. package/.agents/workflows/qa-assist.md +27 -71
  566. package/.agents/workflows/qa-explore.md +19 -59
  567. package/.agents/workflows/qa-run.md +11 -33
  568. package/README.md +1 -1
  569. package/bin/mandrel.js +5 -46
  570. package/bin/postinstall.js +18 -107
  571. package/docs/CHANGELOG.md +25 -0
  572. package/lib/cli/doctor.js +11 -71
  573. package/lib/cli/init.js +26 -165
  574. package/lib/cli/migrate.js +5 -64
  575. package/lib/cli/registry.js +84 -467
  576. package/lib/cli/sync-agents.js +4 -64
  577. package/lib/cli/sync-commands.js +11 -64
  578. package/lib/cli/sync.js +34 -213
  579. package/lib/cli/uninstall.js +40 -219
  580. package/lib/cli/update.js +105 -661
  581. package/lib/cli/version-check.js +8 -72
  582. package/lib/cli/version-helpers.js +14 -87
  583. package/lib/migrations/helpers/retire-agentrc-key.js +11 -52
  584. package/lib/migrations/index.js +15 -92
  585. package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +2 -15
  586. package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +1 -13
  587. package/lib/migrations/steps/2.11.0-retire-max-seed-words.js +2 -15
  588. package/lib/migrations/steps/2.2.0-retire-epic-ac-tags.js +9 -38
  589. package/lib/migrations/steps/2.20.0-retire-codebase-snapshot.js +1 -13
  590. package/lib/migrations/steps/2.32.0-retire-lint-baseline-command.js +2 -27
  591. package/lib/migrations/steps/2.57.0-retire-delivery-limit-knobs.js +2 -23
  592. package/lib/migrations/steps/2.57.0-retire-planning-limit-knobs.js +2 -27
  593. package/lib/migrations/steps/2.60.0-retire-audit-results-autofile.js +2 -21
  594. package/lib/migrations/steps/strip-removed-agentrc-keys.js +333 -0
  595. package/package.json +16 -14
  596. package/.agents/docs/SDLC.md +0 -590
  597. package/.agents/docs/quality-gates.md +0 -1183
  598. package/.agents/rules/known-tooling-behavior.md +0 -200
  599. package/.agents/rules/orchestration-error-handling.md +0 -61
  600. package/.agents/rules/test-seams.md +0 -59
  601. package/.agents/schemas/baselines/lighthouse.schema.json +0 -59
  602. package/.agents/schemas/baselines/lint.schema.json +0 -47
  603. package/.agents/scripts/check-action-pinning.js +0 -260
  604. package/.agents/scripts/check-audit-attribution.js +0 -302
  605. package/.agents/scripts/check-baseline-drift.js +0 -211
  606. package/.agents/scripts/check-baseline-scope.js +0 -362
  607. package/.agents/scripts/check-generated-validator.js +0 -202
  608. package/.agents/scripts/check-knip-entries.js +0 -159
  609. package/.agents/scripts/check-lifecycle-lint.js +0 -294
  610. package/.agents/scripts/check-pinned-override-notes.js +0 -102
  611. package/.agents/scripts/check-schema-references.js +0 -368
  612. package/.agents/scripts/check-test-portability.js +0 -512
  613. package/.agents/scripts/check-workflow-citations.js +0 -218
  614. package/.agents/scripts/check-workflow-cli-lint.js +0 -299
  615. package/.agents/scripts/check-workflow-timeouts.js +0 -291
  616. package/.agents/scripts/install-matrix-assert.js +0 -326
  617. package/.agents/scripts/lib/audit-advisories.js +0 -195
  618. package/.agents/scripts/lib/audit-attribution.js +0 -134
  619. package/.agents/scripts/lib/baselines/drift-detector.js +0 -351
  620. package/.agents/scripts/lib/baselines/kinds/lighthouse.js +0 -87
  621. package/.agents/scripts/lib/baselines/kinds/lint.js +0 -184
  622. package/.agents/scripts/lib/baselines/orphan-pruner.js +0 -233
  623. package/.agents/scripts/lib/baselines/scope-assert.js +0 -223
  624. package/.agents/scripts/lib/baselines/scope-inventory.js +0 -314
  625. package/.agents/scripts/lib/c8-cli-path.js +0 -21
  626. package/.agents/scripts/lib/config/gates/lighthouse.schema.js +0 -51
  627. package/.agents/scripts/lib/config/gates/lint.schema.js +0 -18
  628. package/.agents/scripts/lib/dynamic-workflow/architecture-report-contract.js +0 -70
  629. package/.agents/scripts/lib/dynamic-workflow/audit-orchestrator.js +0 -284
  630. package/.agents/scripts/lib/dynamic-workflow/clean-code-report-contract.js +0 -80
  631. package/.agents/scripts/lib/dynamic-workflow/degraded-coverage.js +0 -81
  632. package/.agents/scripts/lib/dynamic-workflow/documentation-report-contract.js +0 -87
  633. package/.agents/scripts/lib/dynamic-workflow/performance-report-contract.js +0 -74
  634. package/.agents/scripts/lib/dynamic-workflow/quality-report-contract.js +0 -90
  635. package/.agents/scripts/lib/dynamic-workflow/report-contract-core.js +0 -43
  636. package/.agents/scripts/lib/dynamic-workflow/security-report-contract.js +0 -83
  637. package/.agents/scripts/lib/fs-walk.js +0 -52
  638. package/.agents/scripts/lib/knip-config-resolver.js +0 -181
  639. package/.agents/scripts/lib/knip-entry-sync.js +0 -452
  640. package/.agents/scripts/lib/pinned-override-notes.js +0 -88
  641. package/.agents/scripts/lib/pinned-override-resolve.js +0 -212
  642. package/.agents/scripts/lib/test-isolate/cli-options.js +0 -93
  643. package/.agents/scripts/lib/test-isolate/env-snapshot-loader.js +0 -52
  644. package/.agents/scripts/lib/test-isolate/list-files.js +0 -90
  645. package/.agents/scripts/lib/test-isolate/parse-tap.js +0 -75
  646. package/.agents/scripts/lib/test-isolate/progress-log.js +0 -45
  647. package/.agents/scripts/lib/test-isolate/render-report.js +0 -97
  648. package/.agents/scripts/lib/test-isolate/run-isolate.js +0 -87
  649. package/.agents/scripts/lib/test-isolate/runner.js +0 -483
  650. package/.agents/scripts/lib/test-profile/parse-tap.js +0 -136
  651. package/.agents/scripts/lib/test-profile/render-report.js +0 -45
  652. package/.agents/scripts/lint-label-vocabulary.js +0 -214
  653. package/.agents/scripts/post-structured-comment.js +0 -127
  654. package/.agents/scripts/provision-git-hooks.js +0 -85
  655. package/.agents/scripts/prune-baseline-orphans.js +0 -181
  656. package/.agents/scripts/run-coverage.js +0 -197
  657. package/.agents/scripts/run-lint.js +0 -133
  658. package/.agents/scripts/run-test-profile.js +0 -129
  659. package/.agents/scripts/run-verify.js +0 -125
  660. package/.agents/scripts/test-isolate.js +0 -55
  661. package/.agents/scripts/update-dead-exports-baseline.js +0 -321
@@ -1,35 +1,26 @@
1
1
  /**
2
- * coverage-capture.js — ensure `coverage/coverage-final.json` is present and
3
- * fresh before any CRAP gate (close-validation pre-flight, pre-push, CI) reads
4
- * it. The CRAP scorer treats "no coverage" as "skip the method" under the
5
- * default `requireCoverage: true` policy, so a missing or stale artifact
6
- * silently weakens the gate. This helper closes that hole by capturing
7
- * coverage in-band when it is missing or older than the CRAP-target sources.
8
- *
9
- * Pure functions live here; the spawn wiring lives in
10
- * `.agents/scripts/coverage-capture.js` (CLI). Importers test freshness via
11
- * `isCoverageFresh` and decide whether to delegate to `runCapture`.
2
+ * Keep `coverage/coverage-final.json` present and fresh before a CRAP gate
3
+ * reads it: the scorer skips uncovered methods, so a stale artifact silently
4
+ * weakens the gate.
12
5
  */
13
- import { spawnSync } from 'node:child_process';
6
+ import { spawn, spawnSync } from 'node:child_process';
14
7
  import crypto from 'node:crypto';
15
8
  import fs from 'node:fs';
16
9
  import path from 'node:path';
10
+ import { LOCK_WAIT_EXPIRED_EXIT_CODE } from './full-suite-lock.js';
11
+ import {
12
+ groupSpawnOptions,
13
+ superviseGroup,
14
+ TIMEOUT_EXIT_CODE,
15
+ } from './process-group.js';
17
16
  import {
18
17
  isScorableSourceFile,
19
18
  SCORABLE_SOURCE_EXT_RE,
20
19
  } from './source-extensions.js';
21
20
 
22
21
  /**
23
- * Walk a directory tree and return the newest mtime (ms since epoch) seen
24
- * across the scorable source files (`source-extensions.js`) — the same set
25
- * the CRAP scanner walks, so freshness tracks exactly what the gate scores.
26
- * Symlinks, missing dirs, and unreadable nodes resolve to 0.
27
- *
28
- * A 0 return means "discovery found nothing", which {@link isCoverageFresh}
29
- * treats as an absence of evidence rather than as freshness — see its
30
- * `no-sources` contract.
31
- *
32
- * Exported for unit testing.
22
+ * Newest mtime across the scorable sources the CRAP scanner walks; unreadable
23
+ * nodes are skipped. 0 means "found nothing", never "fresh".
33
24
  *
34
25
  * @param {string} cwd Absolute repo root.
35
26
  * @param {string[]} targetDirs Repo-relative directories to scan.
@@ -74,11 +65,8 @@ export function newestSourceMtime(cwd, targetDirs, io = {}) {
74
65
  }
75
66
 
76
67
  /**
77
- * Resolve the capture-stamp path that sits next to the coverage artifact.
78
- * The stamp persists the content digest of the CRAP-target sources at the
79
- * moment coverage was last captured, so freshness can be decided by content
80
- * rather than mtime (mtime churns on branch switches / checkouts even when
81
- * content is unchanged).
68
+ * The stamp records the sources' content digest at capture time, so freshness
69
+ * survives mtime churn from checkouts.
82
70
  *
83
71
  * @param {string} cwd Absolute repo root.
84
72
  * @param {string} coveragePath Repo-relative coverage artifact path.
@@ -92,13 +80,8 @@ export function captureStampPath(cwd, coveragePath) {
92
80
  }
93
81
 
94
82
  /**
95
- * Fold every dirty scorable working-tree file under the scanned dirs into
96
- * `hash`, and report how many there were.
97
- *
98
- * Dirty files are not represented by their index blob SHA, so their on-disk
99
- * bytes (or absence) go in explicitly. Split out of
100
- * {@link computeContentDigest} to keep that function's complexity at its
101
- * committed CRAP floor.
83
+ * Fold dirty scorable files' on-disk bytes (or absence) into `hash`; their
84
+ * index blob SHA does not represent them.
102
85
  *
103
86
  * @param {{
104
87
  * hash: import('node:crypto').Hash,
@@ -127,19 +110,10 @@ function foldDirtySources({ hash, cwd, readFileSync, porcelain }) {
127
110
  }
128
111
 
129
112
  /**
130
- * Compute a stable content digest of the scorable sources
131
- * (`source-extensions.js`) under `targetDirs`: the `git ls-files -s` listing (mode + blob SHA + path) of
132
- * tracked content, plus the on-disk bytes of any dirty working-tree files.
133
- * Checkout/branch churn leaves blob SHAs untouched, so the digest only moves
134
- * when content actually changes.
135
- *
136
- * Returns `null` when the digest cannot be computed (git unavailable, not a
137
- * repo, empty target list) so callers can fall back to the mtime heuristic.
138
- * A target list that matches **no** scorable file is the same "unavailable"
139
- * case, not a digest over zero files: this path is the primary freshness
140
- * test, so returning a real hash of empty input would pin the artifact
141
- * permanently fresh and make the mtime path's fail-closed verdict
142
- * unreachable (Story #5076).
113
+ * Digest of the scorable sources under `targetDirs`: `git ls-files -s` of
114
+ * tracked content plus dirty files' bytes, so it moves only on content change.
115
+ * `null` means unavailable (no git, no dirs, or zero matching files — a hash
116
+ * of empty input would pin the artifact permanently fresh).
143
117
  *
144
118
  * @param {string} cwd Absolute repo root.
145
119
  * @param {string[]} targetDirs Repo-relative directories to digest.
@@ -175,9 +149,6 @@ export function computeContentDigest(cwd, targetDirs, io = {}) {
175
149
  readFileSync,
176
150
  porcelain: git('status', '--porcelain', '--', ...dirs),
177
151
  });
178
- // Discovery found nothing to digest: hashing the empty input would yield
179
- // a constant that can never go stale, so report "unavailable" instead and
180
- // let the caller's fail-closed mtime path decide.
181
152
  if (tracked.length + scorableDirty === 0) return null;
182
153
  return hash.digest('hex');
183
154
  } catch {
@@ -186,16 +157,9 @@ export function computeContentDigest(cwd, targetDirs, io = {}) {
186
157
  }
187
158
 
188
159
  /**
189
- * Persist the capture stamp next to the coverage artifact. Best-effort: a
190
- * write failure returns `false` rather than throwing — the worst case is a
191
- * fall back to the mtime heuristic on the next freshness check.
192
- *
193
- * `scope` / `files` / `ref` are Story #4981 additions for incremental-mode
194
- * capture. They are written to the stamp **only when the caller supplies
195
- * `scope`** — the default (full-scope) call sites never pass it, so the
196
- * emitted JSON stays the exact `{ digest, capturedAt }` shape byte-for-byte
197
- * (AC-5). `isCoverageFresh` reads `scope` back to refuse letting a scoped
198
- * stamp satisfy a full-scope freshness probe (AC-4).
160
+ * Best-effort: a write failure returns `false` (next check falls back to
161
+ * mtime). Full-scope callers omit `scope`, keeping the `{ digest, capturedAt }`
162
+ * shape.
199
163
  *
200
164
  * @param {{
201
165
  * cwd: string,
@@ -234,16 +198,10 @@ export function writeCaptureStamp({
234
198
  }
235
199
 
236
200
  /**
237
- * Read a persisted capture stamp's digest and scope tag back into the shape
238
- * `isCoverageFresh` needs, applying the Story #4981 scope-asymmetry rule
239
- * (AC-4) in one place. Extracted so the parent function's own branching
240
- * stays under the cyclomatic ceiling.
241
- *
242
201
  * @param {{digest?: unknown, scope?: unknown} | null} stamp
243
202
  * @param {'full' | 'incremental'} requireScope
244
203
  * @returns {{ digest: string } | { scopeMismatch: true } | null} `null`
245
- * means the stamp is missing/unreadable/digest-less — fall through to the
246
- * mtime heuristic.
204
+ * falls through to the mtime heuristic.
247
205
  */
248
206
  function readStampForScope(stamp, requireScope) {
249
207
  if (typeof stamp?.digest !== 'string' || stamp.digest.length === 0) {
@@ -257,33 +215,11 @@ function readStampForScope(stamp, requireScope) {
257
215
  }
258
216
 
259
217
  /**
260
- * Decide whether the existing coverage artifact is "fresh".
261
- *
262
- * Primary test (content-aware, Story #3982): when a capture stamp exists
263
- * next to the artifact, compare its persisted digest against the current
264
- * content digest of `targetDirs`. Equal digests → fresh; different → stale.
265
- * Branch switches and checkouts that bump mtimes without changing content
266
- * no longer invalidate coverage.
267
- *
268
- * Fallback (stamp absent / unreadable / digest unavailable): the original
269
- * mtime heuristic — artifact at least as new as the newest source file
270
- * under `targetDirs`. Missing files, missing target dirs, or any IO error
271
- * resolve to `false` so the caller captures rather than trusting stale data.
272
- *
273
- * **Both paths fail closed on an empty source set (Story #5076).** Finding no
274
- * scorable source under `targetDirs` means the check learned nothing, so it
275
- * reports `{ fresh: false, reason: 'no-sources' }` and the caller captures.
276
- * The alternative — treating "found nothing" as "nothing changed" — is how a
277
- * `js|mjs`-only selector left the CRAP gate green while measuring nothing in
278
- * every TypeScript consumer.
279
- *
280
- * **Scope asymmetry (Story #4981, AC-4).** A stamp written by an incremental
281
- * capture (`scope: 'incremental'`) only covers the files the diff touched —
282
- * it must never satisfy a caller that requires the full-scope guarantee
283
- * (`requireScope` defaults to `'full'`, matching every pre-existing caller
284
- * byte-for-byte). A full-scope stamp (or a legacy stamp with no `scope`
285
- * field, which predates this Story and is therefore full-scope by
286
- * construction) satisfies either probe.
218
+ * Stamp digest vs current digest when a stamp exists; otherwise artifact
219
+ * mtime vs newest source. IO errors resolve stale. Both paths fail closed
220
+ * (`no-sources`) on an empty source set — "found nothing" is not "nothing
221
+ * changed". An incremental stamp never satisfies a full-scope probe; a stamp
222
+ * with no `scope` is full-scope.
287
223
  *
288
224
  * @param {{
289
225
  * coveragePath: string,
@@ -345,9 +281,6 @@ export function isCoverageFresh({
345
281
  statSync,
346
282
  readdirSync,
347
283
  });
348
- // Source discovery found nothing. That is an absence of evidence, never a
349
- // freshness guarantee — trusting it silently disables the capture (and with
350
- // it the CRAP gate) for any tree the walk cannot see (Story #5076).
351
284
  if (newestSrc === 0) return { fresh: false, reason: 'no-sources' };
352
285
  return coverageMtime >= newestSrc
353
286
  ? { fresh: true, reason: 'fresh' }
@@ -355,14 +288,8 @@ export function isCoverageFresh({
355
288
  }
356
289
 
357
290
  /**
358
- * Render a freshness verdict for the operator-facing capture log.
359
- *
360
- * Every reason but `no-sources` speaks for itself. That one does not: failing
361
- * closed on an empty source walk is correct, but bare it reads as an
362
- * unexplained full capture on every run, and the cause is far more often a
363
- * `targetDirs` that does not name the project's sources than a genuine
364
- * recapture — so the walked dirs and the key to fix are named inline
365
- * (Story #5076).
291
+ * `no-sources` usually means a misconfigured `targetDirs`, so it names the
292
+ * walked dirs and the key to fix.
366
293
  *
367
294
  * @param {{ reason?: string }} freshness Verdict from {@link isCoverageFresh}.
368
295
  * @param {string[]} targetDirs The CRAP scan scope that was walked.
@@ -375,37 +302,19 @@ export function describeFreshness(freshness, targetDirs) {
375
302
  return `${reason} — no scorable source file found under [${dirs}]; if that does not name this project's sources, fix quality.gates.crap.targetDirs`;
376
303
  }
377
304
 
378
- /**
379
- * The invocation that deposits capture credit for a Story branch. Named in
380
- * the uncredited-capture announcement so a reader of a close log sees the
381
- * command that would have avoided the cost, not just the cost.
382
- */
383
305
  const CREDITING_INVOCATION =
384
306
  'node <main-repo>/.agents/scripts/coverage-capture.js --cwd <workCwd>';
385
307
 
386
308
  /**
387
- * Announce — and, when the consumer requires credit, refuse — a full-suite
388
- * capture that no committed stamp covers.
389
- *
390
- * Every caller invokes this immediately before it would spawn the suite, and
391
- * the ordering is the whole point. The capture itself is the most expensive
392
- * thing a close does; discovering that it ran uncredited is only actionable
393
- * while it is still ahead of you, not once it is visible as a `durationMs`
394
- * in `validation-evidence.json` twelve minutes later.
395
- *
396
- * The probe is read-only by construction: every caller has already decided
397
- * to capture by the time it runs, and it writes nothing — so it never takes
398
- * the full-suite host lock and can never itself be the reason a close waits.
309
+ * Announce (or, under `--require-credited`, refuse) an uncredited full-suite
310
+ * capture — before the spawn, while it is still actionable. Read-only, so it
311
+ * never takes the host lock.
399
312
  *
400
313
  * @param {{
401
314
  * requireCredited?: boolean,
402
315
  * logger: { info: Function, warn: Function, error: Function },
403
- * }} opts `requireCredited` comes from the CLI's `--require-credited`
404
- * argument, which the close gate passes when
405
- * `delivery.execution.requireCreditedCapture` is set (default false →
406
- * announce and run). Story #5278: it is deliberately NOT read from config
407
- * here — that made the refusal cover the depositing invocation too, leaving
408
- * no way to earn the credit it demanded.
316
+ * }} opts `requireCredited` is a per-invocation CLI opt-in, never config:
317
+ * from config it would also refuse the invocation that deposits credit.
409
318
  * @returns {number | null} A non-zero exit code the caller MUST return
410
319
  * without spawning the suite, or `null` to proceed with the capture.
411
320
  */
@@ -424,48 +333,25 @@ function announceUncreditedCapture({ requireCredited = false, logger }) {
424
333
  }
425
334
 
426
335
  /**
427
- * Compose the uncredited-capture probe over a capture runner, so the
428
- * announcement is structurally inseparable from the spawn it describes.
429
- *
430
- * This mirrors `lockedCapture`, and for the same reason: there are two
431
- * capture paths (full-scope and incremental) and neither should have to
432
- * remember the policy. Wrapping the runner they share means a third path
433
- * added later inherits the probe for free, and that the warning can never be
434
- * emitted for a capture that does not happen — or omitted for one that does.
336
+ * Wrap a capture runner so the announcement is inseparable from the spawn.
337
+ * Composes outside `lockedCapture`, so a refusal never acquires the lock.
435
338
  *
436
- * It composes OUTSIDE `lockedCapture`, so a refusal costs nothing: the host
437
- * lock is never acquired for a run that is about to be declined.
438
- *
439
- * @param {(opts: object) => number} runCaptureFn The (possibly already
440
- * lock-wrapped) capture runner.
339
+ * @param {(opts: object) => Promise<number>|number} runCaptureFn
441
340
  * @param {{ requireCredited?: boolean, logger: object }} policy
442
- * @returns {(opts?: object) => number} A runner returning the capture's exit
443
- * code, or a non-zero refusal code without having spawned anything.
341
+ * @returns {(opts?: object) => Promise<number>} Exit code, or a refusal code
342
+ * without spawning.
444
343
  */
445
344
  export function creditedCapture(runCaptureFn, { requireCredited, logger }) {
446
- return (captureOpts = {}) => {
345
+ return async (captureOpts = {}) => {
447
346
  const refusal = announceUncreditedCapture({ requireCredited, logger });
448
- return refusal === null ? runCaptureFn(captureOpts) : refusal;
347
+ return refusal === null ? await runCaptureFn(captureOpts) : refusal;
449
348
  };
450
349
  }
451
350
 
452
351
  /**
453
- * Write the capture stamp for a run that has just finished — but only when
454
- * the tree it measured is still the tree on disk (Story #5278).
455
- *
456
- * The stamp is a claim about content: "coverage/coverage-final.json reflects
457
- * sources digesting to X". Computing X *after* the suite finishes makes that
458
- * claim false whenever anything moved while the suite ran — a sibling
459
- * worktree's write, a rebase, an editor save minutes into a ten-minute run.
460
- * The digest taken **before** the spawn is the one the run actually measured,
461
- * so that is the value written, and a post-run digest that disagrees means
462
- * the artifact describes a tree nobody has any more: no stamp is written at
463
- * all, and the next reader captures rather than crediting a run against
464
- * sources it never saw.
465
- *
466
- * A `null` on either digest is "unavailable", not "changed" — the same
467
- * fail-open the pre-#5278 code had, since without a digest there is nothing
468
- * to stamp.
352
+ * Stamp the pre-spawn digest (the tree the run measured), and write nothing
353
+ * when the post-run digest differs — the artifact then describes a tree no
354
+ * longer on disk. A `null` post-digest is "unavailable", not "changed".
469
355
  *
470
356
  * @param {{
471
357
  * preDigest: string|null,
@@ -520,12 +406,7 @@ export function stampCapturedTree({
520
406
  }
521
407
 
522
408
  /**
523
- * Narrow `changedFiles` to the subset that lives under one of `targetDirs`.
524
- *
525
- * Both inputs are forward-slash-normalised; `targetDirs` are matched as path
526
- * prefixes followed by `/`. Shared by `anyChangedUnderTargets` (the pre-push
527
- * fast-path boolean) and the incremental-coverage scope resolver (Story
528
- * #4981), which needs the actual file list rather than a yes/no.
409
+ * Changed files under a `targetDirs` prefix, forward-slash-normalised.
529
410
  *
530
411
  * @param {string[]} changedFiles
531
412
  * @param {string[]} targetDirs
@@ -543,11 +424,7 @@ export function filterFilesUnderTargets(changedFiles, targetDirs) {
543
424
  }
544
425
 
545
426
  /**
546
- * Decide whether any of `changedFiles` lives under one of `targetDirs`.
547
- * Used by the pre-push fast-path so we can skip the (slow) coverage capture
548
- * when the push touches only files outside the CRAP scoring scope.
549
- *
550
- * An empty changed-file list returns `false`.
427
+ * Pre-push fast path: skip capture when nothing in CRAP scope changed.
551
428
  *
552
429
  * @param {string[]} changedFiles
553
430
  * @param {string[]} targetDirs
@@ -557,75 +434,73 @@ export function anyChangedUnderTargets(changedFiles, targetDirs) {
557
434
  return filterFilesUnderTargets(changedFiles, targetDirs).length > 0;
558
435
  }
559
436
 
560
- /**
561
- * Exit code surfaced when the bounded `npm run test:coverage` spawn was
562
- * killed by the timeout watchdog. Matches the GNU `timeout(1)` convention so
563
- * the close-validation caller can branch on "hang" (124) vs. "tests failed"
564
- * (any other non-zero status). Story #2136 / Task #2142.
565
- */
566
- export const COVERAGE_TIMEOUT_EXIT_CODE = 124;
437
+ /** GNU `timeout(1)` code, so callers tell a hang (124) from failing tests. */
438
+ export const COVERAGE_TIMEOUT_EXIT_CODE = TIMEOUT_EXIT_CODE;
567
439
 
568
440
  /**
569
- * Spawn `npm run test:coverage` in `cwd` with a bounded wall clock. Inherits
570
- * stdio so the operator sees the raw test output. Returns the exit status; a
571
- * non-zero exit means the caller should propagate the failure (a broken test
572
- * suite cannot be papered over by the CRAP gate).
573
- *
574
- * The `timeoutMs` budget is enforced by `spawnSync` with `killSignal:
575
- * 'SIGKILL'` — Node fires the signal at the budget boundary and the result
576
- * surfaces with `signal: 'SIGKILL'`. We translate that into the GNU
577
- * `timeout(1)` convention exit code 124 so callers can pattern-match a
578
- * runaway runner without inspecting signal names.
579
- *
580
- * The spawn takes **no positional file arguments**. Story #4981 forwarded the
581
- * changed-file list as `npm run test:coverage -- <files...>` on the premise
582
- * that a test runner treats trailing positionals as filters over the suite.
583
- * Node's runner does not: it treats each path as a test file to execute, so a
584
- * forwarded *source* file runs as a trivially-passing test and the real suite
585
- * never runs. `run-coverage.js` discarded the list, which is the only reason
586
- * that never bit; Story #5063 measured it and Story #5065 removed the
587
- * plumbing rather than leave a parameter whose obvious "fix" empties the
588
- * coverage artifact.
441
+ * Spawn `npm run test:coverage` asynchronously as its own process group, so
442
+ * the lock heartbeat keeps running and a timeout or signal kills every
443
+ * worker. Takes no positional file args: node's runner would execute a
444
+ * forwarded source file as a test instead of filtering the suite.
589
445
  *
590
446
  * @param {{
591
447
  * cwd: string,
592
448
  * timeoutMs?: number,
593
- * runner?: typeof spawnSync,
449
+ * spawnImpl?: typeof spawn,
594
450
  * log?: (m: string) => void,
595
451
  * }} opts
596
- * @returns {number}
452
+ * @returns {Promise<number>}
597
453
  */
598
454
  export function runCapture({
599
455
  cwd,
600
456
  timeoutMs,
601
- runner = spawnSync,
457
+ spawnImpl = spawn,
602
458
  log = () => {},
603
459
  } = {}) {
604
460
  const args = ['run', 'test:coverage'];
605
461
  log(`[coverage-capture] ▶ npm ${args.join(' ')}`);
606
- const spawnOpts = {
607
- cwd,
608
- stdio: 'inherit',
609
- shell: process.platform === 'win32',
610
- killSignal: 'SIGKILL',
611
- };
612
- if (
613
- typeof timeoutMs === 'number' &&
614
- Number.isFinite(timeoutMs) &&
615
- timeoutMs > 0
616
- ) {
617
- spawnOpts.timeout = timeoutMs;
618
- }
619
- const res = runner('npm', args, spawnOpts);
620
- // A timeout-induced kill surfaces as `signal: 'SIGKILL'` (or, on some
621
- // platforms, as a non-numeric status). Either signal indicates the
622
- // watchdog tripped — surface the GNU `timeout` convention 124 so the
623
- // caller can distinguish a hang from a normal test-suite failure.
624
- if (res?.signal === 'SIGKILL') {
625
- log(
626
- `[coverage-capture] ⏱ npm run test:coverage exceeded ${timeoutMs}ms — killed (SIGKILL). Returning exit ${COVERAGE_TIMEOUT_EXIT_CODE}.`,
462
+ return new Promise((resolve) => {
463
+ const child = spawnImpl('npm', args, {
464
+ cwd,
465
+ stdio: 'inherit',
466
+ shell: process.platform === 'win32',
467
+ ...groupSpawnOptions(),
468
+ });
469
+ const supervisor = superviseGroup(child, { timeoutMs });
470
+ child.on('error', () => {
471
+ supervisor.release();
472
+ resolve(1);
473
+ });
474
+ child.on('exit', (code) => {
475
+ supervisor.release();
476
+ if (!supervisor.timedOut) {
477
+ resolve(code ?? 1);
478
+ return;
479
+ }
480
+ log(
481
+ `[coverage-capture] ⏱ npm run test:coverage exceeded ${timeoutMs}ms — killed its process group. Returning exit ${COVERAGE_TIMEOUT_EXIT_CODE}.`,
482
+ );
483
+ resolve(COVERAGE_TIMEOUT_EXIT_CODE);
484
+ });
485
+ });
486
+ }
487
+
488
+ /**
489
+ * Report a non-zero capture; an expired lock wait is not a failing suite.
490
+ *
491
+ * @param {number} code
492
+ * @param {{ info: Function, error: Function }} logger
493
+ * @returns {number}
494
+ */
495
+ export function reportCaptureFailure(code, logger) {
496
+ if (code === LOCK_WAIT_EXPIRED_EXIT_CODE) {
497
+ logger.info(
498
+ `[coverage-capture] ⏸ the full-suite lock wait expired and this capture was deferred — no suite ran. Exiting ${code}.`,
627
499
  );
628
- return COVERAGE_TIMEOUT_EXIT_CODE;
500
+ return code;
629
501
  }
630
- return res.status ?? 1;
502
+ logger.error(
503
+ `[coverage-capture] ✖ npm run test:coverage exited ${code}. Fix failing tests or coverage-threshold breaches before re-running the CRAP gate.`,
504
+ );
505
+ return code;
631
506
  }
@@ -4,12 +4,7 @@ const COVERAGE_INDEX = Symbol('coverage-utils.coverage-index');
4
4
  const ENTRY_INDEX = Symbol('coverage-utils.entry-index');
5
5
 
6
6
  /**
7
- * Load and parse an istanbul/c8 `coverage-final.json` artifact.
8
- *
9
- * Returns the parsed object (keyed by absolute file path) on success, or
10
- * `null` when the file is missing, unreadable, non-JSON, or structurally
11
- * unusable. Never throws — consumers treat a null map as "no coverage
12
- * available" and apply their own `requireCoverage` policy.
7
+ * Never throws; `null` for any missing or unusable artifact.
13
8
  *
14
9
  * @param {string} coveragePath
15
10
  * @returns {object|null}
@@ -37,12 +32,7 @@ function stripLeadingDotSlash(p) {
37
32
  }
38
33
 
39
34
  /**
40
- * Build a single-pass index over a parsed `coverage-final.json` map.
41
- *
42
- * Returns `{map, byNormalizedSuffix}` where `byNormalizedSuffix` is a
43
- * `Map<string, object>` keyed by the POSIX-normalized form of each original
44
- * key. Lookups that need exact-equality or `/`-bounded suffix matching
45
- * consult that Map without re-enumerating `Object.keys(map)` on every call.
35
+ * Entries keyed by POSIX-normalized path.
46
36
  *
47
37
  * @param {object|null} map
48
38
  * @returns {{map: object|null, byNormalizedSuffix: Map<string, object>}}
@@ -72,15 +62,8 @@ function getCoverageIndex(map) {
72
62
  }
73
63
 
74
64
  /**
75
- * Locate the coverage entry for a repo-relative path.
76
- *
77
- * `coverage-final.json` keys are typically absolute, platform-specific paths,
78
- * while callers pass POSIX-ish repo-relative strings. Match by exact equality
79
- * or by `/`-bounded suffix so we tolerate both Windows and POSIX producers.
80
- * If two distinct keys both end with the same `/`-bounded suffix (duplicate
81
- * basenames in different trees), the suffix is ambiguous — return null
82
- * rather than picking the first iteration-order hit and silently scoring
83
- * the wrong file.
65
+ * Match a repo-relative path to an absolute key by exact or `/`-bounded
66
+ * suffix. An ambiguous suffix returns null rather than scoring the wrong file.
84
67
  */
85
68
  function findFileEntry(map, relPath) {
86
69
  if (!map || !relPath) return null;
@@ -103,8 +86,6 @@ function findFileEntry(map, relPath) {
103
86
  export { findFileEntry as findCoverageEntry };
104
87
 
105
88
  /**
106
- * Does the map contain any entry whose path matches `relPath`?
107
- *
108
89
  * @param {object|null} map
109
90
  * @param {string} relPath
110
91
  * @returns {boolean}
@@ -114,17 +95,8 @@ export function hasCoverageFor(map, relPath) {
114
95
  }
115
96
 
116
97
  /**
117
- * Build a per-entry index that turns method-coverage lookups from
118
- * `O(fnCount + statementCount)` per call into `O(method-line-span)`.
119
- *
120
- * - `fnByStartLine`: maps either `decl.start.line` or `loc.start.line` to the
121
- * raw `fnMap` entry — so callers may key by the escomplex `lineStart`
122
- * (which can match either, depending on producer).
123
- * - `fnLocByStartLine`: same keying, value is `{fnStart, fnEnd}` derived once.
124
- * - `fnRanges`: every function's `{fnStart, fnEnd, declLine}` triple, used by
125
- * the containment / nearest-decl fallbacks when exact-line keying misses.
126
- * - `statementsByLine`: `Map<line, {total, covered}>` so range scans don't
127
- * re-walk the full statement map.
98
+ * Per-entry index making a method lookup `O(method-line-span)`. Functions are
99
+ * keyed by both `decl` and `loc` start lines (producers differ).
128
100
  *
129
101
  * @param {object|null} entry One inner value from a `coverage-final.json` map.
130
102
  */
@@ -181,36 +153,15 @@ export function buildEntryIndex(entry) {
181
153
  }
182
154
 
183
155
  /**
184
- * How far from a `fnMap` declaration line a method start may sit and still
185
- * be considered the same function.
186
- *
187
- * Even after remapping to original-source coordinates (Story #4775), a
188
- * method's start and istanbul's `decl.start.line` do not always agree on the
189
- * token: escomplex anchors on the function node, istanbul on the declaration
190
- * it instruments, and a decorator, a leading `export`, or a multi-line
191
- * parameter list puts them one line apart. One line of slack absorbs that
192
- * without letting an unrelated neighbouring function be claimed.
156
+ * escomplex and istanbul can disagree by one line on a function's start
157
+ * (decorator, leading `export`, multi-line params); wider would claim a
158
+ * neighbour.
193
159
  */
194
160
  const DECL_MATCH_WINDOW = 1;
195
161
 
196
162
  /**
197
- * Resolve the `{fnStart, fnEnd}` range of the function a method start line
198
- * belongs to, in the coordinate system of the coverage entry.
199
- *
200
- * Three strategies, most precise first:
201
- *
202
- * 1. **Exact** — the line keys a `fnMap` `decl.start.line` or
203
- * `loc.start.line`. This is the pre-#4775 behaviour and still wins, so
204
- * every already-resolving row keeps its exact prior value.
205
- * 2. **Containment** — the innermost function whose `loc` range contains
206
- * the line. Smallest span wins, so a nested callback is preferred over
207
- * the enclosing function that also contains the line.
208
- * 3. **Nearest declaration** — the closest `decl` line within
209
- * `DECL_MATCH_WINDOW`, which absorbs the ±1 token disagreement between
210
- * escomplex's method start and istanbul's declaration line.
211
- *
212
- * Returns `null` when none of the three finds a function — the caller
213
- * surfaces that as "no data" rather than "tested zero times."
163
+ * Exact start line, else innermost containing range, else nearest `decl`
164
+ * within `DECL_MATCH_WINDOW`; `null` means "no data", not "untested".
214
165
  *
215
166
  * @param {{fnByStartLine: Map, fnLocByStartLine: Map, fnRanges: Array}} idx
216
167
  * @param {number} startLine
@@ -264,23 +215,9 @@ function getEntryIndex(entry) {
264
215
  }
265
216
 
266
217
  /**
267
- * Compute the statement-coverage ratio for a single method inside a single
268
- * file's coverage entry.
269
- *
270
- * The ratio is the fraction of statements whose `start.line` falls within the
271
- * function's `loc` range that were executed at least once. An empty range
272
- * returns 0. A missing / malformed entry or no matching function returns
273
- * `null` so the caller can distinguish "no data" from "tested zero times."
274
- *
275
- * `startLine` MUST be in the coverage entry's own (original-source)
276
- * coordinate system. Callers scoring transpiled TypeScript remap escomplex's
277
- * transpiled `lineStart` first — see `transpileIfNeeded`'s `withLineMap`
278
- * option (Story #4775). Matching is exact-then-containment-then-nearest-decl;
279
- * see `resolveFnRangeForLine`.
280
- *
281
- * The first call on a given entry builds and caches a per-entry index via a
282
- * non-enumerable Symbol property; consecutive method lookups in the same
283
- * file pay the build cost exactly once.
218
+ * Executed fraction of statements in the method's range (0 for an empty
219
+ * range, `null` for no data). `startLine` MUST be in original-source
220
+ * coordinates. The entry index is cached on the entry.
284
221
  *
285
222
  * @param {object|null} entry One inner value from a `coverage-final.json` map.
286
223
  * @param {number} startLine The method's start line, in entry coordinates.
@@ -307,8 +244,6 @@ export function coverageForMethodInEntry(entry, startLine) {
307
244
  }
308
245
 
309
246
  /**
310
- * Look up per-method coverage in a full coverage map.
311
- *
312
247
  * @param {object|null} map Parsed `coverage-final.json`.
313
248
  * @param {string} relPath Repo-relative path of the source file.
314
249
  * @param {number} startLine The method's start line, in entry coordinates.