mandrel 1.94.0 → 2.1.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 (560) hide show
  1. package/.agents/README.md +116 -99
  2. package/.agents/agents/acceptance-critic.md +9 -7
  3. package/.agents/agents/story-worker.md +45 -51
  4. package/.agents/audit-checklists/performance.md +1 -1
  5. package/.agents/docs/SDLC.md +498 -1287
  6. package/.agents/docs/agentrc-reference.json +185 -80
  7. package/.agents/docs/configuration.md +132 -190
  8. package/.agents/docs/execution-reference.md +51 -25
  9. package/.agents/docs/quality-gates.md +25 -33
  10. package/.agents/docs/workflows.md +8 -8
  11. package/.agents/instructions.md +113 -139
  12. package/.agents/rules/ci-remediation.md +11 -15
  13. package/.agents/rules/git-conventions-reference.md +48 -58
  14. package/.agents/rules/git-conventions.md +16 -22
  15. package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
  16. package/.agents/schemas/agentrc.schema.json +83 -254
  17. package/.agents/schemas/audit-rules.json +59 -1
  18. package/.agents/schemas/audit-rules.schema.json +33 -1
  19. package/.agents/schemas/lifecycle/README.md +1 -2
  20. package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
  21. package/.agents/schemas/lifecycle/merge.flip-failed.schema.json +33 -0
  22. package/.agents/schemas/lifecycle/merge.unlanded.schema.json +1 -0
  23. package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
  24. package/.agents/schemas/lifecycle/story.merged.schema.json +1 -1
  25. package/.agents/schemas/signal-event.schema.json +3 -3
  26. package/.agents/schemas/story-deliver-terminal.schema.json +152 -0
  27. package/.agents/schemas/validation-evidence.schema.json +1 -1
  28. package/.agents/scripts/acceptance-eval.js +22 -66
  29. package/.agents/scripts/agents-bootstrap-github.js +1 -1
  30. package/.agents/scripts/audit-to-stories.js +7 -7
  31. package/.agents/scripts/boot-sweep.js +1 -1
  32. package/.agents/scripts/bootstrap.js +3 -3
  33. package/.agents/scripts/check-dead-exports.js +43 -104
  34. package/.agents/scripts/check-doc-links.js +2 -2
  35. package/.agents/scripts/check-lifecycle-lint.js +7 -10
  36. package/.agents/scripts/check-workflow-cli-lint.js +91 -0
  37. package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
  38. package/.agents/scripts/deliver-recover.js +122 -0
  39. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  40. package/.agents/scripts/evidence-gate.js +20 -50
  41. package/.agents/scripts/generate-skills-index.js +17 -1
  42. package/.agents/scripts/generate-workflows-doc.js +4 -4
  43. package/.agents/scripts/lib/ITicketingProvider.js +1 -19
  44. package/.agents/scripts/lib/Logger.js +6 -10
  45. package/.agents/scripts/lib/audit-suite/runner.js +2 -2
  46. package/.agents/scripts/lib/audit-suite/selector.js +328 -28
  47. package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
  48. package/.agents/scripts/lib/baselines/kernel.js +206 -18
  49. package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -15
  50. package/.agents/scripts/lib/baselines/reader.js +1 -6
  51. package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
  52. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +28 -33
  53. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
  54. package/.agents/scripts/lib/bootstrap/manifest.js +8 -11
  55. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +30 -53
  56. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +0 -2
  57. package/.agents/scripts/lib/checks/core-bare-clean.js +6 -3
  58. package/.agents/scripts/lib/checks/index.js +3 -2
  59. package/.agents/scripts/lib/checks/loop-health.js +12 -11
  60. package/.agents/scripts/lib/checks/state.js +17 -248
  61. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +26 -24
  62. package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +3 -4
  63. package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +2 -2
  64. package/.agents/scripts/lib/checks/worktree-residue-biome.js +3 -3
  65. package/.agents/scripts/lib/cli/standard-args.js +13 -22
  66. package/.agents/scripts/lib/cli-args.js +39 -9
  67. package/.agents/scripts/lib/close-validation/gates.js +15 -15
  68. package/.agents/scripts/lib/close-validation/projections/inputs.js +7 -7
  69. package/.agents/scripts/lib/close-validation/projections/maintainability.js +12 -12
  70. package/.agents/scripts/lib/close-validation/runner.js +13 -21
  71. package/.agents/scripts/lib/close-validation/telemetry.js +17 -8
  72. package/.agents/scripts/lib/config/ci.js +6 -31
  73. package/.agents/scripts/lib/config/delivery-routing.js +52 -35
  74. package/.agents/scripts/lib/config/explain.js +61 -48
  75. package/.agents/scripts/lib/config/github.js +7 -5
  76. package/.agents/scripts/lib/config/limits.js +29 -80
  77. package/.agents/scripts/lib/config/paths.js +0 -2
  78. package/.agents/scripts/lib/config/quality.js +12 -15
  79. package/.agents/scripts/lib/config/runners.js +20 -66
  80. package/.agents/scripts/lib/config/temp-paths.js +30 -63
  81. package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
  82. package/.agents/scripts/lib/config-resolver.js +2 -7
  83. package/.agents/scripts/lib/config-settings-schema-delivery.js +55 -161
  84. package/.agents/scripts/lib/config-settings-schema-quality.js +17 -16
  85. package/.agents/scripts/lib/config-settings-schema.js +100 -60
  86. package/.agents/scripts/lib/dead-exports-knip.js +105 -0
  87. package/.agents/scripts/lib/dead-exports-mode.js +51 -0
  88. package/.agents/scripts/lib/dependency-parser.js +3 -2
  89. package/.agents/scripts/lib/doc-tiers.js +2 -2
  90. package/.agents/scripts/lib/duplicate-search.js +242 -41
  91. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
  92. package/.agents/scripts/lib/findings/promote-finding.js +23 -14
  93. package/.agents/scripts/lib/format-generated-json.js +97 -0
  94. package/.agents/scripts/lib/framework-version.js +19 -190
  95. package/.agents/scripts/lib/gh-exec.js +8 -0
  96. package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
  97. package/.agents/scripts/lib/git-branch-lifecycle.js +17 -180
  98. package/.agents/scripts/lib/git-utils.js +32 -20
  99. package/.agents/scripts/lib/github/framework-repo.js +6 -0
  100. package/.agents/scripts/lib/json-utils.js +1 -2
  101. package/.agents/scripts/lib/label-constants.js +10 -38
  102. package/.agents/scripts/lib/label-taxonomy.js +10 -55
  103. package/.agents/scripts/lib/observability/active-story-env.js +44 -165
  104. package/.agents/scripts/lib/observability/runtime-friction.js +243 -0
  105. package/.agents/scripts/lib/observability/signal-validator.js +4 -4
  106. package/.agents/scripts/lib/observability/signals-writer.js +6 -82
  107. package/.agents/scripts/lib/observability/source-classifier.js +5 -5
  108. package/.agents/scripts/lib/observability/tool-trace-hook.js +2 -12
  109. package/.agents/scripts/lib/onboard/init-tail.js +1 -3
  110. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +1 -1
  111. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +2 -2
  112. package/.agents/scripts/lib/orchestration/ceremony-routing.js +105 -44
  113. package/.agents/scripts/lib/orchestration/code-review.js +78 -436
  114. package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
  115. package/.agents/scripts/lib/orchestration/consolidation-precondition.js +4 -4
  116. package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
  117. package/.agents/scripts/lib/orchestration/deliver-recover.js +328 -0
  118. package/.agents/scripts/lib/orchestration/detectors-phase.js +12 -6
  119. package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
  120. package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
  121. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
  122. package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +34 -0
  123. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +3 -2
  124. package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +142 -0
  125. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +17 -19
  126. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +86 -0
  127. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +37 -103
  128. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
  129. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +21 -43
  130. package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +50 -85
  131. package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +3 -14
  132. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
  133. package/.agents/scripts/lib/orchestration/merge-block-class.js +77 -21
  134. package/.agents/scripts/lib/orchestration/merge-poll.js +104 -0
  135. package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
  136. package/.agents/scripts/lib/orchestration/plan-context.js +354 -282
  137. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +11 -22
  138. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +4 -8
  139. package/.agents/scripts/lib/orchestration/plan-metrics.js +38 -6
  140. package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
  141. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +71 -0
  142. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +245 -0
  143. package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +116 -0
  144. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +432 -858
  145. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +778 -0
  146. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +47 -115
  147. package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +509 -0
  148. package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
  149. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
  150. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +52 -51
  151. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
  152. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +1 -1
  153. package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
  154. package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
  155. package/.agents/scripts/lib/orchestration/resolve-stories.js +344 -0
  156. package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
  157. package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
  158. package/.agents/scripts/lib/orchestration/review-depth.js +126 -47
  159. package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
  160. package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +3 -13
  161. package/.agents/scripts/lib/orchestration/review-providers/native.js +1 -154
  162. package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +3 -2
  163. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
  164. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +1 -1
  165. package/.agents/scripts/lib/orchestration/review-providers/types.js +5 -4
  166. package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +1 -1
  167. package/.agents/scripts/lib/orchestration/run-epilogue.js +784 -0
  168. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +25 -1
  169. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +11 -9
  170. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +4 -4
  171. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +86 -41
  172. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +608 -152
  173. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +77 -32
  174. package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +305 -0
  175. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +1 -1
  176. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +44 -0
  177. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +37 -4
  178. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +2 -2
  179. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +275 -46
  180. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +1 -1
  181. package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
  182. package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
  183. package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
  184. package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
  185. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
  186. package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +10 -10
  187. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +28 -42
  188. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +360 -0
  189. package/.agents/scripts/lib/orchestration/story-follow-ups.js +298 -0
  190. package/.agents/scripts/lib/orchestration/story-init-remote.js +51 -0
  191. package/.agents/scripts/lib/orchestration/story-plan-state.js +33 -0
  192. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
  193. package/.agents/scripts/lib/orchestration/task-body-validator.js +60 -25
  194. package/.agents/scripts/lib/orchestration/ticket-lease.js +27 -74
  195. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +130 -75
  196. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +192 -377
  197. package/.agents/scripts/lib/orchestration/ticket-validator.js +123 -25
  198. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +14 -72
  199. package/.agents/scripts/lib/orchestration/ticketing/reads.js +45 -55
  200. package/.agents/scripts/lib/orchestration/ticketing/transition.js +66 -6
  201. package/.agents/scripts/lib/orchestration/ticketing.js +0 -1
  202. package/.agents/scripts/lib/plan-phase-cleanup.js +12 -14
  203. package/.agents/scripts/lib/planning-corpus.js +12 -281
  204. package/.agents/scripts/lib/preflight-runner.js +4 -4
  205. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
  206. package/.agents/scripts/lib/qa/qa-context-hydrator.js +5 -5
  207. package/.agents/scripts/lib/signals/index.js +4 -17
  208. package/.agents/scripts/lib/signals/read.js +35 -35
  209. package/.agents/scripts/lib/signals/schema.js +8 -11
  210. package/.agents/scripts/lib/signals/span-tree.js +7 -7
  211. package/.agents/scripts/lib/signals/write.js +0 -1
  212. package/.agents/scripts/lib/single-story/story-merged-notify.js +13 -2
  213. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
  214. package/.agents/scripts/lib/skills/parse-skill.js +16 -3
  215. package/.agents/scripts/lib/story-adjacency.js +17 -19
  216. package/.agents/scripts/lib/story-body/story-body.js +130 -75
  217. package/.agents/scripts/lib/story-plan.js +2 -4
  218. package/.agents/scripts/lib/templates/decomposer-prompts.js +51 -46
  219. package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
  220. package/.agents/scripts/lib/test-env.js +14 -1
  221. package/.agents/scripts/lib/test-tiers.js +0 -3
  222. package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +25 -39
  223. package/.agents/scripts/lib/validation-evidence.js +32 -60
  224. package/.agents/scripts/lib/wave-runner/ready-set.js +38 -12
  225. package/.agents/scripts/lib/workspace-provisioner.js +1 -1
  226. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +1 -1
  227. package/.agents/scripts/lib/worktree/lifecycle/reap.js +72 -25
  228. package/.agents/scripts/lib/worktree/lifecycle-manager.js +1 -2
  229. package/.agents/scripts/lint-issue-body.js +71 -40
  230. package/.agents/scripts/mandrel-update-preflight.js +1 -1
  231. package/.agents/scripts/notify.js +4 -3
  232. package/.agents/scripts/plan-context.js +102 -80
  233. package/.agents/scripts/plan-persist.js +230 -279
  234. package/.agents/scripts/plan-run-epilogue.js +142 -0
  235. package/.agents/scripts/post-structured-comment.js +0 -38
  236. package/.agents/scripts/pr-watch-with-update.js +43 -22
  237. package/.agents/scripts/providers/github/compose.js +0 -1
  238. package/.agents/scripts/providers/github/errors.js +0 -19
  239. package/.agents/scripts/providers/github/issues.js +13 -39
  240. package/.agents/scripts/providers/github/mappers.js +5 -12
  241. package/.agents/scripts/providers/github/sub-issues.js +0 -47
  242. package/.agents/scripts/providers/github/tickets.js +33 -156
  243. package/.agents/scripts/providers/github.js +17 -6
  244. package/.agents/scripts/resolve-stories.js +236 -0
  245. package/.agents/scripts/run-coverage.js +4 -1
  246. package/.agents/scripts/run-lint.js +2 -2
  247. package/.agents/scripts/run-verify.js +31 -2
  248. package/.agents/scripts/signals-view.js +25 -21
  249. package/.agents/scripts/single-story-close.js +178 -26
  250. package/.agents/scripts/single-story-confirm-merge.js +313 -24
  251. package/.agents/scripts/single-story-init.js +35 -30
  252. package/.agents/scripts/stories-wave-tick.js +85 -10
  253. package/.agents/scripts/story-plan.js +28 -49
  254. package/.agents/scripts/update-ticket-state.js +14 -65
  255. package/.agents/skills/core/code-review-and-quality/SKILL.md +28 -450
  256. package/.agents/skills/core/code-review-and-quality/reference.md +458 -0
  257. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +22 -315
  258. package/.agents/skills/core/debugging-and-error-recovery/reference.md +323 -0
  259. package/.agents/skills/core/diagnose-friction/SKILL.md +14 -18
  260. package/.agents/skills/core/documentation-and-adrs/SKILL.md +25 -397
  261. package/.agents/skills/core/documentation-and-adrs/reference.md +403 -0
  262. package/.agents/skills/core/gates-and-baselines/SKILL.md +12 -12
  263. package/.agents/skills/core/idea-refinement/SKILL.md +9 -9
  264. package/.agents/skills/core/scope-triage/SKILL.md +31 -172
  265. package/.agents/skills/core/security-and-hardening/SKILL.md +22 -367
  266. package/.agents/skills/core/security-and-hardening/reference.md +375 -0
  267. package/.agents/skills/skills.index.json +3 -53
  268. package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +2 -4
  269. package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +1 -1
  270. package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -3
  271. package/.agents/starter-agentrc.json +0 -5
  272. package/.agents/templates/agent-protocol.md +9 -10
  273. package/.agents/workflows/audit-architecture.md +6 -7
  274. package/.agents/workflows/audit-clean-code.md +7 -7
  275. package/.agents/workflows/audit-dependencies.md +3 -3
  276. package/.agents/workflows/audit-devops.md +3 -3
  277. package/.agents/workflows/audit-documentation.md +9 -10
  278. package/.agents/workflows/audit-lighthouse.md +11 -3
  279. package/.agents/workflows/audit-navigability.md +13 -2
  280. package/.agents/workflows/audit-performance.md +5 -6
  281. package/.agents/workflows/audit-privacy.md +3 -3
  282. package/.agents/workflows/audit-quality.md +11 -12
  283. package/.agents/workflows/audit-security.md +4 -5
  284. package/.agents/workflows/audit-seo.md +13 -3
  285. package/.agents/workflows/audit-sre.md +3 -3
  286. package/.agents/workflows/audit-to-stories.md +20 -20
  287. package/.agents/workflows/audit-ux-ui.md +10 -3
  288. package/.agents/workflows/deliver.md +177 -176
  289. package/.agents/workflows/git-cleanup.md +5 -6
  290. package/.agents/workflows/git-deliver.md +1 -1
  291. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  292. package/.agents/workflows/helpers/acceptance-self-eval.md +35 -40
  293. package/.agents/workflows/helpers/code-quality-guardrails.md +7 -7
  294. package/.agents/workflows/helpers/code-review.md +75 -196
  295. package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +83 -44
  296. package/.agents/workflows/helpers/deliver-story.md +606 -0
  297. package/.agents/workflows/helpers/diagnose.md +10 -10
  298. package/.agents/workflows/helpers/parallel-tooling.md +3 -3
  299. package/.agents/workflows/helpers/signals.md +16 -16
  300. package/.agents/workflows/helpers/worktree-lifecycle.md +66 -86
  301. package/.agents/workflows/mandrel-update.md +2 -1
  302. package/.agents/workflows/plan.md +277 -145
  303. package/.agents/workflows/qa-assist.md +27 -33
  304. package/.agents/workflows/qa-explore.md +29 -38
  305. package/.agents/workflows/qa-run.md +2 -6
  306. package/README.md +9 -8
  307. package/bin/mandrel.js +12 -1
  308. package/docs/CHANGELOG.md +70 -0
  309. package/lib/cli/registry.js +262 -19
  310. package/lib/cli/sync-agents.js +157 -0
  311. package/lib/cli/sync-commands.js +115 -6
  312. package/lib/cli/sync.js +168 -6
  313. package/lib/cli/update.js +105 -8
  314. package/lib/cli/version-helpers.js +131 -0
  315. package/lib/migrations/README.md +7 -5
  316. package/lib/migrations/index.js +12 -8
  317. package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +100 -0
  318. package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +101 -0
  319. package/package.json +2 -2
  320. package/.agents/agents/retro.md +0 -42
  321. package/.agents/personas/architect.md +0 -113
  322. package/.agents/personas/devops-engineer.md +0 -38
  323. package/.agents/personas/engineer.md +0 -33
  324. package/.agents/personas/project-manager.md +0 -114
  325. package/.agents/personas/qa-engineer.md +0 -95
  326. package/.agents/personas/security-engineer.md +0 -111
  327. package/.agents/personas/technical-writer.md +0 -101
  328. package/.agents/schemas/dispatch-manifest.json +0 -232
  329. package/.agents/schemas/epic-perf-report.schema.json +0 -89
  330. package/.agents/schemas/epic-spec.schema.json +0 -153
  331. package/.agents/schemas/lifecycle/acceptance.reconcile.failed.schema.json +0 -13
  332. package/.agents/schemas/lifecycle/acceptance.reconcile.ok.schema.json +0 -13
  333. package/.agents/schemas/lifecycle/acceptance.reconcile.skipped.schema.json +0 -13
  334. package/.agents/schemas/lifecycle/acceptance.reconcile.start.schema.json +0 -12
  335. package/.agents/schemas/lifecycle/acceptance.reconcile.waived.schema.json +0 -13
  336. package/.agents/schemas/lifecycle/epic.automerge.end.schema.json +0 -15
  337. package/.agents/schemas/lifecycle/epic.automerge.start.schema.json +0 -13
  338. package/.agents/schemas/lifecycle/epic.blocked.schema.json +0 -13
  339. package/.agents/schemas/lifecycle/epic.cleanup.end.schema.json +0 -12
  340. package/.agents/schemas/lifecycle/epic.cleanup.start.schema.json +0 -12
  341. package/.agents/schemas/lifecycle/epic.close.end.schema.json +0 -12
  342. package/.agents/schemas/lifecycle/epic.complete.schema.json +0 -13
  343. package/.agents/schemas/lifecycle/epic.finalize.end.schema.json +0 -13
  344. package/.agents/schemas/lifecycle/epic.finalize.start.schema.json +0 -12
  345. package/.agents/schemas/lifecycle/epic.merge.armed.schema.json +0 -13
  346. package/.agents/schemas/lifecycle/epic.merge.blocked.schema.json +0 -14
  347. package/.agents/schemas/lifecycle/epic.merge.confirmed.schema.json +0 -17
  348. package/.agents/schemas/lifecycle/epic.merge.ready.schema.json +0 -15
  349. package/.agents/schemas/lifecycle/epic.plan.end.schema.json +0 -18
  350. package/.agents/schemas/lifecycle/epic.plan.start.schema.json +0 -12
  351. package/.agents/schemas/lifecycle/epic.snapshot.end.schema.json +0 -16
  352. package/.agents/schemas/lifecycle/epic.snapshot.start.schema.json +0 -12
  353. package/.agents/schemas/lifecycle/epic.watch.end.schema.json +0 -29
  354. package/.agents/schemas/lifecycle/epic.watch.start.schema.json +0 -16
  355. package/.agents/schemas/lifecycle/slice.end.schema.json +0 -21
  356. package/.agents/schemas/lifecycle/slice.heartbeat.schema.json +0 -20
  357. package/.agents/schemas/lifecycle/slice.start.schema.json +0 -17
  358. package/.agents/schemas/lifecycle/story.heartbeat.schema.json +0 -20
  359. package/.agents/schemas/risk-verdict.schema.json +0 -66
  360. package/.agents/schemas/story-perf-summary.schema.json +0 -73
  361. package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
  362. package/.agents/scripts/analyze-execution.js +0 -444
  363. package/.agents/scripts/bookkeeping-reconcile.js +0 -117
  364. package/.agents/scripts/check-prepush-recovery.js +0 -90
  365. package/.agents/scripts/dispatcher.js +0 -295
  366. package/.agents/scripts/epic-audit-prepare.js +0 -497
  367. package/.agents/scripts/epic-audit-recheck.js +0 -274
  368. package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
  369. package/.agents/scripts/epic-deliver-preflight.js +0 -462
  370. package/.agents/scripts/epic-deliver-prepare.js +0 -852
  371. package/.agents/scripts/epic-execute-record-wave.js +0 -449
  372. package/.agents/scripts/epic-plan-clarity.js +0 -211
  373. package/.agents/scripts/epic-plan-healthcheck.js +0 -581
  374. package/.agents/scripts/epic-reconcile.js +0 -625
  375. package/.agents/scripts/lib/baseline-snapshot.js +0 -979
  376. package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
  377. package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
  378. package/.agents/scripts/lib/config/lifecycle.js +0 -40
  379. package/.agents/scripts/lib/config/preflight.js +0 -58
  380. package/.agents/scripts/lib/config/retro.js +0 -77
  381. package/.agents/scripts/lib/epic-merge-lock.js +0 -322
  382. package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
  383. package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
  384. package/.agents/scripts/lib/git-merge-orchestrator.js +0 -261
  385. package/.agents/scripts/lib/observability/baseline-refresh-rate.js +0 -221
  386. package/.agents/scripts/lib/observability/hook-heartbeat.js +0 -219
  387. package/.agents/scripts/lib/observability/perf-aggregator.js +0 -813
  388. package/.agents/scripts/lib/observability/perf-report-readers.js +0 -328
  389. package/.agents/scripts/lib/observability/perf-report-render.js +0 -182
  390. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +0 -270
  391. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -539
  392. package/.agents/scripts/lib/orchestration/deliver-route.js +0 -173
  393. package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
  394. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
  395. package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
  396. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
  397. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
  398. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
  399. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
  400. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
  401. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
  402. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
  403. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
  404. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
  405. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
  406. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
  407. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
  408. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/risk-verdict.js +0 -105
  409. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
  410. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
  411. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
  412. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -621
  413. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
  414. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
  415. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
  416. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
  417. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
  418. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
  419. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
  420. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
  421. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
  422. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
  423. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
  424. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
  425. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
  426. package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +0 -400
  427. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
  428. package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
  429. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
  430. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
  431. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
  432. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
  433. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
  434. package/.agents/scripts/lib/orchestration/error-journal.js +0 -139
  435. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
  436. package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
  437. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
  438. package/.agents/scripts/lib/orchestration/lifecycle/emit-slice-lifecycle.js +0 -270
  439. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
  440. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +0 -155
  441. package/.agents/scripts/lib/orchestration/lifecycle/ledger-diff.js +0 -140
  442. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -465
  443. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
  444. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
  445. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
  446. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -284
  447. package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
  448. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
  449. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
  450. package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
  451. package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
  452. package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +0 -665
  453. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
  454. package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
  455. package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
  456. package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
  457. package/.agents/scripts/lib/orchestration/plan-review-routing.js +0 -63
  458. package/.agents/scripts/lib/orchestration/planning-context-budget.js +0 -213
  459. package/.agents/scripts/lib/orchestration/planning-risk.js +0 -194
  460. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +0 -56
  461. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +0 -33
  462. package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +0 -78
  463. package/.agents/scripts/lib/orchestration/post-merge/phases/temp-cleanup.js +0 -68
  464. package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +0 -118
  465. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +0 -396
  466. package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
  467. package/.agents/scripts/lib/orchestration/preflight-cache.js +0 -187
  468. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
  469. package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
  470. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
  471. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
  472. package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
  473. package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
  474. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +0 -275
  475. package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
  476. package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
  477. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
  478. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
  479. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
  480. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
  481. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
  482. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
  483. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
  484. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
  485. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
  486. package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
  487. package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
  488. package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
  489. package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
  490. package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
  491. package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
  492. package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
  493. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
  494. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
  495. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
  496. package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
  497. package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
  498. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
  499. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
  500. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
  501. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -302
  502. package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
  503. package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
  504. package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
  505. package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
  506. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
  507. package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
  508. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
  509. package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
  510. package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
  511. package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
  512. package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
  513. package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
  514. package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
  515. package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
  516. package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
  517. package/.agents/scripts/lib/push-epic-retry.js +0 -209
  518. package/.agents/scripts/lib/spec/index.js +0 -36
  519. package/.agents/scripts/lib/spec/loader.js +0 -425
  520. package/.agents/scripts/lib/spec/state.js +0 -208
  521. package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
  522. package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
  523. package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
  524. package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
  525. package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
  526. package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
  527. package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
  528. package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
  529. package/.agents/scripts/lib/wave-runner/tick.js +0 -754
  530. package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
  531. package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
  532. package/.agents/scripts/lifecycle-emit.js +0 -510
  533. package/.agents/scripts/retro-run.js +0 -218
  534. package/.agents/scripts/slice-phase.js +0 -361
  535. package/.agents/scripts/standalone-feedback-rollup.js +0 -188
  536. package/.agents/scripts/story-close.js +0 -294
  537. package/.agents/scripts/story-init.js +0 -599
  538. package/.agents/scripts/story-phase.js +0 -369
  539. package/.agents/scripts/wave-tick.js +0 -464
  540. package/.agents/skills/core/analyze-execution/SKILL.md +0 -98
  541. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
  542. package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
  543. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
  544. package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
  545. package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
  546. package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
  547. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -383
  548. package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
  549. package/.agents/workflows/helpers/deliver-epic-reference.md +0 -547
  550. package/.agents/workflows/helpers/deliver-epic-single.md +0 -331
  551. package/.agents/workflows/helpers/deliver-epic.md +0 -998
  552. package/.agents/workflows/helpers/deliver-stories.md +0 -450
  553. package/.agents/workflows/helpers/epic-audit.md +0 -189
  554. package/.agents/workflows/helpers/epic-deliver-story.md +0 -436
  555. package/.agents/workflows/helpers/epic-testing.md +0 -125
  556. package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
  557. package/.agents/workflows/helpers/plan-epic.md +0 -353
  558. package/.agents/workflows/helpers/plan-story.md +0 -251
  559. package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
  560. package/.agents/workflows/helpers/single-story-deliver.md +0 -557
@@ -10,7 +10,9 @@
10
10
 
11
11
  import path from 'node:path';
12
12
  import { parseSprintArgs } from '../../../cli-args.js';
13
+ import { getDeliveryRouting } from '../../../config/delivery-routing.js';
13
14
  import { PROJECT_ROOT } from '../../../project-root.js';
15
+ import { isOperatorMergeReason } from './auto-merge.js';
14
16
 
15
17
  /**
16
18
  * Resolve a flag value from an explicit override, a parsed CLI arg, or a
@@ -27,34 +29,66 @@ function resolveFlag(paramValue, parsedValue, defaultValue) {
27
29
  }
28
30
 
29
31
  /**
30
- * Resolve the `waitForMerge` option: an explicit `--no-wait-merge` opt-out
31
- * always wins (preserves the pre-Story-#4428 exit shape even if a future
32
- * headless wrapper defaults to waiting); otherwise the explicit
33
- * `--wait-merge` / injected value governs, defaulting to `false` so
34
- * attended (non-headless) invocations are byte-identical to before.
32
+ * Resolve whether close lands the PR in-process (`waitForMerge`).
35
33
  *
36
- * @param {{ waitForMergeParam, noWaitForMergeParam, parsed }} raw
37
- * @returns {boolean}
34
+ * Called by `runSingleStoryClose` **after** config resolution and the
35
+ * auto-merge phase, because two of its four inputs are not knowable at
36
+ * parse time: the resolved config (whose `cwd` this parse produces) and the
37
+ * actual arm outcome. Resolving it here — once, where every input exists —
38
+ * is what makes `delivery.routing.closeAndLand` governable at all.
39
+ *
40
+ * Precedence, highest first:
41
+ * 1. `--no-wait-merge` / injected opt-out — always wins.
42
+ * 2. **Operator owns the merge** (`--no-auto-merge`, or
43
+ * `delivery.ci.autoMerge: "strict"`): the PR was deliberately left
44
+ * un-armed, so there is nothing for close to land. Resting at
45
+ * `agent::closing` for the human IS the documented contract for both
46
+ * surfaces; waiting would only burn the poll budget and then block a
47
+ * perfectly healthy Story. An explicit `--wait-merge` cannot override
48
+ * this — you cannot land-in-one-close a PR you refused to arm — so the
49
+ * caller is told rather than silently ignored.
50
+ * 3. Explicit `--wait-merge` / injected boolean.
51
+ * 4. `delivery.routing.closeAndLand` (framework default `true`).
52
+ *
53
+ * @param {{
54
+ * waitForMergeExplicit?: boolean,
55
+ * noWaitForMerge?: boolean,
56
+ * config?: object|null,
57
+ * autoMergeReason?: string|null,
58
+ * }} args
59
+ * @returns {{ waitForMerge: boolean, reason: 'opt-out-flag'|'operator-merge'|'explicit-flag'|'config-close-and-land' }}
38
60
  */
39
- function resolveWaitForMerge({
40
- waitForMergeParam,
41
- noWaitForMergeParam,
42
- parsed,
43
- }) {
44
- const optedOut = resolveFlag(
45
- noWaitForMergeParam,
46
- parsed.noWaitForMerge,
47
- false,
48
- );
49
- if (optedOut) return false;
50
- return resolveFlag(waitForMergeParam, parsed.waitForMerge, false);
61
+ export function resolveWaitForMerge({
62
+ waitForMergeExplicit,
63
+ noWaitForMerge = false,
64
+ config = null,
65
+ autoMergeReason = null,
66
+ } = {}) {
67
+ if (noWaitForMerge) {
68
+ return { waitForMerge: false, reason: 'opt-out-flag' };
69
+ }
70
+ if (isOperatorMergeReason(autoMergeReason)) {
71
+ return { waitForMerge: false, reason: 'operator-merge' };
72
+ }
73
+ if (typeof waitForMergeExplicit === 'boolean') {
74
+ return { waitForMerge: waitForMergeExplicit, reason: 'explicit-flag' };
75
+ }
76
+ return {
77
+ waitForMerge: getDeliveryRouting(config).closeAndLand,
78
+ reason: 'config-close-and-land',
79
+ };
51
80
  }
52
81
 
53
82
  /**
54
83
  * Parse and resolve all CLI / injection options for `runSingleStoryClose`.
55
84
  *
56
- * @param {{ storyIdParam, cwdParam, skipValidationParam, skipSyncParam, noAutoMergeParam, noFullScopeCrapParam, waitForMergeParam, noWaitForMergeParam }} raw
57
- * @returns {{ storyId, cwd, skipValidation, skipSync, noAutoMerge, noFullScopeCrap, waitForMerge }}
85
+ * `waitForMerge` is deliberately **not** resolved here see
86
+ * {@link resolveWaitForMerge}. This returns the raw operator intent
87
+ * (`waitForMergeExplicit` / `noWaitForMerge`) for the runner to resolve once
88
+ * the config and the arm outcome exist.
89
+ *
90
+ * @param {{ storyIdParam, cwdParam, skipValidationParam, skipSyncParam, noAutoMergeParam, waitForMergeParam, noWaitForMergeParam, maxWaitSecondsParam }} raw
91
+ * @returns {{ storyId, cwd, skipValidation, skipSync, noAutoMerge, waitForMergeExplicit, noWaitForMerge, maxWaitSeconds }}
58
92
  */
59
93
  export function parseCloseOptions({
60
94
  storyIdParam,
@@ -62,9 +96,9 @@ export function parseCloseOptions({
62
96
  skipValidationParam,
63
97
  skipSyncParam,
64
98
  noAutoMergeParam,
65
- noFullScopeCrapParam,
66
99
  waitForMergeParam,
67
100
  noWaitForMergeParam,
101
+ maxWaitSecondsParam,
68
102
  }) {
69
103
  const parsed =
70
104
  storyIdParam !== undefined
@@ -74,14 +108,26 @@ export function parseCloseOptions({
74
108
  skipValidation: !!skipValidationParam,
75
109
  skipSync: !!skipSyncParam,
76
110
  noAutoMerge: !!noAutoMergeParam,
77
- noFullScopeCrap: !!noFullScopeCrapParam,
78
- waitForMerge: !!waitForMergeParam,
111
+ // Preserve undefined so resolveWaitForMerge can apply the
112
+ // closeAndLand config default when neither flag was injected.
113
+ waitForMerge: waitForMergeParam,
79
114
  noWaitForMerge: !!noWaitForMergeParam,
115
+ maxWaitSeconds: maxWaitSecondsParam,
80
116
  }
81
117
  : parseSprintArgs();
118
+ const waitForMergeExplicit = waitForMergeParam ?? parsed.waitForMerge;
119
+ const maxWaitSeconds = maxWaitSecondsParam ?? parsed.maxWaitSeconds;
82
120
  return {
83
121
  storyId: parsed.storyId,
84
122
  cwd: path.resolve(cwdParam ?? parsed.cwd ?? PROJECT_ROOT),
123
+ // `undefined` when unsupplied — the merge wait then reads
124
+ // `delivery.mergeWatch.maxWaitSeconds`. A per-run override exists so a
125
+ // headless caller with no host tool-invocation ceiling can keep
126
+ // single-block semantics without editing the consumer's config.
127
+ maxWaitSeconds:
128
+ Number.isInteger(maxWaitSeconds) && maxWaitSeconds > 0
129
+ ? maxWaitSeconds
130
+ : undefined,
85
131
  skipValidation: resolveFlag(
86
132
  skipValidationParam,
87
133
  parsed.skipValidation,
@@ -89,15 +135,14 @@ export function parseCloseOptions({
89
135
  ),
90
136
  skipSync: resolveFlag(skipSyncParam, parsed.skipSync, false),
91
137
  noAutoMerge: resolveFlag(noAutoMergeParam, parsed.noAutoMerge, false),
92
- noFullScopeCrap: resolveFlag(
93
- noFullScopeCrapParam,
94
- parsed.noFullScopeCrap,
138
+ waitForMergeExplicit:
139
+ typeof waitForMergeExplicit === 'boolean'
140
+ ? waitForMergeExplicit
141
+ : undefined,
142
+ noWaitForMerge: resolveFlag(
143
+ noWaitForMergeParam,
144
+ parsed.noWaitForMerge,
95
145
  false,
96
146
  ),
97
- waitForMerge: resolveWaitForMerge({
98
- waitForMergeParam,
99
- noWaitForMergeParam,
100
- parsed,
101
- }),
102
147
  };
103
148
  }
@@ -0,0 +1,305 @@
1
+ /**
2
+ * phases/post-land.js — the script-owned land tail (Story #4543).
3
+ *
4
+ * Everything after "the PR merged and the Story is `agent::done`" used to be
5
+ * prose in `helpers/deliver-story.md`: Step 5.5 resync, Step 6 cleanup, and
6
+ * follow-up capture, each a separate CLI an agent may or may not have run.
7
+ * Follow-up capture was the sharpest edge — it lived only on the standalone
8
+ * `single-story-confirm-merge.js` path, which close-and-land (the DEFAULT)
9
+ * is explicitly told to skip, so per-Story follow-ups were captured *never*
10
+ * on the default path, and a belated manual confirm could not backfill (the
11
+ * Story is already `agent::done`, so confirm short-circuits `noop` and the
12
+ * capture's `action === 'done'` gate never opens).
13
+ *
14
+ * This module folds all four steps into one phase both landing surfaces
15
+ * reach — the in-close wait (`phases/confirm-merge.js`) and the standalone
16
+ * `single-story-confirm-merge.js` CLI — so the two paths cannot diverge and
17
+ * "landed" means the whole tail ran.
18
+ *
19
+ * **Per-step booleans, not an aggregate.** {@link runPostLandTail} reports
20
+ * each step's outcome individually. That is not bookkeeping fastidiousness:
21
+ * the worktree-reap defect this repo fixed existed because a phase reported
22
+ * an outcome it never checked, and a single `tailOk: true` bit invites that
23
+ * class of bug straight back. A degraded step is visible in the terminal
24
+ * envelope without failing an otherwise-healthy land.
25
+ *
26
+ * **Never throws.** The merge already landed — the code is on the base
27
+ * branch. Failing the land because a Projects v2 mutation flaked would
28
+ * report a false negative about work that is demonstrably done. Every step
29
+ * is best-effort and records its own reason.
30
+ */
31
+
32
+ import { gitSpawn as defaultGitSpawn } from '../../../git-utils.js';
33
+ import { Logger } from '../../../Logger.js';
34
+ import {
35
+ executeFastForward as defaultExecuteFastForward,
36
+ planFastForward as defaultPlanFastForward,
37
+ } from '../../git-cleanup/phases/fast-forward.js';
38
+ import { reassertStatusColumn as defaultReassertStatusColumn } from '../../reassert-status-column.js';
39
+ import { captureStoryFollowUps as defaultCaptureStoryFollowUps } from '../../story-follow-ups.js';
40
+
41
+ /**
42
+ * Run one tail step, converting any throw into a `false` + reason. Keeps
43
+ * each step's own body free of defensive boilerplate while guaranteeing the
44
+ * module-level never-throws contract.
45
+ *
46
+ * @template T
47
+ * @param {() => Promise<{ ok: boolean, detail?: string|null }>} run
48
+ * @param {{ name: string, progress?: Function }} ctx
49
+ * @returns {Promise<{ ok: boolean, detail: string|null }>}
50
+ */
51
+ async function step(run, { name, progress }) {
52
+ try {
53
+ const outcome = await run();
54
+ if (!outcome.ok) {
55
+ progress?.(
56
+ 'POST-LAND',
57
+ `⚠️ ${name} degraded (land stands): ${outcome.detail ?? 'no detail'}`,
58
+ );
59
+ }
60
+ return { ok: Boolean(outcome.ok), detail: outcome.detail ?? null };
61
+ } catch (err) {
62
+ const detail = String(err?.message ?? err);
63
+ Logger.warn(`[post-land] ${name} threw (land stands): ${detail}`);
64
+ progress?.('POST-LAND', `⚠️ ${name} threw (land stands): ${detail}`);
65
+ return { ok: false, detail };
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Capture the Story's follow-ups from its friction signal stream.
71
+ *
72
+ * Calls `captureStoryFollowUps` **directly** rather than through the
73
+ * `captureFollowUpsAfterConfirm` action-gate wrapper: by the time the tail
74
+ * runs, the merge is already confirmed, so re-deriving that fact from a
75
+ * confirmation envelope's `action` field is the exact coupling that made
76
+ * the default path skip capture entirely.
77
+ */
78
+ async function stepFollowUps({
79
+ storyId,
80
+ provider,
81
+ config,
82
+ cwd,
83
+ progress,
84
+ captureStoryFollowUpsFn,
85
+ }) {
86
+ const result = await captureStoryFollowUpsFn({
87
+ storyId,
88
+ provider,
89
+ config,
90
+ cwd,
91
+ progress,
92
+ });
93
+ return {
94
+ ok: result?.ok === true,
95
+ detail: result?.ok === true ? null : (result?.reason ?? 'capture-failed'),
96
+ };
97
+ }
98
+
99
+ /**
100
+ * Re-assert the Projects v2 Status column against the bot's late write.
101
+ *
102
+ * A `skipped` envelope (`no-project`, `not-on-project`, `no-meta`) is a
103
+ * **success**: the board the helper would defend does not exist, so there
104
+ * is nothing to get wrong. Only a genuine `drifted` outcome — the helper
105
+ * fired, polled, and still lost — degrades the step.
106
+ */
107
+ async function stepStatusResync({
108
+ storyId,
109
+ provider,
110
+ config,
111
+ progress,
112
+ reassertStatusColumnFn,
113
+ }) {
114
+ const outcome = await reassertStatusColumnFn({
115
+ provider,
116
+ ticketId: storyId,
117
+ config,
118
+ logger: {
119
+ info: (m) => progress?.('POST-LAND', m),
120
+ warn: (m) => progress?.('POST-LAND', `⚠️ ${m}`),
121
+ },
122
+ });
123
+ if (outcome?.status === 'synced' || outcome?.status === 'skipped') {
124
+ return { ok: true, detail: null };
125
+ }
126
+ return {
127
+ ok: false,
128
+ detail: `status column ${outcome?.status ?? 'unknown'} (target=${outcome?.column ?? 'n/a'}, attempts=${outcome?.attempts ?? 0})`,
129
+ };
130
+ }
131
+
132
+ /**
133
+ * Reap the local `story-<id>` ref. GitHub deletes the *remote* branch on
134
+ * squash-merge (`--delete-branch`), but the local ref lingers in the main
135
+ * checkout until something prunes it.
136
+ *
137
+ * An absent ref is a success, not a failure — the sweep is idempotent and
138
+ * a previous run (or the init-time merged-sweep) may have already reaped it.
139
+ */
140
+ async function stepRefCleanup({ cwd, storyBranch, progress, gitSpawnFn }) {
141
+ const exists = gitSpawnFn(
142
+ cwd,
143
+ 'show-ref',
144
+ '--verify',
145
+ '--quiet',
146
+ `refs/heads/${storyBranch}`,
147
+ );
148
+ if (exists.status !== 0) {
149
+ progress?.('POST-LAND', `⏭ local ${storyBranch} already absent.`);
150
+ return { ok: true, detail: null };
151
+ }
152
+ const del = gitSpawnFn(cwd, 'branch', '-D', storyBranch);
153
+ if (del.status !== 0) {
154
+ return { ok: false, detail: `git branch -D failed: ${del.stderr ?? ''}` };
155
+ }
156
+ progress?.('POST-LAND', `🧹 reaped local ${storyBranch}.`);
157
+ return { ok: true, detail: null };
158
+ }
159
+
160
+ /**
161
+ * Fast-forward local `baseBranch` so the next Story seeds from the tip that
162
+ * now contains this merge. Reuses the same planner/executor pair
163
+ * `single-story-init.js` imports (rather than shelling out to
164
+ * `/git-cleanup`), which is the established in-process composition pattern.
165
+ *
166
+ * `already-up-to-date` is a success. A dirty tree is a legitimate, expected
167
+ * skip on a shared checkout — another worker is mid-flight — so it degrades
168
+ * the step's report without pretending the base moved.
169
+ */
170
+ async function stepBaseFastForward({
171
+ cwd,
172
+ baseBranch,
173
+ progress,
174
+ planFastForwardFn,
175
+ executeFastForwardFn,
176
+ }) {
177
+ const plan = planFastForwardFn({ cwd, baseBranch });
178
+ if (!plan.runnable && plan.reason === 'already-up-to-date') {
179
+ progress?.('POST-LAND', `⏭ local ${baseBranch} already up to date.`);
180
+ return { ok: true, detail: null };
181
+ }
182
+ const ff = executeFastForwardFn({
183
+ cwd,
184
+ baseBranch,
185
+ plan,
186
+ logger: {
187
+ info: (m) => progress?.('POST-LAND', m),
188
+ warn: (m) => progress?.('POST-LAND', `⚠️ ${m}`),
189
+ },
190
+ });
191
+ if (ff.applied) {
192
+ progress?.(
193
+ 'POST-LAND',
194
+ `⏩ fast-forwarded ${baseBranch} by ${ff.behind} commit(s).`,
195
+ );
196
+ return { ok: true, detail: null };
197
+ }
198
+ return {
199
+ ok: false,
200
+ detail: `fast-forward skipped: ${ff.reason ?? plan.reason ?? 'unknown'}`,
201
+ };
202
+ }
203
+
204
+ /**
205
+ * Run the whole post-land tail. Never throws.
206
+ *
207
+ * Steps run **sequentially** and in this order deliberately: follow-up
208
+ * capture and the status resync touch GitHub, while the ref reap and the
209
+ * fast-forward mutate the local checkout — and the fast-forward must run
210
+ * after the ref reap so `git branch -D` is not fighting a checkout that just
211
+ * moved HEAD.
212
+ *
213
+ * @param {object} args
214
+ * @param {number} args.storyId
215
+ * @param {string} args.storyBranch
216
+ * @param {string} args.baseBranch
217
+ * @param {string} args.cwd The MAIN checkout (never the worktree).
218
+ * @param {object} args.provider
219
+ * @param {object} [args.config]
220
+ * @param {(tag: string, msg: string) => void} [args.progress]
221
+ * @param {Function} [args.captureStoryFollowUpsFn] Test seam.
222
+ * @param {Function} [args.reassertStatusColumnFn] Test seam.
223
+ * @param {Function} [args.gitSpawnFn] Test seam.
224
+ * @param {Function} [args.planFastForwardFn] Test seam.
225
+ * @param {Function} [args.executeFastForwardFn] Test seam.
226
+ * @returns {Promise<{ followUps: boolean, statusResync: boolean, refCleanup: boolean, baseFastForward: boolean, details: Record<string, string|null> }>}
227
+ */
228
+ export async function runPostLandTail({
229
+ storyId,
230
+ storyBranch,
231
+ baseBranch,
232
+ cwd,
233
+ provider,
234
+ config,
235
+ progress,
236
+ captureStoryFollowUpsFn = defaultCaptureStoryFollowUps,
237
+ reassertStatusColumnFn = defaultReassertStatusColumn,
238
+ gitSpawnFn = defaultGitSpawn,
239
+ planFastForwardFn = defaultPlanFastForward,
240
+ executeFastForwardFn = defaultExecuteFastForward,
241
+ }) {
242
+ progress?.('POST-LAND', `🧾 Running land tail for Story #${storyId}...`);
243
+
244
+ const followUps = await step(
245
+ () =>
246
+ stepFollowUps({
247
+ storyId,
248
+ provider,
249
+ config,
250
+ cwd,
251
+ progress,
252
+ captureStoryFollowUpsFn,
253
+ }),
254
+ { name: 'follow-up capture', progress },
255
+ );
256
+ const statusResync = await step(
257
+ () =>
258
+ stepStatusResync({
259
+ storyId,
260
+ provider,
261
+ config,
262
+ progress,
263
+ reassertStatusColumnFn,
264
+ }),
265
+ { name: 'status-column resync', progress },
266
+ );
267
+ const refCleanup = await step(
268
+ () => stepRefCleanup({ cwd, storyBranch, progress, gitSpawnFn }),
269
+ { name: 'local ref cleanup', progress },
270
+ );
271
+ const baseFastForward = await step(
272
+ () =>
273
+ stepBaseFastForward({
274
+ cwd,
275
+ baseBranch,
276
+ progress,
277
+ planFastForwardFn,
278
+ executeFastForwardFn,
279
+ }),
280
+ { name: 'base fast-forward', progress },
281
+ );
282
+
283
+ const tail = {
284
+ followUps: followUps.ok,
285
+ statusResync: statusResync.ok,
286
+ refCleanup: refCleanup.ok,
287
+ baseFastForward: baseFastForward.ok,
288
+ details: {
289
+ followUps: followUps.detail,
290
+ statusResync: statusResync.detail,
291
+ refCleanup: refCleanup.detail,
292
+ baseFastForward: baseFastForward.detail,
293
+ },
294
+ };
295
+ const degraded = Object.entries(tail)
296
+ .filter(([k, v]) => k !== 'details' && v === false)
297
+ .map(([k]) => k);
298
+ progress?.(
299
+ 'POST-LAND',
300
+ degraded.length === 0
301
+ ? `✅ Land tail complete for Story #${storyId} (all steps ok).`
302
+ : `✅ Land tail complete for Story #${storyId} — degraded: ${degraded.join(', ')} (the merge stands).`,
303
+ );
304
+ return tail;
305
+ }
@@ -95,7 +95,7 @@ export async function ensurePullRequestWith({
95
95
  const body = [
96
96
  `Closes #${storyId}`,
97
97
  '',
98
- `_Auto-opened by \`/single-story-deliver\`._`,
98
+ `_Auto-opened by \`/deliver\`._`,
99
99
  ].join('\n');
100
100
  try {
101
101
  const createResult = await gh.pr.create([
@@ -0,0 +1,44 @@
1
+ import { Logger } from '../../../Logger.js';
2
+ import {
3
+ STATE_LABELS,
4
+ transitionTicketState,
5
+ upsertStructuredComment,
6
+ } from '../../ticketing.js';
7
+
8
+ /**
9
+ * Record a critical code-review halt as authoritative blocked state before
10
+ * close releases the Story lease and returns non-zero.
11
+ */
12
+ export async function handleCriticalReviewBlock({
13
+ provider,
14
+ storyId,
15
+ prUrl,
16
+ criticalCount,
17
+ }) {
18
+ const body = [
19
+ '### Code review blocked delivery',
20
+ '',
21
+ `The Story-scope review reported **${criticalCount} critical blocker(s)** on ${prUrl}.`,
22
+ 'Remediate the posted findings, then re-run `/deliver`.',
23
+ ].join('\n');
24
+ try {
25
+ await upsertStructuredComment(provider, storyId, 'friction', body);
26
+ } catch (err) {
27
+ Logger.warn(
28
+ `[single-story-close] failed to post review-block friction: ${err?.message ?? err}`,
29
+ );
30
+ }
31
+ // Story #4539 — route through the canonical mutator rather than writing
32
+ // labels directly. A bare `provider.updateTicket` skips the Projects v2
33
+ // column sync (Story #2548), leaving the board on the Story's prior
34
+ // status. That is benign today only because agent::blocked and
35
+ // agent::executing happen to map to the same column — a coincidence, not
36
+ // a design, and exactly how the next drift gets in.
37
+ try {
38
+ await transitionTicketState(provider, storyId, STATE_LABELS.BLOCKED, {});
39
+ } catch (err) {
40
+ Logger.warn(
41
+ `[single-story-close] failed to block Story after critical review: ${err?.message ?? err}`,
42
+ );
43
+ }
44
+ }
@@ -7,6 +7,16 @@
7
7
  * reports success because the operator can clean stale worktrees out of
8
8
  * band.
9
9
  *
10
+ * **Report what happened, not what was attempted** (Story #4539). This
11
+ * phase used to set `worktreeReaped = true` and log "🧹 Reaped worktree"
12
+ * on any non-throwing call — without reading the returned envelope. Since
13
+ * `reap` signals refusal by *returning* `{ removed: false, reason }`
14
+ * rather than throwing, and a v2-era precondition refused every
15
+ * `story-<id>` worktree outright, the result was that no close ever
16
+ * actually reaped and every close said it did. Best-effort means the close
17
+ * still succeeds on refusal; it does not mean the close may claim an
18
+ * outcome it never checked.
19
+ *
10
20
  * Also clears the trace-hook env vars so subsequent tooling falls back to
11
21
  * the no-op branch instead of pointing at a (now-reaped) worktree.
12
22
  */
@@ -26,7 +36,8 @@ import { WorktreeManager as DefaultWorktreeManager } from '../../../worktree-man
26
36
  * wtIsolation: object|undefined,
27
37
  * progress: (tag: string, msg: string) => void,
28
38
  * }} args
29
- * @returns {Promise<boolean>} true when reap completed
39
+ * @returns {Promise<boolean>} `true` only when the worktree was actually
40
+ * removed — never merely because the call did not throw.
30
41
  */
31
42
  export async function reapWorktreePhase({
32
43
  cwd,
@@ -49,9 +60,31 @@ export async function reapWorktreePhase({
49
60
  error: (m) => Logger.error(`[single-story-close] ${m}`),
50
61
  },
51
62
  });
52
- await wm.reap(storyId);
53
- worktreeReaped = true;
54
- progress('WORKTREE', `🧹 Reaped worktree for story-${storyId}.`);
63
+ // Deliberately NO base ref. This phase runs BEFORE the merge (see
64
+ // `../runner.js` — reap precedes the confirm phase), so "is this work
65
+ // integrated into the base?" is the wrong question: the answer is
66
+ // always no, and supplying a ref would activate `isSafeToRemove`'s
67
+ // merge-reachability gate and refuse every reap with
68
+ // `unmerged-commits` — trading one always-refuse precondition for
69
+ // another.
70
+ //
71
+ // What actually makes the reap safe here is that close has already
72
+ // pushed `story-<id>` to origin and opened the PR, so the work is
73
+ // durable off-machine; and `isSafeToRemove` still refuses a dirty
74
+ // tree (`uncommitted-changes`), which is the check that protects
75
+ // unsaved work. Refusal is signalled by the returned envelope rather
76
+ // than by throwing — so read it.
77
+ const result = await wm.reap(storyId);
78
+ worktreeReaped = result?.removed === true;
79
+ if (worktreeReaped) {
80
+ progress('WORKTREE', `🧹 Reaped worktree for story-${storyId}.`);
81
+ } else {
82
+ progress(
83
+ 'WORKTREE',
84
+ `⚠️ Worktree for story-${storyId} not reaped (${result?.reason ?? 'unknown reason'}) — ` +
85
+ `${worktreePath} left in place for the next sweep.`,
86
+ );
87
+ }
55
88
  } catch (err) {
56
89
  Logger.error(
57
90
  `[single-story-close] ⚠️ Failed to reap worktree: ${err?.message ?? err}`,
@@ -232,7 +232,7 @@ export function formatWrongTreeFinding({ storyId, strayFiles, worktreePath }) {
232
232
  `**Recovery:** relocate these edits into the worktree (re-apply them under ` +
233
233
  `\`${worktreePath}\`), restore the main checkout ` +
234
234
  `(\`git -C <main-repo> checkout -- <files>\`), then re-run ` +
235
- `\`/single-story-deliver\`.`
235
+ `\`/deliver ${storyId}\`.`
236
236
  );
237
237
  }
238
238
 
@@ -307,7 +307,7 @@ async function abortWrongTree({
307
307
  `diff-path set while the worktree (${worktreePath}) is the active work ` +
308
308
  `tree. Close aborted to avoid an empty-diff PR. Stray files: ` +
309
309
  `${strayFiles.join(', ')}. Relocate the edits into the worktree, ` +
310
- `restore the main checkout, then re-run /single-story-deliver.`,
310
+ `restore the main checkout, then re-run /deliver ${storyId}.`,
311
311
  );
312
312
  }
313
313