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
@@ -12,8 +12,8 @@
12
12
  * Emits a single `audit-to-stories-plan.json` envelope to --out (or
13
13
  * stdout when --json is set).
14
14
  *
15
- * --emit-epic-seed --plan <plan.json> --out <path>
16
- * Read the plan envelope from disk, render the `/plan --idea`
15
+ * --emit-plan-seed --plan <plan.json> --out <path>
16
+ * Read the plan envelope from disk, render the `/plan --seed`
17
17
  * seed markdown, persist to --out.
18
18
  *
19
19
  * --emit-stories --plan <plan.json>
@@ -37,7 +37,7 @@ import { classifyGroupsAgainstGitHub } from './lib/audit-to-stories/dedupe-again
37
37
  import { withFingerprints } from './lib/audit-to-stories/finding-adapter.js';
38
38
  import { groupFindings } from './lib/audit-to-stories/group-findings.js';
39
39
  import { parseAuditReports } from './lib/audit-to-stories/parse-audit-md.js';
40
- import { buildEpicSeedMarkdown } from './lib/audit-to-stories/seed-epic-from-findings.js';
40
+ import { buildPlanSeedMarkdown } from './lib/audit-to-stories/seed-from-findings.js';
41
41
  import { runAsCli } from './lib/cli-utils.js';
42
42
  import { Logger } from './lib/Logger.js';
43
43
  import { parse as parseStoryBody } from './lib/story-body/story-body.js';
@@ -291,7 +291,7 @@ async function main() {
291
291
  args: process.argv.slice(2),
292
292
  options: {
293
293
  scan: { type: 'boolean' },
294
- 'emit-epic-seed': { type: 'boolean' },
294
+ 'emit-plan-seed': { type: 'boolean' },
295
295
  'emit-stories': { type: 'boolean' },
296
296
  glob: { type: 'string' },
297
297
  severity: { type: 'string' },
@@ -315,9 +315,9 @@ async function main() {
315
315
  return;
316
316
  }
317
317
 
318
- if (values['emit-epic-seed']) {
318
+ if (values['emit-plan-seed']) {
319
319
  const plan = loadPlan(values.plan);
320
- const md = buildEpicSeedMarkdown({
320
+ const md = buildPlanSeedMarkdown({
321
321
  groups: plan.groups ?? [],
322
322
  findings: plan.findings ?? [],
323
323
  sourceReports: plan.sourceReports ?? [],
@@ -346,7 +346,7 @@ async function main() {
346
346
  }
347
347
 
348
348
  throw new Error(
349
- 'Usage: node audit-to-stories.js (--scan | --emit-epic-seed | --emit-stories) [options]',
349
+ 'Usage: node audit-to-stories.js (--scan | --emit-plan-seed | --emit-stories) [options]',
350
350
  );
351
351
  }
352
352
 
@@ -72,7 +72,7 @@ Options:
72
72
  * returns the sweep envelope so no caller can be blocked by a failure.
73
73
  *
74
74
  * DI-friendly: `injectedConfig` / `injectedProvider` let a caller (e.g.
75
- * `epic-deliver-prepare.js`) reuse an already-resolved config + provider,
75
+ * `single-story-init.js`) reuse an already-resolved config + provider,
76
76
  * and `injectedSweep` swaps the engine for unit tests.
77
77
  *
78
78
  * @param {{
@@ -45,8 +45,8 @@
45
45
  * and custom fields. Off by default — the project
46
46
  * board object is still created when a project
47
47
  * name is supplied, but decoration is skipped.
48
- * --with-issue-forms Opt-in: generate .github/ISSUE_TEMPLATE/story.yml
49
- * and epic.yml. Off by default.
48
+ * --with-issue-forms Opt-in: generate .github/ISSUE_TEMPLATE/story.yml.
49
+ * Off by default.
50
50
  * --reap-conflicting-workflows Delete Projects V2 built-in workflows that
51
51
  * race against the orchestrator (destructive)
52
52
  * --help Print this help
@@ -112,7 +112,7 @@ Flags:
112
112
  --with-project-board Opt-in: provision the Projects V2 Status field
113
113
  and custom fields (default: off — prompted y/N).
114
114
  --with-issue-forms Opt-in: generate .github/ISSUE_TEMPLATE/story.yml
115
- and epic.yml (default: off — prompted y/N).
115
+ (default: off — prompted y/N).
116
116
  --reap-conflicting-workflows Delete Projects V2 built-in workflows that
117
117
  race against the orchestrator (destructive)
118
118
  --help Print this help
@@ -9,12 +9,18 @@
9
9
  * misconfigured knip installation cannot block CI when we have no current
10
10
  * snapshot to compare against.
11
11
  *
12
+ * Story #4575 adds the **production pass** (`--production`), the test-only-
13
+ * importer discount: default mode counts a test as an importer, so
14
+ * production-dead code hides behind its own tests. See
15
+ * `lib/dead-exports-mode.js` for why the two passes carry separate baselines.
16
+ *
12
17
  * Contract:
13
- * - Reads the committed baseline at `baselines/dead-exports.json`
14
- * (override with `--baseline <path>`). Envelope shape:
18
+ * - Reads the committed baseline at `baselines/dead-exports.json` — or
19
+ * `baselines/dead-exports-production.json` under `--production`
20
+ * (override either with `--baseline <path>`). Envelope shape:
15
21
  * { $schema, kernelVersion, generatedAt, rows: [{ file, symbol }] }
16
- * - Spawns `npx knip --reporter json --no-progress`, parses stdout,
17
- * extracts `{ file, symbol }` rows from `issues[].exports[]`.
22
+ * - Spawns `npx knip --reporter json --no-progress` (plus `--production`),
23
+ * parses stdout, extracts `{ file, symbol }` rows from `issues[].exports[]`.
18
24
  * - Diffs current vs. baseline by `(file, symbol)` identity.
19
25
  * - Prints `+ <file>: <symbol>` for each added dead export and
20
26
  * `- <file>: <symbol>` for each removed one, then a summary line.
@@ -25,24 +31,30 @@
25
31
  * Knip spawn/parse failure exits 0 (advisory) with a stderr warning.
26
32
  */
27
33
 
28
- import { spawnSync } from 'node:child_process';
29
34
  import fs from 'node:fs';
30
35
  import path from 'node:path';
31
36
  import process from 'node:process';
32
37
  import { runAsCli } from './lib/cli-utils.js';
38
+ import {
39
+ extractRowsFromKnip,
40
+ readKnipOutput,
41
+ runKnip,
42
+ } from './lib/dead-exports-knip.js';
43
+ import { resolveDeadExportsMode } from './lib/dead-exports-mode.js';
33
44
 
34
45
  /**
35
- * Parse argv for `--baseline <path>`, `--json`, and `--knip-output <path>`.
36
- * `--knip-output` is a test seam: pass a pre-captured knip JSON file instead
37
- * of spawning knip. Exported so unit tests can pin the parser.
46
+ * Parse argv for `--baseline <path>`, `--json`, `--knip-output <path>`, and
47
+ * `--production`. `--knip-output` is a test seam: pass a pre-captured knip JSON
48
+ * file instead of spawning knip. Exported so unit tests can pin the parser.
38
49
  *
39
50
  * @param {string[]} argv
40
- * @returns {{ baselinePath: string | null, json: boolean, knipOutputPath: string | null }}
51
+ * @returns {{ baselinePath: string | null, json: boolean, knipOutputPath: string | null, production: boolean }}
41
52
  */
42
53
  export function parseArgv(argv = []) {
43
54
  let baselinePath = null;
44
55
  let json = false;
45
56
  let knipOutputPath = null;
57
+ let production = false;
46
58
  for (let i = 0; i < argv.length; i += 1) {
47
59
  const a = argv[i];
48
60
  if (a === '--baseline') {
@@ -53,6 +65,8 @@ export function parseArgv(argv = []) {
53
65
  }
54
66
  } else if (a === '--json') {
55
67
  json = true;
68
+ } else if (a === '--production') {
69
+ production = true;
56
70
  } else if (a === '--knip-output') {
57
71
  const next = argv[i + 1];
58
72
  if (next && !next.startsWith('--')) {
@@ -61,7 +75,7 @@ export function parseArgv(argv = []) {
61
75
  }
62
76
  }
63
77
  }
64
- return { baselinePath, json, knipOutputPath };
78
+ return { baselinePath, json, knipOutputPath, production };
65
79
  }
66
80
 
67
81
  /**
@@ -84,36 +98,6 @@ export function loadBaseline(baselinePath) {
84
98
  }
85
99
  }
86
100
 
87
- /**
88
- * Pure helper: normalize knip's `--reporter json` output into a flat array of
89
- * `{ file, symbol }` rows. Knip emits `{ issues: [{ file, exports: [{ name, ... }], ... }, ...] }`.
90
- * Only `exports` rows are mapped — the dead-export ratchet ignores file-level,
91
- * dependency-level, and duplicate-level issues (knip surfaces those via
92
- * separate `rules` keys).
93
- *
94
- * @param {unknown} knipEnvelope The parsed knip JSON report.
95
- * @returns {Array<{ file: string, symbol: string }>}
96
- */
97
- export function extractRowsFromKnip(knipEnvelope) {
98
- const rows = [];
99
- if (!knipEnvelope || typeof knipEnvelope !== 'object') return rows;
100
- const issues = Array.isArray(knipEnvelope.issues) ? knipEnvelope.issues : [];
101
- for (const issue of issues) {
102
- const file = issue?.file;
103
- if (typeof file !== 'string' || file.length === 0) continue;
104
- const exports_ = Array.isArray(issue.exports) ? issue.exports : [];
105
- for (const e of exports_) {
106
- const symbol =
107
- (e && typeof e.name === 'string' && e.name) ||
108
- (e && typeof e.symbol === 'string' && e.symbol) ||
109
- null;
110
- if (!symbol) continue;
111
- rows.push({ file, symbol });
112
- }
113
- }
114
- return rows;
115
- }
116
-
117
101
  /**
118
102
  * Pure helper: diff two `{ file, symbol }` row sets. Returns `added` (in
119
103
  * current but not baseline) and `removed` (in baseline but not current).
@@ -151,75 +135,24 @@ export function diffRows(baselineRows, currentRows) {
151
135
  * "no drift" signal. When added rows are present the summary includes a
152
136
  * "(gate fail)" marker so the ratchet violation is visible in CI output.
153
137
  *
138
+ * `label` distinguishes the two passes in CI logs, which run back to back and
139
+ * would otherwise emit two identical-looking summaries.
140
+ *
154
141
  * @param {{ added: Array, removed: Array }} diff
142
+ * @param {string} [label='dead-exports']
155
143
  * @returns {string}
156
144
  */
157
- export function renderDiff(diff) {
145
+ export function renderDiff(diff, label = 'dead-exports') {
158
146
  const lines = [];
159
147
  for (const r of diff.added) lines.push(`+ ${r.file}: ${r.symbol}`);
160
148
  for (const r of diff.removed) lines.push(`- ${r.file}: ${r.symbol}`);
161
149
  const tag = diff.added.length > 0 ? '(gate fail)' : '(ok)';
162
150
  lines.push(
163
- `[dead-exports] added=${diff.added.length} removed=${diff.removed.length} ${tag}`,
151
+ `[${label}] added=${diff.added.length} removed=${diff.removed.length} ${tag}`,
164
152
  );
165
153
  return lines.join('\n');
166
154
  }
167
155
 
168
- /**
169
- * Spawn `npx knip --reporter json --no-progress` and return the parsed
170
- * envelope. Returns `null` on spawn / parse failure — the caller logs the
171
- * underlying error and falls back to treating current rows as empty (which
172
- * surfaces every baseline row as "removed", a loud-but-safe signal).
173
- *
174
- * Exported as a hook so tests can stub the spawn without setting up a
175
- * functioning knip workspace.
176
- *
177
- * @param {{ cwd?: string, spawn?: typeof spawnSync }} [opts]
178
- * @returns {{ ok: true, envelope: unknown } | { ok: false, error: string }}
179
- */
180
- export function runKnip({ cwd = process.cwd(), spawn = spawnSync } = {}) {
181
- const result = spawn(
182
- process.platform === 'win32' ? 'npx.cmd' : 'npx',
183
- ['knip', '--reporter', 'json', '--no-progress'],
184
- {
185
- cwd,
186
- stdio: ['ignore', 'pipe', 'pipe'],
187
- encoding: 'utf-8',
188
- shell: process.platform === 'win32',
189
- },
190
- );
191
- if (result.error) {
192
- return { ok: false, error: `spawn failed: ${result.error.message}` };
193
- }
194
- const stdout = typeof result.stdout === 'string' ? result.stdout : '';
195
- if (stdout.trim().length === 0) {
196
- return { ok: false, error: 'knip produced empty stdout' };
197
- }
198
- try {
199
- return { ok: true, envelope: JSON.parse(stdout) };
200
- } catch (err) {
201
- return {
202
- ok: false,
203
- error: `knip JSON parse failed: ${err?.message ?? err}`,
204
- };
205
- }
206
- }
207
-
208
- /**
209
- * Read a pre-captured knip JSON envelope from disk (for the `--knip-output`
210
- * test seam). Returns the parsed envelope or `null` on failure.
211
- *
212
- * @param {string} filePath
213
- * @returns {unknown}
214
- */
215
- function readKnipOutput(filePath) {
216
- try {
217
- return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
218
- } catch {
219
- return null;
220
- }
221
- }
222
-
223
156
  /**
224
157
  * Top-level CLI entry. Exported so tests can drive the full pipeline through
225
158
  * injected hooks without spawning knip.
@@ -242,10 +175,15 @@ export async function runCli({
242
175
  runKnipImpl = runKnip,
243
176
  loadBaselineImpl = loadBaseline,
244
177
  } = {}) {
245
- const { baselinePath, json, knipOutputPath } = parseArgv(argv);
178
+ const { baselinePath, json, knipOutputPath, production } = parseArgv(argv);
179
+ const {
180
+ mode,
181
+ label,
182
+ baseline: defaultBaseline,
183
+ } = resolveDeadExportsMode(production);
246
184
  const resolvedBaselinePath = path.resolve(
247
185
  cwd,
248
- baselinePath ?? path.join('baselines', 'dead-exports.json'),
186
+ baselinePath ?? defaultBaseline,
249
187
  );
250
188
  const baseline = loadBaselineImpl(resolvedBaselinePath);
251
189
  const baselineRows = Array.isArray(baseline?.rows) ? baseline.rows : [];
@@ -256,7 +194,7 @@ export async function runCli({
256
194
  knipEnvelope = readKnipOutput(path.resolve(cwd, knipOutputPath));
257
195
  if (!knipEnvelope) knipError = `failed to read ${knipOutputPath}`;
258
196
  } else {
259
- const result = runKnipImpl({ cwd });
197
+ const result = runKnipImpl({ cwd, production });
260
198
  if (result.ok) {
261
199
  knipEnvelope = result.envelope;
262
200
  } else {
@@ -275,6 +213,7 @@ export async function runCli({
275
213
  if (json) {
276
214
  const envelope = {
277
215
  kind: 'dead-exports-report',
216
+ mode,
278
217
  baselinePath: resolvedBaselinePath,
279
218
  baselineRows,
280
219
  currentRows,
@@ -287,14 +226,14 @@ export async function runCli({
287
226
  } else {
288
227
  if (!baseline) {
289
228
  stderr.write(
290
- `[dead-exports] ⚠ baseline not found at ${resolvedBaselinePath} — treating as empty\n`,
229
+ `[${label}] ⚠ baseline not found at ${resolvedBaselinePath} — treating as empty\n`,
291
230
  );
292
231
  }
293
232
  if (knipError) {
294
- stderr.write(`[dead-exports] ⚠ knip run failed: ${knipError}\n`);
233
+ stderr.write(`[${label}] ⚠ knip run failed: ${knipError}\n`);
295
234
  }
296
- stdout.write(`\n--- dead-exports preview ---\n`);
297
- stdout.write(`${renderDiff(diff)}\n`);
235
+ stdout.write(`\n--- ${label} preview ---\n`);
236
+ stdout.write(`${renderDiff(diff, label)}\n`);
298
237
  }
299
238
 
300
239
  return exitCode;
@@ -257,8 +257,8 @@ function stripAnchorAndQuery(target) {
257
257
  // A slash token is `/<name>` where:
258
258
  // - the preceding char is NOT a word char, `/`, `:`, `.`, `>`, `]`, `)`,
259
259
  // so we don't match URL path segments or fragments embedded in paths
260
- // like `temp/epic-<id>/lifecycle.ndjson` (preceded by `>`) or
261
- // `temp/epic-[ID]/tickets.json` (preceded by `]`).
260
+ // like `temp/run-<id>/lifecycle.ndjson` (preceded by `>`) or
261
+ // `temp/run-[ID]/tickets.json` (preceded by `]`).
262
262
  // - the following char is NOT a word char, `-`, or `.`, so file
263
263
  // extensions like `/tickets.json` and identifier suffixes don't match.
264
264
  // The optional `(?::[a-z][a-z0-9-]*)?` tail captures the namespaced
@@ -17,7 +17,7 @@
17
17
  * Any module under `.agents/scripts/lib/orchestration/lifecycle/listeners/**`
18
18
  * that calls `bus.on('*', …)` MUST NOT import a side-effecting module.
19
19
  * The static blocklist is small (the modules that mutate GitHub state,
20
- * the worktree, or write outside `temp/epic-<id>/`); we match by module
20
+ * the worktree, or write outside `temp/run-<id>/`); we match by module
21
21
  * specifier suffix to keep the rule simple and stable.
22
22
  *
23
23
  * Rule 3 — "Auto-merge lockout" (Story #2253 / Task #2255, Epic #2172
@@ -80,17 +80,14 @@ const SCRIPTS_DIR = path.join(REPO_ROOT, '.agents', 'scripts');
80
80
  * auto-merge call could re-enter the codebase.
81
81
  */
82
82
  const MERGE_LOCKOUT_ALLOWED_SUFFIXES = Object.freeze([
83
- // Story #2256 / #2336 — the predicate-gated AutomergeArmer listener is
84
- // now the SOLE production code path authorized to call `gh pr merge`.
85
- // The legacy `.agents/scripts/epic-deliver-automerge.js` exemption was
86
- // removed in Story #2336 / Task #2340 once the CLI was reduced to a
87
- // pure `epic.automerge.start` emit shim.
83
+ // v2 Story close path — the sole production code path authorized to
84
+ // call `gh pr merge` after the Epic AutomergeArmer listener was removed.
88
85
  path.join(
89
86
  'lib',
90
87
  'orchestration',
91
- 'lifecycle',
92
- 'listeners',
93
- 'automerge-armer.js',
88
+ 'single-story-close',
89
+ 'phases',
90
+ 'auto-merge.js',
94
91
  ),
95
92
  ]);
96
93
 
@@ -339,7 +336,7 @@ export function findMergeLockoutViolations(
339
336
  violations.push({
340
337
  file,
341
338
  line: i + 1,
342
- hint: `String literal containing '${FORBIDDEN}' is forbidden outside automerge-armer.js (Story #2253 review High-1). Auto-merge enablement must flow through the AutomergeArmer listener so blocker/review predicates gate the call.`,
339
+ hint: `String literal containing '${FORBIDDEN}' is forbidden outside single-story-close/phases/auto-merge.js. Auto-merge enablement must flow through the Story close path.`,
343
340
  });
344
341
  break; // one violation per line is enough
345
342
  }
@@ -61,6 +61,19 @@ const BACKTICK_CALL_RE = /`[A-Za-z_$][\w$]*\s*\(/;
61
61
  const EXPORTED_FROM_RE = /\bexported from\b/;
62
62
  const LIB_IMPORT_RE = /\b(?:import|require)\(\s*['"`][^'"`]*scripts\/lib\//;
63
63
 
64
+ /** A markdown table row (leading pipe, optionally indented). */
65
+ const TABLE_ROW_RE = /^\s*\|/;
66
+ /** A markdown heading of any level — the lookback boundary for Rule 4. */
67
+ const HEADING_RE = /^\s*#{1,6}\s/;
68
+ /** A backticked `--flag` occupying a table row's first cell. */
69
+ const FLAG_CELL_RE = /^\s*\|\s*`?--[\w-]+/;
70
+ /** A `.js` script filename — bare or path-qualified. */
71
+ const SCRIPT_NAME_RE = /([\w./-]*[\w-]+\.js)\b/;
72
+ /** A markdown table's delimiter row (`| --- | --- |`). */
73
+ const TABLE_DELIMITER_RE = /^\s*\|[\s|:-]+\|?\s*$/;
74
+ /** Minimum `--flag` rows before a table counts as a flag *table*. */
75
+ export const MIN_FLAG_ROWS = 2;
76
+
64
77
  /**
65
78
  * Strip fenced code blocks (``` / ~~~), replacing their lines with empty
66
79
  * strings so line numbers stay stable. Complete runnable commands live in
@@ -106,6 +119,82 @@ export function toParagraphs(lines) {
106
119
  return paragraphs;
107
120
  }
108
121
 
122
+ /**
123
+ * Rule 4 — CLI flag table. Find markdown tables that enumerate the `--flags`
124
+ * of a script the repo already owns, and flag them as duplicated surface.
125
+ *
126
+ * The script's own argument parser is the source of truth for its flags, and
127
+ * it prints them itself; a copy in prose is drift waiting to happen (the very
128
+ * drift Story #4546 removed). Prose must point at the command instead.
129
+ *
130
+ * The signal is deliberately narrow, to stay at zero false positives:
131
+ *
132
+ * 1. The table has at least `MIN_FLAG_ROWS` data rows whose **first cell**
133
+ * is a `--flag`. One flag row among prose rows is a contract/behaviour
134
+ * table (e.g. "Default | …", "`--dry-run` | …"), not a flag enumeration.
135
+ * 2. A `.js` script is named between the table and the nearest preceding
136
+ * heading (inclusive) — i.e. the section is *about* that script, so the
137
+ * table is restating its surface.
138
+ *
139
+ * A slash command's own argument table (`/plan`, `/deliver`) has no script
140
+ * behind it — nothing owns those flags but the workflow prose itself — so
141
+ * condition 2 leaves it alone by design.
142
+ *
143
+ * @param {string[]} rawLines unstripped source lines (fenced commands are the
144
+ * usual place a script is named, so this rule reads the original text).
145
+ * @returns {Array<{ rule: string, line: number, hint: string }>}
146
+ */
147
+ export function lintFlagTables(rawLines) {
148
+ const violations = [];
149
+ let inFence = false;
150
+
151
+ for (let i = 0; i < rawLines.length; i++) {
152
+ if (/^\s*(```|~~~)/.test(rawLines[i])) {
153
+ inFence = !inFence;
154
+ continue;
155
+ }
156
+ if (inFence || !TABLE_ROW_RE.test(rawLines[i])) continue;
157
+
158
+ // Collect the contiguous table block starting here.
159
+ const start = i;
160
+ let end = i;
161
+ while (end + 1 < rawLines.length && TABLE_ROW_RE.test(rawLines[end + 1])) {
162
+ end += 1;
163
+ }
164
+ i = end; // continue scanning after this table
165
+
166
+ const flagRows = rawLines
167
+ .slice(start, end + 1)
168
+ .filter((l) => !TABLE_DELIMITER_RE.test(l) && FLAG_CELL_RE.test(l));
169
+ if (flagRows.length < MIN_FLAG_ROWS) continue;
170
+
171
+ // Look back to the nearest heading (inclusive) for a named script.
172
+ let script = null;
173
+ for (let j = start - 1; j >= 0; j--) {
174
+ const m = SCRIPT_NAME_RE.exec(rawLines[j]);
175
+ if (m) {
176
+ script = m[1];
177
+ break;
178
+ }
179
+ if (HEADING_RE.test(rawLines[j])) break;
180
+ }
181
+ if (!script) continue;
182
+
183
+ const base = script.split('/').pop();
184
+ violations.push({
185
+ rule: 'no-cli-flag-table',
186
+ line: start + 1,
187
+ hint:
188
+ `Workflow prose restates the flag surface of \`${base}\` as a table (${flagRows.length} flag rows). ` +
189
+ "The script's argument parser owns those flags, so a prose copy is drift waiting to happen. " +
190
+ `Delete the table and point at the command (\`node .agents/scripts/${base} …\`), keeping only the ` +
191
+ 'judgement a reader cannot get from the command itself. If the script has no help output to point ' +
192
+ 'at, add one — do not re-inline the table.',
193
+ });
194
+ }
195
+ return violations;
196
+ }
197
+
109
198
  /**
110
199
  * Lint one markdown source. Returns violations
111
200
  * `{ rule, line, hint }[]` (empty when clean).
@@ -115,7 +204,9 @@ export function toParagraphs(lines) {
115
204
  */
116
205
  export function lintWorkflowSource(source) {
117
206
  const violations = [];
207
+ const rawLines = source.split('\n');
118
208
  const lines = stripFences(source);
209
+ violations.push(...lintFlagTables(rawLines));
119
210
  for (const para of toParagraphs(lines)) {
120
211
  if (IMPERATIVE_CALL_RE.test(para.text)) {
121
212
  violations.push({
@@ -20,7 +20,12 @@
20
20
  import { existsSync, readdirSync, rmSync } from 'node:fs';
21
21
  import path from 'node:path';
22
22
  import { runAsCli } from './lib/cli-utils.js';
23
- import { isReservedTestEpicTempDirName } from './lib/test-reserved-epic-temp-ids.js';
23
+
24
+ const RESERVED_TEST_EPIC_TEMP_DIR = /^epic-999\d{3}$/;
25
+
26
+ function isReservedTestEpicTempDirName(name) {
27
+ return RESERVED_TEST_EPIC_TEMP_DIR.test(name);
28
+ }
24
29
 
25
30
  /**
26
31
  * @param {object} [opts]
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * deliver-recover.js — probe a stranded Story's live state and print the ONE
5
+ * command that resumes it (Story #4543).
6
+ *
7
+ * Read-only by construction. This CLI mutates nothing: it reads the ticket's
8
+ * labels and lease, the Story branch locally and via its tracking ref, the
9
+ * worktree, and the PR (state + checks), then walks a fixed decision table
10
+ * and prints one command with the evidence it was derived from. It never
11
+ * prints a menu — a menu of options is what the operator already has, and it
12
+ * is the thing they cannot act on.
13
+ *
14
+ * The strand this exists for above all others is the **merged-but-label-stale**
15
+ * Story: a `/deliver` re-run refuses it outright, because
16
+ * `single-story-init.js` hard-errors on an already-closed Story. Before this
17
+ * surface, that Story had no automated way back.
18
+ *
19
+ * Usage:
20
+ * node .agents/scripts/deliver-recover.js --story <STORY_ID> [--cwd <main-repo>]
21
+ * [--json]
22
+ *
23
+ * Exit codes:
24
+ * 0 — a recovery shape was resolved and its next command printed (including
25
+ * the "nothing to recover" shapes). Reading state is not a failure.
26
+ * 1 — the probe itself could not run (unreadable ticket, bad input).
27
+ *
28
+ * @see .agents/scripts/lib/orchestration/deliver-recover.js
29
+ * @see .agents/schemas/story-deliver-terminal.schema.json
30
+ */
31
+
32
+ import { parseArgs } from 'node:util';
33
+ import { runAsCli } from './lib/cli-utils.js';
34
+ import { resolveConfig } from './lib/config-resolver.js';
35
+ import { Logger } from './lib/Logger.js';
36
+ import {
37
+ recoverStory,
38
+ renderRecovery,
39
+ } from './lib/orchestration/deliver-recover.js';
40
+ import { PROJECT_ROOT } from './lib/project-root.js';
41
+ import { createProvider } from './lib/provider-factory.js';
42
+
43
+ const HELP = `Usage: node .agents/scripts/deliver-recover.js --story <id> [--cwd <main-repo>] [--json]
44
+
45
+ Probes a Story's live delivery state — labels, lease, branch, worktree, PR
46
+ state and checks — and prints the single next command that resumes it, with
47
+ the evidence it was derived from. Read-only: mutates nothing.
48
+
49
+ Flags:
50
+ --story GitHub issue number of the Story (required).
51
+ --cwd Main-repo checkout to probe (default: project root).
52
+ --json Emit the full recovery envelope as JSON instead of prose.
53
+ --help Show this message.
54
+ `;
55
+
56
+ export function parseArgv(argv) {
57
+ const { values } = parseArgs({
58
+ args: argv,
59
+ options: {
60
+ story: { type: 'string' },
61
+ cwd: { type: 'string' },
62
+ json: { type: 'boolean', default: false },
63
+ help: { type: 'boolean', default: false },
64
+ },
65
+ strict: false,
66
+ });
67
+ return {
68
+ storyId: Number.parseInt(String(values.story ?? ''), 10),
69
+ cwd: values.cwd ?? null,
70
+ json: Boolean(values.json),
71
+ help: Boolean(values.help),
72
+ };
73
+ }
74
+
75
+ /**
76
+ * Probe and report. Exported for testing.
77
+ */
78
+ export async function runDeliverRecover({
79
+ storyId: storyIdParam,
80
+ cwd: cwdParam,
81
+ json: jsonParam,
82
+ argv,
83
+ injectedProvider,
84
+ injectedConfig,
85
+ injectedGh,
86
+ injectedGitSpawn,
87
+ } = {}) {
88
+ const parsed =
89
+ storyIdParam !== undefined
90
+ ? { storyId: storyIdParam, cwd: cwdParam ?? null, json: !!jsonParam }
91
+ : parseArgv(argv ?? process.argv.slice(2));
92
+
93
+ if (parsed.help) {
94
+ Logger.info(HELP);
95
+ return { success: true, result: null };
96
+ }
97
+ if (!Number.isInteger(parsed.storyId) || parsed.storyId <= 0) {
98
+ throw new Error(
99
+ 'Usage: node deliver-recover.js --story <STORY_ID> [--cwd <main-repo>] [--json]',
100
+ );
101
+ }
102
+
103
+ const cwd = parsed.cwd ?? PROJECT_ROOT;
104
+ const config = injectedConfig || resolveConfig({ cwd });
105
+ const provider = injectedProvider || createProvider(config);
106
+
107
+ const recovery = await recoverStory({
108
+ storyId: parsed.storyId,
109
+ cwd,
110
+ provider,
111
+ config,
112
+ gh: injectedGh,
113
+ gitSpawnFn: injectedGitSpawn,
114
+ });
115
+
116
+ Logger.info(
117
+ parsed.json ? JSON.stringify(recovery, null, 2) : renderRecovery(recovery),
118
+ );
119
+ return { success: true, result: recovery };
120
+ }
121
+
122
+ runAsCli(import.meta.url, runDeliverRecover, { source: 'deliver-recover' });
@@ -8,7 +8,7 @@
8
8
  * any still-stuck entries by enumerating the processes holding handles
9
9
  * inside the worktree path and terminating them.
10
10
  *
11
- * Invoked by `/deliver`, `/epic-plan-spec` / `/epic-plan-decompose`
11
+ * Invoked by `/deliver` and `/plan`
12
12
  * (via `drainPendingCleanupAtBoot` → `worktree-sweep.js`), and
13
13
  * `story-close` so the pending-cleanup ledger drains automatically
14
14
  * across the sprint lifecycle. Operators can also run it standalone: