mandrel 1.93.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 (463) hide show
  1. package/.agents/README.md +59 -73
  2. package/.agents/agents/acceptance-critic.md +129 -0
  3. package/.agents/agents/story-worker.md +161 -0
  4. package/.agents/docs/SDLC.md +489 -1285
  5. package/.agents/docs/agentrc-reference.json +177 -67
  6. package/.agents/docs/configuration.md +108 -136
  7. package/.agents/docs/execution-reference.md +44 -22
  8. package/.agents/docs/quality-gates.md +13 -19
  9. package/.agents/docs/workflows.md +3 -3
  10. package/.agents/instructions.md +107 -108
  11. package/.agents/rules/ci-remediation.md +8 -12
  12. package/.agents/rules/git-conventions-reference.md +224 -0
  13. package/.agents/rules/git-conventions.md +42 -223
  14. package/.agents/rules/security-baseline.md +5 -0
  15. package/.agents/rules/testing-standards.md +106 -13
  16. package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
  17. package/.agents/schemas/agentrc.schema.json +71 -201
  18. package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
  19. package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
  20. package/.agents/schemas/risk-verdict.schema.json +0 -13
  21. package/.agents/scripts/acceptance-eval.js +62 -18
  22. package/.agents/scripts/agents-bootstrap-github.js +1 -1
  23. package/.agents/scripts/analyze-execution.js +1 -1
  24. package/.agents/scripts/audit-to-stories.js +7 -7
  25. package/.agents/scripts/boot-sweep.js +1 -1
  26. package/.agents/scripts/check-context-budget.js +62 -5
  27. package/.agents/scripts/check-lifecycle-lint.js +6 -9
  28. package/.agents/scripts/check-prepush-recovery.js +1 -1
  29. package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
  30. package/.agents/scripts/diagnose-friction.js +0 -6
  31. package/.agents/scripts/lib/Logger.js +6 -10
  32. package/.agents/scripts/lib/audit-suite/runner.js +2 -2
  33. package/.agents/scripts/lib/audit-suite/selector.js +5 -5
  34. package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
  35. package/.agents/scripts/lib/baselines/kernel.js +206 -18
  36. package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -4
  37. package/.agents/scripts/lib/baselines/reader.js +1 -6
  38. package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
  39. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
  40. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +56 -18
  41. package/.agents/scripts/lib/checks/core-bare-clean.js +2 -2
  42. package/.agents/scripts/lib/checks/index.js +2 -1
  43. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +23 -21
  44. package/.agents/scripts/lib/cli/standard-args.js +13 -22
  45. package/.agents/scripts/lib/cli-args.js +16 -7
  46. package/.agents/scripts/lib/close-validation/gates.js +160 -22
  47. package/.agents/scripts/lib/config/acceptance-eval.js +52 -5
  48. package/.agents/scripts/lib/config/ci.js +6 -31
  49. package/.agents/scripts/lib/config/delivery-routing.js +103 -0
  50. package/.agents/scripts/lib/config/explain.js +57 -36
  51. package/.agents/scripts/lib/config/limits.js +17 -58
  52. package/.agents/scripts/lib/config/paths.js +0 -2
  53. package/.agents/scripts/lib/config/quality.js +1 -1
  54. package/.agents/scripts/lib/config/runners.js +17 -50
  55. package/.agents/scripts/lib/config/temp-paths.js +19 -14
  56. package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
  57. package/.agents/scripts/lib/config-resolver.js +3 -8
  58. package/.agents/scripts/lib/config-settings-schema-delivery.js +46 -136
  59. package/.agents/scripts/lib/config-settings-schema-quality.js +17 -14
  60. package/.agents/scripts/lib/config-settings-schema.js +52 -38
  61. package/.agents/scripts/lib/dependency-parser.js +3 -2
  62. package/.agents/scripts/lib/doc-tiers.js +39 -4
  63. package/.agents/scripts/lib/duplicate-search.js +211 -41
  64. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
  65. package/.agents/scripts/lib/findings/promote-finding.js +5 -5
  66. package/.agents/scripts/lib/framework-version.js +2 -3
  67. package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
  68. package/.agents/scripts/lib/git-branch-lifecycle.js +17 -22
  69. package/.agents/scripts/lib/git-utils.js +32 -6
  70. package/.agents/scripts/lib/github/framework-repo.js +6 -0
  71. package/.agents/scripts/lib/label-constants.js +10 -23
  72. package/.agents/scripts/lib/label-taxonomy.js +9 -43
  73. package/.agents/scripts/lib/observability/active-story-env.js +112 -3
  74. package/.agents/scripts/lib/observability/hook-heartbeat.js +187 -0
  75. package/.agents/scripts/lib/observability/source-classifier.js +3 -3
  76. package/.agents/scripts/lib/observability/tool-trace-hook.js +15 -4
  77. package/.agents/scripts/lib/onboard/init-tail.js +1 -3
  78. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +111 -0
  79. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +32 -4
  80. package/.agents/scripts/lib/orchestration/audit-lens-routing.js +128 -0
  81. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +273 -0
  82. package/.agents/scripts/lib/orchestration/ceremony-routing.js +204 -0
  83. package/.agents/scripts/lib/orchestration/code-review.js +20 -268
  84. package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
  85. package/.agents/scripts/lib/orchestration/consolidation-precondition.js +1 -1
  86. package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
  87. package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
  88. package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
  89. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
  90. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +8 -8
  91. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +2 -2
  92. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
  93. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +17 -43
  94. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
  95. package/.agents/scripts/lib/orchestration/merge-block-class.js +1 -1
  96. package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
  97. package/.agents/scripts/lib/orchestration/plan-context.js +248 -266
  98. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +3 -2
  99. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +1 -1
  100. package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
  101. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +61 -0
  102. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +97 -0
  103. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +223 -854
  104. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +361 -0
  105. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +35 -108
  106. package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
  107. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
  108. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +14 -14
  109. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
  110. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/risk-verdict.js +3 -4
  111. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +2 -2
  112. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +8 -20
  113. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +3 -2
  114. package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
  115. package/.agents/scripts/lib/orchestration/preflight-cache.js +5 -5
  116. package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
  117. package/.agents/scripts/lib/orchestration/resolve-plan-run.js +155 -0
  118. package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
  119. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +8 -8
  120. package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
  121. package/.agents/scripts/lib/orchestration/review-depth.js +26 -12
  122. package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
  123. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
  124. package/.agents/scripts/lib/orchestration/run-epilogue.js +426 -0
  125. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +1 -1
  126. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +1 -0
  127. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +95 -41
  128. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +16 -13
  129. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +40 -0
  130. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +11 -3
  131. package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
  132. package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
  133. package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
  134. package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
  135. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
  136. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +15 -12
  137. package/.agents/scripts/lib/orchestration/story-follow-ups.js +237 -0
  138. package/.agents/scripts/lib/orchestration/story-init-remote.js +47 -0
  139. package/.agents/scripts/lib/orchestration/story-plan-state.js +48 -0
  140. package/.agents/scripts/lib/orchestration/{epic-runner → story-progress}/story-run-progress-writer.js +3 -3
  141. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
  142. package/.agents/scripts/lib/orchestration/task-body-validator.js +8 -18
  143. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +11 -61
  144. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +189 -373
  145. package/.agents/scripts/lib/orchestration/ticket-validator.js +3 -8
  146. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +0 -25
  147. package/.agents/scripts/lib/orchestration/ticketing/reads.js +29 -26
  148. package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -5
  149. package/.agents/scripts/lib/planning-corpus.js +16 -11
  150. package/.agents/scripts/lib/preflight-runner.js +2 -2
  151. package/.agents/scripts/lib/provider-factory.js +1 -1
  152. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
  153. package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +36 -0
  154. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
  155. package/.agents/scripts/lib/story-adjacency.js +11 -14
  156. package/.agents/scripts/lib/story-body/story-body.js +124 -70
  157. package/.agents/scripts/lib/story-plan.js +2 -4
  158. package/.agents/scripts/lib/templates/decomposer-prompts.js +46 -45
  159. package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
  160. package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +26 -26
  161. package/.agents/scripts/lib/validation-evidence.js +1 -1
  162. package/.agents/scripts/lib/wave-runner/ready-set.js +6 -6
  163. package/.agents/scripts/lib/workspace-provisioner.js +1 -1
  164. package/.agents/scripts/lib/worktree/lifecycle/reap.js +5 -7
  165. package/.agents/scripts/lint-issue-body.js +71 -40
  166. package/.agents/scripts/mandrel-update-preflight.js +1 -1
  167. package/.agents/scripts/notify.js +4 -3
  168. package/.agents/scripts/plan-context.js +64 -74
  169. package/.agents/scripts/plan-persist.js +121 -280
  170. package/.agents/scripts/plan-run-epilogue.js +97 -0
  171. package/.agents/scripts/post-structured-comment.js +38 -0
  172. package/.agents/scripts/providers/github/issues.js +17 -33
  173. package/.agents/scripts/providers/github/mappers.js +0 -12
  174. package/.agents/scripts/providers/github/tickets.js +2 -5
  175. package/.agents/scripts/resolve-plan-run.js +117 -0
  176. package/.agents/scripts/signals-view.js +24 -19
  177. package/.agents/scripts/single-story-close.js +11 -14
  178. package/.agents/scripts/single-story-confirm-merge.js +39 -23
  179. package/.agents/scripts/single-story-init.js +29 -20
  180. package/.agents/scripts/stories-wave-tick.js +6 -6
  181. package/.agents/scripts/story-plan.js +26 -47
  182. package/.agents/scripts/sync-claude-agents.js +165 -0
  183. package/.agents/scripts/update-ticket-state.js +37 -15
  184. package/.agents/skills/core/analyze-execution/SKILL.md +21 -18
  185. package/.agents/skills/core/api-and-interface-design/SKILL.md +5 -3
  186. package/.agents/skills/core/code-review-and-quality/SKILL.md +63 -7
  187. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +1 -1
  188. package/.agents/skills/core/gates-and-baselines/SKILL.md +149 -0
  189. package/.agents/skills/core/idea-refinement/SKILL.md +8 -14
  190. package/.agents/skills/core/qa-coverage-mapping/SKILL.md +7 -7
  191. package/.agents/skills/core/scope-triage/SKILL.md +28 -172
  192. package/.agents/skills/skills.index.json +8 -418
  193. package/.agents/starter-agentrc.json +0 -5
  194. package/.agents/templates/agent-protocol.md +9 -10
  195. package/.agents/workflows/audit-architecture.md +3 -3
  196. package/.agents/workflows/audit-clean-code.md +3 -3
  197. package/.agents/workflows/audit-dependencies.md +3 -3
  198. package/.agents/workflows/audit-devops.md +3 -3
  199. package/.agents/workflows/audit-documentation.md +5 -5
  200. package/.agents/workflows/audit-lighthouse.md +3 -3
  201. package/.agents/workflows/audit-navigability.md +3 -2
  202. package/.agents/workflows/audit-performance.md +3 -3
  203. package/.agents/workflows/audit-privacy.md +3 -3
  204. package/.agents/workflows/audit-quality.md +3 -3
  205. package/.agents/workflows/audit-security.md +3 -3
  206. package/.agents/workflows/audit-seo.md +3 -3
  207. package/.agents/workflows/audit-sre.md +3 -3
  208. package/.agents/workflows/audit-to-stories.md +20 -20
  209. package/.agents/workflows/audit-ux-ui.md +3 -3
  210. package/.agents/workflows/deliver.md +122 -131
  211. package/.agents/workflows/git-cleanup.md +3 -4
  212. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  213. package/.agents/workflows/helpers/acceptance-self-eval.md +52 -40
  214. package/.agents/workflows/helpers/code-review.md +70 -193
  215. package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +12 -14
  216. package/.agents/workflows/helpers/{single-story-deliver.md → deliver-story.md} +113 -139
  217. package/.agents/workflows/helpers/diagnose.md +10 -10
  218. package/.agents/workflows/helpers/mandrel-sync-config.md +1 -1
  219. package/.agents/workflows/helpers/parallel-tooling.md +1 -1
  220. package/.agents/workflows/helpers/signals.md +16 -16
  221. package/.agents/workflows/helpers/worktree-lifecycle.md +48 -64
  222. package/.agents/workflows/mandrel-update.md +3 -2
  223. package/.agents/workflows/plan.md +112 -145
  224. package/.agents/workflows/qa-assist.md +24 -30
  225. package/.agents/workflows/qa-explore.md +29 -38
  226. package/.agents/workflows/qa-run.md +2 -2
  227. package/README.md +9 -8
  228. package/docs/CHANGELOG.md +46 -0
  229. package/lib/cli/registry.js +95 -0
  230. package/lib/migrations/index.js +6 -5
  231. package/package.json +5 -3
  232. package/.agents/personas/architect.md +0 -113
  233. package/.agents/personas/devops-engineer.md +0 -38
  234. package/.agents/personas/engineer-mobile.md +0 -120
  235. package/.agents/personas/engineer-web.md +0 -111
  236. package/.agents/personas/engineer.md +0 -119
  237. package/.agents/personas/product.md +0 -94
  238. package/.agents/personas/project-manager.md +0 -114
  239. package/.agents/personas/qa-engineer.md +0 -95
  240. package/.agents/personas/refactorer.md +0 -113
  241. package/.agents/personas/security-engineer.md +0 -112
  242. package/.agents/personas/sre.md +0 -86
  243. package/.agents/personas/technical-writer.md +0 -101
  244. package/.agents/personas/ux-designer.md +0 -95
  245. package/.agents/schemas/dispatch-manifest.json +0 -232
  246. package/.agents/schemas/epic-spec.schema.json +0 -153
  247. package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
  248. package/.agents/scripts/dispatcher.js +0 -295
  249. package/.agents/scripts/epic-audit-prepare.js +0 -497
  250. package/.agents/scripts/epic-audit-recheck.js +0 -274
  251. package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
  252. package/.agents/scripts/epic-deliver-preflight.js +0 -462
  253. package/.agents/scripts/epic-deliver-prepare.js +0 -590
  254. package/.agents/scripts/epic-execute-record-wave.js +0 -449
  255. package/.agents/scripts/epic-plan-clarity.js +0 -211
  256. package/.agents/scripts/epic-plan-decompose.js +0 -54
  257. package/.agents/scripts/epic-plan-healthcheck.js +0 -581
  258. package/.agents/scripts/epic-plan-spec.js +0 -64
  259. package/.agents/scripts/epic-reconcile.js +0 -625
  260. package/.agents/scripts/lib/baseline-snapshot.js +0 -979
  261. package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
  262. package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
  263. package/.agents/scripts/lib/config/lifecycle.js +0 -40
  264. package/.agents/scripts/lib/config/preflight.js +0 -58
  265. package/.agents/scripts/lib/config/retro.js +0 -77
  266. package/.agents/scripts/lib/epic-merge-lock.js +0 -322
  267. package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
  268. package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
  269. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -660
  270. package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
  271. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
  272. package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
  273. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
  274. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
  275. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
  276. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
  277. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
  278. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
  279. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
  280. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
  281. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
  282. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
  283. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
  284. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
  285. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
  286. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
  287. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
  288. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -388
  289. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
  290. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
  291. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
  292. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
  293. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
  294. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
  295. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
  296. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
  297. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
  298. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
  299. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
  300. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
  301. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
  302. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
  303. package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
  304. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
  305. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
  306. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
  307. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
  308. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
  309. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
  310. package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
  311. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
  312. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
  313. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -384
  314. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
  315. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
  316. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
  317. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -278
  318. package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
  319. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
  320. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
  321. package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
  322. package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
  323. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
  324. package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
  325. package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
  326. package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
  327. package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
  328. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
  329. package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
  330. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
  331. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
  332. package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
  333. package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
  334. package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
  335. package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +0 -109
  336. package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
  337. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
  338. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
  339. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
  340. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
  341. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
  342. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
  343. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
  344. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
  345. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
  346. package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
  347. package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
  348. package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
  349. package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
  350. package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
  351. package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
  352. package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
  353. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
  354. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
  355. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
  356. package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
  357. package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
  358. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
  359. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
  360. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
  361. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -301
  362. package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
  363. package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
  364. package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
  365. package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
  366. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
  367. package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
  368. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
  369. package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
  370. package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
  371. package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
  372. package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
  373. package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
  374. package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
  375. package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
  376. package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
  377. package/.agents/scripts/lib/push-epic-retry.js +0 -209
  378. package/.agents/scripts/lib/spec/index.js +0 -36
  379. package/.agents/scripts/lib/spec/loader.js +0 -425
  380. package/.agents/scripts/lib/spec/state.js +0 -208
  381. package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
  382. package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
  383. package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
  384. package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
  385. package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
  386. package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
  387. package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
  388. package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
  389. package/.agents/scripts/lib/wave-runner/tick.js +0 -754
  390. package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
  391. package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
  392. package/.agents/scripts/lifecycle-emit.js +0 -510
  393. package/.agents/scripts/plan-critics.js +0 -199
  394. package/.agents/scripts/retro-run.js +0 -218
  395. package/.agents/scripts/standalone-feedback-rollup.js +0 -188
  396. package/.agents/scripts/story-close.js +0 -294
  397. package/.agents/scripts/story-init.js +0 -599
  398. package/.agents/scripts/story-phase.js +0 -369
  399. package/.agents/scripts/wave-tick.js +0 -335
  400. package/.agents/skills/core/baseline-refresh/SKILL.md +0 -181
  401. package/.agents/skills/core/ci-cd-and-automation/SKILL.md +0 -274
  402. package/.agents/skills/core/ci-cd-and-automation/examples.md +0 -211
  403. package/.agents/skills/core/code-simplification/SKILL.md +0 -389
  404. package/.agents/skills/core/context-engineering/SKILL.md +0 -309
  405. package/.agents/skills/core/context-engineering/examples.md +0 -58
  406. package/.agents/skills/core/deprecation-and-migration/SKILL.md +0 -250
  407. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
  408. package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
  409. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
  410. package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
  411. package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
  412. package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
  413. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -413
  414. package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
  415. package/.agents/skills/core/frontend-ui-engineering/SKILL.md +0 -357
  416. package/.agents/skills/core/hydrate-context/SKILL.md +0 -123
  417. package/.agents/skills/core/idea-refinement/examples.md +0 -437
  418. package/.agents/skills/core/idea-refinement/frameworks.md +0 -135
  419. package/.agents/skills/core/incremental-implementation/SKILL.md +0 -271
  420. package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +0 -213
  421. package/.agents/skills/core/knowledge-transfer/SKILL.md +0 -180
  422. package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +0 -117
  423. package/.agents/skills/core/performance-optimization/SKILL.md +0 -314
  424. package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +0 -277
  425. package/.agents/skills/core/property-based-testing/SKILL.md +0 -148
  426. package/.agents/skills/core/refactoring-discipline/SKILL.md +0 -111
  427. package/.agents/skills/core/shipping-and-launch/SKILL.md +0 -328
  428. package/.agents/skills/core/spec-driven-development/SKILL.md +0 -252
  429. package/.agents/skills/core/test-driven-development/SKILL.md +0 -475
  430. package/.agents/skills/core/using-agent-skills/SKILL.md +0 -232
  431. package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +0 -31
  432. package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +0 -51
  433. package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +0 -76
  434. package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +0 -31
  435. package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +0 -33
  436. package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +0 -31
  437. package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +0 -51
  438. package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +0 -54
  439. package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +0 -29
  440. package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +0 -30
  441. package/.agents/skills/stack/backend/stripe-integration/SKILL.md +0 -57
  442. package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +0 -9
  443. package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +0 -48
  444. package/.agents/skills/stack/frontend/astro/SKILL.md +0 -62
  445. package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +0 -30
  446. package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +0 -29
  447. package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +0 -50
  448. package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +0 -58
  449. package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +0 -34
  450. package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +0 -51
  451. package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +0 -199
  452. package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +0 -68
  453. package/.agents/workflows/helpers/deliver-epic-reference.md +0 -534
  454. package/.agents/workflows/helpers/deliver-epic.md +0 -955
  455. package/.agents/workflows/helpers/deliver-stories.md +0 -440
  456. package/.agents/workflows/helpers/epic-audit.md +0 -189
  457. package/.agents/workflows/helpers/epic-deliver-story.md +0 -427
  458. package/.agents/workflows/helpers/epic-testing.md +0 -125
  459. package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
  460. package/.agents/workflows/helpers/plan-epic.md +0 -351
  461. package/.agents/workflows/helpers/plan-story.md +0 -251
  462. package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
  463. /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);
@@ -22,6 +22,10 @@ import fs from 'node:fs/promises';
22
22
  import { parseArgs } from 'node:util';
23
23
  import { runAsCli } from './lib/cli-utils.js';
24
24
  import { resolveConfig } from './lib/config-resolver.js';
25
+ import {
26
+ outboxPathFor,
27
+ postCommentOrBuffer,
28
+ } from './lib/orchestration/bookkeeping-outbox.js';
25
29
  import {
26
30
  assertValidStructuredCommentType,
27
31
  upsertStructuredComment,
@@ -37,6 +41,11 @@ Flags:
37
41
  retro, epic-run-state, wave-0-start) (required).
38
42
  --body-file Path to a file containing the markdown body (required).
39
43
  --provider Provider name (default: inferred from .agentrc.json github block).
44
+ --buffer Headless mode: buffer this upsert to the per-Epic bookkeeping
45
+ outbox instead of posting live. Requires --epic. Drained to
46
+ GitHub once at finalize by bookkeeping-reconcile.js (Epic
47
+ #4476). Omit for attended runs (posts live, unchanged).
48
+ --epic <id> Epic id owning the outbox (required with --buffer).
40
49
  --help Show this message.
41
50
  `;
42
51
 
@@ -64,6 +73,8 @@ export function parseArgv(argv) {
64
73
  marker: { type: 'string' },
65
74
  'body-file': { type: 'string' },
66
75
  provider: { type: 'string' },
76
+ buffer: { type: 'boolean' },
77
+ epic: { type: 'string' },
67
78
  help: { type: 'boolean' },
68
79
  },
69
80
  strict: false,
@@ -115,6 +126,33 @@ export async function main(argv = process.argv.slice(2)) {
115
126
  : config;
116
127
  const provider = createProvider(effectiveConfig);
117
128
 
129
+ // Headless buffering (Epic #4476 M5): route the upsert to the per-Epic
130
+ // outbox instead of a live GitHub round-trip. Requires --epic to locate the
131
+ // outbox; finalize's bookkeeping-reconcile.js drains it once. Attended runs
132
+ // (no --buffer) are unchanged.
133
+ if (values.buffer) {
134
+ const epicId = Number.parseInt(values.epic ?? '', 10);
135
+ if (!Number.isInteger(epicId) || epicId <= 0) {
136
+ process.stderr.write(
137
+ '[post-structured-comment] --buffer requires --epic <id>.\n',
138
+ );
139
+ process.exit(2);
140
+ }
141
+ assertValidStructuredCommentType(values.marker);
142
+ const { buffered } = await postCommentOrBuffer({
143
+ provider,
144
+ ticketId,
145
+ marker: values.marker,
146
+ body,
147
+ headless: true,
148
+ outboxPath: outboxPathFor(epicId, config),
149
+ });
150
+ process.stdout.write(
151
+ `${JSON.stringify({ success: true, ticketId, type: values.marker, buffered })}\n`,
152
+ );
153
+ return;
154
+ }
155
+
118
156
  const envelope = await runPostStructuredComment({
119
157
  ticketId,
120
158
  type: values.marker,