mandrel 1.94.0 → 2.1.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 (560) hide show
  1. package/.agents/README.md +116 -99
  2. package/.agents/agents/acceptance-critic.md +9 -7
  3. package/.agents/agents/story-worker.md +45 -51
  4. package/.agents/audit-checklists/performance.md +1 -1
  5. package/.agents/docs/SDLC.md +498 -1287
  6. package/.agents/docs/agentrc-reference.json +185 -80
  7. package/.agents/docs/configuration.md +132 -190
  8. package/.agents/docs/execution-reference.md +51 -25
  9. package/.agents/docs/quality-gates.md +25 -33
  10. package/.agents/docs/workflows.md +8 -8
  11. package/.agents/instructions.md +113 -139
  12. package/.agents/rules/ci-remediation.md +11 -15
  13. package/.agents/rules/git-conventions-reference.md +48 -58
  14. package/.agents/rules/git-conventions.md +16 -22
  15. package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
  16. package/.agents/schemas/agentrc.schema.json +83 -254
  17. package/.agents/schemas/audit-rules.json +59 -1
  18. package/.agents/schemas/audit-rules.schema.json +33 -1
  19. package/.agents/schemas/lifecycle/README.md +1 -2
  20. package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
  21. package/.agents/schemas/lifecycle/merge.flip-failed.schema.json +33 -0
  22. package/.agents/schemas/lifecycle/merge.unlanded.schema.json +1 -0
  23. package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
  24. package/.agents/schemas/lifecycle/story.merged.schema.json +1 -1
  25. package/.agents/schemas/signal-event.schema.json +3 -3
  26. package/.agents/schemas/story-deliver-terminal.schema.json +152 -0
  27. package/.agents/schemas/validation-evidence.schema.json +1 -1
  28. package/.agents/scripts/acceptance-eval.js +22 -66
  29. package/.agents/scripts/agents-bootstrap-github.js +1 -1
  30. package/.agents/scripts/audit-to-stories.js +7 -7
  31. package/.agents/scripts/boot-sweep.js +1 -1
  32. package/.agents/scripts/bootstrap.js +3 -3
  33. package/.agents/scripts/check-dead-exports.js +43 -104
  34. package/.agents/scripts/check-doc-links.js +2 -2
  35. package/.agents/scripts/check-lifecycle-lint.js +7 -10
  36. package/.agents/scripts/check-workflow-cli-lint.js +91 -0
  37. package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
  38. package/.agents/scripts/deliver-recover.js +122 -0
  39. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  40. package/.agents/scripts/evidence-gate.js +20 -50
  41. package/.agents/scripts/generate-skills-index.js +17 -1
  42. package/.agents/scripts/generate-workflows-doc.js +4 -4
  43. package/.agents/scripts/lib/ITicketingProvider.js +1 -19
  44. package/.agents/scripts/lib/Logger.js +6 -10
  45. package/.agents/scripts/lib/audit-suite/runner.js +2 -2
  46. package/.agents/scripts/lib/audit-suite/selector.js +328 -28
  47. package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
  48. package/.agents/scripts/lib/baselines/kernel.js +206 -18
  49. package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -15
  50. package/.agents/scripts/lib/baselines/reader.js +1 -6
  51. package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
  52. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +28 -33
  53. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
  54. package/.agents/scripts/lib/bootstrap/manifest.js +8 -11
  55. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +30 -53
  56. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +0 -2
  57. package/.agents/scripts/lib/checks/core-bare-clean.js +6 -3
  58. package/.agents/scripts/lib/checks/index.js +3 -2
  59. package/.agents/scripts/lib/checks/loop-health.js +12 -11
  60. package/.agents/scripts/lib/checks/state.js +17 -248
  61. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +26 -24
  62. package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +3 -4
  63. package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +2 -2
  64. package/.agents/scripts/lib/checks/worktree-residue-biome.js +3 -3
  65. package/.agents/scripts/lib/cli/standard-args.js +13 -22
  66. package/.agents/scripts/lib/cli-args.js +39 -9
  67. package/.agents/scripts/lib/close-validation/gates.js +15 -15
  68. package/.agents/scripts/lib/close-validation/projections/inputs.js +7 -7
  69. package/.agents/scripts/lib/close-validation/projections/maintainability.js +12 -12
  70. package/.agents/scripts/lib/close-validation/runner.js +13 -21
  71. package/.agents/scripts/lib/close-validation/telemetry.js +17 -8
  72. package/.agents/scripts/lib/config/ci.js +6 -31
  73. package/.agents/scripts/lib/config/delivery-routing.js +52 -35
  74. package/.agents/scripts/lib/config/explain.js +61 -48
  75. package/.agents/scripts/lib/config/github.js +7 -5
  76. package/.agents/scripts/lib/config/limits.js +29 -80
  77. package/.agents/scripts/lib/config/paths.js +0 -2
  78. package/.agents/scripts/lib/config/quality.js +12 -15
  79. package/.agents/scripts/lib/config/runners.js +20 -66
  80. package/.agents/scripts/lib/config/temp-paths.js +30 -63
  81. package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
  82. package/.agents/scripts/lib/config-resolver.js +2 -7
  83. package/.agents/scripts/lib/config-settings-schema-delivery.js +55 -161
  84. package/.agents/scripts/lib/config-settings-schema-quality.js +17 -16
  85. package/.agents/scripts/lib/config-settings-schema.js +100 -60
  86. package/.agents/scripts/lib/dead-exports-knip.js +105 -0
  87. package/.agents/scripts/lib/dead-exports-mode.js +51 -0
  88. package/.agents/scripts/lib/dependency-parser.js +3 -2
  89. package/.agents/scripts/lib/doc-tiers.js +2 -2
  90. package/.agents/scripts/lib/duplicate-search.js +242 -41
  91. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
  92. package/.agents/scripts/lib/findings/promote-finding.js +23 -14
  93. package/.agents/scripts/lib/format-generated-json.js +97 -0
  94. package/.agents/scripts/lib/framework-version.js +19 -190
  95. package/.agents/scripts/lib/gh-exec.js +8 -0
  96. package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
  97. package/.agents/scripts/lib/git-branch-lifecycle.js +17 -180
  98. package/.agents/scripts/lib/git-utils.js +32 -20
  99. package/.agents/scripts/lib/github/framework-repo.js +6 -0
  100. package/.agents/scripts/lib/json-utils.js +1 -2
  101. package/.agents/scripts/lib/label-constants.js +10 -38
  102. package/.agents/scripts/lib/label-taxonomy.js +10 -55
  103. package/.agents/scripts/lib/observability/active-story-env.js +44 -165
  104. package/.agents/scripts/lib/observability/runtime-friction.js +243 -0
  105. package/.agents/scripts/lib/observability/signal-validator.js +4 -4
  106. package/.agents/scripts/lib/observability/signals-writer.js +6 -82
  107. package/.agents/scripts/lib/observability/source-classifier.js +5 -5
  108. package/.agents/scripts/lib/observability/tool-trace-hook.js +2 -12
  109. package/.agents/scripts/lib/onboard/init-tail.js +1 -3
  110. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +1 -1
  111. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +2 -2
  112. package/.agents/scripts/lib/orchestration/ceremony-routing.js +105 -44
  113. package/.agents/scripts/lib/orchestration/code-review.js +78 -436
  114. package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
  115. package/.agents/scripts/lib/orchestration/consolidation-precondition.js +4 -4
  116. package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
  117. package/.agents/scripts/lib/orchestration/deliver-recover.js +328 -0
  118. package/.agents/scripts/lib/orchestration/detectors-phase.js +12 -6
  119. package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
  120. package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
  121. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
  122. package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +34 -0
  123. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +3 -2
  124. package/.agents/scripts/lib/orchestration/lifecycle/emit-ledger-event.js +142 -0
  125. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +17 -19
  126. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-flip-failed.js +86 -0
  127. package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +37 -103
  128. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
  129. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +21 -43
  130. package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +50 -85
  131. package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +3 -14
  132. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
  133. package/.agents/scripts/lib/orchestration/merge-block-class.js +77 -21
  134. package/.agents/scripts/lib/orchestration/merge-poll.js +104 -0
  135. package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
  136. package/.agents/scripts/lib/orchestration/plan-context.js +354 -282
  137. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +11 -22
  138. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +4 -8
  139. package/.agents/scripts/lib/orchestration/plan-metrics.js +38 -6
  140. package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
  141. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +71 -0
  142. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +245 -0
  143. package/.agents/scripts/lib/orchestration/plan-persist/plan-context-source.js +116 -0
  144. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +432 -858
  145. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +778 -0
  146. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +47 -115
  147. package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +509 -0
  148. package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
  149. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
  150. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +52 -51
  151. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
  152. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +1 -1
  153. package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
  154. package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
  155. package/.agents/scripts/lib/orchestration/resolve-stories.js +344 -0
  156. package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
  157. package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
  158. package/.agents/scripts/lib/orchestration/review-depth.js +126 -47
  159. package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
  160. package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +3 -13
  161. package/.agents/scripts/lib/orchestration/review-providers/native.js +1 -154
  162. package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +3 -2
  163. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
  164. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +1 -1
  165. package/.agents/scripts/lib/orchestration/review-providers/types.js +5 -4
  166. package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +1 -1
  167. package/.agents/scripts/lib/orchestration/run-epilogue.js +784 -0
  168. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +25 -1
  169. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +11 -9
  170. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +4 -4
  171. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +86 -41
  172. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +608 -152
  173. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +77 -32
  174. package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +305 -0
  175. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +1 -1
  176. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +44 -0
  177. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +37 -4
  178. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +2 -2
  179. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +275 -46
  180. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +1 -1
  181. package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
  182. package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
  183. package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
  184. package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
  185. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
  186. package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +10 -10
  187. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +28 -42
  188. package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +360 -0
  189. package/.agents/scripts/lib/orchestration/story-follow-ups.js +298 -0
  190. package/.agents/scripts/lib/orchestration/story-init-remote.js +51 -0
  191. package/.agents/scripts/lib/orchestration/story-plan-state.js +33 -0
  192. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
  193. package/.agents/scripts/lib/orchestration/task-body-validator.js +60 -25
  194. package/.agents/scripts/lib/orchestration/ticket-lease.js +27 -74
  195. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +130 -75
  196. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +192 -377
  197. package/.agents/scripts/lib/orchestration/ticket-validator.js +123 -25
  198. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +14 -72
  199. package/.agents/scripts/lib/orchestration/ticketing/reads.js +45 -55
  200. package/.agents/scripts/lib/orchestration/ticketing/transition.js +66 -6
  201. package/.agents/scripts/lib/orchestration/ticketing.js +0 -1
  202. package/.agents/scripts/lib/plan-phase-cleanup.js +12 -14
  203. package/.agents/scripts/lib/planning-corpus.js +12 -281
  204. package/.agents/scripts/lib/preflight-runner.js +4 -4
  205. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
  206. package/.agents/scripts/lib/qa/qa-context-hydrator.js +5 -5
  207. package/.agents/scripts/lib/signals/index.js +4 -17
  208. package/.agents/scripts/lib/signals/read.js +35 -35
  209. package/.agents/scripts/lib/signals/schema.js +8 -11
  210. package/.agents/scripts/lib/signals/span-tree.js +7 -7
  211. package/.agents/scripts/lib/signals/write.js +0 -1
  212. package/.agents/scripts/lib/single-story/story-merged-notify.js +13 -2
  213. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
  214. package/.agents/scripts/lib/skills/parse-skill.js +16 -3
  215. package/.agents/scripts/lib/story-adjacency.js +17 -19
  216. package/.agents/scripts/lib/story-body/story-body.js +130 -75
  217. package/.agents/scripts/lib/story-plan.js +2 -4
  218. package/.agents/scripts/lib/templates/decomposer-prompts.js +51 -46
  219. package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
  220. package/.agents/scripts/lib/test-env.js +14 -1
  221. package/.agents/scripts/lib/test-tiers.js +0 -3
  222. package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +25 -39
  223. package/.agents/scripts/lib/validation-evidence.js +32 -60
  224. package/.agents/scripts/lib/wave-runner/ready-set.js +38 -12
  225. package/.agents/scripts/lib/workspace-provisioner.js +1 -1
  226. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +1 -1
  227. package/.agents/scripts/lib/worktree/lifecycle/reap.js +72 -25
  228. package/.agents/scripts/lib/worktree/lifecycle-manager.js +1 -2
  229. package/.agents/scripts/lint-issue-body.js +71 -40
  230. package/.agents/scripts/mandrel-update-preflight.js +1 -1
  231. package/.agents/scripts/notify.js +4 -3
  232. package/.agents/scripts/plan-context.js +102 -80
  233. package/.agents/scripts/plan-persist.js +230 -279
  234. package/.agents/scripts/plan-run-epilogue.js +142 -0
  235. package/.agents/scripts/post-structured-comment.js +0 -38
  236. package/.agents/scripts/pr-watch-with-update.js +43 -22
  237. package/.agents/scripts/providers/github/compose.js +0 -1
  238. package/.agents/scripts/providers/github/errors.js +0 -19
  239. package/.agents/scripts/providers/github/issues.js +13 -39
  240. package/.agents/scripts/providers/github/mappers.js +5 -12
  241. package/.agents/scripts/providers/github/sub-issues.js +0 -47
  242. package/.agents/scripts/providers/github/tickets.js +33 -156
  243. package/.agents/scripts/providers/github.js +17 -6
  244. package/.agents/scripts/resolve-stories.js +236 -0
  245. package/.agents/scripts/run-coverage.js +4 -1
  246. package/.agents/scripts/run-lint.js +2 -2
  247. package/.agents/scripts/run-verify.js +31 -2
  248. package/.agents/scripts/signals-view.js +25 -21
  249. package/.agents/scripts/single-story-close.js +178 -26
  250. package/.agents/scripts/single-story-confirm-merge.js +313 -24
  251. package/.agents/scripts/single-story-init.js +35 -30
  252. package/.agents/scripts/stories-wave-tick.js +85 -10
  253. package/.agents/scripts/story-plan.js +28 -49
  254. package/.agents/scripts/update-ticket-state.js +14 -65
  255. package/.agents/skills/core/code-review-and-quality/SKILL.md +28 -450
  256. package/.agents/skills/core/code-review-and-quality/reference.md +458 -0
  257. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +22 -315
  258. package/.agents/skills/core/debugging-and-error-recovery/reference.md +323 -0
  259. package/.agents/skills/core/diagnose-friction/SKILL.md +14 -18
  260. package/.agents/skills/core/documentation-and-adrs/SKILL.md +25 -397
  261. package/.agents/skills/core/documentation-and-adrs/reference.md +403 -0
  262. package/.agents/skills/core/gates-and-baselines/SKILL.md +12 -12
  263. package/.agents/skills/core/idea-refinement/SKILL.md +9 -9
  264. package/.agents/skills/core/scope-triage/SKILL.md +31 -172
  265. package/.agents/skills/core/security-and-hardening/SKILL.md +22 -367
  266. package/.agents/skills/core/security-and-hardening/reference.md +375 -0
  267. package/.agents/skills/skills.index.json +3 -53
  268. package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +2 -4
  269. package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +1 -1
  270. package/.agents/skills/stack/qa/qa-harness/SKILL.md +1 -3
  271. package/.agents/starter-agentrc.json +0 -5
  272. package/.agents/templates/agent-protocol.md +9 -10
  273. package/.agents/workflows/audit-architecture.md +6 -7
  274. package/.agents/workflows/audit-clean-code.md +7 -7
  275. package/.agents/workflows/audit-dependencies.md +3 -3
  276. package/.agents/workflows/audit-devops.md +3 -3
  277. package/.agents/workflows/audit-documentation.md +9 -10
  278. package/.agents/workflows/audit-lighthouse.md +11 -3
  279. package/.agents/workflows/audit-navigability.md +13 -2
  280. package/.agents/workflows/audit-performance.md +5 -6
  281. package/.agents/workflows/audit-privacy.md +3 -3
  282. package/.agents/workflows/audit-quality.md +11 -12
  283. package/.agents/workflows/audit-security.md +4 -5
  284. package/.agents/workflows/audit-seo.md +13 -3
  285. package/.agents/workflows/audit-sre.md +3 -3
  286. package/.agents/workflows/audit-to-stories.md +20 -20
  287. package/.agents/workflows/audit-ux-ui.md +10 -3
  288. package/.agents/workflows/deliver.md +177 -176
  289. package/.agents/workflows/git-cleanup.md +5 -6
  290. package/.agents/workflows/git-deliver.md +1 -1
  291. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  292. package/.agents/workflows/helpers/acceptance-self-eval.md +35 -40
  293. package/.agents/workflows/helpers/code-quality-guardrails.md +7 -7
  294. package/.agents/workflows/helpers/code-review.md +75 -196
  295. package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +83 -44
  296. package/.agents/workflows/helpers/deliver-story.md +606 -0
  297. package/.agents/workflows/helpers/diagnose.md +10 -10
  298. package/.agents/workflows/helpers/parallel-tooling.md +3 -3
  299. package/.agents/workflows/helpers/signals.md +16 -16
  300. package/.agents/workflows/helpers/worktree-lifecycle.md +66 -86
  301. package/.agents/workflows/mandrel-update.md +2 -1
  302. package/.agents/workflows/plan.md +277 -145
  303. package/.agents/workflows/qa-assist.md +27 -33
  304. package/.agents/workflows/qa-explore.md +29 -38
  305. package/.agents/workflows/qa-run.md +2 -6
  306. package/README.md +9 -8
  307. package/bin/mandrel.js +12 -1
  308. package/docs/CHANGELOG.md +70 -0
  309. package/lib/cli/registry.js +262 -19
  310. package/lib/cli/sync-agents.js +157 -0
  311. package/lib/cli/sync-commands.js +115 -6
  312. package/lib/cli/sync.js +168 -6
  313. package/lib/cli/update.js +105 -8
  314. package/lib/cli/version-helpers.js +131 -0
  315. package/lib/migrations/README.md +7 -5
  316. package/lib/migrations/index.js +12 -8
  317. package/lib/migrations/steps/2.1.0-retire-mi-drop-knobs.js +100 -0
  318. package/lib/migrations/steps/2.1.0-retire-verify-concurrency-cap.js +101 -0
  319. package/package.json +2 -2
  320. package/.agents/agents/retro.md +0 -42
  321. package/.agents/personas/architect.md +0 -113
  322. package/.agents/personas/devops-engineer.md +0 -38
  323. package/.agents/personas/engineer.md +0 -33
  324. package/.agents/personas/project-manager.md +0 -114
  325. package/.agents/personas/qa-engineer.md +0 -95
  326. package/.agents/personas/security-engineer.md +0 -111
  327. package/.agents/personas/technical-writer.md +0 -101
  328. package/.agents/schemas/dispatch-manifest.json +0 -232
  329. package/.agents/schemas/epic-perf-report.schema.json +0 -89
  330. package/.agents/schemas/epic-spec.schema.json +0 -153
  331. package/.agents/schemas/lifecycle/acceptance.reconcile.failed.schema.json +0 -13
  332. package/.agents/schemas/lifecycle/acceptance.reconcile.ok.schema.json +0 -13
  333. package/.agents/schemas/lifecycle/acceptance.reconcile.skipped.schema.json +0 -13
  334. package/.agents/schemas/lifecycle/acceptance.reconcile.start.schema.json +0 -12
  335. package/.agents/schemas/lifecycle/acceptance.reconcile.waived.schema.json +0 -13
  336. package/.agents/schemas/lifecycle/epic.automerge.end.schema.json +0 -15
  337. package/.agents/schemas/lifecycle/epic.automerge.start.schema.json +0 -13
  338. package/.agents/schemas/lifecycle/epic.blocked.schema.json +0 -13
  339. package/.agents/schemas/lifecycle/epic.cleanup.end.schema.json +0 -12
  340. package/.agents/schemas/lifecycle/epic.cleanup.start.schema.json +0 -12
  341. package/.agents/schemas/lifecycle/epic.close.end.schema.json +0 -12
  342. package/.agents/schemas/lifecycle/epic.complete.schema.json +0 -13
  343. package/.agents/schemas/lifecycle/epic.finalize.end.schema.json +0 -13
  344. package/.agents/schemas/lifecycle/epic.finalize.start.schema.json +0 -12
  345. package/.agents/schemas/lifecycle/epic.merge.armed.schema.json +0 -13
  346. package/.agents/schemas/lifecycle/epic.merge.blocked.schema.json +0 -14
  347. package/.agents/schemas/lifecycle/epic.merge.confirmed.schema.json +0 -17
  348. package/.agents/schemas/lifecycle/epic.merge.ready.schema.json +0 -15
  349. package/.agents/schemas/lifecycle/epic.plan.end.schema.json +0 -18
  350. package/.agents/schemas/lifecycle/epic.plan.start.schema.json +0 -12
  351. package/.agents/schemas/lifecycle/epic.snapshot.end.schema.json +0 -16
  352. package/.agents/schemas/lifecycle/epic.snapshot.start.schema.json +0 -12
  353. package/.agents/schemas/lifecycle/epic.watch.end.schema.json +0 -29
  354. package/.agents/schemas/lifecycle/epic.watch.start.schema.json +0 -16
  355. package/.agents/schemas/lifecycle/slice.end.schema.json +0 -21
  356. package/.agents/schemas/lifecycle/slice.heartbeat.schema.json +0 -20
  357. package/.agents/schemas/lifecycle/slice.start.schema.json +0 -17
  358. package/.agents/schemas/lifecycle/story.heartbeat.schema.json +0 -20
  359. package/.agents/schemas/risk-verdict.schema.json +0 -66
  360. package/.agents/schemas/story-perf-summary.schema.json +0 -73
  361. package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
  362. package/.agents/scripts/analyze-execution.js +0 -444
  363. package/.agents/scripts/bookkeeping-reconcile.js +0 -117
  364. package/.agents/scripts/check-prepush-recovery.js +0 -90
  365. package/.agents/scripts/dispatcher.js +0 -295
  366. package/.agents/scripts/epic-audit-prepare.js +0 -497
  367. package/.agents/scripts/epic-audit-recheck.js +0 -274
  368. package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
  369. package/.agents/scripts/epic-deliver-preflight.js +0 -462
  370. package/.agents/scripts/epic-deliver-prepare.js +0 -852
  371. package/.agents/scripts/epic-execute-record-wave.js +0 -449
  372. package/.agents/scripts/epic-plan-clarity.js +0 -211
  373. package/.agents/scripts/epic-plan-healthcheck.js +0 -581
  374. package/.agents/scripts/epic-reconcile.js +0 -625
  375. package/.agents/scripts/lib/baseline-snapshot.js +0 -979
  376. package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
  377. package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
  378. package/.agents/scripts/lib/config/lifecycle.js +0 -40
  379. package/.agents/scripts/lib/config/preflight.js +0 -58
  380. package/.agents/scripts/lib/config/retro.js +0 -77
  381. package/.agents/scripts/lib/epic-merge-lock.js +0 -322
  382. package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
  383. package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
  384. package/.agents/scripts/lib/git-merge-orchestrator.js +0 -261
  385. package/.agents/scripts/lib/observability/baseline-refresh-rate.js +0 -221
  386. package/.agents/scripts/lib/observability/hook-heartbeat.js +0 -219
  387. package/.agents/scripts/lib/observability/perf-aggregator.js +0 -813
  388. package/.agents/scripts/lib/observability/perf-report-readers.js +0 -328
  389. package/.agents/scripts/lib/observability/perf-report-render.js +0 -182
  390. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +0 -270
  391. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -539
  392. package/.agents/scripts/lib/orchestration/deliver-route.js +0 -173
  393. package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
  394. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
  395. package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
  396. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
  397. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
  398. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
  399. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
  400. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
  401. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
  402. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
  403. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
  404. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
  405. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
  406. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
  407. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
  408. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/risk-verdict.js +0 -105
  409. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
  410. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
  411. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
  412. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -621
  413. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
  414. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
  415. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
  416. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
  417. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
  418. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
  419. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
  420. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
  421. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
  422. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
  423. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
  424. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
  425. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
  426. package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +0 -400
  427. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
  428. package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
  429. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
  430. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
  431. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
  432. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
  433. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
  434. package/.agents/scripts/lib/orchestration/error-journal.js +0 -139
  435. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
  436. package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
  437. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
  438. package/.agents/scripts/lib/orchestration/lifecycle/emit-slice-lifecycle.js +0 -270
  439. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
  440. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +0 -155
  441. package/.agents/scripts/lib/orchestration/lifecycle/ledger-diff.js +0 -140
  442. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -465
  443. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
  444. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
  445. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
  446. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -284
  447. package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
  448. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
  449. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
  450. package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
  451. package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
  452. package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +0 -665
  453. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
  454. package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
  455. package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
  456. package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
  457. package/.agents/scripts/lib/orchestration/plan-review-routing.js +0 -63
  458. package/.agents/scripts/lib/orchestration/planning-context-budget.js +0 -213
  459. package/.agents/scripts/lib/orchestration/planning-risk.js +0 -194
  460. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +0 -56
  461. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +0 -33
  462. package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +0 -78
  463. package/.agents/scripts/lib/orchestration/post-merge/phases/temp-cleanup.js +0 -68
  464. package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +0 -118
  465. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +0 -396
  466. package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
  467. package/.agents/scripts/lib/orchestration/preflight-cache.js +0 -187
  468. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
  469. package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
  470. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
  471. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
  472. package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
  473. package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
  474. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +0 -275
  475. package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
  476. package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
  477. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
  478. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
  479. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
  480. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
  481. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
  482. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
  483. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
  484. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
  485. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
  486. package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
  487. package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
  488. package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
  489. package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
  490. package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
  491. package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
  492. package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
  493. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
  494. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
  495. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
  496. package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
  497. package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
  498. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
  499. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
  500. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
  501. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -302
  502. package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
  503. package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
  504. package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
  505. package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
  506. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
  507. package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
  508. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
  509. package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
  510. package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
  511. package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
  512. package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
  513. package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
  514. package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
  515. package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
  516. package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
  517. package/.agents/scripts/lib/push-epic-retry.js +0 -209
  518. package/.agents/scripts/lib/spec/index.js +0 -36
  519. package/.agents/scripts/lib/spec/loader.js +0 -425
  520. package/.agents/scripts/lib/spec/state.js +0 -208
  521. package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
  522. package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
  523. package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
  524. package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
  525. package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
  526. package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
  527. package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
  528. package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
  529. package/.agents/scripts/lib/wave-runner/tick.js +0 -754
  530. package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
  531. package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
  532. package/.agents/scripts/lifecycle-emit.js +0 -510
  533. package/.agents/scripts/retro-run.js +0 -218
  534. package/.agents/scripts/slice-phase.js +0 -361
  535. package/.agents/scripts/standalone-feedback-rollup.js +0 -188
  536. package/.agents/scripts/story-close.js +0 -294
  537. package/.agents/scripts/story-init.js +0 -599
  538. package/.agents/scripts/story-phase.js +0 -369
  539. package/.agents/scripts/wave-tick.js +0 -464
  540. package/.agents/skills/core/analyze-execution/SKILL.md +0 -98
  541. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
  542. package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
  543. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
  544. package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
  545. package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
  546. package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
  547. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -383
  548. package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
  549. package/.agents/workflows/helpers/deliver-epic-reference.md +0 -547
  550. package/.agents/workflows/helpers/deliver-epic-single.md +0 -331
  551. package/.agents/workflows/helpers/deliver-epic.md +0 -998
  552. package/.agents/workflows/helpers/deliver-stories.md +0 -450
  553. package/.agents/workflows/helpers/epic-audit.md +0 -189
  554. package/.agents/workflows/helpers/epic-deliver-story.md +0 -436
  555. package/.agents/workflows/helpers/epic-testing.md +0 -125
  556. package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
  557. package/.agents/workflows/helpers/plan-epic.md +0 -353
  558. package/.agents/workflows/helpers/plan-story.md +0 -251
  559. package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
  560. package/.agents/workflows/helpers/single-story-deliver.md +0 -557
@@ -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
- });