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
@@ -30,6 +30,8 @@ import { runBaseSyncPhase } from './phases/base-sync.js';
30
30
  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
+ import { runGraphqlPreflight } from './phases/graphql-preflight.js';
34
+ import { lockWaitPending } from './phases/lock-wait-pending.js';
33
35
  import { parseCloseOptions, resolveWaitForMerge } from './phases/options.js';
34
36
  import { ensurePullRequestWith } from './phases/pull-request.js';
35
37
  import { pushStoryBranch } from './phases/push.js';
@@ -41,29 +43,11 @@ import { runWrongTreeGuardPhase } from './phases/wrong-tree-guard.js';
41
43
  const progress = Logger.createProgress('single-story-close', { stderr: true });
42
44
 
43
45
  /**
44
- * Emit the terminal envelope on stdout alongside the legacy close result.
45
- *
46
- * Both are printed: the envelope is the contract callers parse (Story
47
- * #4543), while `STORY CLOSE RESULT` stays byte-compatible for the existing
48
- * surfaces that grep it. One writer, one place — so the envelope can never
49
- * be emitted from a path that forgot it.
50
- *
51
- * Story #4578 — the same one-place property is why the runtime-derived
52
- * friction emit hangs here: a close that ends `failed`, or parks `pending`
53
- * on an exhausted merge-wait budget, is friction the retro must see, and
54
- * routing it through the single emitter means no terminal path can forget
55
- * it. `emitTerminalFriction` decides what (if anything) is worth a record —
56
- * see `frictionForTerminal` for why `blocked` and a `--no-wait-merge`
57
- * `pending` are deliberately NOT flagged here.
58
- *
59
- * Async, and awaited by every caller: the CLI exits via `process.exit` the
60
- * moment `main` resolves, so a fire-and-forget append would be discarded.
61
- * 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.
62
49
  */
63
50
  async function emitTerminal({ terminal, result, config }) {
64
- // Story #4685 — the human-facing result dump goes to a temp log; the agent
65
- // acts on the (separate, unsuppressible) terminal envelope emitted below.
66
- // The single summary line keeps the fields worth an at-a-glance read.
67
51
  if (result) {
68
52
  emitTerseResult({
69
53
  label: 'STORY CLOSE RESULT',
@@ -83,21 +67,16 @@ async function emitTerminal({ terminal, result, config }) {
83
67
  }
84
68
 
85
69
  /**
86
- * Terminal for a Story that was already closed before this run started.
87
- *
88
- * `state: 'closed'` alone does NOT mean the work landed. GitHub closes an
89
- * issue as `completed` (the `Closes #<id>` footer firing on merge — the work
90
- * IS on the base branch) or as `not_planned` (superseded by a re-plan,
91
- * abandoned — nothing ever merged). Reporting the second as `landed` told
92
- * `/mandrel-deliver` that work had reached `main` when no PR ever merged, which would
93
- * also satisfy any dependent Story waiting on it. Fail loudly instead: being
94
- * handed an abandoned Story is an input error only the operator can resolve.
95
- *
96
- * A null `stateReason` keeps the `completed` reading — GitHub defaults to it,
97
- * and issues closed before the field existed carry null.
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.
98
73
  */
99
74
  async function alreadyClosedResult(storyId, stateReason = null, config) {
100
75
  if (stateReason === 'not_planned') {
76
+ progress(
77
+ 'NOOP',
78
+ `Story #${storyId} is closed as not planned — nothing to land.`,
79
+ );
101
80
  const result = {
102
81
  storyId,
103
82
  standalone: true,
@@ -120,15 +99,13 @@ async function alreadyClosedResult(storyId, stateReason = null, config) {
120
99
  return { success: false, result, terminal };
121
100
  }
122
101
 
102
+ progress('NOOP', `Story #${storyId} is already closed. Nothing to do.`);
123
103
  const result = {
124
104
  storyId,
125
105
  standalone: true,
126
106
  action: 'noop',
127
107
  reason: 'already-closed',
128
108
  };
129
- // Idempotent re-run against a Story closed as completed. `landed` is the
130
- // honest status — the issue closed on merge, so the work is on the base
131
- // branch — and there is nothing left to command.
132
109
  const terminal = buildTerminalEnvelope({
133
110
  storyId,
134
111
  status: 'landed',
@@ -141,16 +118,49 @@ async function alreadyClosedResult(storyId, stateReason = null, config) {
141
118
  }
142
119
 
143
120
  /**
144
- * Project the baselines entries out of close-validation's per-gate outcomes,
145
- * keyed by the gate's own name (Story #5172).
121
+ * Reuses the classifier's fallback class: the vocabulary is pinned by the
122
+ * terminal schema, so `reason` names the blocker instead.
123
+ */
124
+ const PREFLIGHT_BLOCK_CLASS = 'api-race-other';
125
+
126
+ /**
127
+ * Returned, not thrown: a classified block, not a crash (a throw surfaces as
128
+ * `failed`). The next command is the same close.
146
129
  *
147
- * The envelope's `gates` map used to roll the whole gate chain up into a
148
- * single `validation` verdict, which was fine while the baselines gate was
149
- * one entry and stopped being fine when it became two: a reader of a failed
150
- * close could not tell whether the cheap coverage-independent baselines had
151
- * breached or the expensive coverage-consuming ones had. Only registered
152
- * entries are reported — a consumer whose config registers just one of the
153
- * pair gets just that one, never a phantom key for a gate that never existed.
130
+ * @param {{ storyId: number, preflight: { verdict: string, reason: string },
131
+ * config: object, startedAtMs: number }} args
132
+ * @returns {Promise<{ success: false, result: object, terminal: object }>}
133
+ */
134
+ async function preflightBlockedResult({
135
+ storyId,
136
+ preflight,
137
+ config,
138
+ startedAtMs,
139
+ }) {
140
+ const result = {
141
+ storyId,
142
+ standalone: true,
143
+ action: 'noop',
144
+ reason: `graphql-preflight-${preflight.verdict}`,
145
+ };
146
+ const terminal = buildTerminalEnvelope({
147
+ storyId,
148
+ status: 'blocked',
149
+ phase: 'init',
150
+ blocked: {
151
+ blockClass: PREFLIGHT_BLOCK_CLASS,
152
+ reason: preflight.reason,
153
+ frictionCommentId: null,
154
+ },
155
+ nextCommand: NEXT_COMMANDS.close(storyId),
156
+ elapsedSeconds: elapsedSecondsSince(startedAtMs),
157
+ });
158
+ await emitTerminal({ terminal, result, config });
159
+ return { success: false, result, terminal };
160
+ }
161
+
162
+ /**
163
+ * The split baselines gates, by name; only registered ones, never a phantom key.
154
164
  *
155
165
  * @param {Record<string, string>|null|undefined} validationGates
156
166
  * @returns {Record<string, string>}
@@ -164,6 +174,22 @@ function baselinesEnvelopeGates(validationGates) {
164
174
  return out;
165
175
  }
166
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
+
167
193
  function resolveWorktreePath({ cwd, config, storyId }) {
168
194
  const root = config.delivery?.worktreeIsolation?.root ?? '.worktrees';
169
195
  const candidate = path.resolve(cwd, root, `story-${storyId}`);
@@ -171,25 +197,16 @@ function resolveWorktreePath({ cwd, config, storyId }) {
171
197
  }
172
198
 
173
199
  /**
174
- * The pre-push phases, in the order the pipeline walks them: wrong-tree
175
- * guard → base-sync → close-validation.
176
- *
177
- * Story #5172 put base-sync AHEAD of close-validation, for two reasons that
178
- * are really one. The cheap one: a base-sync conflict is a hard block that
179
- * costs nothing to detect, so paying for the full gate chain before
180
- * discovering it burns the pipeline's most expensive minutes on a tree that
181
- * was never going to be pushed. The load-bearing one: with the gates last,
182
- * **the validated tree is the pushed tree**. Under the old order the merge
183
- * commit base-sync writes landed AFTER validation, so every close pushed a
184
- * tree no gate had ever seen.
185
- *
186
- * `--skip-sync` and `--skip-validation` stay independent — either, both or
187
- * 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.
188
203
  *
189
- * @returns {Promise<{ validationGates: Record<string, string>|null }>}
190
- * The per-gate outcomes close-validation observed, or `null` when the phase
191
- * was skipped. Feeds the terminal envelope's `gates` map so the split
192
- * 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.
193
210
  */
194
211
  async function runPrePushPhases({
195
212
  cwd,
@@ -235,7 +252,7 @@ async function runPrePushPhases({
235
252
  }
236
253
  if (skipValidation) {
237
254
  progress('VALIDATE', '⏭ Skipped (--skip-validation).');
238
- return { validationGates: null };
255
+ return { validationGates: null, lockWait: null, pending: false };
239
256
  }
240
257
  setPhase('close-validation');
241
258
  let validation;
@@ -252,12 +269,7 @@ async function runPrePushPhases({
252
269
  buildDefaultGates,
253
270
  });
254
271
  } catch (err) {
255
- // Story #5279 — the failed terminal REPORTS gates rather than
256
- // reconstructing them, so hand it what this run observed. The phase tags
257
- // `closeGate` with the entry that died; that one name is the whole of
258
- // what the run observed about gate outcomes, and therefore the whole of
259
- // what the envelope may claim. Anything else it might have named is a
260
- // gate the run never proved ran at all.
272
+ // The gate that died is all this run observed; the envelope claims no more.
261
273
  if (typeof err?.closeGate === 'string') {
262
274
  setObservedGates({ [err.closeGate]: 'failed' });
263
275
  }
@@ -265,7 +277,11 @@ async function runPrePushPhases({
265
277
  }
266
278
  const gates = validation?.gates ?? null;
267
279
  setObservedGates(gates);
268
- return { validationGates: gates };
280
+ return {
281
+ validationGates: gates,
282
+ lockWait: validation?.lockWait ?? null,
283
+ pending: validation?.pending === true,
284
+ };
269
285
  }
270
286
 
271
287
  async function openAndReviewPr({
@@ -283,17 +299,14 @@ async function openAndReviewPr({
283
299
  setPhase = () => {},
284
300
  }) {
285
301
  setPhase('push');
286
- // Issue #4990 — push from the Story worktree so `pre-push` measures the
287
- // tree being sent. `gh` and the review's ref-based diffs below keep the
288
- // caller's `cwd`: they read the shared `.git`, so they resolve identically
289
- // 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`.
290
304
  pushStoryBranch({ cwd, worktreePath, storyBranch, gitSync, progress });
291
305
  setPhase('pull-request');
292
306
  const { url: prUrl, alreadyMerged } = await ensurePullRequestWith({
293
307
  cwd,
294
308
  storyId,
295
309
  storyTitle: story.title,
296
- // Scanned for a declared `BREAKING CHANGE:` footer — see pull-request.js.
297
310
  storyBody: story.body,
298
311
  storyBranch,
299
312
  baseBranch,
@@ -301,10 +314,7 @@ async function openAndReviewPr({
301
314
  progress,
302
315
  });
303
316
  const prNumber = parsePrNumber(prUrl);
304
- // Story #4873 — the head's PR already merged (an armed PR that landed while
305
- // a previous close invocation was between phases). There is nothing left to
306
- // review and nothing left to arm; the confirm phase probes the PR, observes
307
- // MERGED, and lands the Story on the merge that actually happened.
317
+ // Already merged (landed between invocations): skip review and arm; confirm observes it.
308
318
  if (alreadyMerged) {
309
319
  return { prUrl, prNumber, alreadyMerged: true };
310
320
  }
@@ -318,19 +328,12 @@ async function openAndReviewPr({
318
328
  prNumber,
319
329
  provider,
320
330
  runCodeReviewFn: injectedRunCodeReview ?? runCodeReviewDefault,
321
- // The runner owns the git seam it hands its phases (same as `gitSync` to
322
- // `pushStoryBranch`). The review needs it to resolve `origin/<base>` —
323
- // the ref base-sync merged from — before it will score anything
324
- // (Story #5325).
325
331
  gitSpawnFn: gitSpawn,
326
332
  progress,
327
333
  });
328
334
  if (reviewOutcome.halted) {
329
335
  const criticalCount = reviewOutcome.severity?.critical ?? 0;
330
- // The sanctioned override. Checked BEFORE the blocked
331
- // transition so an overridden run never touches `agent::blocked`: the
332
- // Story is proceeding, and parking it would make the label lie for the
333
- // rest of the close.
336
+ // Checked before the blocked transition: an overridden Story proceeds.
334
337
  if (overrideReviewBlock) {
335
338
  const override = await handleOverriddenReviewBlock({
336
339
  provider,
@@ -390,30 +393,12 @@ async function releaseLease({
390
393
  }
391
394
 
392
395
  /**
393
- * Story #4257 — run a blocked-prone phase and, if it throws, release the
394
- * assignee-lease best-effort BEFORE re-throwing the original error.
395
- *
396
- * The two recoverable-blocked close exits (base-sync conflict in
397
- * `runBaseSyncPhase`, and a critical-blocker review halt in
398
- * `openAndReviewPr`) throw before the clean-close lease release at the
399
- * tail of `runSingleStoryClose`, stranding the operator's lease
400
- * indefinitely. The standalone lease has **no** TTL to expire by (Story
401
- * #5006 deleted it): `acquireLease` refuses any foreign assignee outright,
402
- * so a stranded claim is cleared only by `--steal` or de-assignment. That fail-closed-refuses a different operator who picks up
403
- * the blocked Story — exactly the hand-off case. Releasing here closes
404
- * that gap.
405
- *
406
- * The original throw is preserved verbatim (per
407
- * `rules/orchestration-error-handling.md` — throw, never `Logger.fatal`),
408
- * so the CLI boundary still maps it to a non-zero exit; the lease release
409
- * must not swallow it. `releaseLease` is itself best-effort and never
410
- * throws, so it cannot mask the real failure. Fail-closed re-acquire
411
- * semantics are preserved: `releaseStoryLease` no-ops when the operator no
412
- * longer holds the claim, and a self-held re-acquire on a re-run still
413
- * 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.
414
399
  *
415
400
  * @template T
416
- * @param {() => Promise<T>} run The blocked-prone phase to execute.
401
+ * @param {() => Promise<T>} run
417
402
  * @param {{ provider: object, storyId: number, config: object, injectedReleaseLease?: Function }} leaseArgs
418
403
  * @returns {Promise<T>}
419
404
  */
@@ -427,25 +412,8 @@ async function releaseLeaseOnBlock(run, leaseArgs) {
427
412
  }
428
413
 
429
414
  /**
430
- * Did this run OBSERVE the PR merge? (Story #5279)
431
- *
432
- * `merged` used to be whatever the caller happened to pass, and the two
433
- * finishers passed different halves of the truth. Three observations say a
434
- * merge happened, and each of them reported `merged: false` on at least one
435
- * path:
436
- *
437
- * - the confirm phase watched it land (`waitOutcome.confirmed`);
438
- * - it landed and only the `agent::done` label write failed
439
- * (`merged-flip-failed`) — the terminal envelope for that same run
440
- * already reports `pr.state: MERGED` from the probe, so a result denying
441
- * the merge made the two halves of one run contradict each other;
442
- * - the arm phase direct-squash-merged it synchronously because the
443
- * repository has no native auto-merge (`directMerged`), which the
444
- * no-wait finisher never consulted at all.
445
- *
446
- * Deliberately observation-only: it reads what the run saw, never what the
447
- * run intended. A `null`/absent `waitOutcome` is the no-wait finisher, whose
448
- * 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.
449
417
  *
450
418
  * @param {{ waitOutcome?: object|null, directMerged?: boolean }} args
451
419
  * @returns {boolean}
@@ -486,25 +454,13 @@ function closeResult({
486
454
  autoMergeReason,
487
455
  worktreeReaped,
488
456
  leaseReleased,
489
- // Story #4681 — `gh`'s local head-branch delete failed while the remote
490
- // merge/arm stood. Surfaced so the land is auditable as
491
- // merged-with-deferred-cleanup rather than silently degraded.
457
+ // `gh`'s local branch delete failed while the remote merge/arm stood.
492
458
  localCleanupDeferred,
493
- // Story #4682 — native auto-merge was unavailable (no branch protection /
494
- // an already-clean PR), so the PR was landed by a direct squash-merge.
495
- // Surfaced so a checks-less land is auditable rather than looking like a
496
- // queued auto-merge that never fired.
459
+ // No native auto-merge, so the arm squash-merged directly.
497
460
  directMerged,
498
461
  waitedForMerge,
499
462
  merged,
500
- // Story #5266 — derived from `merged` / `directMerged` / `autoMergeEnabled`,
501
- // never from `waitedForMerge`. A wait that expired unmerged used to write
502
- // "PR merge confirmed" beside `merged: false`, and this log is what the
503
- // operator reads first. See close-note.js for the invariant.
504
- // Story #5279 — `landCompleted` keeps that invariant intact now that
505
- // `merged: true` no longer implies the flip and the tail ran: a direct
506
- // merge under `--no-wait-merge`, and a `merged-flip-failed` block, are
507
- // both merged WITHOUT a completed land.
463
+ // Never from `waitedForMerge`; `merged` can be true without a completed land.
508
464
  note: deriveCloseNote({
509
465
  merged,
510
466
  directMerged,
@@ -534,6 +490,7 @@ export async function runSingleStoryClose({
534
490
  injectedGh,
535
491
  injectedGitSpawn,
536
492
  injectedReleaseLease,
493
+ injectedGraphqlProbe,
537
494
  } = {}) {
538
495
  const options = parseCloseOptions({
539
496
  storyIdParam,
@@ -554,18 +511,10 @@ export async function runSingleStoryClose({
554
511
  );
555
512
  }
556
513
 
557
- // Story #4543 — track the phase so a crash is attributable. The runner
558
- // deliberately keeps THROWING (the library contract every caller and test
559
- // relies on: a failed gate must not look like a return value); it only tags
560
- // the error with the phase it died in, and the CLI boundary turns that into
561
- // the `failed` terminal envelope. Tagging rather than swallowing is what
562
- // 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.
563
517
  let phase = 'init';
564
- // Story #5279 — the per-gate outcomes this run OBSERVED, tagged onto a
565
- // throwing error alongside the phase so `failedTerminalFor` reports gates
566
- // instead of reconstructing which ones "must have" run. Stays null until
567
- // close-validation reports, so a run that died before it claims no gates at
568
- // all rather than inventing names for gates that were never registered.
569
518
  let observedGates = null;
570
519
  const setPhase = (next) => {
571
520
  phase = next;
@@ -586,6 +535,7 @@ export async function runSingleStoryClose({
586
535
  injectedGh,
587
536
  injectedGitSpawn,
588
537
  injectedReleaseLease,
538
+ injectedGraphqlProbe,
589
539
  });
590
540
  } catch (err) {
591
541
  if (err && typeof err === 'object') {
@@ -597,10 +547,7 @@ export async function runSingleStoryClose({
597
547
  }
598
548
 
599
549
  /**
600
- * Resolve the arm outcome. An already-merged head PR (Story #4873) has nothing
601
- * to arm — `gh pr merge` against it fails, which would report the arm as a
602
- * fault and block a Story whose work is already on the base branch. Skip the
603
- * 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).
604
551
  *
605
552
  * @param {object} args
606
553
  * @returns {Promise<{ autoMergeEnabled: boolean, autoMergeReason: string|null,
@@ -620,10 +567,6 @@ async function resolveAutoMergeOutcome({ alreadyMerged, ...phaseArgs }) {
620
567
  }
621
568
 
622
569
  /**
623
- * Report the merge-wait terminal on the progress channel. Three endings, each
624
- * with its own operator-facing shape — `landed` is done, `pending` is
625
- * resumable and NOT a failure, anything else is a block naming its class.
626
- *
627
570
  * @param {{ status: string, nextCommand: string, blocked?: {blockClass?: string} }} terminal
628
571
  * @param {{ storyId: number, prUrl: string|null }} ctx
629
572
  * @returns {void}
@@ -634,9 +577,7 @@ function reportWaitTerminal(terminal, { storyId, prUrl }) {
634
577
  return;
635
578
  }
636
579
  if (terminal.status === 'pending') {
637
- // NOT a failure and NOT a block — the wait reached the edge of its
638
- // host slot with the PR healthy and in flight. The CLI maps this to
639
- // its own exit code so a caller can resume without classifying.
580
+ // Not a failure: resumable, with its own CLI exit code.
640
581
  progress(
641
582
  'PENDING',
642
583
  `⏸ Story #${storyId}: PR ${prUrl} still in flight — resume with: ${terminal.nextCommand}`,
@@ -652,11 +593,8 @@ function reportWaitTerminal(terminal, { storyId, prUrl }) {
652
593
  }
653
594
 
654
595
  /**
655
- * The close-and-land ending (Story #4428): poll the just-armed PR to merge
656
- * confirmation and emit the terminal the outcome names.
657
- *
658
- * @param {object} prCtx The shared PR/gate context built by the pipeline.
659
- * @param {object} deps Runtime seams the confirm phase needs.
596
+ * @param {object} prCtx
597
+ * @param {object} deps
660
598
  * @returns {Promise<{ success: boolean, result: object, terminal: object }>}
661
599
  */
662
600
  async function finishWithMergeWait(prCtx, deps) {
@@ -689,6 +627,7 @@ async function finishWithMergeWait(prCtx, deps) {
689
627
  prUrl: prCtx.prUrl,
690
628
  autoMergeEnabled: prCtx.autoMergeEnabled,
691
629
  gates: prCtx.gates,
630
+ lockWait: prCtx.lockWait,
692
631
  elapsedSeconds: elapsedSecondsSince(prCtx.startedAtMs),
693
632
  });
694
633
  const result = closeResult({
@@ -700,22 +639,15 @@ async function finishWithMergeWait(prCtx, deps) {
700
639
  autoMergeEnabled: prCtx.autoMergeEnabled,
701
640
  autoMergeReason: prCtx.autoMergeReason,
702
641
  worktreeReaped: prCtx.worktreeReaped,
703
- // Story #4860 — the release is a post-land tail step now, so the tail's
704
- // own per-step boolean IS the answer. A wait that ended anything other
705
- // than landed never ran the tail, and correctly reports `false`: the
706
- // claim is still held, by design.
642
+ // Released by the post-land tail only; any other ending keeps the claim.
707
643
  leaseReleased: waitOutcome.tail?.leaseRelease === true,
708
644
  localCleanupDeferred: prCtx.localCleanupDeferred,
709
645
  directMerged: prCtx.directMerged,
710
646
  waitedForMerge: true,
711
- // Story #5279 — `confirmed` alone denied the merge behind a
712
- // `merged-flip-failed` block, whose own envelope (above) reports
713
- // `pr.state: MERGED` off the probe.
714
647
  merged: deriveObservedMerge({
715
648
  waitOutcome,
716
649
  directMerged: prCtx.directMerged,
717
650
  }),
718
- // Only the confirmed ending runs the flip, the issue close and the tail.
719
651
  landCompleted: waitOutcome.confirmed === true,
720
652
  });
721
653
  await emitTerminal({ terminal, result, config: prCtx.config });
@@ -724,20 +656,14 @@ async function finishWithMergeWait(prCtx, deps) {
724
656
  }
725
657
 
726
658
  /**
727
- * The no-wait ending — `--no-wait-merge` / operator-merge. The PR is open and
728
- * a human owns the land. That is a `pending` terminal by definition: the work
729
- * is not done, nothing is broken, and one named command finishes it — rather
730
- * 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.
731
661
  *
732
662
  * @param {object} prCtx
733
663
  * @param {string} waitForMergeReason
734
664
  * @returns {Promise<{ success: boolean, result: object, terminal: object }>}
735
665
  */
736
666
  async function finishWithoutMergeWait(prCtx, waitForMergeReason) {
737
- // Story #5279 — a repository with no native auto-merge is direct
738
- // squash-merged synchronously by the arm phase, so this ending can and does
739
- // hold an OBSERVED merge. It used to report `merged: false` and hard-code
740
- // `pr.state: 'OPEN'` for a PR the same run had just merged.
741
667
  const merged = deriveObservedMerge({ directMerged: prCtx.directMerged });
742
668
  const result = closeResult({
743
669
  storyId: prCtx.storyId,
@@ -748,15 +674,11 @@ async function finishWithoutMergeWait(prCtx, waitForMergeReason) {
748
674
  autoMergeEnabled: prCtx.autoMergeEnabled,
749
675
  autoMergeReason: prCtx.autoMergeReason,
750
676
  worktreeReaped: prCtx.worktreeReaped,
751
- // Story #4860 — this is the no-wait ending: the PR is open and a human
752
- // owns the merge, so the Story stays assigned until the confirm-merge
753
- // surface lands it and runs the tail.
754
677
  leaseReleased: false,
755
678
  localCleanupDeferred: prCtx.localCleanupDeferred,
756
679
  directMerged: prCtx.directMerged,
757
680
  merged,
758
- // Whatever the merge state, this ending never flips `agent::done`, never
759
- // closes the issue and never runs the tail — `nextCommand` does.
681
+ // The flip, issue close and tail belong to `nextCommand`.
760
682
  landCompleted: false,
761
683
  });
762
684
  const terminal = buildTerminalEnvelope({
@@ -772,6 +694,7 @@ async function finishWithoutMergeWait(prCtx, waitForMergeReason) {
772
694
  autoMergeEnabled: Boolean(prCtx.autoMergeEnabled),
773
695
  },
774
696
  gates: prCtx.gates,
697
+ lockWait: prCtx.lockWait,
775
698
  nextCommand: NEXT_COMMANDS.confirmMerge(prCtx.storyId),
776
699
  elapsedSeconds: elapsedSecondsSince(prCtx.startedAtMs),
777
700
  });
@@ -784,9 +707,25 @@ async function finishWithoutMergeWait(prCtx, waitForMergeReason) {
784
707
  }
785
708
 
786
709
  /**
787
- * Wall-clock seconds since the close started, rounded — the terminal
788
- * envelope's `elapsedSeconds`.
710
+ * A full-suite lock wait expired: `pending`, nothing pushed.
789
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
+ /**
790
729
  * @param {number} startedAtMs
791
730
  * @returns {number}
792
731
  */
@@ -795,10 +734,6 @@ function elapsedSecondsSince(startedAtMs) {
795
734
  }
796
735
 
797
736
  /**
798
- * Announce the operator-merge skip: the PR was deliberately left un-armed, so
799
- * nothing here can land it and the Story rests at `agent::closing`. No-op on
800
- * every other wait reason.
801
- *
802
737
  * @param {{ waitForMergeReason: string, autoMergeReason: string|null,
803
738
  * storyId: number, waitForMergeExplicit?: boolean }} args
804
739
  * @returns {void}
@@ -820,11 +755,6 @@ function reportOperatorMergeSkip({
820
755
  );
821
756
  }
822
757
 
823
- /**
824
- * The close pipeline proper. Split out of `runSingleStoryClose` so the
825
- * phase-tagging wrapper above stays a thin, obviously-correct boundary rather
826
- * than a try block wrapped around a hundred lines of pipeline.
827
- */
828
758
  async function runClosePipeline({
829
759
  options,
830
760
  setPhase,
@@ -837,6 +767,7 @@ async function runClosePipeline({
837
767
  injectedGh,
838
768
  injectedGitSpawn,
839
769
  injectedReleaseLease,
770
+ injectedGraphqlProbe,
840
771
  }) {
841
772
  const startedAtMs = Date.now();
842
773
  const config = injectedConfig || resolveConfig({ cwd: options.cwd });
@@ -846,12 +777,6 @@ async function runClosePipeline({
846
777
  progress('INIT', `Closing standalone Story #${options.storyId}...`);
847
778
  const story = await provider.getTicket(options.storyId);
848
779
  if (story.state === 'closed') {
849
- progress(
850
- 'NOOP',
851
- story.stateReason === 'not_planned'
852
- ? `Story #${options.storyId} is closed as not planned — nothing to land.`
853
- : `Story #${options.storyId} is already closed. Nothing to do.`,
854
- );
855
780
  return await alreadyClosedResult(
856
781
  options.storyId,
857
782
  story.stateReason,
@@ -859,16 +784,35 @@ async function runClosePipeline({
859
784
  );
860
785
  }
861
786
 
862
- // Story #4891 — the base branch this run was SEEDED from, read back off the
863
- // run's `story-init` receipt rather than re-resolved from a config file that
864
- // may have changed during the whole implementation window. Throws (fail
865
- // closed, naming both values) when the pin and current config disagree —
866
- // deliberately here, before the gate chain, format-autofix and base-sync,
867
- // so a wrong base is never merged into the Story branch. `baseConfirmed`
868
- // gates the base-merge remediation advice further down.
787
+ const leaseArgs = {
788
+ provider,
789
+ storyId: options.storyId,
790
+ config,
791
+ injectedReleaseLease,
792
+ };
793
+
794
+ // `gh pr` needs GraphQL; one cheap read here beats the gate chain plus a push.
795
+ const preflight = await runGraphqlPreflight({
796
+ storyId: options.storyId,
797
+ provider,
798
+ progress,
799
+ ghFacade: injectedGh,
800
+ probe: injectedGraphqlProbe,
801
+ });
802
+ if (preflight) {
803
+ await releaseLease(leaseArgs);
804
+ return await preflightBlockedResult({
805
+ storyId: options.storyId,
806
+ preflight,
807
+ config,
808
+ startedAtMs,
809
+ });
810
+ }
811
+
812
+ // The base the run was SEEDED from (init receipt); throws before any merge
813
+ // when it disagrees with current config.
869
814
  const { values: runScoped, confirmed: baseConfirmed } =
870
815
  await resolveRunScopedConfig({
871
- provider,
872
816
  storyId: options.storyId,
873
817
  config,
874
818
  progress,
@@ -880,17 +824,7 @@ async function runClosePipeline({
880
824
  config,
881
825
  storyId: options.storyId,
882
826
  });
883
- // Story #4257 — the base-sync conflict and review-critical exits throw
884
- // before the clean-close lease release at the tail of this function.
885
- // Wrap both blocked-prone phases so the lease is released best-effort
886
- // before the throw propagates; the original error is preserved.
887
- const leaseArgs = {
888
- provider,
889
- storyId: options.storyId,
890
- config,
891
- injectedReleaseLease,
892
- };
893
- const { validationGates } = await releaseLeaseOnBlock(
827
+ const prePush = await releaseLeaseOnBlock(
894
828
  () =>
895
829
  runPrePushPhases({
896
830
  ...options,
@@ -907,6 +841,15 @@ async function runClosePipeline({
907
841
  }),
908
842
  leaseArgs,
909
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
+ }
910
853
 
911
854
  const { prUrl, prNumber, alreadyMerged, reviewOverride } =
912
855
  await releaseLeaseOnBlock(
@@ -927,16 +870,9 @@ async function runClosePipeline({
927
870
  }),
928
871
  leaseArgs,
929
872
  );
930
- // Reap the per-Story worktree BEFORE the arm (Story #4681). Arming runs
931
- // `gh pr merge --auto --squash --delete-branch`, which — against an
932
- // already-mergeable PR — merges immediately and then shells out to local
933
- // `git` to drop `story-<id>`. A live worktree still holding that ref makes
934
- // the local delete fail, `gh` exit non-zero, and the arm read as failed,
935
- // which used to strand a genuinely merged PR at `agent::blocked`.
936
- // Pre-empting the hold is the ordering half of the fix (the tolerate half
937
- // lives in `phases/auto-merge.js`); it is safe here because push and PR
938
- // creation already made the work durable off-machine, and `isSafeToRemove`
939
- // 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.
940
876
  const worktreeReaped = await reapWorktreePhase({
941
877
  cwd: options.cwd,
942
878
  storyId: options.storyId,
@@ -960,7 +896,6 @@ async function runClosePipeline({
960
896
  prUrl,
961
897
  noAutoMerge: options.noAutoMerge,
962
898
  autoMergePolicy: ciDelivery.autoMerge,
963
- // Story #5096 — the pre-arm advisory-gate refusal.
964
899
  blockOnAdvisoryFailure: ciDelivery.blockOnAdvisoryFailure,
965
900
  advisoryAllowlist: ciDelivery.advisoryAllowlist,
966
901
  gh: injectedGh,
@@ -977,30 +912,11 @@ async function runClosePipeline({
977
912
  config,
978
913
  progress,
979
914
  });
980
- // Story #4860 — the clean-path lease release USED to sit here, immediately
981
- // after the arm and the `agent::closing` flip. That dropped the operator's
982
- // claim the moment the PR opened, so a ticket read unassigned for the whole
983
- // time its PR was in flight — and forever on the operator-merge path, where
984
- // nothing downstream ever re-claimed it. The release now belongs to the
985
- // post-land tail, which runs only on a CONFIRMED merge and which both
986
- // landing surfaces reach. Every non-merged ending below — the
987
- // `merge.unlanded` block, an exhausted wait budget, `--no-wait-merge`,
988
- // `--no-auto-merge` — deliberately RETAINS the claim: the PR is open and the
989
- // work still has an owner. The only releases that survive here are
990
- // `releaseLeaseOnBlock`'s two throwing exits above, which fire before the PR
991
- // 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.
992
917
 
993
- // Close-and-land (Story #4428; default since `delivery.routing.closeAndLand`
994
- // — Story #4539): poll the just-armed PR to merge confirmation, or block
995
- // explicitly with `merge.unlanded`, instead of resting at `agent::closing`.
996
- // This is the DEFAULT path for attended and headless runs alike.
997
- //
998
- // Resolved here rather than at parse time because two inputs do not exist
999
- // until now: the resolved config (whose cwd the parse produces) and the
1000
- // actual arm outcome. A PR the operator deliberately left un-armed
1001
- // (`--no-auto-merge` / `autoMerge: "strict"`) has nothing to land, so it
1002
- // rests at `agent::closing` for the human instead of burning the poll
1003
- // 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).
1004
920
  const { waitForMerge, reason: waitForMergeReason } = resolveWaitForMerge({
1005
921
  waitForMergeExplicit: options.waitForMergeExplicit,
1006
922
  noWaitForMerge: options.noWaitForMerge,
@@ -1027,17 +943,8 @@ async function runClosePipeline({
1027
943
  directMerged,
1028
944
  config,
1029
945
  startedAtMs,
1030
- gates: {
1031
- validation: options.skipValidation ? 'skipped' : 'passed',
1032
- // Story #5172 — the split baselines entries, named individually so a
1033
- // reader can tell the two apart. Absent when validation was skipped.
1034
- ...baselinesEnvelopeGates(validationGates),
1035
- baseSync: options.skipSync ? 'skipped' : 'passed',
1036
- // An overridden blocker reports `overridden`, never
1037
- // `passed`. The review DID fail; a human authorized shipping anyway, and
1038
- // the envelope is the machine-readable trail that says so.
1039
- codeReview: reviewOverride ? 'overridden' : 'passed',
1040
- },
946
+ lockWait: prePush.lockWait,
947
+ gates: closeEnvelopeGates(options, prePush.validationGates, reviewOverride),
1041
948
  };
1042
949
 
1043
950
  if (waitForMerge) {