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,264 +0,0 @@
1
- // .agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js
2
- /**
3
- * BranchCleaner — lifecycle listener that owns post-merge **branch** reap
4
- * for `/deliver`. Story #2398 (companion to Cleaner, which owns the
5
- * temp-tree archival half of end-of-Epic cleanup).
6
- *
7
- * Subscribes to:
8
- * - `epic.cleanup.start` → and ONLY this event.
9
- *
10
- * Why `epic.cleanup.start` and not `epic.merge.armed`:
11
- * Cleaner subscribes to `epic.merge.armed` and is the source of the
12
- * `epic.cleanup.start → epic.cleanup.end → epic.complete` terminal
13
- * sequence. The Bus runs listeners awaited and in registration order,
14
- * so a BranchCleaner registered on `epic.cleanup.start` BEFORE Cleaner
15
- * registers on `epic.merge.armed` will run synchronously inside
16
- * Cleaner's emit chain, between the start and end events, and crucially
17
- * BEFORE Cleaner's archive rename moves `temp/epic-<id>/` to
18
- * `temp/archive/epic-<id>-<ts>/`. The state checkpoint that we read to
19
- * enumerate Story branches lives on the Epic Issue (as the
20
- * `epic-run-state` structured comment), not under `temp/`, so the
21
- * ordering above is for symmetry with the existing Cleaner contract
22
- * — both halves of cleanup observe the same temp tree as it exists at
23
- * `epic.cleanup.start`.
24
- *
25
- * Side effects executed inside `handle()`:
26
- * 1. Read the `epic-run-state` checkpoint via the injected
27
- * `checkpointer`. Skip with classification `no-state` when the
28
- * checkpoint is missing or carries no Stories (a brand-new run
29
- * that armed without ever finalising a wave should never reach
30
- * `epic.cleanup.start`, but the guard keeps this listener
31
- * idempotent under replay).
32
- * 2. Call `reapEpicBranches()` from `lib/orchestration/epic-cleanup.js`,
33
- * which:
34
- * - switches the main checkout off `epic/<id>` to the baseBranch
35
- * when needed (so `git branch -D epic/<id>` isn't refused);
36
- * - removes attached worktrees with the Windows file-lock fallback
37
- * (worktree-remove → worktree-remove --force → fs.rm + prune);
38
- * - deletes every `story-<id>` branch listed in the checkpoint plus
39
- * the `epic/<id>` branch itself;
40
- * - runs `git remote prune` to drop stale `<remote>/...` tracking
41
- * refs left behind by `gh pr merge --delete-branch`;
42
- * - deletes the `wt-branch` scratch ref left by `story-close.js`'s
43
- * internal merge worktree when it is no longer checked out;
44
- * - fast-forwards the base branch to `<remote>/<baseBranch>` after the
45
- * confirmed merge so the local checkout converges to origin with no
46
- * manual `git pull` (skipped when the epic branch is kept for an
47
- * open PR).
48
- * 3. Record one classification entry per invocation (`reaped`,
49
- * `no-state`, `failed`, or `skipped-duplicate`) so failures surface
50
- * in the lifecycle ledger alongside Cleaner's archival outcome.
51
- *
52
- * Idempotency contract: per-instance `Set<string>` of `${event}:${seqId}`
53
- * keys — repeat `(event, seqId)` invocation short-circuits and classifies
54
- * `skipped-duplicate`. Mirrors Cleaner's bus-level replay defence.
55
- *
56
- * Side-effect firewall: the listener mutates **local git state** (branch
57
- * refs, worktree paths, remote tracking refs) and nothing else. It does
58
- * NOT touch the temp tree, the ticketing provider (the checkpointer
59
- * `read()` is the only ticketing call and is read-only), or label state.
60
- * Label transitions stay with LabelTransitioner on `epic.complete`.
61
- *
62
- * Production failure mode: `reapEpicBranches()` aggregates per-branch
63
- * failures into the result envelope rather than throwing — a single
64
- * branch that won't reap (e.g. because the operator stashed unmerged
65
- * work onto it) must not block the rest of cleanup. The listener
66
- * therefore records `failed` as a classification with the failure
67
- * summary; orchestration callers that want hard-stop semantics can
68
- * inspect the classifications. Programmer errors in the listener's own
69
- * inputs (missing bus / non-numeric epicId / missing checkpointer)
70
- * throw at construction time per
71
- * `.agents/rules/orchestration-error-handling.md`.
72
- */
73
-
74
- import { rmSync as defaultRmSync } from 'node:fs';
75
-
76
- import { gitSpawn as defaultGitSpawn } from '../../../git-utils.js';
77
- import { reapEpicBranches } from '../../epic-cleanup.js';
78
-
79
- /**
80
- * BranchCleaner listener.
81
- */
82
- export class BranchCleaner {
83
- /**
84
- * @param {object} opts
85
- * @param {object} opts.bus
86
- * @param {number} opts.epicId
87
- * @param {{ read: () => Promise<object|null> }} opts.checkpointer
88
- * Object exposing `read()` returning the `epic-run-state` checkpoint
89
- * shape (epicId + waves[].stories[].id). Production passes the
90
- * stateless `epic-run-state-store` module bound to `{provider, epicId}`;
91
- * tests pass a fake.
92
- * @param {string} opts.cwd - Absolute path to the **main** checkout
93
- * (not a worktree). `reapEpicBranches()` runs `git checkout`,
94
- * `git branch -D`, and `git remote prune` against this directory.
95
- * @param {string} [opts.baseBranch='main'] - Branch to switch the main
96
- * checkout to before reaping `epic/<id>`.
97
- * @param {string} [opts.remote='origin'] - Remote to prune.
98
- * @param {Function} [opts.gitSpawn] - Injectable git spawner for tests.
99
- * @param {Function} [opts.rmSyncFn] - Injectable filesystem remove for
100
- * the worktree Windows-lock fallback.
101
- * @param {Function} [opts.spawnFn] - Injectable process spawner forwarded
102
- * to `reapEpicBranches` for the Story #3367 open-PR guard probe
103
- * (`gh pr list --head epic/<id> --state open`). Defaults to the real
104
- * `spawnSync` inside `epic-cleanup.js`; tests inject a stub.
105
- * @param {{ info?: Function, warn?: Function, debug?: Function }} [opts.logger]
106
- */
107
- constructor(opts = {}) {
108
- if (
109
- !opts.bus ||
110
- typeof opts.bus.on !== 'function' ||
111
- typeof opts.bus.emit !== 'function'
112
- ) {
113
- throw new TypeError('BranchCleaner requires a bus with on() and emit()');
114
- }
115
- if (!Number.isInteger(opts.epicId) || opts.epicId < 1) {
116
- throw new TypeError('BranchCleaner requires a numeric epicId');
117
- }
118
- if (!opts.checkpointer || typeof opts.checkpointer.read !== 'function') {
119
- throw new TypeError(
120
- 'BranchCleaner requires a checkpointer exposing read()',
121
- );
122
- }
123
- if (typeof opts.cwd !== 'string' || opts.cwd.length === 0) {
124
- throw new TypeError('BranchCleaner requires a non-empty cwd string');
125
- }
126
- this.bus = opts.bus;
127
- this.epicId = opts.epicId;
128
- this.checkpointer = opts.checkpointer;
129
- this.cwd = opts.cwd;
130
- this.baseBranch = opts.baseBranch ?? 'main';
131
- this.remote = opts.remote ?? 'origin';
132
- this.gitSpawn = opts.gitSpawn ?? defaultGitSpawn;
133
- this.rmSyncFn = opts.rmSyncFn ?? defaultRmSync;
134
- // Story #3367 — forwarded to reapEpicBranches' open-PR guard probe.
135
- // `undefined` lets epic-cleanup.js fall back to its real `spawnSync`.
136
- this.spawnFn = opts.spawnFn;
137
- this.logger = opts.logger ?? console;
138
- /** @type {Set<string>} `${event}:${seqId}` idempotency cache. */
139
- this._seen = new Set();
140
- /**
141
- * Classification log — every `epic.cleanup.start` observed lands
142
- * here with the outcome (`reaped`, `no-state`, `failed`,
143
- * `skipped-duplicate`). Mirrors Cleaner's "no silent skip" surface.
144
- */
145
- this.classifications = [];
146
- // Frozen tuple — BranchCleaner subscribes to EXACTLY one event.
147
- this.events = Object.freeze(['epic.cleanup.start']);
148
- }
149
-
150
- register() {
151
- return this.events.map((event) =>
152
- this.bus.on(event, async (ctx) => this.handle(ctx)),
153
- );
154
- }
155
-
156
- async handle({ event, seqId }) {
157
- const key = `${event}:${seqId}`;
158
- if (this._seen.has(key)) {
159
- this.classifications.push({
160
- event,
161
- seqId,
162
- outcome: 'skipped-duplicate',
163
- });
164
- this.logger.debug?.(`[BranchCleaner] skip duplicate ${key} (idempotent)`);
165
- return;
166
- }
167
- this._seen.add(key);
168
-
169
- let state;
170
- try {
171
- state = await this.checkpointer.read();
172
- } catch (err) {
173
- this.classifications.push({
174
- event,
175
- seqId,
176
- outcome: 'failed',
177
- reason: `checkpoint-read-failed:${err?.message ?? err}`,
178
- });
179
- this.logger.warn?.(
180
- `[BranchCleaner] checkpoint read failed: ${err?.message ?? err}`,
181
- );
182
- return;
183
- }
184
-
185
- if (!state || !Number.isInteger(state.epicId) || state.epicId < 1) {
186
- this.classifications.push({
187
- event,
188
- seqId,
189
- outcome: 'no-state',
190
- reason: 'checkpoint-absent-or-empty',
191
- });
192
- this.logger.info?.(
193
- '[BranchCleaner] no epic-run-state checkpoint; nothing to reap.',
194
- );
195
- return;
196
- }
197
-
198
- const result = reapEpicBranches({
199
- state,
200
- cwd: this.cwd,
201
- gitSpawn: this.gitSpawn,
202
- rmSyncFn: this.rmSyncFn,
203
- baseBranch: this.baseBranch,
204
- remote: this.remote,
205
- spawnFn: this.spawnFn,
206
- logger: this.logger,
207
- });
208
-
209
- const summary = summarizeReap(result);
210
- if (result.ok) {
211
- this.classifications.push({
212
- event,
213
- seqId,
214
- outcome: 'reaped',
215
- epicId: result.epicId,
216
- ...summary,
217
- });
218
- this.logger.info?.(
219
- `[BranchCleaner] reaped ${summary.branchesDeleted} branch(es) + ${summary.worktreesRemoved} worktree(s) for epic/${result.epicId}`,
220
- );
221
- } else {
222
- this.classifications.push({
223
- event,
224
- seqId,
225
- outcome: 'failed',
226
- reason: 'reap-failures',
227
- epicId: result.epicId,
228
- ...summary,
229
- failures: result.failures.map((f) => ({
230
- branch: f.branch,
231
- stderr: f.stderr ?? null,
232
- })),
233
- });
234
- this.logger.warn?.(
235
- `[BranchCleaner] ${result.failures.length} branch(es) failed to reap for epic/${result.epicId}`,
236
- );
237
- }
238
- }
239
-
240
- reset() {
241
- this._seen.clear();
242
- this.classifications = [];
243
- }
244
- }
245
-
246
- /**
247
- * Pure: condense a `reapEpicBranches()` result into the counts that the
248
- * classification log carries. Exported for tests.
249
- *
250
- * @param {{ reaped: Array<object>, pruned: { pruned: string[] }|null, wtBranch: { deleted: boolean }|null, fastForward: { applied: boolean }|null }} result
251
- * @returns {{ branchesDeleted: number, worktreesRemoved: number, tracksPruned: number, wtBranchDeleted: boolean, fastForwarded: boolean }}
252
- */
253
- export function summarizeReap(result) {
254
- const reaped = Array.isArray(result?.reaped) ? result.reaped : [];
255
- return {
256
- branchesDeleted: reaped.filter((r) => r.branchDeleted).length,
257
- worktreesRemoved: reaped.filter(
258
- (r) => r.worktreeReaped && r.method !== 'no-worktree',
259
- ).length,
260
- tracksPruned: result?.pruned?.pruned?.length ?? 0,
261
- wtBranchDeleted: result?.wtBranch?.deleted === true,
262
- fastForwarded: result?.fastForward?.applied === true,
263
- };
264
- }
@@ -1,284 +0,0 @@
1
- // .agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js
2
- /**
3
- * CheckpointPointerWriter — lifecycle listener that maintains a
4
- * minimal pointer file at `temp/epic-<id>/checkpoint.json` after every
5
- * `*.end` lifecycle event (Story #2266 / Task #2268, Epic #2172).
6
- *
7
- * The writer replaces the legacy `epic-runner/checkpointer.js`
8
- * structured-comment checkpointer with a ledger-driven pointer: the
9
- * NDJSON ledger (`lifecycle.ndjson`) is the canonical run history, and
10
- * the pointer file is a tiny `{ lastCompletedSeqId, phase }` snapshot
11
- * the runner reads at resume time to seek the right offset into the
12
- * ledger.
13
- *
14
- * Subscription set: **every event whose name ends in `.end`**. The
15
- * frozen `EVENTS` tuple is computed from the lifecycle schema directory
16
- * via the helper export so the registration cannot drift from the
17
- * taxonomy without updating the schema set.
18
- *
19
- * Self-emit contract: after the pointer write succeeds the listener
20
- * emits `checkpoint.written` exactly once per observed `*.end`. The
21
- * self-emit is guarded by the per-instance `(event, seqId)` idempotency
22
- * set so the bus's resume window (re-emitting an event whose `emitted`
23
- * line landed but whose `completed` did not) cannot produce a duplicate
24
- * `checkpoint.written`. The seqId set persists for the lifetime of the
25
- * listener; cross-process restart relies on the on-disk pointer's
26
- * monotonicity (the second invocation observes `lastCompletedSeqId >=
27
- * payload.seqId` and short-circuits).
28
- *
29
- * Side-effect firewall: filesystem write + exactly one `bus.emit`. No
30
- * provider calls, no GitHub IO, no runner-state mutation.
31
- *
32
- * Registration order: the runner factory registers this listener
33
- * EARLY — before downstream listeners that may fail — so the pointer
34
- * file always advances even if a later listener throws on the SAME
35
- * `*.end`. The throw still flows through the bus's `onFailed` hook
36
- * (LedgerWriter records a `failed` line) but the pointer reflects the
37
- * last `*.end` that reached this listener, which is what the resume
38
- * coordinator needs to skip past completed events on the next start.
39
- */
40
-
41
- import { mkdirSync, writeFileSync } from 'node:fs';
42
- import path from 'node:path';
43
-
44
- /**
45
- * The pointer file name under `temp/epic-<id>/`. Stable and grep-able
46
- * so future tooling can locate the file without re-deriving the path.
47
- */
48
- export const POINTER_FILENAME = 'checkpoint.json';
49
-
50
- /**
51
- * The self-emitted lifecycle event name. Matches the schema id at
52
- * `.agents/schemas/lifecycle/checkpoint.written.schema.json`.
53
- */
54
- export const CHECKPOINT_WRITTEN_EVENT = 'checkpoint.written';
55
-
56
- /**
57
- * The frozen list of `*.end` events the writer subscribes to. Sourced
58
- * from the lifecycle taxonomy (`.agents/schemas/lifecycle/*.end.schema.json`).
59
- *
60
- * Listed explicitly rather than discovered at runtime so:
61
- * (a) the registration set is a code-visible contract — adding a new
62
- * `*.end` event to the schema set forces a code change here,
63
- * which is the seam reviewers grep for;
64
- * (b) construction stays synchronous (no readdir + parse) and the
65
- * constructor remains safe to call inside the runner factory.
66
- *
67
- * If a new `*.end` event is added to the schema directory, append it
68
- * here. The `checkpoint.written` event itself is intentionally NOT in
69
- * this list — the writer's own self-emit must not retrigger the writer
70
- * (that would loop), and `checkpoint.written` is not an `*.end` event
71
- * by naming convention.
72
- */
73
- export const SUBSCRIBED_END_EVENTS = Object.freeze([
74
- 'close-validate.end',
75
- 'code-review.end',
76
- 'epic.automerge.end',
77
- 'epic.cleanup.end',
78
- 'epic.close.end',
79
- 'epic.finalize.end',
80
- 'epic.plan.end',
81
- 'epic.snapshot.end',
82
- 'epic.watch.end',
83
- 'retro.end',
84
- // Epic #4475 (M4-A) — single-delivery slice boundary. A completed slice is
85
- // a resume checkpoint for the one long guarded session (the analogue of
86
- // story.dispatch.end for fan-out). Subscribed now so the pointer updates
87
- // once the M4-B executor emits slice.end through the bus; inert until then
88
- // (nothing emits it in M4-A).
89
- 'slice.end',
90
- 'story.dispatch.end',
91
- ]);
92
-
93
- /**
94
- * Resolve the pointer-file path for a given Epic. Exported so tests
95
- * can target the same file without re-deriving the layout.
96
- */
97
- export function resolvePointerPath({ tempRoot, epicId }) {
98
- if (typeof tempRoot !== 'string' || tempRoot.length === 0) {
99
- throw new TypeError(
100
- 'resolvePointerPath: tempRoot must be a non-empty string',
101
- );
102
- }
103
- if (!Number.isInteger(epicId) || epicId < 1) {
104
- throw new TypeError(
105
- 'resolvePointerPath: epicId must be a positive integer',
106
- );
107
- }
108
- return path.join(tempRoot, `epic-${epicId}`, POINTER_FILENAME);
109
- }
110
-
111
- /**
112
- * Build the pointer payload. Pulled out so tests can assert the exact
113
- * on-disk shape without parsing JSON every time.
114
- */
115
- export function buildPointerPayload({ lastCompletedSeqId, phase }) {
116
- return {
117
- lastCompletedSeqId,
118
- phase,
119
- };
120
- }
121
-
122
- /**
123
- * CheckpointPointerWriter listener.
124
- */
125
- export class CheckpointPointerWriter {
126
- /**
127
- * @param {object} opts
128
- * @param {object} opts.bus Lifecycle bus exposing `on()` + `emit()`.
129
- * @param {number} opts.epicId Epic ticket id.
130
- * @param {string} opts.tempRoot Absolute or repo-relative path; the
131
- * listener resolves `<tempRoot>/epic-<id>/checkpoint.json`.
132
- * @param {typeof writeFileSync} [opts.writeFn] Injectable writer for
133
- * tests.
134
- * @param {typeof mkdirSync} [opts.mkdirFn] Injectable directory
135
- * creator for tests.
136
- * @param {{ info?: Function, warn?: Function, debug?: Function }} [opts.logger]
137
- */
138
- constructor(opts = {}) {
139
- if (
140
- !opts.bus ||
141
- typeof opts.bus.on !== 'function' ||
142
- typeof opts.bus.emit !== 'function'
143
- ) {
144
- throw new TypeError(
145
- 'CheckpointPointerWriter requires a bus with on() and emit()',
146
- );
147
- }
148
- if (!Number.isInteger(opts.epicId) || opts.epicId < 1) {
149
- throw new TypeError('CheckpointPointerWriter requires a numeric epicId');
150
- }
151
- if (typeof opts.tempRoot !== 'string' || opts.tempRoot.length === 0) {
152
- throw new TypeError(
153
- 'CheckpointPointerWriter requires a non-empty tempRoot string',
154
- );
155
- }
156
- this.bus = opts.bus;
157
- this.epicId = opts.epicId;
158
- this.tempRoot = opts.tempRoot;
159
- this._writeFn = opts.writeFn ?? writeFileSync;
160
- this._mkdirFn = opts.mkdirFn ?? mkdirSync;
161
- this.logger = opts.logger ?? console;
162
- this._pointerPath = resolvePointerPath({
163
- tempRoot: this.tempRoot,
164
- epicId: this.epicId,
165
- });
166
- this._epicDir = path.dirname(this._pointerPath);
167
- /** @type {Set<string>} `${event}:${seqId}` idempotency cache. */
168
- this._seen = new Set();
169
- /**
170
- * Monotonic seqId guard. The pointer's `lastCompletedSeqId` MUST
171
- * be non-decreasing — observing a lower seqId after a higher one
172
- * means we are replaying an out-of-order event (resume window or
173
- * test misuse). The listener short-circuits on the regression and
174
- * logs a debug line; it does NOT throw, because a resume cycle
175
- * can legitimately replay older `emitted` lines before catching
176
- * up.
177
- */
178
- this._lastSeqId = 0;
179
- this.events = SUBSCRIBED_END_EVENTS;
180
- }
181
-
182
- /**
183
- * Resolved on-disk path for the pointer file. Exposed for tests.
184
- */
185
- get pointerPath() {
186
- return this._pointerPath;
187
- }
188
-
189
- /**
190
- * Register the listener on every subscribed `*.end` event. Returns
191
- * the array of unsubscribe callbacks the bus produced (parity with
192
- * `signals-appender.register()`).
193
- */
194
- register() {
195
- return this.events.map((event) =>
196
- this.bus.on(event, async (ctx) => this.handle(ctx)),
197
- );
198
- }
199
-
200
- /**
201
- * Bus listener body. Idempotent on `(event, seqId)`; emits
202
- * `checkpoint.written` exactly once after the pointer write
203
- * succeeds.
204
- */
205
- async handle({ event, seqId, payload: _payload }) {
206
- const key = `${event}:${seqId}`;
207
- if (this._seen.has(key)) {
208
- this.logger.debug?.(
209
- `[CheckpointPointerWriter] skip duplicate ${key} (idempotent)`,
210
- );
211
- return;
212
- }
213
- this._seen.add(key);
214
-
215
- // Resume / out-of-order guard. The on-disk pointer is the
216
- // canonical "highest seqId observed so far" — when a replay
217
- // delivers a seqId lower than what we already wrote, we keep the
218
- // pointer untouched and do NOT re-emit `checkpoint.written` for
219
- // the stale event. This makes the listener safe to register
220
- // BEFORE the resume coordinator has fully consumed the prior
221
- // ledger.
222
- if (seqId <= this._lastSeqId) {
223
- this.logger.debug?.(
224
- `[CheckpointPointerWriter] skip non-advancing seqId=${seqId} (lastCompletedSeqId=${this._lastSeqId})`,
225
- );
226
- return;
227
- }
228
-
229
- // The `phase` carried in the pointer is the event name itself —
230
- // every `*.end` event is by convention a phase boundary, so the
231
- // event name is the human-readable phase label the resume
232
- // coordinator displays ("we crashed after wave.end seqId=42").
233
- // Embedding the event name keeps the pointer self-describing
234
- // without requiring an extra `payload.phase` field on every
235
- // schema.
236
- const phase = event;
237
- const pointerPayload = buildPointerPayload({
238
- lastCompletedSeqId: seqId,
239
- phase,
240
- });
241
-
242
- try {
243
- this._mkdirFn(this._epicDir, { recursive: true });
244
- // `writeFileSync` with the default flag truncates — exactly
245
- // what we want: the pointer is a single-line atomic snapshot,
246
- // not an append log. The ledger is the append log; this file
247
- // is the cursor.
248
- this._writeFn(
249
- this._pointerPath,
250
- `${JSON.stringify(pointerPayload)}\n`,
251
- 'utf8',
252
- );
253
- } catch (err) {
254
- // A failed pointer write is recoverable — the ledger still has
255
- // the full history, and the next `*.end` will retry the
256
- // pointer. Surface as a warning and bail before the self-emit
257
- // so we don't claim progress we didn't persist.
258
- this.logger.warn?.(
259
- `[CheckpointPointerWriter] pointer write failed for ${key}: ${err?.message ?? err}`,
260
- );
261
- // Leave the seqId guard advanced for this `(event, seqId)` so
262
- // the in-process retry path doesn't loop on the same failure,
263
- // but DO NOT bump `_lastSeqId` — the next event may still want
264
- // to advance past `seqId`.
265
- return;
266
- }
267
- this._lastSeqId = seqId;
268
-
269
- // Self-emit AFTER the pointer write succeeds. Per the listener
270
- // README, listeners MAY emit follow-up events; the seqId guard
271
- // above ensures `checkpoint.written` fires exactly once per
272
- // observed `*.end`.
273
- await this.bus.emit(CHECKPOINT_WRITTEN_EVENT, pointerPayload);
274
- }
275
-
276
- /**
277
- * Test-only — clear the seqId cache so a single instance can
278
- * exercise resume scenarios without re-constructing the listener.
279
- */
280
- resetSeen() {
281
- this._seen.clear();
282
- this._lastSeqId = 0;
283
- }
284
- }