mandrel 1.94.0 → 2.0.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 (393) hide show
  1. package/.agents/README.md +59 -73
  2. package/.agents/agents/story-worker.md +12 -13
  3. package/.agents/docs/SDLC.md +489 -1285
  4. package/.agents/docs/agentrc-reference.json +177 -67
  5. package/.agents/docs/configuration.md +104 -138
  6. package/.agents/docs/execution-reference.md +17 -20
  7. package/.agents/docs/quality-gates.md +13 -19
  8. package/.agents/docs/workflows.md +3 -3
  9. package/.agents/instructions.md +70 -81
  10. package/.agents/rules/ci-remediation.md +8 -12
  11. package/.agents/rules/git-conventions-reference.md +6 -7
  12. package/.agents/rules/git-conventions.md +16 -22
  13. package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
  14. package/.agents/schemas/agentrc.schema.json +54 -214
  15. package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
  16. package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
  17. package/.agents/schemas/risk-verdict.schema.json +0 -13
  18. package/.agents/scripts/analyze-execution.js +1 -1
  19. package/.agents/scripts/audit-to-stories.js +7 -7
  20. package/.agents/scripts/boot-sweep.js +1 -1
  21. package/.agents/scripts/check-lifecycle-lint.js +6 -9
  22. package/.agents/scripts/check-prepush-recovery.js +1 -1
  23. package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
  24. package/.agents/scripts/lib/Logger.js +6 -10
  25. package/.agents/scripts/lib/audit-suite/runner.js +2 -2
  26. package/.agents/scripts/lib/audit-suite/selector.js +5 -5
  27. package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
  28. package/.agents/scripts/lib/baselines/kernel.js +206 -18
  29. package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -4
  30. package/.agents/scripts/lib/baselines/reader.js +1 -6
  31. package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
  32. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
  33. package/.agents/scripts/lib/checks/core-bare-clean.js +2 -2
  34. package/.agents/scripts/lib/checks/index.js +2 -1
  35. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +23 -21
  36. package/.agents/scripts/lib/cli/standard-args.js +13 -22
  37. package/.agents/scripts/lib/cli-args.js +16 -7
  38. package/.agents/scripts/lib/close-validation/gates.js +2 -2
  39. package/.agents/scripts/lib/config/ci.js +6 -31
  40. package/.agents/scripts/lib/config/delivery-routing.js +45 -29
  41. package/.agents/scripts/lib/config/explain.js +55 -36
  42. package/.agents/scripts/lib/config/limits.js +17 -58
  43. package/.agents/scripts/lib/config/paths.js +0 -2
  44. package/.agents/scripts/lib/config/quality.js +1 -1
  45. package/.agents/scripts/lib/config/runners.js +17 -50
  46. package/.agents/scripts/lib/config/temp-paths.js +19 -14
  47. package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
  48. package/.agents/scripts/lib/config-resolver.js +2 -7
  49. package/.agents/scripts/lib/config-settings-schema-delivery.js +24 -148
  50. package/.agents/scripts/lib/config-settings-schema-quality.js +8 -14
  51. package/.agents/scripts/lib/config-settings-schema.js +52 -38
  52. package/.agents/scripts/lib/dependency-parser.js +3 -2
  53. package/.agents/scripts/lib/doc-tiers.js +2 -2
  54. package/.agents/scripts/lib/duplicate-search.js +211 -41
  55. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
  56. package/.agents/scripts/lib/findings/promote-finding.js +5 -5
  57. package/.agents/scripts/lib/framework-version.js +2 -3
  58. package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
  59. package/.agents/scripts/lib/git-branch-lifecycle.js +17 -22
  60. package/.agents/scripts/lib/git-utils.js +32 -6
  61. package/.agents/scripts/lib/github/framework-repo.js +6 -0
  62. package/.agents/scripts/lib/label-constants.js +10 -23
  63. package/.agents/scripts/lib/label-taxonomy.js +9 -43
  64. package/.agents/scripts/lib/observability/active-story-env.js +1 -1
  65. package/.agents/scripts/lib/observability/hook-heartbeat.js +20 -52
  66. package/.agents/scripts/lib/observability/source-classifier.js +3 -3
  67. package/.agents/scripts/lib/onboard/init-tail.js +1 -3
  68. package/.agents/scripts/lib/orchestration/audit-lens-routing.js +128 -0
  69. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +8 -5
  70. package/.agents/scripts/lib/orchestration/ceremony-routing.js +83 -20
  71. package/.agents/scripts/lib/orchestration/code-review.js +20 -268
  72. package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
  73. package/.agents/scripts/lib/orchestration/consolidation-precondition.js +1 -1
  74. package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
  75. package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
  76. package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
  77. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
  78. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +8 -8
  79. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +2 -2
  80. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
  81. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +17 -43
  82. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
  83. package/.agents/scripts/lib/orchestration/merge-block-class.js +1 -1
  84. package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
  85. package/.agents/scripts/lib/orchestration/plan-context.js +248 -266
  86. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +1 -1
  87. package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
  88. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +61 -0
  89. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +97 -0
  90. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +223 -854
  91. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +361 -0
  92. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +35 -108
  93. package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
  94. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
  95. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +13 -13
  96. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
  97. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/risk-verdict.js +3 -4
  98. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +2 -2
  99. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +8 -20
  100. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +3 -2
  101. package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
  102. package/.agents/scripts/lib/orchestration/preflight-cache.js +5 -5
  103. package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
  104. package/.agents/scripts/lib/orchestration/resolve-plan-run.js +155 -0
  105. package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
  106. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +8 -8
  107. package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
  108. package/.agents/scripts/lib/orchestration/review-depth.js +26 -12
  109. package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
  110. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
  111. package/.agents/scripts/lib/orchestration/run-epilogue.js +426 -0
  112. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +1 -1
  113. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +95 -41
  114. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +16 -13
  115. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +40 -0
  116. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +11 -3
  117. package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
  118. package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
  119. package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
  120. package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
  121. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
  122. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +15 -12
  123. package/.agents/scripts/lib/orchestration/story-follow-ups.js +237 -0
  124. package/.agents/scripts/lib/orchestration/story-init-remote.js +47 -0
  125. package/.agents/scripts/lib/orchestration/story-plan-state.js +48 -0
  126. package/.agents/scripts/lib/orchestration/{epic-runner → story-progress}/story-run-progress-writer.js +3 -3
  127. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
  128. package/.agents/scripts/lib/orchestration/task-body-validator.js +8 -18
  129. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +11 -61
  130. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +189 -373
  131. package/.agents/scripts/lib/orchestration/ticket-validator.js +2 -7
  132. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +0 -25
  133. package/.agents/scripts/lib/orchestration/ticketing/reads.js +29 -26
  134. package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -5
  135. package/.agents/scripts/lib/planning-corpus.js +16 -11
  136. package/.agents/scripts/lib/preflight-runner.js +2 -2
  137. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
  138. package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +36 -0
  139. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
  140. package/.agents/scripts/lib/story-adjacency.js +11 -14
  141. package/.agents/scripts/lib/story-body/story-body.js +124 -70
  142. package/.agents/scripts/lib/story-plan.js +2 -4
  143. package/.agents/scripts/lib/templates/decomposer-prompts.js +46 -45
  144. package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
  145. package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +26 -26
  146. package/.agents/scripts/lib/validation-evidence.js +1 -1
  147. package/.agents/scripts/lib/wave-runner/ready-set.js +6 -6
  148. package/.agents/scripts/lib/workspace-provisioner.js +1 -1
  149. package/.agents/scripts/lib/worktree/lifecycle/reap.js +5 -7
  150. package/.agents/scripts/lint-issue-body.js +71 -40
  151. package/.agents/scripts/mandrel-update-preflight.js +1 -1
  152. package/.agents/scripts/notify.js +4 -3
  153. package/.agents/scripts/plan-context.js +64 -74
  154. package/.agents/scripts/plan-persist.js +121 -280
  155. package/.agents/scripts/plan-run-epilogue.js +97 -0
  156. package/.agents/scripts/providers/github/issues.js +17 -33
  157. package/.agents/scripts/providers/github/mappers.js +0 -12
  158. package/.agents/scripts/providers/github/tickets.js +2 -5
  159. package/.agents/scripts/resolve-plan-run.js +117 -0
  160. package/.agents/scripts/signals-view.js +24 -19
  161. package/.agents/scripts/single-story-close.js +11 -14
  162. package/.agents/scripts/single-story-confirm-merge.js +39 -23
  163. package/.agents/scripts/single-story-init.js +29 -20
  164. package/.agents/scripts/stories-wave-tick.js +6 -6
  165. package/.agents/scripts/story-plan.js +26 -47
  166. package/.agents/scripts/update-ticket-state.js +6 -15
  167. package/.agents/skills/core/analyze-execution/SKILL.md +21 -18
  168. package/.agents/skills/core/idea-refinement/SKILL.md +6 -6
  169. package/.agents/skills/core/scope-triage/SKILL.md +28 -172
  170. package/.agents/skills/skills.index.json +3 -43
  171. package/.agents/starter-agentrc.json +0 -5
  172. package/.agents/templates/agent-protocol.md +9 -10
  173. package/.agents/workflows/audit-architecture.md +3 -3
  174. package/.agents/workflows/audit-clean-code.md +3 -3
  175. package/.agents/workflows/audit-dependencies.md +3 -3
  176. package/.agents/workflows/audit-devops.md +3 -3
  177. package/.agents/workflows/audit-documentation.md +5 -5
  178. package/.agents/workflows/audit-lighthouse.md +3 -3
  179. package/.agents/workflows/audit-navigability.md +3 -2
  180. package/.agents/workflows/audit-performance.md +3 -3
  181. package/.agents/workflows/audit-privacy.md +3 -3
  182. package/.agents/workflows/audit-quality.md +3 -3
  183. package/.agents/workflows/audit-security.md +3 -3
  184. package/.agents/workflows/audit-seo.md +3 -3
  185. package/.agents/workflows/audit-sre.md +3 -3
  186. package/.agents/workflows/audit-to-stories.md +20 -20
  187. package/.agents/workflows/audit-ux-ui.md +3 -3
  188. package/.agents/workflows/deliver.md +122 -174
  189. package/.agents/workflows/git-cleanup.md +3 -4
  190. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  191. package/.agents/workflows/helpers/acceptance-self-eval.md +16 -29
  192. package/.agents/workflows/helpers/code-review.md +70 -193
  193. package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +12 -14
  194. package/.agents/workflows/helpers/{single-story-deliver.md → deliver-story.md} +113 -139
  195. package/.agents/workflows/helpers/diagnose.md +10 -10
  196. package/.agents/workflows/helpers/parallel-tooling.md +1 -1
  197. package/.agents/workflows/helpers/signals.md +16 -16
  198. package/.agents/workflows/helpers/worktree-lifecycle.md +48 -64
  199. package/.agents/workflows/mandrel-update.md +2 -1
  200. package/.agents/workflows/plan.md +112 -145
  201. package/.agents/workflows/qa-assist.md +24 -30
  202. package/.agents/workflows/qa-explore.md +29 -38
  203. package/.agents/workflows/qa-run.md +2 -2
  204. package/README.md +9 -8
  205. package/docs/CHANGELOG.md +30 -0
  206. package/lib/migrations/index.js +6 -5
  207. package/package.json +2 -2
  208. package/.agents/agents/retro.md +0 -42
  209. package/.agents/personas/architect.md +0 -113
  210. package/.agents/personas/devops-engineer.md +0 -38
  211. package/.agents/personas/engineer.md +0 -33
  212. package/.agents/personas/project-manager.md +0 -114
  213. package/.agents/personas/qa-engineer.md +0 -95
  214. package/.agents/personas/security-engineer.md +0 -111
  215. package/.agents/personas/technical-writer.md +0 -101
  216. package/.agents/schemas/dispatch-manifest.json +0 -232
  217. package/.agents/schemas/epic-spec.schema.json +0 -153
  218. package/.agents/schemas/lifecycle/slice.end.schema.json +0 -21
  219. package/.agents/schemas/lifecycle/slice.heartbeat.schema.json +0 -20
  220. package/.agents/schemas/lifecycle/slice.start.schema.json +0 -17
  221. package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
  222. package/.agents/scripts/bookkeeping-reconcile.js +0 -117
  223. package/.agents/scripts/dispatcher.js +0 -295
  224. package/.agents/scripts/epic-audit-prepare.js +0 -497
  225. package/.agents/scripts/epic-audit-recheck.js +0 -274
  226. package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
  227. package/.agents/scripts/epic-deliver-preflight.js +0 -462
  228. package/.agents/scripts/epic-deliver-prepare.js +0 -852
  229. package/.agents/scripts/epic-execute-record-wave.js +0 -449
  230. package/.agents/scripts/epic-plan-clarity.js +0 -211
  231. package/.agents/scripts/epic-plan-healthcheck.js +0 -581
  232. package/.agents/scripts/epic-reconcile.js +0 -625
  233. package/.agents/scripts/lib/baseline-snapshot.js +0 -979
  234. package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
  235. package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
  236. package/.agents/scripts/lib/config/lifecycle.js +0 -40
  237. package/.agents/scripts/lib/config/preflight.js +0 -58
  238. package/.agents/scripts/lib/config/retro.js +0 -77
  239. package/.agents/scripts/lib/epic-merge-lock.js +0 -322
  240. package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
  241. package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
  242. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -539
  243. package/.agents/scripts/lib/orchestration/deliver-route.js +0 -173
  244. package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
  245. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
  246. package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
  247. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
  248. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
  249. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
  250. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
  251. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
  252. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
  253. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
  254. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
  255. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
  256. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
  257. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
  258. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
  259. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
  260. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
  261. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
  262. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -621
  263. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
  264. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
  265. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
  266. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
  267. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
  268. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
  269. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
  270. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
  271. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
  272. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
  273. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
  274. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
  275. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
  276. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
  277. package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
  278. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
  279. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
  280. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
  281. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
  282. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
  283. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
  284. package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
  285. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
  286. package/.agents/scripts/lib/orchestration/lifecycle/emit-slice-lifecycle.js +0 -270
  287. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
  288. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -465
  289. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
  290. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
  291. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
  292. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -284
  293. package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
  294. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
  295. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
  296. package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
  297. package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
  298. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
  299. package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
  300. package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
  301. package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
  302. package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
  303. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
  304. package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
  305. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
  306. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
  307. package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
  308. package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
  309. package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
  310. package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
  311. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
  312. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
  313. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
  314. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
  315. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
  316. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
  317. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
  318. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
  319. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
  320. package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
  321. package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
  322. package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
  323. package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
  324. package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
  325. package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
  326. package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
  327. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
  328. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
  329. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
  330. package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
  331. package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
  332. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
  333. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
  334. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
  335. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -302
  336. package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
  337. package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
  338. package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
  339. package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
  340. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
  341. package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
  342. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
  343. package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
  344. package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
  345. package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
  346. package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
  347. package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
  348. package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
  349. package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
  350. package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
  351. package/.agents/scripts/lib/push-epic-retry.js +0 -209
  352. package/.agents/scripts/lib/spec/index.js +0 -36
  353. package/.agents/scripts/lib/spec/loader.js +0 -425
  354. package/.agents/scripts/lib/spec/state.js +0 -208
  355. package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
  356. package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
  357. package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
  358. package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
  359. package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
  360. package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
  361. package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
  362. package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
  363. package/.agents/scripts/lib/wave-runner/tick.js +0 -754
  364. package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
  365. package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
  366. package/.agents/scripts/lifecycle-emit.js +0 -510
  367. package/.agents/scripts/retro-run.js +0 -218
  368. package/.agents/scripts/slice-phase.js +0 -361
  369. package/.agents/scripts/standalone-feedback-rollup.js +0 -188
  370. package/.agents/scripts/story-close.js +0 -294
  371. package/.agents/scripts/story-init.js +0 -599
  372. package/.agents/scripts/story-phase.js +0 -369
  373. package/.agents/scripts/wave-tick.js +0 -464
  374. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
  375. package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
  376. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
  377. package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
  378. package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
  379. package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
  380. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -383
  381. package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
  382. package/.agents/workflows/helpers/deliver-epic-reference.md +0 -547
  383. package/.agents/workflows/helpers/deliver-epic-single.md +0 -331
  384. package/.agents/workflows/helpers/deliver-epic.md +0 -998
  385. package/.agents/workflows/helpers/deliver-stories.md +0 -450
  386. package/.agents/workflows/helpers/epic-audit.md +0 -189
  387. package/.agents/workflows/helpers/epic-deliver-story.md +0 -436
  388. package/.agents/workflows/helpers/epic-testing.md +0 -125
  389. package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
  390. package/.agents/workflows/helpers/plan-epic.md +0 -353
  391. package/.agents/workflows/helpers/plan-story.md +0 -251
  392. package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
  393. /package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +0 -0
@@ -1,97 +1,44 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * plan-persist.js — single GitHub-write surface for the collapsed /plan
5
- * flow (Epic #4474, PR3 design §1 Step 3).
4
+ * plan-persist.js — flat Story GitHub-write surface for v2 `/plan`
5
+ * (Stage 3`docs/roadmap.md`).
6
6
  *
7
- * Supersedes the retired 12-phase pipeline's separate persist halves
8
- * (Epic #4474 PR7 the delegate CLIs are import shims now, deleted next
9
- * release). Given the author-written planning artifacts
10
- * (Tech Spec, optional Acceptance Table, risk verdict, tickets JSON), this
11
- * CLI performs every GitHub mutation of the plan flow in one ordered,
12
- * fail-closed pass:
7
+ * Given the author-written planning artifacts (`stories.json` +
8
+ * `risk-verdict.json`, optional shared Tech Spec), this CLI validates and
9
+ * creates Story issue(s) directly:
13
10
  *
14
- * section gate → risk-verdict + mode-coherence → ticket validator /
15
- * file-assumption gate / DAG / budget (ideation: open the Epic)
16
- * Epic lease managed sections + risk comment + freshness advisory →
17
- * story creation (structural reconciler) inline healthcheck
18
- * single terminal `agent::ready` flip (no intermediate
19
- * `agent::review-spec`) → checkpoint v2 + `plan-summary` comment with
20
- * the dry-run wave table → temp cleanup at terminal success only.
11
+ * risk-verdict → ticket validator / DAG / capacity → reachability →
12
+ * split-policy partition fold/spill Spec into each Story body
13
+ * createIssue(s) with type::story + agent::ready risk-verdict +
14
+ * story-plan-state on every Story; plan-summary on the primary temp
15
+ * cleanup.
21
16
  *
22
- * Modes:
23
- * --epic <id> Persist against an existing Epic. Artifact paths
24
- * default to the per-Epic temp tree
25
- * (`temp/epic-<id>/techspec.md`, `risk-verdict.json`,
26
- * `tickets.json`, and `acceptance-spec.md` when
27
- * present).
28
- * --one-pager <path> Ideation mode: render + open the Epic from a
29
- * sharpened one-pager first (folds the former
30
- * Phase 3/4 steps in). Artifact paths must be
31
- * explicit (there is no Epic id to derive them from).
32
- *
33
- * Modes (Epic #4474 PR4, design §2 mode matrix): the risk verdict's
34
- * optional `deliveryShape` field selects between the full fan-out persist
35
- * (default; requires tickets) and the spec-only single-delivery variant
36
- * (`deliveryShape: "single"`; NO tickets — the ticket validator + DAG are
37
- * skipped, fenced by construction, and the `delivery::single` routing
38
- * marker is applied instead of a Story tree; inert until #4475 lands the
39
- * deliver-side reader). `--amend` selects the change-request delta path:
40
- * tickets carry `op: add|modify|keep|close` and the persist maps the ops
41
- * onto the existing tree.
42
- *
43
- * Flags:
44
- * --force Deliberate re-persist: overwrite managed sections,
45
- * close + recreate the story tree (reconciler
46
- * --explicit-delete). Reuses on-disk artifacts —
47
- * cleanup is deferred to terminal success, so a
48
- * failed run leaves them in place.
49
- * --resume Continue a partial persist after a crash
50
- * (rate-limit, network): sections short-circuit
51
- * idempotently, the reconciler creates only the
52
- * missing slugs from its per-slug state ledger.
53
- * --amend Change-request delta persist: every ticket carries
54
- * `op: add|modify|keep|close`; close-and-recreate is
55
- * scoped to modify/close slugs only, keeps are
56
- * untouched, and the DAG is validated over the
57
- * merged set.
58
- * --explicit-delete Confirm the close ops of an --amend plan (mirrors
59
- * epic-reconcile.js). Without it, an amend carrying
60
- * close ops prints the dry-run diff and exits 2.
61
- * --steal Force-transfer a live foreign Epic-lease claim.
62
- * --force-review Operator-forced review routing (recorded in the
63
- * checkpoint's reviewRouting envelope).
17
+ * CLI:
18
+ * --stories <file> Required Story ticket array (default length 1)
19
+ * --risk-verdict <file> Required risk verdict (no deliveryShape)
20
+ * --tech-spec <file> Optional shared Tech Spec folded into each Story
21
+ * --plan-dir <dir> Optional temp dir deleted at terminal success
22
+ * --plan-acceptance <file> Optional JSON string[] for partition coverage
23
+ * --plan-run-id <id> Optional plan-run token when N>1
24
+ * --dry-run Assemble + validate without GitHub writes
25
+ * --force-review Record operator-forced review routing
64
26
  * --allow-over-budget / --allow-large-fan-out
65
- * Same overrides as the retired split persist.
66
27
  *
67
- * Exit codes: 0 persist complete, Epic is `agent::ready`; 1 — fatal
68
- * error (see stderr); 2 — amend close ops require --explicit-delete (the
69
- * dry-run diff is printed; nothing was mutated); 3 — reachability orphans
70
- * (Epic #4474 PR6 named soft failure: the deterministic route-glob vs
71
- * `planning.navigation.navRegistry` scan found route-adding draft stories
72
- * with no navigation owner — the orphan-surface list is printed, nothing
73
- * was mutated; apply one targeted amend and re-run the persist once). The
74
- * Epic lease is released on every exit path.
28
+ * Exit codes: 0 success; 1 fatal; 3 reachability orphans (nothing mutated).
75
29
  */
76
30
 
77
- // Fail-fast if the framework's runtime deps are not installed — must be the
78
- // first import so the check runs before any third-party-importing sibling
79
- // module is evaluated (Story #3432).
80
31
  import './lib/runtime-deps/ensure-installed.js';
81
32
  import { readFile } from 'node:fs/promises';
82
33
  import path from 'node:path';
83
34
  import { parseArgs } from 'node:util';
84
35
 
85
36
  import { runAsCli } from './lib/cli-utils.js';
86
- import { epicArtifactPath } from './lib/config/temp-paths.js';
87
37
  import {
88
- PROJECT_ROOT,
89
38
  resolveConfig,
90
39
  validateOrchestrationConfig,
91
40
  } from './lib/config-resolver.js';
92
41
  import { Logger } from './lib/Logger.js';
93
- import { drainPendingCleanupAtBoot } from './lib/orchestration/epic-plan-spec/phases/drain.js';
94
- import { loadRiskVerdict } from './lib/orchestration/epic-plan-spec/phases/risk-verdict.js';
95
42
  import {
96
43
  readPlanMetrics,
97
44
  recordPlanInvocation,
@@ -99,7 +46,6 @@ import {
99
46
  summarizePlanMetrics,
100
47
  } from './lib/orchestration/plan-metrics.js';
101
48
  import {
102
- resolveDeliveryMode,
103
49
  runPlanPersist,
104
50
  writeCheckpointV2,
105
51
  } from './lib/orchestration/plan-persist/run-plan-persist.js';
@@ -108,128 +54,139 @@ import {
108
54
  buildWaveTable,
109
55
  PLAN_SUMMARY_COMMENT_TYPE,
110
56
  } from './lib/orchestration/plan-persist/summary.js';
57
+ import { loadRiskVerdict } from './lib/orchestration/planning/risk-verdict.js';
111
58
  import { createProvider } from './lib/provider-factory.js';
112
59
 
113
- // Re-exports for the stable public API (tests import through the CLI
114
- // module, mirroring the plan-context.js CLI-shell shape).
115
60
  export {
116
61
  buildPlanSummaryCommentBody,
117
62
  buildWaveTable,
118
63
  PLAN_SUMMARY_COMMENT_TYPE,
119
- resolveDeliveryMode,
120
64
  runPlanPersist,
121
65
  writeCheckpointV2,
122
66
  };
123
67
 
124
- export const EPIC_FROM_IDEA_TEMPLATE_PATH = path.resolve(
125
- PROJECT_ROOT,
126
- '.agents',
127
- 'templates',
128
- 'epic-from-idea.md',
129
- );
130
-
131
68
  const CLI_OPTIONS = {
132
- epic: { type: 'string' },
133
- 'one-pager': { type: 'string' },
134
- 'tech-spec': { type: 'string' },
135
- 'acceptance-table': { type: 'string' },
69
+ stories: { type: 'string' },
136
70
  'risk-verdict': { type: 'string' },
137
- tickets: { type: 'string' },
138
- force: { type: 'boolean', default: false },
139
- resume: { type: 'boolean', default: false },
140
- steal: { type: 'boolean', default: false },
71
+ 'tech-spec': { type: 'string' },
72
+ 'plan-dir': { type: 'string' },
73
+ 'plan-acceptance': { type: 'string' },
74
+ 'plan-run-id': { type: 'string' },
75
+ 'dry-run': { type: 'boolean', default: false },
141
76
  'force-review': { type: 'boolean', default: false },
142
77
  'allow-over-budget': { type: 'boolean', default: false },
143
78
  'allow-large-fan-out': { type: 'boolean', default: false },
144
- amend: { type: 'boolean', default: false },
145
- 'explicit-delete': { type: 'boolean', default: false },
146
79
  };
147
80
 
148
81
  const USAGE =
149
- 'Usage: plan-persist.js (--epic <EpicId> | --one-pager <file>) ' +
150
- '[--tech-spec <file>] [--acceptance-table <file>] [--risk-verdict <file>] ' +
151
- '[--tickets <file>] [--force | --resume | --amend [--explicit-delete]] ' +
152
- '[--steal] [--force-review] [--allow-over-budget] [--allow-large-fan-out]';
82
+ 'Usage: plan-persist.js --stories <file> --risk-verdict <file> ' +
83
+ '[--tech-spec <file>] [--plan-dir <dir>] [--plan-acceptance <file>] ' +
84
+ '[--plan-run-id <id>] [--dry-run] [--force-review] ' +
85
+ '[--allow-over-budget] [--allow-large-fan-out]';
153
86
 
154
- /**
155
- * Parse `--epic`; returns null when absent (ideation mode).
156
- */
157
- function parseEpicId(rawEpic) {
158
- if (rawEpic === undefined) return null;
159
- const epicId = Number.parseInt(rawEpic, 10);
160
- if (Number.isNaN(epicId)) {
161
- throw new Error(
162
- `Invalid epic ID: "${rawEpic}" — must be a number.\n${USAGE}`,
163
- );
87
+ async function readOptional(filePath, { required }) {
88
+ try {
89
+ return await readFile(filePath, 'utf8');
90
+ } catch (err) {
91
+ if (!required && err?.code === 'ENOENT') return null;
92
+ throw new Error(`Cannot read ${filePath}: ${err.message}`);
164
93
  }
165
- return epicId;
166
94
  }
167
95
 
168
- /**
169
- * Resolve the artifact file paths. Existing-Epic mode defaults each path to
170
- * the per-Epic temp tree — the same locations the authoring skill writes to
171
- * — so a `--force`/`--resume` re-persist reuses the on-disk artifacts with
172
- * no re-typing (they survive until terminal success now that cleanup is
173
- * deferred). Ideation mode has no Epic id to derive from, so the paths must
174
- * be explicit.
175
- */
176
- function resolveArtifactPaths({ epicId, values, config }) {
177
- const fallback = (basename) =>
178
- epicId === null ? undefined : epicArtifactPath(epicId, basename, config);
179
- const techSpecPath = values['tech-spec'] ?? fallback('techspec.md');
180
- const riskVerdictPath =
181
- values['risk-verdict'] ?? fallback('risk-verdict.json');
182
- const ticketsPath = values.tickets ?? fallback('tickets.json');
183
- const acceptancePath =
184
- values['acceptance-table'] ?? fallback('acceptance-spec.md');
185
- if (!techSpecPath || !riskVerdictPath) {
96
+ async function readJsonFile(filePath, label) {
97
+ const raw = await readOptional(filePath, { required: true });
98
+ try {
99
+ return JSON.parse(raw);
100
+ } catch (err) {
186
101
  throw new Error(
187
- `Missing artifact path(s): ideation mode requires explicit --tech-spec and --risk-verdict.\n${USAGE}`,
102
+ `Failed to parse ${label} file "${filePath}" as JSON: ${err.message}`,
188
103
  );
189
104
  }
105
+ }
106
+
107
+ function resolveInputPaths(values) {
190
108
  return {
191
- techSpecPath,
192
- riskVerdictPath,
193
- ticketsPath,
194
- acceptancePath,
195
- acceptanceExplicit: values['acceptance-table'] !== undefined,
196
- ticketsExplicit: values.tickets !== undefined,
109
+ storiesPath: path.resolve(values.stories),
110
+ riskVerdictPath: path.resolve(values['risk-verdict']),
111
+ techSpecPath: values['tech-spec']
112
+ ? path.resolve(values['tech-spec'])
113
+ : null,
114
+ planAcceptancePath: values['plan-acceptance']
115
+ ? path.resolve(values['plan-acceptance'])
116
+ : null,
117
+ planDir: values['plan-dir'] ? path.resolve(values['plan-dir']) : null,
197
118
  };
198
119
  }
199
120
 
200
- async function readOptional(filePath, { required }) {
121
+ async function loadArtifacts(paths) {
122
+ const riskVerdict = loadRiskVerdict(paths.riskVerdictPath);
123
+ const stories = await readJsonFile(paths.storiesPath, 'stories');
124
+ const techSpecContent = paths.techSpecPath
125
+ ? await readOptional(paths.techSpecPath, { required: true })
126
+ : null;
127
+ const planAcceptance = paths.planAcceptancePath
128
+ ? await readJsonFile(paths.planAcceptancePath, 'plan-acceptance')
129
+ : null;
130
+
131
+ return { stories, riskVerdict, techSpecContent, planAcceptance };
132
+ }
133
+
134
+ function buildPersistOptions(values, paths) {
135
+ return {
136
+ forceReview: values['force-review'],
137
+ allowOverBudget: values['allow-over-budget'],
138
+ allowLargeFanOut: values['allow-large-fan-out'],
139
+ dryRun: values['dry-run'],
140
+ planRunId: values['plan-run-id'],
141
+ planDir: paths.planDir,
142
+ skipCleanup: values['dry-run'],
143
+ };
144
+ }
145
+
146
+ async function runPersistInvocation({ values, config, provider, artifacts }) {
147
+ const paths = resolveInputPaths(values);
148
+ const settings = {
149
+ baseBranch: config.project?.baseBranch,
150
+ paths: config.project?.paths,
151
+ planning: config.planning,
152
+ docsContextFiles: config.project?.docsContextFiles,
153
+ };
154
+
155
+ return recordPlanInvocation(
156
+ {
157
+ cli: 'plan-persist',
158
+ mode: values['dry-run'] ? 'dry-run' : 'persist',
159
+ config,
160
+ },
161
+ () =>
162
+ runPlanPersist({
163
+ provider,
164
+ artifacts,
165
+ config,
166
+ settings,
167
+ opts: buildPersistOptions(values, paths),
168
+ }),
169
+ );
170
+ }
171
+
172
+ async function attachPlanMetrics(result, config) {
201
173
  try {
202
- return await readFile(filePath, 'utf8');
174
+ const summary = summarizePlanMetrics(await readPlanMetrics(config));
175
+ if (summary) {
176
+ result.planMetrics = summary;
177
+ Logger.info(`[plan-persist] ${renderPlanMetricsSummaryLine(summary)}`);
178
+ }
203
179
  } catch (err) {
204
- if (!required && err?.code === 'ENOENT') return null;
205
- throw new Error(`Cannot read ${filePath}: ${err.message}`);
180
+ Logger.warn(`[plan-persist] plan-metrics summary skipped: ${err.message}`);
206
181
  }
207
182
  }
208
183
 
209
184
  async function main() {
210
185
  const { values } = parseArgs({ options: CLI_OPTIONS });
211
186
 
212
- if (values.force && values.resume) {
213
- throw new Error('--force and --resume are mutually exclusive.');
214
- }
215
- if (values.amend && (values.force || values.resume)) {
216
- throw new Error(
217
- '--amend is mutually exclusive with --force/--resume — the amend ' +
218
- 'delta is already an incremental re-persist.',
219
- );
220
- }
221
-
222
- const epicId = parseEpicId(values.epic);
223
- const onePagerPath = values['one-pager'];
224
- if (epicId === null && !onePagerPath) {
187
+ if (!values.stories || !values['risk-verdict']) {
225
188
  throw new Error(USAGE);
226
189
  }
227
- if (epicId !== null && onePagerPath) {
228
- throw new Error(
229
- '--epic and --one-pager are mutually exclusive (ideation mode opens ' +
230
- `the Epic itself).\n${USAGE}`,
231
- );
232
- }
233
190
 
234
191
  let config;
235
192
  try {
@@ -238,123 +195,19 @@ async function main() {
238
195
  } catch (err) {
239
196
  throw new Error(`Config schema validation failed:\n${err.message}`);
240
197
  }
241
- const settings = {
242
- baseBranch: config.project?.baseBranch,
243
- paths: config.project?.paths,
244
- planning: config.planning,
245
- docsContextFiles: config.project?.docsContextFiles,
246
- };
247
198
  const provider = createProvider(config);
199
+ const paths = resolveInputPaths(values);
200
+ const artifacts = await loadArtifacts(paths);
248
201
 
202
+ let result;
249
203
  try {
250
- await drainPendingCleanupAtBoot({
251
- repoRoot: PROJECT_ROOT,
204
+ result = await runPersistInvocation({
205
+ values,
252
206
  config,
253
207
  provider,
208
+ artifacts,
254
209
  });
255
210
  } catch (err) {
256
- Logger.warn(`[plan-persist] pending-cleanup drain skipped: ${err.message}`);
257
- }
258
-
259
- const {
260
- techSpecPath,
261
- riskVerdictPath,
262
- ticketsPath,
263
- acceptancePath,
264
- acceptanceExplicit,
265
- ticketsExplicit,
266
- } = resolveArtifactPaths({ epicId, values, config });
267
-
268
- // Deterministic local reads + validation before any GitHub call. A
269
- // malformed risk verdict fails closed here (Epic #3865); the section
270
- // gate itself runs first inside runPlanPersist.
271
- const techSpecContent = await readOptional(techSpecPath, { required: true });
272
- const riskVerdict = loadRiskVerdict(riskVerdictPath);
273
- // Tickets are mode-dependent (#4474 PR4): required when explicitly
274
- // passed or in --amend mode; otherwise best-effort — a single-delivery
275
- // plan authors no tickets file at all, and the mode-coherence gate
276
- // (`resolveDeliveryMode`) hard-errors on every contradictory combination
277
- // (including a stale tickets.json next to a `deliveryShape: "single"`
278
- // verdict).
279
- const ticketsRequired = ticketsExplicit || values.amend;
280
- const ticketsRaw = ticketsPath
281
- ? await readOptional(ticketsPath, { required: ticketsRequired })
282
- : null;
283
- let tickets = null;
284
- if (ticketsRaw !== null) {
285
- try {
286
- tickets = JSON.parse(ticketsRaw);
287
- } catch (err) {
288
- throw new Error(
289
- `Failed to parse tickets file "${ticketsPath}" as JSON: ${err.message}`,
290
- );
291
- }
292
- }
293
- // Acceptance table: explicit path is required to exist; the per-Epic
294
- // default is best-effort (absent file → no acceptance section, matching
295
- // the waived/none dispositions).
296
- const acceptanceSpecContent = acceptancePath
297
- ? await readOptional(acceptancePath, { required: acceptanceExplicit })
298
- : null;
299
- const onePagerContent = onePagerPath
300
- ? await readOptional(onePagerPath, { required: true })
301
- : null;
302
- const templateContent = onePagerContent
303
- ? await readOptional(EPIC_FROM_IDEA_TEMPLATE_PATH, { required: true })
304
- : null;
305
-
306
- // Plan-metrics ledger (#4474 PR1): stamp entry/exit + mode. Ideation runs
307
- // have no Epic id at entry, so they stamp on the standalone stream.
308
- const mode = values.amend
309
- ? 'amend'
310
- : values.resume
311
- ? 'resume'
312
- : values.force
313
- ? 'force'
314
- : 'persist';
315
- let result;
316
- try {
317
- result = await recordPlanInvocation(
318
- { cli: 'plan-persist', mode, epicId, config },
319
- () =>
320
- runPlanPersist({
321
- epicId,
322
- provider,
323
- artifacts: {
324
- techSpecContent,
325
- acceptanceSpecContent,
326
- riskVerdict,
327
- tickets,
328
- onePagerContent,
329
- templateContent,
330
- },
331
- config,
332
- settings,
333
- opts: {
334
- force: values.force,
335
- resume: values.resume,
336
- amend: values.amend,
337
- explicitDelete: values['explicit-delete'],
338
- steal: values.steal,
339
- forceReview: values['force-review'],
340
- allowOverBudget: values['allow-over-budget'],
341
- allowLargeFanOut: values['allow-large-fan-out'],
342
- },
343
- }),
344
- );
345
- } catch (err) {
346
- // Amend close-op confirmation gate (exit 2, mirroring the
347
- // epic-reconcile.js contract): print the dry-run diff so the operator
348
- // reviews exactly what would close, mutate nothing, and exit 2 so
349
- // non-interactive callers can branch on the code.
350
- if (err?.code === 'PLAN_AMEND_EXPLICIT_DELETE_REQUIRED') {
351
- process.stdout.write(`${err.diff}\n\n${err.message}\n`);
352
- process.exitCode = 2;
353
- return;
354
- }
355
- // Reachability soft failure (#4474 PR6): the orphan-surface list is the
356
- // message; nothing was mutated (the check runs before any provider
357
- // call). Exit 3 so non-interactive callers can branch on the code.
358
211
  if (err?.code === 'PLAN_REACHABILITY_ORPHANS') {
359
212
  process.stdout.write(`${err.message}\n`);
360
213
  process.exitCode = 3;
@@ -363,19 +216,7 @@ async function main() {
363
216
  throw err;
364
217
  }
365
218
 
366
- // Surface the whole plan run's invocation ledger in the persist summary
367
- // (#4474 PR1). Additive and best-effort.
368
- try {
369
- const summary = summarizePlanMetrics(
370
- await readPlanMetrics(result.epicId, config),
371
- );
372
- if (summary) {
373
- result.planMetrics = summary;
374
- Logger.info(`[plan-persist] ${renderPlanMetricsSummaryLine(summary)}`);
375
- }
376
- } catch (err) {
377
- Logger.warn(`[plan-persist] plan-metrics summary skipped: ${err.message}`);
378
- }
219
+ await attachPlanMetrics(result, config);
379
220
 
380
221
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
381
222
  }
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * plan-run-epilogue.js — execute the real per-run closeout for
4
+ * `/deliver --run <planRunId>` and positional multi-Story delivers.
5
+ *
6
+ * Usage:
7
+ * node .agents/scripts/plan-run-epilogue.js --run <planRunId>
8
+ * node .agents/scripts/plan-run-epilogue.js --run <planRunId> --stories 1,2,3
9
+ * node .agents/scripts/plan-run-epilogue.js --stories 1,2,3
10
+ *
11
+ * When `--stories` is omitted, `--run` is required and the set is resolved
12
+ * via plan-run labels (`state=all` so landed Stories are included).
13
+ * When `--stories` is supplied without `--run`, an adhoc planRunId is
14
+ * synthesized from the sorted Story ids.
15
+ */
16
+
17
+ import './lib/runtime-deps/ensure-installed.js';
18
+ import { parseArgs } from 'node:util';
19
+
20
+ import { runAsCli } from './lib/cli-utils.js';
21
+ import { resolveConfig } from './lib/config-resolver.js';
22
+ import { Logger } from './lib/Logger.js';
23
+ import {
24
+ fetchPlanRunIssues,
25
+ normalizePlanRunLabel,
26
+ resolvePlanRunFromIssues,
27
+ } from './lib/orchestration/resolve-plan-run.js';
28
+ import { runPlanRunEpilogue } from './lib/orchestration/run-epilogue.js';
29
+ import { createProvider } from './lib/provider-factory.js';
30
+
31
+ const CLI_OPTIONS = {
32
+ run: { type: 'string' },
33
+ stories: { type: 'string' },
34
+ cwd: { type: 'string' },
35
+ };
36
+
37
+ /**
38
+ * @param {string[]} [argv]
39
+ * @returns {Promise<object>}
40
+ */
41
+ export async function main(argv = process.argv.slice(2)) {
42
+ const { values } = parseArgs({
43
+ args: argv,
44
+ options: CLI_OPTIONS,
45
+ strict: false,
46
+ });
47
+ const runFlag = typeof values.run === 'string' ? values.run.trim() : '';
48
+ const hasStoriesFlag =
49
+ typeof values.stories === 'string' && values.stories.trim().length > 0;
50
+ if (!runFlag && !hasStoriesFlag) {
51
+ throw new Error(
52
+ 'Usage: node plan-run-epilogue.js (--run <planRunId> | --stories 1,2,3) [--stories 1,2,3]',
53
+ );
54
+ }
55
+ const cwd =
56
+ typeof values.cwd === 'string' && values.cwd.trim()
57
+ ? values.cwd.trim()
58
+ : process.cwd();
59
+ const config = resolveConfig({ cwd });
60
+ const provider = createProvider(config);
61
+
62
+ let stories = [];
63
+ if (hasStoriesFlag) {
64
+ stories = values.stories
65
+ .split(',')
66
+ .map((s) => Number(s.trim()))
67
+ .filter((n) => Number.isInteger(n) && n > 0);
68
+ } else {
69
+ const planRunLabel = normalizePlanRunLabel(runFlag);
70
+ const issues = await fetchPlanRunIssues(provider, {
71
+ planRunLabel,
72
+ state: 'all',
73
+ });
74
+ const envelope = resolvePlanRunFromIssues({ run: runFlag, issues });
75
+ stories = (envelope.stories ?? [])
76
+ .map((s) => Number(s?.id ?? s))
77
+ .filter((n) => Number.isInteger(n) && n > 0);
78
+ }
79
+
80
+ const planRunId =
81
+ runFlag || `adhoc-${[...stories].sort((a, b) => a - b).join('-')}`;
82
+
83
+ const result = await runPlanRunEpilogue({
84
+ planRunId,
85
+ stories,
86
+ provider,
87
+ config,
88
+ cwd,
89
+ });
90
+ Logger.info(JSON.stringify(result, null, 2));
91
+ if (result.errors?.length) {
92
+ process.exitCode = 1;
93
+ }
94
+ return result;
95
+ }
96
+
97
+ await runAsCli(import.meta.url, main);