mandrel 2.60.0 → 2.62.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 (662) 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/merge-queue.js +158 -0
  318. package/.agents/scripts/lib/orchestration/pinned-identifier-lint.js +17 -57
  319. package/.agents/scripts/lib/orchestration/plan-context.js +52 -303
  320. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +22 -79
  321. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +5 -31
  322. package/.agents/scripts/lib/orchestration/plan-metrics.js +29 -108
  323. package/.agents/scripts/lib/orchestration/plan-navigation.js +8 -27
  324. package/.agents/scripts/lib/orchestration/plan-persist/acceptance-handle-repair.js +12 -49
  325. package/.agents/scripts/lib/orchestration/plan-persist/audit-provenance.js +18 -73
  326. package/.agents/scripts/lib/orchestration/plan-persist/changes-repair.js +14 -78
  327. package/.agents/scripts/lib/orchestration/plan-persist/cross-plan-links.js +6 -30
  328. package/.agents/scripts/lib/orchestration/plan-persist/epic-adoption.js +14 -65
  329. package/.agents/scripts/lib/orchestration/plan-persist/epic-ops.js +21 -76
  330. package/.agents/scripts/lib/orchestration/plan-persist/external-deps.js +6 -43
  331. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +14 -68
  332. package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +9 -41
  333. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +49 -248
  334. package/.agents/scripts/lib/orchestration/plan-persist/soft-findings.js +2 -12
  335. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +85 -368
  336. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +8 -38
  337. package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +30 -190
  338. package/.agents/scripts/lib/orchestration/plan-persist/wave-collision-gate.js +9 -49
  339. package/.agents/scripts/lib/orchestration/plan-persist/wave-serialisation.js +7 -28
  340. package/.agents/scripts/lib/orchestration/plan-reachability.js +13 -42
  341. package/.agents/scripts/lib/orchestration/plan-run-labels/reap.js +16 -91
  342. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +16 -54
  343. package/.agents/scripts/lib/orchestration/plan-text-hygiene.js +10 -52
  344. package/.agents/scripts/lib/orchestration/planning/authoring-context.js +14 -109
  345. package/.agents/scripts/lib/orchestration/planning/memory-pool-advisory.js +11 -83
  346. package/.agents/scripts/lib/orchestration/pr-watch.js +48 -306
  347. package/.agents/scripts/lib/orchestration/project-meta-cache.js +15 -80
  348. package/.agents/scripts/lib/orchestration/project-meta-resolver.js +10 -51
  349. package/.agents/scripts/lib/orchestration/reassert-status-column.js +12 -76
  350. package/.agents/scripts/lib/orchestration/remote-verifier.js +12 -36
  351. package/.agents/scripts/lib/orchestration/resolve-stories.js +33 -164
  352. package/.agents/scripts/lib/orchestration/retro-proposals.js +66 -361
  353. package/.agents/scripts/lib/orchestration/review-base-ref.js +9 -43
  354. package/.agents/scripts/lib/orchestration/review-depth.js +12 -94
  355. package/.agents/scripts/lib/orchestration/review-providers/codex.js +10 -111
  356. package/.agents/scripts/lib/orchestration/review-providers/degraded-gates.js +13 -71
  357. package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +7 -51
  358. package/.agents/scripts/lib/orchestration/review-providers/mi-exemptions.js +8 -53
  359. package/.agents/scripts/lib/orchestration/review-providers/native.js +30 -214
  360. package/.agents/scripts/lib/orchestration/review-providers/parse-findings.js +7 -52
  361. package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +4 -33
  362. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +11 -71
  363. package/.agents/scripts/lib/orchestration/review-providers/scoped-lint.js +19 -131
  364. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +6 -89
  365. package/.agents/scripts/lib/orchestration/review-providers/types.js +26 -56
  366. package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +3 -46
  367. package/.agents/scripts/lib/orchestration/run-epilogue.js +40 -199
  368. package/.agents/scripts/lib/orchestration/run-scoped-config.js +13 -81
  369. package/.agents/scripts/lib/orchestration/single-story-close/close-note.js +7 -34
  370. package/.agents/scripts/lib/orchestration/single-story-close/failed-terminal.js +16 -89
  371. package/.agents/scripts/lib/orchestration/single-story-close/gate-log.js +18 -109
  372. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +190 -280
  373. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +18 -80
  374. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +103 -97
  375. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +8 -64
  376. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +183 -485
  377. package/.agents/scripts/lib/orchestration/single-story-close/phases/conventional-subject.js +30 -134
  378. package/.agents/scripts/lib/orchestration/single-story-close/phases/graphql-preflight.js +9 -50
  379. package/.agents/scripts/lib/orchestration/single-story-close/phases/lock-wait-pending.js +49 -0
  380. package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +13 -86
  381. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +20 -95
  382. package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +46 -203
  383. package/.agents/scripts/lib/orchestration/single-story-close/phases/pre-gate-steps.js +8 -50
  384. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +12 -83
  385. package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +6 -39
  386. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +1 -6
  387. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-outcome.js +4 -28
  388. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-override.js +6 -51
  389. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +6 -34
  390. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +23 -121
  391. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +110 -290
  392. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +15 -69
  393. package/.agents/scripts/lib/orchestration/story-body-gate.js +4 -23
  394. package/.agents/scripts/lib/orchestration/story-close/baseline-upward-writeback.js +50 -179
  395. package/.agents/scripts/lib/orchestration/story-close/context-budget-writeback.js +11 -41
  396. package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +23 -311
  397. package/.agents/scripts/lib/orchestration/story-close/phases/local-lens-review.js +22 -147
  398. package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +16 -67
  399. package/.agents/scripts/lib/orchestration/story-deliver-terminal-schema.js +12 -68
  400. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +42 -201
  401. package/.agents/scripts/lib/orchestration/story-follow-ups.js +43 -245
  402. package/.agents/scripts/lib/orchestration/story-init-envelope.js +4 -23
  403. package/.agents/scripts/lib/orchestration/story-init-remote.js +2 -6
  404. package/.agents/scripts/lib/orchestration/story-reachability.js +3 -23
  405. package/.agents/scripts/lib/orchestration/task-body-validator.js +12 -126
  406. package/.agents/scripts/lib/orchestration/ticket-lease.js +28 -131
  407. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +15 -149
  408. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +5 -33
  409. package/.agents/scripts/lib/orchestration/ticket-validator.js +39 -181
  410. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +51 -244
  411. package/.agents/scripts/lib/orchestration/ticketing/reads.js +39 -250
  412. package/.agents/scripts/lib/orchestration/ticketing/state.js +14 -68
  413. package/.agents/scripts/lib/orchestration/ticketing/transition.js +46 -263
  414. package/.agents/scripts/lib/orchestration/ticketing.js +2 -26
  415. package/.agents/scripts/lib/orchestration/verify-credit.js +18 -79
  416. package/.agents/scripts/lib/orchestration/worktree-dirty.js +5 -30
  417. package/.agents/scripts/lib/path-security.js +3 -6
  418. package/.agents/scripts/lib/plan-phase-cleanup.js +9 -49
  419. package/.agents/scripts/lib/preflight-runner.js +13 -69
  420. package/.agents/scripts/lib/process-group.js +143 -0
  421. package/.agents/scripts/lib/project-root.js +2 -8
  422. package/.agents/scripts/lib/provider-factory.js +2 -25
  423. package/.agents/scripts/lib/qa/console-allowlist.js +10 -59
  424. package/.agents/scripts/lib/qa/qa-session.js +15 -69
  425. package/.agents/scripts/lib/qa/redact-evidence.js +18 -129
  426. package/.agents/scripts/lib/qa/resolve-qa-contract.js +26 -135
  427. package/.agents/scripts/lib/qa/resolve-selection.js +16 -84
  428. package/.agents/scripts/lib/reserved-test-ids.js +9 -47
  429. package/.agents/scripts/lib/runtime-deps/dep-resolution.js +13 -53
  430. package/.agents/scripts/lib/runtime-deps/ensure-installed.js +10 -44
  431. package/.agents/scripts/lib/runtime-deps/manifest.js +10 -30
  432. package/.agents/scripts/lib/runtime-deps/parser-major.js +15 -51
  433. package/.agents/scripts/lib/runtime-deps/preflight.js +4 -22
  434. package/.agents/scripts/lib/runtime-deps/scan-imports.js +11 -55
  435. package/.agents/scripts/lib/signals/detectors/common.js +12 -38
  436. package/.agents/scripts/lib/signals/index.js +2 -19
  437. package/.agents/scripts/lib/signals/schema.js +14 -109
  438. package/.agents/scripts/lib/signals/write.js +2 -11
  439. package/.agents/scripts/lib/single-story/confirm-merge.js +31 -72
  440. package/.agents/scripts/lib/single-story/story-merged-notify.js +8 -49
  441. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +4 -26
  442. package/.agents/scripts/lib/single-story-sweep/protection.js +13 -100
  443. package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +60 -258
  444. package/.agents/scripts/lib/single-story-sweep.js +14 -97
  445. package/.agents/scripts/lib/skills/parse-skill.js +13 -59
  446. package/.agents/scripts/lib/skills/skills-index.js +8 -29
  447. package/.agents/scripts/lib/skills/walk-skill-files.js +17 -78
  448. package/.agents/scripts/lib/source-extensions.js +11 -42
  449. package/.agents/scripts/lib/source-text/strip-js-comments.js +8 -41
  450. package/.agents/scripts/lib/stdio-flush.js +9 -36
  451. package/.agents/scripts/lib/story-adjacency.js +8 -40
  452. package/.agents/scripts/lib/story-body/body-format-lints.js +22 -83
  453. package/.agents/scripts/lib/story-body/footer-block.js +11 -44
  454. package/.agents/scripts/lib/story-body/story-body.js +83 -358
  455. package/.agents/scripts/lib/temp-retention.js +42 -143
  456. package/.agents/scripts/lib/templates/decomposer-prompts.js +11 -65
  457. package/.agents/scripts/lib/test-env.js +12 -65
  458. package/.agents/scripts/lib/test-run-credit.js +10 -65
  459. package/.agents/scripts/lib/test-runner-contract.js +19 -74
  460. package/.agents/scripts/lib/test-temp.js +38 -184
  461. package/.agents/scripts/lib/test-tiers.js +12 -96
  462. package/.agents/scripts/lib/ticket-body-sections.js +21 -96
  463. package/.agents/scripts/lib/transpile.js +15 -74
  464. package/.agents/scripts/lib/util/concurrent-map.js +6 -25
  465. package/.agents/scripts/lib/util/parse-id-list.js +8 -34
  466. package/.agents/scripts/lib/util/poll-loop.js +8 -28
  467. package/.agents/scripts/lib/util/with-timeout.js +2 -11
  468. package/.agents/scripts/lib/validation-evidence.js +21 -96
  469. package/.agents/scripts/lib/wave-runner/footprint.js +17 -70
  470. package/.agents/scripts/lib/wave-runner/live-probe.js +53 -221
  471. package/.agents/scripts/lib/wave-runner/ready-set.js +72 -301
  472. package/.agents/scripts/lib/workers/crap-worker.js +11 -64
  473. package/.agents/scripts/lib/workers/maintainability-report-worker.js +8 -45
  474. package/.agents/scripts/lib/workers/maintainability-worker.js +5 -21
  475. package/.agents/scripts/lib/workers/serve-worker-messages.js +2 -18
  476. package/.agents/scripts/lib/workflow-closure.js +22 -105
  477. package/.agents/scripts/lib/workspace-provisioner.js +16 -54
  478. package/.agents/scripts/lib/worktree/git-hooks.js +15 -60
  479. package/.agents/scripts/lib/worktree/lifecycle/force-drain.js +20 -60
  480. package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +10 -62
  481. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +22 -86
  482. package/.agents/scripts/lib/worktree/lifecycle/reap.js +24 -126
  483. package/.agents/scripts/lib/worktree/lifecycle-manager.js +2 -20
  484. package/.agents/scripts/lib/worktree/node-modules-strategy.js +46 -180
  485. package/.agents/scripts/lib/worktree-manager.js +15 -40
  486. package/.agents/scripts/lint-issue-body.js +12 -68
  487. package/.agents/scripts/mandrel-update-preflight.js +10 -70
  488. package/.agents/scripts/merge-baseline.js +30 -104
  489. package/.agents/scripts/nav-registry-diff.js +22 -108
  490. package/.agents/scripts/notify.js +12 -69
  491. package/.agents/scripts/plan-context.js +27 -111
  492. package/.agents/scripts/plan-critics.js +12 -66
  493. package/.agents/scripts/plan-persist.js +31 -148
  494. package/.agents/scripts/plan-run-epilogue.js +11 -37
  495. package/.agents/scripts/pr-watch-with-update.js +76 -267
  496. package/.agents/scripts/providers/github/auth.js +3 -8
  497. package/.agents/scripts/providers/github/blocked-by-add.js +14 -61
  498. package/.agents/scripts/providers/github/board-add.js +5 -21
  499. package/.agents/scripts/providers/github/branch-protection.js +11 -43
  500. package/.agents/scripts/providers/github/cache.js +2 -14
  501. package/.agents/scripts/providers/github/comments.js +7 -40
  502. package/.agents/scripts/providers/github/compose.js +3 -19
  503. package/.agents/scripts/providers/github/errors.js +22 -125
  504. package/.agents/scripts/providers/github/issues.js +31 -123
  505. package/.agents/scripts/providers/github/labels.js +24 -124
  506. package/.agents/scripts/providers/github/mappers.js +5 -27
  507. package/.agents/scripts/providers/github/merge-methods.js +3 -22
  508. package/.agents/scripts/providers/github/project-board.js +2 -17
  509. package/.agents/scripts/providers/github/projects-v2-graphql.js +3 -6
  510. package/.agents/scripts/providers/github/request-helpers.js +5 -32
  511. package/.agents/scripts/providers/github/search-budget.js +9 -39
  512. package/.agents/scripts/providers/github/search-query.js +5 -26
  513. package/.agents/scripts/providers/github/sub-issue-add.js +15 -65
  514. package/.agents/scripts/providers/github/sub-issues.js +7 -36
  515. package/.agents/scripts/providers/github/tickets.js +32 -134
  516. package/.agents/scripts/providers/github.js +18 -59
  517. package/.agents/scripts/prune-plan-run-labels.js +12 -46
  518. package/.agents/scripts/quality-preview.js +35 -220
  519. package/.agents/scripts/resolve-doc-tiers.js +3 -26
  520. package/.agents/scripts/resolve-stories.js +16 -67
  521. package/.agents/scripts/resync-status-column.js +6 -25
  522. package/.agents/scripts/run-tests.js +29 -104
  523. package/.agents/scripts/single-story-close.js +23 -135
  524. package/.agents/scripts/single-story-confirm-merge.js +32 -139
  525. package/.agents/scripts/single-story-init.js +47 -209
  526. package/.agents/scripts/stories-wave-tick.js +102 -472
  527. package/.agents/scripts/sync-agentrc.js +3 -21
  528. package/.agents/scripts/sync-claude-agents.js +9 -55
  529. package/.agents/scripts/sync-claude-commands.js +20 -110
  530. package/.agents/scripts/test-wrapper.js +6 -43
  531. package/.agents/scripts/update-coverage-baseline.js +5 -22
  532. package/.agents/scripts/update-crap-baseline.js +7 -30
  533. package/.agents/scripts/update-duplication-baseline.js +16 -92
  534. package/.agents/scripts/update-maintainability-baseline.js +8 -62
  535. package/.agents/scripts/update-ticket-state.js +1 -7
  536. package/.agents/scripts/validate-skills.js +6 -26
  537. package/.agents/templates/agent-protocol.md +2 -2
  538. package/.agents/templates/docs/audit-sweep-runbook.md +3 -4
  539. package/.agents/workflows/audit-accessibility.md +4 -7
  540. package/.agents/workflows/audit-adrs.md +3 -6
  541. package/.agents/workflows/audit-architecture.md +3 -11
  542. package/.agents/workflows/audit-baselines.md +6 -9
  543. package/.agents/workflows/audit-clean-code.md +8 -12
  544. package/.agents/workflows/audit-data-model.md +3 -7
  545. package/.agents/workflows/audit-dependencies.md +4 -7
  546. package/.agents/workflows/audit-devops.md +4 -8
  547. package/.agents/workflows/audit-documentation.md +1 -4
  548. package/.agents/workflows/audit-mobile.md +4 -7
  549. package/.agents/workflows/audit-navigability.md +3 -6
  550. package/.agents/workflows/audit-performance.md +2 -4
  551. package/.agents/workflows/audit-privacy.md +4 -7
  552. package/.agents/workflows/audit-quality.md +4 -7
  553. package/.agents/workflows/audit-security.md +4 -7
  554. package/.agents/workflows/audit-seo.md +4 -7
  555. package/.agents/workflows/audit-sre.md +4 -7
  556. package/.agents/workflows/audit-to-stories.md +17 -30
  557. package/.agents/workflows/audit-ux-ui.md +4 -7
  558. package/.agents/workflows/helpers/audit-lens-core.md +1 -1
  559. package/.agents/workflows/helpers/code-quality-guardrails.md +12 -15
  560. package/.agents/workflows/helpers/deliver-digest.md +6 -4
  561. package/.agents/workflows/helpers/deliver-reference.md +114 -188
  562. package/.agents/workflows/helpers/deliver-story-reference.md +189 -533
  563. package/.agents/workflows/helpers/plan-reference.md +86 -139
  564. package/.agents/workflows/helpers/qa-core.md +12 -0
  565. package/.agents/workflows/memory-consolidate.md +1 -1
  566. package/.agents/workflows/qa-assist.md +27 -71
  567. package/.agents/workflows/qa-explore.md +19 -59
  568. package/.agents/workflows/qa-run.md +11 -33
  569. package/README.md +1 -1
  570. package/bin/mandrel.js +5 -46
  571. package/bin/postinstall.js +18 -107
  572. package/docs/CHANGELOG.md +32 -0
  573. package/lib/cli/doctor.js +11 -71
  574. package/lib/cli/init.js +26 -165
  575. package/lib/cli/migrate.js +5 -64
  576. package/lib/cli/registry.js +84 -467
  577. package/lib/cli/sync-agents.js +4 -64
  578. package/lib/cli/sync-commands.js +11 -64
  579. package/lib/cli/sync.js +34 -213
  580. package/lib/cli/uninstall.js +40 -219
  581. package/lib/cli/update.js +105 -661
  582. package/lib/cli/version-check.js +8 -72
  583. package/lib/cli/version-helpers.js +14 -87
  584. package/lib/migrations/helpers/retire-agentrc-key.js +11 -52
  585. package/lib/migrations/index.js +15 -92
  586. package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +2 -15
  587. package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +1 -13
  588. package/lib/migrations/steps/2.11.0-retire-max-seed-words.js +2 -15
  589. package/lib/migrations/steps/2.2.0-retire-epic-ac-tags.js +9 -38
  590. package/lib/migrations/steps/2.20.0-retire-codebase-snapshot.js +1 -13
  591. package/lib/migrations/steps/2.32.0-retire-lint-baseline-command.js +2 -27
  592. package/lib/migrations/steps/2.57.0-retire-delivery-limit-knobs.js +2 -23
  593. package/lib/migrations/steps/2.57.0-retire-planning-limit-knobs.js +2 -27
  594. package/lib/migrations/steps/2.60.0-retire-audit-results-autofile.js +2 -21
  595. package/lib/migrations/steps/strip-removed-agentrc-keys.js +333 -0
  596. package/package.json +16 -14
  597. package/.agents/docs/SDLC.md +0 -590
  598. package/.agents/docs/quality-gates.md +0 -1183
  599. package/.agents/rules/known-tooling-behavior.md +0 -200
  600. package/.agents/rules/orchestration-error-handling.md +0 -61
  601. package/.agents/rules/test-seams.md +0 -59
  602. package/.agents/schemas/baselines/lighthouse.schema.json +0 -59
  603. package/.agents/schemas/baselines/lint.schema.json +0 -47
  604. package/.agents/scripts/check-action-pinning.js +0 -260
  605. package/.agents/scripts/check-audit-attribution.js +0 -302
  606. package/.agents/scripts/check-baseline-drift.js +0 -211
  607. package/.agents/scripts/check-baseline-scope.js +0 -362
  608. package/.agents/scripts/check-generated-validator.js +0 -202
  609. package/.agents/scripts/check-knip-entries.js +0 -159
  610. package/.agents/scripts/check-lifecycle-lint.js +0 -294
  611. package/.agents/scripts/check-pinned-override-notes.js +0 -102
  612. package/.agents/scripts/check-schema-references.js +0 -368
  613. package/.agents/scripts/check-test-portability.js +0 -512
  614. package/.agents/scripts/check-workflow-citations.js +0 -218
  615. package/.agents/scripts/check-workflow-cli-lint.js +0 -299
  616. package/.agents/scripts/check-workflow-timeouts.js +0 -291
  617. package/.agents/scripts/install-matrix-assert.js +0 -326
  618. package/.agents/scripts/lib/audit-advisories.js +0 -195
  619. package/.agents/scripts/lib/audit-attribution.js +0 -134
  620. package/.agents/scripts/lib/baselines/drift-detector.js +0 -351
  621. package/.agents/scripts/lib/baselines/kinds/lighthouse.js +0 -87
  622. package/.agents/scripts/lib/baselines/kinds/lint.js +0 -184
  623. package/.agents/scripts/lib/baselines/orphan-pruner.js +0 -233
  624. package/.agents/scripts/lib/baselines/scope-assert.js +0 -223
  625. package/.agents/scripts/lib/baselines/scope-inventory.js +0 -314
  626. package/.agents/scripts/lib/c8-cli-path.js +0 -21
  627. package/.agents/scripts/lib/config/gates/lighthouse.schema.js +0 -51
  628. package/.agents/scripts/lib/config/gates/lint.schema.js +0 -18
  629. package/.agents/scripts/lib/dynamic-workflow/architecture-report-contract.js +0 -70
  630. package/.agents/scripts/lib/dynamic-workflow/audit-orchestrator.js +0 -284
  631. package/.agents/scripts/lib/dynamic-workflow/clean-code-report-contract.js +0 -80
  632. package/.agents/scripts/lib/dynamic-workflow/degraded-coverage.js +0 -81
  633. package/.agents/scripts/lib/dynamic-workflow/documentation-report-contract.js +0 -87
  634. package/.agents/scripts/lib/dynamic-workflow/performance-report-contract.js +0 -74
  635. package/.agents/scripts/lib/dynamic-workflow/quality-report-contract.js +0 -90
  636. package/.agents/scripts/lib/dynamic-workflow/report-contract-core.js +0 -43
  637. package/.agents/scripts/lib/dynamic-workflow/security-report-contract.js +0 -83
  638. package/.agents/scripts/lib/fs-walk.js +0 -52
  639. package/.agents/scripts/lib/knip-config-resolver.js +0 -181
  640. package/.agents/scripts/lib/knip-entry-sync.js +0 -452
  641. package/.agents/scripts/lib/pinned-override-notes.js +0 -88
  642. package/.agents/scripts/lib/pinned-override-resolve.js +0 -212
  643. package/.agents/scripts/lib/test-isolate/cli-options.js +0 -93
  644. package/.agents/scripts/lib/test-isolate/env-snapshot-loader.js +0 -52
  645. package/.agents/scripts/lib/test-isolate/list-files.js +0 -90
  646. package/.agents/scripts/lib/test-isolate/parse-tap.js +0 -75
  647. package/.agents/scripts/lib/test-isolate/progress-log.js +0 -45
  648. package/.agents/scripts/lib/test-isolate/render-report.js +0 -97
  649. package/.agents/scripts/lib/test-isolate/run-isolate.js +0 -87
  650. package/.agents/scripts/lib/test-isolate/runner.js +0 -483
  651. package/.agents/scripts/lib/test-profile/parse-tap.js +0 -136
  652. package/.agents/scripts/lib/test-profile/render-report.js +0 -45
  653. package/.agents/scripts/lint-label-vocabulary.js +0 -214
  654. package/.agents/scripts/post-structured-comment.js +0 -127
  655. package/.agents/scripts/provision-git-hooks.js +0 -85
  656. package/.agents/scripts/prune-baseline-orphans.js +0 -181
  657. package/.agents/scripts/run-coverage.js +0 -197
  658. package/.agents/scripts/run-lint.js +0 -133
  659. package/.agents/scripts/run-test-profile.js +0 -129
  660. package/.agents/scripts/run-verify.js +0 -125
  661. package/.agents/scripts/test-isolate.js +0 -55
  662. package/.agents/scripts/update-dead-exports-baseline.js +0 -321
@@ -31,6 +31,7 @@ import { runCloseValidationPhase } from './phases/close-validation.js';
31
31
  import { parsePrNumber, runStoryScopeReview } from './phases/code-review.js';
32
32
  import { runConfirmMergePhase } from './phases/confirm-merge.js';
33
33
  import { runGraphqlPreflight } from './phases/graphql-preflight.js';
34
+ import { lockWaitPending } from './phases/lock-wait-pending.js';
34
35
  import { parseCloseOptions, resolveWaitForMerge } from './phases/options.js';
35
36
  import { ensurePullRequestWith } from './phases/pull-request.js';
36
37
  import { pushStoryBranch } from './phases/push.js';
@@ -42,29 +43,11 @@ import { runWrongTreeGuardPhase } from './phases/wrong-tree-guard.js';
42
43
  const progress = Logger.createProgress('single-story-close', { stderr: true });
43
44
 
44
45
  /**
45
- * Emit the terminal envelope on stdout alongside the legacy close result.
46
- *
47
- * Both are printed: the envelope is the contract callers parse (Story
48
- * #4543), while `STORY CLOSE RESULT` stays byte-compatible for the existing
49
- * surfaces that grep it. One writer, one place — so the envelope can never
50
- * be emitted from a path that forgot it.
51
- *
52
- * Story #4578 — the same one-place property is why the runtime-derived
53
- * friction emit hangs here: a close that ends `failed`, or parks `pending`
54
- * on an exhausted merge-wait budget, is friction the retro must see, and
55
- * routing it through the single emitter means no terminal path can forget
56
- * it. `emitTerminalFriction` decides what (if anything) is worth a record —
57
- * see `frictionForTerminal` for why `blocked` and a `--no-wait-merge`
58
- * `pending` are deliberately NOT flagged here.
59
- *
60
- * Async, and awaited by every caller: the CLI exits via `process.exit` the
61
- * moment `main` resolves, so a fire-and-forget append would be discarded.
62
- * The emit is best-effort internally and cannot throw.
46
+ * The single terminal writer: the result summary, the envelope callers parse,
47
+ * and terminal friction — so no ending can forget one. Must be awaited: the
48
+ * CLI `process.exit`s as soon as `main` resolves.
63
49
  */
64
50
  async function emitTerminal({ terminal, result, config }) {
65
- // Story #4685 — the human-facing result dump goes to a temp log; the agent
66
- // acts on the (separate, unsuppressible) terminal envelope emitted below.
67
- // The single summary line keeps the fields worth an at-a-glance read.
68
51
  if (result) {
69
52
  emitTerseResult({
70
53
  label: 'STORY CLOSE RESULT',
@@ -84,23 +67,9 @@ async function emitTerminal({ terminal, result, config }) {
84
67
  }
85
68
 
86
69
  /**
87
- * Terminal for a Story that was already closed before this run started.
88
- *
89
- * `state: 'closed'` alone does NOT mean the work landed. GitHub closes an
90
- * issue as `completed` (the `Closes #<id>` footer firing on merge — the work
91
- * IS on the base branch) or as `not_planned` (superseded by a re-plan,
92
- * abandoned — nothing ever merged). Reporting the second as `landed` told
93
- * `/mandrel-deliver` that work had reached `main` when no PR ever merged, which would
94
- * also satisfy any dependent Story waiting on it. Fail loudly instead: being
95
- * handed an abandoned Story is an input error only the operator can resolve.
96
- *
97
- * A null `stateReason` keeps the `completed` reading — GitHub defaults to it,
98
- * and issues closed before the field existed carry null.
99
- *
100
- * The operator-facing `NOOP` line is emitted here rather than at the call
101
- * site: both halves read the same field, and deciding what `not_planned`
102
- * means in two places is how the log and the envelope come to disagree about
103
- * one Story.
70
+ * Terminal for an already-closed Story. `not_planned` means nothing merged,
71
+ * so it fails rather than reporting `landed` (which would also unblock
72
+ * dependents); `completed` or null (GitHub's default) reads as landed.
104
73
  */
105
74
  async function alreadyClosedResult(storyId, stateReason = null, config) {
106
75
  if (stateReason === 'not_planned') {
@@ -137,9 +106,6 @@ async function alreadyClosedResult(storyId, stateReason = null, config) {
137
106
  action: 'noop',
138
107
  reason: 'already-closed',
139
108
  };
140
- // Idempotent re-run against a Story closed as completed. `landed` is the
141
- // honest status — the issue closed on merge, so the work is on the base
142
- // branch — and there is nothing left to command.
143
109
  const terminal = buildTerminalEnvelope({
144
110
  storyId,
145
111
  status: 'landed',
@@ -152,27 +118,14 @@ async function alreadyClosedResult(storyId, stateReason = null, config) {
152
118
  }
153
119
 
154
120
  /**
155
- * The block class a refused GraphQL preflight reports (Story #5355).
156
- *
157
- * `api-race-other` is the shared classifier's documented fallback for "a
158
- * transient GraphQL/API error, an ambiguous probe result, or a genuinely
159
- * novel condition", and a preflight refusal is the third of those. It is
160
- * reused rather than joined by a new class on purpose: the class vocabulary
161
- * is pinned by `story-deliver-terminal.schema.json`, and this refusal is
162
- * required to validate against the shipped schema unchanged. The `reason`
163
- * string — not the class — is what names the blocker and its remedy.
121
+ * Reuses the classifier's fallback class: the vocabulary is pinned by the
122
+ * terminal schema, so `reason` names the blocker instead.
164
123
  */
165
124
  const PREFLIGHT_BLOCK_CLASS = 'api-race-other';
166
125
 
167
126
  /**
168
- * Terminal for a close the GraphQL preflight refused during `init`.
169
- *
170
- * Returned rather than thrown: a throw would surface as `failed` at the CLI
171
- * boundary, and this is not a crash — it is a classified block detected
172
- * before the pipeline spent anything, with the Story already flipped to
173
- * `agent::blocked` and a friction comment carrying the remedy. The next
174
- * command is the same close, which is exactly right: from a session that can
175
- * reach GraphQL it runs to completion from where the Story stands now.
127
+ * Returned, not thrown: a classified block, not a crash (a throw surfaces as
128
+ * `failed`). The next command is the same close.
176
129
  *
177
130
  * @param {{ storyId: number, preflight: { verdict: string, reason: string },
178
131
  * config: object, startedAtMs: number }} args
@@ -207,16 +160,7 @@ async function preflightBlockedResult({
207
160
  }
208
161
 
209
162
  /**
210
- * Project the baselines entries out of close-validation's per-gate outcomes,
211
- * keyed by the gate's own name (Story #5172).
212
- *
213
- * The envelope's `gates` map used to roll the whole gate chain up into a
214
- * single `validation` verdict, which was fine while the baselines gate was
215
- * one entry and stopped being fine when it became two: a reader of a failed
216
- * close could not tell whether the cheap coverage-independent baselines had
217
- * breached or the expensive coverage-consuming ones had. Only registered
218
- * entries are reported — a consumer whose config registers just one of the
219
- * pair gets just that one, never a phantom key for a gate that never existed.
163
+ * The split baselines gates, by name; only registered ones, never a phantom key.
220
164
  *
221
165
  * @param {Record<string, string>|null|undefined} validationGates
222
166
  * @returns {Record<string, string>}
@@ -230,6 +174,22 @@ function baselinesEnvelopeGates(validationGates) {
230
174
  return out;
231
175
  }
232
176
 
177
+ /**
178
+ * @param {{ skipValidation?: boolean, skipSync?: boolean }} options
179
+ * @param {Record<string, string>|null} validationGates
180
+ * @param {object|null} reviewOverride
181
+ * @returns {Record<string, string>}
182
+ */
183
+ function closeEnvelopeGates(options, validationGates, reviewOverride) {
184
+ return {
185
+ validation: options.skipValidation ? 'skipped' : 'passed',
186
+ ...baselinesEnvelopeGates(validationGates),
187
+ baseSync: options.skipSync ? 'skipped' : 'passed',
188
+ // The review did fail; the envelope records the human override.
189
+ codeReview: reviewOverride ? 'overridden' : 'passed',
190
+ };
191
+ }
192
+
233
193
  function resolveWorktreePath({ cwd, config, storyId }) {
234
194
  const root = config.delivery?.worktreeIsolation?.root ?? '.worktrees';
235
195
  const candidate = path.resolve(cwd, root, `story-${storyId}`);
@@ -237,25 +197,16 @@ function resolveWorktreePath({ cwd, config, storyId }) {
237
197
  }
238
198
 
239
199
  /**
240
- * The pre-push phases, in the order the pipeline walks them: wrong-tree
241
- * guard → base-sync → close-validation.
242
- *
243
- * Story #5172 put base-sync AHEAD of close-validation, for two reasons that
244
- * are really one. The cheap one: a base-sync conflict is a hard block that
245
- * costs nothing to detect, so paying for the full gate chain before
246
- * discovering it burns the pipeline's most expensive minutes on a tree that
247
- * was never going to be pushed. The load-bearing one: with the gates last,
248
- * **the validated tree is the pushed tree**. Under the old order the merge
249
- * commit base-sync writes landed AFTER validation, so every close pushed a
250
- * tree no gate had ever seen.
251
- *
252
- * `--skip-sync` and `--skip-validation` stay independent — either, both or
253
- * neither may be set, and each still elides exactly its own phase.
200
+ * wrong-tree guard → base-sync → close-validation. Validation runs last so
201
+ * the validated tree is the pushed tree (base-sync's merge commit included),
202
+ * and a cheap conflict is found before the expensive gates.
254
203
  *
255
- * @returns {Promise<{ validationGates: Record<string, string>|null }>}
256
- * The per-gate outcomes close-validation observed, or `null` when the phase
257
- * was skipped. Feeds the terminal envelope's `gates` map so the split
258
- * baselines entries are separable there.
204
+ * @returns {Promise<{
205
+ * validationGates: Record<string, string>|null,
206
+ * lockWait: { waitedSeconds: number, expired: boolean }|null,
207
+ * pending: boolean,
208
+ * }>} `validationGates` is null when skipped; `pending` means a full-suite
209
+ * lock wait expired and the gates deferred.
259
210
  */
260
211
  async function runPrePushPhases({
261
212
  cwd,
@@ -301,7 +252,7 @@ async function runPrePushPhases({
301
252
  }
302
253
  if (skipValidation) {
303
254
  progress('VALIDATE', '⏭ Skipped (--skip-validation).');
304
- return { validationGates: null };
255
+ return { validationGates: null, lockWait: null, pending: false };
305
256
  }
306
257
  setPhase('close-validation');
307
258
  let validation;
@@ -318,12 +269,7 @@ async function runPrePushPhases({
318
269
  buildDefaultGates,
319
270
  });
320
271
  } catch (err) {
321
- // Story #5279 — the failed terminal REPORTS gates rather than
322
- // reconstructing them, so hand it what this run observed. The phase tags
323
- // `closeGate` with the entry that died; that one name is the whole of
324
- // what the run observed about gate outcomes, and therefore the whole of
325
- // what the envelope may claim. Anything else it might have named is a
326
- // gate the run never proved ran at all.
272
+ // The gate that died is all this run observed; the envelope claims no more.
327
273
  if (typeof err?.closeGate === 'string') {
328
274
  setObservedGates({ [err.closeGate]: 'failed' });
329
275
  }
@@ -331,7 +277,11 @@ async function runPrePushPhases({
331
277
  }
332
278
  const gates = validation?.gates ?? null;
333
279
  setObservedGates(gates);
334
- return { validationGates: gates };
280
+ return {
281
+ validationGates: gates,
282
+ lockWait: validation?.lockWait ?? null,
283
+ pending: validation?.pending === true,
284
+ };
335
285
  }
336
286
 
337
287
  async function openAndReviewPr({
@@ -349,17 +299,14 @@ async function openAndReviewPr({
349
299
  setPhase = () => {},
350
300
  }) {
351
301
  setPhase('push');
352
- // Issue #4990 — push from the Story worktree so `pre-push` measures the
353
- // tree being sent. `gh` and the review's ref-based diffs below keep the
354
- // caller's `cwd`: they read the shared `.git`, so they resolve identically
355
- // from either tree.
302
+ // Push from the worktree so `pre-push` measures the tree being sent; the
303
+ // ref-based reads below resolve identically from the shared `.git`.
356
304
  pushStoryBranch({ cwd, worktreePath, storyBranch, gitSync, progress });
357
305
  setPhase('pull-request');
358
306
  const { url: prUrl, alreadyMerged } = await ensurePullRequestWith({
359
307
  cwd,
360
308
  storyId,
361
309
  storyTitle: story.title,
362
- // Scanned for a declared `BREAKING CHANGE:` footer — see pull-request.js.
363
310
  storyBody: story.body,
364
311
  storyBranch,
365
312
  baseBranch,
@@ -367,10 +314,7 @@ async function openAndReviewPr({
367
314
  progress,
368
315
  });
369
316
  const prNumber = parsePrNumber(prUrl);
370
- // Story #4873 — the head's PR already merged (an armed PR that landed while
371
- // a previous close invocation was between phases). There is nothing left to
372
- // review and nothing left to arm; the confirm phase probes the PR, observes
373
- // MERGED, and lands the Story on the merge that actually happened.
317
+ // Already merged (landed between invocations): skip review and arm; confirm observes it.
374
318
  if (alreadyMerged) {
375
319
  return { prUrl, prNumber, alreadyMerged: true };
376
320
  }
@@ -384,19 +328,12 @@ async function openAndReviewPr({
384
328
  prNumber,
385
329
  provider,
386
330
  runCodeReviewFn: injectedRunCodeReview ?? runCodeReviewDefault,
387
- // The runner owns the git seam it hands its phases (same as `gitSync` to
388
- // `pushStoryBranch`). The review needs it to resolve `origin/<base>` —
389
- // the ref base-sync merged from — before it will score anything
390
- // (Story #5325).
391
331
  gitSpawnFn: gitSpawn,
392
332
  progress,
393
333
  });
394
334
  if (reviewOutcome.halted) {
395
335
  const criticalCount = reviewOutcome.severity?.critical ?? 0;
396
- // The sanctioned override. Checked BEFORE the blocked
397
- // transition so an overridden run never touches `agent::blocked`: the
398
- // Story is proceeding, and parking it would make the label lie for the
399
- // rest of the close.
336
+ // Checked before the blocked transition: an overridden Story proceeds.
400
337
  if (overrideReviewBlock) {
401
338
  const override = await handleOverriddenReviewBlock({
402
339
  provider,
@@ -456,30 +393,12 @@ async function releaseLease({
456
393
  }
457
394
 
458
395
  /**
459
- * Story #4257 — run a blocked-prone phase and, if it throws, release the
460
- * assignee-lease best-effort BEFORE re-throwing the original error.
461
- *
462
- * The two recoverable-blocked close exits (base-sync conflict in
463
- * `runBaseSyncPhase`, and a critical-blocker review halt in
464
- * `openAndReviewPr`) throw before the clean-close lease release at the
465
- * tail of `runSingleStoryClose`, stranding the operator's lease
466
- * indefinitely. The standalone lease has **no** TTL to expire by (Story
467
- * #5006 deleted it): `acquireLease` refuses any foreign assignee outright,
468
- * so a stranded claim is cleared only by `--steal` or de-assignment. That fail-closed-refuses a different operator who picks up
469
- * the blocked Story — exactly the hand-off case. Releasing here closes
470
- * that gap.
471
- *
472
- * The original throw is preserved verbatim (per
473
- * `rules/orchestration-error-handling.md` — throw, never `Logger.fatal`),
474
- * so the CLI boundary still maps it to a non-zero exit; the lease release
475
- * must not swallow it. `releaseLease` is itself best-effort and never
476
- * throws, so it cannot mask the real failure. Fail-closed re-acquire
477
- * semantics are preserved: `releaseStoryLease` no-ops when the operator no
478
- * longer holds the claim, and a self-held re-acquire on a re-run still
479
- * succeeds against the now-unclaimed ticket.
396
+ * Release the lease best-effort before re-throwing a blocked-prone phase's
397
+ * error verbatim. The lease has no TTL, so a stranded claim would refuse the
398
+ * next operator who picks up the blocked Story.
480
399
  *
481
400
  * @template T
482
- * @param {() => Promise<T>} run The blocked-prone phase to execute.
401
+ * @param {() => Promise<T>} run
483
402
  * @param {{ provider: object, storyId: number, config: object, injectedReleaseLease?: Function }} leaseArgs
484
403
  * @returns {Promise<T>}
485
404
  */
@@ -493,25 +412,8 @@ async function releaseLeaseOnBlock(run, leaseArgs) {
493
412
  }
494
413
 
495
414
  /**
496
- * Did this run OBSERVE the PR merge? (Story #5279)
497
- *
498
- * `merged` used to be whatever the caller happened to pass, and the two
499
- * finishers passed different halves of the truth. Three observations say a
500
- * merge happened, and each of them reported `merged: false` on at least one
501
- * path:
502
- *
503
- * - the confirm phase watched it land (`waitOutcome.confirmed`);
504
- * - it landed and only the `agent::done` label write failed
505
- * (`merged-flip-failed`) — the terminal envelope for that same run
506
- * already reports `pr.state: MERGED` from the probe, so a result denying
507
- * the merge made the two halves of one run contradict each other;
508
- * - the arm phase direct-squash-merged it synchronously because the
509
- * repository has no native auto-merge (`directMerged`), which the
510
- * no-wait finisher never consulted at all.
511
- *
512
- * Deliberately observation-only: it reads what the run saw, never what the
513
- * run intended. A `null`/absent `waitOutcome` is the no-wait finisher, whose
514
- * sole observation is the direct merge.
415
+ * Did this run OBSERVE the merge — confirmed, merged-but-flip-failed, or
416
+ * direct-merged? Observation only, never intent.
515
417
  *
516
418
  * @param {{ waitOutcome?: object|null, directMerged?: boolean }} args
517
419
  * @returns {boolean}
@@ -552,25 +454,13 @@ function closeResult({
552
454
  autoMergeReason,
553
455
  worktreeReaped,
554
456
  leaseReleased,
555
- // Story #4681 — `gh`'s local head-branch delete failed while the remote
556
- // merge/arm stood. Surfaced so the land is auditable as
557
- // merged-with-deferred-cleanup rather than silently degraded.
457
+ // `gh`'s local branch delete failed while the remote merge/arm stood.
558
458
  localCleanupDeferred,
559
- // Story #4682 — native auto-merge was unavailable (no branch protection /
560
- // an already-clean PR), so the PR was landed by a direct squash-merge.
561
- // Surfaced so a checks-less land is auditable rather than looking like a
562
- // queued auto-merge that never fired.
459
+ // No native auto-merge, so the arm squash-merged directly.
563
460
  directMerged,
564
461
  waitedForMerge,
565
462
  merged,
566
- // Story #5266 — derived from `merged` / `directMerged` / `autoMergeEnabled`,
567
- // never from `waitedForMerge`. A wait that expired unmerged used to write
568
- // "PR merge confirmed" beside `merged: false`, and this log is what the
569
- // operator reads first. See close-note.js for the invariant.
570
- // Story #5279 — `landCompleted` keeps that invariant intact now that
571
- // `merged: true` no longer implies the flip and the tail ran: a direct
572
- // merge under `--no-wait-merge`, and a `merged-flip-failed` block, are
573
- // both merged WITHOUT a completed land.
463
+ // Never from `waitedForMerge`; `merged` can be true without a completed land.
574
464
  note: deriveCloseNote({
575
465
  merged,
576
466
  directMerged,
@@ -621,18 +511,10 @@ export async function runSingleStoryClose({
621
511
  );
622
512
  }
623
513
 
624
- // Story #4543 — track the phase so a crash is attributable. The runner
625
- // deliberately keeps THROWING (the library contract every caller and test
626
- // relies on: a failed gate must not look like a return value); it only tags
627
- // the error with the phase it died in, and the CLI boundary turns that into
628
- // the `failed` terminal envelope. Tagging rather than swallowing is what
629
- // lets `failed` name its phase without inventing a second success path.
514
+ // The runner keeps THROWING; it only tags the error with its phase and the
515
+ // gates it observed (null until validation reports), and the CLI boundary
516
+ // builds the `failed` envelope from those tags.
630
517
  let phase = 'init';
631
- // Story #5279 — the per-gate outcomes this run OBSERVED, tagged onto a
632
- // throwing error alongside the phase so `failedTerminalFor` reports gates
633
- // instead of reconstructing which ones "must have" run. Stays null until
634
- // close-validation reports, so a run that died before it claims no gates at
635
- // all rather than inventing names for gates that were never registered.
636
518
  let observedGates = null;
637
519
  const setPhase = (next) => {
638
520
  phase = next;
@@ -665,10 +547,7 @@ export async function runSingleStoryClose({
665
547
  }
666
548
 
667
549
  /**
668
- * Resolve the arm outcome. An already-merged head PR (Story #4873) has nothing
669
- * to arm — `gh pr merge` against it fails, which would report the arm as a
670
- * fault and block a Story whose work is already on the base branch. Skip the
671
- * arm and let the confirm phase observe the merge that happened.
550
+ * An already-merged PR skips the arm (`gh pr merge` would fail and block it).
672
551
  *
673
552
  * @param {object} args
674
553
  * @returns {Promise<{ autoMergeEnabled: boolean, autoMergeReason: string|null,
@@ -688,10 +567,6 @@ async function resolveAutoMergeOutcome({ alreadyMerged, ...phaseArgs }) {
688
567
  }
689
568
 
690
569
  /**
691
- * Report the merge-wait terminal on the progress channel. Three endings, each
692
- * with its own operator-facing shape — `landed` is done, `pending` is
693
- * resumable and NOT a failure, anything else is a block naming its class.
694
- *
695
570
  * @param {{ status: string, nextCommand: string, blocked?: {blockClass?: string} }} terminal
696
571
  * @param {{ storyId: number, prUrl: string|null }} ctx
697
572
  * @returns {void}
@@ -702,9 +577,7 @@ function reportWaitTerminal(terminal, { storyId, prUrl }) {
702
577
  return;
703
578
  }
704
579
  if (terminal.status === 'pending') {
705
- // NOT a failure and NOT a block — the wait reached the edge of its
706
- // host slot with the PR healthy and in flight. The CLI maps this to
707
- // its own exit code so a caller can resume without classifying.
580
+ // Not a failure: resumable, with its own CLI exit code.
708
581
  progress(
709
582
  'PENDING',
710
583
  `⏸ Story #${storyId}: PR ${prUrl} still in flight — resume with: ${terminal.nextCommand}`,
@@ -720,11 +593,8 @@ function reportWaitTerminal(terminal, { storyId, prUrl }) {
720
593
  }
721
594
 
722
595
  /**
723
- * The close-and-land ending (Story #4428): poll the just-armed PR to merge
724
- * confirmation and emit the terminal the outcome names.
725
- *
726
- * @param {object} prCtx The shared PR/gate context built by the pipeline.
727
- * @param {object} deps Runtime seams the confirm phase needs.
596
+ * @param {object} prCtx
597
+ * @param {object} deps
728
598
  * @returns {Promise<{ success: boolean, result: object, terminal: object }>}
729
599
  */
730
600
  async function finishWithMergeWait(prCtx, deps) {
@@ -757,6 +627,7 @@ async function finishWithMergeWait(prCtx, deps) {
757
627
  prUrl: prCtx.prUrl,
758
628
  autoMergeEnabled: prCtx.autoMergeEnabled,
759
629
  gates: prCtx.gates,
630
+ lockWait: prCtx.lockWait,
760
631
  elapsedSeconds: elapsedSecondsSince(prCtx.startedAtMs),
761
632
  });
762
633
  const result = closeResult({
@@ -768,22 +639,15 @@ async function finishWithMergeWait(prCtx, deps) {
768
639
  autoMergeEnabled: prCtx.autoMergeEnabled,
769
640
  autoMergeReason: prCtx.autoMergeReason,
770
641
  worktreeReaped: prCtx.worktreeReaped,
771
- // Story #4860 — the release is a post-land tail step now, so the tail's
772
- // own per-step boolean IS the answer. A wait that ended anything other
773
- // than landed never ran the tail, and correctly reports `false`: the
774
- // claim is still held, by design.
642
+ // Released by the post-land tail only; any other ending keeps the claim.
775
643
  leaseReleased: waitOutcome.tail?.leaseRelease === true,
776
644
  localCleanupDeferred: prCtx.localCleanupDeferred,
777
645
  directMerged: prCtx.directMerged,
778
646
  waitedForMerge: true,
779
- // Story #5279 — `confirmed` alone denied the merge behind a
780
- // `merged-flip-failed` block, whose own envelope (above) reports
781
- // `pr.state: MERGED` off the probe.
782
647
  merged: deriveObservedMerge({
783
648
  waitOutcome,
784
649
  directMerged: prCtx.directMerged,
785
650
  }),
786
- // Only the confirmed ending runs the flip, the issue close and the tail.
787
651
  landCompleted: waitOutcome.confirmed === true,
788
652
  });
789
653
  await emitTerminal({ terminal, result, config: prCtx.config });
@@ -792,20 +656,14 @@ async function finishWithMergeWait(prCtx, deps) {
792
656
  }
793
657
 
794
658
  /**
795
- * The no-wait ending — `--no-wait-merge` / operator-merge. The PR is open and
796
- * a human owns the land. That is a `pending` terminal by definition: the work
797
- * is not done, nothing is broken, and one named command finishes it — rather
798
- * than a fourth status invented for this one case.
659
+ * The no-wait ending: a human owns the land, so it is `pending` with one
660
+ * command to finish it. A direct merge by the arm is still observed.
799
661
  *
800
662
  * @param {object} prCtx
801
663
  * @param {string} waitForMergeReason
802
664
  * @returns {Promise<{ success: boolean, result: object, terminal: object }>}
803
665
  */
804
666
  async function finishWithoutMergeWait(prCtx, waitForMergeReason) {
805
- // Story #5279 — a repository with no native auto-merge is direct
806
- // squash-merged synchronously by the arm phase, so this ending can and does
807
- // hold an OBSERVED merge. It used to report `merged: false` and hard-code
808
- // `pr.state: 'OPEN'` for a PR the same run had just merged.
809
667
  const merged = deriveObservedMerge({ directMerged: prCtx.directMerged });
810
668
  const result = closeResult({
811
669
  storyId: prCtx.storyId,
@@ -816,15 +674,11 @@ async function finishWithoutMergeWait(prCtx, waitForMergeReason) {
816
674
  autoMergeEnabled: prCtx.autoMergeEnabled,
817
675
  autoMergeReason: prCtx.autoMergeReason,
818
676
  worktreeReaped: prCtx.worktreeReaped,
819
- // Story #4860 — this is the no-wait ending: the PR is open and a human
820
- // owns the merge, so the Story stays assigned until the confirm-merge
821
- // surface lands it and runs the tail.
822
677
  leaseReleased: false,
823
678
  localCleanupDeferred: prCtx.localCleanupDeferred,
824
679
  directMerged: prCtx.directMerged,
825
680
  merged,
826
- // Whatever the merge state, this ending never flips `agent::done`, never
827
- // closes the issue and never runs the tail — `nextCommand` does.
681
+ // The flip, issue close and tail belong to `nextCommand`.
828
682
  landCompleted: false,
829
683
  });
830
684
  const terminal = buildTerminalEnvelope({
@@ -840,6 +694,7 @@ async function finishWithoutMergeWait(prCtx, waitForMergeReason) {
840
694
  autoMergeEnabled: Boolean(prCtx.autoMergeEnabled),
841
695
  },
842
696
  gates: prCtx.gates,
697
+ lockWait: prCtx.lockWait,
843
698
  nextCommand: NEXT_COMMANDS.confirmMerge(prCtx.storyId),
844
699
  elapsedSeconds: elapsedSecondsSince(prCtx.startedAtMs),
845
700
  });
@@ -852,9 +707,25 @@ async function finishWithoutMergeWait(prCtx, waitForMergeReason) {
852
707
  }
853
708
 
854
709
  /**
855
- * Wall-clock seconds since the close started, rounded — the terminal
856
- * envelope's `elapsedSeconds`.
710
+ * A full-suite lock wait expired: `pending`, nothing pushed.
857
711
  *
712
+ * @param {{ waitedSeconds: number, expired: boolean }|null} lockWait
713
+ * @param {{ storyId: number, storyBranch: string, baseBranch: string,
714
+ * config: object, startedAtMs: number }} ctx
715
+ * @returns {Promise<{ success: false, result: object, terminal: object }>}
716
+ */
717
+ async function finishDeferred(lockWait, { config, startedAtMs, ...ids }) {
718
+ const { result, terminal, note } = lockWaitPending({
719
+ ...ids,
720
+ lockWait,
721
+ elapsedSeconds: elapsedSecondsSince(startedAtMs),
722
+ });
723
+ await emitTerminal({ terminal, result, config });
724
+ progress('PENDING', note);
725
+ return { success: false, result, terminal };
726
+ }
727
+
728
+ /**
858
729
  * @param {number} startedAtMs
859
730
  * @returns {number}
860
731
  */
@@ -863,10 +734,6 @@ function elapsedSecondsSince(startedAtMs) {
863
734
  }
864
735
 
865
736
  /**
866
- * Announce the operator-merge skip: the PR was deliberately left un-armed, so
867
- * nothing here can land it and the Story rests at `agent::closing`. No-op on
868
- * every other wait reason.
869
- *
870
737
  * @param {{ waitForMergeReason: string, autoMergeReason: string|null,
871
738
  * storyId: number, waitForMergeExplicit?: boolean }} args
872
739
  * @returns {void}
@@ -888,11 +755,6 @@ function reportOperatorMergeSkip({
888
755
  );
889
756
  }
890
757
 
891
- /**
892
- * The close pipeline proper. Split out of `runSingleStoryClose` so the
893
- * phase-tagging wrapper above stays a thin, obviously-correct boundary rather
894
- * than a try block wrapped around a hundred lines of pipeline.
895
- */
896
758
  async function runClosePipeline({
897
759
  options,
898
760
  setPhase,
@@ -922,10 +784,6 @@ async function runClosePipeline({
922
784
  );
923
785
  }
924
786
 
925
- // Story #4257 — the base-sync conflict and review-critical exits throw
926
- // before the clean-close lease release at the tail of this function.
927
- // Built here, ahead of the first blocked-prone step, so the preflight
928
- // refusal below releases the lease on the same terms those exits do.
929
787
  const leaseArgs = {
930
788
  provider,
931
789
  storyId: options.storyId,
@@ -933,11 +791,7 @@ async function runClosePipeline({
933
791
  injectedReleaseLease,
934
792
  };
935
793
 
936
- // Story #5355 — one cheap GraphQL read, before anything is resolved,
937
- // validated, committed or pushed. `gh` routes the whole `gh pr` surface
938
- // through GraphQL, so a session that cannot reach it cannot land this
939
- // Story however green its gates are; discovering that here costs one API
940
- // call instead of the entire close-validation chain plus a push.
794
+ // `gh pr` needs GraphQL; one cheap read here beats the gate chain plus a push.
941
795
  const preflight = await runGraphqlPreflight({
942
796
  storyId: options.storyId,
943
797
  provider,
@@ -955,13 +809,8 @@ async function runClosePipeline({
955
809
  });
956
810
  }
957
811
 
958
- // Story #4891 — the base branch this run was SEEDED from, read back off the
959
- // run's init receipt on disk rather than re-resolved from a config file that
960
- // may have changed during the whole implementation window. Throws (fail
961
- // closed, naming both values) when the pin and current config disagree —
962
- // deliberately here, before the gate chain, format-autofix and base-sync,
963
- // so a wrong base is never merged into the Story branch. `baseConfirmed`
964
- // gates the base-merge remediation advice further down.
812
+ // The base the run was SEEDED from (init receipt); throws before any merge
813
+ // when it disagrees with current config.
965
814
  const { values: runScoped, confirmed: baseConfirmed } =
966
815
  await resolveRunScopedConfig({
967
816
  storyId: options.storyId,
@@ -975,9 +824,7 @@ async function runClosePipeline({
975
824
  config,
976
825
  storyId: options.storyId,
977
826
  });
978
- // Both blocked-prone phases are wrapped so the lease is released
979
- // best-effort before the throw propagates; the original error is preserved.
980
- const { validationGates } = await releaseLeaseOnBlock(
827
+ const prePush = await releaseLeaseOnBlock(
981
828
  () =>
982
829
  runPrePushPhases({
983
830
  ...options,
@@ -994,6 +841,15 @@ async function runClosePipeline({
994
841
  }),
995
842
  leaseArgs,
996
843
  );
844
+ if (prePush.pending) {
845
+ return await finishDeferred(prePush.lockWait, {
846
+ storyId: options.storyId,
847
+ storyBranch,
848
+ baseBranch,
849
+ config,
850
+ startedAtMs,
851
+ });
852
+ }
997
853
 
998
854
  const { prUrl, prNumber, alreadyMerged, reviewOverride } =
999
855
  await releaseLeaseOnBlock(
@@ -1014,16 +870,9 @@ async function runClosePipeline({
1014
870
  }),
1015
871
  leaseArgs,
1016
872
  );
1017
- // Reap the per-Story worktree BEFORE the arm (Story #4681). Arming runs
1018
- // `gh pr merge --auto --squash --delete-branch`, which — against an
1019
- // already-mergeable PR — merges immediately and then shells out to local
1020
- // `git` to drop `story-<id>`. A live worktree still holding that ref makes
1021
- // the local delete fail, `gh` exit non-zero, and the arm read as failed,
1022
- // which used to strand a genuinely merged PR at `agent::blocked`.
1023
- // Pre-empting the hold is the ordering half of the fix (the tolerate half
1024
- // lives in `phases/auto-merge.js`); it is safe here because push and PR
1025
- // creation already made the work durable off-machine, and `isSafeToRemove`
1026
- // still refuses a dirty tree.
873
+ // Reap BEFORE the arm: `gh pr merge --delete-branch` may merge at once and
874
+ // then fail deleting a branch a live worktree holds, reading as a failed
875
+ // arm. Safe — the work is pushed, and a dirty tree is still refused.
1027
876
  const worktreeReaped = await reapWorktreePhase({
1028
877
  cwd: options.cwd,
1029
878
  storyId: options.storyId,
@@ -1047,7 +896,6 @@ async function runClosePipeline({
1047
896
  prUrl,
1048
897
  noAutoMerge: options.noAutoMerge,
1049
898
  autoMergePolicy: ciDelivery.autoMerge,
1050
- // Story #5096 — the pre-arm advisory-gate refusal.
1051
899
  blockOnAdvisoryFailure: ciDelivery.blockOnAdvisoryFailure,
1052
900
  advisoryAllowlist: ciDelivery.advisoryAllowlist,
1053
901
  gh: injectedGh,
@@ -1064,30 +912,11 @@ async function runClosePipeline({
1064
912
  config,
1065
913
  progress,
1066
914
  });
1067
- // Story #4860 — the clean-path lease release USED to sit here, immediately
1068
- // after the arm and the `agent::closing` flip. That dropped the operator's
1069
- // claim the moment the PR opened, so a ticket read unassigned for the whole
1070
- // time its PR was in flight — and forever on the operator-merge path, where
1071
- // nothing downstream ever re-claimed it. The release now belongs to the
1072
- // post-land tail, which runs only on a CONFIRMED merge and which both
1073
- // landing surfaces reach. Every non-merged ending below — the
1074
- // `merge.unlanded` block, an exhausted wait budget, `--no-wait-merge`,
1075
- // `--no-auto-merge` — deliberately RETAINS the claim: the PR is open and the
1076
- // work still has an owner. The only releases that survive here are
1077
- // `releaseLeaseOnBlock`'s two throwing exits above, which fire before the PR
1078
- // is ever armed (Story #4257's hand-off property).
915
+ // No lease release here: only the post-land tail (confirmed merge) releases
916
+ // it; every non-merged ending keeps the claim while the PR is open.
1079
917
 
1080
- // Close-and-land (Story #4428; default since `delivery.routing.closeAndLand`
1081
- // — Story #4539): poll the just-armed PR to merge confirmation, or block
1082
- // explicitly with `merge.unlanded`, instead of resting at `agent::closing`.
1083
- // This is the DEFAULT path for attended and headless runs alike.
1084
- //
1085
- // Resolved here rather than at parse time because two inputs do not exist
1086
- // until now: the resolved config (whose cwd the parse produces) and the
1087
- // actual arm outcome. A PR the operator deliberately left un-armed
1088
- // (`--no-auto-merge` / `autoMerge: "strict"`) has nothing to land, so it
1089
- // rests at `agent::closing` for the human instead of burning the poll
1090
- // budget and then blocking a healthy Story.
918
+ // Resolved now, not at parse time: it needs the config and the arm outcome
919
+ // (an un-armed PR rests at `agent::closing` rather than waiting).
1091
920
  const { waitForMerge, reason: waitForMergeReason } = resolveWaitForMerge({
1092
921
  waitForMergeExplicit: options.waitForMergeExplicit,
1093
922
  noWaitForMerge: options.noWaitForMerge,
@@ -1114,17 +943,8 @@ async function runClosePipeline({
1114
943
  directMerged,
1115
944
  config,
1116
945
  startedAtMs,
1117
- gates: {
1118
- validation: options.skipValidation ? 'skipped' : 'passed',
1119
- // Story #5172 — the split baselines entries, named individually so a
1120
- // reader can tell the two apart. Absent when validation was skipped.
1121
- ...baselinesEnvelopeGates(validationGates),
1122
- baseSync: options.skipSync ? 'skipped' : 'passed',
1123
- // An overridden blocker reports `overridden`, never
1124
- // `passed`. The review DID fail; a human authorized shipping anyway, and
1125
- // the envelope is the machine-readable trail that says so.
1126
- codeReview: reviewOverride ? 'overridden' : 'passed',
1127
- },
946
+ lockWait: prePush.lockWait,
947
+ gates: closeEnvelopeGates(options, prePush.validationGates, reviewOverride),
1128
948
  };
1129
949
 
1130
950
  if (waitForMerge) {