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,173 +0,0 @@
1
- /**
2
- * lib/orchestration/deliver-route.js — the deliver-side reader for the
3
- * plan-time single-delivery seam (Epic #4475, M4-A).
4
- *
5
- * The plan path already ships the seam inert (Epic #4474): the risk verdict's
6
- * `deliveryShape`, the `delivery::single` label, and the
7
- * `epic-plan-state.decompose = { ticketCount: 0, shape: "single" }`
8
- * checkpoint. Nothing on the deliver side read them — until this module. It
9
- * folds those two markers (plus the global kill-switch) into a single
10
- * delivery-route verdict for `/deliver`.
11
- *
12
- * Pure and total — inputs in, verdict out. No GitHub calls, no I/O, no
13
- * throws. It mirrors how `review-depth.js#resolveDepth` and
14
- * `epic-audit-prepare.js` read `planningRisk` / `decompose` off the
15
- * `epic-plan-state` checkpoint: the caller fetches the Epic labels + the
16
- * checkpoint, then hands both here.
17
- *
18
- * ── Routing precedence (highest wins) ──────────────────────────────────
19
- * 1. Kill-switch. `delivery.routing.singleDelivery === false` forces
20
- * `fan-out` for EVERY Epic, even a single-labelled one — the instant
21
- * global revert (`lib/config/delivery-routing.js`). Overrides all.
22
- * 2. Single marker. The `delivery::single` label (primary) OR
23
- * `checkpoint.decompose.shape === "single"` (secondary) → `single`.
24
- * 3. Wide-DAG advisory. A fan-out-shaped Epic whose ready-width > 1 is
25
- * genuine parallelism → `fan-out`. Deliver-time width only ADVISES —
26
- * it never reroutes a single-marked Epic (that would orphan a Story
27
- * tree that does not exist; re-route = re-plan).
28
- * 4. Legacy / no marker → `fan-out` (safe backward-compat: a legacy Epic
29
- * has an authored Story tree the fan-out engine consumes).
30
- *
31
- * BEHAVIOR-PRESERVING in M4-A: the router consumes a `single` verdict via a
32
- * stub that continues at `deliver-epic.md` (fan-out), so no `/deliver`
33
- * observably changes until M4-B lands `deliver-epic-single.md`.
34
- *
35
- * @typedef {'single'|'fan-out'} DeliveryRoute
36
- */
37
-
38
- import { getDeliveryRouting } from '../config/delivery-routing.js';
39
-
40
- /** The canonical single-delivery routing marker label. */
41
- export const DELIVERY_SINGLE_LABEL = 'delivery::single';
42
-
43
- /**
44
- * True when the Epic carries the `delivery::single` routing label. Tolerant
45
- * of the two label shapes callers hold: an array of label-name strings, or an
46
- * array of `{ name }` objects (the GitHub REST label shape).
47
- *
48
- * @param {{ labels?: Array<string | { name?: string }> } | null | undefined} epic
49
- * @returns {boolean}
50
- */
51
- function hasSingleLabel(epic) {
52
- const labels = Array.isArray(epic?.labels) ? epic.labels : [];
53
- return labels.some((l) => {
54
- const name = typeof l === 'string' ? l : l?.name;
55
- return name === DELIVERY_SINGLE_LABEL;
56
- });
57
- }
58
-
59
- /**
60
- * True when the plan-state checkpoint's `decompose.shape` is the deliberate
61
- * single shape. `plan-persist.js` writes `decompose = { ticketCount: 0,
62
- * shape: "single" }` for a spec-only plan; every other value (including a
63
- * legacy checkpoint with no `shape` field) is not-single.
64
- *
65
- * @param {{ decompose?: { shape?: string } } | null | undefined} checkpoint
66
- * @returns {boolean}
67
- */
68
- function hasSingleDecomposeShape(checkpoint) {
69
- return checkpoint?.decompose?.shape === 'single';
70
- }
71
-
72
- /**
73
- * Resolve the delivery route for one Epic from its labels, its plan-state
74
- * checkpoint, and the resolved config. See the module header for the full
75
- * precedence. Pure — never throws; malformed / absent inputs degrade to the
76
- * safe `fan-out` default.
77
- *
78
- * @param {{ labels?: Array<string | { name?: string }> } | null | undefined} epic
79
- * The Epic ticket snapshot (only `labels` is read here).
80
- * @param {{ decompose?: { shape?: string } } | null | undefined} checkpoint
81
- * The `epic-plan-state` structured comment, parsed (or `null` on a legacy
82
- * Epic that predates the checkpoint — treated as no marker).
83
- * @param {object | null | undefined} config
84
- * The resolved config; `delivery.routing.singleDelivery` is the kill-switch.
85
- * @returns {{ route: DeliveryRoute, reason: string, singleDeliveryEnabled: boolean }}
86
- */
87
- export function resolveEpicDeliveryRoute(epic, checkpoint, config) {
88
- const { singleDelivery } = getDeliveryRouting(config);
89
-
90
- // 1. Kill-switch — overrides all. A `false` value forces fan-out even for
91
- // an Epic the planner marked single (the instant global revert).
92
- if (singleDelivery === false) {
93
- return {
94
- route: 'fan-out',
95
- reason:
96
- 'kill-switch: delivery.routing.singleDelivery=false forces fan-out for every Epic',
97
- singleDeliveryEnabled: false,
98
- };
99
- }
100
-
101
- // 2. Single marker — label (primary) OR checkpoint decompose shape
102
- // (secondary). Either alone routes single.
103
- const labelled = hasSingleLabel(epic);
104
- const shaped = hasSingleDecomposeShape(checkpoint);
105
- if (labelled || shaped) {
106
- const via =
107
- labelled && shaped
108
- ? `${DELIVERY_SINGLE_LABEL} label + decompose.shape="single"`
109
- : labelled
110
- ? `${DELIVERY_SINGLE_LABEL} label`
111
- : 'decompose.shape="single"';
112
- return {
113
- route: 'single',
114
- reason: `single marker present (${via})`,
115
- singleDeliveryEnabled: true,
116
- };
117
- }
118
-
119
- // 3/4. No single marker → fan-out (a wide DAG or a legacy Story tree; the
120
- // deliver-time width only advises and never reroutes here).
121
- return {
122
- route: 'fan-out',
123
- reason: 'no single marker — fan-out (legacy Story tree or wide DAG)',
124
- singleDeliveryEnabled: true,
125
- };
126
- }
127
-
128
- /**
129
- * Compute the ready-width of a delivery plan — the count of work units that
130
- * could dispatch on the first beat. It is the mechanical parallelism signal
131
- * the planner uses at plan time to mark a genuinely-wide Epic `fan-out`, and
132
- * that `/deliver` may surface as an advisory at deliver time (it never
133
- * reroutes — see the module header).
134
- *
135
- * Accepts either input shape the framework already produces:
136
- * - Delivery-Slicing rows — `[{ independent: boolean }, …]` from
137
- * `parseDeliverySlicingTable`. A serial chain (every row
138
- * `Independent: No`, or a lone independent slice) has width 1; two or
139
- * more independent slices yield a width equal to that independent count
140
- * (> 1) — genuine parallelism.
141
- * - A wave DAG — `[[…], […], …]` (the array-of-waves `state.waves` shape
142
- * `runBuildWaveDagPhase` produces). The width is the largest wave — the
143
- * most Stories ready to dispatch on a single beat.
144
- *
145
- * Pure and total: an empty / malformed / unrecognized input degrades to
146
- * width 1 (the safe "not wide" signal). Never throws.
147
- *
148
- * @param {Array<{ independent?: boolean }> | Array<Array<unknown>> | null | undefined} deliverySlicingRowsOrDag
149
- * @returns {number} an integer ≥ 1.
150
- */
151
- export function computeReadyWidth(deliverySlicingRowsOrDag) {
152
- const input = deliverySlicingRowsOrDag;
153
- if (!Array.isArray(input) || input.length === 0) return 1;
154
-
155
- // Wave-DAG shape: an array whose entries are themselves arrays.
156
- if (input.every((entry) => Array.isArray(entry))) {
157
- let widest = 1;
158
- for (const wave of input) {
159
- if (wave.length > widest) widest = wave.length;
160
- }
161
- return widest;
162
- }
163
-
164
- // Delivery-Slicing rows: entries are `{ independent }` records.
165
- const independentCount = input.reduce(
166
- (acc, row) =>
167
- row && typeof row === 'object' && row.independent === true
168
- ? acc + 1
169
- : acc,
170
- 0,
171
- );
172
- return independentCount >= 2 ? independentCount : 1;
173
- }
@@ -1,134 +0,0 @@
1
- /**
2
- * lib/orchestration/dispatch-engine.js — Core Dispatch Engine (SDK coordinator)
3
- *
4
- * Thin facade composing:
5
- * - `dispatch-pipeline.js` — internal resolve/fetch/reconcile/graph helpers
6
- *
7
- * Every Epic is 2-tier (Epic → Story); `dispatch()` computes a
8
- * Story-level wave plan and emits a 2-tier manifest. The legacy Task-tier
9
- * dispatch runtime (Task fetcher, single-Story executor, the per-Task
10
- * wave fan-out, and the Epic-completion detector) was removed in Epic
11
- * #3163.
12
- */
13
-
14
- import { PROJECT_ROOT, resolveConfig } from '../config-resolver.js';
15
- import { ConflictingTypeLabelsError } from '../errors/index.js';
16
- import { ensureLocalBranch } from '../git-branch-lifecycle.js';
17
- import { Logger } from '../Logger.js';
18
- import { TYPE_LABELS } from '../label-constants.js';
19
- import { createProvider } from '../provider-factory.js';
20
- import {
21
- buildStoryDispatchGraph,
22
- fetchEpicContext,
23
- isTwoTierDispatch,
24
- resolveDispatchContext,
25
- } from './dispatch-pipeline.js';
26
- import { buildManifest } from './manifest-builder.js';
27
- import { STATE_LABELS } from './ticketing.js';
28
-
29
- export const AGENT_DONE_LABEL = STATE_LABELS.DONE;
30
-
31
- /* node:coverage ignore next */
32
- export function ensureBranch(branchName, baseBranch) {
33
- ensureLocalBranch(branchName, baseBranch, PROJECT_ROOT, {
34
- log: (msg) => Logger.info(msg),
35
- });
36
- }
37
-
38
- /**
39
- * Resolve a single ticket ID, detect its type, and delegate to the
40
- * appropriate execution pipeline. Single entry point shared by the CLI
41
- * wrapper and the MCP `dispatch_wave` tool.
42
- */
43
- export async function resolveAndDispatch(options) {
44
- const { ticketId, dryRun = false } = options;
45
- const config = resolveConfig();
46
- const provider = options.provider ?? createProvider(config);
47
-
48
- const ticket = await provider.getTicket(ticketId);
49
- const labels = ticket.labels || [];
50
-
51
- const typeLabels = labels.filter((l) => l.startsWith('type::'));
52
- if (typeLabels.length > 1) {
53
- throw new ConflictingTypeLabelsError(
54
- `Ticket #${ticketId} has conflicting type labels: ${typeLabels.join(', ')}. Exactly one type::* label is required.`,
55
- );
56
- }
57
-
58
- const isStory = labels.includes(TYPE_LABELS.STORY);
59
- const isEpic = labels.includes(TYPE_LABELS.EPIC);
60
-
61
- if (isStory) {
62
- throw new Error(
63
- `[Dispatcher] Ticket #${ticketId} is a **Story**. Stories are dispatched ` +
64
- 'through the Story delivery path, not directly via the dispatcher. ' +
65
- `Run \`/deliver ${ticketId}\` to execute this Story, ` +
66
- `or dispatch its parent Epic with \`/deliver #<epicId>\`.`,
67
- );
68
- }
69
-
70
- if (isEpic) {
71
- return dispatch({ epicId: ticketId, dryRun, provider });
72
- }
73
-
74
- const typeLabel = labels.find((l) => l.startsWith('type::')) || 'unknown';
75
- throw new Error(
76
- `[Dispatcher] Ticket #${ticketId} has type "${typeLabel.replace('type::', '')}". ` +
77
- `Only "epic" or "story" tickets can be dispatched. ` +
78
- `Please ensure the ticket is correctly categorized before execution.`,
79
- );
80
- }
81
-
82
- /**
83
- * Main dispatcher. Orchestrates one dispatch cycle for an Epic.
84
- * Primary public export of the orchestration SDK.
85
- */
86
- export async function dispatch(options) {
87
- const ctx = resolveDispatchContext(options, ensureBranch);
88
- const { epicId, dryRun } = ctx;
89
-
90
- const fetched = await fetchEpicContext(ctx);
91
-
92
- // Every Epic is 2-tier (Epic → Story). Compute Story-level
93
- // waves directly from the Story tickets and emit a 2-tier-shaped
94
- // manifest with `waves[].stories[]` so downstream consumers (manifest
95
- // renderer, /deliver wave planner) see the correct execution plan.
96
- // Per-Story execution is owned by `/deliver` (story-init →
97
- // story-close), not by this dispatcher.
98
- if (isTwoTierDispatch(fetched.allTickets)) {
99
- Logger.info(
100
- 'Detected 2-tier hierarchy — computing Story-level execution waves.',
101
- );
102
- const { allWaves: storyWaves } = buildStoryDispatchGraph(
103
- fetched.allTickets,
104
- );
105
- return buildManifest({
106
- epicId,
107
- epic: fetched.epic,
108
- tasks: [],
109
- allTickets: fetched.allTickets,
110
- waves: storyWaves,
111
- dispatched: [],
112
- dryRun,
113
- hierarchy: '2-tier',
114
- });
115
- }
116
-
117
- // No Story tickets under the Epic — throw loudly rather than emit an
118
- // empty manifest, matching the wave-loop's behavior (build-wave-dag.js
119
- // throws the same message shape on this input). A silently-empty
120
- // manifest masks a pre-cutover Epic whose children are legacy Features.
121
- const typedChildren = (fetched.allTickets ?? [])
122
- .map((t) => (t.labels ?? []).find((l) => l.startsWith('type::')))
123
- .filter(Boolean);
124
- const legacyHint =
125
- typedChildren.length > 0
126
- ? ` Found ${typedChildren.length} non-Story child ticket(s) ` +
127
- `(${[...new Set(typedChildren)].join(', ')}) — this Epic looks ` +
128
- `pre-cutover (legacy Feature children) and needs migration to the ` +
129
- `2-tier (Epic → Story) hierarchy before dispatch.`
130
- : '';
131
- throw new Error(
132
- `Epic #${epicId} has no child stories to dispatch.${legacyHint}`,
133
- );
134
- }
@@ -1,183 +0,0 @@
1
- /**
2
- * dispatch-pipeline.js
3
- *
4
- * Internal pipeline helpers composed by `dispatch-engine.js::dispatch()`.
5
- * Keeping these out of the coordinator keeps the public entry point compact
6
- * and focused on the 2-tier flow: resolve → fetch → Story-graph.
7
- */
8
-
9
- import { PROJECT_ROOT, resolveConfig } from '../config-resolver.js';
10
- import { getEpicBranch } from '../git-utils.js';
11
- import { Logger } from '../Logger.js';
12
- import { TYPE_LABELS } from '../label-constants.js';
13
- import { createProvider } from '../provider-factory.js';
14
- import { buildStoryAdjacency } from '../story-adjacency.js';
15
- import { WorktreeManager } from '../worktree-manager.js';
16
- import { computeStoryWaves } from './dependency-analyzer.js';
17
-
18
- /**
19
- * Runtime context for a single dispatch cycle.
20
- *
21
- * Produced by {@link resolveDispatchContext} and consumed by every pipeline
22
- * stage (fetch → graph → scaffold → GC → dispatch). All fields
23
- * are resolved once up-front so downstream helpers can stay free of
24
- * configuration look-ups.
25
- *
26
- * @typedef {object} DispatchContext
27
- * @property {number} epicId Epic ticket number under dispatch.
28
- * @property {boolean} dryRun When true, mutating side-effects are skipped.
29
- * @property {object} config Resolved canonical `.agentrc.json` (with `project`, `github`, `planning`, `delivery` blocks).
30
- * @property {import('../ITicketingProvider.js').ITicketingProvider} provider Ticketing provider (may come from cache).
31
- * @property {import('../worktree-manager.js').WorktreeManager | undefined} worktreeManager Optional worktree manager (only when isolation is enabled and not dry-run).
32
- * @property {string} baseBranch Trunk branch the Epic branches from (default `main`).
33
- * @property {string} epicBranch Epic branch name (`epic/<epicId>`).
34
- * @property {(branchName: string, baseBranch: string) => void} ensureBranch Caller-supplied branch-creation helper.
35
- */
36
-
37
- /**
38
- * The output of {@link fetchEpicContext}.
39
- *
40
- * @typedef {object} FetchedEpic
41
- * @property {object} epic The Epic ticket record.
42
- * @property {object[]} allTickets Every ticket under the Epic (stories + health).
43
- * @property {Map<number, object>} allTicketsById Index of `allTickets` by ticket id.
44
- */
45
-
46
- /**
47
- * Resolve the runtime context for a dispatch: canonical config, provider, adapter,
48
- * worktree manager, base/epic branch names, and the `ensureBranch` bound
49
- * helper supplied by the caller.
50
- *
51
- * @param {object} options Dispatch entry options.
52
- * @param {number} options.epicId Epic ticket number.
53
- * @param {boolean} [options.dryRun=false] When true, skip branch creation and worktree setup.
54
- * @param {import('../ITicketingProvider.js').ITicketingProvider} [options.provider] Pre-constructed provider (overrides factory).
55
- * @param {import('../worktree-manager.js').WorktreeManager} [options.worktreeManager] Pre-constructed worktree manager.
56
- * @param {(branchName: string, baseBranch: string) => void} ensureBranch Branch-creation helper bound by caller (keeps engine ↔ git-lifecycle coupling at the edge).
57
- * @returns {DispatchContext} Fully resolved dispatch context.
58
- */
59
- export function resolveDispatchContext(options, ensureBranch) {
60
- const { epicId, dryRun = false } = options;
61
-
62
- const config = resolveConfig();
63
- const provider = options.provider ?? createProvider(config);
64
-
65
- const wtConfig = config?.delivery?.worktreeIsolation;
66
- let worktreeManager = options.worktreeManager;
67
- if (!worktreeManager && wtConfig?.enabled && !dryRun) {
68
- worktreeManager = new WorktreeManager({
69
- repoRoot: PROJECT_ROOT,
70
- config: wtConfig,
71
- });
72
- }
73
-
74
- return {
75
- epicId,
76
- dryRun,
77
- config,
78
- provider,
79
- worktreeManager,
80
- baseBranch: config?.project?.baseBranch ?? 'main',
81
- epicBranch: getEpicBranch(epicId),
82
- ensureBranch,
83
- };
84
- }
85
-
86
- /**
87
- * Fetch Epic + all tickets and prime the provider cache.
88
- *
89
- * @param {DispatchContext} ctx Dispatch context.
90
- * @returns {Promise<FetchedEpic>} Epic + ticket graph.
91
- */
92
- export async function fetchEpicContext(ctx) {
93
- const { provider, epicId } = ctx;
94
-
95
- Logger.info(`\nFetching Epic #${epicId}...`);
96
- const epic = await provider.getEpic(epicId);
97
-
98
- Logger.info(`Fetching all tickets under Epic #${epicId}...`);
99
- const allTickets = await provider.getTickets(epicId);
100
- const allTicketsById = new Map(allTickets.map((t) => [t.id, t]));
101
-
102
- provider.primeTicketCache(allTickets);
103
-
104
- return { epic, allTickets, allTicketsById };
105
- }
106
-
107
- /**
108
- * Detect 2-tier hierarchy from the fetched ticket graph. After Epic #3163's
109
- * hard cutover deleted the `type::task` ticket layer, shape selection is
110
- * purely structural: any Epic carrying at least one `type::story` ticket
111
- * resolves to 2-tier.
112
- *
113
- * @param {object[]} allTickets
114
- * @returns {boolean}
115
- */
116
- export function isTwoTierDispatch(allTickets) {
117
- if (!Array.isArray(allTickets) || allTickets.length === 0) return false;
118
- return allTickets.some((t) =>
119
- (t.labelSet ?? new Set(t.labels ?? [])).has(TYPE_LABELS.STORY),
120
- );
121
- }
122
-
123
- /**
124
- * Build the Story-level dispatch graph for a 2-tier Epic. Reads story
125
- * tickets from `allTickets`, parses cross-Story `blocked by` references
126
- * from each Story body (also honoring an optional `dependencies[]`
127
- * field set by fixture providers), and computes wave indices via
128
- * {@link computeStoryWaves}.
129
- *
130
- * The returned `allWaves` is an array of Story-ticket arrays, ordered by
131
- * wave index. `storyMap` indexes the same Story tickets by id for downstream
132
- * lookups (mirrors the `taskMap` returned by {@link buildDispatchGraph}).
133
- *
134
- * Stories with no resolvable wave (cycle pre-filter, missing in groups)
135
- * are placed in their own trailing wave so they remain visible in the
136
- * manifest output.
137
- *
138
- * @param {object[]} allTickets Fetched ticket graph (Epic + Stories).
139
- * @returns {{ allWaves: object[][], storyMap: Map<number, object> }}
140
- * @throws {Error} When the Story dependency graph contains a cycle.
141
- */
142
- export function buildStoryDispatchGraph(allTickets) {
143
- const stories = (allTickets ?? []).filter((t) =>
144
- (t.labelSet ?? new Set(t.labels ?? [])).has(TYPE_LABELS.STORY),
145
- );
146
- const storyMap = new Map(stories.map((s) => [s.id, s]));
147
-
148
- // Shared story-level adjacency builder (lib/story-adjacency.js) owns the
149
- // dependency-source ordering contract: body `blocked by` references via
150
- // `parseBlockedBy`, then explicit `dependencies[]`, foreign edges dropped.
151
- const explicitDeps = buildStoryAdjacency(stories);
152
-
153
- // computeStoryWaves expects a Map<storyId, { tasks: [] }>; with no Tasks
154
- // present, only explicitDeps + focus-area rollup (no-op for empty
155
- // task lists) drive wave assignment.
156
- const storyGroups = new Map(
157
- stories.map((s) => [s.id, { storyId: s.id, tasks: [] }]),
158
- );
159
- const waveAssignment = computeStoryWaves(storyGroups, explicitDeps);
160
-
161
- // Bucket stories by wave index. `computeStoryWaves` returns -1 for any
162
- // story it could not place; route those into a trailing bucket so they
163
- // still surface in the manifest.
164
- const byWave = new Map();
165
- let maxWave = -1;
166
- for (const story of stories) {
167
- const wave = waveAssignment.get(story.id) ?? -1;
168
- if (wave > maxWave) maxWave = wave;
169
- if (!byWave.has(wave)) byWave.set(wave, []);
170
- byWave.get(wave).push(story);
171
- }
172
-
173
- const allWaves = [];
174
- for (let i = 0; i <= maxWave; i++) {
175
- if (byWave.has(i)) allWaves.push(byWave.get(i));
176
- }
177
- if (byWave.has(-1)) allWaves.push(byWave.get(-1));
178
-
179
- Logger.info(
180
- `Computed ${allWaves.length} Story-level execution wave(s) (2-tier).`,
181
- );
182
- return { allWaves, storyMap };
183
- }