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,998 +0,0 @@
1
- ---
2
- description: >-
3
- Drive an Epic from `agent::ready` to a merged pull request against `main`.
4
- The ten-phase flow runs the wave loop, close-validation, the Epic-close
5
- lens-roster resolve, the code-review pass (which walks the cumulative diff
6
- once with the lens roster folded in), retro, finalize, watch-and-iterate,
7
- conditional auto-merge,
8
- and local branch cleanup. When the run is end-to-end clean (zero manual
9
- interventions, zero 🔴/🟠 review findings, compact retro) the PR
10
- auto-merges via `gh pr merge --squash --delete-branch`; otherwise the
11
- workflow falls back to the operator-merges-button path so a human
12
- inspects the surface area.
13
- ---
14
-
15
- # helpers/deliver-epic — Epic delivery path (invoked by /deliver)
16
-
17
- > **Runtime core.** This file is the always-ingested Epic-delivery path:
18
- > phase flow, commands, gate contracts, and return shapes. The recovery
19
- > procedures, historical rationale, and troubleshooting detail live in the
20
- > sibling [`deliver-epic-reference.md`](deliver-epic-reference.md); each
21
- > moved procedure keeps a one-line pointer at its trigger point below. The
22
- > reference is not projected to `.claude/commands/` — it is consulted on
23
- > demand.
24
-
25
- ## Overview
26
-
27
- This helper is the **Epic delivery path** behind `/deliver` — the router
28
- delegates to it once per Epic ID, either as the sole route (single-Epic
29
- input) or as one **Epic segment** of the sequential segment plan `/deliver`
30
- composes over mixed Epic / standalone-Story input (Epic segments run in
31
- input order, after the standalone segment; see
32
- [`deliver.md`](../deliver.md)). Each invocation opens a PR against `main`
33
- and auto-merges when every signal certifies a clean run; otherwise it falls
34
- back to the operator-merges-button path.
35
-
36
- ```text
37
- /deliver <epicId>
38
- → Phase 1 — prepare (epic-deliver-prepare.js)
39
- → Phase 2 — ready-set loop (wave-tick.js → dispatch ready set → observe → re-tick)
40
- → Phase 3 — close-validation (lint + test + ratchets on epic/<id>)
41
- → Phase 4 — epic-close lens roster (helpers/epic-audit.md — resolve the slim cumulative+global+risk-routed roster)
42
- → Phase 5 — code-review (helpers/code-review.md scope: epic — walks the cumulative diff once, lens roster folded in)
43
- → Phase 6 — retro (.agents/scripts/lib/orchestration/retro-runner.js)
44
- → Phase 6.5 — integration gate (whole-product navigability + journey suite; @pending ≠ green for surface-adding Epics — blocks finalize)
45
- → Phase 7 — finalize (lifecycle-emit → epic.close.end → open PR to main)
46
- → Phase 8 — watch-and-iterate (poll `gh pr checks`; fix locally until green)
47
- → Phase 8.5 — auto-merge gate (lifecycle-emit → epic.automerge.start)
48
- → Phase 9 — cleanup (BranchCleaner + Cleaner lifecycle listeners on epic.cleanup.start / epic.merge.armed; fire via lifecycle-emit → epic.merge.armed)
49
- ```
50
-
51
- The argument is always a single Epic ID (`type::epic`) — multi-Epic or
52
- mixed input is segmented by the `/deliver` router before this helper runs.
53
- Story IDs go to
54
- [`helpers/deliver-stories`](deliver-stories.md) (standalone) or the
55
- [`helpers/epic-deliver-story`](epic-deliver-story.md) helper
56
- (Epic-attached, invoked by this workflow's fan-out); Tasks are not directly
57
- executable.
58
- Story dispatch is in-session via the Agent tool — no subprocess is
59
- spawned.
60
-
61
- ---
62
-
63
- ## Arguments
64
-
65
- ```text
66
- /deliver <epicId> [--skip-epic-audit] [--skip-code-review] [--skip-retro] [--full-retro] [--skip-integration-gate]
67
- ```
68
-
69
- - `epicId` — must carry `type::epic`. Otherwise STOP and tell the operator
70
- to use `/deliver <id>` (standalone Story) or open the parent Epic.
71
- - `--skip-epic-audit` — skip Phase 4 (log the override). Use only when the
72
- change-set audits are known to be irrelevant (e.g., docs-only Epic).
73
- - `--skip-code-review` — skip Phase 5 (log the override).
74
- - `--skip-retro` — skip Phase 6 (use sparingly).
75
- - `--full-retro` — force the six-section retro regardless of manifest
76
- cleanliness. `--skip-retro` wins over `--full-retro`.
77
- - `--skip-integration-gate` — skip Phase 6.5 (log the override). The
78
- explicit operator override for the post-wave integration gate,
79
- consistent with `--skip-epic-audit`. Skipping the gate is recorded as a
80
- manual intervention and disqualifies auto-merge, exactly like the other
81
- `--skip-*` overrides.
82
-
83
- Every other runtime modifier is sourced from the Epic's labels or from
84
- `delivery.deliverRunner` in `.agentrc.json`.
85
-
86
- - `--yes` — the top-level `/deliver` unattended flag (suppresses the
87
- operator confirmation gate; see [`deliver.md`](../deliver.md)). This
88
- helper reads it as the **headless signal** for Phase 8.5's must-land
89
- terminal step (Story #4427): when `/deliver` was invoked with `--yes`,
90
- thread `--headless true` into the Phase 8.5
91
- `epic.automerge.start` `lifecycle-emit.js` call (omit the flag, or
92
- pass `--headless false`, for an attended run). The runtime reads this
93
- as an explicit `headless` input threaded through
94
- `runLifecycleEmit` → `buildDefaultListenerChain` →
95
- `MergeWatcher({ headless })` — never an ambient/undefined global.
96
- Attended-mode behavior (no `--headless` flag) is byte-for-byte
97
- unchanged: `MergeWatcher` defaults `headless` to `false`.
98
-
99
- ---
100
-
101
- ## Contract
102
-
103
- - **Idempotent by checkpoint.** Re-runs resume from `epic-run-state`.
104
- - **Single pause point.** Only `agent::blocked` halts execution. No
105
- clarifying questions — if stuck, flip to `agent::blocked`, post a
106
- friction comment, park.
107
- - **Flat Story dispatch by design.** Host LLM fans out per-Story Agent
108
- calls directly — with `subagent_type: story-worker` when
109
- `delivery.routing.roleScopedAgents` is on (the default; § 2b), else
110
- `general-purpose`. Keeping Story
111
- dispatch flat — the host owns the single fan-out level — is a
112
- **design choice**, not a harness constraint: the wave aggregator, idle
113
- watchdog, and merge-lock all assume one host-owned dispatch level. As of
114
- Claude Code 2.1.202 a level-1 sub-agent **does** carry the `Agent` tool
115
- and can nest further (verified depth 2, announced max depth 5; see
116
- [#2870](https://github.com/dsj1984/mandrel/issues/2870)), so a Story
117
- worker may itself fan out for its own sub-work within that depth budget —
118
- the Epic wave loop nonetheless stays flat by choice, not because nesting
119
- is unavailable.
120
- - **Operator-merges-PR exit.** Phase 7 opens the PR; the workflow
121
- never merges to `main` itself. Phase 8.5 may fire auto-merge when
122
- every signal is clean.
123
- - **Lifecycle bus is the runner model.** Phase transitions, ticket
124
- state flips, structured comments, and notifications are emitted as
125
- typed events on the in-session lifecycle bus; a fixed roster of
126
- listeners performs the side effects. Phase 7, 8.5, and 9 each fire
127
- exactly one lifecycle event via the generic
128
- [`lifecycle-emit.js`](../../scripts/lifecycle-emit.js) CLI
129
- (`--event epic.close.end` / `--event epic.automerge.start` /
130
- `--event epic.merge.armed`); the matching listener chain runs the
131
- bus-driven side effects (acceptance reconcile, automerge-armer,
132
- branch cleanup). The append-only NDJSON ledger at
133
- `temp/epic-<id>/lifecycle.ndjson` is the resume target. See
134
- [`docs/LIFECYCLE.md`](../../../docs/LIFECYCLE.md) for the bus
135
- contract, event taxonomy, ledger format, and listener model.
136
-
137
- > **Hierarchy.** `/deliver` operates over the 2-tier hierarchy
138
- > (Epic → Story). The fan-out is one `Agent` tool call per
139
- > Story per wave (§ 2b); Story branches merge into `epic/<id>` with
140
- > `--no-ff` via `story-close.js`; the close-validation chain
141
- > (Phase 3), epic-audit, code-review, retro, finalize, and auto-merge
142
- > gates all operate on Story-level units.
143
- > [`helpers/epic-deliver-story`](epic-deliver-story.md) runs a
144
- > single Story-implementation phase per Story against the Story's
145
- > inline `acceptance[]` / `verify[]` fields. See
146
- > [`.agents/instructions.md` § 5.D](../../instructions.md) and
147
- > [`.agents/docs/SDLC.md` § Ticket hierarchy](../../docs/SDLC.md) for the full
148
- > contract.
149
-
150
- ---
151
-
152
- ## Phase 1 — Prepare the Epic run
153
-
154
- ### Phase 1 prelude — Delivery preflight (Story #2899 / F13)
155
-
156
- Before `epic-deliver-prepare.js` seeds the checkpoint, run
157
- `epic-deliver-preflight.js` so the operator (and any reviewer reading the
158
- Epic ticket) sees the estimated Story count, install cost, dependency depth,
159
- GitHub API request volume, and Claude Max quota burn for the run that is
160
- about to fan out. **Preflight always runs before Story fan-out.**
161
-
162
- ```bash
163
- node .agents/scripts/epic-deliver-preflight.js --epic <epicId> --post
164
- ```
165
-
166
- The CLI upserts a `delivery-preflight` structured comment on the Epic
167
- (idempotent across re-runs) and prints a JSON envelope on stdout with
168
- the canonical metric keys `storyCount`, `installCostSeconds`,
169
- `dependencyDepth` (the longest dependency chain — the ready-set wall-clock
170
- floor, replacing the retired wave count), `githubApiRequests`,
171
- `claudeQuotaTokens`, plus a `breaches` array describing any
172
- `delivery.preflight.max*` thresholds the estimate exceeds.
173
-
174
- **Breach handling.** When `breaches` is non-empty, the workflow MUST
175
- flip the Epic to `agent::blocked`, surface the envelope in chat for the
176
- operator, and halt before Phase 1's `epic-deliver-prepare.js` call.
177
- Resume after the operator unblocks (raising the threshold in
178
- `.agentrc.json`, splitting the Epic, or accepting the cost) by re-running
179
- `/deliver <epicId>` — the preflight is idempotent and the second
180
- run upserts the same comment in place.
181
-
182
- Threshold defaults live in `delivery.preflight.*` in `.agentrc.json`
183
- (all keys default to "no cap" — the gate is opt-in until an operator
184
- configures `maxStories` etc.).
185
-
186
- **Remote evidence — land or block (issue #4483).** The envelope also
187
- carries `remoteVerified` + `remoteProbe` (deterministic probes:
188
- `git remote get-url origin`, bounded `git ls-remote origin HEAD`). When
189
- `remoteVerified` is `false`, flip the Epic to `agent::blocked`, post a
190
- friction comment quoting `remoteProbe.detail`, and halt — the same
191
- explicit-block shape as #4425/#4480. NEVER fall back to executing Stories
192
- inline in this session or committing the delivery to local `main`; the
193
- worktree/branch/PR path below is the only sanctioned mechanism. Phase 7's
194
- finalize additionally refuses with a `delivery-branch-missing-on-origin`
195
- blocker when `epic/<epicId>` never reached origin.
196
-
197
- ### Phase 1 main — Seed the wave plan
198
-
199
- ```bash
200
- node .agents/scripts/epic-deliver-prepare.js --epic <epicId> [--steal] [--as <handle>]
201
- ```
202
-
203
- Validates `type::epic`, enumerates `type::story` descendants, parses
204
- `blocked by #N` plus explicit `dependencies`, computes the dependency DAG
205
- (to enumerate the open Story set), and upserts the `epic-run-state`
206
- checkpoint in the per-Story-status shape (a flat `stories` map seeded at
207
- `pending`, plus the global `concurrencyCap`). Treat the printed JSON as
208
- `state`: `{ epicId, storyCount, concurrencyCap, stories, checkpointInitializedAt, docsDigestPath }`.
209
- `stories` is the flat dispatch hint (`{ storyId, worktree, title,
210
- checklistPath }` per open Story); the ready-set `tick` (Phase 2) decides
211
- which to dispatch on each beat. `checklistPath` is the repo-relative path to
212
- that Story's footprint-matched local-lens authoring checklist
213
- (`temp/epic-<epicId>/checklists/story-<storyId>.md`, Story #4410) — thread it
214
- into that child's prompt (§ 2b, item 7); it is `null` when the Story's
215
- predicted footprint matched no local lens. `docsDigestPath` is the
216
- repo-relative path to the per-Epic docs digest
217
- (`temp/epic-<epicId>/docs-digest.md`) that prepare writes from
218
- `project.docsContextFiles` — thread it into every child prompt (§ 2b, item 6).
219
- It is `null` when the project configured no `docsContextFiles` (no digest is
220
- written). Flip the Epic to `agent::executing` (idempotent) after the CLI
221
- returns.
222
-
223
- **No spec-ticket linkage to resolve (Story #4324).** The Tech Spec lives
224
- as managed sections of the Epic body itself — there is no separate
225
- Tech-Spec issue id in the envelope and no `--tech-spec` flag to thread
226
- into the per-Story `story-init.js` invocations. Story agents receive the
227
- Tech Spec via context hydration, which embeds the Epic body (with the
228
- `## Acceptance Table` section stripped) directly into each Story prompt.
229
-
230
- > **Preflight guards + acceptance-table start gate.** Before the snapshot
231
- > phase runs — and before any worktree is created — prepare runs two
232
- > **fail-closed** guards (checkout safety + Epic lease), then the snapshot
233
- > phase asserts the Epic carries an `acceptance::n-a` waiver or a
234
- > `## Acceptance Table` section. Both throw on failure. See
235
- > [`deliver-epic-reference.md` § Phase 1 — Preflight guards](deliver-epic-reference.md#phase-1--preflight-guards-story-3482--f-workflow-guards)
236
- > for the remediation detail (dirty-tree recovery, `--steal`, waiver
237
- > options).
238
-
239
- ---
240
-
241
- ## Phase 2 — Ready-set loop
242
-
243
- The scheduler lives in
244
- [`lib/wave-runner/tick.js`](../../scripts/lib/wave-runner/tick.js) — a thin
245
- **Epic adapter over the ready-set core**
246
- ([`lib/wave-runner/ready-set.js`](../../scripts/lib/wave-runner/ready-set.js)).
247
- One stateless `tick({ epic })` call re-derives readiness from the **live**
248
- Story bodies + labels on every beat and returns one `WaveTickResult`
249
- describing the next action. There is **no wave barrier** (Story #4155): a
250
- Story whose own dependencies are all done is dispatched the instant a slot is
251
- free under the GLOBAL in-flight cap, even while an unrelated sibling Story is
252
- still `agent::executing`. The loop is simply:
253
-
254
- ```text
255
- tick → dispatch the ready set → observe → re-tick → … → epic-complete
256
- ```
257
-
258
- The slash command's job each beat is to call `tick()` via its CLI shim,
259
- dispatch the Stories in `nextAction.stories` via the Agent tool, record each
260
- returned Story's terminal status, and re-tick until terminal. There is no
261
- `record-wave` / `currentWave` step — the checkpoint carries only a flat
262
- per-Story status map (for resume + the operator rollup) and the global cap.
263
-
264
- ### 2.0. Open the Epic PR as a draft at wave 1 (Story #4359)
265
-
266
- When `delivery.ci.earlyPr` is on (the default), open the Epic PR as a
267
- **draft** once, before the first `tick`, so every subsequent per-wave push
268
- to `epic/<epicId>` runs CI attributed to its own wave. (CI is keyed on the PR
269
- ref with `cancel-in-progress`, so each new wave push **supersedes** the prior
270
- wave's in-flight run rather than queuing behind it — the latest wave always
271
- gets the verdict, and CI-minute use stays bounded; intermediate wave runs are
272
- cancelled, not completed.) Resolve the flag through the
273
- [`getCiDelivery`](../../scripts/lib/config/ci.js) accessor (default `true`);
274
- do not read `delivery.ci.earlyPr` directly.
275
-
276
- > **This step is host-LLM-driven, with no runtime enforcement seam** — unlike
277
- > the Phase 7 ready-flip, which the `Finalizer` listener wires in
278
- > deterministically (`finalizer.js` resolves `earlyPr` and calls
279
- > `markPrReady`). The asymmetry is intentional and safe: if this wave-1
280
- > draft-open is skipped, the `earlyPr`-on Phase 7 `markPrReady` call degrades
281
- > to a no-op on the PR that finalize opens at close time (`gh pr ready` is a
282
- > no-op on an already-ready PR), so the merge gate is never stranded — the run
283
- > only loses the per-wave CI attribution this step buys.
284
-
285
- - **`earlyPr` on** — call
286
- [`openOrLocatePr`](../../scripts/lib/orchestration/finalize/open-or-locate-pr.js)
287
- with `{ epicId, headBranch: 'epic/<epicId>', baseBranch: 'main', draft: true }`.
288
- The helper probes for an existing open PR first, so this is idempotent — a
289
- resumed `/deliver` run re-locates the same draft and opens no duplicate.
290
- Phase 7 later flips this draft to ready-for-review (it does **not**
291
- re-create the PR).
292
- - **`earlyPr` off** — skip this step entirely. No draft is opened at wave 1;
293
- Phase 7 opens the PR at close time on the pre-Story timing.
294
-
295
- The draft carries the same title/body contract Phase 7 uses
296
- (`feat: Epic #<epicId>` / `Closes #<epicId>`), so no title/body reconciliation
297
- is needed when it is marked ready.
298
-
299
- ### 2a. Tick — plan the next action
300
-
301
- ```bash
302
- node .agents/scripts/wave-tick.js --epic <epicId>
303
- ```
304
-
305
- Stdout is one `WaveTickResult` envelope:
306
-
307
- ```json
308
- {
309
- "nextAction":
310
- { "kind": "dispatch", "stories": [{ "id": <n>, "title": "…" }, ...], "in-flight": [<storyId>, ...] }
311
- | { "kind": "observe", "waitingOn": [<storyId>, ...], "in-flight": [<storyId>, ...] }
312
- | { "kind": "halt", "reason": "dependency-cycle" | "unsatisfiable-dependency", "stuckStories": [<storyId>, ...], "cycle"?: [<storyId>, ...], "in-flight": [<storyId>, ...] }
313
- | { "kind": "epic-complete", "in-flight": [<storyId>, ...] },
314
- "blockedStories": [{ "storyId": <n>, "reason": "…", "detail"?: "…" }, ...],
315
- "gateFailures": [{ "storyId": <n>, "gate": "…", "detail"?: "…" }, ...],
316
- "readyCount": <n>,
317
- "inFlight": [<storyId>, ...]
318
- }
319
- ```
320
-
321
- `nextAction.stories` is the **ready set** for this beat — the
322
- dependency-satisfied, overlap-free subset of open Stories, capped at
323
- `globalCap − inFlight`. The CLI is a planner: it dispatches nothing and
324
- persists nothing. It emits only the two wave-window forensics signals that
325
- have a live consumer — `wave-start` (on the run's first dispatch) and
326
- `wave-complete` (when the run finishes), which the perf-aggregator brackets
327
- into the `waveParallelism` report (and `wave-start` anchors span-tree Story
328
- spans). The [`signals` helper](signals.md)
329
- (`node .agents/scripts/signals-view.js`) renders the forensics signals in the
330
- span-tree view.
331
-
332
- > **Old-shape checkpoint → fail-closed.** A pre-ready-set
333
- > (`plan` / `currentWave` / `totalWaves`) checkpoint makes the tick refuse
334
- > to run and throw; re-seed via `epic-deliver-prepare.js`. See
335
- > [`deliver-epic-reference.md` § Fail-closed on an old-shape checkpoint](deliver-epic-reference.md#fail-closed-on-an-old-shape-checkpoint).
336
-
337
- ### 2b. Dispatch — fan out per-Story Agent calls
338
-
339
- *You* (the LLM running this skill) are the dispatcher; you never invoke
340
- `helpers/epic-deliver-story` yourself. Emit **one `Agent` tool call per
341
- Story** in `nextAction.stories` (even when `length === 1` — the
342
- parent-child boundary keeps the return-parser uniform). The *children*
343
- run [`helpers/epic-deliver-story`](epic-deliver-story.md).
344
-
345
- **Sub-agent type (Epic #4478, M7-B).** When
346
- `delivery.routing.roleScopedAgents` is enabled (the **default**), each Story
347
- child is dispatched with `subagent_type: story-worker` — it boots on the
348
- role-scoped [`story-worker`](../../agents/story-worker.md) context (its own
349
- system prompt, no `CLAUDE.md` @-closure) that carries every load-bearing
350
- delivery MUST standalone, so the spawn stops re-paying the always-loaded
351
- context. When the kill-switch is **off**
352
- (`delivery.routing.roleScopedAgents: false`), fall back to
353
- `subagent_type: general-purpose` — the instant, code-rollback-free revert and
354
- the escape for hosts that ignore `.claude/agents/`.
355
-
356
- Emit **one assistant turn** with **N parallel `Agent` calls** where
357
- `N === nextAction.stories.length` (the ready set is already capped at
358
- `globalCap − inFlight` by the tick, so it never exceeds available slots).
359
- Dispatch the ready set as background calls (`run_in_background: true`) and,
360
- as each child returns, record it (§ 2c) and **re-tick** (§ 2a) to pull the
361
- next ready set — never wait for the whole set before refilling.
362
-
363
- > **Throughput + capability tuning.** The default `concurrencyCap` of 3 is
364
- > a deliberate operator-tuning knob (raise
365
- > `delivery.deliverRunner.concurrencyCap`), and the optional per-call
366
- > `model:` escape hatch lets mechanical Stories run on a cheaper capability.
367
- > See [`deliver-epic-reference.md` § Throughput tradeoff](deliver-epic-reference.md#throughput-tradeoff)
368
- > and [§ Sub-agent dispatch capability](deliver-epic-reference.md#sub-agent-dispatch-capability).
369
-
370
- **Ledger the dispatch BEFORE the Agent call.** Immediately before each
371
- per-Story `Agent` tool call (one shell-out per Story, every attempt —
372
- including retries from a refill), invoke
373
- [`lifecycle-emit-story-dispatch.js`](../../scripts/lifecycle-emit-story-dispatch.js)
374
- so the lifecycle ledger durably records the dispatch attempt. The
375
- emit must happen **before** the Agent call fires — never after — so
376
- that a host-process crash mid-Agent leaves a `story.dispatch.start`
377
- record that `wave-tick.js` (see § 2a) excludes from the next beat's ready
378
- set and surfaces under `nextAction['in-flight']`:
379
-
380
- ```bash
381
- node .agents/scripts/lifecycle-emit-story-dispatch.js \
382
- --epic <epicId> --story <storyId> \
383
- --wave 0 --attempt <attempt>
384
- ```
385
-
386
- Pass `--wave 0` — the ready-set runtime has a single continuous front, so
387
- the ledger's `waveIndex` is a fixed `0` (it is metadata for the start/end
388
- pairing math, not a scheduling input). `<attempt>` starts at 1 for the
389
- Story's first dispatch and increments on each retry/refill. The CLI appends
390
- exactly one NDJSON line to `temp/epic-<epicId>/lifecycle.ndjson`; the
391
- matching `story.dispatch.end` record is appended later by
392
- `epic-execute-record-wave.js` (via `emit-story-dispatch-end.js`, Story #3900)
393
- after the Agent return is recorded in § 2c.
394
-
395
- Each Agent call's prompt must (1) name the Story + Epic ids, (2)
396
- instruct the child to invoke `helpers/epic-deliver-story <storyId>`
397
- (whose Step 4 defines the child's return shape), (3) remind the child
398
- of the **non-interactive contract** (no clarifying questions;
399
- transition to `agent::blocked` and exit if stuck), (4) tell the child to
400
- suppress per-Story chat relay and instead relay **one line per phase
401
- transition** (e.g. `Story #<id>: implementing → closing`) — the child's
402
- authoritative progress lands in the `story-run-progress` snapshot the
403
- `story-phase.js` CLI upserts, not in a verbatim body dump, (5) remind the
404
- child that its `story.heartbeat` liveness signal is emitted **off the token
405
- stream** by the PostToolUse hook (Epic #4476) — a throttled heartbeat lands as
406
- a free byproduct of every tool call, keyed off the active-Story env
407
- `story-init.js` exported — so it does **not** run `story-phase.js` per step
408
- just to heartbeat (a `story-phase.js` call at a genuine Story-level phase
409
- transition still renders the snapshot and stamps an operator-bearing
410
- heartbeat), and if it cannot make progress it must transition to
411
- `agent::blocked` rather than fall silent, and (6) pass the
412
- **docs digest path** — the `docsDigestPath` field from the
413
- `epic-deliver-prepare.js` envelope (§ Phase 1 main), which points at
414
- `temp/epic-<epicId>/docs-digest.md`. Instruct the child to read that
415
- digest instead of re-reading the full `project.docsContextFiles` set,
416
- and to pull individual docs files on demand (per
417
- [`.agents/instructions.md` § 3](../../instructions.md)). When
418
- `docsDigestPath` is null (the project configured no `docsContextFiles`),
419
- say so — the child then has no per-Story docs mandate. (7) pass the
420
- **checklist path** — the `checklistPath` field from that Story's entry in
421
- the `stories` dispatch hint (Story #4410), which points at
422
- `temp/epic-<epicId>/checklists/story-<storyId>.md`. Instruct the child to
423
- read that file (footprint-matched local-lens authoring checklists) and
424
- self-check its change against those concerns while writing. When
425
- `checklistPath` is null (the Story's predicted footprint matched no local
426
- lens), there is nothing to read. The pairing of
427
- `story.heartbeat` and `agent::blocked` is what lets the § 2d Idle
428
- Watchdog distinguish a working child from a dead one; a silent child
429
- with no recent heartbeat and no blocker label is the failure mode the
430
- watchdog is built to catch.
431
-
432
- There is **no per-child JSON return-parsing ceremony** for the parent
433
- to enforce. GitHub state is the contract: `epic-execute-record-wave.js`
434
- (§ 2c, mode B) treats each child's raw return text as a best-effort
435
- hint and reconciles any unparseable, empty, or missing return directly
436
- from the Story's live labels and comments.
437
-
438
- ### 2c. Record the Story outcomes
439
-
440
- As dispatched Stories return (record them as they land — you need not wait
441
- for the whole ready set), persist each Story's terminal status via
442
- `epic-execute-record-wave.js`. There is **no `--wave` flag and no
443
- `currentWave`** — the recorder splices each Story's status into the
444
- checkpoint's flat per-Story map and re-renders the rollup:
445
-
446
- ```bash
447
- # Mode A — host LLM already parsed each child return.
448
- node .agents/scripts/epic-execute-record-wave.js \
449
- --epic <epicId> --results @<file>|<inline-json>
450
-
451
- # Mode B — pipe the raw per-Story sub-agent return texts directly.
452
- node .agents/scripts/epic-execute-record-wave.js \
453
- --epic <epicId> --returns @<file>|<inline-json>
454
- # `<inline-json>` shape: [{ "storyId": <n>, "returnText": "<raw text>" }]
455
- ```
456
-
457
- **Mode B is the default path** — pipe the raw return texts through
458
- without inspecting them. The CLI reconciles parse failures from GitHub,
459
- records each Story's terminal status, emits one `story.dispatch.end` per
460
- recorded Story (closing the ledger pairing), re-renders
461
- `epic-run-progress`, and prints `{ status, nextAction, renderedBody, ... }`.
462
- Print `renderedBody` verbatim, then optionally append a short **Notable**
463
- section (0–5 bullets on newly blocked / failed / slow Stories, friction,
464
- elapsed-time surprises).
465
-
466
- > **Crash recovery.** A child that finished but was never recorded is
467
- > re-derived from its live label on the next `tick` and never
468
- > re-dispatched. See
469
- > [`deliver-epic-reference.md` § Crash recovery (record step)](deliver-epic-reference.md#crash-recovery-record-step)
470
- > for the manual re-record command.
471
-
472
- ### 2d. Loop on `nextAction`
473
-
474
- After `2c`, re-run `wave-tick.js`. Branch on the new envelope:
475
-
476
- - `dispatch` → repeat 2b/2c for the new ready set (the next beat's
477
- dependency-satisfied Stories), then re-tick.
478
- - `observe` → poll the Epic (children may still be in flight, or some
479
- are `agent::blocked`). If `blockedStories` is non-empty, post a
480
- friction comment, flip Epic to `agent::blocked`, park.
481
- - `halt` → the run is stuck: no Story is dispatchable, nothing is in
482
- flight, yet not every Story is done. `reason` distinguishes the two
483
- causes — `dependency-cycle` (the in-scope Stories form a `blocked by`
484
- cycle; `cycle` lists the offending Story ids) or
485
- `unsatisfiable-dependency` (a Story is gated on a dependency that can
486
- never satisfy). `stuckStories` names the Story id(s) that stranded the
487
- run. Post a friction comment quoting `reason` + `stuckStories`, flip the
488
- Epic to `agent::blocked`, and park for the operator. **Never** treat a
489
- `halt` as completion — proceeding to Phase 3 would silently drop the
490
- stuck Story.
491
- - `epic-complete` → **every** in-scope Story is done and nothing is in
492
- flight; proceed to Phase 3. (The tick returns `epic-complete` only when
493
- the done count equals the in-scope Story count — a stuck Story surfaces
494
- as `halt`, not a false `epic-complete`.)
495
-
496
- > **Idle Watchdog.** While any Story is in flight, re-tick every 30 minutes
497
- > with `wave-tick.js --epic <epicId> --check-idle 30` so a silent child
498
- > (crashed host, lost return) is surfaced as a `wave-stall` and
499
- > re-dispatched or blocked. The full cadence, staleness test (heartbeat +
500
- > deterministic branch-commit signal), stall envelope, and the "why 30 not
501
- > 10" rationale are in
502
- > [`deliver-epic-reference.md` § 2e. Idle Watchdog](deliver-epic-reference.md#2e-idle-watchdog).
503
- > Stop the cadence once the tick returns `epic-complete`.
504
-
505
- ---
506
-
507
- ## Phase 3 — Close-validation
508
-
509
- Run lint + test + ratchets against `epic/<epicId>` before opening the PR:
510
-
511
- ```bash
512
- node .agents/scripts/evidence-gate.js \
513
- --epic-id <epicId> --scope-id <epicId> --gate lint -- npm run lint
514
- node .agents/scripts/evidence-gate.js \
515
- --epic-id <epicId> --scope-id <epicId> --gate test -- npm test
516
- ```
517
-
518
- If either gate fails: STOP, fix on a hotfix branch, merge back to the
519
- Epic branch, restart this phase.
520
-
521
- ### 3.1 Refresh ratcheted baselines
522
-
523
- Inspect the scripts in `.husky/pre-push` (typecheck, lint, maintainability,
524
- design tokens, dependency audits, bundle-size budgets). Run each against
525
- the Epic branch; if any drifts, refresh and commit
526
- `chore(baselines): refresh <name> for Epic #<epicId>`.
527
-
528
- ---
529
-
530
- ## Phase 4 — Epic-close lens roster
531
-
532
- Skip when `--skip-epic-audit`. Otherwise auto-invoke
533
- [`helpers/epic-audit.md`](epic-audit.md) inline to **resolve** (not walk) the
534
- slim Epic-close lens roster. The helper runs
535
- [`epic-audit-prepare.js`](../../scripts/epic-audit-prepare.js) to ask the
536
- [`selectAudits`](../../scripts/lib/audit-suite/index.js) SDK which lenses fire
537
- at the `gate3` close gate, **unions in the model-judged risk-routed lenses**
538
- (Story #3889 — `epic-audit-prepare.js` reads the Epic's `planningRisk`
539
- envelope off the `epic-plan-state` checkpoint and maps each high-risk axis to
540
- its lens via `resolveAuditLenses`), then restricts that union to the tiers the
541
- Epic-close tier owns via
542
- [`selectEpicCloseLenses`](../../scripts/lib/orchestration/code-review.js): the
543
- envelope's **`epicCloseLenses`** field is the slim roster of **cumulative +
544
- global + risk-routed** lenses, with every **local-tier** change-set lens
545
- excluded (its concern is already verified shift-left at the write-time and
546
- Story-scope tiers). A high-risk Epic still auto-runs its risk-routed lenses
547
- even when the change set alone did not select them; a docs-only or
548
- already-shift-left-covered change set yields an empty roster.
549
-
550
- **The lens roster is not walked here.** Story #4412 folded the standalone
551
- Phase 4 lens walk into the Phase 5 code-review pass so the cumulative Epic diff
552
- is walked **once**. Phase 4 resolves `epicCloseLenses` (plus `depth`,
553
- `globalLenses`, `substitutionsPayload`) and hands it to Phase 5; there is no
554
- separate `audit-results` comment. Remediation of the lens findings happens in
555
- Phase 5 and is **tier-aware** (Story #4412): the Epic-close tier reads
556
- `delivery.epicAudit.autoFixSeverity` (default **`high`**) and routes only
557
- 🔴 Critical + 🟠 High lens findings into on-branch remediation while 🟡 Medium
558
- and 🟢 Suggestion findings graduate (🟡 Medium concerns are already remediated
559
- shift-left); setting `medium` opts back into routing 🔴/🟠/🟡.
560
-
561
- - **Selector reports `degraded: true`** — STOP. Propagate the
562
- `reason`/`detail`, post a friction comment, do not fall back to a
563
- full-roster audit.
564
- - **`epicCloseLenses` is empty** (docs-only change set, or every selected lens
565
- already covered shift-left, and no risk-routed lens) — there is no lens
566
- dimension for Phase 5 to walk; continue to Phase 5, which still runs its
567
- review pillars.
568
-
569
- ---
570
-
571
- ## Phase 5 — Code review (cumulative diff walked once)
572
-
573
- Skip when `--skip-code-review`. Otherwise resolve the **risk-derived review
574
- depth** for this Epic, then auto-invoke
575
- [`helpers/code-review.md`](code-review.md) inline (read-only audit)
576
- with the argument envelope `{ scope: 'epic', ticketId: <epicId>, baseRef:
577
- 'main', headRef: 'epic/<epicId>', depth: <reviewDepth> }`, threading the
578
- Phase 4 `epicCloseLenses` roster through. The pass walks the cumulative
579
- `main..epic/<epicId>` diff **once**: it executes the Epic-close lens roster as
580
- review dimensions (helper Step 1b) **and** the review pillars, folding both
581
- into a single aggregate. Findings persist as the unified `verification-results`
582
- structured comment on the Epic (the single findings surface — Story #4411
583
- unified the former `code-review` and `audit-results` contracts, and Story #4412
584
- folded the lens walk into this pass).
585
-
586
- The `depth` is the live epic-scope producer for Story #3876's review-depth
587
- lever (Story #3937). Resolve it from the Epic's judged risk envelope the same
588
- best-effort way Phase 4 routes audit lenses — via
589
- [`resolveReviewDepthForEpic`](../../scripts/lib/orchestration/code-review.js),
590
- which reads `planningRisk.overallLevel` off the Epic's `epic-plan-state`
591
- checkpoint and maps it: `high` → `deep`, `low` → `light`, everything else
592
- (including a missing/unparseable checkpoint, or an Epic that skipped
593
- `/plan`) → `standard`. The helper threads `depth` into `runCodeReview`,
594
- which forwards it to every provider's `runReview` input; the LLM-backed
595
- providers (codex, security-review, ultrareview) render it into the prompt they
596
- emit so a high-risk Epic gets a deeper adversarial pass and a low-risk one a
597
- lighter one. Depth is **input-only** — it never changes the findings envelope
598
- or the posted comment shape.
599
-
600
- Remediation in this pass is **tier-aware and split by finding class**
601
- (Story #4412). The **review-pillar** findings (Pillars 1–4) route off
602
- `delivery.codeReview.autoFixSeverity` (default **`medium`** — 🔴/🟠/🟡
603
- on-branch, Mediums batched per lens, 🟢 stays on the comment). The **Epic-close
604
- lens** findings (Step 1b) route off `delivery.epicAudit.autoFixSeverity`
605
- (default **`high`** — only 🔴/🟠 on-branch; 🟡 Medium + 🟢 graduate, because
606
- 🟡 Medium concerns were already remediated shift-left). Setting either key to
607
- its other value re-widens or narrows that class. Remediated findings are
608
- rendered under the single `verification-results` comment's `## Fixed on-branch`
609
- section so they never graduate to follow-up issues. The severity gate below is
610
- **unchanged** — it keys off the surviving (unfixed) findings.
611
-
612
- - **Any surviving 🔴 Critical Blocker** — STOP. Relay to the operator.
613
- - **Only 🟠/🟡/🟢 surviving** — log as non-blocking and continue.
614
-
615
- ---
616
-
617
- ## Phase 6 — Retro
618
-
619
- Skip when `--skip-retro`. Otherwise post the `epic-perf-report` via
620
- `node .agents/scripts/analyze-execution.js --epic <epicId>` (failure →
621
- warn and continue; the retro runner falls back). Then invoke the retro
622
- runner via its CLI wrapper:
623
-
624
- ```bash
625
- node .agents/scripts/retro-run.js --epic <epicId>
626
- ```
627
-
628
- [`retro-run.js`](../../scripts/retro-run.js) resolves the config/provider,
629
- constructs a lifecycle bus with a `LedgerWriter` (so the run's
630
- `retro.start` / `retro.end` boundaries land in
631
- `temp/epic-<epicId>/lifecycle.ndjson`), and calls `runRetro` — the
632
- canonical compose-and-post surface at
633
- [`.agents/scripts/lib/orchestration/retro-runner.js`](../../scripts/lib/orchestration/retro-runner.js).
634
- Propagate `--full-retro` to bypass the compact-path heuristic.
635
-
636
- Retro fires here (before the PR opens) so it stays in the operator's
637
- local session with full env access (env vars, credentials, MCP). After
638
- the GitHub upsert succeeds, the retro body is also **mirrored locally** to
639
- `temp/epic-<epicId>/retro.md` (path resolved via
640
- [`lib/config/temp-paths.js`](../../scripts/lib/config/temp-paths.js)'s
641
- `epicRetroMirrorPath`). GitHub remains the source of truth — a
642
- mirror-write failure only logs a warn and never fails the phase.
643
-
644
- **Auto-file routed proposals (Story #4418).** Between gathering the retro
645
- signals and composing the body, the runner files the retro's **actionable
646
- routed proposals** (the `framework` / `consumer` friction categories that
647
- recurred ≥ 2× or were force-flagged by an unresolved `agent::blocked`) as
648
- GitHub follow-up issues via the graduator pre-parsed-findings seam
649
- ([`retro-proposals-graduator.js`](../../scripts/lib/feedback-loop/retro-proposals-graduator.js)).
650
- Each filed issue carries `meta::<framework-gap|consumer-improvement>` +
651
- `friction::<category>` labels — the join key `/plan` Phase 0's
652
- prior-feedback fetcher reads back — and the rendered retro sections then
653
- list the **real filed issue numbers** instead of paste-ready `gh issue
654
- create` command stanzas. Filing is idempotent (a content-hash marker probe
655
- skips already-filed categories) and respects the graduator per-run filing
656
- cap. The beat runs behind `delivery.feedbackLoop.retroProposals` (default
657
- **ON**); set it to `false` to suppress auto-filing and fall back to the
658
- command stanzas. Filing never fails the phase — a filing error degrades to
659
- the command stanzas.
660
-
661
- ---
662
-
663
- ## Phase 6.5 — Post-wave integration gate (Epic #4131, F1/F4)
664
-
665
- This phase runs **after** the Phase 2 wave loop reports `epic-complete` and
666
- **before** the Phase 7 finalize emit opens the PR to `main`. It is the one
667
- **deliberately-global** gate — its evidence spans the whole product, not just
668
- the Epic's change set — so it catches the surface each Story shipped correctly
669
- in isolation yet the assembled product cannot reach (an unnavigable route, a
670
- broken persona journey).
671
-
672
- Skip when `--skip-integration-gate` (log the override; record a manual
673
- intervention per
674
- [`deliver-epic-reference.md` § Recording manual interventions](deliver-epic-reference.md#recording-manual-interventions)).
675
- The gate is otherwise **always evaluated** but a **silent no-op when
676
- unconfigured** (no `routeGlobs` / `navRegistry` / `journeySuite` in
677
- `.agentrc.json`).
678
-
679
- Sub-steps and hard-failure semantics:
680
-
681
- - **6.5a — Whole-product navigability**: run the `navigability` lens in
682
- whole-route mode over the `epic/<epicId>` tip. An **orphaned** route (no
683
- nav door for any entitled persona) or a dead nav href is a hard failure
684
- that **blocks finalize** and names the surface.
685
- - **6.5b — Consumer journey suite**: run
686
- `delivery.quality.navigability.journeySuite` over the tip. A failing
687
- persona journey is a hard failure that **blocks finalize** and names the
688
- broken journey.
689
- - **6.5c — `@pending` ≠ green for surface-adding Epics (F4)**: for a
690
- **surface-adding** Epic, an AC covered **only** by `@pending` scenarios is
691
- treated as unsatisfied and **fails the close gate** instead of passing
692
- green. This is **purely additive** and scoped to surface-adding Epics —
693
- refactor-only and docs-only Epics are **unaffected** and the existing
694
- `satisfied` / `missing` reconciliation is **not de-scoped** for any Epic.
695
-
696
- On any hard failure, post a friction structured comment naming the surface
697
- (route / nav-door identifier only — never route bodies or persona PII per
698
- `security-baseline.md`), flip the Epic to `agent::blocked`, and **do not**
699
- open the PR — the gate fails safe and loud. See
700
- [`deliver-epic-reference.md` § Phase 6.5](deliver-epic-reference.md#phase-65--post-wave-integration-gate-epic-4131-f1f4)
701
- for the full lens config, the surface-adding-signal derivation, the no-op
702
- degradation contract, and the fail-safe-and-loud security note.
703
-
704
- ---
705
-
706
- ## Phase 7 — Finalize (ready the PR / open PR to main)
707
-
708
- Before the close-tail emit, sync the Epic branch with `origin/main` so the
709
- PR opens with the latest base commits already integrated (a stale base
710
- stalls at branch-protection's `up-to-date branch` rule):
711
-
712
- ```bash
713
- git checkout epic/<epicId>
714
- node .agents/scripts/sync-branch-from-base.js \
715
- --branch epic/<epicId> --base main
716
- git push origin epic/<epicId>
717
- ```
718
-
719
- Then fire the close-tail emit:
720
-
721
- ```bash
722
- node .agents/scripts/lifecycle-emit.js --epic <epicId> --event epic.close.end
723
- ```
724
-
725
- `epic.close.end` drives the bus-owned `Finalizer` chain: acceptance-table
726
- reconciliation (throws and aborts finalize on a coverage gap, `waived` under
727
- `acceptance::n-a`), the PR-open/ready step (below), and the
728
- `epic-handoff` comment naming the PR URL. The chain emits `pr.created` →
729
- `epic.finalize.end` and **stops** — it never emits `epic.merge.ready` (the
730
- auto-merge arm is driven later from the Phase 8.5 gated watch path). The
731
- operator shells nothing beyond the sync and the single emit.
732
-
733
- **PR-open/ready is gated by `delivery.ci.earlyPr` (Story #4359).** Resolve
734
- the flag through the [`getCiDelivery`](../../scripts/lib/config/ci.js)
735
- accessor (default `true`); do not read `delivery.ci.earlyPr` directly.
736
-
737
- - **`earlyPr` on (default)** — the Epic PR already exists as a draft (Phase
738
- 2 opened it at wave 1). Finalize **locates** the existing PR and flips it
739
- ready-for-review via
740
- [`markPrReady`](../../scripts/lib/orchestration/finalize/open-or-locate-pr.js)
741
- rather than creating a PR. `gh pr ready` on an already-ready PR is a
742
- no-op, so a re-run is idempotent.
743
- - **`earlyPr` off** — no draft was opened at wave 1; finalize opens the PR
744
- now via `openOrLocatePr` (no `draft`), exactly as the pre-Story timing.
745
-
746
- In both modes the PR title/body contract (`feat: Epic #<epicId>` /
747
- `Closes #<epicId>`) is identical.
748
-
749
- **Drain the bookkeeping outbox (Epic #4476 M5).** When this run was invoked
750
- with `--yes` (headless), the mechanical bookkeeping — non-urgent
751
- structured-comment upserts and intermediate `agent::*` label flips — was
752
- **buffered to a local per-Epic outbox** instead of posting live per
753
- transition (see the box below). Reconcile it to GitHub once, now, after the PR
754
- is open:
755
-
756
- ```bash
757
- node .agents/scripts/bookkeeping-reconcile.js --epic <epicId>
758
- ```
759
-
760
- This drains `temp/epic-<epicId>/bookkeeping-outbox.ndjson` (FIFO,
761
- idempotent) so GitHub is the source of truth at rest. It exits non-zero and
762
- **retains** the outbox if any op fails (crash-recovery: a later reconcile
763
- re-drains the remainder). Attended runs buffered nothing, so this is a no-op.
764
-
765
- > **Headless buffering, not silence (§1.H / §1.J).** In `--yes` mode the
766
- > comment/label CLIs accept `--buffer --epic <epicId>` to enqueue a mutation
767
- > instead of a live round-trip
768
- > ([`post-structured-comment.js`](../../scripts/post-structured-comment.js),
769
- > [`update-ticket-state.js`](../../scripts/update-ticket-state.js)). The
770
- > `agent::blocked` HITL gate is **never** buffered — a genuine blocker flips
771
- > the label live and immediately, exactly as before, so the operator can see
772
- > and resume it. `agent::done` is also never buffered (its cascade runs live).
773
- > Attended runs pass no `--buffer` and behave byte-for-byte as they always
774
- > have.
775
-
776
- See
777
- [`deliver-epic-reference.md` § Phase 7 — Finalize](deliver-epic-reference.md#phase-7--finalize-close-tail-listener-chain)
778
- for the branch-sync outcome table (conflict / fetch-failed recovery) and the
779
- full three-step listener contract (why finalize must not emit
780
- `epic.merge.ready`, the merge-lockout lint rule, the no planning-ticket close
781
- sweep).
782
-
783
- ---
784
-
785
- ## Phase 8 — Watch-and-iterate until CI is green
786
-
787
- The host LLM owns the green-bar loop until the operator merges. Use
788
- `pr-watch-with-update.js` — the **single CI-watch mechanism** shared with
789
- the standalone single-Story Step 4 path (Story #4358). It polls the PR's
790
- required checks to a terminal state and additionally auto-recovers from
791
- `mergeStateStatus: BEHIND` by calling `gh pr update-branch` once every
792
- required check is green (branch-protection rules requiring "up to date
793
- before merging" otherwise park the PR until the operator clicks **Update
794
- branch** manually):
795
-
796
- ```bash
797
- node <agentRoot>/scripts/pr-watch-with-update.js --pr <prNumber> --epic <epicId>
798
- ```
799
-
800
- `<agentRoot>` resolves from `project.paths.agentRoot` (default `.agents`).
801
- Poll cadence and caps come from `delivery.ci.watch.*`
802
- (`pollIntervalMs`, `maxPolls`, `maxResumes`); pass `--poll-interval-ms`,
803
- `--max-polls`, `--max-resumes`, or `--max-updates` to override for one
804
- run. Passing `--epic <epicId>` scopes the red-path failure digest to
805
- `temp/epic-<epicId>-ci-digest.{json,md}`.
806
-
807
- **Three-way exit (slow-vs-failed semantics):**
808
-
809
- - **Exit 0** — every required check is green → proceed to Phase 8.5.
810
- - **Exit 1** — a required check genuinely failed (red). The CLI writes
811
- `temp/epic-<epicId>-ci-digest.{json,md}` (failing check, run id,
812
- `gh run view --log-failed` tail, coarse classification) and surfaces
813
- the fix-loop handoff. Remediate on `epic/<epicId>` and re-run the
814
- helper (auto-merge stays armed across retries). If the same failure
815
- class recurs, hand the convergence off to a self-paced host loop
816
- (`/loop`) that re-runs the failing check and applies the smallest fix
817
- until it exits green.
818
- - **Exit 2** — **still-running** (slow CI, not red): the poll cap fired
819
- with checks still pending and the watcher exhausted its
820
- `delivery.ci.watch.maxResumes` re-arm budget with nothing red. This is
821
- **never** a failure and **never** `timed_out`. Hand the wait off to the
822
- host's interval loop rather than blocking the delivery turn: `/loop 5m`
823
- polling `gh pr checks` until the checks settle.
824
-
825
- > **Triage authority.** How to classify and remediate a red (or repeatedly
826
- > slow) check — the root-cause-only decision tree for infra/transient and
827
- > flaky failures (reproduce → check `main` → bisect env vs code → fix in-scope
828
- > or file a `meta::framework-gap` issue), the never-rerun / never-quarantine
829
- > prohibitions, and the escalation criteria (three-strikes, the 30-minute
830
- > wall-clock timebox, and the clearly-environmental fast path) — is defined
831
- > once in [`.agents/rules/ci-remediation.md`](../../rules/ci-remediation.md).
832
- > Read it before remediating.
833
- >
834
- > **Remediation + hard prohibitions.** For the per-check fix table (lint,
835
- > baseline drift, test, coverage), the three-strikes halt rule, and the
836
- > never-merge / never-force-push / never-dodge prohibitions, see
837
- > [`deliver-epic-reference.md` § Phase 8 — Watch-and-iterate remediation](deliver-epic-reference.md#phase-8--watch-and-iterate-remediation).
838
-
839
- ---
840
-
841
- ## Phase 8.5 — Auto-merge gate
842
-
843
- After Phase 8 exits 0, evaluate the auto-merge predicate by emitting
844
- `epic.automerge.start`. When this `/deliver` run was invoked with `--yes`,
845
- add `--headless true` so the downstream `MergeWatcher` engages the
846
- must-land terminal step (Story #4427, § Arguments above); omit the flag
847
- (or pass `--headless false`) for an attended run:
848
-
849
- ```bash
850
- node .agents/scripts/lifecycle-emit.js --epic <epicId> \
851
- --event epic.automerge.start --pr-url <prUrl> [--headless true]
852
- ```
853
-
854
- **Must-land terminal step (headless only).** `MergeWatcher` polls
855
- `epic.merge.armed` to confirmation as usual. If its poll budget is
856
- exhausted, a headless (`--headless true`) run does not exit silently —
857
- it classifies the block (`classifyMergeBlock`, the shared classifier
858
- from Story #4426) and applies one bounded retry before giving up:
859
-
860
- - `checks-pending-timeout` (required checks still progressing) — extend
861
- the watch budget once and keep polling.
862
- - `api-race-other` (no definitive block signal) — re-arm once by
863
- re-emitting `epic.merge.ready` on the bus (never a direct `gh pr merge`
864
- call — `AutomergeArmer` remains the sole authorized call site).
865
- - `branch-protection-human-required`, or both bounded retries already
866
- spent — terminal: emit `merge.unlanded` (`scope: "epic"`, carrying the
867
- block class) and fall through to the existing single `epic.blocked`
868
- emit — one blocked path, never a duplicate `agent::blocked` transition.
869
-
870
- Attended runs (no `--headless` flag) keep today's exact behavior: budget
871
- exhaustion emits `epic.blocked` immediately, with no classification, no
872
- retry, and no `merge.unlanded`.
873
-
874
- `AutomergePredicate` first runs a **live `gh pr checks --required` probe**
875
- (Story #4361): green required CI is the arming signal, so if any required
876
- check is red, pending, or the probe is unreadable it emits
877
- `epic.merge.blocked` immediately — even if the Phase 8 watch was interrupted
878
- before it observed green (closing the Story #3901 interrupted-watch hole).
879
- When the probe is green it evaluates the structured-signal verdict under the
880
- `delivery.ci.autoMerge` policy (default `"trust-ci"`; see
881
- [`configuration.md`](../../docs/configuration.md)):
882
-
883
- - **`trust-ci`** (default) — the ONLY structured conditions that block
884
- arming are an unresolved 🔴 critical (red) code-review finding or an
885
- `agent::blocked` state (a story-level blocker recorded in run-state, a
886
- non-done story, or a missing run-state checkpoint). Manual interventions,
887
- 🟠 warning-level findings, and a non-clean retro are **recorded for audit**
888
- (surfaced on the classification log and the arm-reason) but no longer block.
889
- - **`strict`** — restores the prior clean-sprint predicate exactly: empty
890
- manual-interventions, every story done, no story blocked, `0` 🔴 + `0` 🟠
891
- review findings, and the retro's `automerge-verdict` trailer reporting
892
- `cleanSprint: true`. Any dirty signal blocks.
893
-
894
- On an arming decision the predicate emits `epic.merge.ready`; the downstream
895
- `AutomergeArmer` (the sole authorized `gh pr merge` call site) fires
896
- `gh pr merge --auto --squash --delete-branch`. Otherwise the predicate emits
897
- `epic.merge.blocked` with the disqualifying reasons and exits without merging
898
- — the operator merges manually.
899
-
900
- **Blocked-path output (operator merges the button).** When arming is
901
- declined, `epic.merge.armed` never fires inside this run, so Phase 9 does not
902
- reap automatically. Surface the exact one-liner the operator runs **after**
903
- they merge the PR by hand so local refs are reaped and `main` is
904
- fast-forwarded (the idempotent-resume path below runs this automatically on
905
- the next `/deliver <epicId>`):
906
-
907
- ```bash
908
- node .agents/scripts/lifecycle-emit.js --epic <epicId> \
909
- --event epic.merge.armed --pr-url <prUrl>
910
- ```
911
-
912
- Close the phase wrapper by emitting `epic.automerge.end` (records the arm
913
- outcome on the ledger; `merged: true` once GitHub completes the squash,
914
- `merged: false` with a reason otherwise):
915
-
916
- ```bash
917
- node .agents/scripts/lifecycle-emit.js --epic <epicId> \
918
- --event epic.automerge.end --pr-url <prUrl> --merged <true|false>
919
- ```
920
-
921
- > **Predicate wiring + manual-intervention recording.** For the full
922
- > predicate contract (the trailer read, the `delivery.ci.autoMerge` policy
923
- > split, and the Story #4361 live `gh pr checks --required` probe that
924
- > replaced the former CI-freshness skip) and the
925
- > `epic-deliver-note-intervention.js` command + its trigger list, see
926
- > [`deliver-epic-reference.md` § Phase 8.5 — Auto-merge predicate detail](deliver-epic-reference.md#phase-85--auto-merge-predicate-detail).
927
-
928
- ---
929
-
930
- ## Phase 9 — Local branch cleanup
931
-
932
- Phase 9 runs **automatically** inside the lifecycle bus once auto-merge
933
- arms: the `BranchCleaner` listener subscribes to `epic.cleanup.start`
934
- and reaps local refs (the `epic/<id>` branch, every `story-<id>` in the
935
- checkpoint, attached worktrees, and stale tracking refs) before `Cleaner`
936
- archives the `temp/epic-<id>/` tree. No operator step is required on the
937
- auto-merge path.
938
-
939
- For out-of-band cleanup re-entry (resume after a crash, or operator
940
- override), fire `epic.merge.armed`:
941
-
942
- ```bash
943
- node .agents/scripts/lifecycle-emit.js --epic <epicId> \
944
- --event epic.merge.armed --pr-url <prUrl>
945
- ```
946
-
947
- > **Reap order + operator-merges fallback.** For the full in-process reap
948
- > order, the per-branch classification log, and the manual reap sequence
949
- > when Phase 8.5 fell back to the operator-merges-button path (auto-merge
950
- > declined, `epic.merge.armed` never fired), see
951
- > [`deliver-epic-reference.md` § Phase 9 — Local branch cleanup detail](deliver-epic-reference.md#phase-9--local-branch-cleanup-detail).
952
-
953
- ---
954
-
955
- ## Idempotence and resume
956
-
957
- Re-runs pick up at the next undispatched wave (in-flight Stories finish
958
- via `helpers/epic-deliver-story`'s own checkpointing). The PR from Phase 7 is
959
- updated in place on subsequent runs. The authoritative live view is
960
- the `epic-run-progress` structured comment.
961
-
962
- **Resume auto-arm for a merged-but-uncleaned Epic.** When `/deliver` resumes
963
- against an Epic whose PR already merged (operator merged the button in a prior
964
- session) but whose local `epic/<id>` / `story-<id>` refs still linger, the
965
- resume path detects the merged-but-uncleaned state
966
- (`detectMergedUncleanedEpic` in
967
- [`epic-cleanup.js`](../../scripts/lib/orchestration/epic-cleanup.js)) and fires
968
- `epic.merge.armed` automatically so Phase 9 reaps — no manual command. The
969
- detection is idempotent: an already-reaped Epic (no local refs) is a clean
970
- no-op, and an unmerged Epic never arms. It resolves the merged PR's URL for the
971
- required `epic.merge.armed` payload and fails closed (does **not** arm) on any
972
- indeterminate `gh` probe. The one-liner under Phase 8.5 / Phase 9 is the manual
973
- equivalent for the case where the operator does not re-run `/deliver`.
974
-
975
- ---
976
-
977
- ## Constraints
978
-
979
- - **Never** merge `epic/<epicId>` to `main` outside Phase 8.5.
980
- - **Never** dispatch more than the global `concurrencyCap` allows;
981
- concurrency lives inside the ready-set fan-out.
982
- - **Never** flip Story-level labels from this skill; **never** invoke
983
- `helpers/epic-deliver-story` yourself (children run it via Agent fan-out,
984
- even for single-Story waves); **never** spawn a subprocess for dispatch.
985
- - **Always** checkpoint via `epic-deliver-prepare.js` /
986
- `epic-execute-record-wave.js`; never write run state elsewhere.
987
- - **Always** post a friction structured comment before a non-`complete`
988
- outcome.
989
- - **Always** auto-invoke the epic-audit, code-review, and retro helpers
990
- (Phases 4–6) when their artefacts aren't already present.
991
- - **Always** run the Phase 6.5 integration gate after the wave loop
992
- reports `epic-complete` and before Phase 7 finalize (unless
993
- `--skip-integration-gate`); **never** open the PR while the gate
994
- reports a hard failure (orphaned surface, dead nav href, broken
995
- journey, or a surface-adding Epic with only `@pending` AC coverage).
996
- - **Always** drive Phase 8 to green CI before returning control — the
997
- host LLM owns the loop until the PR is mergeable or the Epic is
998
- parked at `agent::blocked`.