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
@@ -0,0 +1,426 @@
1
+ /**
2
+ * run-epilogue.js — real per-run closeout for `/deliver --run`.
3
+ *
4
+ * After the last Story in a multi-Story plan-run lands, this module:
5
+ * 1. Selects the cross-Story audit lens roster over the combined landed
6
+ * tip vs base (deterministic `selectAudits` — host walks lenses).
7
+ * 2. Rolls up friction follow-ups across every Story in the run and
8
+ * files/posts them on the primary Story.
9
+ * 3. Checks sibling Spec/acceptance coherence across Story bodies.
10
+ *
11
+ * There is no inert planner-only path: `planRunEpilogue` enumerates steps
12
+ * and `runPlanRunEpilogue` executes them. Single-Story runs skip the
13
+ * epilogue (`applicable: false`).
14
+ *
15
+ * @module lib/orchestration/run-epilogue
16
+ */
17
+
18
+ import { selectAudits } from '../audit-suite/index.js';
19
+ import { graduateRetroProposals } from '../feedback-loop/retro-proposals-graduator.js';
20
+ import { gitSpawn } from '../git-utils.js';
21
+ import { Logger } from '../Logger.js';
22
+ import { forEachLine } from '../observability/signals-writer.js';
23
+ import { composeRoutedProposals } from './retro-proposals.js';
24
+ import {
25
+ buildFollowUpsCommentBody,
26
+ resolveFollowUpRepos,
27
+ } from './story-follow-ups.js';
28
+ import { upsertStructuredComment } from './ticketing.js';
29
+
30
+ /**
31
+ * Canonical epilogue step kinds, in execution order.
32
+ * @type {readonly ['audit-roster', 'follow-up-rollup', 'sibling-coherence']}
33
+ */
34
+ export const RUN_EPILOGUE_STEP_KINDS = Object.freeze([
35
+ 'audit-roster',
36
+ 'follow-up-rollup',
37
+ 'sibling-coherence',
38
+ ]);
39
+
40
+ /**
41
+ * @param {string|number|{ id?: string|number, slug?: string }} entry
42
+ * @returns {string|null}
43
+ */
44
+ function normalizeStoryId(entry) {
45
+ if (typeof entry === 'string') return entry.trim() || null;
46
+ if (typeof entry === 'number' && Number.isInteger(entry)) {
47
+ return String(entry);
48
+ }
49
+ if (!entry || typeof entry !== 'object') return null;
50
+ if (typeof entry.id === 'string' || Number.isInteger(entry.id)) {
51
+ return String(entry.id).trim() || null;
52
+ }
53
+ return typeof entry.slug === 'string' ? entry.slug.trim() || null : null;
54
+ }
55
+
56
+ /**
57
+ * @param {Array<string|number|{ id?: string|number, slug?: string }>} stories
58
+ * @returns {string[]}
59
+ */
60
+ function normalizeStoryIds(stories) {
61
+ const list = Array.isArray(stories) ? stories : [];
62
+ const seen = new Set();
63
+ const ids = [];
64
+ for (const entry of list) {
65
+ const id = normalizeStoryId(entry);
66
+ if (!id || seen.has(id)) continue;
67
+ seen.add(id);
68
+ ids.push(id);
69
+ }
70
+ return ids;
71
+ }
72
+
73
+ /**
74
+ * Enumerate the ordered epilogue steps for a completed run.
75
+ *
76
+ * @param {object} args
77
+ * @param {string} args.planRunId
78
+ * @param {Array<string|number|{ id?: string|number, slug?: string }>} args.stories
79
+ * @returns {object}
80
+ */
81
+ export function planRunEpilogue({ planRunId, stories } = {}) {
82
+ const ids = normalizeStoryIds(stories);
83
+ const runId =
84
+ typeof planRunId === 'string' && planRunId.trim() !== ''
85
+ ? planRunId.trim()
86
+ : null;
87
+
88
+ if (ids.length <= 1) {
89
+ return {
90
+ applicable: false,
91
+ planRunId: runId,
92
+ stories: ids,
93
+ steps: [],
94
+ reason:
95
+ ids.length === 0
96
+ ? 'no Stories in run'
97
+ : 'single-Story run — per-Story close is the end; no run-scoped epilogue',
98
+ };
99
+ }
100
+
101
+ // Positional `/deliver 101 102` has no plan-run label. Synthesize a
102
+ // stable adhoc id from the sorted Story set so the epilogue still
103
+ // anchors comments / audit roster without requiring `--run`.
104
+ const effectiveRunId =
105
+ runId ??
106
+ `adhoc-${[...ids].sort((a, b) => Number(a) - Number(b)).join('-')}`;
107
+
108
+ const steps = [
109
+ {
110
+ kind: 'audit-roster',
111
+ description: `Select cross-Story audit lenses for run ${effectiveRunId}`,
112
+ stories: ids,
113
+ },
114
+ {
115
+ kind: 'follow-up-rollup',
116
+ description: `Friction follow-up roll-up for run ${effectiveRunId}`,
117
+ stories: ids,
118
+ },
119
+ {
120
+ kind: 'sibling-coherence',
121
+ description: `Sibling-coherence check across the ${ids.length} Story specs of run ${effectiveRunId}`,
122
+ stories: ids,
123
+ },
124
+ ];
125
+
126
+ return {
127
+ applicable: true,
128
+ planRunId: effectiveRunId,
129
+ stories: ids,
130
+ steps,
131
+ };
132
+ }
133
+
134
+ async function listChangedFiles(cwd, baseRef = 'origin/main') {
135
+ try {
136
+ const result = gitSpawn(cwd, 'diff', '--name-only', `${baseRef}...HEAD`);
137
+ if (result.status !== 0) return [];
138
+ return String(result.stdout ?? '')
139
+ .split('\n')
140
+ .map((line) => line.trim())
141
+ .filter(Boolean);
142
+ } catch {
143
+ return [];
144
+ }
145
+ }
146
+
147
+ async function executeAuditRoster({ planRunId, stories, cwd, provider }) {
148
+ const primaryId = Number(stories[0]);
149
+ const changedFiles = await listChangedFiles(cwd);
150
+ let selectedAudits = [];
151
+ if (Number.isInteger(primaryId) && primaryId > 0) {
152
+ const selected = await selectAudits({
153
+ ticketId: primaryId,
154
+ gate: 'gate3',
155
+ provider,
156
+ baseBranch: 'main',
157
+ headRef: 'HEAD',
158
+ });
159
+ selectedAudits = Array.isArray(selected?.selectedAudits)
160
+ ? selected.selectedAudits
161
+ : Array.isArray(selected)
162
+ ? selected
163
+ : [];
164
+ }
165
+ const body = [
166
+ '### plan-run-audit-roster',
167
+ '',
168
+ `Cross-Story audit roster for plan-run \`${planRunId}\`.`,
169
+ '',
170
+ `Changed files considered: ${changedFiles.length}.`,
171
+ '',
172
+ '**Selected lenses** (host MUST walk each against the combined landed diff):',
173
+ ...(selectedAudits.length > 0
174
+ ? selectedAudits.map((lens) => `- \`${lens}\``)
175
+ : ['- _(none — docs-only or no matching change-set lenses)_']),
176
+ '',
177
+ '```json',
178
+ JSON.stringify(
179
+ {
180
+ planRunId,
181
+ stories: stories.map(Number),
182
+ changedFiles,
183
+ selectedAudits,
184
+ },
185
+ null,
186
+ 2,
187
+ ),
188
+ '```',
189
+ ].join('\n');
190
+ if (Number.isInteger(primaryId) && primaryId > 0) {
191
+ await upsertStructuredComment(
192
+ provider,
193
+ primaryId,
194
+ 'plan-run-audit-roster',
195
+ body,
196
+ );
197
+ }
198
+ return {
199
+ kind: 'audit-roster',
200
+ selectedAudits,
201
+ changedFileCount: changedFiles.length,
202
+ };
203
+ }
204
+
205
+ async function executeFollowUpRollup({
206
+ planRunId,
207
+ stories,
208
+ provider,
209
+ config,
210
+ cwd,
211
+ }) {
212
+ const signals = [];
213
+ for (const raw of stories) {
214
+ const sid = Number(raw);
215
+ if (!Number.isInteger(sid) || sid <= 0) continue;
216
+ await forEachLine(
217
+ null,
218
+ sid,
219
+ (parsed) => {
220
+ if (!parsed || typeof parsed !== 'object') return;
221
+ const category =
222
+ typeof parsed.category === 'string' ? parsed.category.trim() : '';
223
+ if (!category) return;
224
+ const source = parsed.source === 'framework' ? 'framework' : 'consumer';
225
+ signals.push({ category, source });
226
+ },
227
+ config,
228
+ );
229
+ }
230
+ const repos = resolveFollowUpRepos(config);
231
+ const primaryId = Number(stories[0]);
232
+ const proposals = composeRoutedProposals({
233
+ anchorId: Number.isInteger(primaryId) ? primaryId : 1,
234
+ anchorKind: 'run',
235
+ frameworkRepo: repos.frameworkRepo,
236
+ consumerRepo: repos.consumerRepo,
237
+ signals,
238
+ unresolvedBlockedEvents: [],
239
+ });
240
+ // Patch titles to mention the plan-run token (anchorKind run uses numeric id).
241
+ for (const item of [...proposals.framework, ...proposals.consumer]) {
242
+ item.title = item.title.replace(/plan-run \d+/, `plan-run ${planRunId}`);
243
+ item.body = item.body.replace(/plan-run \d+/g, `plan-run ${planRunId}`);
244
+ }
245
+ const graduated = await graduateRetroProposals({
246
+ epicId: primaryId,
247
+ provider,
248
+ config,
249
+ currentRepo: repos.currentRepo,
250
+ frameworkRepo: (() => {
251
+ const [owner, repo] = repos.frameworkRepo.split('/');
252
+ return { owner, repo };
253
+ })(),
254
+ routedProposals: proposals,
255
+ cwd,
256
+ });
257
+ if (Number.isInteger(primaryId) && primaryId > 0) {
258
+ const body = buildFollowUpsCommentBody({
259
+ storyId: primaryId,
260
+ proposals,
261
+ graduated,
262
+ }).replace(
263
+ `from Story #${primaryId}`,
264
+ `from plan-run \`${planRunId}\` (primary Story #${primaryId})`,
265
+ );
266
+ await upsertStructuredComment(provider, primaryId, 'follow-ups', body);
267
+ }
268
+ return {
269
+ kind: 'follow-up-rollup',
270
+ signalCount: signals.length,
271
+ filed: graduated.filed?.length ?? 0,
272
+ };
273
+ }
274
+
275
+ function extractSection(body, heading) {
276
+ if (typeof body !== 'string') return '';
277
+ const re = new RegExp(
278
+ `(?:^|\\n)## ${heading}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`,
279
+ 'i',
280
+ );
281
+ const match = body.match(re);
282
+ return match ? match[1].trim() : '';
283
+ }
284
+
285
+ async function executeSiblingCoherence({ planRunId, stories, provider }) {
286
+ const findings = [];
287
+ const bodies = [];
288
+ for (const raw of stories) {
289
+ const sid = Number(raw);
290
+ if (!Number.isInteger(sid) || sid <= 0) continue;
291
+ const ticket = await provider.getTicket(sid);
292
+ bodies.push({
293
+ id: sid,
294
+ title: ticket?.title ?? '',
295
+ acceptance: extractSection(ticket?.body ?? '', 'Acceptance'),
296
+ spec: extractSection(ticket?.body ?? '', 'Spec'),
297
+ });
298
+ }
299
+ const withAcceptance = bodies.filter((b) => b.acceptance.length > 0);
300
+ if (withAcceptance.length > 0 && withAcceptance.length < bodies.length) {
301
+ const missing = bodies
302
+ .filter((b) => b.acceptance.length === 0)
303
+ .map((b) => `#${b.id}`);
304
+ findings.push(
305
+ `Stories missing ## Acceptance while siblings declare ACs: ${missing.join(', ')}`,
306
+ );
307
+ }
308
+ // Detect identical non-empty Spec blobs (likely copy-paste drift).
309
+ const specMap = new Map();
310
+ for (const b of bodies) {
311
+ if (!b.spec) continue;
312
+ const key = b.spec.replace(/\s+/g, ' ').slice(0, 400);
313
+ if (!specMap.has(key)) specMap.set(key, []);
314
+ specMap.get(key).push(b.id);
315
+ }
316
+ for (const ids of specMap.values()) {
317
+ if (ids.length > 1) {
318
+ findings.push(
319
+ `Duplicate ## Spec prose across Stories ${ids.map((id) => `#${id}`).join(', ')} — split or dedupe.`,
320
+ );
321
+ }
322
+ }
323
+ const primaryId = Number(stories[0]);
324
+ const body = [
325
+ '### plan-run-sibling-coherence',
326
+ '',
327
+ `Sibling-coherence check for plan-run \`${planRunId}\`.`,
328
+ '',
329
+ findings.length === 0
330
+ ? '_No coherence findings._'
331
+ : findings.map((f) => `- ${f}`).join('\n'),
332
+ '',
333
+ '```json',
334
+ JSON.stringify(
335
+ { planRunId, stories: stories.map(Number), findings },
336
+ null,
337
+ 2,
338
+ ),
339
+ '```',
340
+ ].join('\n');
341
+ if (Number.isInteger(primaryId) && primaryId > 0) {
342
+ await upsertStructuredComment(
343
+ provider,
344
+ primaryId,
345
+ 'plan-run-sibling-coherence',
346
+ body,
347
+ );
348
+ }
349
+ return { kind: 'sibling-coherence', findings };
350
+ }
351
+
352
+ /**
353
+ * Execute the per-run epilogue. Throws only on programmer misuse; step
354
+ * failures are collected into `errors[]`.
355
+ *
356
+ * @param {object} args
357
+ * @param {string} args.planRunId
358
+ * @param {Array<string|number>} args.stories
359
+ * @param {object} args.provider
360
+ * @param {object} [args.config]
361
+ * @param {string} [args.cwd]
362
+ * @returns {Promise<object>}
363
+ */
364
+ export async function runPlanRunEpilogue({
365
+ planRunId,
366
+ stories,
367
+ provider,
368
+ config,
369
+ cwd = process.cwd(),
370
+ } = {}) {
371
+ const plan = planRunEpilogue({ planRunId, stories });
372
+ if (!plan.applicable) {
373
+ return { ...plan, results: [], errors: [] };
374
+ }
375
+ if (!provider || typeof provider.getTicket !== 'function') {
376
+ throw new TypeError('runPlanRunEpilogue requires a ticketing provider');
377
+ }
378
+
379
+ const results = [];
380
+ const errors = [];
381
+ for (const step of plan.steps) {
382
+ try {
383
+ if (step.kind === 'audit-roster') {
384
+ results.push(
385
+ await executeAuditRoster({
386
+ planRunId: plan.planRunId,
387
+ stories: plan.stories,
388
+ cwd,
389
+ provider,
390
+ }),
391
+ );
392
+ } else if (step.kind === 'follow-up-rollup') {
393
+ results.push(
394
+ await executeFollowUpRollup({
395
+ planRunId: plan.planRunId,
396
+ stories: plan.stories,
397
+ provider,
398
+ config,
399
+ cwd,
400
+ }),
401
+ );
402
+ } else if (step.kind === 'sibling-coherence') {
403
+ results.push(
404
+ await executeSiblingCoherence({
405
+ planRunId: plan.planRunId,
406
+ stories: plan.stories,
407
+ provider,
408
+ }),
409
+ );
410
+ }
411
+ } catch (err) {
412
+ const message = err?.message ?? String(err);
413
+ Logger.warn(`[run-epilogue] step ${step.kind} failed: ${message}`);
414
+ errors.push({ kind: step.kind, message });
415
+ }
416
+ }
417
+
418
+ return {
419
+ applicable: true,
420
+ planRunId: plan.planRunId,
421
+ stories: plan.stories,
422
+ steps: plan.steps,
423
+ results,
424
+ errors,
425
+ };
426
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * phases/auto-merge.js — enable GitHub native auto-merge on the PR.
3
3
  *
4
- * Mirrors the epic-deliver finalize call shape: squash strategy, delete
4
+ * Mirrors the v2 `single-story-close.js` finalize call shape: squash strategy, delete
5
5
  * the branch on merge. Non-fatal — returns `{ enabled: false, reason }`
6
6
  * on any failure so the caller can fall back to the operator-merges-button
7
7
  * path.
@@ -129,6 +129,7 @@ export async function runCloseValidationPhase({
129
129
  config,
130
130
  epicBranch: baseBranch,
131
131
  cwd: worktreePath || cwd,
132
+ log: (m) => Logger.info(m),
132
133
  }),
133
134
  log: (m) => Logger.info(m),
134
135
  storyId,
@@ -21,13 +21,14 @@
21
21
  * the caller raises that to a thrown error so auto-merge is not enabled.
22
22
  *
23
23
  * Delegates the `runCodeReview` invocation to `runStoryReviewCore`
24
- * (exported from `story-close/phases/code-review.js`) so both the
25
- * Epic-attached and standalone close paths share a single invocation
26
- * pattern (Story #3653).
24
+ * (exported from `story-close/phases/code-review.js`) so the close path
25
+ * shares a single invocation pattern (Story #3653). When `planningRisk`
26
+ * is omitted, loads it from the Story's `story-plan-state` checkpoint.
27
27
  */
28
28
 
29
29
  import { parsePrNumberFromUrl } from '../../../github-url.js';
30
30
  import { runStoryReviewCore } from '../../story-close/phases/code-review.js';
31
+ import { resolveStoryPlanningRisk } from '../../story-plan-state.js';
31
32
  import { postStructuredComment } from '../../ticketing/state.js';
32
33
 
33
34
  /**
@@ -71,6 +72,79 @@ export function buildStoryReviewCrossRefBody({
71
72
  );
72
73
  }
73
74
 
75
+ async function invokeStoryReviewCore({
76
+ storyId,
77
+ storyBranch,
78
+ baseBranch,
79
+ prNumber,
80
+ provider,
81
+ planningRisk,
82
+ runCodeReviewFn,
83
+ runLocalLensReviewFn,
84
+ progress,
85
+ }) {
86
+ return runStoryReviewCore({
87
+ storyId,
88
+ baseRef: baseBranch,
89
+ headRef: storyBranch,
90
+ commentTargetId: prNumber,
91
+ provider,
92
+ planningRisk: await resolveStoryPlanningRisk({
93
+ provider,
94
+ storyId,
95
+ planningRisk,
96
+ }),
97
+ progress,
98
+ progressTag: 'REVIEW',
99
+ runCodeReviewFn,
100
+ // Forward the seam only when the caller injects it; otherwise
101
+ // `runStoryReviewCore` uses its default local-lens pass. `undefined`
102
+ // deep-merges to the default via the destructuring default there.
103
+ ...(runLocalLensReviewFn ? { runLocalLensReviewFn } : {}),
104
+ });
105
+ }
106
+
107
+ async function postStoryReviewCrossRef({
108
+ provider,
109
+ storyId,
110
+ prUrl,
111
+ prNumber,
112
+ result,
113
+ severity,
114
+ progress,
115
+ }) {
116
+ if (result.posted && Number.isInteger(result.postedCommentId)) {
117
+ const commentUrl = `${prUrl}#issuecomment-${result.postedCommentId}`;
118
+ const body = buildStoryReviewCrossRefBody({
119
+ prUrl,
120
+ prNumber,
121
+ commentUrl,
122
+ severity,
123
+ });
124
+ try {
125
+ await postStructuredComment(provider, storyId, 'notification', body);
126
+ progress(
127
+ 'REVIEW',
128
+ `📝 Cross-reference comment posted on Story #${storyId} → ${commentUrl}`,
129
+ );
130
+ return true;
131
+ } catch (err) {
132
+ progress(
133
+ 'REVIEW',
134
+ `⚠️ Failed to post Story cross-reference comment: ${err?.message ?? err}`,
135
+ );
136
+ return false;
137
+ }
138
+ }
139
+ if (!result.posted) {
140
+ progress(
141
+ 'REVIEW',
142
+ '⚠️ Skipping Story cross-reference comment: PR-side review comment did not post.',
143
+ );
144
+ }
145
+ return false;
146
+ }
147
+
74
148
  /**
75
149
  * Run the Story-scope code review against `main`, post the structured
76
150
  * findings comment to the PR, and add a one-line cross-reference comment
@@ -93,6 +167,7 @@ export function buildStoryReviewCrossRefBody({
93
167
  * prUrl: string,
94
168
  * prNumber: number|null,
95
169
  * provider: object,
170
+ * planningRisk?: object|null, // omit to load from story-plan-state
96
171
  * runCodeReviewFn: Function,
97
172
  * runLocalLensReviewFn?: Function,
98
173
  * progress: (tag: string, msg: string) => void,
@@ -115,6 +190,7 @@ export async function runStoryScopeReview({
115
190
  prUrl,
116
191
  prNumber,
117
192
  provider,
193
+ planningRisk,
118
194
  runCodeReviewFn,
119
195
  runLocalLensReviewFn,
120
196
  progress,
@@ -132,19 +208,16 @@ export async function runStoryScopeReview({
132
208
  `Running Story-scope code review for Story #${storyId} (${baseBranch}...${storyBranch}) → PR #${prNumber}...`,
133
209
  );
134
210
 
135
- const result = await runStoryReviewCore({
211
+ const result = await invokeStoryReviewCore({
136
212
  storyId,
137
- baseRef: baseBranch,
138
- headRef: storyBranch,
139
- commentTargetId: prNumber,
213
+ storyBranch,
214
+ baseBranch,
215
+ prNumber,
140
216
  provider,
141
- progress,
142
- progressTag: 'REVIEW',
217
+ planningRisk,
143
218
  runCodeReviewFn,
144
- // Forward the seam only when the caller injects it; otherwise
145
- // `runStoryReviewCore` uses its default local-lens pass. `undefined`
146
- // deep-merges to the default via the destructuring default there.
147
- ...(runLocalLensReviewFn ? { runLocalLensReviewFn } : {}),
219
+ runLocalLensReviewFn,
220
+ progress,
148
221
  });
149
222
 
150
223
  const sev = result.severity ?? {
@@ -158,34 +231,15 @@ export async function runStoryScopeReview({
158
231
  `Findings — critical:${sev.critical} high:${sev.high} medium:${sev.medium} suggestion:${sev.suggestion}. Posted to PR #${prNumber}: ${result.posted}.`,
159
232
  );
160
233
 
161
- let crossRefPosted = false;
162
- if (result.posted && Number.isInteger(result.postedCommentId)) {
163
- const commentUrl = `${prUrl}#issuecomment-${result.postedCommentId}`;
164
- const body = buildStoryReviewCrossRefBody({
165
- prUrl,
166
- prNumber,
167
- commentUrl,
168
- severity: sev,
169
- });
170
- try {
171
- await postStructuredComment(provider, storyId, 'notification', body);
172
- crossRefPosted = true;
173
- progress(
174
- 'REVIEW',
175
- `📝 Cross-reference comment posted on Story #${storyId} → ${commentUrl}`,
176
- );
177
- } catch (err) {
178
- progress(
179
- 'REVIEW',
180
- `⚠️ Failed to post Story cross-reference comment: ${err?.message ?? err}`,
181
- );
182
- }
183
- } else if (!result.posted) {
184
- progress(
185
- 'REVIEW',
186
- '⚠️ Skipping Story cross-reference comment: PR-side review comment did not post.',
187
- );
188
- }
234
+ const crossRefPosted = await postStoryReviewCrossRef({
235
+ provider,
236
+ storyId,
237
+ prUrl,
238
+ prNumber,
239
+ result,
240
+ severity: sev,
241
+ progress,
242
+ });
189
243
 
190
244
  return {
191
245
  halted: !!result.halted,
@@ -10,6 +10,7 @@
10
10
 
11
11
  import path from 'node:path';
12
12
  import { parseSprintArgs } from '../../../cli-args.js';
13
+ import { getDeliveryRouting } from '../../../config/delivery-routing.js';
13
14
  import { PROJECT_ROOT } from '../../../project-root.js';
14
15
 
15
16
  /**
@@ -27,11 +28,12 @@ function resolveFlag(paramValue, parsedValue, defaultValue) {
27
28
  }
28
29
 
29
30
  /**
30
- * Resolve the `waitForMerge` option: an explicit `--no-wait-merge` opt-out
31
- * always wins (preserves the pre-Story-#4428 exit shape even if a future
32
- * headless wrapper defaults to waiting); otherwise the explicit
33
- * `--wait-merge` / injected value governs, defaulting to `false` so
34
- * attended (non-headless) invocations are byte-identical to before.
31
+ * Resolve the `waitForMerge` option:
32
+ * 1. `--no-wait-merge` / injected opt-out always wins (stop at
33
+ * `agent::closing`).
34
+ * 2. Explicit `--wait-merge` / injected true forces land-in-close.
35
+ * 3. Otherwise default from `delivery.routing.closeAndLand` (true) so
36
+ * attended and headless delivers share the close-and-land happy path.
35
37
  *
36
38
  * @param {{ waitForMergeParam, noWaitForMergeParam, parsed }} raw
37
39
  * @returns {boolean}
@@ -41,13 +43,12 @@ function resolveWaitForMerge({
41
43
  noWaitForMergeParam,
42
44
  parsed,
43
45
  }) {
44
- const optedOut = resolveFlag(
45
- noWaitForMergeParam,
46
- parsed.noWaitForMerge,
47
- false,
48
- );
49
- if (optedOut) return false;
50
- return resolveFlag(waitForMergeParam, parsed.waitForMerge, false);
46
+ if (resolveFlag(noWaitForMergeParam, parsed.noWaitForMerge, false)) {
47
+ return false;
48
+ }
49
+ const explicit = waitForMergeParam ?? parsed.waitForMerge;
50
+ if (typeof explicit === 'boolean') return explicit;
51
+ return getDeliveryRouting().closeAndLand;
51
52
  }
52
53
 
53
54
  /**
@@ -75,7 +76,9 @@ export function parseCloseOptions({
75
76
  skipSync: !!skipSyncParam,
76
77
  noAutoMerge: !!noAutoMergeParam,
77
78
  noFullScopeCrap: !!noFullScopeCrapParam,
78
- waitForMerge: !!waitForMergeParam,
79
+ // Preserve undefined so resolveWaitForMerge can apply the
80
+ // closeAndLand config default when neither flag was injected.
81
+ waitForMerge: waitForMergeParam,
79
82
  noWaitForMerge: !!noWaitForMergeParam,
80
83
  }
81
84
  : parseSprintArgs();