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,18 +1,7 @@
1
1
  /**
2
- * run-epilogue.js — real per-run closeout for `/mandrel-deliver --run`.
3
- *
4
- * After the last Story in a multi-Story plan-run lands, this module:
5
- * 1. Selects the cross-Story audit lens roster over the combined landed
6
- * tip vs base (deterministic `selectAudits` — host walks lenses).
7
- * 2. Rolls up friction follow-ups across every Story in the run and
8
- * files/posts them on the primary Story.
9
- * 3. Checks sibling Spec/acceptance coherence across Story bodies.
10
- * 4. Reports what the per-Story land tails left the run's container Epics
11
- * in — closed, or still open (Story #5139; read-only since #5280).
12
- *
13
- * There is no inert planner-only path: `planRunEpilogue` enumerates steps
14
- * and `runPlanRunEpilogue` executes them. Single-Story runs skip the
15
- * epilogue (`applicable: false`).
2
+ * Per-run closeout after the last Story of a multi-Story run lands: optional
3
+ * audit roster, friction roll-up, and a read-only container-Epic report.
4
+ * Single-Story runs are `applicable: false`.
16
5
  *
17
6
  * @module lib/orchestration/run-epilogue
18
7
  */
@@ -27,42 +16,28 @@ import {
27
16
  assessRollupOutcome,
28
17
  buildFollowUpsCommentBody,
29
18
  gatherRunFrictionSignals,
19
+ publishFollowUpsRollup,
30
20
  resolveFollowUpRepos,
31
21
  summarizeSignalCategories,
32
22
  } from './story-follow-ups.js';
33
23
  import { upsertStructuredComment } from './ticketing.js';
34
24
 
35
25
  /**
36
- * Canonical epilogue step kinds, in execution order.
37
- * @type {readonly ['audit-roster', 'follow-up-rollup', 'sibling-coherence', 'epic-close']}
26
+ * Step kinds in execution order. `audit-roster` is opt-in (`--audit-roster`)
27
+ * because it costs a sub-agent per lens; the other two are reporting.
28
+ *
29
+ * @type {readonly ['audit-roster', 'follow-up-rollup', 'epic-close']}
38
30
  */
39
31
  export const RUN_EPILOGUE_STEP_KINDS = Object.freeze([
40
32
  'audit-roster',
41
33
  'follow-up-rollup',
42
- 'sibling-coherence',
43
34
  'epic-close',
44
35
  ]);
45
36
 
46
37
  /**
47
- * Report which container Epics this run's Stories left closed, and which are
48
- * still open.
49
- *
50
- * **It derives nothing and writes nothing.** It used to: it walked every Story
51
- * and re-ran the full rollup, closing containers itself. That made sense while
52
- * the rollup only fired on the edges someone had wired, and the epilogue was
53
- * the backstop for the ones that were missed. Every child state change is now
54
- * an edge — init, post-land, the supersede close — so by the time the last
55
- * Story of a run has landed, its container has already been derived from a
56
- * complete child set by that Story's own land tail. Re-deriving here would ask
57
- * the same question a second time and answer it identically, at the cost of a
58
- * full re-read per Story and a second writer on the same issue.
59
- *
60
- * What survives is the report, which is why the step exists at all: one place
61
- * an operator reads to see what a multi-Story run did to its containers. A
62
- * pending Epic here is a real signal — it means a land tail's rollup declined
63
- * to close, and the tail's own outcome says why.
64
- *
65
- * Non-fatal throughout: a container it cannot read is simply not reported.
38
+ * Report which container Epics are closed vs still open. Read-only: each land
39
+ * tail already derived its container, so a pending Epic here means a tail's
40
+ * rollup declined to close. Unreadable containers are omitted.
66
41
  *
67
42
  * @param {{ stories: string[], provider: object }} opts
68
43
  * @returns {Promise<{ kind: string, closed: number[], pending: number[] }>}
@@ -70,8 +45,7 @@ export const RUN_EPILOGUE_STEP_KINDS = Object.freeze([
70
45
  async function executeEpicClose({ stories, provider }) {
71
46
  const closed = new Set();
72
47
  const pending = new Set();
73
- // Siblings share a container: resolve each distinct Epic once, however many
74
- // of the run's Stories point at it.
48
+ // Siblings share a container: report each Epic once.
75
49
  const seen = new Set();
76
50
 
77
51
  for (const raw of stories) {
@@ -97,11 +71,8 @@ async function executeEpicClose({ stories, provider }) {
97
71
  }
98
72
 
99
73
  /**
100
- * Read one Story's container Epic, or null.
101
- *
102
- * One request per Story via the declared parent port. Degrades to null on any
103
- * failure and on a provider without the port — this is a report, and a
104
- * container it could not read is better omitted than guessed at.
74
+ * Null on any failure or a provider without `getParentIssue` — omitted, never
75
+ * guessed.
105
76
  *
106
77
  * @param {{ storyId: number, provider: object }} opts
107
78
  * @returns {Promise<object|null>}
@@ -154,14 +125,17 @@ function normalizeStoryIds(stories) {
154
125
  }
155
126
 
156
127
  /**
157
- * Enumerate the ordered epilogue steps for a completed run.
158
- *
159
128
  * @param {object} args
160
129
  * @param {string} args.planRunId
161
130
  * @param {Array<string|number|{ id?: string|number, slug?: string }>} args.stories
131
+ * @param {boolean} [args.auditRoster] Default `false`.
162
132
  * @returns {object}
163
133
  */
164
- export function planRunEpilogue({ planRunId, stories } = {}) {
134
+ export function planRunEpilogue({
135
+ planRunId,
136
+ stories,
137
+ auditRoster = false,
138
+ } = {}) {
165
139
  const ids = normalizeStoryIds(stories);
166
140
  const runId =
167
141
  typeof planRunId === 'string' && planRunId.trim() !== ''
@@ -181,29 +155,26 @@ export function planRunEpilogue({ planRunId, stories } = {}) {
181
155
  };
182
156
  }
183
157
 
184
- // Positional `/mandrel-deliver 101 102` has no plan-run label. Synthesize a
185
- // stable adhoc id from the sorted Story set so the epilogue still
186
- // anchors comments / audit roster without requiring `--run`.
158
+ // Positional delivery has no plan-run label: synthesize a stable adhoc id.
187
159
  const effectiveRunId =
188
160
  runId ??
189
161
  `adhoc-${[...ids].sort((a, b) => Number(a) - Number(b)).join('-')}`;
190
162
 
191
163
  const steps = [
192
- {
193
- kind: 'audit-roster',
194
- description: `Select cross-Story audit lenses for run ${effectiveRunId}`,
195
- stories: ids,
196
- },
164
+ ...(auditRoster
165
+ ? [
166
+ {
167
+ kind: 'audit-roster',
168
+ description: `Select cross-Story audit lenses for run ${effectiveRunId}`,
169
+ stories: ids,
170
+ },
171
+ ]
172
+ : []),
197
173
  {
198
174
  kind: 'follow-up-rollup',
199
175
  description: `Friction follow-up roll-up for run ${effectiveRunId}`,
200
176
  stories: ids,
201
177
  },
202
- {
203
- kind: 'sibling-coherence',
204
- description: `Sibling-coherence check across the ${ids.length} Story specs of run ${effectiveRunId}`,
205
- stories: ids,
206
- },
207
178
  {
208
179
  kind: 'epic-close',
209
180
  description: `Report the container Epic state the land tails of run ${effectiveRunId} left behind`,
@@ -220,10 +191,7 @@ export function planRunEpilogue({ planRunId, stories } = {}) {
220
191
  }
221
192
 
222
193
  /**
223
- * How many first-parent commits of the base ref to scan when looking for the
224
- * run's landed squash-merges. The epilogue fires immediately after the run's
225
- * last Story lands, so the run's merges sit within the first handful of
226
- * commits; the limit only bounds the pathological case.
194
+ * The run's merges sit near the tip; this only bounds the pathological case.
227
195
  * @type {number}
228
196
  */
229
197
  const BASE_SCAN_LIMIT = 500;
@@ -232,8 +200,7 @@ const BASE_SCAN_LIMIT = 500;
232
200
  const FIELD_SEP = '\x1f';
233
201
 
234
202
  /**
235
- * Read the base ref's first-parent history as `{ sha, parents, subject }`
236
- * records, newest-first.
203
+ * Newest-first.
237
204
  *
238
205
  * @param {object} args
239
206
  * @param {string} args.cwd
@@ -283,35 +250,12 @@ function readFirstParentHistory({ cwd, baseRef, scanLimit, git }) {
283
250
  return { ok: true, commits };
284
251
  }
285
252
 
286
- /**
287
- * One trailing `(#<n>)` / `(refs #<n>)` marker, anchored at the end of what
288
- * is left of a subject after the markers to its right have been peeled off.
289
- */
290
253
  const TRAILING_MARKER_RE = /\s*\((?:refs\s+)?#(\d+)\)$/;
291
254
 
292
255
  /**
293
- * Peel the **trailing run** of `(#<n>)` markers off a squash subject.
294
- *
295
- * The shape this parses is fixed by the close pipeline plus GitHub: the PR
296
- * title `normalizePrTitle` writes ends with `(#<storyId>)`, and GitHub's
297
- * squash appends ` (#<prNumber>)` to it — so a landed Story merge reads
298
- * `<subject> (#<storyId>) (#<prNumber>)` and the Story's own marker is the
299
- * *second-to-last* marker, not the last one. Both are returned; the caller
300
- * decides which ids it cares about.
301
- *
302
- * Why the trailing run rather than a substring scan (the bug this replaces):
303
- * `subject.includes('(#101)')` matched the id **anywhere**, so an unrelated
304
- * later commit quoting an old marker — canonically a revert, whose subject
305
- * embeds the reverted title verbatim: `revert: "fix: x (#101) (#900)" (#950)`
306
- * — anchored the run on a far-older commit and inflated the roster diff with
307
- * everything in between. Peeling from the right stops at the first character
308
- * that is not part of a marker (the closing quote, above), so a quoted marker
309
- * is structurally out of reach.
310
- *
311
- * The `refs #` form is accepted because it is the other PR-title shape this
312
- * repo's own history carries (`feat(x): … (refs #4575) (#4582)`) — the
313
- * `refs #<id>` convention from `rules/git-conventions.md`. A plain substring
314
- * scan for `(#4575)` never matched those at all.
256
+ * Peel the trailing run of `(#<n>)` / `(refs #<n>)` markers off a squash
257
+ * subject (`<title> (#<storyId>) (#<prNumber>)`). Only the trailing run
258
+ * counts, so a revert quoting an old title can't anchor the run on an ancient commit.
315
259
  *
316
260
  * @param {string} subject
317
261
  * @returns {number[]} Marker ids, right-to-left (PR number first).
@@ -328,27 +272,15 @@ function trailingMarkerIds(subject) {
328
272
  }
329
273
 
330
274
  /**
331
- * Resolve the **pre-run base sha**: the commit the base branch pointed at
332
- * before the run's first Story landed.
333
- *
334
- * Why not `origin/main...HEAD` (the bug this replaces): the epilogue runs
335
- * *after* the run's last Story lands, so HEAD in the main checkout is either
336
- * `origin/main` itself or an ancestor of it. The three-dot merge-base is then
337
- * HEAD, and the diff is empty **by construction** — it never reported the
338
- * run's real diff. Rolling HEAD back does not help, so branch-reaping /
339
- * cleanup ordering is not the cause; the refs being compared are.
340
- *
341
- * The derivation walks the base ref's first-parent history for the run's
342
- * landed squash-merges. Every Story PR title carries a `(#<storyId>)` suffix
343
- * (guaranteed by `normalizePrTitle` in the close pipeline) and GitHub uses the
344
- * PR title as the squash subject, so the marker is a reliable, offline handle
345
- * that does **not** depend on the Story branches still existing. The earliest
346
- * such merge's first parent is the pre-run base.
275
+ * The commit the base pointed at before the run's first Story landed: the
276
+ * first parent of the earliest first-parent squash-merge carrying a run
277
+ * Story's `(#<storyId>)` marker. `origin/main...HEAD` would be empty by
278
+ * construction, since the epilogue runs after the last land.
347
279
  *
348
280
  * @param {object} args
349
- * @param {Array<string|number>} args.stories - Story ids in the run.
281
+ * @param {Array<string|number>} args.stories
350
282
  * @param {string} args.cwd
351
- * @param {string} [args.baseRef] - Remote-tracking base ref, e.g. `origin/main`.
283
+ * @param {string} [args.baseRef] - e.g. `origin/main`.
352
284
  * @param {number} [args.scanLimit]
353
285
  * @param {{ gitSpawn: Function }} [args.git]
354
286
  * @returns {{ resolved: true, baseSha: string, mergeSha: string, storyId: number, baseRef: string }
@@ -378,8 +310,7 @@ export function resolveRunBaseSha({
378
310
  return { resolved: false, baseRef, reason: history.reason };
379
311
  }
380
312
 
381
- // `git log` is newest-first; walk backwards so the first hit is the
382
- // *earliest* merge belonging to the run.
313
+ // Walk oldest-first so the first hit is the run's earliest merge.
383
314
  const wanted = new Set(ids);
384
315
  for (let i = history.commits.length - 1; i >= 0; i -= 1) {
385
316
  const commit = history.commits[i];
@@ -414,8 +345,6 @@ export function resolveRunBaseSha({
414
345
  }
415
346
 
416
347
  /**
417
- * List the files the run changed: `<pre-run base>...<baseRef>`.
418
- *
419
348
  * @returns {{ ok: true, files: string[] } | { ok: false, reason: string }}
420
349
  */
421
350
  function listChangedFiles({ cwd, baseSha, headRef, git }) {
@@ -444,8 +373,7 @@ function listChangedFiles({ cwd, baseSha, headRef, git }) {
444
373
  }
445
374
 
446
375
  /**
447
- * Resolve the run's combined landed diff, or an explicit reason it could not
448
- * be computed. Never conflates "could not compute" with "zero files changed".
376
+ * Never conflates "could not compute" with "zero files changed".
449
377
  *
450
378
  * @returns {{ resolved: boolean, changedFiles: string[], baseSha: string|null,
451
379
  * mergeSha: string|null, baseRef: string, reason: string|null }}
@@ -489,8 +417,7 @@ function resolveCombinedDiff({ stories, cwd, baseRef, git }) {
489
417
  }
490
418
 
491
419
  /**
492
- * The diff line of the roster comment. An unresolved base MUST read as a
493
- * loud failure, never as `Changed files considered: 0`.
420
+ * An unresolved base reads as a loud failure, never as zero files.
494
421
  *
495
422
  * @param {ReturnType<typeof resolveCombinedDiff>} diff
496
423
  * @returns {string[]}
@@ -526,48 +453,18 @@ function resolveBaseRef(config) {
526
453
  return `origin/${branch}`;
527
454
  }
528
455
 
529
- async function executeAuditRoster({
456
+ /**
457
+ * @param {object} args
458
+ * @returns {string}
459
+ */
460
+ function renderAuditRosterBody({
530
461
  planRunId,
531
462
  stories,
532
- cwd,
533
- provider,
534
- config,
535
- git,
536
- selectAuditsFn,
463
+ diff,
464
+ lensGrounding,
465
+ selectedAudits,
537
466
  }) {
538
- const primaryId = Number(stories[0]);
539
- const diff = resolveCombinedDiff({
540
- stories,
541
- cwd,
542
- baseRef: resolveBaseRef(config),
543
- git,
544
- });
545
- // Hand `selectAudits` the change set we just resolved — never a git range for
546
- // it to re-derive. This function runs in the main checkout *after* the run's
547
- // Stories merged, so every range it could name (`main...HEAD`) is empty by
548
- // construction; asking for one is how the roster came to select lenses from
549
- // zero files while printing the correct file list beside them (Story #4571).
550
- const lensGrounding = diff.resolved ? 'diff' : 'keyword-only';
551
- let selectedAudits = [];
552
- if (Number.isInteger(primaryId) && primaryId > 0) {
553
- const selected = await selectAuditsFn({
554
- ticketId: primaryId,
555
- gate: 'gate3',
556
- provider,
557
- changedFiles: diff.resolved ? diff.changedFiles : [],
558
- });
559
- selectedAudits = Array.isArray(selected?.selectedAudits)
560
- ? selected.selectedAudits
561
- : Array.isArray(selected)
562
- ? selected
563
- : [];
564
- }
565
- if (!diff.resolved) {
566
- Logger.warn(
567
- `[run-epilogue] plan-run ${planRunId}: combined landed diff unavailable — ${diff.reason}`,
568
- );
569
- }
570
- const body = [
467
+ return [
571
468
  '### plan-run-audit-roster',
572
469
  '',
573
470
  `Cross-Story audit roster for plan-run \`${planRunId}\`.`,
@@ -580,11 +477,7 @@ async function executeAuditRoster({
580
477
  ? selectedAudits.map((lens) => `- \`${lens}\``)
581
478
  : ['- _(none — docs-only or no matching change-set lenses)_']),
582
479
  '',
583
- // Story #4949 — the roster used to name the lenses and say nothing about
584
- // how to dispatch them, which made a serial walk (and a nested
585
- // coordinator) fully compliant with it. The lenses are read-only and share
586
- // no write paths, so they are the textbook independent fan-out; naming the
587
- // shape here is what turns that from an option into the instruction.
480
+ // Lenses are read-only and independent; state the fan-out shape explicitly.
588
481
  '**Dispatch shape (MUST): flat, parallel, one turn.** Spawn one ' +
589
482
  '`auditor` sub-agent per lens listed above and issue every one of those ' +
590
483
  'spawns in a SINGLE turn — no nested fan-out, no serial walk. A ' +
@@ -613,6 +506,53 @@ async function executeAuditRoster({
613
506
  ),
614
507
  '```',
615
508
  ].join('\n');
509
+ }
510
+
511
+ async function executeAuditRoster({
512
+ planRunId,
513
+ stories,
514
+ cwd,
515
+ provider,
516
+ config,
517
+ git,
518
+ selectAuditsFn,
519
+ }) {
520
+ const primaryId = Number(stories[0]);
521
+ const diff = resolveCombinedDiff({
522
+ stories,
523
+ cwd,
524
+ baseRef: resolveBaseRef(config),
525
+ git,
526
+ });
527
+ // Pass the resolved change set, never a range: post-merge, any range
528
+ // `selectAudits` could derive is empty by construction.
529
+ const lensGrounding = diff.resolved ? 'diff' : 'keyword-only';
530
+ let selectedAudits = [];
531
+ if (Number.isInteger(primaryId) && primaryId > 0) {
532
+ const selected = await selectAuditsFn({
533
+ ticketId: primaryId,
534
+ gate: 'gate3',
535
+ provider,
536
+ changedFiles: diff.resolved ? diff.changedFiles : [],
537
+ });
538
+ selectedAudits = Array.isArray(selected?.selectedAudits)
539
+ ? selected.selectedAudits
540
+ : Array.isArray(selected)
541
+ ? selected
542
+ : [];
543
+ }
544
+ if (!diff.resolved) {
545
+ Logger.warn(
546
+ `[run-epilogue] plan-run ${planRunId}: combined landed diff unavailable — ${diff.reason}`,
547
+ );
548
+ }
549
+ const body = renderAuditRosterBody({
550
+ planRunId,
551
+ stories,
552
+ diff,
553
+ lensGrounding,
554
+ selectedAudits,
555
+ });
616
556
  if (Number.isInteger(primaryId) && primaryId > 0) {
617
557
  await upsertStructuredComment(
618
558
  provider,
@@ -624,14 +564,9 @@ async function executeAuditRoster({
624
564
  return {
625
565
  kind: 'audit-roster',
626
566
  selectedAudits,
627
- // Whether the lenses above were chosen from the run's landed files
628
- // (`diff`) or, with no resolvable base, from the primary Story's prose
629
- // alone (`keyword-only`). The two are not interchangeable: a keyword-only
630
- // roster cannot select a lens that declares no keywords, so its silence
631
- // about a lens says nothing about the code.
567
+ // A keyword-only roster's silence about a lens says nothing about the code.
632
568
  lensGrounding,
633
- // `null` — not `0` — when unresolved: a zero count must only ever mean
634
- // "the run genuinely changed nothing".
569
+ // `null`, not `0`, when unresolved.
635
570
  changedFileCount: diff.resolved ? diff.changedFiles.length : null,
636
571
  changedFiles: diff.resolved ? diff.changedFiles : null,
637
572
  baseResolution: {
@@ -644,31 +579,19 @@ async function executeAuditRoster({
644
579
  };
645
580
  }
646
581
 
647
- async function executeFollowUpRollup({
582
+ /**
583
+ * @param {object} args
584
+ * @returns {object}
585
+ */
586
+ function composeRunProposals({
587
+ primaryId,
648
588
  planRunId,
649
589
  stories,
650
- provider,
590
+ signals,
651
591
  config,
652
- cwd,
653
- graduateFn = graduateRetroProposals,
654
592
  }) {
655
- // Shared with the story-scoped gather (Story #4649): `storyId` + `details`
656
- // are what the composer's recovery-netting keys on, and two hand-rolled
657
- // copies of this loop are how they got dropped in the first place.
658
- const { signals, window: frictionWindow } = await gatherRunFrictionSignals(
659
- stories,
660
- config,
661
- );
662
593
  const repos = resolveFollowUpRepos(config);
663
- const primaryId = Number(stories[0]);
664
- // Story #4850 — `runToken` and `anchorStoryIds` are INPUTS. This used to
665
- // compose with the primary Story's numeric id standing in for the run and
666
- // then rewrite the rendered title/body by regex over a `plan-run \d+`
667
- // substring, which meant the composer's own wording could not be changed
668
- // without silently breaking the patch. `anchorStoryIds` is what lets the
669
- // composer tell a corpus confined to this run from one spanning the whole
670
- // surviving window, so it never titles the latter as if it were the former.
671
- const proposals = composeRoutedProposals({
594
+ return composeRoutedProposals({
672
595
  anchorId: Number.isInteger(primaryId) ? primaryId : 1,
673
596
  anchorKind: 'run',
674
597
  runToken: String(planRunId ?? ''),
@@ -678,18 +601,61 @@ async function executeFollowUpRollup({
678
601
  signals,
679
602
  unresolvedBlockedEvents: [],
680
603
  });
681
- const graduated = await graduateFn({
604
+ }
605
+
606
+ /**
607
+ * @param {object} args
608
+ * @returns {Promise<object>}
609
+ */
610
+ function fileRunProposals({
611
+ primaryId,
612
+ proposals,
613
+ provider,
614
+ config,
615
+ cwd,
616
+ graduateFn,
617
+ }) {
618
+ const repos = resolveFollowUpRepos(config);
619
+ return graduateFn({
682
620
  epicId: primaryId,
683
621
  provider,
684
622
  config,
685
623
  currentRepo: repos.currentRepo,
686
- // The resolved bucket object, not a re-split of the slug: routing is
687
- // decided once in `github/framework-repo.js`.
688
624
  frameworkRepo: repos.repos.framework,
689
625
  platformRepo: repos.repos.platform,
690
626
  routedProposals: proposals,
691
627
  cwd,
692
628
  });
629
+ }
630
+
631
+ async function executeFollowUpRollup({
632
+ planRunId,
633
+ stories,
634
+ provider,
635
+ config,
636
+ cwd,
637
+ graduateFn = graduateRetroProposals,
638
+ }) {
639
+ const { signals, window: frictionWindow } = await gatherRunFrictionSignals(
640
+ stories,
641
+ config,
642
+ );
643
+ const primaryId = Number(stories[0]);
644
+ const proposals = composeRunProposals({
645
+ primaryId,
646
+ planRunId,
647
+ stories,
648
+ signals,
649
+ config,
650
+ });
651
+ const graduated = await fileRunProposals({
652
+ primaryId,
653
+ proposals,
654
+ provider,
655
+ config,
656
+ cwd,
657
+ graduateFn,
658
+ });
693
659
  const categories = summarizeSignalCategories(signals);
694
660
  const proposalCount = proposals.framework.length + proposals.consumer.length;
695
661
  const outcome = assessRollupOutcome({
@@ -700,55 +666,97 @@ async function executeFollowUpRollup({
700
666
  filingErrors: graduated.errors,
701
667
  filingSkipped: graduated.skipped,
702
668
  });
703
- if (Number.isInteger(primaryId) && primaryId > 0) {
704
- const body = buildFollowUpsCommentBody({
705
- storyId: primaryId,
706
- proposals,
707
- graduated,
708
- // Story #4578 — the run's Story count is what lets an empty roll-up
709
- // render as a flagged claim ("0 signals across N Stories") rather than
710
- // as "nothing to follow up".
711
- storyCount: stories.length,
712
- // Story #4828 — and the corpus is what lets a zero-proposal or
713
- // zero-filed roll-up name what it saw instead of rendering as clean.
714
- signalCount: signals.length,
715
- categories,
716
- }).replace(
717
- `from Story #${primaryId}`,
718
- `from plan-run \`${planRunId}\` (primary Story #${primaryId})`,
719
- );
720
- await upsertStructuredComment(provider, primaryId, 'follow-ups', body);
721
- }
669
+ await publishRunRollup({
670
+ primaryId,
671
+ planRunId,
672
+ provider,
673
+ config,
674
+ proposals,
675
+ graduated,
676
+ storyCount: stories.length,
677
+ signalCount: signals.length,
678
+ categories,
679
+ filedCount: graduated.filed?.length ?? 0,
680
+ });
681
+ return buildRollupStepResult({
682
+ signals,
683
+ storyCount: stories.length,
684
+ graduated,
685
+ proposals,
686
+ proposalCount,
687
+ categories,
688
+ outcome,
689
+ frictionWindow,
690
+ });
691
+ }
692
+
693
+ /**
694
+ * @param {object} args
695
+ * @returns {Promise<void>}
696
+ */
697
+ async function publishRunRollup({
698
+ primaryId,
699
+ planRunId,
700
+ provider,
701
+ config,
702
+ proposals,
703
+ graduated,
704
+ storyCount,
705
+ signalCount,
706
+ categories,
707
+ filedCount,
708
+ }) {
709
+ if (!Number.isInteger(primaryId) || primaryId <= 0) return;
710
+ const body = buildFollowUpsCommentBody({
711
+ storyId: primaryId,
712
+ proposals,
713
+ graduated,
714
+ storyCount,
715
+ signalCount,
716
+ categories,
717
+ }).replace(
718
+ `from Story #${primaryId}`,
719
+ `from plan-run \`${planRunId}\` (primary Story #${primaryId})`,
720
+ );
721
+ await publishFollowUpsRollup({
722
+ anchorId: primaryId,
723
+ body,
724
+ filedCount,
725
+ provider,
726
+ config,
727
+ });
728
+ }
729
+
730
+ /**
731
+ * The step result carries every suspect flag so the CLI never regexes the
732
+ * comment body.
733
+ *
734
+ * @param {object} args
735
+ * @returns {object}
736
+ */
737
+ function buildRollupStepResult({
738
+ signals,
739
+ storyCount,
740
+ graduated,
741
+ proposals,
742
+ proposalCount,
743
+ categories,
744
+ outcome,
745
+ frictionWindow,
746
+ }) {
722
747
  return {
723
748
  kind: 'follow-up-rollup',
724
749
  signalCount: signals.length,
725
- storyCount: stories.length,
750
+ storyCount,
726
751
  filed: graduated.filed?.length ?? 0,
727
- // Story #4850 — the recurrence window the gather actually applied, and what
728
- // it dropped. `signalCount` alone cannot distinguish "the window is bounded
729
- // at 30 days and 40 rows aged out" from "nothing older exists", and an
730
- // operator triaging a roll-up needs to know which corpus produced it.
752
+ // What the age window excluded, so a bounded corpus is distinguishable.
731
753
  frictionWindow,
732
- // Story #4828 — everything below is what the roll-up saw and what became
733
- // of it. The pre-#4828 result reported `signalCount` and `filed` and
734
- // nothing in between, so nine signals routing into one proposal whose
735
- // every filing attempt errored rendered as `{signalCount: 9, filed: 0,
736
- // discarded: []}` — arithmetically consistent, and indistinguishable from
737
- // a run with nothing to do.
738
754
  proposalCount,
739
- // The categories the corpus actually contained, so a zero-proposal
740
- // roll-up names its own input rather than asserting emptiness.
741
755
  categories,
742
756
  filingErrors: Array.isArray(graduated.errors) ? graduated.errors : [],
743
757
  filingSkipped: outcome.blockingSkipReasons,
744
- // Signals in, nothing out — not even a below-threshold row.
745
758
  zeroProposalSuspect: outcome.zeroProposals,
746
- // Proposals cleared the threshold and the filer produced none of them.
747
759
  unfiledProposalSuspect: outcome.unfiledProposals,
748
- // Story #4824 — a roll-up that discards every candidate must still name
749
- // what it discarded. Rendering that as "nothing to follow up" is how a
750
- // defect recurring once per Story survived eighteen consecutive Stories.
751
- // Surfaced on the step result so the CLI need not regex the comment body.
752
760
  discarded: proposals.discarded.map((item) => ({
753
761
  category: item.category,
754
762
  occurrences: item.occurrences,
@@ -757,93 +765,12 @@ async function executeFollowUpRollup({
757
765
  tools: item.tools ?? [],
758
766
  fingerprint: item.fingerprint ?? null,
759
767
  })),
760
- // Story #4578 — zero signals across a multi-Story run is a claim, not a
761
- // clean bill of health. Surfaced on the step result so the CLI can warn
762
- // the operator without re-deriving it from the comment prose.
763
- emptyRollupSuspect: signals.length === 0 && stories.length > 1,
768
+ emptyRollupSuspect: signals.length === 0 && storyCount > 1,
764
769
  };
765
770
  }
766
771
 
767
- function extractSection(body, heading) {
768
- if (typeof body !== 'string') return '';
769
- const re = new RegExp(
770
- `(?:^|\\n)## ${heading}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`,
771
- 'i',
772
- );
773
- const match = body.match(re);
774
- return match ? match[1].trim() : '';
775
- }
776
-
777
- async function executeSiblingCoherence({ planRunId, stories, provider }) {
778
- const findings = [];
779
- const bodies = [];
780
- for (const raw of stories) {
781
- const sid = Number(raw);
782
- if (!Number.isInteger(sid) || sid <= 0) continue;
783
- const ticket = await provider.getTicket(sid);
784
- bodies.push({
785
- id: sid,
786
- title: ticket?.title ?? '',
787
- acceptance: extractSection(ticket?.body ?? '', 'Acceptance'),
788
- spec: extractSection(ticket?.body ?? '', 'Spec'),
789
- });
790
- }
791
- const withAcceptance = bodies.filter((b) => b.acceptance.length > 0);
792
- if (withAcceptance.length > 0 && withAcceptance.length < bodies.length) {
793
- const missing = bodies
794
- .filter((b) => b.acceptance.length === 0)
795
- .map((b) => `#${b.id}`);
796
- findings.push(
797
- `Stories missing ## Acceptance while siblings declare ACs: ${missing.join(', ')}`,
798
- );
799
- }
800
- // Detect identical non-empty Spec blobs (likely copy-paste drift).
801
- const specMap = new Map();
802
- for (const b of bodies) {
803
- if (!b.spec) continue;
804
- const key = b.spec.replace(/\s+/g, ' ').slice(0, 400);
805
- if (!specMap.has(key)) specMap.set(key, []);
806
- specMap.get(key).push(b.id);
807
- }
808
- for (const ids of specMap.values()) {
809
- if (ids.length > 1) {
810
- findings.push(
811
- `Duplicate ## Spec prose across Stories ${ids.map((id) => `#${id}`).join(', ')} — split or dedupe.`,
812
- );
813
- }
814
- }
815
- const primaryId = Number(stories[0]);
816
- const body = [
817
- '### plan-run-sibling-coherence',
818
- '',
819
- `Sibling-coherence check for plan-run \`${planRunId}\`.`,
820
- '',
821
- findings.length === 0
822
- ? '_No coherence findings._'
823
- : findings.map((f) => `- ${f}`).join('\n'),
824
- '',
825
- '```json',
826
- JSON.stringify(
827
- { planRunId, stories: stories.map(Number), findings },
828
- null,
829
- 2,
830
- ),
831
- '```',
832
- ].join('\n');
833
- if (Number.isInteger(primaryId) && primaryId > 0) {
834
- await upsertStructuredComment(
835
- provider,
836
- primaryId,
837
- 'plan-run-sibling-coherence',
838
- body,
839
- );
840
- }
841
- return { kind: 'sibling-coherence', findings };
842
- }
843
-
844
772
  /**
845
- * Execute the per-run epilogue. Throws only on programmer misuse; step
846
- * failures are collected into `errors[]`.
773
+ * Throws only on programmer misuse; step failures collect into `errors[]`.
847
774
  *
848
775
  * @param {object} args
849
776
  * @param {string} args.planRunId
@@ -851,11 +778,10 @@ async function executeSiblingCoherence({ planRunId, stories, provider }) {
851
778
  * @param {object} args.provider
852
779
  * @param {object} [args.config]
853
780
  * @param {string} [args.cwd]
854
- * @param {{ gitSpawn: Function }} [args.git] - Injection seam for tests.
855
- * @param {typeof selectAudits} [args.selectAuditsFn] - Injection seam for tests.
856
- * @param {typeof graduateRetroProposals} [args.graduateFn] - Injection seam so
857
- * the roll-up's reporting layer can be asserted against a filer that fails
858
- * (Story #4828) without spawning a real `gh`.
781
+ * @param {{ gitSpawn: Function }} [args.git]
782
+ * @param {typeof selectAudits} [args.selectAuditsFn]
783
+ * @param {typeof graduateRetroProposals} [args.graduateFn]
784
+ * @param {boolean} [args.auditRoster] Default `false`.
859
785
  * @returns {Promise<object>}
860
786
  */
861
787
  export async function runPlanRunEpilogue({
@@ -867,8 +793,9 @@ export async function runPlanRunEpilogue({
867
793
  git = { gitSpawn },
868
794
  selectAuditsFn = selectAudits,
869
795
  graduateFn = graduateRetroProposals,
796
+ auditRoster = false,
870
797
  } = {}) {
871
- const plan = planRunEpilogue({ planRunId, stories });
798
+ const plan = planRunEpilogue({ planRunId, stories, auditRoster });
872
799
  if (!plan.applicable) {
873
800
  return { ...plan, results: [], errors: [] };
874
801
  }
@@ -903,14 +830,6 @@ export async function runPlanRunEpilogue({
903
830
  graduateFn,
904
831
  }),
905
832
  );
906
- } else if (step.kind === 'sibling-coherence') {
907
- results.push(
908
- await executeSiblingCoherence({
909
- planRunId: plan.planRunId,
910
- stories: plan.stories,
911
- provider,
912
- }),
913
- );
914
833
  } else if (step.kind === 'epic-close') {
915
834
  results.push(
916
835
  await executeEpicClose({ stories: plan.stories, provider }),