mandrel 1.93.0 → 2.0.0

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