mandrel 1.94.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (393) hide show
  1. package/.agents/README.md +59 -73
  2. package/.agents/agents/story-worker.md +12 -13
  3. package/.agents/docs/SDLC.md +489 -1285
  4. package/.agents/docs/agentrc-reference.json +177 -67
  5. package/.agents/docs/configuration.md +104 -138
  6. package/.agents/docs/execution-reference.md +17 -20
  7. package/.agents/docs/quality-gates.md +13 -19
  8. package/.agents/docs/workflows.md +3 -3
  9. package/.agents/instructions.md +70 -81
  10. package/.agents/rules/ci-remediation.md +8 -12
  11. package/.agents/rules/git-conventions-reference.md +6 -7
  12. package/.agents/rules/git-conventions.md +16 -22
  13. package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
  14. package/.agents/schemas/agentrc.schema.json +54 -214
  15. package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
  16. package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
  17. package/.agents/schemas/risk-verdict.schema.json +0 -13
  18. package/.agents/scripts/analyze-execution.js +1 -1
  19. package/.agents/scripts/audit-to-stories.js +7 -7
  20. package/.agents/scripts/boot-sweep.js +1 -1
  21. package/.agents/scripts/check-lifecycle-lint.js +6 -9
  22. package/.agents/scripts/check-prepush-recovery.js +1 -1
  23. package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
  24. package/.agents/scripts/lib/Logger.js +6 -10
  25. package/.agents/scripts/lib/audit-suite/runner.js +2 -2
  26. package/.agents/scripts/lib/audit-suite/selector.js +5 -5
  27. package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
  28. package/.agents/scripts/lib/baselines/kernel.js +206 -18
  29. package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -4
  30. package/.agents/scripts/lib/baselines/reader.js +1 -6
  31. package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
  32. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
  33. package/.agents/scripts/lib/checks/core-bare-clean.js +2 -2
  34. package/.agents/scripts/lib/checks/index.js +2 -1
  35. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +23 -21
  36. package/.agents/scripts/lib/cli/standard-args.js +13 -22
  37. package/.agents/scripts/lib/cli-args.js +16 -7
  38. package/.agents/scripts/lib/close-validation/gates.js +2 -2
  39. package/.agents/scripts/lib/config/ci.js +6 -31
  40. package/.agents/scripts/lib/config/delivery-routing.js +45 -29
  41. package/.agents/scripts/lib/config/explain.js +55 -36
  42. package/.agents/scripts/lib/config/limits.js +17 -58
  43. package/.agents/scripts/lib/config/paths.js +0 -2
  44. package/.agents/scripts/lib/config/quality.js +1 -1
  45. package/.agents/scripts/lib/config/runners.js +17 -50
  46. package/.agents/scripts/lib/config/temp-paths.js +19 -14
  47. package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
  48. package/.agents/scripts/lib/config-resolver.js +2 -7
  49. package/.agents/scripts/lib/config-settings-schema-delivery.js +24 -148
  50. package/.agents/scripts/lib/config-settings-schema-quality.js +8 -14
  51. package/.agents/scripts/lib/config-settings-schema.js +52 -38
  52. package/.agents/scripts/lib/dependency-parser.js +3 -2
  53. package/.agents/scripts/lib/doc-tiers.js +2 -2
  54. package/.agents/scripts/lib/duplicate-search.js +211 -41
  55. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
  56. package/.agents/scripts/lib/findings/promote-finding.js +5 -5
  57. package/.agents/scripts/lib/framework-version.js +2 -3
  58. package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
  59. package/.agents/scripts/lib/git-branch-lifecycle.js +17 -22
  60. package/.agents/scripts/lib/git-utils.js +32 -6
  61. package/.agents/scripts/lib/github/framework-repo.js +6 -0
  62. package/.agents/scripts/lib/label-constants.js +10 -23
  63. package/.agents/scripts/lib/label-taxonomy.js +9 -43
  64. package/.agents/scripts/lib/observability/active-story-env.js +1 -1
  65. package/.agents/scripts/lib/observability/hook-heartbeat.js +20 -52
  66. package/.agents/scripts/lib/observability/source-classifier.js +3 -3
  67. package/.agents/scripts/lib/onboard/init-tail.js +1 -3
  68. package/.agents/scripts/lib/orchestration/audit-lens-routing.js +128 -0
  69. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +8 -5
  70. package/.agents/scripts/lib/orchestration/ceremony-routing.js +83 -20
  71. package/.agents/scripts/lib/orchestration/code-review.js +20 -268
  72. package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
  73. package/.agents/scripts/lib/orchestration/consolidation-precondition.js +1 -1
  74. package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
  75. package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
  76. package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
  77. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
  78. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +8 -8
  79. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +2 -2
  80. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
  81. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +17 -43
  82. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
  83. package/.agents/scripts/lib/orchestration/merge-block-class.js +1 -1
  84. package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
  85. package/.agents/scripts/lib/orchestration/plan-context.js +248 -266
  86. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +1 -1
  87. package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
  88. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +61 -0
  89. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +97 -0
  90. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +223 -854
  91. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +361 -0
  92. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +35 -108
  93. package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
  94. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
  95. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +13 -13
  96. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
  97. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/risk-verdict.js +3 -4
  98. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +2 -2
  99. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +8 -20
  100. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +3 -2
  101. package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
  102. package/.agents/scripts/lib/orchestration/preflight-cache.js +5 -5
  103. package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
  104. package/.agents/scripts/lib/orchestration/resolve-plan-run.js +155 -0
  105. package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
  106. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +8 -8
  107. package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
  108. package/.agents/scripts/lib/orchestration/review-depth.js +26 -12
  109. package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
  110. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
  111. package/.agents/scripts/lib/orchestration/run-epilogue.js +426 -0
  112. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +1 -1
  113. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +95 -41
  114. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +16 -13
  115. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +40 -0
  116. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +11 -3
  117. package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
  118. package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
  119. package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
  120. package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
  121. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
  122. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +15 -12
  123. package/.agents/scripts/lib/orchestration/story-follow-ups.js +237 -0
  124. package/.agents/scripts/lib/orchestration/story-init-remote.js +47 -0
  125. package/.agents/scripts/lib/orchestration/story-plan-state.js +48 -0
  126. package/.agents/scripts/lib/orchestration/{epic-runner → story-progress}/story-run-progress-writer.js +3 -3
  127. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
  128. package/.agents/scripts/lib/orchestration/task-body-validator.js +8 -18
  129. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +11 -61
  130. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +189 -373
  131. package/.agents/scripts/lib/orchestration/ticket-validator.js +2 -7
  132. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +0 -25
  133. package/.agents/scripts/lib/orchestration/ticketing/reads.js +29 -26
  134. package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -5
  135. package/.agents/scripts/lib/planning-corpus.js +16 -11
  136. package/.agents/scripts/lib/preflight-runner.js +2 -2
  137. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
  138. package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +36 -0
  139. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
  140. package/.agents/scripts/lib/story-adjacency.js +11 -14
  141. package/.agents/scripts/lib/story-body/story-body.js +124 -70
  142. package/.agents/scripts/lib/story-plan.js +2 -4
  143. package/.agents/scripts/lib/templates/decomposer-prompts.js +46 -45
  144. package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
  145. package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +26 -26
  146. package/.agents/scripts/lib/validation-evidence.js +1 -1
  147. package/.agents/scripts/lib/wave-runner/ready-set.js +6 -6
  148. package/.agents/scripts/lib/workspace-provisioner.js +1 -1
  149. package/.agents/scripts/lib/worktree/lifecycle/reap.js +5 -7
  150. package/.agents/scripts/lint-issue-body.js +71 -40
  151. package/.agents/scripts/mandrel-update-preflight.js +1 -1
  152. package/.agents/scripts/notify.js +4 -3
  153. package/.agents/scripts/plan-context.js +64 -74
  154. package/.agents/scripts/plan-persist.js +121 -280
  155. package/.agents/scripts/plan-run-epilogue.js +97 -0
  156. package/.agents/scripts/providers/github/issues.js +17 -33
  157. package/.agents/scripts/providers/github/mappers.js +0 -12
  158. package/.agents/scripts/providers/github/tickets.js +2 -5
  159. package/.agents/scripts/resolve-plan-run.js +117 -0
  160. package/.agents/scripts/signals-view.js +24 -19
  161. package/.agents/scripts/single-story-close.js +11 -14
  162. package/.agents/scripts/single-story-confirm-merge.js +39 -23
  163. package/.agents/scripts/single-story-init.js +29 -20
  164. package/.agents/scripts/stories-wave-tick.js +6 -6
  165. package/.agents/scripts/story-plan.js +26 -47
  166. package/.agents/scripts/update-ticket-state.js +6 -15
  167. package/.agents/skills/core/analyze-execution/SKILL.md +21 -18
  168. package/.agents/skills/core/idea-refinement/SKILL.md +6 -6
  169. package/.agents/skills/core/scope-triage/SKILL.md +28 -172
  170. package/.agents/skills/skills.index.json +3 -43
  171. package/.agents/starter-agentrc.json +0 -5
  172. package/.agents/templates/agent-protocol.md +9 -10
  173. package/.agents/workflows/audit-architecture.md +3 -3
  174. package/.agents/workflows/audit-clean-code.md +3 -3
  175. package/.agents/workflows/audit-dependencies.md +3 -3
  176. package/.agents/workflows/audit-devops.md +3 -3
  177. package/.agents/workflows/audit-documentation.md +5 -5
  178. package/.agents/workflows/audit-lighthouse.md +3 -3
  179. package/.agents/workflows/audit-navigability.md +3 -2
  180. package/.agents/workflows/audit-performance.md +3 -3
  181. package/.agents/workflows/audit-privacy.md +3 -3
  182. package/.agents/workflows/audit-quality.md +3 -3
  183. package/.agents/workflows/audit-security.md +3 -3
  184. package/.agents/workflows/audit-seo.md +3 -3
  185. package/.agents/workflows/audit-sre.md +3 -3
  186. package/.agents/workflows/audit-to-stories.md +20 -20
  187. package/.agents/workflows/audit-ux-ui.md +3 -3
  188. package/.agents/workflows/deliver.md +122 -174
  189. package/.agents/workflows/git-cleanup.md +3 -4
  190. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  191. package/.agents/workflows/helpers/acceptance-self-eval.md +16 -29
  192. package/.agents/workflows/helpers/code-review.md +70 -193
  193. package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +12 -14
  194. package/.agents/workflows/helpers/{single-story-deliver.md → deliver-story.md} +113 -139
  195. package/.agents/workflows/helpers/diagnose.md +10 -10
  196. package/.agents/workflows/helpers/parallel-tooling.md +1 -1
  197. package/.agents/workflows/helpers/signals.md +16 -16
  198. package/.agents/workflows/helpers/worktree-lifecycle.md +48 -64
  199. package/.agents/workflows/mandrel-update.md +2 -1
  200. package/.agents/workflows/plan.md +112 -145
  201. package/.agents/workflows/qa-assist.md +24 -30
  202. package/.agents/workflows/qa-explore.md +29 -38
  203. package/.agents/workflows/qa-run.md +2 -2
  204. package/README.md +9 -8
  205. package/docs/CHANGELOG.md +30 -0
  206. package/lib/migrations/index.js +6 -5
  207. package/package.json +2 -2
  208. package/.agents/agents/retro.md +0 -42
  209. package/.agents/personas/architect.md +0 -113
  210. package/.agents/personas/devops-engineer.md +0 -38
  211. package/.agents/personas/engineer.md +0 -33
  212. package/.agents/personas/project-manager.md +0 -114
  213. package/.agents/personas/qa-engineer.md +0 -95
  214. package/.agents/personas/security-engineer.md +0 -111
  215. package/.agents/personas/technical-writer.md +0 -101
  216. package/.agents/schemas/dispatch-manifest.json +0 -232
  217. package/.agents/schemas/epic-spec.schema.json +0 -153
  218. package/.agents/schemas/lifecycle/slice.end.schema.json +0 -21
  219. package/.agents/schemas/lifecycle/slice.heartbeat.schema.json +0 -20
  220. package/.agents/schemas/lifecycle/slice.start.schema.json +0 -17
  221. package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
  222. package/.agents/scripts/bookkeeping-reconcile.js +0 -117
  223. package/.agents/scripts/dispatcher.js +0 -295
  224. package/.agents/scripts/epic-audit-prepare.js +0 -497
  225. package/.agents/scripts/epic-audit-recheck.js +0 -274
  226. package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
  227. package/.agents/scripts/epic-deliver-preflight.js +0 -462
  228. package/.agents/scripts/epic-deliver-prepare.js +0 -852
  229. package/.agents/scripts/epic-execute-record-wave.js +0 -449
  230. package/.agents/scripts/epic-plan-clarity.js +0 -211
  231. package/.agents/scripts/epic-plan-healthcheck.js +0 -581
  232. package/.agents/scripts/epic-reconcile.js +0 -625
  233. package/.agents/scripts/lib/baseline-snapshot.js +0 -979
  234. package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
  235. package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
  236. package/.agents/scripts/lib/config/lifecycle.js +0 -40
  237. package/.agents/scripts/lib/config/preflight.js +0 -58
  238. package/.agents/scripts/lib/config/retro.js +0 -77
  239. package/.agents/scripts/lib/epic-merge-lock.js +0 -322
  240. package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
  241. package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
  242. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -539
  243. package/.agents/scripts/lib/orchestration/deliver-route.js +0 -173
  244. package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
  245. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
  246. package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
  247. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
  248. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
  249. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
  250. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
  251. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
  252. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
  253. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
  254. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
  255. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
  256. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
  257. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
  258. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
  259. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
  260. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
  261. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
  262. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -621
  263. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
  264. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
  265. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
  266. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
  267. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
  268. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
  269. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
  270. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
  271. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
  272. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
  273. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
  274. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
  275. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
  276. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
  277. package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
  278. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
  279. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
  280. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
  281. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
  282. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
  283. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
  284. package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
  285. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
  286. package/.agents/scripts/lib/orchestration/lifecycle/emit-slice-lifecycle.js +0 -270
  287. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
  288. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -465
  289. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
  290. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
  291. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
  292. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -284
  293. package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
  294. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
  295. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
  296. package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
  297. package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
  298. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
  299. package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
  300. package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
  301. package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
  302. package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
  303. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
  304. package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
  305. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
  306. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
  307. package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
  308. package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
  309. package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
  310. package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
  311. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
  312. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
  313. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
  314. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
  315. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
  316. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
  317. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
  318. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
  319. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
  320. package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
  321. package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
  322. package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
  323. package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
  324. package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
  325. package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
  326. package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
  327. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
  328. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
  329. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
  330. package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
  331. package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
  332. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
  333. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
  334. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
  335. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -302
  336. package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
  337. package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
  338. package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
  339. package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
  340. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
  341. package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
  342. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
  343. package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
  344. package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
  345. package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
  346. package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
  347. package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
  348. package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
  349. package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
  350. package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
  351. package/.agents/scripts/lib/push-epic-retry.js +0 -209
  352. package/.agents/scripts/lib/spec/index.js +0 -36
  353. package/.agents/scripts/lib/spec/loader.js +0 -425
  354. package/.agents/scripts/lib/spec/state.js +0 -208
  355. package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
  356. package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
  357. package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
  358. package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
  359. package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
  360. package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
  361. package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
  362. package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
  363. package/.agents/scripts/lib/wave-runner/tick.js +0 -754
  364. package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
  365. package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
  366. package/.agents/scripts/lifecycle-emit.js +0 -510
  367. package/.agents/scripts/retro-run.js +0 -218
  368. package/.agents/scripts/slice-phase.js +0 -361
  369. package/.agents/scripts/standalone-feedback-rollup.js +0 -188
  370. package/.agents/scripts/story-close.js +0 -294
  371. package/.agents/scripts/story-init.js +0 -599
  372. package/.agents/scripts/story-phase.js +0 -369
  373. package/.agents/scripts/wave-tick.js +0 -464
  374. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
  375. package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
  376. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
  377. package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
  378. package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
  379. package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
  380. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -383
  381. package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
  382. package/.agents/workflows/helpers/deliver-epic-reference.md +0 -547
  383. package/.agents/workflows/helpers/deliver-epic-single.md +0 -331
  384. package/.agents/workflows/helpers/deliver-epic.md +0 -998
  385. package/.agents/workflows/helpers/deliver-stories.md +0 -450
  386. package/.agents/workflows/helpers/epic-audit.md +0 -189
  387. package/.agents/workflows/helpers/epic-deliver-story.md +0 -436
  388. package/.agents/workflows/helpers/epic-testing.md +0 -125
  389. package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
  390. package/.agents/workflows/helpers/plan-epic.md +0 -353
  391. package/.agents/workflows/helpers/plan-story.md +0 -251
  392. package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
  393. /package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +0 -0
@@ -1,198 +0,0 @@
1
- /**
2
- * merge-subject.js — assemble the conventional-commit subject used by
3
- * `runFinalizeMerge` and `runResumeMerge` and auto-truncate it on a
4
- * word boundary when it would exceed commitlint's `header-max-length`.
5
- *
6
- * Story #2466 (Epic #2453) auto-generated a 102-char merge subject that
7
- * commitlint rejected; `story-close.js`'s merge step silently rolled
8
- * back to staged-only on each retry. This helper prevents the rejection
9
- * by shaping the subject pre-commit:
10
- *
11
- * - The Conventional-Commits prefix (`<type>(<scope>): ` if scope is
12
- * provided, otherwise `<type>: `) is preserved verbatim.
13
- * - The ` (resolves #N)` suffix is preserved verbatim.
14
- * - The title segment is truncated on a word boundary (whitespace),
15
- * never mid-word, until the assembled subject's byte length fits
16
- * within the cap.
17
- * - On truncation, an operator-facing `Logger.warn` fires once and a
18
- * `truncated-from: <original>` body trailer is returned so the
19
- * caller can append it to the commit body.
20
- *
21
- * The cap is loaded from commitlint config via `@commitlint/load`,
22
- * cached per-cwd, and falls back to 100 (the
23
- * `@commitlint/config-conventional` default) when load fails.
24
- *
25
- * Pure (the shape function) + cached async loader. No I/O at shape time.
26
- */
27
-
28
- import path from 'node:path';
29
- import { Logger as DefaultLogger } from '../../Logger.js';
30
- import { resolvesToken } from '../resolves-token.js';
31
-
32
- const COMMITLINT_DEFAULT_HEADER_MAX_LENGTH = 100;
33
- const headerCapCache = new Map();
34
-
35
- /**
36
- * Load commitlint's `header-max-length` rule value for the given cwd.
37
- * Caches the resolved cap per absolute cwd so repeated close-path calls
38
- * inside a single process do not re-read commitlint config.
39
- *
40
- * Returns the default (100) when commitlint is not installed, the
41
- * config is missing, or the rule is absent / disabled.
42
- *
43
- * @param {string} cwd
44
- * @param {{ logger?: { warn?: Function } }} [opts]
45
- * @returns {Promise<number>}
46
- */
47
- export async function loadHeaderMaxLength(cwd, opts = {}) {
48
- const logger = opts.logger ?? DefaultLogger;
49
- const key = path.resolve(cwd);
50
- if (headerCapCache.has(key)) return headerCapCache.get(key);
51
- let cap = COMMITLINT_DEFAULT_HEADER_MAX_LENGTH;
52
- try {
53
- const mod = await import('@commitlint/load');
54
- const load = mod.default ?? mod.load ?? mod;
55
- const loaded = await load({}, { cwd: key });
56
- const rule = loaded?.rules?.['header-max-length'];
57
- if (Array.isArray(rule) && rule.length >= 3) {
58
- const [level, _applicable, value] = rule;
59
- if (level > 0 && Number.isFinite(value) && value > 0) {
60
- cap = value;
61
- }
62
- }
63
- } catch (err) {
64
- logger?.warn?.(
65
- `[merge-subject] commitlint header-max-length load failed; ` +
66
- `using default ${COMMITLINT_DEFAULT_HEADER_MAX_LENGTH}: ${err?.message ?? err}`,
67
- );
68
- }
69
- headerCapCache.set(key, cap);
70
- return cap;
71
- }
72
-
73
- /**
74
- * Test-only: clear the per-cwd cap cache.
75
- */
76
- export function _resetHeaderMaxLengthCache() {
77
- headerCapCache.clear();
78
- }
79
-
80
- function buildPrefix(type, scope) {
81
- return scope ? `${type}(${scope}): ` : `${type}: `;
82
- }
83
-
84
- // Caps the `truncated-from: <subject>` trailer at `cap` bytes so it
85
- // satisfies commitlint's `footer-max-line-length` rule. Without this
86
- // cap, an original subject near the header cap (100) produces a
87
- // ~116-char trailer line.
88
- function buildTruncatedFromTrailer(originalSubject, cap) {
89
- const prefix = 'truncated-from: ';
90
- const budget = Math.max(0, cap - Buffer.byteLength(prefix, 'utf8'));
91
- if (Buffer.byteLength(originalSubject, 'utf8') <= budget) {
92
- return `${prefix}${originalSubject}`;
93
- }
94
- const ellipsisBytes = Buffer.byteLength('…', 'utf8');
95
- let value = originalSubject;
96
- while (Buffer.byteLength(value, 'utf8') + ellipsisBytes > budget) {
97
- value = value.slice(0, -1);
98
- }
99
- return `${prefix}${value}…`;
100
- }
101
-
102
- function truncateTitleOnWordBoundary(title, budget) {
103
- if (budget <= 0) return '';
104
- if (Buffer.byteLength(title, 'utf8') <= budget) return title;
105
- // Greedy: drop trailing tokens until the title fits the byte budget.
106
- let truncated = title;
107
- while (Buffer.byteLength(truncated, 'utf8') > budget) {
108
- const lastWs = truncated.search(/\s+\S*$/u);
109
- if (lastWs <= 0) {
110
- // No earlier whitespace — fall back to byte-safe slice.
111
- truncated = truncated.slice(0, Math.max(0, truncated.length - 1));
112
- continue;
113
- }
114
- truncated = truncated.slice(0, lastWs);
115
- }
116
- return truncated.replace(/\s+$/u, '');
117
- }
118
-
119
- /**
120
- * Shape a Conventional-Commits subject so it fits within `headerMaxLength`.
121
- *
122
- * Returns `{ subject, original, truncated, bodyTrailer }`:
123
- * - `subject` — the (possibly truncated) one-line subject.
124
- * - `original` — the un-truncated subject (always populated).
125
- * - `truncated` — boolean, true iff truncation fired.
126
- * - `bodyTrailer` — `truncated-from: <original>` when truncated, else null.
127
- *
128
- * Side effects: on truncation, emits a single `Logger.warn` line naming
129
- * the original and truncated subjects.
130
- *
131
- * @param {{
132
- * type: string,
133
- * scope?: string|null,
134
- * title: string,
135
- * storyId: number|string,
136
- * headerMaxLength?: number,
137
- * logger?: { warn?: Function },
138
- * }} args
139
- * @returns {{ subject: string, original: string, truncated: boolean, bodyTrailer: string|null }}
140
- */
141
- export function shapeMergeSubject({
142
- type,
143
- scope = null,
144
- title,
145
- storyId,
146
- headerMaxLength = COMMITLINT_DEFAULT_HEADER_MAX_LENGTH,
147
- logger = DefaultLogger,
148
- }) {
149
- const lcTitle = title.charAt(0).toLowerCase() + title.slice(1);
150
- const prefix = buildPrefix(type, scope);
151
- const suffix = resolvesToken(storyId);
152
- const originalSubject = `${prefix}${lcTitle}${suffix}`;
153
- if (Buffer.byteLength(originalSubject, 'utf8') <= headerMaxLength) {
154
- return {
155
- subject: originalSubject,
156
- original: originalSubject,
157
- truncated: false,
158
- bodyTrailer: null,
159
- };
160
- }
161
- const fixedBytes =
162
- Buffer.byteLength(prefix, 'utf8') + Buffer.byteLength(suffix, 'utf8');
163
- const titleBudget = headerMaxLength - fixedBytes;
164
- const truncatedTitle = truncateTitleOnWordBoundary(lcTitle, titleBudget);
165
- const subject = `${prefix}${truncatedTitle}${suffix}`;
166
- logger?.warn?.(
167
- `[merge-subject] subject exceeded commitlint cap (${headerMaxLength}); ` +
168
- `truncated on word boundary. original="${originalSubject}" ` +
169
- `truncated="${subject}"`,
170
- );
171
- return {
172
- subject,
173
- original: originalSubject,
174
- truncated: true,
175
- bodyTrailer: buildTruncatedFromTrailer(originalSubject, headerMaxLength),
176
- };
177
- }
178
-
179
- /**
180
- * Convenience: shape a subject and assemble the final commit message
181
- * (subject plus optional trailer block). Returns a single string suitable
182
- * for passing as the `-m` argument to `git commit` / `git merge`.
183
- *
184
- * @param {Parameters<typeof shapeMergeSubject>[0]} args
185
- * @returns {{ message: string, subject: string, original: string, truncated: boolean }}
186
- */
187
- export function buildMergeMessageWithCap(args) {
188
- const shaped = shapeMergeSubject(args);
189
- const message = shaped.bodyTrailer
190
- ? `${shaped.subject}\n\n${shaped.bodyTrailer}`
191
- : shaped.subject;
192
- return {
193
- message,
194
- subject: shaped.subject,
195
- original: shaped.original,
196
- truncated: shaped.truncated,
197
- };
198
- }
@@ -1,105 +0,0 @@
1
- /**
2
- * phases/branch-restore.js — capture + restore the main-repo's starting
3
- * branch around the merge-lock-protected close (Story #2138 / #2141; moved
4
- * into the phases pipeline by Story #2460, Epic #2453).
5
- *
6
- * The orchestrator captures the starting branch BEFORE entering the
7
- * merge lock and runs `restoreStartingBranch` in a `finally` block, so
8
- * any throw inside `runStoryCloseLocked` leaves the operator on the
9
- * branch they came in on rather than stranded mid-rebase / mid-merge.
10
- *
11
- * Public surface:
12
- * - captureStartingBranch(cwd, deps?) ← exported (story-close.js re-export)
13
- * - restoreStartingBranch(opts, deps?) ← exported (story-close.js re-export)
14
- */
15
-
16
- import { gitSpawn as defaultGitSpawn } from '../../../git-utils.js';
17
- import { Logger } from '../../../Logger.js';
18
-
19
- /**
20
- * Capture the main-repo's current branch name before `runStoryCloseLocked`
21
- * runs. Returns `{ ok: true, branch }` on success, `{ ok: false, reason }`
22
- * when HEAD is detached or `git rev-parse` fails.
23
- *
24
- * @param {string} cwd
25
- * @param {{ gitSpawn?: typeof defaultGitSpawn }} [deps]
26
- * @returns {{ ok: true, branch: string } | { ok: false, reason: string }}
27
- */
28
- export function captureStartingBranch(cwd, deps = {}) {
29
- const gitSpawn = deps.gitSpawn ?? defaultGitSpawn;
30
- const res = gitSpawn(cwd, 'rev-parse', '--abbrev-ref', 'HEAD');
31
- if (res.status !== 0) {
32
- return {
33
- ok: false,
34
- reason: `rev-parse-failed: ${res.stderr || 'unknown'}`,
35
- };
36
- }
37
- const branch = (res.stdout || '').trim();
38
- if (!branch || branch === 'HEAD') {
39
- return { ok: false, reason: 'detached-head' };
40
- }
41
- return { ok: true, branch };
42
- }
43
-
44
- /**
45
- * Restore the main-repo to `startingBranch` via `git switch`. Refuses the
46
- * switch when the destination tree is dirty (`git status --porcelain` is
47
- * non-empty). Never invokes `git reset --hard` or `git checkout --force`.
48
- *
49
- * Returns a structured envelope so callers (and tests) can assert which
50
- * branch they end up on and why.
51
- *
52
- * @param {object} opts
53
- * @param {string} opts.cwd
54
- * @param {{ ok: boolean, branch?: string, reason?: string }} opts.captured
55
- * @param {{ gitSpawn?: typeof defaultGitSpawn, logger?: object }} [deps]
56
- * @returns {{ restored: boolean, branch?: string, reason?: string, skipped?: boolean }}
57
- */
58
- export function restoreStartingBranch({ cwd, captured }, deps = {}) {
59
- const gitSpawn = deps.gitSpawn ?? defaultGitSpawn;
60
- const log = deps.logger ?? Logger;
61
- if (!captured || captured.ok !== true) {
62
- return {
63
- restored: false,
64
- skipped: true,
65
- reason: captured?.reason
66
- ? `no-starting-branch: ${captured.reason}`
67
- : 'no-starting-branch',
68
- };
69
- }
70
- const { branch } = captured;
71
- const currentRes = gitSpawn(cwd, 'rev-parse', '--abbrev-ref', 'HEAD');
72
- if (currentRes.status === 0 && currentRes.stdout.trim() === branch) {
73
- return { restored: true, branch, reason: 'already-on-branch' };
74
- }
75
- const statusRes = gitSpawn(cwd, 'status', '--porcelain');
76
- if (statusRes.status !== 0) {
77
- log.warn?.(
78
- `[story-close] branch-restore: \`git status --porcelain\` failed in ${cwd}: ${statusRes.stderr || 'unknown'}`,
79
- );
80
- return {
81
- restored: false,
82
- branch,
83
- reason: `status-failed: ${statusRes.stderr || 'unknown'}`,
84
- };
85
- }
86
- if (statusRes.stdout.length > 0) {
87
- log.error?.(
88
- `[story-close] branch-restore: refusing to switch to \`${branch}\` — working tree is dirty in ${cwd}. ` +
89
- `Resolve the local changes manually, then \`git switch ${branch}\`.`,
90
- );
91
- return { restored: false, branch, reason: 'dirty-tree' };
92
- }
93
- const switchRes = gitSpawn(cwd, 'switch', branch);
94
- if (switchRes.status !== 0) {
95
- log.warn?.(
96
- `[story-close] branch-restore: \`git switch ${branch}\` failed: ${switchRes.stderr || 'unknown'}`,
97
- );
98
- return {
99
- restored: false,
100
- branch,
101
- reason: `switch-failed: ${switchRes.stderr || 'unknown'}`,
102
- };
103
- }
104
- return { restored: true, branch };
105
- }
@@ -1,222 +0,0 @@
1
- /**
2
- * phases/close.js — merge + post-merge pipeline phase (Story #2460,
3
- * Epic #2453 — CLI thinning pilot).
4
- *
5
- * Runs once the pre-merge gates have passed (or been skipped on a
6
- * resume path). Owns:
7
- * - the resume-aware merge runner dispatch (`runResumeMerge` vs
8
- * `runFinalizeMerge`, skipped entirely on a `resumeFromPostMerge` path),
9
- * - the post-merge close pipeline (ticket transitions, cascade, health,
10
- * dashboard regen) via `runPostMergeClose`,
11
- * - the success-path close-result envelope serialisation.
12
- *
13
- * Public surface:
14
- * - runMergePhase(ctx)
15
- * - runPostMergePhase(ctx)
16
- * - runClosePhase(ctx) ← composite (merge → post-merge)
17
- *
18
- * The split between `runMergePhase` and `runPostMergePhase` keeps each
19
- * function at one level of abstraction (and well under the < 200 LOC /
20
- * CC < 12 phase-file budget).
21
- */
22
-
23
- import { Logger } from '../../../Logger.js';
24
- import { PROJECT_ROOT } from '../../../project-root.js';
25
- import { STATE_LABELS } from '../../ticketing.js';
26
- import { runFinalizeMerge, runResumeMerge } from '../merge-runner.js';
27
- import { runPostMergeClose } from '../post-merge-close.js';
28
-
29
- /**
30
- * Story #2961 — final assertion that the Story ticket reached
31
- * `agent::done` after the post-merge cascade. The cascade is the single
32
- * writer of the `closing → done` label flip; without this readback,
33
- * `runStoryClose` returns `success: true` even when the flip silently
34
- * failed (the failure mode that Epic #2880 wave 0's friction note
35
- * F-W0-2 surfaced via the runner's GitHub probe — see Story #2894).
36
- *
37
- * Outcomes:
38
- * - `{ ok: true }` — ticket has `agent::done` (or is closed).
39
- * - `{ ok: false, actualLabels }` — cascade returned but the label
40
- * never reached `agent::done`. The caller must downgrade
41
- * `success: true` → `success: false`.
42
- * - `{ ok: 'skipped', warning }` — `provider.getTicket` threw. The
43
- * verification could not run, but the close itself succeeded, so
44
- * the caller returns the success envelope with a `warnings[]` entry.
45
- */
46
- export async function verifyFinalStoryLabel({ provider, storyId }) {
47
- if (!provider || typeof provider.getTicket !== 'function') {
48
- return {
49
- ok: 'skipped',
50
- warning: `label-verification-skipped: provider.getTicket unavailable`,
51
- };
52
- }
53
- let ticket;
54
- try {
55
- ticket = await provider.getTicket(storyId, { fresh: true });
56
- } catch (err) {
57
- return {
58
- ok: 'skipped',
59
- warning: `label-verification-skipped: ${err?.message ?? err}`,
60
- };
61
- }
62
- const labels = Array.isArray(ticket?.labels) ? ticket.labels : [];
63
- if (labels.includes(STATE_LABELS.DONE) || ticket?.state === 'closed') {
64
- return { ok: true };
65
- }
66
- return { ok: false, actualLabels: labels };
67
- }
68
-
69
- /**
70
- * Run the merge step. Skipped entirely on the already-merged resume path
71
- * — the merge already landed on `origin/epic/<id>` during the prior close
72
- * attempt; the only remaining work is the post-merge pipeline.
73
- */
74
- export async function runMergePhase(ctx) {
75
- const {
76
- resumeFromConflict,
77
- resumeFromPostMerge,
78
- cwd,
79
- epicBranch,
80
- storyBranch,
81
- story,
82
- storyId,
83
- epicId,
84
- config,
85
- bus,
86
- progress,
87
- progressLog,
88
- } = ctx;
89
-
90
- if (resumeFromPostMerge) {
91
- progress(
92
- 'MERGE',
93
- `Skipping rebase + merge — story tip already reachable from ${epicBranch}`,
94
- );
95
- return;
96
- }
97
-
98
- const mergeArgs = {
99
- cwd,
100
- epicBranch,
101
- storyBranch,
102
- storyTitle: story.title,
103
- storyId,
104
- epicId,
105
- config,
106
- bus,
107
- log: progressLog,
108
- };
109
- await (resumeFromConflict ? runResumeMerge : runFinalizeMerge)(mergeArgs);
110
- }
111
-
112
- /**
113
- * Run the post-merge close pipeline — ticket transitions, cascade, health
114
- * regen, dashboard regen. Returns the final close-result envelope.
115
- */
116
- export async function runPostMergePhase(ctx) {
117
- const {
118
- config,
119
- storyId,
120
- epicId,
121
- story,
122
- storyBranch,
123
- epicBranch,
124
- cwd,
125
- provider,
126
- notifyFn,
127
- tasks,
128
- skipDashboard,
129
- progress,
130
- phaseTimer,
131
- clearPhaseTimerState,
132
- bus,
133
- } = ctx;
134
-
135
- return runPostMergeClose({
136
- config,
137
- storyId,
138
- epicId,
139
- story,
140
- storyBranch,
141
- epicBranch,
142
- cwd,
143
- projectRoot: PROJECT_ROOT,
144
- provider,
145
- notify: notifyFn,
146
- tasks,
147
- skipDashboard,
148
- progress,
149
- logger: Logger,
150
- phaseTimer,
151
- clearPhaseTimerState,
152
- bus,
153
- });
154
- }
155
-
156
- /**
157
- * Pure envelope builder. Given the post-merge `result` and the
158
- * `verifyFinalStoryLabel` verdict, returns the close-result envelope
159
- * `runClosePhase` will surface back to `runStoryClose`. Exported so the
160
- * contract test can drive the failure / skipped / success branches
161
- * without spinning up the merge + cascade pipeline.
162
- */
163
- export function buildCloseEnvelope({ result, verdict, storyId }) {
164
- if (verdict.ok === false) {
165
- const failedResult = {
166
- ...result,
167
- status: 'failed',
168
- phase: 'closing',
169
- reason: 'label-transition-failed',
170
- actualLabels: verdict.actualLabels,
171
- };
172
- Logger.warn?.(
173
- `[story-close] ❌ Story #${storyId} cascade returned but label is not ` +
174
- `${STATE_LABELS.DONE} (actual: ${JSON.stringify(verdict.actualLabels)}). ` +
175
- `Returning failure envelope.`,
176
- );
177
- return { success: false, result: failedResult };
178
- }
179
- if (verdict.ok === 'skipped') {
180
- return {
181
- success: true,
182
- result: { ...result, warnings: [verdict.warning] },
183
- };
184
- }
185
- return { success: true, result };
186
- }
187
-
188
- /**
189
- * Composite phase: merge → post-merge close → final-label readback →
190
- * envelope serialise. The caller (`runStoryCloseLocked` in
191
- * story-close.js) marks the `close` phase on its phase timer before
192
- * calling in.
193
- */
194
- export async function runClosePhase(ctx) {
195
- await runMergePhase(ctx);
196
- const result = await runPostMergePhase(ctx);
197
-
198
- // Story #2961 — final readback before declaring success. The
199
- // post-merge cascade is the single writer for the `closing → done`
200
- // label flip; if it silently failed, surface a failure envelope here
201
- // rather than relying on the runner's downstream GitHub probe.
202
- const verdict = await verifyFinalStoryLabel({
203
- provider: ctx.provider,
204
- storyId: ctx.storyId,
205
- });
206
- const envelope = buildCloseEnvelope({
207
- result,
208
- verdict,
209
- storyId: ctx.storyId,
210
- });
211
-
212
- Logger.info(
213
- `\n--- STORY CLOSE RESULT ---\n${JSON.stringify(envelope.result, null, 2)}\n--- END RESULT ---\n`,
214
- );
215
- if (envelope.success) {
216
- ctx.progress(
217
- 'DONE',
218
- `✅ Story #${ctx.storyId} merged into ${ctx.epicBranch}. ${envelope.result.ticketsClosed.length} ticket(s) closed.`,
219
- );
220
- }
221
- return envelope;
222
- }