mandrel 2.60.0 → 2.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (661) hide show
  1. package/.agents/README.md +10 -10
  2. package/.agents/agents/story-worker.md +1 -1
  3. package/.agents/docs/agentrc-reference.json +4 -82
  4. package/.agents/docs/configuration.md +20 -87
  5. package/.agents/docs/workflows.md +1 -1
  6. package/.agents/instructions.md +1 -3
  7. package/.agents/rules/gherkin-standards.md +4 -0
  8. package/.agents/schemas/agentrc.schema.json +11 -486
  9. package/.agents/schemas/story-deliver-terminal.schema.json +10 -0
  10. package/.agents/schemas/validation-evidence.schema.json +2 -1
  11. package/.agents/scripts/README.md +14 -14
  12. package/.agents/scripts/acceptance-eval.js +32 -164
  13. package/.agents/scripts/agents-bootstrap-github.js +27 -129
  14. package/.agents/scripts/apply-quality-bootstrap.js +4 -40
  15. package/.agents/scripts/audit-baselines.js +6 -27
  16. package/.agents/scripts/audit-labels-bootstrap.js +5 -29
  17. package/.agents/scripts/audit-to-stories.js +91 -361
  18. package/.agents/scripts/boot-sweep.js +19 -72
  19. package/.agents/scripts/bootstrap.js +74 -395
  20. package/.agents/scripts/ceremony-derive.js +9 -45
  21. package/.agents/scripts/check-arch-cycles.js +14 -64
  22. package/.agents/scripts/check-baselines.js +8 -48
  23. package/.agents/scripts/check-context-budget.js +46 -172
  24. package/.agents/scripts/check-cyclomatic.js +12 -44
  25. package/.agents/scripts/check-dead-exports.js +13 -64
  26. package/.agents/scripts/check-doc-links.js +38 -186
  27. package/.agents/scripts/check-gherkin-corpus.js +24 -127
  28. package/.agents/scripts/check-test-temp-hygiene.js +28 -169
  29. package/.agents/scripts/coverage-capture.js +32 -99
  30. package/.agents/scripts/deliver-light.js +14 -101
  31. package/.agents/scripts/deliver-recover.js +6 -42
  32. package/.agents/scripts/deliver-run.js +36 -133
  33. package/.agents/scripts/diagnose-friction.js +24 -116
  34. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  35. package/.agents/scripts/evidence-gate.js +23 -85
  36. package/.agents/scripts/file-ci-gap.js +10 -50
  37. package/.agents/scripts/generate-config-docs.js +30 -170
  38. package/.agents/scripts/generate-lens-checklists.js +8 -52
  39. package/.agents/scripts/generate-skills-index.js +14 -112
  40. package/.agents/scripts/generate-workflows-doc.js +10 -70
  41. package/.agents/scripts/git-cleanup.js +2 -34
  42. package/.agents/scripts/lib/Graph.js +24 -81
  43. package/.agents/scripts/lib/ITicketingProvider.js +47 -143
  44. package/.agents/scripts/lib/Logger.js +14 -76
  45. package/.agents/scripts/lib/audit-baselines/engine.js +11 -31
  46. package/.agents/scripts/lib/audit-baselines/gate-surface.js +3 -17
  47. package/.agents/scripts/lib/audit-baselines/headroom.js +4 -20
  48. package/.agents/scripts/lib/audit-baselines/hotspots.js +3 -15
  49. package/.agents/scripts/lib/audit-baselines/kinds.js +23 -89
  50. package/.agents/scripts/lib/audit-baselines/outliers.js +6 -23
  51. package/.agents/scripts/lib/audit-baselines/read.js +3 -16
  52. package/.agents/scripts/lib/audit-baselines/staleness.js +7 -26
  53. package/.agents/scripts/lib/audit-baselines/surface-entry.js +7 -28
  54. package/.agents/scripts/lib/audit-baselines/trend.js +7 -20
  55. package/.agents/scripts/lib/audit-baselines/weights.js +9 -37
  56. package/.agents/scripts/lib/audit-suite/audit-rules-reader.js +3 -18
  57. package/.agents/scripts/lib/audit-suite/checklist-threading.js +26 -124
  58. package/.agents/scripts/lib/audit-suite/dispatch-checklist.js +14 -45
  59. package/.agents/scripts/lib/audit-suite/findings.js +12 -52
  60. package/.agents/scripts/lib/audit-suite/frontmatter.js +5 -29
  61. package/.agents/scripts/lib/audit-suite/index.js +1 -15
  62. package/.agents/scripts/lib/audit-suite/lens-checklist.js +10 -45
  63. package/.agents/scripts/lib/audit-suite/lens-diff-floor.js +11 -76
  64. package/.agents/scripts/lib/audit-suite/runner.js +13 -43
  65. package/.agents/scripts/lib/audit-suite/selector.js +49 -349
  66. package/.agents/scripts/lib/audit-suite/substitutions.js +12 -40
  67. package/.agents/scripts/lib/audit-suite/workflow-loader.js +3 -15
  68. package/.agents/scripts/lib/audit-to-stories/audit-label-taxonomy.js +11 -73
  69. package/.agents/scripts/lib/audit-to-stories/audit-lenses.js +8 -37
  70. package/.agents/scripts/lib/audit-to-stories/build-story-body.js +25 -143
  71. package/.agents/scripts/lib/audit-to-stories/dedupe-against-github.js +14 -80
  72. package/.agents/scripts/lib/audit-to-stories/epic-grouping-directive.js +4 -18
  73. package/.agents/scripts/lib/audit-to-stories/finding-adapter.js +7 -40
  74. package/.agents/scripts/lib/audit-to-stories/group-findings.js +9 -39
  75. package/.agents/scripts/lib/audit-to-stories/issue-corpus.js +10 -66
  76. package/.agents/scripts/lib/audit-to-stories/issue-index.js +6 -30
  77. package/.agents/scripts/lib/audit-to-stories/issues-file.js +6 -36
  78. package/.agents/scripts/lib/audit-to-stories/ledger-commit.js +17 -69
  79. package/.agents/scripts/lib/audit-to-stories/ledger-pr.js +17 -85
  80. package/.agents/scripts/lib/audit-to-stories/ledger-record.js +10 -48
  81. package/.agents/scripts/lib/audit-to-stories/parse-audit-md.js +38 -146
  82. package/.agents/scripts/lib/audit-to-stories/seed-from-findings.js +7 -42
  83. package/.agents/scripts/lib/audit-to-stories/wire-dependencies.js +10 -57
  84. package/.agents/scripts/lib/baseline-loader.js +12 -51
  85. package/.agents/scripts/lib/baseline-schema-registry.js +5 -22
  86. package/.agents/scripts/lib/baselines/component-matcher.js +3 -12
  87. package/.agents/scripts/lib/baselines/components.js +10 -61
  88. package/.agents/scripts/lib/baselines/coverage-updater-cli.js +7 -36
  89. package/.agents/scripts/lib/baselines/crap-preview-incremental.js +5 -21
  90. package/.agents/scripts/lib/baselines/crap-preview-scan.js +19 -45
  91. package/.agents/scripts/lib/baselines/crap-updater-cli.js +16 -65
  92. package/.agents/scripts/lib/baselines/diff-scope-cli.js +5 -33
  93. package/.agents/scripts/lib/baselines/duplication-scanner.js +11 -60
  94. package/.agents/scripts/lib/baselines/env-overrides.js +12 -67
  95. package/.agents/scripts/lib/baselines/envelope.js +13 -129
  96. package/.agents/scripts/lib/baselines/exit-codes.js +6 -49
  97. package/.agents/scripts/lib/baselines/git-base.js +23 -142
  98. package/.agents/scripts/lib/baselines/kernel.js +11 -111
  99. package/.agents/scripts/lib/baselines/kinds/_crap-new-method-gate.js +9 -47
  100. package/.agents/scripts/lib/baselines/kinds/_crap-read.js +8 -51
  101. package/.agents/scripts/lib/baselines/kinds/_shared-metric.js +7 -62
  102. package/.agents/scripts/lib/baselines/kinds/bundle-size.js +8 -29
  103. package/.agents/scripts/lib/baselines/kinds/coverage.js +3 -15
  104. package/.agents/scripts/lib/baselines/kinds/crap.js +94 -415
  105. package/.agents/scripts/lib/baselines/kinds/duplication.js +4 -30
  106. package/.agents/scripts/lib/baselines/kinds/kind-factory.js +7 -53
  107. package/.agents/scripts/lib/baselines/kinds/maintainability.js +15 -80
  108. package/.agents/scripts/lib/baselines/kinds/mutation.js +12 -72
  109. package/.agents/scripts/lib/baselines/maintainability-baseline-io.js +4 -11
  110. package/.agents/scripts/lib/baselines/merge-envelopes.js +30 -146
  111. package/.agents/scripts/lib/baselines/path-canon.js +19 -128
  112. package/.agents/scripts/lib/baselines/preview-gates.js +8 -37
  113. package/.agents/scripts/lib/baselines/reader.js +14 -107
  114. package/.agents/scripts/lib/baselines/refresh-service.js +35 -252
  115. package/.agents/scripts/lib/baselines/scope.js +11 -135
  116. package/.agents/scripts/lib/baselines/writer.js +16 -149
  117. package/.agents/scripts/lib/bdd-runner-detect.js +18 -113
  118. package/.agents/scripts/lib/bdd-scenario-budget.js +9 -36
  119. package/.agents/scripts/lib/bdd-scenario-scanner.js +11 -73
  120. package/.agents/scripts/lib/bdd-step-index.js +26 -100
  121. package/.agents/scripts/lib/bootstrap/baseline-merge-driver.js +23 -103
  122. package/.agents/scripts/lib/bootstrap/branch-protection.js +2 -5
  123. package/.agents/scripts/lib/bootstrap/commit-push.js +12 -50
  124. package/.agents/scripts/lib/bootstrap/gh-preflight.js +14 -101
  125. package/.agents/scripts/lib/bootstrap/hitl-confirm.js +5 -30
  126. package/.agents/scripts/lib/bootstrap/install-ledger.js +17 -73
  127. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +17 -121
  128. package/.agents/scripts/lib/bootstrap/manifest.js +15 -86
  129. package/.agents/scripts/lib/bootstrap/merge-methods.js +4 -33
  130. package/.agents/scripts/lib/bootstrap/preflight.js +12 -61
  131. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +34 -235
  132. package/.agents/scripts/lib/bootstrap/prompt.js +21 -129
  133. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +27 -141
  134. package/.agents/scripts/lib/bootstrap/summary.js +1 -8
  135. package/.agents/scripts/lib/bootstrap/workflow-audit.js +11 -84
  136. package/.agents/scripts/lib/branch-name-guard.js +4 -23
  137. package/.agents/scripts/lib/changed-files.js +31 -143
  138. package/.agents/scripts/lib/checks/core-bare-clean.js +4 -24
  139. package/.agents/scripts/lib/checks/index.js +18 -101
  140. package/.agents/scripts/lib/checks/loop-health.js +11 -53
  141. package/.agents/scripts/lib/checks/state.js +16 -91
  142. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +10 -61
  143. package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +14 -83
  144. package/.agents/scripts/lib/child-exec.js +39 -108
  145. package/.agents/scripts/lib/cli/standard-args.js +9 -116
  146. package/.agents/scripts/lib/cli-args.js +31 -146
  147. package/.agents/scripts/lib/cli-usage.js +5 -27
  148. package/.agents/scripts/lib/cli-utils.js +2 -12
  149. package/.agents/scripts/lib/close-validation/commands.js +13 -76
  150. package/.agents/scripts/lib/close-validation/gates.js +92 -331
  151. package/.agents/scripts/lib/close-validation/process.js +121 -151
  152. package/.agents/scripts/lib/close-validation/projections/advisories.js +5 -31
  153. package/.agents/scripts/lib/close-validation/projections/crap.js +19 -67
  154. package/.agents/scripts/lib/close-validation/projections/head-sha.js +1 -17
  155. package/.agents/scripts/lib/close-validation/projections/inputs.js +4 -34
  156. package/.agents/scripts/lib/close-validation/projections/maintainability.js +11 -58
  157. package/.agents/scripts/lib/close-validation/runner.js +53 -110
  158. package/.agents/scripts/lib/command-header.js +6 -28
  159. package/.agents/scripts/lib/config/acceptance-eval.js +4 -30
  160. package/.agents/scripts/lib/config/baselines.js +3 -14
  161. package/.agents/scripts/lib/config/ci.js +8 -38
  162. package/.agents/scripts/lib/config/commands.js +1 -15
  163. package/.agents/scripts/lib/config/defaults.js +4 -33
  164. package/.agents/scripts/lib/config/delivery-routing.js +6 -35
  165. package/.agents/scripts/lib/config/explain.js +9 -80
  166. package/.agents/scripts/lib/config/gates/coverage.schema.js +0 -12
  167. package/.agents/scripts/lib/config/gates/crap-incremental-coverage.schema.js +2 -30
  168. package/.agents/scripts/lib/config/gates/crap.schema.js +1 -34
  169. package/.agents/scripts/lib/config/gates/duplication.schema.js +1 -8
  170. package/.agents/scripts/lib/config/gates/index.js +2 -17
  171. package/.agents/scripts/lib/config/gates/maintainability.schema.js +1 -20
  172. package/.agents/scripts/lib/config/gates/mutation.schema.js +1 -7
  173. package/.agents/scripts/lib/config/gates/shared.js +4 -64
  174. package/.agents/scripts/lib/config/github.js +4 -22
  175. package/.agents/scripts/lib/config/limits.js +4 -57
  176. package/.agents/scripts/lib/config/paths.js +2 -21
  177. package/.agents/scripts/lib/config/qa.js +4 -38
  178. package/.agents/scripts/lib/config/quality.js +76 -432
  179. package/.agents/scripts/lib/config/runners.js +12 -56
  180. package/.agents/scripts/lib/config/runtime.js +13 -57
  181. package/.agents/scripts/lib/config/shared.js +2 -16
  182. package/.agents/scripts/lib/config/sync-agentrc.js +9 -50
  183. package/.agents/scripts/lib/config/temp-paths.js +40 -280
  184. package/.agents/scripts/lib/config/validate-orchestration.js +5 -17
  185. package/.agents/scripts/lib/config/worktree-isolation.js +9 -28
  186. package/.agents/scripts/lib/config-resolver.js +10 -52
  187. package/.agents/scripts/lib/config-schema-shared.js +1 -4
  188. package/.agents/scripts/lib/config-settings-schema-delivery.js +12 -294
  189. package/.agents/scripts/lib/config-settings-schema-quality.js +7 -219
  190. package/.agents/scripts/lib/config-settings-schema.js +37 -274
  191. package/.agents/scripts/lib/coverage-baseline.js +20 -110
  192. package/.agents/scripts/lib/coverage-capture-fullscope.js +12 -37
  193. package/.agents/scripts/lib/coverage-capture-incremental.js +12 -43
  194. package/.agents/scripts/lib/coverage-capture-usage.js +4 -24
  195. package/.agents/scripts/lib/coverage-capture.js +99 -224
  196. package/.agents/scripts/lib/coverage-utils.js +14 -79
  197. package/.agents/scripts/lib/cpu-pool.js +17 -123
  198. package/.agents/scripts/lib/crap-baseline-join.js +16 -88
  199. package/.agents/scripts/lib/crap-coordinates.js +6 -25
  200. package/.agents/scripts/lib/crap-engine.js +40 -153
  201. package/.agents/scripts/lib/crap-method-identity.js +16 -78
  202. package/.agents/scripts/lib/crap-utils.js +31 -155
  203. package/.agents/scripts/lib/cyclomatic-ceiling.js +14 -87
  204. package/.agents/scripts/lib/cyclomatic-scope.js +10 -50
  205. package/.agents/scripts/lib/dead-exports-knip.js +18 -56
  206. package/.agents/scripts/lib/dead-exports-mode.js +5 -24
  207. package/.agents/scripts/lib/degraded-mode.js +3 -26
  208. package/.agents/scripts/lib/dependency-parser.js +8 -40
  209. package/.agents/scripts/lib/dependency-version.js +13 -35
  210. package/.agents/scripts/lib/detect-package-manager.js +6 -36
  211. package/.agents/scripts/lib/doc-tiers.js +22 -126
  212. package/.agents/scripts/lib/duplicate-search.js +8 -72
  213. package/.agents/scripts/lib/env-loader.js +5 -27
  214. package/.agents/scripts/lib/error-redactor.js +6 -31
  215. package/.agents/scripts/lib/errors/index.js +2 -22
  216. package/.agents/scripts/lib/escomplex-ast-compat.js +22 -163
  217. package/.agents/scripts/lib/escomplex-kernel.js +21 -123
  218. package/.agents/scripts/lib/feedback-loop/graduator-core.js +93 -419
  219. package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +20 -98
  220. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +27 -151
  221. package/.agents/scripts/lib/findings/audit-ledger.js +23 -97
  222. package/.agents/scripts/lib/findings/classify-finding.js +14 -69
  223. package/.agents/scripts/lib/findings/promote-finding.js +14 -112
  224. package/.agents/scripts/lib/findings/provenance-field.js +11 -52
  225. package/.agents/scripts/lib/findings/route-finding.js +37 -255
  226. package/.agents/scripts/lib/findings/semantic-issue-search.js +14 -59
  227. package/.agents/scripts/lib/findings/severity.js +18 -104
  228. package/.agents/scripts/lib/format-generated-json.js +12 -44
  229. package/.agents/scripts/lib/full-suite-lock.js +160 -429
  230. package/.agents/scripts/lib/full-suite-queue.js +213 -0
  231. package/.agents/scripts/lib/gates/baseline-store.js +5 -9
  232. package/.agents/scripts/lib/gates/friction.js +1 -3
  233. package/.agents/scripts/lib/generated/agentrc-validator.js +2 -2
  234. package/.agents/scripts/lib/gh-exec.js +31 -259
  235. package/.agents/scripts/lib/git/cached-fetch.js +9 -52
  236. package/.agents/scripts/lib/git/sync-from-base.js +15 -107
  237. package/.agents/scripts/lib/git-branch-cleanup.js +14 -61
  238. package/.agents/scripts/lib/git-branch-lifecycle.js +16 -87
  239. package/.agents/scripts/lib/git-utils.js +37 -161
  240. package/.agents/scripts/lib/github/framework-repo.js +8 -71
  241. package/.agents/scripts/lib/github-url.js +2 -17
  242. package/.agents/scripts/lib/import-graph.js +11 -38
  243. package/.agents/scripts/lib/install-cmd-parser.js +4 -13
  244. package/.agents/scripts/lib/json-utils.js +3 -18
  245. package/.agents/scripts/lib/label-constants.js +16 -111
  246. package/.agents/scripts/lib/label-taxonomy.js +4 -30
  247. package/.agents/scripts/lib/maintainability-engine.js +12 -80
  248. package/.agents/scripts/lib/maintainability-unscorable.js +5 -25
  249. package/.agents/scripts/lib/maintainability-utils.js +16 -92
  250. package/.agents/scripts/lib/mandrel-catalog.js +12 -70
  251. package/.agents/scripts/lib/notifications/notifier.js +13 -38
  252. package/.agents/scripts/lib/npm-scripts.js +4 -23
  253. package/.agents/scripts/lib/observability/metrics-ledger.js +16 -76
  254. package/.agents/scripts/lib/observability/runtime-friction.js +44 -286
  255. package/.agents/scripts/lib/observability/signal-validator.js +5 -37
  256. package/.agents/scripts/lib/observability/signals-writer.js +11 -121
  257. package/.agents/scripts/lib/observability/source-classifier.js +21 -203
  258. package/.agents/scripts/lib/observability/terse-result.js +14 -47
  259. package/.agents/scripts/lib/onboard/init-tail.js +13 -74
  260. package/.agents/scripts/lib/onboard/scaffold-docs.js +11 -34
  261. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +25 -139
  262. package/.agents/scripts/lib/orchestration/auto-merge-cwd.js +11 -66
  263. package/.agents/scripts/lib/orchestration/behind-recovery.js +10 -55
  264. package/.agents/scripts/lib/orchestration/ceremony-routing.js +5 -75
  265. package/.agents/scripts/lib/orchestration/change-set.js +7 -36
  266. package/.agents/scripts/lib/orchestration/check-baselines/phases/compare.js +9 -46
  267. package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +11 -44
  268. package/.agents/scripts/lib/orchestration/check-baselines/phases/floors.js +5 -24
  269. package/.agents/scripts/lib/orchestration/check-baselines/phases/friction.js +3 -12
  270. package/.agents/scripts/lib/orchestration/check-baselines/phases/parse-args.js +5 -38
  271. package/.agents/scripts/lib/orchestration/check-baselines/phases/pipeline.js +3 -8
  272. package/.agents/scripts/lib/orchestration/check-baselines/phases/refresh-ack.js +28 -136
  273. package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +3 -13
  274. package/.agents/scripts/lib/orchestration/check-state.js +92 -0
  275. package/.agents/scripts/lib/orchestration/ci-gap-intake.js +37 -144
  276. package/.agents/scripts/lib/orchestration/ci-rerun-guard.js +42 -189
  277. package/.agents/scripts/lib/orchestration/code-review.js +24 -128
  278. package/.agents/scripts/lib/orchestration/column-sync.js +23 -111
  279. package/.agents/scripts/lib/orchestration/complexity-gate.js +42 -214
  280. package/.agents/scripts/lib/orchestration/deliver-recover.js +36 -168
  281. package/.agents/scripts/lib/orchestration/dependency-analyzer.js +4 -35
  282. package/.agents/scripts/lib/orchestration/dependency-candidates.js +9 -41
  283. package/.agents/scripts/lib/orchestration/diff-magnitude.js +25 -115
  284. package/.agents/scripts/lib/orchestration/doc-reader.js +2 -6
  285. package/.agents/scripts/lib/orchestration/docs-digest.js +13 -51
  286. package/.agents/scripts/lib/orchestration/epic-candidates.js +13 -53
  287. package/.agents/scripts/lib/orchestration/epic-checklist.js +9 -33
  288. package/.agents/scripts/lib/orchestration/epic-container.js +41 -167
  289. package/.agents/scripts/lib/orchestration/epic-expansion.js +10 -40
  290. package/.agents/scripts/lib/orchestration/epic-rollup.js +55 -207
  291. package/.agents/scripts/lib/orchestration/file-assumption-enum.js +2 -22
  292. package/.agents/scripts/lib/orchestration/file-assumptions.js +45 -253
  293. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-detect.js +9 -46
  294. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-reap.js +7 -57
  295. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches.js +21 -126
  296. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +2 -6
  297. package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +1 -4
  298. package/.agents/scripts/lib/orchestration/git-cleanup/phases/filters.js +1 -5
  299. package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes-ff.js +9 -34
  300. package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes.js +41 -190
  301. package/.agents/scripts/lib/orchestration/git-cleanup/phases/merged-tip.js +9 -45
  302. package/.agents/scripts/lib/orchestration/git-cleanup/phases/parse-args.js +1 -4
  303. package/.agents/scripts/lib/orchestration/git-cleanup/phases/phase-drivers.js +19 -85
  304. package/.agents/scripts/lib/orchestration/git-cleanup/phases/prompts.js +3 -17
  305. package/.agents/scripts/lib/orchestration/git-cleanup/phases/prune.js +1 -5
  306. package/.agents/scripts/lib/orchestration/git-cleanup/phases/render.js +16 -100
  307. package/.agents/scripts/lib/orchestration/git-cleanup/phases/stashes.js +1 -4
  308. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +16 -67
  309. package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +9 -33
  310. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +8 -29
  311. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +15 -68
  312. package/.agents/scripts/lib/orchestration/light-backstop.js +11 -49
  313. package/.agents/scripts/lib/orchestration/light-escalation.js +21 -89
  314. package/.agents/scripts/lib/orchestration/light-suitability.js +26 -231
  315. package/.agents/scripts/lib/orchestration/merge-block-class.js +39 -216
  316. package/.agents/scripts/lib/orchestration/merge-poll.js +104 -377
  317. package/.agents/scripts/lib/orchestration/pinned-identifier-lint.js +17 -57
  318. package/.agents/scripts/lib/orchestration/plan-context.js +52 -303
  319. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +22 -79
  320. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +5 -31
  321. package/.agents/scripts/lib/orchestration/plan-metrics.js +29 -108
  322. package/.agents/scripts/lib/orchestration/plan-navigation.js +8 -27
  323. package/.agents/scripts/lib/orchestration/plan-persist/acceptance-handle-repair.js +12 -49
  324. package/.agents/scripts/lib/orchestration/plan-persist/audit-provenance.js +18 -73
  325. package/.agents/scripts/lib/orchestration/plan-persist/changes-repair.js +14 -78
  326. package/.agents/scripts/lib/orchestration/plan-persist/cross-plan-links.js +6 -30
  327. package/.agents/scripts/lib/orchestration/plan-persist/epic-adoption.js +14 -65
  328. package/.agents/scripts/lib/orchestration/plan-persist/epic-ops.js +21 -76
  329. package/.agents/scripts/lib/orchestration/plan-persist/external-deps.js +6 -43
  330. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +14 -68
  331. package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +9 -41
  332. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +49 -248
  333. package/.agents/scripts/lib/orchestration/plan-persist/soft-findings.js +2 -12
  334. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +85 -368
  335. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +8 -38
  336. package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +30 -190
  337. package/.agents/scripts/lib/orchestration/plan-persist/wave-collision-gate.js +9 -49
  338. package/.agents/scripts/lib/orchestration/plan-persist/wave-serialisation.js +7 -28
  339. package/.agents/scripts/lib/orchestration/plan-reachability.js +13 -42
  340. package/.agents/scripts/lib/orchestration/plan-run-labels/reap.js +16 -91
  341. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +16 -54
  342. package/.agents/scripts/lib/orchestration/plan-text-hygiene.js +10 -52
  343. package/.agents/scripts/lib/orchestration/planning/authoring-context.js +14 -109
  344. package/.agents/scripts/lib/orchestration/planning/memory-pool-advisory.js +11 -83
  345. package/.agents/scripts/lib/orchestration/pr-watch.js +48 -306
  346. package/.agents/scripts/lib/orchestration/project-meta-cache.js +15 -80
  347. package/.agents/scripts/lib/orchestration/project-meta-resolver.js +10 -51
  348. package/.agents/scripts/lib/orchestration/reassert-status-column.js +12 -76
  349. package/.agents/scripts/lib/orchestration/remote-verifier.js +12 -36
  350. package/.agents/scripts/lib/orchestration/resolve-stories.js +33 -164
  351. package/.agents/scripts/lib/orchestration/retro-proposals.js +66 -361
  352. package/.agents/scripts/lib/orchestration/review-base-ref.js +9 -43
  353. package/.agents/scripts/lib/orchestration/review-depth.js +12 -94
  354. package/.agents/scripts/lib/orchestration/review-providers/codex.js +10 -111
  355. package/.agents/scripts/lib/orchestration/review-providers/degraded-gates.js +13 -71
  356. package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +7 -51
  357. package/.agents/scripts/lib/orchestration/review-providers/mi-exemptions.js +8 -53
  358. package/.agents/scripts/lib/orchestration/review-providers/native.js +30 -214
  359. package/.agents/scripts/lib/orchestration/review-providers/parse-findings.js +7 -52
  360. package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +4 -33
  361. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +11 -71
  362. package/.agents/scripts/lib/orchestration/review-providers/scoped-lint.js +19 -131
  363. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +6 -89
  364. package/.agents/scripts/lib/orchestration/review-providers/types.js +26 -56
  365. package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +3 -46
  366. package/.agents/scripts/lib/orchestration/run-epilogue.js +40 -199
  367. package/.agents/scripts/lib/orchestration/run-scoped-config.js +13 -81
  368. package/.agents/scripts/lib/orchestration/single-story-close/close-note.js +7 -34
  369. package/.agents/scripts/lib/orchestration/single-story-close/failed-terminal.js +16 -89
  370. package/.agents/scripts/lib/orchestration/single-story-close/gate-log.js +18 -109
  371. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +83 -239
  372. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +18 -80
  373. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +103 -97
  374. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +8 -64
  375. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +136 -486
  376. package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +30 -134
  377. package/.agents/scripts/lib/orchestration/single-story-close/phases/graphql-preflight.js +9 -50
  378. package/.agents/scripts/lib/orchestration/single-story-close/phases/lock-wait-pending.js +49 -0
  379. package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +13 -86
  380. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +20 -95
  381. package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +46 -203
  382. package/.agents/scripts/lib/orchestration/single-story-close/phases/pre-gate-steps.js +8 -50
  383. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +12 -83
  384. package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +6 -39
  385. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +1 -6
  386. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-outcome.js +4 -28
  387. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-override.js +6 -51
  388. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +6 -34
  389. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +23 -121
  390. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +110 -290
  391. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +15 -69
  392. package/.agents/scripts/lib/orchestration/story-body-gate.js +4 -23
  393. package/.agents/scripts/lib/orchestration/story-close/baseline-upward-writeback.js +50 -179
  394. package/.agents/scripts/lib/orchestration/story-close/context-budget-writeback.js +11 -41
  395. package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +23 -311
  396. package/.agents/scripts/lib/orchestration/story-close/phases/local-lens-review.js +22 -147
  397. package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +16 -67
  398. package/.agents/scripts/lib/orchestration/story-deliver-terminal-schema.js +12 -68
  399. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +42 -201
  400. package/.agents/scripts/lib/orchestration/story-follow-ups.js +43 -245
  401. package/.agents/scripts/lib/orchestration/story-init-envelope.js +4 -23
  402. package/.agents/scripts/lib/orchestration/story-init-remote.js +2 -6
  403. package/.agents/scripts/lib/orchestration/story-reachability.js +3 -23
  404. package/.agents/scripts/lib/orchestration/task-body-validator.js +12 -126
  405. package/.agents/scripts/lib/orchestration/ticket-lease.js +28 -131
  406. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +15 -149
  407. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +5 -33
  408. package/.agents/scripts/lib/orchestration/ticket-validator.js +39 -181
  409. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +51 -244
  410. package/.agents/scripts/lib/orchestration/ticketing/reads.js +39 -250
  411. package/.agents/scripts/lib/orchestration/ticketing/state.js +14 -68
  412. package/.agents/scripts/lib/orchestration/ticketing/transition.js +46 -263
  413. package/.agents/scripts/lib/orchestration/ticketing.js +2 -26
  414. package/.agents/scripts/lib/orchestration/verify-credit.js +18 -79
  415. package/.agents/scripts/lib/orchestration/worktree-dirty.js +5 -30
  416. package/.agents/scripts/lib/path-security.js +3 -6
  417. package/.agents/scripts/lib/plan-phase-cleanup.js +9 -49
  418. package/.agents/scripts/lib/preflight-runner.js +13 -69
  419. package/.agents/scripts/lib/process-group.js +143 -0
  420. package/.agents/scripts/lib/project-root.js +2 -8
  421. package/.agents/scripts/lib/provider-factory.js +2 -25
  422. package/.agents/scripts/lib/qa/console-allowlist.js +10 -59
  423. package/.agents/scripts/lib/qa/qa-session.js +15 -69
  424. package/.agents/scripts/lib/qa/redact-evidence.js +18 -129
  425. package/.agents/scripts/lib/qa/resolve-qa-contract.js +26 -135
  426. package/.agents/scripts/lib/qa/resolve-selection.js +16 -84
  427. package/.agents/scripts/lib/reserved-test-ids.js +9 -47
  428. package/.agents/scripts/lib/runtime-deps/dep-resolution.js +13 -53
  429. package/.agents/scripts/lib/runtime-deps/ensure-installed.js +10 -44
  430. package/.agents/scripts/lib/runtime-deps/manifest.js +10 -30
  431. package/.agents/scripts/lib/runtime-deps/parser-major.js +15 -51
  432. package/.agents/scripts/lib/runtime-deps/preflight.js +4 -22
  433. package/.agents/scripts/lib/runtime-deps/scan-imports.js +11 -55
  434. package/.agents/scripts/lib/signals/detectors/common.js +12 -38
  435. package/.agents/scripts/lib/signals/index.js +2 -19
  436. package/.agents/scripts/lib/signals/schema.js +14 -109
  437. package/.agents/scripts/lib/signals/write.js +2 -11
  438. package/.agents/scripts/lib/single-story/confirm-merge.js +31 -72
  439. package/.agents/scripts/lib/single-story/story-merged-notify.js +8 -49
  440. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +4 -26
  441. package/.agents/scripts/lib/single-story-sweep/protection.js +13 -100
  442. package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +60 -258
  443. package/.agents/scripts/lib/single-story-sweep.js +14 -97
  444. package/.agents/scripts/lib/skills/parse-skill.js +13 -59
  445. package/.agents/scripts/lib/skills/skills-index.js +8 -29
  446. package/.agents/scripts/lib/skills/walk-skill-files.js +17 -78
  447. package/.agents/scripts/lib/source-extensions.js +11 -42
  448. package/.agents/scripts/lib/source-text/strip-js-comments.js +8 -41
  449. package/.agents/scripts/lib/stdio-flush.js +9 -36
  450. package/.agents/scripts/lib/story-adjacency.js +8 -40
  451. package/.agents/scripts/lib/story-body/body-format-lints.js +22 -83
  452. package/.agents/scripts/lib/story-body/footer-block.js +11 -44
  453. package/.agents/scripts/lib/story-body/story-body.js +83 -358
  454. package/.agents/scripts/lib/temp-retention.js +42 -143
  455. package/.agents/scripts/lib/templates/decomposer-prompts.js +11 -65
  456. package/.agents/scripts/lib/test-env.js +12 -65
  457. package/.agents/scripts/lib/test-run-credit.js +10 -65
  458. package/.agents/scripts/lib/test-runner-contract.js +19 -74
  459. package/.agents/scripts/lib/test-temp.js +38 -184
  460. package/.agents/scripts/lib/test-tiers.js +12 -96
  461. package/.agents/scripts/lib/ticket-body-sections.js +21 -96
  462. package/.agents/scripts/lib/transpile.js +15 -74
  463. package/.agents/scripts/lib/util/concurrent-map.js +6 -25
  464. package/.agents/scripts/lib/util/parse-id-list.js +8 -34
  465. package/.agents/scripts/lib/util/poll-loop.js +8 -28
  466. package/.agents/scripts/lib/util/with-timeout.js +2 -11
  467. package/.agents/scripts/lib/validation-evidence.js +21 -96
  468. package/.agents/scripts/lib/wave-runner/footprint.js +17 -70
  469. package/.agents/scripts/lib/wave-runner/live-probe.js +53 -221
  470. package/.agents/scripts/lib/wave-runner/ready-set.js +72 -301
  471. package/.agents/scripts/lib/workers/crap-worker.js +11 -64
  472. package/.agents/scripts/lib/workers/maintainability-report-worker.js +8 -45
  473. package/.agents/scripts/lib/workers/maintainability-worker.js +5 -21
  474. package/.agents/scripts/lib/workers/serve-worker-messages.js +2 -18
  475. package/.agents/scripts/lib/workflow-closure.js +22 -105
  476. package/.agents/scripts/lib/workspace-provisioner.js +16 -54
  477. package/.agents/scripts/lib/worktree/git-hooks.js +15 -60
  478. package/.agents/scripts/lib/worktree/lifecycle/force-drain.js +20 -60
  479. package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +10 -62
  480. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +22 -86
  481. package/.agents/scripts/lib/worktree/lifecycle/reap.js +24 -126
  482. package/.agents/scripts/lib/worktree/lifecycle-manager.js +2 -20
  483. package/.agents/scripts/lib/worktree/node-modules-strategy.js +46 -180
  484. package/.agents/scripts/lib/worktree-manager.js +15 -40
  485. package/.agents/scripts/lint-issue-body.js +12 -68
  486. package/.agents/scripts/mandrel-update-preflight.js +10 -70
  487. package/.agents/scripts/merge-baseline.js +30 -104
  488. package/.agents/scripts/nav-registry-diff.js +22 -108
  489. package/.agents/scripts/notify.js +12 -69
  490. package/.agents/scripts/plan-context.js +27 -111
  491. package/.agents/scripts/plan-critics.js +12 -66
  492. package/.agents/scripts/plan-persist.js +31 -148
  493. package/.agents/scripts/plan-run-epilogue.js +11 -37
  494. package/.agents/scripts/pr-watch-with-update.js +76 -267
  495. package/.agents/scripts/providers/github/auth.js +3 -8
  496. package/.agents/scripts/providers/github/blocked-by-add.js +14 -61
  497. package/.agents/scripts/providers/github/board-add.js +5 -21
  498. package/.agents/scripts/providers/github/branch-protection.js +11 -43
  499. package/.agents/scripts/providers/github/cache.js +2 -14
  500. package/.agents/scripts/providers/github/comments.js +7 -40
  501. package/.agents/scripts/providers/github/compose.js +3 -19
  502. package/.agents/scripts/providers/github/errors.js +22 -125
  503. package/.agents/scripts/providers/github/issues.js +31 -123
  504. package/.agents/scripts/providers/github/labels.js +24 -124
  505. package/.agents/scripts/providers/github/mappers.js +5 -27
  506. package/.agents/scripts/providers/github/merge-methods.js +3 -22
  507. package/.agents/scripts/providers/github/project-board.js +2 -17
  508. package/.agents/scripts/providers/github/projects-v2-graphql.js +3 -6
  509. package/.agents/scripts/providers/github/request-helpers.js +5 -32
  510. package/.agents/scripts/providers/github/search-budget.js +9 -39
  511. package/.agents/scripts/providers/github/search-query.js +5 -26
  512. package/.agents/scripts/providers/github/sub-issue-add.js +15 -65
  513. package/.agents/scripts/providers/github/sub-issues.js +7 -36
  514. package/.agents/scripts/providers/github/tickets.js +32 -134
  515. package/.agents/scripts/providers/github.js +18 -59
  516. package/.agents/scripts/prune-plan-run-labels.js +12 -46
  517. package/.agents/scripts/quality-preview.js +35 -220
  518. package/.agents/scripts/resolve-doc-tiers.js +3 -26
  519. package/.agents/scripts/resolve-stories.js +16 -67
  520. package/.agents/scripts/resync-status-column.js +6 -25
  521. package/.agents/scripts/run-tests.js +29 -104
  522. package/.agents/scripts/single-story-close.js +23 -135
  523. package/.agents/scripts/single-story-confirm-merge.js +32 -139
  524. package/.agents/scripts/single-story-init.js +47 -209
  525. package/.agents/scripts/stories-wave-tick.js +102 -472
  526. package/.agents/scripts/sync-agentrc.js +3 -21
  527. package/.agents/scripts/sync-claude-agents.js +9 -55
  528. package/.agents/scripts/sync-claude-commands.js +20 -110
  529. package/.agents/scripts/test-wrapper.js +6 -43
  530. package/.agents/scripts/update-coverage-baseline.js +5 -22
  531. package/.agents/scripts/update-crap-baseline.js +7 -30
  532. package/.agents/scripts/update-duplication-baseline.js +16 -92
  533. package/.agents/scripts/update-maintainability-baseline.js +8 -62
  534. package/.agents/scripts/update-ticket-state.js +1 -7
  535. package/.agents/scripts/validate-skills.js +6 -26
  536. package/.agents/templates/agent-protocol.md +2 -2
  537. package/.agents/templates/docs/audit-sweep-runbook.md +3 -4
  538. package/.agents/workflows/audit-accessibility.md +4 -7
  539. package/.agents/workflows/audit-adrs.md +3 -6
  540. package/.agents/workflows/audit-architecture.md +3 -11
  541. package/.agents/workflows/audit-baselines.md +6 -9
  542. package/.agents/workflows/audit-clean-code.md +8 -12
  543. package/.agents/workflows/audit-data-model.md +3 -7
  544. package/.agents/workflows/audit-dependencies.md +4 -7
  545. package/.agents/workflows/audit-devops.md +4 -8
  546. package/.agents/workflows/audit-documentation.md +1 -4
  547. package/.agents/workflows/audit-mobile.md +4 -7
  548. package/.agents/workflows/audit-navigability.md +3 -6
  549. package/.agents/workflows/audit-performance.md +2 -4
  550. package/.agents/workflows/audit-privacy.md +4 -7
  551. package/.agents/workflows/audit-quality.md +4 -7
  552. package/.agents/workflows/audit-security.md +4 -7
  553. package/.agents/workflows/audit-seo.md +4 -7
  554. package/.agents/workflows/audit-sre.md +4 -7
  555. package/.agents/workflows/audit-to-stories.md +17 -30
  556. package/.agents/workflows/audit-ux-ui.md +4 -7
  557. package/.agents/workflows/helpers/audit-lens-core.md +1 -1
  558. package/.agents/workflows/helpers/code-quality-guardrails.md +12 -15
  559. package/.agents/workflows/helpers/deliver-digest.md +6 -4
  560. package/.agents/workflows/helpers/deliver-reference.md +114 -188
  561. package/.agents/workflows/helpers/deliver-story-reference.md +189 -533
  562. package/.agents/workflows/helpers/plan-reference.md +86 -139
  563. package/.agents/workflows/helpers/qa-core.md +12 -0
  564. package/.agents/workflows/memory-consolidate.md +1 -1
  565. package/.agents/workflows/qa-assist.md +27 -71
  566. package/.agents/workflows/qa-explore.md +19 -59
  567. package/.agents/workflows/qa-run.md +11 -33
  568. package/README.md +1 -1
  569. package/bin/mandrel.js +5 -46
  570. package/bin/postinstall.js +18 -107
  571. package/docs/CHANGELOG.md +25 -0
  572. package/lib/cli/doctor.js +11 -71
  573. package/lib/cli/init.js +26 -165
  574. package/lib/cli/migrate.js +5 -64
  575. package/lib/cli/registry.js +84 -467
  576. package/lib/cli/sync-agents.js +4 -64
  577. package/lib/cli/sync-commands.js +11 -64
  578. package/lib/cli/sync.js +34 -213
  579. package/lib/cli/uninstall.js +40 -219
  580. package/lib/cli/update.js +105 -661
  581. package/lib/cli/version-check.js +8 -72
  582. package/lib/cli/version-helpers.js +14 -87
  583. package/lib/migrations/helpers/retire-agentrc-key.js +11 -52
  584. package/lib/migrations/index.js +15 -92
  585. package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +2 -15
  586. package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +1 -13
  587. package/lib/migrations/steps/2.11.0-retire-max-seed-words.js +2 -15
  588. package/lib/migrations/steps/2.2.0-retire-epic-ac-tags.js +9 -38
  589. package/lib/migrations/steps/2.20.0-retire-codebase-snapshot.js +1 -13
  590. package/lib/migrations/steps/2.32.0-retire-lint-baseline-command.js +2 -27
  591. package/lib/migrations/steps/2.57.0-retire-delivery-limit-knobs.js +2 -23
  592. package/lib/migrations/steps/2.57.0-retire-planning-limit-knobs.js +2 -27
  593. package/lib/migrations/steps/2.60.0-retire-audit-results-autofile.js +2 -21
  594. package/lib/migrations/steps/strip-removed-agentrc-keys.js +333 -0
  595. package/package.json +16 -14
  596. package/.agents/docs/SDLC.md +0 -590
  597. package/.agents/docs/quality-gates.md +0 -1183
  598. package/.agents/rules/known-tooling-behavior.md +0 -200
  599. package/.agents/rules/orchestration-error-handling.md +0 -61
  600. package/.agents/rules/test-seams.md +0 -59
  601. package/.agents/schemas/baselines/lighthouse.schema.json +0 -59
  602. package/.agents/schemas/baselines/lint.schema.json +0 -47
  603. package/.agents/scripts/check-action-pinning.js +0 -260
  604. package/.agents/scripts/check-audit-attribution.js +0 -302
  605. package/.agents/scripts/check-baseline-drift.js +0 -211
  606. package/.agents/scripts/check-baseline-scope.js +0 -362
  607. package/.agents/scripts/check-generated-validator.js +0 -202
  608. package/.agents/scripts/check-knip-entries.js +0 -159
  609. package/.agents/scripts/check-lifecycle-lint.js +0 -294
  610. package/.agents/scripts/check-pinned-override-notes.js +0 -102
  611. package/.agents/scripts/check-schema-references.js +0 -368
  612. package/.agents/scripts/check-test-portability.js +0 -512
  613. package/.agents/scripts/check-workflow-citations.js +0 -218
  614. package/.agents/scripts/check-workflow-cli-lint.js +0 -299
  615. package/.agents/scripts/check-workflow-timeouts.js +0 -291
  616. package/.agents/scripts/install-matrix-assert.js +0 -326
  617. package/.agents/scripts/lib/audit-advisories.js +0 -195
  618. package/.agents/scripts/lib/audit-attribution.js +0 -134
  619. package/.agents/scripts/lib/baselines/drift-detector.js +0 -351
  620. package/.agents/scripts/lib/baselines/kinds/lighthouse.js +0 -87
  621. package/.agents/scripts/lib/baselines/kinds/lint.js +0 -184
  622. package/.agents/scripts/lib/baselines/orphan-pruner.js +0 -233
  623. package/.agents/scripts/lib/baselines/scope-assert.js +0 -223
  624. package/.agents/scripts/lib/baselines/scope-inventory.js +0 -314
  625. package/.agents/scripts/lib/c8-cli-path.js +0 -21
  626. package/.agents/scripts/lib/config/gates/lighthouse.schema.js +0 -51
  627. package/.agents/scripts/lib/config/gates/lint.schema.js +0 -18
  628. package/.agents/scripts/lib/dynamic-workflow/architecture-report-contract.js +0 -70
  629. package/.agents/scripts/lib/dynamic-workflow/audit-orchestrator.js +0 -284
  630. package/.agents/scripts/lib/dynamic-workflow/clean-code-report-contract.js +0 -80
  631. package/.agents/scripts/lib/dynamic-workflow/degraded-coverage.js +0 -81
  632. package/.agents/scripts/lib/dynamic-workflow/documentation-report-contract.js +0 -87
  633. package/.agents/scripts/lib/dynamic-workflow/performance-report-contract.js +0 -74
  634. package/.agents/scripts/lib/dynamic-workflow/quality-report-contract.js +0 -90
  635. package/.agents/scripts/lib/dynamic-workflow/report-contract-core.js +0 -43
  636. package/.agents/scripts/lib/dynamic-workflow/security-report-contract.js +0 -83
  637. package/.agents/scripts/lib/fs-walk.js +0 -52
  638. package/.agents/scripts/lib/knip-config-resolver.js +0 -181
  639. package/.agents/scripts/lib/knip-entry-sync.js +0 -452
  640. package/.agents/scripts/lib/pinned-override-notes.js +0 -88
  641. package/.agents/scripts/lib/pinned-override-resolve.js +0 -212
  642. package/.agents/scripts/lib/test-isolate/cli-options.js +0 -93
  643. package/.agents/scripts/lib/test-isolate/env-snapshot-loader.js +0 -52
  644. package/.agents/scripts/lib/test-isolate/list-files.js +0 -90
  645. package/.agents/scripts/lib/test-isolate/parse-tap.js +0 -75
  646. package/.agents/scripts/lib/test-isolate/progress-log.js +0 -45
  647. package/.agents/scripts/lib/test-isolate/render-report.js +0 -97
  648. package/.agents/scripts/lib/test-isolate/run-isolate.js +0 -87
  649. package/.agents/scripts/lib/test-isolate/runner.js +0 -483
  650. package/.agents/scripts/lib/test-profile/parse-tap.js +0 -136
  651. package/.agents/scripts/lib/test-profile/render-report.js +0 -45
  652. package/.agents/scripts/lint-label-vocabulary.js +0 -214
  653. package/.agents/scripts/post-structured-comment.js +0 -127
  654. package/.agents/scripts/provision-git-hooks.js +0 -85
  655. package/.agents/scripts/prune-baseline-orphans.js +0 -181
  656. package/.agents/scripts/run-coverage.js +0 -197
  657. package/.agents/scripts/run-lint.js +0 -133
  658. package/.agents/scripts/run-test-profile.js +0 -129
  659. package/.agents/scripts/run-verify.js +0 -125
  660. package/.agents/scripts/test-isolate.js +0 -55
  661. package/.agents/scripts/update-dead-exports-baseline.js +0 -321
@@ -1,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,15 +166,10 @@ 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-in** since Story
294
- * #5341: the toggle defaults to `false` and only an explicit `true` enables
295
- * it, because the filings the channel produced unattended were dominated by
296
- * noise (see `config-settings-schema-delivery.js` for the measured record).
169
+ * Opt-in `delivery.feedbackLoop.<key>` reader: only an explicit `true`
170
+ * enables filing, because unattended filings were dominated by noise.
297
171
  *
298
- * @param {string} toggleKey — key under `config.delivery.feedbackLoop`
299
- * (today, only "retroProposals" — the factory stays keyed so the next
300
- * graduator does not have to reinvent the resolution)
172
+ * @param {string} toggleKey
301
173
  * @returns {(config: object|undefined|null) => boolean}
302
174
  */
303
175
  export function makeIsAutoFileEnabled(toggleKey) {
@@ -307,13 +179,8 @@ export function makeIsAutoFileEnabled(toggleKey) {
307
179
  }
308
180
 
309
181
  /**
310
- * Probe whether the cited path exists in the merged tree at the given git
311
- * ref, distinguishing a confirmed-missing file from a probe failure.
312
- * Resolves `{ exists, probeError }`:
313
- *
314
- * - `git cat-file -e <ref>:<path>` exit 0 → `{ exists: true, probeError: false }`
315
- * - clean non-zero exit (file genuinely absent) → `{ exists: false, probeError: false }`
316
- * - 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.
317
184
  *
318
185
  * @param {object} opts
319
186
  * @param {string} opts.ref
@@ -344,16 +211,8 @@ export async function probePathStatus({
344
211
  }
345
212
 
346
213
  /**
347
- * Normalize an idempotency marker into a `gh search issues` query. Markers
348
- * are HTML comments (`<!-- … -->`) so they survive markdown rendering
349
- * without leaking into the visible body, but the `<` / `>` delimiters are
350
- * NOT index-safe as a query: GitHub full-text search DOES index the text
351
- * inside an HTML comment, yet a query that carries the `<!--` / `-->`
352
- * delimiters never matches that indexed text (measured against this repo,
353
- * Story #4657). Stripping the delimiters and trimming yields the bare marker
354
- * text — `retro-proposal-followup: <fp>` — which the index matches.
355
- * The caller-facing marker is left untouched; normalization is the probe's
356
- * 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.
357
216
  *
358
217
  * @param {string} marker
359
218
  * @returns {string}
@@ -364,11 +223,8 @@ function normalizeMarkerQuery(marker) {
364
223
  }
365
224
 
366
225
  /**
367
- * Normalize one `gh` issue row (from `search issues` or `issue list`) into
368
- * the identity the update path needs. `state` is lowercased and defaults to
369
- * the empty string — deliberately NOT to `'open'`: an unknown state must
370
- * never authorize editing somebody's issue (see
371
- * {@link resolveFollowUpRecurrence}).
226
+ * `state` defaults to `''`, never `'open'`: an unknown state must not
227
+ * authorize editing an issue.
372
228
  *
373
229
  * @param {object} row
374
230
  * @returns {{ number: number|null, state: string, url: string }}
@@ -383,15 +239,8 @@ function toFollowUpRef(row) {
383
239
  }
384
240
 
385
241
  /**
386
- * Search the routed repo for a follow-up carrying `marker`, resolving the
387
- * matched issue's identity rather than a bare yes/no. Uses `gh search issues`
388
- * so we hit the body field directly, querying the delimiter-stripped marker
389
- * text (see {@link normalizeMarkerQuery}) — the raw `<!-- … -->` form never
390
- * matches the index.
391
- *
392
- * Returns `null` when nothing matched OR when the probe could not decide
393
- * (spawn/parse error): the deliberate degrade-toward-filing posture, better
394
- * 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.
395
244
  *
396
245
  * @returns {Promise<{ number: number|null, state: string, url: string }|null>}
397
246
  */
@@ -428,46 +277,23 @@ async function searchFollowUpByMarker({
428
277
  }
429
278
  }
430
279
 
431
- /**
432
- * Probe whether a follow-up issue carrying the given idempotency marker
433
- * already exists in the routed repo. Thin boolean façade over
434
- * {@link searchFollowUpByMarker} — kept as the module's exported probe seam
435
- * so callers that only need the yes/no do not have to know about the issue
436
- * identity the recurrence path resolves.
437
- *
438
- * @returns {Promise<boolean>}
439
- */
280
+ /** @returns {Promise<boolean>} */
440
281
  export async function probeMarkerExists(opts) {
441
282
  return (await searchFollowUpByMarker(opts)) !== null;
442
283
  }
443
284
 
444
285
  /**
445
- * Strongly-consistent lookup of an already-filed follow-up, run ONLY on the
446
- * would-file path as the last gate before creating. `gh search issues` reads
447
- * an eventually-consistent index whose catch-up latency (measured under 20s
448
- * against this repo, Story #4657) is exactly wide enough to miss a
449
- * byte-identical duplicate filed seconds earlier in the same rollup. A
450
- * label-scoped `gh issue list … --state all` is strongly consistent, so it
451
- * closes that window. The list is narrowed by the follow-up's own labels
452
- * (supplied by the same `spec.buildFollowUp` that writes the marker, so the
453
- * two agree by construction) to keep the read bounded.
454
- *
455
- * `markers` is a LIST of body substrings, any one of which identifies a prior
456
- * filing (Story #4837). One finding can have been filed under more than one
457
- * marker shape — the retro graduator's pre-cutover marker embedded the run
458
- * anchor, so the same finding sits behind `epic-<anchor>-<fp>` on already-
459
- * filed issues and behind the anchor-free `<fp>` on new ones. Matching any of
460
- * them is what stops a marker-format change from re-filing the whole backlog.
461
- *
462
- * Returns `null` when nothing matched, or on any spawn/parse error — the
463
- * deliberate degrade-toward-filing posture: an undecidable probe risks a
464
- * 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).
465
291
  *
466
292
  * @param {object} opts
467
- * @param {string[]} opts.markers — body substrings identifying a prior filing.
293
+ * @param {string[]} opts.markers
468
294
  * @param {string} opts.owner
469
295
  * @param {string} opts.repo
470
- * @param {string[]} [opts.labels] — the follow-up's labels; scopes the list.
296
+ * @param {string[]} [opts.labels]
471
297
  * @param {string} [opts.ghPath]
472
298
  * @param {Function} [opts.spawnImpl]
473
299
  * @param {string} [opts.cwd]
@@ -518,9 +344,7 @@ async function findExistingFollowUp({
518
344
  tokens.some((token) => issue.body.includes(token)),
519
345
  );
520
346
  if (matches.length === 0) return null;
521
- // Prefer an OPEN match: a recurrence updates the live issue, while a closed
522
- // one is a decided follow-up. When several match, the open one is the one a
523
- // human is still looking at.
347
+ // Prefer an open match: a closed one is a decided follow-up.
524
348
  const open = matches.find(
525
349
  (issue) => String(issue?.state ?? '').toLowerCase() === 'open',
526
350
  );
@@ -528,13 +352,8 @@ async function findExistingFollowUp({
528
352
  }
529
353
 
530
354
  /**
531
- * Refresh an existing follow-up's body in place — the recurrence path
532
- * (Story #4837). A finding that recurs is the SAME finding: the loop's job is
533
- * to keep one issue current, not to mint issue #N+1 whose only new
534
- * information is that the count went up.
535
- *
536
- * Body-only: labels, title, assignees and state are left exactly as a human
537
- * may have curated them.
355
+ * Recurrence path: refresh the body only, leaving human-curated labels,
356
+ * title, assignees and state untouched.
538
357
  *
539
358
  * @returns {Promise<{ url: string|null, error: string|null }>}
540
359
  */
@@ -574,14 +393,10 @@ export async function updateFollowUpIssue({
574
393
  return { url: (res.stdout || '').trim(), error: null };
575
394
  }
576
395
 
577
- /** Prefix of the per-category friction axis the feedback loop mints. */
578
396
  const FRICTION_LABEL_PREFIX = 'friction::';
579
397
 
580
398
  /**
581
- * Resolve the color + description for a label the feedback loop is about to
582
- * mint. Only two axes reach this path — `meta::*` (routing) and
583
- * `friction::<category>` (the telemetry bucket) — so the mapping is a
584
- * two-branch lookup rather than a registry.
399
+ * Only `meta::*` and `friction::<category>` labels reach this path.
585
400
  *
586
401
  * @param {string} name
587
402
  * @returns {{ color: string, description: string }}
@@ -600,11 +415,7 @@ function describeMintedLabel(name) {
600
415
  }
601
416
 
602
417
  /**
603
- * Read the routed repo's live label names once per repo, memoized in
604
- * `labelCache`. Returns `null` when the set could not be established —
605
- * "verification unavailable", which is deliberately NOT the same as "the repo
606
- * has no labels": an unreadable set must not be read as proof that every
607
- * label is missing.
418
+ * Memoized per repo. `known: null` means unverifiable, not "no labels".
608
419
  *
609
420
  * @returns {Promise<{ known: Set<string>|null, error: string|null }>}
610
421
  */
@@ -654,28 +465,16 @@ async function readLiveLabelNames({
654
465
  }
655
466
 
656
467
  /**
657
- * Mint any of `labels` the routed repo does not already carry, so
658
- * `gh issue create --label …` can attach them (Story #4828).
659
- *
660
- * **Why this exists.** `gh issue create` resolves every `--label` name against
661
- * the repo before it creates anything, and fails the whole call when one is
662
- * absent. The feedback loop mints two axes that no bootstrap can enumerate
663
- * ahead of time — `meta::consumer-improvement` is absent from `LABEL_TAXONOMY`
664
- * outright, and `friction::<category>` names come from live telemetry — so on
665
- * a repo that never had them, *every* filing failed. The failure landed in the
666
- * graduator's `errors[]`, which the run epilogue did not surface, so a
667
- * hard-failing feedback loop rendered as `filed: 0`: indistinguishable from
668
- * "nothing was actionable".
669
- *
670
- * Degrades rather than blocks: when the live set cannot be read, this returns
671
- * no `missing` entries so the caller still attempts the filing (the old
672
- * 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.
673
472
  *
674
473
  * @param {object} opts
675
474
  * @param {string} opts.owner
676
475
  * @param {string} opts.repo
677
476
  * @param {string[]} opts.labels
678
- * @param {Map<string, Set<string>>} [opts.labelCache] — per-repo live-set memo.
477
+ * @param {Map<string, Set<string>>} [opts.labelCache]
679
478
  * @param {string} [opts.ghPath]
680
479
  * @param {Function} [opts.spawnImpl]
681
480
  * @param {string} [opts.cwd]
@@ -706,7 +505,6 @@ export async function ensureIssueLabels({
706
505
  cwd,
707
506
  timeoutMs,
708
507
  });
709
- // Verification unavailable — attempt the filing anyway rather than refuse.
710
508
  if (!known) return { created: [], missing: [], errors: error ? [error] : [] };
711
509
 
712
510
  const created = [];
@@ -735,8 +533,7 @@ export async function ensureIssueLabels({
735
533
  const failed =
736
534
  Boolean(res.spawnError) ||
737
535
  (typeof res.code === 'number' && res.code !== 0);
738
- // A concurrent roll-up may have minted it between the list and the create;
739
- // that is the idempotent outcome, not a failure.
536
+ // A concurrent mint between list and create is success.
740
537
  const raced = /label\b[\s\S]*?already exists/i.test(
741
538
  `${res.stderr ?? ''}${res.spawnError?.message ?? ''}`,
742
539
  );
@@ -753,12 +550,7 @@ export async function ensureIssueLabels({
753
550
  return { created, missing, errors };
754
551
  }
755
552
 
756
- /**
757
- * File a new follow-up issue via `gh issue create` and resolve to
758
- * `{ url, error }`. On success `url` is the trimmed stdout and `error` is
759
- * null; on failure `url` is null and `error` carries a human-readable
760
- * message.
761
- */
553
+ /** Resolves `{ url, error }`; exactly one is non-null. */
762
554
  export async function createFollowUpIssue({
763
555
  owner,
764
556
  repo,
@@ -797,16 +589,9 @@ export async function createFollowUpIssue({
797
589
  }
798
590
 
799
591
  /**
800
- * Validate the `graduate` preconditions (toggle, epicId, currentRepo shape).
801
- * Returns `null` when all preconditions pass, or a `{ skipped?, errors? }`
802
- * partial-envelope the caller short-circuits on. Story #4075 — extracted from
803
- * `graduate` so the orchestrating body holds no guard-chain branching.
804
- *
805
- * Story #5003 dropped the `provider.getTicketComments` gate with the
806
- * structured-comment read limb. The provider is now consulted only by the
807
- * best-effort cross-repo-deferred upsert, which reports its own faults into
808
- * `errors[]` — gating the whole walk on a shape only that path needs would
809
- * 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.
810
595
  */
811
596
  function checkGraduatePreconditions({ epicId, currentRepo, config, spec }) {
812
597
  if (!spec.isAutoFileEnabled(config)) {
@@ -826,16 +611,9 @@ function checkGraduatePreconditions({ epicId, currentRepo, config, spec }) {
826
611
  }
827
612
 
828
613
  /**
829
- * Probe whether a finding was already filed, checking both the current
830
- * content-hash marker AND the legacy `(epicId, parse-index)` marker so
831
- * findings filed before the fingerprint cutover are not re-filed. The
832
- * content-hash marker is passed in precomputed so a caller can consult an
833
- * in-process memo before spending a spawn.
834
- *
835
- * Resolves `{ alreadyFiled, existing }` — `existing` carries the matched
836
- * issue's `{ number, state, url }` when the search index surfaced it, so a
837
- * recurrence can update that issue rather than only knowing that one exists.
838
- * `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.
839
617
  */
840
618
  async function resolveAlreadyFiled({
841
619
  finding,
@@ -861,8 +639,6 @@ async function resolveAlreadyFiled({
861
639
 
862
640
  const hit = await probe(contentMarker);
863
641
  if (hit) return { alreadyFiled: true, existing: hit };
864
- // Legacy recognition — a pre-cutover follow-up carries the ordinal
865
- // marker, not the content hash. Skip re-filing when it is present.
866
642
  if (typeof spec.buildLegacyMarker === 'function') {
867
643
  const legacyMarker = spec.buildLegacyMarker(epicId, finding.index);
868
644
  if (legacyMarker) {
@@ -874,18 +650,9 @@ async function resolveAlreadyFiled({
874
650
  }
875
651
 
876
652
  /**
877
- * Resolve what a recurrence of an already-identified follow-up should do
878
- * (Story #4837), and fold the outcome into the running envelope.
879
- *
880
- * An **open** issue with a resolvable number is refreshed in place and
881
- * recorded on `envelope.filed` with `action: 'updated'` — same array as a
882
- * creation, because both are live writes this run performed and the roll-up
883
- * that reports "filed" must count them alike.
884
- *
885
- * Anything else records `already-filed` and touches nothing: a closed
886
- * follow-up is a decided one (reopening it would relitigate a human's call),
887
- * and an unresolvable number or state is not licence to edit an issue we
888
- * 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.
889
656
  *
890
657
  * @returns {Promise<boolean>} `true` when the recurrence was handled here.
891
658
  */
@@ -941,13 +708,6 @@ async function resolveFollowUpRecurrence({
941
708
  return true;
942
709
  }
943
710
 
944
- /**
945
- * Route a single finding (path-exists probe → repo routing → idempotency
946
- * probe → cap → file) and fold the outcome into the running envelope. Story
947
- * #4075 extracted this from `graduate`'s per-finding loop; Story #4415
948
- * hardened it (path-less seam, probe-error distinction, legacy-marker
949
- * recognition, filing cap, and cross-repo-deferred collection).
950
- */
951
711
  async function processGraduateFinding({
952
712
  finding,
953
713
  envelope,
@@ -981,9 +741,7 @@ async function processGraduateFinding({
981
741
  ),
982
742
  );
983
743
 
984
- // Path-less findings (the retro auto-filer seam) are not file-scoped, so
985
- // the path-exists gate does not apply — probing an empty path would
986
- // misclassify them `file-removed`. Only file-scoped findings are probed.
744
+ // A path-less finding would misclassify as `file-removed`; skip the probe.
987
745
  const hasPath =
988
746
  typeof finding.path === 'string' && finding.path.trim().length > 0;
989
747
  if (hasPath) {
@@ -994,18 +752,13 @@ async function processGraduateFinding({
994
752
  cwd,
995
753
  timeoutMs,
996
754
  });
997
- // A probe failure is not proof the file is gone — record it distinctly
998
- // so a transient git/spawn fault does not masquerade as a removal.
999
755
  if (probeError) return skip('probe-error');
1000
756
  if (!exists) return skip('file-removed');
1001
757
  }
1002
758
 
1003
759
  const source = classifier(finding.path, null);
1004
- // Ownership routing is the shared SSOT's call, and an unroutable bucket is
1005
- // an outcome rather than a fallback: the predecessor resolved an absent
1006
- // framework slug to the CONSUMER's repo, silently filing framework-owned
1007
- // work in the wrong place (see `github/framework-repo.js`). Unroutable
1008
- // findings are deferred and named, never re-pointed.
760
+ // Unroutable findings are deferred and named, never re-pointed at the
761
+ // consumer's repo.
1009
762
  const routing = routeOwnership({ bucket: source, repos, currentRepo });
1010
763
  if (!routing.routable) {
1011
764
  const logLine = `[${spec.fnName}] unroutable ${source} finding (${routing.missingKey} is unset) — not filed: ${finding.title ?? finding.path ?? `finding ${finding.index}`}`;
@@ -1029,11 +782,7 @@ async function processGraduateFinding({
1029
782
 
1030
783
  const contentMarker = spec.buildContentMarker(epicId, finding);
1031
784
 
1032
- // In-process memo (Story #4657): a marker already filed earlier in THIS
1033
- // invocation — e.g. the framework bucket of a retro rollup that also has
1034
- // the same category in the consumer bucket — short-circuits a repeat in a
1035
- // later bucket without spending a single spawn, and closes the same-rollup
1036
- // race the eventually-consistent search index cannot.
785
+ // In-process memo closes the same-invocation race the search index cannot.
1037
786
  if (filedMarkers?.has(contentMarker)) return skip('already-filed');
1038
787
 
1039
788
  const { alreadyFiled, existing } = await resolveAlreadyFiled({
@@ -1048,10 +797,8 @@ async function processGraduateFinding({
1048
797
  spec,
1049
798
  });
1050
799
 
1051
- // Resolve the follow-up (title/body/labels) BEFORE the dedup decision so
1052
- // the strong read can scope its `gh issue list` by the very labels this
1053
- // filing would carry (they agree with the marker by construction), and so
1054
- // 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.
1055
802
  const { title, body, labels } = spec.buildFollowUp({
1056
803
  finding,
1057
804
  source,
@@ -1078,15 +825,10 @@ async function processGraduateFinding({
1078
825
  return;
1079
826
  }
1080
827
 
1081
- // Per-run filing cap — bounds the live writes this run performs. Checked
1082
- // only on the would-file path: an `already-filed` finding resolved above
1083
- // never reaches here. The excess is surfaced so a re-run picks it up.
1084
828
  if (envelope.filed.length >= maxFilingsPerRun) return skip('cap-reached');
1085
829
 
1086
- // Mint any routing label the repo does not carry yet (Story #4828). This
1087
- // runs BEFORE the strong read as well as before the create: `gh issue list
1088
- // --label <absent>` exits 0 with `[]`, so an absent label silently degrades
1089
- // 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.
1090
832
  const ensured = await ensureIssueLabels({
1091
833
  owner: routedRepo.owner,
1092
834
  repo: routedRepo.repo,
@@ -1099,17 +841,9 @@ async function processGraduateFinding({
1099
841
  });
1100
842
  envelope.errors.push(...ensured.errors);
1101
843
  if (ensured.missing.length > 0) {
1102
- // `gh issue create` would reject the whole call on the absent name; say
1103
- // which label blocked it rather than replaying an opaque CLI failure.
1104
844
  return skip('label-ensure-failed');
1105
845
  }
1106
846
 
1107
- // Strong read (would-file path only, Story #4657): the search probe reads
1108
- // an eventually-consistent index that can miss a byte-identical duplicate
1109
- // filed seconds earlier. Confirm against a strongly-consistent,
1110
- // label-scoped `gh issue list` before creating. Skipped entirely on the
1111
- // already-filed path above, so it never fires when the search probe
1112
- // already matched.
1113
847
  const confirmed = await findExistingFollowUp({
1114
848
  markers:
1115
849
  typeof spec.buildMatchTokens === 'function'
@@ -1176,12 +910,6 @@ async function processGraduateFinding({
1176
910
  );
1177
911
  }
1178
912
 
1179
- /**
1180
- * Render the durable cross-repo-deferred comment body from the collected
1181
- * deferrals. Each row names the finding path/severity plus the would-be
1182
- * `gh issue create` command so an operator (or a later cross-repo pass)
1183
- * can act on it.
1184
- */
1185
913
  function renderCrossRepoDeferredBody(deferred, spec) {
1186
914
  const header =
1187
915
  spec.crossRepoCommentHeader ??
@@ -1191,8 +919,6 @@ function renderCrossRepoDeferredBody(deferred, spec) {
1191
919
  typeof finding.path === 'string' && finding.path.length > 0
1192
920
  ? `\`${finding.path}\``
1193
921
  : '_(no path)_';
1194
- // An unroutable finding has no destination to name — say which config
1195
- // key would give it one instead of inventing a repo for the row.
1196
922
  const destination = routedRepo
1197
923
  ? `${routedRepo.owner}/${routedRepo.repo}`
1198
924
  : `**unroutable** (\`${missingKey}\` is unset)`;
@@ -1204,12 +930,7 @@ function renderCrossRepoDeferredBody(deferred, spec) {
1204
930
  return [header, '', ...rows].join('\n');
1205
931
  }
1206
932
 
1207
- /**
1208
- * Durably persist the cross-repo-deferred findings as a structured comment
1209
- * on the Epic (upserted — one comment per graduator, refreshed in place).
1210
- * Best-effort: a provider that cannot post comments is a no-op, and an
1211
- * upsert failure lands in `envelope.errors` rather than throwing.
1212
- */
933
+ /** Best-effort upsert; failures land in `envelope.errors`, never thrown. */
1213
934
  async function persistCrossRepoDeferred({
1214
935
  epicId,
1215
936
  provider,
@@ -1235,74 +956,36 @@ async function persistCrossRepoDeferred({
1235
956
  }
1236
957
 
1237
958
  /**
1238
- * Parametrized graduator walk. Takes a pre-parsed `findings` array and, for
1239
- * each finding, runs the shared route → path probe → idempotency probe →
1240
- * cap → file sequence. Never throws — every failure path is captured in
1241
- * `errors[]`.
1242
- *
1243
- * Each finding MUST carry `{ severity, path, summary, index }` and MAY carry
1244
- * additional fields (e.g. `category`) that the builders use.
1245
- *
1246
- * The per-graduator variation lives entirely in the injected callbacks:
1247
- *
1248
- * - `buildContentMarker(epicId, finding)` — the content-hash HTML-comment
1249
- * marker embedded in (and searched for in) follow-up bodies.
1250
- * - `buildLegacyMarker(epicId, index)` — the pre-cutover ordinal marker,
1251
- * probed for idempotency so legacy filings are not duplicated.
1252
- * - `buildMatchTokens({ epicId, finding, contentMarker })` — optional; the
1253
- * body substrings the strong read accepts as proof of a prior filing.
1254
- * Defaults to `[contentMarker]`. A graduator whose marker format changed
1255
- * returns the old shape here too, so the cutover recognizes the backlog
1256
- * it already filed instead of duplicating it.
1257
- * - `buildFollowUp({ finding, source, epicId, idMarker })` — returns
1258
- * `{ title, body, labels }` for the issue to file.
1259
- * - `buildCrossRepoLog({ finding, routedRepo, source })` — returns the
1260
- * human-readable would-be-command string for a cross-repo skip.
1261
- * - `decorateRecord(record, finding)` — copies finding-specific fields
1262
- * (e.g. `lens`) onto a `skipped`/`filed` record before it is pushed.
1263
- * - `crossRepoCommentAttrs` — discriminator attrs for the durable
1264
- * cross-repo-deferred comment (so the two graduators do not clobber
1265
- * 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`.
1266
964
  *
1267
965
  * @param {object} opts
1268
966
  * @param {number} opts.epicId
1269
- * @param {object} opts.provider — exposes `postComment(ticketId, body)` for
1270
- * the durable cross-repo-deferred persistence
967
+ * @param {object} opts.provider
1271
968
  * @param {object} [opts.config]
1272
969
  * @param {{owner: string, repo: string}} opts.currentRepo
1273
- * @param {{owner: string, repo: string}} [opts.frameworkRepo] — the
1274
- * `framework` ownership bucket. Absent means **unroutable**, never the
1275
- * consumer's repo: a framework-classified finding is then deferred and
1276
- * named rather than filed in the wrong tracker.
1277
- * @param {{owner: string, repo: string}} [opts.platformRepo] — the shared
1278
- * 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]
1279
973
  * @param {string} [opts.gitRef='HEAD']
1280
974
  * @param {Function} [opts.classifier=classifyPathSource]
1281
975
  * @param {string} [opts.ghPath='gh']
1282
976
  * @param {Function} [opts.spawnImpl]
1283
977
  * @param {string} [opts.cwd]
1284
- * @param {number} [opts.timeoutMs] — per-spawn watchdog bound
1285
- * @param {number} [opts.maxFilingsPerRun] — per-run filing cap
1286
- * @param {Array<object>} opts.findings — the pre-parsed findings to file.
1287
- * Required: a non-array is an `errors[]` short-circuit, never a silent
1288
- * no-op.
1289
- * @param {Set<string>} [opts.filedMarkers] — in-process memo of content
1290
- * markers filed so far. Pass a shared Set across multiple `graduate()`
1291
- * calls in one logical invocation (e.g. the retro graduator's two source
1292
- * buckets) so a marker filed in one call short-circuits a repeat in the
1293
- * next without a spawn. Defaults to a fresh per-call Set.
1294
- * @param {Map<string, Set<string>>} [opts.labelCache] — per-repo memo of the
1295
- * live label set, so the just-in-time label mint (Story #4828) costs one
1296
- * `gh label list` per routed repo rather than one per finding. Share it
1297
- * across the calls of one logical invocation, like `filedMarkers`.
1298
- * @param {NodeJS.ProcessEnv} [opts.env] — injectable for the blast-radius
1299
- * guard's context decision; defaults to `process.env`.
1300
- * @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]
1301
986
  * @param {{info?: Function, warn?: Function, debug?: Function}} [opts.logger]
1302
- * @param {object} opts.spec — the per-graduator behaviour bundle
987
+ * @param {object} opts.spec
1303
988
  * @returns {Promise<{ filed: object[], skipped: object[], errors: string[] }>}
1304
- * Each `filed` record carries `action: 'created'|'updated'` — both are live
1305
- * writes this run performed, so a roll-up counting "filed" counts both.
1306
989
  */
1307
990
  export async function graduate({
1308
991
  epicId,
@@ -1340,10 +1023,6 @@ export async function graduate({
1340
1023
  });
1341
1024
  if (precondition) return { ...envelope, ...precondition };
1342
1025
 
1343
- // Pre-parsed findings are the only source (Story #5003). The
1344
- // structured-comment read/parse limb went with the audit-results
1345
- // graduator: it walked an Epic's `verification-results` comment, and v2
1346
- // has no Epics, so it could only ever resolve zero findings.
1347
1026
  if (!Array.isArray(preParsedFindings)) {
1348
1027
  return {
1349
1028
  ...envelope,
@@ -1352,8 +1031,7 @@ export async function graduate({
1352
1031
  }
1353
1032
  const findings = preParsedFindings;
1354
1033
 
1355
- // Blast-radius guard (Story #4837): decided ONCE per walk, before the
1356
- // first spawn, so a refused context costs no child process at all.
1034
+ // Decided once, before any spawn.
1357
1035
  const filing = resolveFilingContext({
1358
1036
  spawnImpl,
1359
1037
  ...(env === undefined ? {} : { env }),
@@ -1379,10 +1057,6 @@ export async function graduate({
1379
1057
  return envelope;
1380
1058
  }
1381
1059
 
1382
- // The ownership map the routing SSOT resolves against. `platform` is
1383
- // absent for both graduators today (their classifier is binary) and is
1384
- // threaded so a caller that does know a shared-infra repo routes there
1385
- // rather than into the nearest plausible tracker.
1386
1060
  const repos = {
1387
1061
  consumer: currentRepo,
1388
1062
  framework: frameworkRepo ?? null,