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,510 +0,0 @@
1
- #!/usr/bin/env node
2
- /* node:coverage ignore file */
3
- /**
4
- * lifecycle-emit.js — generic argv-driven emit helper (Story #2425 /
5
- * Task #2434, Epic #2307).
6
- *
7
- * Replaces the three single-purpose emit shims
8
- * (`epic-deliver-finalize.js`, `epic-deliver-automerge.js`,
9
- * `epic-deliver-cleanup.js`) that the `/deliver` workflow markdown
10
- * invoked in Phase 6, 7.5, and 8. Those shims each did exactly one
11
- * thing: construct a bus and emit one event. Collapsing them into a
12
- * single argv-driven CLI lets the workflow stay declarative ("fire
13
- * <event> with <payload>") while keeping the lifecycle-bus contract
14
- * untouched.
15
- *
16
- * Usage:
17
- * node .agents/scripts/lifecycle-emit.js --epic <id> --event <name> \
18
- * [--<field> <value>]*
19
- *
20
- * Examples:
21
- * # Phase 6 — close-tail entry event
22
- * node .agents/scripts/lifecycle-emit.js --epic 2307 \
23
- * --event epic.close.end
24
- *
25
- * # Phase 7.5 — automerge wrapper start
26
- * node .agents/scripts/lifecycle-emit.js --epic 2307 \
27
- * --event epic.automerge.start \
28
- * --pr-url https://github.com/dsj1984/mandrel/pull/123
29
- *
30
- * # Phase 8 — cleanup (epic.merge.armed)
31
- * node .agents/scripts/lifecycle-emit.js --epic 2307 \
32
- * --event epic.merge.armed \
33
- * --pr-url https://github.com/dsj1984/mandrel/pull/123
34
- *
35
- * Argv → payload mapping:
36
- * - `--event <name>` selects the lifecycle event. The CLI validates
37
- * that `.agents/schemas/lifecycle/<event>.schema.json` exists
38
- * before invoking the bus; an unknown event exits non-zero with a
39
- * message pointing at the missing schema file.
40
- * - `--epic <id>` is mapped to `epicId` (integer) for events whose
41
- * schema requires it.
42
- * - Any other `--<kebab-case> <value>` flag is mapped to a
43
- * camelCase payload key. Values that look like integers are
44
- * parsed; everything else is forwarded as a string. Schema
45
- * validation in the bus catches type mismatches.
46
- *
47
- * Missing required payload fields surface via the bus's schema
48
- * validator with `code: 'BUS_SCHEMA_VALIDATION'` and a non-zero exit.
49
- */
50
-
51
- import { existsSync } from 'node:fs';
52
- import path from 'node:path';
53
- import { fileURLToPath } from 'node:url';
54
-
55
- import { runAsCli } from './lib/cli-utils.js';
56
- import { epicLedgerPath } from './lib/config/temp-paths.js';
57
- import { resolveConfig } from './lib/config-resolver.js';
58
- import { appendEpicSignal } from './lib/observability/signals-writer.js';
59
- import * as epicRunStateStoreModule from './lib/orchestration/epic-run-state-store.js';
60
- import { createBus } from './lib/orchestration/lifecycle/bus.js';
61
- import { buildDefaultListenerChain } from './lib/orchestration/lifecycle/listeners/index.js';
62
- import {
63
- STATE_LABELS,
64
- transitionTicketState,
65
- } from './lib/orchestration/ticketing.js';
66
- import { createProvider } from './lib/provider-factory.js';
67
-
68
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
69
- const DEFAULT_SCHEMA_DIR = path.resolve(
70
- __dirname,
71
- '..',
72
- 'schemas',
73
- 'lifecycle',
74
- );
75
-
76
- /**
77
- * Convert a kebab-case argv key (`pr-url`) to its camelCase payload
78
- * counterpart (`prUrl`). Leading dashes have already been stripped by
79
- * the argv parser.
80
- */
81
- function toCamelCase(kebab) {
82
- return kebab.replace(/-([a-z0-9])/g, (_, ch) => ch.toUpperCase());
83
- }
84
-
85
- /**
86
- * Best-effort coercion: argv strings that look like positive integers
87
- * are parsed; the literals `true` / `false` coerce to booleans (so
88
- * boolean-typed payload fields like `epic.automerge.end`'s `merged` flag
89
- * pass schema validation from the workflow's `--merged true` invocation,
90
- * Story #3901); everything else is forwarded as-is. Schema validation in
91
- * the bus catches genuine type mismatches.
92
- */
93
- function coerceValue(raw) {
94
- if (typeof raw !== 'string') return raw;
95
- if (raw === 'true') return true;
96
- if (raw === 'false') return false;
97
- if (/^-?\d+$/.test(raw)) {
98
- const n = Number.parseInt(raw, 10);
99
- if (Number.isInteger(n)) return n;
100
- }
101
- return raw;
102
- }
103
-
104
- /**
105
- * Parse a flat argv array (`['--event', 'foo', '--epic', '42']`) into
106
- * an object map of flag → value. Boolean flags are not supported — the
107
- * helper is intentionally minimal and every value lands in the payload.
108
- */
109
- export function parseArgv(argv) {
110
- const out = {};
111
- for (let i = 0; i < argv.length; i += 1) {
112
- const tok = argv[i];
113
- if (typeof tok !== 'string' || !tok.startsWith('--')) {
114
- throw new Error(
115
- `lifecycle-emit: unexpected positional argument: ${String(tok)}`,
116
- );
117
- }
118
- const key = tok.slice(2);
119
- const value = argv[i + 1];
120
- if (
121
- value === undefined ||
122
- (typeof value === 'string' && value.startsWith('--'))
123
- ) {
124
- throw new Error(`lifecycle-emit: --${key} requires a value`);
125
- }
126
- out[key] = value;
127
- i += 1;
128
- }
129
- return out;
130
- }
131
-
132
- /**
133
- * Argv keys that are runtime OPTIONS consumed by `main()` /
134
- * `runLifecycleEmit()` directly rather than forwarded into the emitted
135
- * bus payload. `--headless` (Story #4427) is the first member: every
136
- * lifecycle event schema declares `additionalProperties: false`, so a
137
- * flag that selects delivery-run behavior (rather than describing the
138
- * event itself) would fail schema validation if it leaked into the
139
- * payload.
140
- */
141
- const RUNTIME_OPTION_KEYS = Object.freeze(['event', 'headless']);
142
-
143
- /**
144
- * Build the bus emit payload from parsed argv. `event` and `headless`
145
- * (see `RUNTIME_OPTION_KEYS`) are consumed as runtime options, not
146
- * payload fields. `--epic` is mapped to `epicId` (integer). All other
147
- * flags are mapped from kebab-case to camelCase with light value
148
- * coercion.
149
- */
150
- export function buildPayload(parsed) {
151
- const payload = {};
152
- for (const [key, raw] of Object.entries(parsed)) {
153
- if (RUNTIME_OPTION_KEYS.includes(key)) continue;
154
- if (key === 'epic') {
155
- const n = Number.parseInt(raw, 10);
156
- if (!Number.isInteger(n) || n < 1) {
157
- throw new Error(
158
- `lifecycle-emit: --epic must be a positive integer (got ${raw})`,
159
- );
160
- }
161
- payload.epicId = n;
162
- continue;
163
- }
164
- payload[toCamelCase(key)] = coerceValue(raw);
165
- }
166
- return payload;
167
- }
168
-
169
- /**
170
- * The listener-chain keys (as returned by `buildDefaultListenerChain`)
171
- * whose listener instances carry a `classifications` array. Each listener
172
- * records one `{ event, seqId, outcome, reason? }` entry per invocation
173
- * (the "no silent skip" contract). We flatten every listener's
174
- * classifications into a single `outcomes[]` array so the CLI can surface
175
- * them and decide its exit code.
176
- */
177
- const CLASSIFYING_LISTENER_KEYS = Object.freeze([
178
- 'acceptanceReconciler',
179
- 'finalizer',
180
- 'automergeArmer',
181
- 'automergePredicate',
182
- 'branchCleaner',
183
- 'mergeWatcher',
184
- 'cleaner',
185
- ]);
186
-
187
- /**
188
- * Flatten the listener-chain's per-listener `classifications` arrays into
189
- * a single ordered `outcomes[]` list. Each entry is tagged with the
190
- * `listener` key it came from so an operator (or the retro substrate) can
191
- * see WHICH listener classified WHAT.
192
- *
193
- * A `null`/`undefined` chain (caller-supplied bus, or no chain wired)
194
- * yields an empty array — the CLI then has nothing to fail on, preserving
195
- * the injected-bus test contract.
196
- *
197
- * @param {object|null} chain result of `buildDefaultListenerChain`
198
- * @returns {Array<{ listener: string, event?: string, seqId?: number,
199
- * outcome: string, reason?: string }>}
200
- */
201
- export function collectOutcomes(chain) {
202
- if (!chain || typeof chain !== 'object') return [];
203
- const outcomes = [];
204
- for (const key of CLASSIFYING_LISTENER_KEYS) {
205
- const listener = chain[key];
206
- const classifications = listener?.classifications;
207
- if (!Array.isArray(classifications)) continue;
208
- for (const c of classifications) {
209
- if (!c || typeof c !== 'object') continue;
210
- outcomes.push({ listener: key, ...c });
211
- }
212
- }
213
- return outcomes;
214
- }
215
-
216
- /**
217
- * Default operator-visible blocker signal. Fired by `runLifecycleEmit`
218
- * when one or more listener classifications came back `failed` and an
219
- * `epicId` is resolvable. It does two things, each best-effort:
220
- *
221
- * 1. Flips the Epic ticket to `agent::blocked` (the authoritative HITL
222
- * runtime pause point per `instructions.md` § 1.J) via the canonical
223
- * `transitionTicketState` API — but only when a `provider` is wired
224
- * in. The standalone CLI is usable in repos with no `github` block,
225
- * so a missing provider degrades to "signal-only".
226
- * 2. Appends a `friction` signal to the per-Epic `signals.ndjson` stream
227
- * so the failure is recorded out-of-band even when no provider is
228
- * configured (the no-ticket fallback from § 1.H).
229
- *
230
- * Neither step throws: the CLI must still print its `outcomes[]` envelope
231
- * and exit non-zero on the underlying failure regardless of whether the
232
- * side-effect plumbing succeeded.
233
- *
234
- * @param {object} args
235
- * @param {number} args.epicId resolved Epic id
236
- * @param {string} args.event the lifecycle event that produced the failure
237
- * @param {Array<object>} args.failedOutcomes the `outcome: 'failed'` entries
238
- * @param {object|null} [args.provider] ticketing provider (label flip)
239
- * @param {object} [args.config] resolved agent config (signal path)
240
- * @param {object} [args.logger] logger surface
241
- * @returns {Promise<{ labelFlipped: boolean, signalAppended: boolean }>}
242
- */
243
- export async function emitBlockedSignal({
244
- epicId,
245
- event,
246
- failedOutcomes,
247
- provider,
248
- config,
249
- logger,
250
- } = {}) {
251
- const log = logger ?? console;
252
- const reasons = (failedOutcomes ?? [])
253
- .map((o) => `${o.listener}:${o.reason ?? o.outcome}`)
254
- .join('; ');
255
- let labelFlipped = false;
256
- if (provider) {
257
- try {
258
- await transitionTicketState(provider, epicId, STATE_LABELS.BLOCKED);
259
- labelFlipped = true;
260
- } catch (err) {
261
- log?.warn?.(
262
- `[lifecycle-emit] failed to flip Epic #${epicId} to agent::blocked: ${err?.message ?? err}`,
263
- );
264
- }
265
- } else {
266
- log?.debug?.(
267
- `[lifecycle-emit] no provider wired — skipping agent::blocked flip for Epic #${epicId} (signal-only)`,
268
- );
269
- }
270
- let signalAppended = false;
271
- try {
272
- signalAppended = await appendEpicSignal({
273
- epicId,
274
- config,
275
- signal: {
276
- kind: 'friction',
277
- ts: new Date().toISOString(),
278
- epicId,
279
- category: 'lifecycle-listener-failure',
280
- emitter: { tool: 'lifecycle-emit.js' },
281
- severity: 'high',
282
- event,
283
- details: {
284
- message: `lifecycle-emit: ${event} produced failed listener classification(s): ${reasons}`,
285
- outcomes: failedOutcomes,
286
- },
287
- },
288
- });
289
- } catch (err) {
290
- log?.warn?.(
291
- `[lifecycle-emit] failed to append friction signal for Epic #${epicId}: ${err?.message ?? err}`,
292
- );
293
- }
294
- return { labelFlipped, signalAppended };
295
- }
296
-
297
- /**
298
- * Programmatic entry point. Tests inject `bus` to assert payload
299
- * shape without triggering real schema validation.
300
- *
301
- * When the caller does NOT supply a `bus`, the helper constructs a
302
- * default bus AND subscribes the canonical listener chain via
303
- * `buildDefaultListenerChain` so the standalone CLI surface fires every
304
- * documented downstream side effect (acceptance reconcile, finalize,
305
- * automerge, cleanup). Callers that inject a bus retain full control —
306
- * they are responsible for wiring whatever listeners they want.
307
- *
308
- * The listener chain requires `epicId` (decoded from the payload) and a
309
- * `repoRoot` (defaulted from `process.cwd()`). Story #2531 (Epic #2527)
310
- * additionally resolves the canonical provider, the
311
- * full agent `config`, and a per-Epic `checkpointer` bound to the
312
- * `epic-run-state` structured comment so the FULL listener roster
313
- * (including AutomergePredicate and BranchCleaner) subscribes — the
314
- * skip path that previously dropped those two listeners is reserved
315
- * for callers that inject overrides via `opts`.
316
- *
317
- * @param {object} opts
318
- * @param {string} opts.event lifecycle event name (matches schema file)
319
- * @param {object} opts.payload assembled emit payload
320
- * @param {object} [opts.bus] override bus (defaults to `createBus()`)
321
- * @param {string} [opts.schemaDir] override schema dir for existence check
322
- * @param {string} [opts.repoRoot] override repo root for shell-out
323
- * listeners (defaults to `process.cwd()`)
324
- * @param {object} [opts.logger] optional logger forwarded to the chain
325
- * @param {object} [opts.provider] override provider (defaults to
326
- * `createProvider(config)` from the resolved config).
327
- * Pass `null` to explicitly skip provider-dependent listeners.
328
- * @param {object} [opts.checkpointer] override checkpointer (defaults
329
- * to a provider/epicId-bound `epic-run-state-store` facade). Pass
330
- * `null` to explicitly skip BranchCleaner.
331
- * @param {object} [opts.config] override resolved config (defaults to
332
- * `resolveConfig()`).
333
- * @param {(args: object) => Promise<unknown>} [opts.emitBlockedSignalFn]
334
- * override the operator-visible blocker signal (defaults to
335
- * `emitBlockedSignal`). Tests inject a spy to assert it fires on a
336
- * `failed` classification without touching GitHub or the filesystem.
337
- * @param {object} [opts.chain] override the listener chain whose
338
- * `classifications` arrays are collected into `outcomes[]`. Only honoured
339
- * alongside an injected `bus` (when the caller owns listener wiring) —
340
- * lets a test inject a bus + a chain carrying a `failed`-classifying
341
- * listener to exercise the non-zero-exit path without the real roster.
342
- * @param {boolean} [opts.headless] Explicit must-land signal (Story
343
- * #4427), forwarded to `buildDefaultListenerChain({ headless })` (and
344
- * from there to `MergeWatcher`) when this call constructs the default
345
- * chain. Defaults to `false` — attended-mode behavior is unchanged.
346
- * Ignored when the caller injects its own `bus`/`chain`.
347
- *
348
- * @returns {Promise<{ event: string, payload: object, seqId: number,
349
- * outcomes: Array<object>, failed: boolean }>} The `outcomes[]` array
350
- * carries every listener classification (tagged with its listener key);
351
- * `failed` is `true` when any classification's `outcome` is `'failed'`.
352
- * The CLI maps `failed` to a non-zero exit code.
353
- */
354
- export async function runLifecycleEmit({
355
- event,
356
- payload,
357
- bus,
358
- schemaDir = DEFAULT_SCHEMA_DIR,
359
- repoRoot,
360
- logger,
361
- provider,
362
- checkpointer,
363
- config,
364
- emitBlockedSignalFn = emitBlockedSignal,
365
- chain: injectedChain,
366
- headless = false,
367
- } = {}) {
368
- if (typeof event !== 'string' || event.length === 0) {
369
- throw new Error('lifecycle-emit: --event is required');
370
- }
371
- const schemaPath = path.join(schemaDir, `${event}.schema.json`);
372
- if (!existsSync(schemaPath)) {
373
- throw new Error(
374
- `lifecycle-emit: unknown event "${event}" — no schema at ${schemaPath}`,
375
- );
376
- }
377
- const callerSuppliedBus = Boolean(bus);
378
- const targetBus = bus ?? createBus({ schemaDir });
379
- const epicId = Number(payload?.epicId);
380
- const hasEpicId = Number.isInteger(epicId) && epicId > 0;
381
- // An injected chain is only meaningful when the caller also injected the
382
- // bus (otherwise we build the chain ourselves below).
383
- let chain = callerSuppliedBus ? (injectedChain ?? null) : null;
384
- let resolvedConfig = config;
385
- let resolvedProvider = provider;
386
- // Wire the default listener chain only when we constructed the bus
387
- // ourselves. Callers that inject a bus own its listener wiring.
388
- if (!callerSuppliedBus && hasEpicId) {
389
- const ledgerPath = epicLedgerPath(epicId);
390
- // Resolve config + provider + checkpointer so the full canonical
391
- // listener roster subscribes (Story #2531). The CLI swallows
392
- // resolution errors (missing/invalid .agentrc.json or
393
- // unconfigured provider) and falls back to the skip-cleanly
394
- // behaviour — the standalone CLI MUST remain usable in repos
395
- // that have not configured the github block yet, just
396
- // with a reduced listener roster.
397
- let resolvedCheckpointer = checkpointer;
398
- if (resolvedConfig === undefined) {
399
- try {
400
- resolvedConfig = resolveConfig();
401
- } catch (err) {
402
- (logger ?? console)?.debug?.(
403
- `[lifecycle-emit] resolveConfig failed (continuing with skipped collaborators): ${err?.message ?? err}`,
404
- );
405
- resolvedConfig = null;
406
- }
407
- }
408
- if (resolvedProvider === undefined) {
409
- try {
410
- resolvedProvider = createProvider(resolvedConfig);
411
- } catch (err) {
412
- (logger ?? console)?.debug?.(
413
- `[lifecycle-emit] createProvider skipped (no provider configured): ${err?.message ?? err}`,
414
- );
415
- resolvedProvider = null;
416
- }
417
- }
418
- if (resolvedCheckpointer === undefined) {
419
- resolvedCheckpointer = resolvedProvider
420
- ? buildEpicCheckpointer({ provider: resolvedProvider, epicId })
421
- : null;
422
- }
423
- chain = await buildDefaultListenerChain({
424
- bus: targetBus,
425
- ledgerPath,
426
- repoRoot: repoRoot ?? process.cwd(),
427
- provider: resolvedProvider,
428
- checkpointer: resolvedCheckpointer,
429
- config: resolvedConfig,
430
- logger,
431
- headless,
432
- });
433
- }
434
- const { seqId } = await targetBus.emit(event, payload ?? {});
435
-
436
- // Collect every listener classification the chain recorded. Listeners
437
- // record `failed` classifications instead of throwing (the bus's
438
- // `onFailed` boundary already persists the originating event), so the
439
- // bus emit resolves cleanly even when a downstream side effect — e.g.
440
- // an acceptance-reconcile gap or an `openOrLocatePr` throw inside
441
- // the Finalizer — failed. Without surfacing these, the CLI would exit 0
442
- // with success-shaped JSON despite a partial finalize (Story #3904).
443
- const outcomes = collectOutcomes(chain);
444
- const failedOutcomes = outcomes.filter((o) => o.outcome === 'failed');
445
- const failed = failedOutcomes.length > 0;
446
-
447
- // Operator-visible signal: a failed classification surfaces an
448
- // `agent::blocked` flip + friction signal rather than a silent exit 0.
449
- // Fired only when we own the chain AND have a target Epic to flag.
450
- if (failed && hasEpicId) {
451
- await emitBlockedSignalFn({
452
- epicId,
453
- event,
454
- failedOutcomes,
455
- provider: resolvedProvider ?? null,
456
- config: resolvedConfig ?? undefined,
457
- logger,
458
- });
459
- }
460
-
461
- return { event, payload: payload ?? {}, seqId, outcomes, failed };
462
- }
463
-
464
- /**
465
- * Build a thin per-Epic checkpointer facade over `epic-run-state-store`.
466
- * Exposes the `read()`/`write()`/`setPhase()`/`appendIntervention()`
467
- * surface BranchCleaner expects. (This was previously also constructed by
468
- * the in-process `epic-runner/factory.js`, deleted with the dead runner
469
- * stratum in Story #3908; this CLI is now the only builder of the facade.)
470
- */
471
- function buildEpicCheckpointer({ provider, epicId }) {
472
- return {
473
- read: () => epicRunStateStoreModule.read({ provider, epicId }),
474
- write: (state) =>
475
- epicRunStateStoreModule.write({ provider, epicId, state }),
476
- setPhase: (nextPhase) =>
477
- epicRunStateStoreModule.setPhase({ provider, epicId, nextPhase }),
478
- appendIntervention: (entry) =>
479
- epicRunStateStoreModule.appendIntervention({ provider, epicId, entry }),
480
- };
481
- }
482
-
483
- async function main() {
484
- const parsed = parseArgv(process.argv.slice(2));
485
- if (!parsed.event) {
486
- throw new Error(
487
- 'lifecycle-emit: --event <name> is required. Example: --event epic.close.end',
488
- );
489
- }
490
- const event = parsed.event;
491
- const payload = buildPayload(parsed);
492
- // `--headless true` is a runtime option (Story #4427), not a payload
493
- // field — see RUNTIME_OPTION_KEYS. Threaded explicitly through
494
- // runLifecycleEmit → buildDefaultListenerChain → MergeWatcher so the
495
- // epic-path must-land terminal step reads a caller-supplied input
496
- // rather than an ambient global.
497
- const headless = parsed.headless === 'true';
498
- const out = await runLifecycleEmit({ event, payload, headless });
499
- process.stdout.write(`${JSON.stringify(out)}\n`);
500
- // Exit non-zero when any listener classification came back `failed` so
501
- // the workflow's "re-run on non-zero" loop closes the partial-finalize
502
- // gap (Story #3904). `runAsCli`'s `propagateExitCode` maps this return
503
- // value to `process.exit`.
504
- return out.failed ? 1 : 0;
505
- }
506
-
507
- runAsCli(import.meta.url, main, {
508
- source: 'lifecycle-emit',
509
- propagateExitCode: true,
510
- });