mandrel 2.59.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 (678) hide show
  1. package/.agents/README.md +21 -19
  2. package/.agents/agents/acceptance-critic.md +24 -43
  3. package/.agents/agents/story-worker.md +20 -21
  4. package/.agents/docs/agentrc-reference.json +5 -84
  5. package/.agents/docs/configuration.md +48 -132
  6. package/.agents/docs/workflows.md +2 -2
  7. package/.agents/instructions.md +5 -8
  8. package/.agents/rules/ci-remediation.md +41 -8
  9. package/.agents/rules/gherkin-standards.md +4 -0
  10. package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
  11. package/.agents/schemas/agentrc.schema.json +16 -496
  12. package/.agents/schemas/story-deliver-terminal.schema.json +13 -3
  13. package/.agents/schemas/validation-evidence.schema.json +2 -1
  14. package/.agents/scripts/README.md +23 -13
  15. package/.agents/scripts/acceptance-eval.js +35 -169
  16. package/.agents/scripts/agents-bootstrap-github.js +27 -129
  17. package/.agents/scripts/apply-quality-bootstrap.js +4 -40
  18. package/.agents/scripts/audit-baselines.js +6 -27
  19. package/.agents/scripts/audit-labels-bootstrap.js +5 -29
  20. package/.agents/scripts/audit-to-stories.js +91 -361
  21. package/.agents/scripts/boot-sweep.js +19 -72
  22. package/.agents/scripts/bootstrap.js +74 -395
  23. package/.agents/scripts/ceremony-derive.js +10 -41
  24. package/.agents/scripts/check-arch-cycles.js +14 -64
  25. package/.agents/scripts/check-baselines.js +8 -48
  26. package/.agents/scripts/check-context-budget.js +105 -311
  27. package/.agents/scripts/check-cyclomatic.js +12 -44
  28. package/.agents/scripts/check-dead-exports.js +13 -64
  29. package/.agents/scripts/check-doc-links.js +38 -186
  30. package/.agents/scripts/check-gherkin-corpus.js +24 -127
  31. package/.agents/scripts/check-test-temp-hygiene.js +28 -169
  32. package/.agents/scripts/coverage-capture.js +34 -98
  33. package/.agents/scripts/deliver-light.js +25 -171
  34. package/.agents/scripts/deliver-recover.js +6 -42
  35. package/.agents/scripts/deliver-run.js +534 -0
  36. package/.agents/scripts/diagnose-friction.js +24 -116
  37. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  38. package/.agents/scripts/evidence-gate.js +23 -85
  39. package/.agents/scripts/file-ci-gap.js +57 -49
  40. package/.agents/scripts/generate-config-docs.js +30 -170
  41. package/.agents/scripts/generate-lens-checklists.js +8 -52
  42. package/.agents/scripts/generate-skills-index.js +14 -112
  43. package/.agents/scripts/generate-workflows-doc.js +10 -70
  44. package/.agents/scripts/git-cleanup.js +2 -34
  45. package/.agents/scripts/lib/Graph.js +24 -81
  46. package/.agents/scripts/lib/ITicketingProvider.js +47 -143
  47. package/.agents/scripts/lib/Logger.js +14 -76
  48. package/.agents/scripts/lib/audit-baselines/engine.js +11 -31
  49. package/.agents/scripts/lib/audit-baselines/gate-surface.js +3 -17
  50. package/.agents/scripts/lib/audit-baselines/headroom.js +4 -20
  51. package/.agents/scripts/lib/audit-baselines/hotspots.js +3 -15
  52. package/.agents/scripts/lib/audit-baselines/kinds.js +23 -89
  53. package/.agents/scripts/lib/audit-baselines/outliers.js +6 -23
  54. package/.agents/scripts/lib/audit-baselines/read.js +3 -16
  55. package/.agents/scripts/lib/audit-baselines/staleness.js +7 -26
  56. package/.agents/scripts/lib/audit-baselines/surface-entry.js +7 -28
  57. package/.agents/scripts/lib/audit-baselines/trend.js +7 -20
  58. package/.agents/scripts/lib/audit-baselines/weights.js +9 -37
  59. package/.agents/scripts/lib/audit-suite/audit-rules-reader.js +3 -18
  60. package/.agents/scripts/lib/audit-suite/checklist-threading.js +26 -124
  61. package/.agents/scripts/lib/audit-suite/dispatch-checklist.js +14 -45
  62. package/.agents/scripts/lib/audit-suite/findings.js +12 -52
  63. package/.agents/scripts/lib/audit-suite/frontmatter.js +5 -29
  64. package/.agents/scripts/lib/audit-suite/index.js +1 -15
  65. package/.agents/scripts/lib/audit-suite/lens-checklist.js +10 -45
  66. package/.agents/scripts/lib/audit-suite/lens-diff-floor.js +11 -76
  67. package/.agents/scripts/lib/audit-suite/runner.js +13 -43
  68. package/.agents/scripts/lib/audit-suite/selector.js +49 -349
  69. package/.agents/scripts/lib/audit-suite/substitutions.js +12 -40
  70. package/.agents/scripts/lib/audit-suite/workflow-loader.js +3 -15
  71. package/.agents/scripts/lib/audit-to-stories/audit-label-taxonomy.js +11 -73
  72. package/.agents/scripts/lib/audit-to-stories/audit-lenses.js +8 -37
  73. package/.agents/scripts/lib/audit-to-stories/build-story-body.js +25 -143
  74. package/.agents/scripts/lib/audit-to-stories/dedupe-against-github.js +14 -80
  75. package/.agents/scripts/lib/audit-to-stories/epic-grouping-directive.js +4 -18
  76. package/.agents/scripts/lib/audit-to-stories/finding-adapter.js +7 -40
  77. package/.agents/scripts/lib/audit-to-stories/group-findings.js +9 -39
  78. package/.agents/scripts/lib/audit-to-stories/issue-corpus.js +10 -66
  79. package/.agents/scripts/lib/audit-to-stories/issue-index.js +6 -30
  80. package/.agents/scripts/lib/audit-to-stories/issues-file.js +6 -36
  81. package/.agents/scripts/lib/audit-to-stories/ledger-commit.js +17 -69
  82. package/.agents/scripts/lib/audit-to-stories/ledger-pr.js +17 -85
  83. package/.agents/scripts/lib/audit-to-stories/ledger-record.js +10 -48
  84. package/.agents/scripts/lib/audit-to-stories/parse-audit-md.js +38 -146
  85. package/.agents/scripts/lib/audit-to-stories/seed-from-findings.js +7 -42
  86. package/.agents/scripts/lib/audit-to-stories/wire-dependencies.js +10 -57
  87. package/.agents/scripts/lib/baseline-loader.js +12 -51
  88. package/.agents/scripts/lib/baseline-schema-registry.js +5 -22
  89. package/.agents/scripts/lib/baselines/component-matcher.js +3 -12
  90. package/.agents/scripts/lib/baselines/components.js +10 -61
  91. package/.agents/scripts/lib/baselines/coverage-updater-cli.js +7 -36
  92. package/.agents/scripts/lib/baselines/crap-preview-incremental.js +7 -19
  93. package/.agents/scripts/lib/baselines/crap-preview-scan.js +19 -45
  94. package/.agents/scripts/lib/baselines/crap-updater-cli.js +16 -65
  95. package/.agents/scripts/lib/baselines/diff-scope-cli.js +5 -33
  96. package/.agents/scripts/lib/baselines/duplication-scanner.js +11 -60
  97. package/.agents/scripts/lib/baselines/env-overrides.js +12 -67
  98. package/.agents/scripts/lib/baselines/envelope.js +13 -129
  99. package/.agents/scripts/lib/baselines/exit-codes.js +6 -49
  100. package/.agents/scripts/lib/baselines/git-base.js +23 -142
  101. package/.agents/scripts/lib/baselines/kernel.js +11 -111
  102. package/.agents/scripts/lib/baselines/kinds/_crap-new-method-gate.js +9 -47
  103. package/.agents/scripts/lib/baselines/kinds/_crap-read.js +8 -51
  104. package/.agents/scripts/lib/baselines/kinds/_shared-metric.js +7 -62
  105. package/.agents/scripts/lib/baselines/kinds/bundle-size.js +8 -29
  106. package/.agents/scripts/lib/baselines/kinds/coverage.js +3 -15
  107. package/.agents/scripts/lib/baselines/kinds/crap.js +94 -415
  108. package/.agents/scripts/lib/baselines/kinds/duplication.js +4 -30
  109. package/.agents/scripts/lib/baselines/kinds/kind-factory.js +7 -53
  110. package/.agents/scripts/lib/baselines/kinds/maintainability.js +15 -80
  111. package/.agents/scripts/lib/baselines/kinds/mutation.js +12 -72
  112. package/.agents/scripts/lib/baselines/maintainability-baseline-io.js +4 -11
  113. package/.agents/scripts/lib/baselines/merge-envelopes.js +30 -146
  114. package/.agents/scripts/lib/baselines/path-canon.js +19 -128
  115. package/.agents/scripts/lib/baselines/preview-gates.js +8 -37
  116. package/.agents/scripts/lib/baselines/reader.js +14 -107
  117. package/.agents/scripts/lib/baselines/refresh-service.js +35 -252
  118. package/.agents/scripts/lib/baselines/scope.js +11 -135
  119. package/.agents/scripts/lib/baselines/writer.js +16 -149
  120. package/.agents/scripts/lib/bdd-runner-detect.js +18 -113
  121. package/.agents/scripts/lib/bdd-scenario-budget.js +9 -36
  122. package/.agents/scripts/lib/bdd-scenario-scanner.js +11 -73
  123. package/.agents/scripts/lib/bdd-step-index.js +26 -100
  124. package/.agents/scripts/lib/bootstrap/baseline-merge-driver.js +23 -103
  125. package/.agents/scripts/lib/bootstrap/branch-protection.js +2 -5
  126. package/.agents/scripts/lib/bootstrap/commit-push.js +12 -50
  127. package/.agents/scripts/lib/bootstrap/gh-preflight.js +14 -101
  128. package/.agents/scripts/lib/bootstrap/hitl-confirm.js +5 -30
  129. package/.agents/scripts/lib/bootstrap/install-ledger.js +17 -73
  130. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +17 -121
  131. package/.agents/scripts/lib/bootstrap/manifest.js +15 -86
  132. package/.agents/scripts/lib/bootstrap/merge-methods.js +4 -33
  133. package/.agents/scripts/lib/bootstrap/preflight.js +12 -61
  134. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +34 -235
  135. package/.agents/scripts/lib/bootstrap/prompt.js +21 -129
  136. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +27 -141
  137. package/.agents/scripts/lib/bootstrap/summary.js +1 -8
  138. package/.agents/scripts/lib/bootstrap/workflow-audit.js +11 -84
  139. package/.agents/scripts/lib/branch-name-guard.js +4 -23
  140. package/.agents/scripts/lib/changed-files.js +39 -121
  141. package/.agents/scripts/lib/checks/core-bare-clean.js +4 -24
  142. package/.agents/scripts/lib/checks/index.js +18 -101
  143. package/.agents/scripts/lib/checks/loop-health.js +11 -53
  144. package/.agents/scripts/lib/checks/state.js +16 -91
  145. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +10 -61
  146. package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +14 -83
  147. package/.agents/scripts/lib/child-exec.js +39 -108
  148. package/.agents/scripts/lib/cli/standard-args.js +9 -116
  149. package/.agents/scripts/lib/cli-args.js +31 -146
  150. package/.agents/scripts/lib/cli-usage.js +5 -27
  151. package/.agents/scripts/lib/cli-utils.js +2 -12
  152. package/.agents/scripts/lib/close-validation/commands.js +13 -76
  153. package/.agents/scripts/lib/close-validation/gates.js +92 -331
  154. package/.agents/scripts/lib/close-validation/process.js +121 -151
  155. package/.agents/scripts/lib/close-validation/projections/advisories.js +5 -31
  156. package/.agents/scripts/lib/close-validation/projections/crap.js +19 -67
  157. package/.agents/scripts/lib/close-validation/projections/head-sha.js +1 -17
  158. package/.agents/scripts/lib/close-validation/projections/inputs.js +4 -34
  159. package/.agents/scripts/lib/close-validation/projections/maintainability.js +11 -58
  160. package/.agents/scripts/lib/close-validation/runner.js +53 -110
  161. package/.agents/scripts/lib/command-header.js +6 -28
  162. package/.agents/scripts/lib/config/acceptance-eval.js +4 -30
  163. package/.agents/scripts/lib/config/baselines.js +3 -14
  164. package/.agents/scripts/lib/config/ci.js +8 -38
  165. package/.agents/scripts/lib/config/commands.js +1 -15
  166. package/.agents/scripts/lib/config/defaults.js +4 -33
  167. package/.agents/scripts/lib/config/delivery-routing.js +6 -34
  168. package/.agents/scripts/lib/config/explain.js +10 -83
  169. package/.agents/scripts/lib/config/gates/coverage.schema.js +0 -12
  170. package/.agents/scripts/lib/config/gates/crap-incremental-coverage.schema.js +3 -31
  171. package/.agents/scripts/lib/config/gates/crap.schema.js +1 -34
  172. package/.agents/scripts/lib/config/gates/duplication.schema.js +1 -8
  173. package/.agents/scripts/lib/config/gates/index.js +2 -17
  174. package/.agents/scripts/lib/config/gates/maintainability.schema.js +1 -20
  175. package/.agents/scripts/lib/config/gates/mutation.schema.js +1 -7
  176. package/.agents/scripts/lib/config/gates/shared.js +4 -64
  177. package/.agents/scripts/lib/config/github.js +4 -22
  178. package/.agents/scripts/lib/config/limits.js +4 -57
  179. package/.agents/scripts/lib/config/paths.js +2 -21
  180. package/.agents/scripts/lib/config/qa.js +4 -38
  181. package/.agents/scripts/lib/config/quality.js +76 -432
  182. package/.agents/scripts/lib/config/runners.js +12 -56
  183. package/.agents/scripts/lib/config/runtime.js +13 -57
  184. package/.agents/scripts/lib/config/shared.js +2 -16
  185. package/.agents/scripts/lib/config/sync-agentrc.js +9 -50
  186. package/.agents/scripts/lib/config/temp-paths.js +40 -280
  187. package/.agents/scripts/lib/config/validate-orchestration.js +5 -17
  188. package/.agents/scripts/lib/config/worktree-isolation.js +9 -28
  189. package/.agents/scripts/lib/config-resolver.js +11 -52
  190. package/.agents/scripts/lib/config-schema-shared.js +1 -4
  191. package/.agents/scripts/lib/config-settings-schema-delivery.js +16 -291
  192. package/.agents/scripts/lib/config-settings-schema-quality.js +7 -219
  193. package/.agents/scripts/lib/config-settings-schema.js +37 -274
  194. package/.agents/scripts/lib/coverage-baseline.js +20 -110
  195. package/.agents/scripts/lib/coverage-capture-fullscope.js +18 -35
  196. package/.agents/scripts/lib/coverage-capture-incremental.js +15 -45
  197. package/.agents/scripts/lib/coverage-capture-usage.js +8 -25
  198. package/.agents/scripts/lib/coverage-capture.js +99 -224
  199. package/.agents/scripts/lib/coverage-utils.js +14 -79
  200. package/.agents/scripts/lib/cpu-pool.js +17 -123
  201. package/.agents/scripts/lib/crap-baseline-join.js +16 -88
  202. package/.agents/scripts/lib/crap-coordinates.js +6 -25
  203. package/.agents/scripts/lib/crap-engine.js +40 -153
  204. package/.agents/scripts/lib/crap-method-identity.js +16 -78
  205. package/.agents/scripts/lib/crap-utils.js +31 -155
  206. package/.agents/scripts/lib/cyclomatic-ceiling.js +14 -87
  207. package/.agents/scripts/lib/cyclomatic-scope.js +10 -50
  208. package/.agents/scripts/lib/dead-exports-knip.js +18 -56
  209. package/.agents/scripts/lib/dead-exports-mode.js +5 -24
  210. package/.agents/scripts/lib/degraded-mode.js +3 -26
  211. package/.agents/scripts/lib/dependency-parser.js +8 -40
  212. package/.agents/scripts/lib/dependency-version.js +13 -35
  213. package/.agents/scripts/lib/detect-package-manager.js +6 -36
  214. package/.agents/scripts/lib/doc-tiers.js +22 -124
  215. package/.agents/scripts/lib/duplicate-search.js +8 -72
  216. package/.agents/scripts/lib/env-loader.js +5 -27
  217. package/.agents/scripts/lib/error-redactor.js +6 -31
  218. package/.agents/scripts/lib/errors/index.js +2 -22
  219. package/.agents/scripts/lib/escomplex-ast-compat.js +22 -163
  220. package/.agents/scripts/lib/escomplex-kernel.js +21 -123
  221. package/.agents/scripts/lib/feedback-loop/graduator-core.js +94 -419
  222. package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +20 -98
  223. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +27 -149
  224. package/.agents/scripts/lib/findings/audit-ledger.js +23 -97
  225. package/.agents/scripts/lib/findings/classify-finding.js +14 -69
  226. package/.agents/scripts/lib/findings/promote-finding.js +14 -112
  227. package/.agents/scripts/lib/findings/provenance-field.js +11 -52
  228. package/.agents/scripts/lib/findings/route-finding.js +37 -255
  229. package/.agents/scripts/lib/findings/semantic-issue-search.js +14 -59
  230. package/.agents/scripts/lib/findings/severity.js +18 -104
  231. package/.agents/scripts/lib/format-generated-json.js +12 -44
  232. package/.agents/scripts/lib/full-suite-lock.js +160 -429
  233. package/.agents/scripts/lib/full-suite-queue.js +213 -0
  234. package/.agents/scripts/lib/gates/baseline-store.js +5 -9
  235. package/.agents/scripts/lib/gates/friction.js +1 -3
  236. package/.agents/scripts/lib/generated/agentrc-validator.js +2 -2
  237. package/.agents/scripts/lib/gh-exec.js +123 -191
  238. package/.agents/scripts/lib/git/cached-fetch.js +9 -52
  239. package/.agents/scripts/lib/git/sync-from-base.js +15 -107
  240. package/.agents/scripts/lib/git-branch-cleanup.js +14 -61
  241. package/.agents/scripts/lib/git-branch-lifecycle.js +16 -87
  242. package/.agents/scripts/lib/git-utils.js +37 -161
  243. package/.agents/scripts/lib/github/framework-repo.js +8 -71
  244. package/.agents/scripts/lib/github-url.js +2 -17
  245. package/.agents/scripts/lib/import-graph.js +11 -38
  246. package/.agents/scripts/lib/install-cmd-parser.js +4 -13
  247. package/.agents/scripts/lib/json-utils.js +3 -18
  248. package/.agents/scripts/lib/label-constants.js +16 -111
  249. package/.agents/scripts/lib/label-taxonomy.js +4 -30
  250. package/.agents/scripts/lib/maintainability-engine.js +12 -80
  251. package/.agents/scripts/lib/maintainability-unscorable.js +5 -25
  252. package/.agents/scripts/lib/maintainability-utils.js +16 -92
  253. package/.agents/scripts/lib/mandrel-catalog.js +12 -70
  254. package/.agents/scripts/lib/notifications/notifier.js +13 -38
  255. package/.agents/scripts/lib/npm-scripts.js +4 -23
  256. package/.agents/scripts/lib/observability/metrics-ledger.js +16 -76
  257. package/.agents/scripts/lib/observability/runtime-friction.js +44 -286
  258. package/.agents/scripts/lib/observability/signal-validator.js +5 -37
  259. package/.agents/scripts/lib/observability/signals-writer.js +11 -121
  260. package/.agents/scripts/lib/observability/source-classifier.js +22 -203
  261. package/.agents/scripts/lib/observability/terse-result.js +14 -47
  262. package/.agents/scripts/lib/onboard/init-tail.js +13 -74
  263. package/.agents/scripts/lib/onboard/scaffold-docs.js +11 -34
  264. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +25 -139
  265. package/.agents/scripts/lib/orchestration/auto-merge-cwd.js +11 -66
  266. package/.agents/scripts/lib/orchestration/behind-recovery.js +10 -55
  267. package/.agents/scripts/lib/orchestration/ceremony-routing.js +28 -156
  268. package/.agents/scripts/lib/orchestration/change-set.js +7 -36
  269. package/.agents/scripts/lib/orchestration/check-baselines/phases/compare.js +9 -46
  270. package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +11 -44
  271. package/.agents/scripts/lib/orchestration/check-baselines/phases/floors.js +5 -24
  272. package/.agents/scripts/lib/orchestration/check-baselines/phases/friction.js +3 -12
  273. package/.agents/scripts/lib/orchestration/check-baselines/phases/parse-args.js +5 -38
  274. package/.agents/scripts/lib/orchestration/check-baselines/phases/pipeline.js +3 -8
  275. package/.agents/scripts/lib/orchestration/check-baselines/phases/refresh-ack.js +28 -136
  276. package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +3 -13
  277. package/.agents/scripts/lib/orchestration/check-state.js +92 -0
  278. package/.agents/scripts/lib/orchestration/ci-gap-intake.js +37 -144
  279. package/.agents/scripts/lib/orchestration/ci-rerun-guard.js +121 -157
  280. package/.agents/scripts/lib/orchestration/code-review.js +24 -128
  281. package/.agents/scripts/lib/orchestration/column-sync.js +23 -111
  282. package/.agents/scripts/lib/orchestration/complexity-gate.js +118 -462
  283. package/.agents/scripts/lib/orchestration/deliver-recover.js +36 -168
  284. package/.agents/scripts/lib/orchestration/dependency-analyzer.js +4 -35
  285. package/.agents/scripts/lib/orchestration/dependency-candidates.js +9 -41
  286. package/.agents/scripts/lib/orchestration/diff-magnitude.js +25 -115
  287. package/.agents/scripts/lib/orchestration/doc-reader.js +2 -6
  288. package/.agents/scripts/lib/orchestration/docs-digest.js +13 -51
  289. package/.agents/scripts/lib/orchestration/epic-candidates.js +13 -53
  290. package/.agents/scripts/lib/orchestration/epic-checklist.js +9 -33
  291. package/.agents/scripts/lib/orchestration/epic-container.js +41 -167
  292. package/.agents/scripts/lib/orchestration/epic-expansion.js +10 -40
  293. package/.agents/scripts/lib/orchestration/epic-rollup.js +55 -207
  294. package/.agents/scripts/lib/orchestration/file-assumption-enum.js +2 -22
  295. package/.agents/scripts/lib/orchestration/file-assumptions.js +45 -253
  296. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-detect.js +9 -46
  297. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-reap.js +7 -57
  298. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches.js +21 -126
  299. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +2 -6
  300. package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +1 -4
  301. package/.agents/scripts/lib/orchestration/git-cleanup/phases/filters.js +1 -5
  302. package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes-ff.js +9 -34
  303. package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes.js +41 -190
  304. package/.agents/scripts/lib/orchestration/git-cleanup/phases/merged-tip.js +9 -45
  305. package/.agents/scripts/lib/orchestration/git-cleanup/phases/parse-args.js +1 -4
  306. package/.agents/scripts/lib/orchestration/git-cleanup/phases/phase-drivers.js +19 -85
  307. package/.agents/scripts/lib/orchestration/git-cleanup/phases/prompts.js +3 -17
  308. package/.agents/scripts/lib/orchestration/git-cleanup/phases/prune.js +1 -5
  309. package/.agents/scripts/lib/orchestration/git-cleanup/phases/render.js +16 -100
  310. package/.agents/scripts/lib/orchestration/git-cleanup/phases/stashes.js +1 -4
  311. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +16 -67
  312. package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +9 -33
  313. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +8 -29
  314. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +15 -68
  315. package/.agents/scripts/lib/orchestration/light-backstop.js +11 -49
  316. package/.agents/scripts/lib/orchestration/light-escalation.js +21 -89
  317. package/.agents/scripts/lib/orchestration/light-suitability.js +37 -307
  318. package/.agents/scripts/lib/orchestration/merge-block-class.js +39 -216
  319. package/.agents/scripts/lib/orchestration/merge-poll.js +104 -377
  320. package/.agents/scripts/lib/orchestration/pinned-identifier-lint.js +17 -57
  321. package/.agents/scripts/lib/orchestration/plan-context.js +55 -318
  322. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +22 -79
  323. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +5 -31
  324. package/.agents/scripts/lib/orchestration/plan-metrics.js +29 -108
  325. package/.agents/scripts/lib/orchestration/plan-navigation.js +8 -27
  326. package/.agents/scripts/lib/orchestration/plan-persist/acceptance-handle-repair.js +12 -49
  327. package/.agents/scripts/lib/orchestration/plan-persist/audit-provenance.js +18 -73
  328. package/.agents/scripts/lib/orchestration/plan-persist/changes-repair.js +16 -78
  329. package/.agents/scripts/lib/orchestration/plan-persist/cross-plan-links.js +6 -30
  330. package/.agents/scripts/lib/orchestration/plan-persist/epic-adoption.js +14 -65
  331. package/.agents/scripts/lib/orchestration/plan-persist/epic-ops.js +21 -76
  332. package/.agents/scripts/lib/orchestration/plan-persist/external-deps.js +6 -43
  333. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +14 -68
  334. package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +9 -41
  335. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +71 -289
  336. package/.agents/scripts/lib/orchestration/plan-persist/soft-findings.js +2 -12
  337. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +96 -362
  338. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +9 -39
  339. package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +60 -186
  340. package/.agents/scripts/lib/orchestration/plan-persist/wave-collision-gate.js +9 -49
  341. package/.agents/scripts/lib/orchestration/plan-persist/wave-serialisation.js +7 -28
  342. package/.agents/scripts/lib/orchestration/plan-reachability.js +13 -42
  343. package/.agents/scripts/lib/orchestration/plan-run-labels/reap.js +16 -91
  344. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +16 -54
  345. package/.agents/scripts/lib/orchestration/plan-text-hygiene.js +10 -52
  346. package/.agents/scripts/lib/orchestration/planning/authoring-context.js +14 -109
  347. package/.agents/scripts/lib/orchestration/planning/memory-pool-advisory.js +11 -83
  348. package/.agents/scripts/lib/orchestration/pr-watch.js +48 -306
  349. package/.agents/scripts/lib/orchestration/project-meta-cache.js +15 -80
  350. package/.agents/scripts/lib/orchestration/project-meta-resolver.js +10 -51
  351. package/.agents/scripts/lib/orchestration/reassert-status-column.js +12 -76
  352. package/.agents/scripts/lib/orchestration/remote-verifier.js +12 -36
  353. package/.agents/scripts/lib/orchestration/resolve-stories.js +33 -164
  354. package/.agents/scripts/lib/orchestration/retro-proposals.js +66 -361
  355. package/.agents/scripts/lib/orchestration/review-base-ref.js +9 -43
  356. package/.agents/scripts/lib/orchestration/review-depth.js +12 -91
  357. package/.agents/scripts/lib/orchestration/review-providers/codex.js +10 -111
  358. package/.agents/scripts/lib/orchestration/review-providers/degraded-gates.js +13 -71
  359. package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +7 -51
  360. package/.agents/scripts/lib/orchestration/review-providers/mi-exemptions.js +8 -53
  361. package/.agents/scripts/lib/orchestration/review-providers/native.js +30 -214
  362. package/.agents/scripts/lib/orchestration/review-providers/parse-findings.js +7 -52
  363. package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +4 -33
  364. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +11 -71
  365. package/.agents/scripts/lib/orchestration/review-providers/scoped-lint.js +19 -131
  366. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +6 -89
  367. package/.agents/scripts/lib/orchestration/review-providers/types.js +26 -56
  368. package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +3 -46
  369. package/.agents/scripts/lib/orchestration/run-epilogue.js +245 -326
  370. package/.agents/scripts/lib/orchestration/run-scoped-config.js +55 -159
  371. package/.agents/scripts/lib/orchestration/single-story-close/close-note.js +7 -34
  372. package/.agents/scripts/lib/orchestration/single-story-close/failed-terminal.js +16 -89
  373. package/.agents/scripts/lib/orchestration/single-story-close/gate-log.js +18 -109
  374. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +83 -239
  375. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +20 -82
  376. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +103 -97
  377. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +8 -64
  378. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +136 -486
  379. package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +30 -134
  380. package/.agents/scripts/lib/orchestration/single-story-close/phases/graphql-preflight.js +96 -0
  381. package/.agents/scripts/lib/orchestration/single-story-close/phases/lock-wait-pending.js +49 -0
  382. package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +13 -86
  383. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +20 -95
  384. package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +46 -203
  385. package/.agents/scripts/lib/orchestration/single-story-close/phases/pre-gate-steps.js +8 -50
  386. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +12 -83
  387. package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +6 -39
  388. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +1 -6
  389. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-outcome.js +4 -28
  390. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-override.js +6 -51
  391. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +6 -34
  392. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +23 -121
  393. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +180 -273
  394. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +15 -69
  395. package/.agents/scripts/lib/orchestration/story-body-gate.js +4 -23
  396. package/.agents/scripts/lib/orchestration/story-close/baseline-upward-writeback.js +50 -179
  397. package/.agents/scripts/lib/orchestration/story-close/context-budget-writeback.js +11 -41
  398. package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +23 -311
  399. package/.agents/scripts/lib/orchestration/story-close/phases/local-lens-review.js +22 -147
  400. package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +16 -67
  401. package/.agents/scripts/lib/orchestration/story-deliver-terminal-schema.js +12 -68
  402. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +42 -200
  403. package/.agents/scripts/lib/orchestration/story-follow-ups.js +167 -252
  404. package/.agents/scripts/lib/orchestration/story-init-envelope.js +52 -0
  405. package/.agents/scripts/lib/orchestration/story-init-remote.js +2 -6
  406. package/.agents/scripts/lib/orchestration/story-reachability.js +3 -23
  407. package/.agents/scripts/lib/orchestration/task-body-validator.js +12 -135
  408. package/.agents/scripts/lib/orchestration/ticket-lease.js +28 -131
  409. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +15 -149
  410. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +5 -33
  411. package/.agents/scripts/lib/orchestration/ticket-validator.js +63 -344
  412. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +51 -244
  413. package/.agents/scripts/lib/orchestration/ticketing/reads.js +39 -261
  414. package/.agents/scripts/lib/orchestration/ticketing/state.js +14 -68
  415. package/.agents/scripts/lib/orchestration/ticketing/transition.js +46 -263
  416. package/.agents/scripts/lib/orchestration/ticketing.js +2 -26
  417. package/.agents/scripts/lib/orchestration/verify-credit.js +18 -79
  418. package/.agents/scripts/lib/orchestration/worktree-dirty.js +5 -30
  419. package/.agents/scripts/lib/path-security.js +3 -6
  420. package/.agents/scripts/lib/plan-phase-cleanup.js +9 -49
  421. package/.agents/scripts/lib/preflight-runner.js +13 -69
  422. package/.agents/scripts/lib/process-group.js +143 -0
  423. package/.agents/scripts/lib/project-root.js +2 -8
  424. package/.agents/scripts/lib/provider-factory.js +2 -25
  425. package/.agents/scripts/lib/qa/console-allowlist.js +10 -59
  426. package/.agents/scripts/lib/qa/qa-session.js +15 -69
  427. package/.agents/scripts/lib/qa/redact-evidence.js +18 -129
  428. package/.agents/scripts/lib/qa/resolve-qa-contract.js +26 -135
  429. package/.agents/scripts/lib/qa/resolve-selection.js +16 -84
  430. package/.agents/scripts/lib/reserved-test-ids.js +9 -47
  431. package/.agents/scripts/lib/runtime-deps/dep-resolution.js +13 -53
  432. package/.agents/scripts/lib/runtime-deps/ensure-installed.js +10 -44
  433. package/.agents/scripts/lib/runtime-deps/manifest.js +10 -30
  434. package/.agents/scripts/lib/runtime-deps/parser-major.js +15 -51
  435. package/.agents/scripts/lib/runtime-deps/preflight.js +4 -22
  436. package/.agents/scripts/lib/runtime-deps/scan-imports.js +11 -55
  437. package/.agents/scripts/lib/signals/detectors/common.js +12 -38
  438. package/.agents/scripts/lib/signals/index.js +2 -19
  439. package/.agents/scripts/lib/signals/schema.js +14 -109
  440. package/.agents/scripts/lib/signals/write.js +2 -11
  441. package/.agents/scripts/lib/single-story/confirm-merge.js +31 -72
  442. package/.agents/scripts/lib/single-story/story-merged-notify.js +8 -49
  443. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +4 -26
  444. package/.agents/scripts/lib/single-story-sweep/protection.js +13 -100
  445. package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +60 -258
  446. package/.agents/scripts/lib/single-story-sweep.js +14 -97
  447. package/.agents/scripts/lib/skills/parse-skill.js +13 -59
  448. package/.agents/scripts/lib/skills/skills-index.js +8 -29
  449. package/.agents/scripts/lib/skills/walk-skill-files.js +17 -78
  450. package/.agents/scripts/lib/source-extensions.js +11 -42
  451. package/.agents/scripts/lib/source-text/strip-js-comments.js +8 -41
  452. package/.agents/scripts/lib/stdio-flush.js +9 -36
  453. package/.agents/scripts/lib/story-adjacency.js +8 -40
  454. package/.agents/scripts/lib/story-body/body-format-lints.js +51 -66
  455. package/.agents/scripts/lib/story-body/footer-block.js +11 -44
  456. package/.agents/scripts/lib/story-body/story-body.js +123 -344
  457. package/.agents/scripts/lib/temp-retention.js +42 -143
  458. package/.agents/scripts/lib/templates/decomposer-prompts.js +18 -80
  459. package/.agents/scripts/lib/test-env.js +12 -65
  460. package/.agents/scripts/lib/test-run-credit.js +10 -65
  461. package/.agents/scripts/lib/test-runner-contract.js +19 -74
  462. package/.agents/scripts/lib/test-temp.js +38 -184
  463. package/.agents/scripts/lib/test-tiers.js +12 -96
  464. package/.agents/scripts/lib/ticket-body-sections.js +21 -96
  465. package/.agents/scripts/lib/transpile.js +15 -74
  466. package/.agents/scripts/lib/util/concurrent-map.js +6 -25
  467. package/.agents/scripts/lib/util/parse-id-list.js +8 -34
  468. package/.agents/scripts/lib/util/poll-loop.js +8 -28
  469. package/.agents/scripts/lib/util/with-timeout.js +2 -11
  470. package/.agents/scripts/lib/validation-evidence.js +21 -96
  471. package/.agents/scripts/lib/wave-runner/footprint.js +17 -70
  472. package/.agents/scripts/lib/wave-runner/live-probe.js +67 -209
  473. package/.agents/scripts/lib/wave-runner/ready-set.js +72 -301
  474. package/.agents/scripts/lib/workers/crap-worker.js +11 -64
  475. package/.agents/scripts/lib/workers/maintainability-report-worker.js +8 -45
  476. package/.agents/scripts/lib/workers/maintainability-worker.js +5 -21
  477. package/.agents/scripts/lib/workers/serve-worker-messages.js +2 -18
  478. package/.agents/scripts/lib/workflow-closure.js +22 -105
  479. package/.agents/scripts/lib/workspace-provisioner.js +16 -54
  480. package/.agents/scripts/lib/worktree/git-hooks.js +15 -60
  481. package/.agents/scripts/lib/worktree/lifecycle/force-drain.js +20 -60
  482. package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +10 -62
  483. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +22 -86
  484. package/.agents/scripts/lib/worktree/lifecycle/reap.js +24 -126
  485. package/.agents/scripts/lib/worktree/lifecycle-manager.js +2 -20
  486. package/.agents/scripts/lib/worktree/node-modules-strategy.js +46 -180
  487. package/.agents/scripts/lib/worktree-manager.js +15 -40
  488. package/.agents/scripts/lint-issue-body.js +12 -68
  489. package/.agents/scripts/mandrel-update-preflight.js +10 -70
  490. package/.agents/scripts/merge-baseline.js +30 -105
  491. package/.agents/scripts/nav-registry-diff.js +22 -108
  492. package/.agents/scripts/notify.js +12 -69
  493. package/.agents/scripts/plan-context.js +97 -92
  494. package/.agents/scripts/plan-critics.js +12 -66
  495. package/.agents/scripts/plan-persist.js +71 -137
  496. package/.agents/scripts/plan-run-epilogue.js +20 -43
  497. package/.agents/scripts/pr-watch-with-update.js +79 -263
  498. package/.agents/scripts/providers/github/auth.js +3 -8
  499. package/.agents/scripts/providers/github/blocked-by-add.js +14 -61
  500. package/.agents/scripts/providers/github/board-add.js +5 -21
  501. package/.agents/scripts/providers/github/branch-protection.js +11 -43
  502. package/.agents/scripts/providers/github/cache.js +2 -14
  503. package/.agents/scripts/providers/github/comments.js +7 -40
  504. package/.agents/scripts/providers/github/compose.js +3 -19
  505. package/.agents/scripts/providers/github/errors.js +22 -125
  506. package/.agents/scripts/providers/github/issues.js +31 -123
  507. package/.agents/scripts/providers/github/labels.js +24 -124
  508. package/.agents/scripts/providers/github/mappers.js +5 -27
  509. package/.agents/scripts/providers/github/merge-methods.js +3 -22
  510. package/.agents/scripts/providers/github/project-board.js +2 -17
  511. package/.agents/scripts/providers/github/projects-v2-graphql.js +3 -6
  512. package/.agents/scripts/providers/github/request-helpers.js +5 -32
  513. package/.agents/scripts/providers/github/search-budget.js +9 -39
  514. package/.agents/scripts/providers/github/search-query.js +5 -26
  515. package/.agents/scripts/providers/github/sub-issue-add.js +15 -65
  516. package/.agents/scripts/providers/github/sub-issues.js +7 -36
  517. package/.agents/scripts/providers/github/tickets.js +32 -134
  518. package/.agents/scripts/providers/github.js +18 -59
  519. package/.agents/scripts/prune-plan-run-labels.js +12 -46
  520. package/.agents/scripts/quality-preview.js +35 -220
  521. package/.agents/scripts/resolve-doc-tiers.js +3 -26
  522. package/.agents/scripts/resolve-stories.js +16 -67
  523. package/.agents/scripts/resync-status-column.js +6 -25
  524. package/.agents/scripts/run-tests.js +29 -104
  525. package/.agents/scripts/single-story-close.js +23 -135
  526. package/.agents/scripts/single-story-confirm-merge.js +32 -139
  527. package/.agents/scripts/single-story-init.js +47 -259
  528. package/.agents/scripts/stories-wave-tick.js +179 -415
  529. package/.agents/scripts/sync-agentrc.js +3 -21
  530. package/.agents/scripts/sync-claude-agents.js +9 -55
  531. package/.agents/scripts/sync-claude-commands.js +20 -110
  532. package/.agents/scripts/test-wrapper.js +6 -43
  533. package/.agents/scripts/update-coverage-baseline.js +5 -22
  534. package/.agents/scripts/update-crap-baseline.js +7 -30
  535. package/.agents/scripts/update-duplication-baseline.js +16 -92
  536. package/.agents/scripts/update-maintainability-baseline.js +8 -62
  537. package/.agents/scripts/update-ticket-state.js +1 -7
  538. package/.agents/scripts/validate-skills.js +6 -26
  539. package/.agents/skills/core/gates-and-baselines/reference.md +0 -1
  540. package/.agents/skills/skills.index.json +2 -2
  541. package/.agents/skills/stack/qa/playwright/SKILL.md +26 -0
  542. package/.agents/templates/agent-protocol.md +2 -2
  543. package/.agents/templates/docs/audit-sweep-runbook.md +3 -4
  544. package/.agents/workflows/audit-accessibility.md +4 -7
  545. package/.agents/workflows/audit-adrs.md +3 -6
  546. package/.agents/workflows/audit-architecture.md +3 -11
  547. package/.agents/workflows/audit-baselines.md +6 -9
  548. package/.agents/workflows/audit-clean-code.md +8 -12
  549. package/.agents/workflows/audit-data-model.md +3 -7
  550. package/.agents/workflows/audit-dependencies.md +4 -7
  551. package/.agents/workflows/audit-devops.md +4 -8
  552. package/.agents/workflows/audit-documentation.md +1 -4
  553. package/.agents/workflows/audit-mobile.md +4 -7
  554. package/.agents/workflows/audit-navigability.md +3 -6
  555. package/.agents/workflows/audit-performance.md +2 -4
  556. package/.agents/workflows/audit-privacy.md +4 -7
  557. package/.agents/workflows/audit-quality.md +4 -7
  558. package/.agents/workflows/audit-security.md +4 -7
  559. package/.agents/workflows/audit-seo.md +4 -7
  560. package/.agents/workflows/audit-sre.md +4 -7
  561. package/.agents/workflows/audit-to-stories.md +17 -30
  562. package/.agents/workflows/audit-ux-ui.md +4 -7
  563. package/.agents/workflows/helpers/acceptance-self-eval.md +84 -157
  564. package/.agents/workflows/helpers/audit-lens-core.md +1 -1
  565. package/.agents/workflows/helpers/code-quality-guardrails.md +12 -15
  566. package/.agents/workflows/helpers/code-review.md +4 -2
  567. package/.agents/workflows/helpers/deliver-digest.md +37 -28
  568. package/.agents/workflows/helpers/deliver-light.md +92 -101
  569. package/.agents/workflows/helpers/deliver-reference.md +162 -220
  570. package/.agents/workflows/helpers/deliver-story-reference.md +197 -607
  571. package/.agents/workflows/helpers/deliver-story.md +17 -18
  572. package/.agents/workflows/helpers/plan-reference.md +125 -167
  573. package/.agents/workflows/helpers/qa-core.md +12 -0
  574. package/.agents/workflows/mandrel-deliver.md +47 -31
  575. package/.agents/workflows/mandrel-plan.md +22 -21
  576. package/.agents/workflows/mandrel-update.md +36 -21
  577. package/.agents/workflows/memory-consolidate.md +1 -1
  578. package/.agents/workflows/qa-assist.md +27 -71
  579. package/.agents/workflows/qa-explore.md +19 -59
  580. package/.agents/workflows/qa-run.md +11 -33
  581. package/README.md +1 -1
  582. package/bin/mandrel.js +5 -46
  583. package/bin/postinstall.js +18 -107
  584. package/docs/CHANGELOG.md +60 -0
  585. package/lib/cli/doctor.js +11 -71
  586. package/lib/cli/init.js +26 -165
  587. package/lib/cli/migrate.js +5 -64
  588. package/lib/cli/registry.js +84 -467
  589. package/lib/cli/sync-agents.js +4 -64
  590. package/lib/cli/sync-commands.js +11 -64
  591. package/lib/cli/sync.js +34 -213
  592. package/lib/cli/uninstall.js +40 -219
  593. package/lib/cli/update.js +326 -523
  594. package/lib/cli/version-check.js +8 -72
  595. package/lib/cli/version-helpers.js +14 -87
  596. package/lib/migrations/helpers/retire-agentrc-key.js +11 -52
  597. package/lib/migrations/index.js +17 -92
  598. package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +2 -15
  599. package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +1 -13
  600. package/lib/migrations/steps/2.11.0-retire-max-seed-words.js +2 -15
  601. package/lib/migrations/steps/2.2.0-retire-epic-ac-tags.js +9 -38
  602. package/lib/migrations/steps/2.20.0-retire-codebase-snapshot.js +1 -13
  603. package/lib/migrations/steps/2.32.0-retire-lint-baseline-command.js +2 -27
  604. package/lib/migrations/steps/2.57.0-retire-delivery-limit-knobs.js +2 -23
  605. package/lib/migrations/steps/2.57.0-retire-planning-limit-knobs.js +2 -27
  606. package/lib/migrations/steps/2.60.0-retire-audit-results-autofile.js +21 -0
  607. package/lib/migrations/steps/strip-removed-agentrc-keys.js +333 -0
  608. package/package.json +17 -14
  609. package/.agents/docs/SDLC.md +0 -590
  610. package/.agents/docs/quality-gates.md +0 -1179
  611. package/.agents/rules/known-tooling-behavior.md +0 -150
  612. package/.agents/rules/orchestration-error-handling.md +0 -61
  613. package/.agents/rules/test-seams.md +0 -59
  614. package/.agents/schemas/baselines/lighthouse.schema.json +0 -59
  615. package/.agents/schemas/baselines/lint.schema.json +0 -47
  616. package/.agents/schemas/model-attribution.schema.json +0 -53
  617. package/.agents/scripts/check-action-pinning.js +0 -260
  618. package/.agents/scripts/check-audit-attribution.js +0 -302
  619. package/.agents/scripts/check-baseline-drift.js +0 -211
  620. package/.agents/scripts/check-baseline-scope.js +0 -362
  621. package/.agents/scripts/check-generated-validator.js +0 -202
  622. package/.agents/scripts/check-knip-entries.js +0 -159
  623. package/.agents/scripts/check-lifecycle-lint.js +0 -294
  624. package/.agents/scripts/check-pinned-override-notes.js +0 -102
  625. package/.agents/scripts/check-schema-references.js +0 -366
  626. package/.agents/scripts/check-test-portability.js +0 -512
  627. package/.agents/scripts/check-workflow-citations.js +0 -332
  628. package/.agents/scripts/check-workflow-cli-lint.js +0 -299
  629. package/.agents/scripts/check-workflow-timeouts.js +0 -291
  630. package/.agents/scripts/install-matrix-assert.js +0 -326
  631. package/.agents/scripts/lib/audit-advisories.js +0 -195
  632. package/.agents/scripts/lib/audit-attribution.js +0 -134
  633. package/.agents/scripts/lib/baselines/drift-detector.js +0 -351
  634. package/.agents/scripts/lib/baselines/kinds/lighthouse.js +0 -87
  635. package/.agents/scripts/lib/baselines/kinds/lint.js +0 -184
  636. package/.agents/scripts/lib/baselines/orphan-pruner.js +0 -233
  637. package/.agents/scripts/lib/baselines/scope-assert.js +0 -223
  638. package/.agents/scripts/lib/baselines/scope-inventory.js +0 -314
  639. package/.agents/scripts/lib/c8-cli-path.js +0 -21
  640. package/.agents/scripts/lib/config/gates/lighthouse.schema.js +0 -51
  641. package/.agents/scripts/lib/config/gates/lint.schema.js +0 -18
  642. package/.agents/scripts/lib/dynamic-workflow/architecture-report-contract.js +0 -70
  643. package/.agents/scripts/lib/dynamic-workflow/audit-orchestrator.js +0 -284
  644. package/.agents/scripts/lib/dynamic-workflow/clean-code-report-contract.js +0 -80
  645. package/.agents/scripts/lib/dynamic-workflow/degraded-coverage.js +0 -81
  646. package/.agents/scripts/lib/dynamic-workflow/documentation-report-contract.js +0 -87
  647. package/.agents/scripts/lib/dynamic-workflow/performance-report-contract.js +0 -74
  648. package/.agents/scripts/lib/dynamic-workflow/quality-report-contract.js +0 -90
  649. package/.agents/scripts/lib/dynamic-workflow/report-contract-core.js +0 -43
  650. package/.agents/scripts/lib/dynamic-workflow/security-report-contract.js +0 -83
  651. package/.agents/scripts/lib/fs-walk.js +0 -52
  652. package/.agents/scripts/lib/knip-config-resolver.js +0 -181
  653. package/.agents/scripts/lib/knip-entry-sync.js +0 -452
  654. package/.agents/scripts/lib/orchestration/model-attribution.js +0 -418
  655. package/.agents/scripts/lib/orchestration/story-plan-state.js +0 -33
  656. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +0 -67
  657. package/.agents/scripts/lib/pinned-override-notes.js +0 -88
  658. package/.agents/scripts/lib/pinned-override-resolve.js +0 -212
  659. package/.agents/scripts/lib/test-isolate/cli-options.js +0 -93
  660. package/.agents/scripts/lib/test-isolate/env-snapshot-loader.js +0 -52
  661. package/.agents/scripts/lib/test-isolate/list-files.js +0 -90
  662. package/.agents/scripts/lib/test-isolate/parse-tap.js +0 -75
  663. package/.agents/scripts/lib/test-isolate/progress-log.js +0 -45
  664. package/.agents/scripts/lib/test-isolate/render-report.js +0 -97
  665. package/.agents/scripts/lib/test-isolate/run-isolate.js +0 -87
  666. package/.agents/scripts/lib/test-isolate/runner.js +0 -483
  667. package/.agents/scripts/lib/test-profile/parse-tap.js +0 -136
  668. package/.agents/scripts/lib/test-profile/render-report.js +0 -45
  669. package/.agents/scripts/lint-label-vocabulary.js +0 -214
  670. package/.agents/scripts/post-structured-comment.js +0 -127
  671. package/.agents/scripts/provision-git-hooks.js +0 -85
  672. package/.agents/scripts/prune-baseline-orphans.js +0 -181
  673. package/.agents/scripts/run-coverage.js +0 -197
  674. package/.agents/scripts/run-lint.js +0 -133
  675. package/.agents/scripts/run-test-profile.js +0 -129
  676. package/.agents/scripts/run-verify.js +0 -118
  677. package/.agents/scripts/test-isolate.js +0 -55
  678. 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.