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,55 +1,8 @@
1
1
  /**
2
- * graduator-core.js — shared mechanism for the feedback-loop graduators.
3
- *
4
- * Story #3845 / Epic #3823. The since-retired audit-results and code-review
5
- * graduators duplicated ~90% of their mechanism: a
6
- * `spawn`-based child runner, the `git cat-file` path probe, the
7
- * `gh search issues` idempotency probe, the `gh issue create` filer, the
8
- * `isAutoFileEnabled` toggle reader, and the route → probe → file
9
- * envelope walk. This module folds all of that into one place so a
10
- * graduator becomes a thin shell that injects the bits that genuinely
11
- * differ (the body/title/label builders).
12
- *
13
- * Story #5003 removed the structured-comment read limb. Both comment-reading
14
- * graduators were Epic-era — they walked an Epic's `verification-results`
15
- * comment, and v2 has no Epics — leaving `retro-proposals-graduator.js` and
16
- * its pre-parsed `findings[]` as the one live caller.
17
- *
18
- * The third `runGh` spawn copy in `prior-feedback-fetcher.js` is also
19
- * collapsed onto the single `runChild` helper here.
20
- *
21
- * Story #4415 / Epic #4406 hardens the walk so it is bounded and
22
- * replay-safe — the shared mechanism the retro auto-filer will reuse:
23
- *
24
- * - **Content-hash idempotency markers.** Follow-up markers derive from
25
- * a `category|path|title` digest (`contentFingerprint`) instead of a
26
- * `(epicId, parse-index)` ordinal, so a finding keeps its marker when
27
- * sibling findings are added, removed, or reordered in the source
28
- * comment, and two distinct findings never collide.
29
- * - **Legacy-marker recognition.** The idempotency probe also checks the
30
- * legacy `(epicId, parse-index)` marker so findings filed before the
31
- * fingerprint cutover are not re-filed.
32
- * - **Bounded spawns.** `runChild` enforces a caller-overridable timeout
33
- * (default 30000 ms) and kills a child that overruns instead of
34
- * hanging finalize forever.
35
- * - **Probe-error vs confirmed-missing.** A `git cat-file` spawn failure
36
- * (or timeout) records the finding as skipped `probe-error`, not the
37
- * confirmed-missing `file-removed`.
38
- * - **Per-run filing cap.** `graduate()` stops filing once
39
- * `maxFilingsPerRun` issues are created and records the excess as
40
- * skipped `cap-reached`.
41
- * - **Pre-parsed / path-less seam.** `graduate()` takes its findings as a
42
- * pre-parsed array, and a path-less finding skips the path-exists gate
43
- * instead of being misclassified `file-removed` — the seam the retro
44
- * auto-filer consumes.
45
- * - **Durable cross-repo deferral.** Cross-repo-deferred findings are
46
- * upserted into a structured comment on the Epic instead of only a
47
- * log line.
48
- * - **Routed, never re-pointed.** Ownership routing is delegated to
49
- * `github/framework-repo.js#routeOwnership`; an unroutable bucket is
50
- * skipped `unroutable` and named in that same durable comment. The
51
- * predecessor resolved an absent framework slug to the consumer's own
52
- * repo, which silently mis-filed framework-owned work.
2
+ * Shared graduator walk: route → path probe → idempotency probe → cap → file.
3
+ * A graduator injects only its title/body/label/marker builders (`spec`).
4
+ * The walk is bounded (spawn timeouts, per-run filing cap) and replay-safe
5
+ * (content-hash markers survive sibling reordering).
53
6
  */
54
7
 
55
8
  import { spawn as defaultSpawn } from 'node:child_process';
@@ -61,71 +14,25 @@ import { LABEL_COLORS } from '../label-constants.js';
61
14
  import { classifyPathSource as defaultClassifier } from '../observability/source-classifier.js';
62
15
  import { upsertStructuredComment } from '../orchestration/ticketing.js';
63
16
 
64
- /**
65
- * Default child-process timeout. A hung `gh`/`git` spawn previously blocked
66
- * finalize indefinitely; the walk now caps every spawn at this bound unless
67
- * a caller overrides it.
68
- */
69
17
  const DEFAULT_RUN_CHILD_TIMEOUT_MS = 30000;
70
18
 
71
- /**
72
- * Default per-run filing cap. `graduate()` files at most this many follow-up
73
- * issues per invocation; the remainder is recorded as skipped `cap-reached`.
74
- */
75
19
  export const DEFAULT_MAX_FILINGS_PER_RUN = 20;
76
20
 
77
- /**
78
- * Structured-comment type used to durably persist cross-repo-deferred
79
- * findings on the Epic. Registered in `STRUCTURED_COMMENT_TYPES`.
80
- */
21
+ /** Registered in `STRUCTURED_COMMENT_TYPES`. */
81
22
  const CROSS_REPO_DEFERRED_COMMENT_TYPE = 'cross-repo-deferred';
82
23
 
83
- /**
84
- * Explicit, greppable opt-back-in to live issue filing from a context the
85
- * guard below refuses (Story #4837). Deliberately shaped like
86
- * `MANDREL_TEST_ALLOW_REAL_TEMP` (`config/temp-paths.js`) rather than a new
87
- * bespoke flag: same env-var idiom, same "an escape hatch must be visible in
88
- * a grep" posture.
89
- */
24
+ /** Explicit, greppable opt-in to live filing from a context the guard refuses. */
90
25
  const ALLOW_LIVE_FILING_ENV = 'MANDREL_ALLOW_LIVE_ISSUE_FILING';
91
26
 
92
- /**
93
- * Skip reason recorded for every finding a refused filing context drops.
94
- * Module-local: it reaches callers as data on the returned envelope, so
95
- * exporting the constant would only add a symbol nothing imports.
96
- */
97
27
  const LIVE_FILING_BLOCKED_REASON = 'live-api-guard';
98
28
 
99
- /** `NODE_ENV` values that declare this process is not a production run. */
100
29
  const NON_PRODUCTION_NODE_ENVS = new Set(['test', 'development']);
101
30
 
102
31
  /**
103
- * Decide whether this process may let the graduator walk reach the live
104
- * GitHub API (Story #4837).
105
- *
106
- * **Why this exists.** Issues #4833 and #4834 were created against the live
107
- * `dsj1984/mandrel` tracker — from fixture findings anchored to `epic-101`
108
- * and `epic-777` — by a development run of the filing path. Nothing in the
109
- * walk distinguished "a real close is filing a real follow-up" from "someone
110
- * is exercising this module", so the only thing standing between a test and
111
- * the production tracker was the author remembering to stub `spawnImpl`.
112
- *
113
- * **The seam.** There are exactly two ways to be safe, and this returns
114
- * `allowed` only for them:
115
- *
116
- * 1. `spawnImpl` was injected — the walk then spawns the caller's stub and
117
- * no child process reaches `gh` at all. This is the seam
118
- * `.agents/rules/test-seams.md` already mandates, so a well-behaved test
119
- * is unaffected.
120
- * 2. The process provably is **not** a test or development context — not a
121
- * node:test run (per the single shared detector in
122
- * `config/temp-paths.js#inNodeTestContext`) and not a run that declared
123
- * itself non-production via `NODE_ENV`.
124
- *
125
- * **Fail closed.** Anything else refuses: a test context with the real
126
- * `spawn` (the #4833/#4834 shape), and — critically — a context that cannot
127
- * be *decided*, because an unreadable env is not evidence of production. The
128
- * refusal is a skip, not a throw: observability must never fail a close.
32
+ * Decide whether the walk may reach the live GitHub API. Allowed only when
33
+ * `spawnImpl` is injected (no child reaches `gh`) or the process is provably
34
+ * not a test/development run. Fails closed — an undecidable env refuses — and
35
+ * refusal is a skip, never a throw: observability must not fail a close.
129
36
  *
130
37
  * @param {object} opts
131
38
  * @param {Function} [opts.spawnImpl]
@@ -141,38 +48,26 @@ function resolveFilingContext({
141
48
  const refuse = { allowed: false, reason: LIVE_FILING_BLOCKED_REASON };
142
49
  const allow = { allowed: true, reason: null };
143
50
 
144
- // An injected seam cannot reach the live API by construction.
145
51
  if (typeof spawnImpl === 'function') return allow;
146
52
 
147
- // Undecidable context → refuse. Both inputs must be readable for the
148
- // detector's answer to mean anything.
149
53
  if (env === null || typeof env !== 'object' || !Array.isArray(execArgv)) {
150
54
  return refuse;
151
55
  }
152
56
  try {
153
57
  if (env[ALLOW_LIVE_FILING_ENV] === '1') return allow;
154
58
  if (inNodeTestContext(env, execArgv)) return refuse;
155
- // A declared non-production environment is the other half of "a test or
156
- // development context". `lib/test-env.js` stamps `NODE_ENV=test` on the
157
- // whole suite environment, and `development` is the universal marker for
158
- // a hand-run session; nothing on the close path sets either.
59
+ // The suite stamps NODE_ENV=test; the close path sets neither value.
159
60
  return NON_PRODUCTION_NODE_ENVS.has(String(env.NODE_ENV ?? ''))
160
61
  ? refuse
161
62
  : allow;
162
63
  } catch {
163
- // An env we cannot even read is not evidence of production.
164
64
  return refuse;
165
65
  }
166
66
  }
167
67
 
168
68
  /**
169
- * Compute a stable content fingerprint for a finding from its
170
- * `category|path|title` triple. Pure — the digest depends only on the
171
- * finding content, never on its position in the source comment, so the
172
- * marker survives sibling insert/remove/reorder churn. Distinct triples
173
- * yield distinct digests (SHA-256, truncated to 16 hex chars for a compact
174
- * marker that still has a negligible collision probability across a single
175
- * Epic's finding set).
69
+ * Position-independent `category|path|title` digest, so a marker survives
70
+ * sibling reordering (SHA-256 truncated to 16 hex).
176
71
  *
177
72
  * @param {{ category?: unknown, path?: unknown, title?: unknown }} parts
178
73
  * @returns {string} 16-char lowercase hex digest.
@@ -184,29 +79,16 @@ export function contentFingerprint({ category, path, title } = {}) {
184
79
  }
185
80
 
186
81
  /**
187
- * Spawn a child process and resolve to
188
- * `{ code, stdout, stderr, spawnError, timedOut }`. Never throws — spawn-time
189
- * errors are captured as `spawnError` and an overrun is captured as
190
- * `timedOut: true` with a matching `spawnError`.
191
- *
192
- * This is the single spawn helper for the feedback-loop modules. Both
193
- * graduators and `prior-feedback-fetcher.js` route their child-process
194
- * reads through it so the error envelope stays consistent. `stdio` is
195
- * always `['ignore', 'pipe', 'pipe']`; callers that need extra spawn
196
- * options (e.g. omitting `cwd`) pass `undefined` and the option is
197
- * dropped by the child_process layer.
198
- *
199
- * A caller-overridable `timeoutMs` (default {@link DEFAULT_RUN_CHILD_TIMEOUT_MS})
200
- * bounds the wait: when it elapses the child is SIGKILL'd and the promise
201
- * resolves with `{ code: null, timedOut: true, spawnError }` rather than
202
- * hanging. Pass `0`/`Infinity` to disable the watchdog.
82
+ * The feedback loop's single spawn helper. Never throws: spawn errors land in
83
+ * `spawnError`; an overrun is SIGKILL'd and resolves `timedOut: true`.
84
+ * `timeoutMs` of `0`/`Infinity` disables the watchdog.
203
85
  *
204
86
  * @param {object} opts
205
- * @param {string} opts.cmd — binary to spawn (e.g. "git", "gh")
206
- * @param {string[]} opts.args — positional + flag arguments
207
- * @param {Function} [opts.spawnImpl] — test seam; defaults to node:child_process spawn
208
- * @param {string} [opts.cwd] — working directory for the child
209
- * @param {number} [opts.timeoutMs] — watchdog bound in ms
87
+ * @param {string} opts.cmd
88
+ * @param {string[]} opts.args
89
+ * @param {Function} [opts.spawnImpl]
90
+ * @param {string} [opts.cwd]
91
+ * @param {number} [opts.timeoutMs]
210
92
  * @returns {Promise<{ code: number|null, stdout: string, stderr: string, spawnError: Error|null, timedOut: boolean }>}
211
93
  */
212
94
  export function runChild({
@@ -249,7 +131,7 @@ export function runChild({
249
131
  try {
250
132
  child.kill?.('SIGKILL');
251
133
  } catch {
252
- // Killing an already-dead / stub child is a no-op we ignore.
134
+ // already dead / stub child
253
135
  }
254
136
  finish({
255
137
  code: null,
@@ -264,14 +146,9 @@ export function runChild({
264
146
  timedOut: true,
265
147
  });
266
148
  }, timeoutMs);
267
- // Intentionally NOT unref'd: this is a watchdog timer that MUST keep
268
- // the event loop alive until it fires (or the child settles). A real
269
- // spawned child keeps the loop alive via its stdio handles, but a
270
- // child whose handles close early — or a stub in tests — leaves the
271
- // loop idle; an unref'd timer would then never fire, so the timeout
272
- // silently would not bound a hung spawn (and the awaiting promise
273
- // would hang forever). `finish()` always clearTimeout()s it, so the
274
- // ref'd timer never outlives its purpose.
149
+ // Deliberately NOT unref'd: a child whose handles close early (or a
150
+ // stub) leaves the loop idle, and an unref'd watchdog would never fire.
151
+ // `finish()` always clears it.
275
152
  }
276
153
  child.stdout?.on('data', (chunk) => {
277
154
  stdout += chunk.toString();
@@ -289,30 +166,21 @@ export function runChild({
289
166
  }
290
167
 
291
168
  /**
292
- * Build an `isAutoFileEnabled(config)` reader bound to a specific
293
- * `delivery.feedbackLoop.<key>` toggle. The feature is opt-out: the
294
- * toggle defaults to `true` and only an explicit `false` disables it.
169
+ * Opt-in `delivery.feedbackLoop.<key>` reader: only an explicit `true`
170
+ * enables filing, because unattended filings were dominated by noise.
295
171
  *
296
- * @param {string} toggleKey — key under `config.delivery.feedbackLoop`
297
- * (e.g. "auditResultsAutoFile", "retroProposals")
172
+ * @param {string} toggleKey
298
173
  * @returns {(config: object|undefined|null) => boolean}
299
174
  */
300
175
  export function makeIsAutoFileEnabled(toggleKey) {
301
176
  return function isAutoFileEnabled(config) {
302
- const value = config?.delivery?.feedbackLoop?.[toggleKey];
303
- if (value === false) return false;
304
- return true;
177
+ return config?.delivery?.feedbackLoop?.[toggleKey] === true;
305
178
  };
306
179
  }
307
180
 
308
181
  /**
309
- * Probe whether the cited path exists in the merged tree at the given git
310
- * ref, distinguishing a confirmed-missing file from a probe failure.
311
- * Resolves `{ exists, probeError }`:
312
- *
313
- * - `git cat-file -e <ref>:<path>` exit 0 → `{ exists: true, probeError: false }`
314
- * - clean non-zero exit (file genuinely absent) → `{ exists: false, probeError: false }`
315
- * - spawn failure / timeout (cannot decide) → `{ exists: false, probeError: true }`
182
+ * `git cat-file -e <ref>:<path>`; a spawn failure/timeout is `probeError`,
183
+ * distinct from a confirmed-missing file.
316
184
  *
317
185
  * @param {object} opts
318
186
  * @param {string} opts.ref
@@ -343,16 +211,8 @@ export async function probePathStatus({
343
211
  }
344
212
 
345
213
  /**
346
- * Normalize an idempotency marker into a `gh search issues` query. Markers
347
- * are HTML comments (`<!-- … -->`) so they survive markdown rendering
348
- * without leaking into the visible body, but the `<` / `>` delimiters are
349
- * NOT index-safe as a query: GitHub full-text search DOES index the text
350
- * inside an HTML comment, yet a query that carries the `<!--` / `-->`
351
- * delimiters never matches that indexed text (measured against this repo,
352
- * Story #4657). Stripping the delimiters and trimming yields the bare marker
353
- * text — `retro-proposal-followup: <fp>` — which the index matches.
354
- * The caller-facing marker is left untouched; normalization is the probe's
355
- * own concern.
214
+ * GitHub search indexes the text inside an HTML-comment marker, but a query
215
+ * carrying the `<!--`/`-->` delimiters never matches it; strip them.
356
216
  *
357
217
  * @param {string} marker
358
218
  * @returns {string}
@@ -363,11 +223,8 @@ function normalizeMarkerQuery(marker) {
363
223
  }
364
224
 
365
225
  /**
366
- * Normalize one `gh` issue row (from `search issues` or `issue list`) into
367
- * the identity the update path needs. `state` is lowercased and defaults to
368
- * the empty string — deliberately NOT to `'open'`: an unknown state must
369
- * never authorize editing somebody's issue (see
370
- * {@link resolveFollowUpRecurrence}).
226
+ * `state` defaults to `''`, never `'open'`: an unknown state must not
227
+ * authorize editing an issue.
371
228
  *
372
229
  * @param {object} row
373
230
  * @returns {{ number: number|null, state: string, url: string }}
@@ -382,15 +239,8 @@ function toFollowUpRef(row) {
382
239
  }
383
240
 
384
241
  /**
385
- * Search the routed repo for a follow-up carrying `marker`, resolving the
386
- * matched issue's identity rather than a bare yes/no. Uses `gh search issues`
387
- * so we hit the body field directly, querying the delimiter-stripped marker
388
- * text (see {@link normalizeMarkerQuery}) — the raw `<!-- … -->` form never
389
- * matches the index.
390
- *
391
- * Returns `null` when nothing matched OR when the probe could not decide
392
- * (spawn/parse error): the deliberate degrade-toward-filing posture, better
393
- * to risk a duplicate than swallow the finding entirely.
242
+ * `null` on no match OR an undecidable probe — degrade toward filing: a
243
+ * duplicate beats a swallowed finding.
394
244
  *
395
245
  * @returns {Promise<{ number: number|null, state: string, url: string }|null>}
396
246
  */
@@ -427,46 +277,23 @@ async function searchFollowUpByMarker({
427
277
  }
428
278
  }
429
279
 
430
- /**
431
- * Probe whether a follow-up issue carrying the given idempotency marker
432
- * already exists in the routed repo. Thin boolean façade over
433
- * {@link searchFollowUpByMarker} — kept as the module's exported probe seam
434
- * so callers that only need the yes/no do not have to know about the issue
435
- * identity the recurrence path resolves.
436
- *
437
- * @returns {Promise<boolean>}
438
- */
280
+ /** @returns {Promise<boolean>} */
439
281
  export async function probeMarkerExists(opts) {
440
282
  return (await searchFollowUpByMarker(opts)) !== null;
441
283
  }
442
284
 
443
285
  /**
444
- * Strongly-consistent lookup of an already-filed follow-up, run ONLY on the
445
- * would-file path as the last gate before creating. `gh search issues` reads
446
- * an eventually-consistent index whose catch-up latency (measured under 20s
447
- * against this repo, Story #4657) is exactly wide enough to miss a
448
- * byte-identical duplicate filed seconds earlier in the same rollup. A
449
- * label-scoped `gh issue list … --state all` is strongly consistent, so it
450
- * closes that window. The list is narrowed by the follow-up's own labels
451
- * (supplied by the same `spec.buildFollowUp` that writes the marker, so the
452
- * two agree by construction) to keep the read bounded.
453
- *
454
- * `markers` is a LIST of body substrings, any one of which identifies a prior
455
- * filing (Story #4837). One finding can have been filed under more than one
456
- * marker shape — the retro graduator's pre-cutover marker embedded the run
457
- * anchor, so the same finding sits behind `epic-<anchor>-<fp>` on already-
458
- * filed issues and behind the anchor-free `<fp>` on new ones. Matching any of
459
- * them is what stops a marker-format change from re-filing the whole backlog.
460
- *
461
- * Returns `null` when nothing matched, or on any spawn/parse error — the
462
- * deliberate degrade-toward-filing posture: an undecidable probe risks a
463
- * duplicate rather than swallowing the finding.
286
+ * Strongly-consistent last gate before creating: the search index can lag
287
+ * long enough to miss a duplicate filed seconds earlier, while a
288
+ * label-scoped `gh issue list --state all` cannot. Any of `markers` matching
289
+ * counts, so a marker-format change does not re-file the backlog. `null` on
290
+ * no match or error (degrade toward filing).
464
291
  *
465
292
  * @param {object} opts
466
- * @param {string[]} opts.markers — body substrings identifying a prior filing.
293
+ * @param {string[]} opts.markers
467
294
  * @param {string} opts.owner
468
295
  * @param {string} opts.repo
469
- * @param {string[]} [opts.labels] — the follow-up's labels; scopes the list.
296
+ * @param {string[]} [opts.labels]
470
297
  * @param {string} [opts.ghPath]
471
298
  * @param {Function} [opts.spawnImpl]
472
299
  * @param {string} [opts.cwd]
@@ -517,9 +344,7 @@ async function findExistingFollowUp({
517
344
  tokens.some((token) => issue.body.includes(token)),
518
345
  );
519
346
  if (matches.length === 0) return null;
520
- // Prefer an OPEN match: a recurrence updates the live issue, while a closed
521
- // one is a decided follow-up. When several match, the open one is the one a
522
- // human is still looking at.
347
+ // Prefer an open match: a closed one is a decided follow-up.
523
348
  const open = matches.find(
524
349
  (issue) => String(issue?.state ?? '').toLowerCase() === 'open',
525
350
  );
@@ -527,13 +352,8 @@ async function findExistingFollowUp({
527
352
  }
528
353
 
529
354
  /**
530
- * Refresh an existing follow-up's body in place — the recurrence path
531
- * (Story #4837). A finding that recurs is the SAME finding: the loop's job is
532
- * to keep one issue current, not to mint issue #N+1 whose only new
533
- * information is that the count went up.
534
- *
535
- * Body-only: labels, title, assignees and state are left exactly as a human
536
- * may have curated them.
355
+ * Recurrence path: refresh the body only, leaving human-curated labels,
356
+ * title, assignees and state untouched.
537
357
  *
538
358
  * @returns {Promise<{ url: string|null, error: string|null }>}
539
359
  */
@@ -573,14 +393,10 @@ export async function updateFollowUpIssue({
573
393
  return { url: (res.stdout || '').trim(), error: null };
574
394
  }
575
395
 
576
- /** Prefix of the per-category friction axis the feedback loop mints. */
577
396
  const FRICTION_LABEL_PREFIX = 'friction::';
578
397
 
579
398
  /**
580
- * Resolve the color + description for a label the feedback loop is about to
581
- * mint. Only two axes reach this path — `meta::*` (routing) and
582
- * `friction::<category>` (the telemetry bucket) — so the mapping is a
583
- * two-branch lookup rather than a registry.
399
+ * Only `meta::*` and `friction::<category>` labels reach this path.
584
400
  *
585
401
  * @param {string} name
586
402
  * @returns {{ color: string, description: string }}
@@ -599,11 +415,7 @@ function describeMintedLabel(name) {
599
415
  }
600
416
 
601
417
  /**
602
- * Read the routed repo's live label names once per repo, memoized in
603
- * `labelCache`. Returns `null` when the set could not be established —
604
- * "verification unavailable", which is deliberately NOT the same as "the repo
605
- * has no labels": an unreadable set must not be read as proof that every
606
- * label is missing.
418
+ * Memoized per repo. `known: null` means unverifiable, not "no labels".
607
419
  *
608
420
  * @returns {Promise<{ known: Set<string>|null, error: string|null }>}
609
421
  */
@@ -653,28 +465,16 @@ async function readLiveLabelNames({
653
465
  }
654
466
 
655
467
  /**
656
- * Mint any of `labels` the routed repo does not already carry, so
657
- * `gh issue create --label …` can attach them (Story #4828).
658
- *
659
- * **Why this exists.** `gh issue create` resolves every `--label` name against
660
- * the repo before it creates anything, and fails the whole call when one is
661
- * absent. The feedback loop mints two axes that no bootstrap can enumerate
662
- * ahead of time — `meta::consumer-improvement` is absent from `LABEL_TAXONOMY`
663
- * outright, and `friction::<category>` names come from live telemetry — so on
664
- * a repo that never had them, *every* filing failed. The failure landed in the
665
- * graduator's `errors[]`, which the run epilogue did not surface, so a
666
- * hard-failing feedback loop rendered as `filed: 0`: indistinguishable from
667
- * "nothing was actionable".
668
- *
669
- * Degrades rather than blocks: when the live set cannot be read, this returns
670
- * no `missing` entries so the caller still attempts the filing (the old
671
- * behaviour) instead of refusing on an unproven premise.
468
+ * Mint absent labels: `gh issue create` fails the whole call on any unknown
469
+ * `--label`, and `friction::<category>` names come from live telemetry so no
470
+ * bootstrap can pre-create them. An unreadable live set reports nothing
471
+ * `missing`, so the caller still attempts the filing.
672
472
  *
673
473
  * @param {object} opts
674
474
  * @param {string} opts.owner
675
475
  * @param {string} opts.repo
676
476
  * @param {string[]} opts.labels
677
- * @param {Map<string, Set<string>>} [opts.labelCache] — per-repo live-set memo.
477
+ * @param {Map<string, Set<string>>} [opts.labelCache]
678
478
  * @param {string} [opts.ghPath]
679
479
  * @param {Function} [opts.spawnImpl]
680
480
  * @param {string} [opts.cwd]
@@ -705,7 +505,6 @@ export async function ensureIssueLabels({
705
505
  cwd,
706
506
  timeoutMs,
707
507
  });
708
- // Verification unavailable — attempt the filing anyway rather than refuse.
709
508
  if (!known) return { created: [], missing: [], errors: error ? [error] : [] };
710
509
 
711
510
  const created = [];
@@ -734,8 +533,7 @@ export async function ensureIssueLabels({
734
533
  const failed =
735
534
  Boolean(res.spawnError) ||
736
535
  (typeof res.code === 'number' && res.code !== 0);
737
- // A concurrent roll-up may have minted it between the list and the create;
738
- // that is the idempotent outcome, not a failure.
536
+ // A concurrent mint between list and create is success.
739
537
  const raced = /label\b[\s\S]*?already exists/i.test(
740
538
  `${res.stderr ?? ''}${res.spawnError?.message ?? ''}`,
741
539
  );
@@ -752,12 +550,7 @@ export async function ensureIssueLabels({
752
550
  return { created, missing, errors };
753
551
  }
754
552
 
755
- /**
756
- * File a new follow-up issue via `gh issue create` and resolve to
757
- * `{ url, error }`. On success `url` is the trimmed stdout and `error` is
758
- * null; on failure `url` is null and `error` carries a human-readable
759
- * message.
760
- */
553
+ /** Resolves `{ url, error }`; exactly one is non-null. */
761
554
  export async function createFollowUpIssue({
762
555
  owner,
763
556
  repo,
@@ -796,16 +589,9 @@ export async function createFollowUpIssue({
796
589
  }
797
590
 
798
591
  /**
799
- * Validate the `graduate` preconditions (toggle, epicId, currentRepo shape).
800
- * Returns `null` when all preconditions pass, or a `{ skipped?, errors? }`
801
- * partial-envelope the caller short-circuits on. Story #4075 — extracted from
802
- * `graduate` so the orchestrating body holds no guard-chain branching.
803
- *
804
- * Story #5003 dropped the `provider.getTicketComments` gate with the
805
- * structured-comment read limb. The provider is now consulted only by the
806
- * best-effort cross-repo-deferred upsert, which reports its own faults into
807
- * `errors[]` — gating the whole walk on a shape only that path needs would
808
- * refuse work the walk can complete.
592
+ * `null` when all pass, else a partial envelope to short-circuit on. The
593
+ * provider is deliberately not gated: only the best-effort cross-repo upsert
594
+ * needs it, and that reports its own faults.
809
595
  */
810
596
  function checkGraduatePreconditions({ epicId, currentRepo, config, spec }) {
811
597
  if (!spec.isAutoFileEnabled(config)) {
@@ -825,16 +611,9 @@ function checkGraduatePreconditions({ epicId, currentRepo, config, spec }) {
825
611
  }
826
612
 
827
613
  /**
828
- * Probe whether a finding was already filed, checking both the current
829
- * content-hash marker AND the legacy `(epicId, parse-index)` marker so
830
- * findings filed before the fingerprint cutover are not re-filed. The
831
- * content-hash marker is passed in precomputed so a caller can consult an
832
- * in-process memo before spending a spawn.
833
- *
834
- * Resolves `{ alreadyFiled, existing }` — `existing` carries the matched
835
- * issue's `{ number, state, url }` when the search index surfaced it, so a
836
- * recurrence can update that issue rather than only knowing that one exists.
837
- * `existing` is `null` on the not-found path.
614
+ * Checks the content-hash marker, then the legacy ordinal marker so
615
+ * pre-fingerprint filings are not re-filed. `existing` identifies the match
616
+ * so a recurrence can update it.
838
617
  */
839
618
  async function resolveAlreadyFiled({
840
619
  finding,
@@ -860,8 +639,6 @@ async function resolveAlreadyFiled({
860
639
 
861
640
  const hit = await probe(contentMarker);
862
641
  if (hit) return { alreadyFiled: true, existing: hit };
863
- // Legacy recognition — a pre-cutover follow-up carries the ordinal
864
- // marker, not the content hash. Skip re-filing when it is present.
865
642
  if (typeof spec.buildLegacyMarker === 'function') {
866
643
  const legacyMarker = spec.buildLegacyMarker(epicId, finding.index);
867
644
  if (legacyMarker) {
@@ -873,18 +650,9 @@ async function resolveAlreadyFiled({
873
650
  }
874
651
 
875
652
  /**
876
- * Resolve what a recurrence of an already-identified follow-up should do
877
- * (Story #4837), and fold the outcome into the running envelope.
878
- *
879
- * An **open** issue with a resolvable number is refreshed in place and
880
- * recorded on `envelope.filed` with `action: 'updated'` — same array as a
881
- * creation, because both are live writes this run performed and the roll-up
882
- * that reports "filed" must count them alike.
883
- *
884
- * Anything else records `already-filed` and touches nothing: a closed
885
- * follow-up is a decided one (reopening it would relitigate a human's call),
886
- * and an unresolvable number or state is not licence to edit an issue we
887
- * cannot identify.
653
+ * An open, numbered match is refreshed and recorded on `filed` as
654
+ * `action: 'updated'` (a live write, counted like a creation). Anything else
655
+ * is `already-filed` and untouched: a closed follow-up is a human's decision.
888
656
  *
889
657
  * @returns {Promise<boolean>} `true` when the recurrence was handled here.
890
658
  */
@@ -940,13 +708,6 @@ async function resolveFollowUpRecurrence({
940
708
  return true;
941
709
  }
942
710
 
943
- /**
944
- * Route a single finding (path-exists probe → repo routing → idempotency
945
- * probe → cap → file) and fold the outcome into the running envelope. Story
946
- * #4075 extracted this from `graduate`'s per-finding loop; Story #4415
947
- * hardened it (path-less seam, probe-error distinction, legacy-marker
948
- * recognition, filing cap, and cross-repo-deferred collection).
949
- */
950
711
  async function processGraduateFinding({
951
712
  finding,
952
713
  envelope,
@@ -980,9 +741,7 @@ async function processGraduateFinding({
980
741
  ),
981
742
  );
982
743
 
983
- // Path-less findings (the retro auto-filer seam) are not file-scoped, so
984
- // the path-exists gate does not apply — probing an empty path would
985
- // misclassify them `file-removed`. Only file-scoped findings are probed.
744
+ // A path-less finding would misclassify as `file-removed`; skip the probe.
986
745
  const hasPath =
987
746
  typeof finding.path === 'string' && finding.path.trim().length > 0;
988
747
  if (hasPath) {
@@ -993,18 +752,13 @@ async function processGraduateFinding({
993
752
  cwd,
994
753
  timeoutMs,
995
754
  });
996
- // A probe failure is not proof the file is gone — record it distinctly
997
- // so a transient git/spawn fault does not masquerade as a removal.
998
755
  if (probeError) return skip('probe-error');
999
756
  if (!exists) return skip('file-removed');
1000
757
  }
1001
758
 
1002
759
  const source = classifier(finding.path, null);
1003
- // Ownership routing is the shared SSOT's call, and an unroutable bucket is
1004
- // an outcome rather than a fallback: the predecessor resolved an absent
1005
- // framework slug to the CONSUMER's repo, silently filing framework-owned
1006
- // work in the wrong place (see `github/framework-repo.js`). Unroutable
1007
- // findings are deferred and named, never re-pointed.
760
+ // Unroutable findings are deferred and named, never re-pointed at the
761
+ // consumer's repo.
1008
762
  const routing = routeOwnership({ bucket: source, repos, currentRepo });
1009
763
  if (!routing.routable) {
1010
764
  const logLine = `[${spec.fnName}] unroutable ${source} finding (${routing.missingKey} is unset) — not filed: ${finding.title ?? finding.path ?? `finding ${finding.index}`}`;
@@ -1028,11 +782,7 @@ async function processGraduateFinding({
1028
782
 
1029
783
  const contentMarker = spec.buildContentMarker(epicId, finding);
1030
784
 
1031
- // In-process memo (Story #4657): a marker already filed earlier in THIS
1032
- // invocation — e.g. the framework bucket of a retro rollup that also has
1033
- // the same category in the consumer bucket — short-circuits a repeat in a
1034
- // later bucket without spending a single spawn, and closes the same-rollup
1035
- // race the eventually-consistent search index cannot.
785
+ // In-process memo closes the same-invocation race the search index cannot.
1036
786
  if (filedMarkers?.has(contentMarker)) return skip('already-filed');
1037
787
 
1038
788
  const { alreadyFiled, existing } = await resolveAlreadyFiled({
@@ -1047,10 +797,8 @@ async function processGraduateFinding({
1047
797
  spec,
1048
798
  });
1049
799
 
1050
- // Resolve the follow-up (title/body/labels) BEFORE the dedup decision so
1051
- // the strong read can scope its `gh issue list` by the very labels this
1052
- // filing would carry (they agree with the marker by construction), and so
1053
- // the recurrence path has the refreshed body to write.
800
+ // Built before dedup: the strong read scopes by these labels and a
801
+ // recurrence writes this body.
1054
802
  const { title, body, labels } = spec.buildFollowUp({
1055
803
  finding,
1056
804
  source,
@@ -1077,15 +825,10 @@ async function processGraduateFinding({
1077
825
  return;
1078
826
  }
1079
827
 
1080
- // Per-run filing cap — bounds the live writes this run performs. Checked
1081
- // only on the would-file path: an `already-filed` finding resolved above
1082
- // never reaches here. The excess is surfaced so a re-run picks it up.
1083
828
  if (envelope.filed.length >= maxFilingsPerRun) return skip('cap-reached');
1084
829
 
1085
- // Mint any routing label the repo does not carry yet (Story #4828). This
1086
- // runs BEFORE the strong read as well as before the create: `gh issue list
1087
- // --label <absent>` exits 0 with `[]`, so an absent label silently degrades
1088
- // the dedup confirm too, not just the filing.
830
+ // Before the strong read too: `gh issue list --label <absent>` exits 0
831
+ // with `[]`, silently defeating the dedup confirm.
1089
832
  const ensured = await ensureIssueLabels({
1090
833
  owner: routedRepo.owner,
1091
834
  repo: routedRepo.repo,
@@ -1098,17 +841,9 @@ async function processGraduateFinding({
1098
841
  });
1099
842
  envelope.errors.push(...ensured.errors);
1100
843
  if (ensured.missing.length > 0) {
1101
- // `gh issue create` would reject the whole call on the absent name; say
1102
- // which label blocked it rather than replaying an opaque CLI failure.
1103
844
  return skip('label-ensure-failed');
1104
845
  }
1105
846
 
1106
- // Strong read (would-file path only, Story #4657): the search probe reads
1107
- // an eventually-consistent index that can miss a byte-identical duplicate
1108
- // filed seconds earlier. Confirm against a strongly-consistent,
1109
- // label-scoped `gh issue list` before creating. Skipped entirely on the
1110
- // already-filed path above, so it never fires when the search probe
1111
- // already matched.
1112
847
  const confirmed = await findExistingFollowUp({
1113
848
  markers:
1114
849
  typeof spec.buildMatchTokens === 'function'
@@ -1175,12 +910,6 @@ async function processGraduateFinding({
1175
910
  );
1176
911
  }
1177
912
 
1178
- /**
1179
- * Render the durable cross-repo-deferred comment body from the collected
1180
- * deferrals. Each row names the finding path/severity plus the would-be
1181
- * `gh issue create` command so an operator (or a later cross-repo pass)
1182
- * can act on it.
1183
- */
1184
913
  function renderCrossRepoDeferredBody(deferred, spec) {
1185
914
  const header =
1186
915
  spec.crossRepoCommentHeader ??
@@ -1190,8 +919,6 @@ function renderCrossRepoDeferredBody(deferred, spec) {
1190
919
  typeof finding.path === 'string' && finding.path.length > 0
1191
920
  ? `\`${finding.path}\``
1192
921
  : '_(no path)_';
1193
- // An unroutable finding has no destination to name — say which config
1194
- // key would give it one instead of inventing a repo for the row.
1195
922
  const destination = routedRepo
1196
923
  ? `${routedRepo.owner}/${routedRepo.repo}`
1197
924
  : `**unroutable** (\`${missingKey}\` is unset)`;
@@ -1203,12 +930,7 @@ function renderCrossRepoDeferredBody(deferred, spec) {
1203
930
  return [header, '', ...rows].join('\n');
1204
931
  }
1205
932
 
1206
- /**
1207
- * Durably persist the cross-repo-deferred findings as a structured comment
1208
- * on the Epic (upserted — one comment per graduator, refreshed in place).
1209
- * Best-effort: a provider that cannot post comments is a no-op, and an
1210
- * upsert failure lands in `envelope.errors` rather than throwing.
1211
- */
933
+ /** Best-effort upsert; failures land in `envelope.errors`, never thrown. */
1212
934
  async function persistCrossRepoDeferred({
1213
935
  epicId,
1214
936
  provider,
@@ -1234,74 +956,36 @@ async function persistCrossRepoDeferred({
1234
956
  }
1235
957
 
1236
958
  /**
1237
- * Parametrized graduator walk. Takes a pre-parsed `findings` array and, for
1238
- * each finding, runs the shared route → path probe → idempotency probe →
1239
- * cap → file sequence. Never throws — every failure path is captured in
1240
- * `errors[]`.
1241
- *
1242
- * Each finding MUST carry `{ severity, path, summary, index }` and MAY carry
1243
- * additional fields (e.g. `category`) that the builders use.
1244
- *
1245
- * The per-graduator variation lives entirely in the injected callbacks:
1246
- *
1247
- * - `buildContentMarker(epicId, finding)` — the content-hash HTML-comment
1248
- * marker embedded in (and searched for in) follow-up bodies.
1249
- * - `buildLegacyMarker(epicId, index)` — the pre-cutover ordinal marker,
1250
- * probed for idempotency so legacy filings are not duplicated.
1251
- * - `buildMatchTokens({ epicId, finding, contentMarker })` — optional; the
1252
- * body substrings the strong read accepts as proof of a prior filing.
1253
- * Defaults to `[contentMarker]`. A graduator whose marker format changed
1254
- * returns the old shape here too, so the cutover recognizes the backlog
1255
- * it already filed instead of duplicating it.
1256
- * - `buildFollowUp({ finding, source, epicId, idMarker })` — returns
1257
- * `{ title, body, labels }` for the issue to file.
1258
- * - `buildCrossRepoLog({ finding, routedRepo, source })` — returns the
1259
- * human-readable would-be-command string for a cross-repo skip.
1260
- * - `decorateRecord(record, finding)` — copies finding-specific fields
1261
- * (e.g. `lens`) onto a `skipped`/`filed` record before it is pushed.
1262
- * - `crossRepoCommentAttrs` — discriminator attrs for the durable
1263
- * cross-repo-deferred comment (so the two graduators do not clobber
1264
- * each other's comment).
959
+ * Never throws; every failure lands in `errors[]`. Each finding carries
960
+ * `{ severity, path, summary, index }`. `spec` supplies `buildContentMarker`,
961
+ * `buildLegacyMarker`, optional `buildMatchTokens` (strong-read substrings,
962
+ * default `[contentMarker]`), `buildFollowUp`, `buildCrossRepoLog`,
963
+ * `decorateRecord`, and `crossRepoCommentAttrs`.
1265
964
  *
1266
965
  * @param {object} opts
1267
966
  * @param {number} opts.epicId
1268
- * @param {object} opts.provider — exposes `postComment(ticketId, body)` for
1269
- * the durable cross-repo-deferred persistence
967
+ * @param {object} opts.provider
1270
968
  * @param {object} [opts.config]
1271
969
  * @param {{owner: string, repo: string}} opts.currentRepo
1272
- * @param {{owner: string, repo: string}} [opts.frameworkRepo] — the
1273
- * `framework` ownership bucket. Absent means **unroutable**, never the
1274
- * consumer's repo: a framework-classified finding is then deferred and
1275
- * named rather than filed in the wrong tracker.
1276
- * @param {{owner: string, repo: string}} [opts.platformRepo] — the shared
1277
- * platform/infra bucket, for a caller whose classifier can reach it.
970
+ * @param {{owner: string, repo: string}} [opts.frameworkRepo] — absent means
971
+ * unroutable, never the consumer's repo.
972
+ * @param {{owner: string, repo: string}} [opts.platformRepo]
1278
973
  * @param {string} [opts.gitRef='HEAD']
1279
974
  * @param {Function} [opts.classifier=classifyPathSource]
1280
975
  * @param {string} [opts.ghPath='gh']
1281
976
  * @param {Function} [opts.spawnImpl]
1282
977
  * @param {string} [opts.cwd]
1283
- * @param {number} [opts.timeoutMs] — per-spawn watchdog bound
1284
- * @param {number} [opts.maxFilingsPerRun] — per-run filing cap
1285
- * @param {Array<object>} opts.findings — the pre-parsed findings to file.
1286
- * Required: a non-array is an `errors[]` short-circuit, never a silent
1287
- * no-op.
1288
- * @param {Set<string>} [opts.filedMarkers] — in-process memo of content
1289
- * markers filed so far. Pass a shared Set across multiple `graduate()`
1290
- * calls in one logical invocation (e.g. the retro graduator's two source
1291
- * buckets) so a marker filed in one call short-circuits a repeat in the
1292
- * next without a spawn. Defaults to a fresh per-call Set.
1293
- * @param {Map<string, Set<string>>} [opts.labelCache] — per-repo memo of the
1294
- * live label set, so the just-in-time label mint (Story #4828) costs one
1295
- * `gh label list` per routed repo rather than one per finding. Share it
1296
- * across the calls of one logical invocation, like `filedMarkers`.
1297
- * @param {NodeJS.ProcessEnv} [opts.env] — injectable for the blast-radius
1298
- * guard's context decision; defaults to `process.env`.
1299
- * @param {string[]} [opts.execArgv] — ditto; defaults to `process.execArgv`.
978
+ * @param {number} [opts.timeoutMs]
979
+ * @param {number} [opts.maxFilingsPerRun]
980
+ * @param {Array<object>} opts.findings — a non-array is an error, not a no-op.
981
+ * @param {Set<string>} [opts.filedMarkers] — share across calls of one
982
+ * invocation so a repeat short-circuits without a spawn.
983
+ * @param {Map<string, Set<string>>} [opts.labelCache] — share likewise.
984
+ * @param {NodeJS.ProcessEnv} [opts.env]
985
+ * @param {string[]} [opts.execArgv]
1300
986
  * @param {{info?: Function, warn?: Function, debug?: Function}} [opts.logger]
1301
- * @param {object} opts.spec — the per-graduator behaviour bundle
987
+ * @param {object} opts.spec
1302
988
  * @returns {Promise<{ filed: object[], skipped: object[], errors: string[] }>}
1303
- * Each `filed` record carries `action: 'created'|'updated'` — both are live
1304
- * writes this run performed, so a roll-up counting "filed" counts both.
1305
989
  */
1306
990
  export async function graduate({
1307
991
  epicId,
@@ -1339,10 +1023,6 @@ export async function graduate({
1339
1023
  });
1340
1024
  if (precondition) return { ...envelope, ...precondition };
1341
1025
 
1342
- // Pre-parsed findings are the only source (Story #5003). The
1343
- // structured-comment read/parse limb went with the audit-results
1344
- // graduator: it walked an Epic's `verification-results` comment, and v2
1345
- // has no Epics, so it could only ever resolve zero findings.
1346
1026
  if (!Array.isArray(preParsedFindings)) {
1347
1027
  return {
1348
1028
  ...envelope,
@@ -1351,8 +1031,7 @@ export async function graduate({
1351
1031
  }
1352
1032
  const findings = preParsedFindings;
1353
1033
 
1354
- // Blast-radius guard (Story #4837): decided ONCE per walk, before the
1355
- // first spawn, so a refused context costs no child process at all.
1034
+ // Decided once, before any spawn.
1356
1035
  const filing = resolveFilingContext({
1357
1036
  spawnImpl,
1358
1037
  ...(env === undefined ? {} : { env }),
@@ -1378,10 +1057,6 @@ export async function graduate({
1378
1057
  return envelope;
1379
1058
  }
1380
1059
 
1381
- // The ownership map the routing SSOT resolves against. `platform` is
1382
- // absent for both graduators today (their classifier is binary) and is
1383
- // threaded so a caller that does know a shared-infra repo routes there
1384
- // rather than into the nearest plausible tracker.
1385
1060
  const repos = {
1386
1061
  consumer: currentRepo,
1387
1062
  framework: frameworkRepo ?? null,