mandrel 1.93.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/.agents/README.md +59 -73
  2. package/.agents/agents/acceptance-critic.md +129 -0
  3. package/.agents/agents/story-worker.md +161 -0
  4. package/.agents/docs/SDLC.md +489 -1285
  5. package/.agents/docs/agentrc-reference.json +177 -67
  6. package/.agents/docs/configuration.md +108 -136
  7. package/.agents/docs/execution-reference.md +44 -22
  8. package/.agents/docs/quality-gates.md +13 -19
  9. package/.agents/docs/workflows.md +3 -3
  10. package/.agents/instructions.md +107 -108
  11. package/.agents/rules/ci-remediation.md +8 -12
  12. package/.agents/rules/git-conventions-reference.md +224 -0
  13. package/.agents/rules/git-conventions.md +42 -223
  14. package/.agents/rules/security-baseline.md +5 -0
  15. package/.agents/rules/testing-standards.md +106 -13
  16. package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
  17. package/.agents/schemas/agentrc.schema.json +71 -201
  18. package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
  19. package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
  20. package/.agents/schemas/risk-verdict.schema.json +0 -13
  21. package/.agents/scripts/acceptance-eval.js +62 -18
  22. package/.agents/scripts/agents-bootstrap-github.js +1 -1
  23. package/.agents/scripts/analyze-execution.js +1 -1
  24. package/.agents/scripts/audit-to-stories.js +7 -7
  25. package/.agents/scripts/boot-sweep.js +1 -1
  26. package/.agents/scripts/check-context-budget.js +62 -5
  27. package/.agents/scripts/check-lifecycle-lint.js +6 -9
  28. package/.agents/scripts/check-prepush-recovery.js +1 -1
  29. package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
  30. package/.agents/scripts/diagnose-friction.js +0 -6
  31. package/.agents/scripts/lib/Logger.js +6 -10
  32. package/.agents/scripts/lib/audit-suite/runner.js +2 -2
  33. package/.agents/scripts/lib/audit-suite/selector.js +5 -5
  34. package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
  35. package/.agents/scripts/lib/baselines/kernel.js +206 -18
  36. package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -4
  37. package/.agents/scripts/lib/baselines/reader.js +1 -6
  38. package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
  39. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
  40. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +56 -18
  41. package/.agents/scripts/lib/checks/core-bare-clean.js +2 -2
  42. package/.agents/scripts/lib/checks/index.js +2 -1
  43. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +23 -21
  44. package/.agents/scripts/lib/cli/standard-args.js +13 -22
  45. package/.agents/scripts/lib/cli-args.js +16 -7
  46. package/.agents/scripts/lib/close-validation/gates.js +160 -22
  47. package/.agents/scripts/lib/config/acceptance-eval.js +52 -5
  48. package/.agents/scripts/lib/config/ci.js +6 -31
  49. package/.agents/scripts/lib/config/delivery-routing.js +103 -0
  50. package/.agents/scripts/lib/config/explain.js +57 -36
  51. package/.agents/scripts/lib/config/limits.js +17 -58
  52. package/.agents/scripts/lib/config/paths.js +0 -2
  53. package/.agents/scripts/lib/config/quality.js +1 -1
  54. package/.agents/scripts/lib/config/runners.js +17 -50
  55. package/.agents/scripts/lib/config/temp-paths.js +19 -14
  56. package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
  57. package/.agents/scripts/lib/config-resolver.js +3 -8
  58. package/.agents/scripts/lib/config-settings-schema-delivery.js +46 -136
  59. package/.agents/scripts/lib/config-settings-schema-quality.js +17 -14
  60. package/.agents/scripts/lib/config-settings-schema.js +52 -38
  61. package/.agents/scripts/lib/dependency-parser.js +3 -2
  62. package/.agents/scripts/lib/doc-tiers.js +39 -4
  63. package/.agents/scripts/lib/duplicate-search.js +211 -41
  64. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
  65. package/.agents/scripts/lib/findings/promote-finding.js +5 -5
  66. package/.agents/scripts/lib/framework-version.js +2 -3
  67. package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
  68. package/.agents/scripts/lib/git-branch-lifecycle.js +17 -22
  69. package/.agents/scripts/lib/git-utils.js +32 -6
  70. package/.agents/scripts/lib/github/framework-repo.js +6 -0
  71. package/.agents/scripts/lib/label-constants.js +10 -23
  72. package/.agents/scripts/lib/label-taxonomy.js +9 -43
  73. package/.agents/scripts/lib/observability/active-story-env.js +112 -3
  74. package/.agents/scripts/lib/observability/hook-heartbeat.js +187 -0
  75. package/.agents/scripts/lib/observability/source-classifier.js +3 -3
  76. package/.agents/scripts/lib/observability/tool-trace-hook.js +15 -4
  77. package/.agents/scripts/lib/onboard/init-tail.js +1 -3
  78. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +111 -0
  79. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +32 -4
  80. package/.agents/scripts/lib/orchestration/audit-lens-routing.js +128 -0
  81. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +273 -0
  82. package/.agents/scripts/lib/orchestration/ceremony-routing.js +204 -0
  83. package/.agents/scripts/lib/orchestration/code-review.js +20 -268
  84. package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
  85. package/.agents/scripts/lib/orchestration/consolidation-precondition.js +1 -1
  86. package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
  87. package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
  88. package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
  89. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
  90. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +8 -8
  91. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +2 -2
  92. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
  93. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +17 -43
  94. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
  95. package/.agents/scripts/lib/orchestration/merge-block-class.js +1 -1
  96. package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
  97. package/.agents/scripts/lib/orchestration/plan-context.js +248 -266
  98. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +3 -2
  99. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +1 -1
  100. package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
  101. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +61 -0
  102. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +97 -0
  103. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +223 -854
  104. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +361 -0
  105. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +35 -108
  106. package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
  107. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
  108. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +14 -14
  109. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
  110. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/risk-verdict.js +3 -4
  111. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +2 -2
  112. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +8 -20
  113. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +3 -2
  114. package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
  115. package/.agents/scripts/lib/orchestration/preflight-cache.js +5 -5
  116. package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
  117. package/.agents/scripts/lib/orchestration/resolve-plan-run.js +155 -0
  118. package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
  119. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +8 -8
  120. package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
  121. package/.agents/scripts/lib/orchestration/review-depth.js +26 -12
  122. package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
  123. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
  124. package/.agents/scripts/lib/orchestration/run-epilogue.js +426 -0
  125. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +1 -1
  126. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +1 -0
  127. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +95 -41
  128. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +16 -13
  129. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +40 -0
  130. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +11 -3
  131. package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
  132. package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
  133. package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
  134. package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
  135. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
  136. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +15 -12
  137. package/.agents/scripts/lib/orchestration/story-follow-ups.js +237 -0
  138. package/.agents/scripts/lib/orchestration/story-init-remote.js +47 -0
  139. package/.agents/scripts/lib/orchestration/story-plan-state.js +48 -0
  140. package/.agents/scripts/lib/orchestration/{epic-runner → story-progress}/story-run-progress-writer.js +3 -3
  141. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
  142. package/.agents/scripts/lib/orchestration/task-body-validator.js +8 -18
  143. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +11 -61
  144. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +189 -373
  145. package/.agents/scripts/lib/orchestration/ticket-validator.js +3 -8
  146. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +0 -25
  147. package/.agents/scripts/lib/orchestration/ticketing/reads.js +29 -26
  148. package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -5
  149. package/.agents/scripts/lib/planning-corpus.js +16 -11
  150. package/.agents/scripts/lib/preflight-runner.js +2 -2
  151. package/.agents/scripts/lib/provider-factory.js +1 -1
  152. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
  153. package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +36 -0
  154. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
  155. package/.agents/scripts/lib/story-adjacency.js +11 -14
  156. package/.agents/scripts/lib/story-body/story-body.js +124 -70
  157. package/.agents/scripts/lib/story-plan.js +2 -4
  158. package/.agents/scripts/lib/templates/decomposer-prompts.js +46 -45
  159. package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
  160. package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +26 -26
  161. package/.agents/scripts/lib/validation-evidence.js +1 -1
  162. package/.agents/scripts/lib/wave-runner/ready-set.js +6 -6
  163. package/.agents/scripts/lib/workspace-provisioner.js +1 -1
  164. package/.agents/scripts/lib/worktree/lifecycle/reap.js +5 -7
  165. package/.agents/scripts/lint-issue-body.js +71 -40
  166. package/.agents/scripts/mandrel-update-preflight.js +1 -1
  167. package/.agents/scripts/notify.js +4 -3
  168. package/.agents/scripts/plan-context.js +64 -74
  169. package/.agents/scripts/plan-persist.js +121 -280
  170. package/.agents/scripts/plan-run-epilogue.js +97 -0
  171. package/.agents/scripts/post-structured-comment.js +38 -0
  172. package/.agents/scripts/providers/github/issues.js +17 -33
  173. package/.agents/scripts/providers/github/mappers.js +0 -12
  174. package/.agents/scripts/providers/github/tickets.js +2 -5
  175. package/.agents/scripts/resolve-plan-run.js +117 -0
  176. package/.agents/scripts/signals-view.js +24 -19
  177. package/.agents/scripts/single-story-close.js +11 -14
  178. package/.agents/scripts/single-story-confirm-merge.js +39 -23
  179. package/.agents/scripts/single-story-init.js +29 -20
  180. package/.agents/scripts/stories-wave-tick.js +6 -6
  181. package/.agents/scripts/story-plan.js +26 -47
  182. package/.agents/scripts/sync-claude-agents.js +165 -0
  183. package/.agents/scripts/update-ticket-state.js +37 -15
  184. package/.agents/skills/core/analyze-execution/SKILL.md +21 -18
  185. package/.agents/skills/core/api-and-interface-design/SKILL.md +5 -3
  186. package/.agents/skills/core/code-review-and-quality/SKILL.md +63 -7
  187. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +1 -1
  188. package/.agents/skills/core/gates-and-baselines/SKILL.md +149 -0
  189. package/.agents/skills/core/idea-refinement/SKILL.md +8 -14
  190. package/.agents/skills/core/qa-coverage-mapping/SKILL.md +7 -7
  191. package/.agents/skills/core/scope-triage/SKILL.md +28 -172
  192. package/.agents/skills/skills.index.json +8 -418
  193. package/.agents/starter-agentrc.json +0 -5
  194. package/.agents/templates/agent-protocol.md +9 -10
  195. package/.agents/workflows/audit-architecture.md +3 -3
  196. package/.agents/workflows/audit-clean-code.md +3 -3
  197. package/.agents/workflows/audit-dependencies.md +3 -3
  198. package/.agents/workflows/audit-devops.md +3 -3
  199. package/.agents/workflows/audit-documentation.md +5 -5
  200. package/.agents/workflows/audit-lighthouse.md +3 -3
  201. package/.agents/workflows/audit-navigability.md +3 -2
  202. package/.agents/workflows/audit-performance.md +3 -3
  203. package/.agents/workflows/audit-privacy.md +3 -3
  204. package/.agents/workflows/audit-quality.md +3 -3
  205. package/.agents/workflows/audit-security.md +3 -3
  206. package/.agents/workflows/audit-seo.md +3 -3
  207. package/.agents/workflows/audit-sre.md +3 -3
  208. package/.agents/workflows/audit-to-stories.md +20 -20
  209. package/.agents/workflows/audit-ux-ui.md +3 -3
  210. package/.agents/workflows/deliver.md +122 -131
  211. package/.agents/workflows/git-cleanup.md +3 -4
  212. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  213. package/.agents/workflows/helpers/acceptance-self-eval.md +52 -40
  214. package/.agents/workflows/helpers/code-review.md +70 -193
  215. package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +12 -14
  216. package/.agents/workflows/helpers/{single-story-deliver.md → deliver-story.md} +113 -139
  217. package/.agents/workflows/helpers/diagnose.md +10 -10
  218. package/.agents/workflows/helpers/mandrel-sync-config.md +1 -1
  219. package/.agents/workflows/helpers/parallel-tooling.md +1 -1
  220. package/.agents/workflows/helpers/signals.md +16 -16
  221. package/.agents/workflows/helpers/worktree-lifecycle.md +48 -64
  222. package/.agents/workflows/mandrel-update.md +3 -2
  223. package/.agents/workflows/plan.md +112 -145
  224. package/.agents/workflows/qa-assist.md +24 -30
  225. package/.agents/workflows/qa-explore.md +29 -38
  226. package/.agents/workflows/qa-run.md +2 -2
  227. package/README.md +9 -8
  228. package/docs/CHANGELOG.md +46 -0
  229. package/lib/cli/registry.js +95 -0
  230. package/lib/migrations/index.js +6 -5
  231. package/package.json +5 -3
  232. package/.agents/personas/architect.md +0 -113
  233. package/.agents/personas/devops-engineer.md +0 -38
  234. package/.agents/personas/engineer-mobile.md +0 -120
  235. package/.agents/personas/engineer-web.md +0 -111
  236. package/.agents/personas/engineer.md +0 -119
  237. package/.agents/personas/product.md +0 -94
  238. package/.agents/personas/project-manager.md +0 -114
  239. package/.agents/personas/qa-engineer.md +0 -95
  240. package/.agents/personas/refactorer.md +0 -113
  241. package/.agents/personas/security-engineer.md +0 -112
  242. package/.agents/personas/sre.md +0 -86
  243. package/.agents/personas/technical-writer.md +0 -101
  244. package/.agents/personas/ux-designer.md +0 -95
  245. package/.agents/schemas/dispatch-manifest.json +0 -232
  246. package/.agents/schemas/epic-spec.schema.json +0 -153
  247. package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
  248. package/.agents/scripts/dispatcher.js +0 -295
  249. package/.agents/scripts/epic-audit-prepare.js +0 -497
  250. package/.agents/scripts/epic-audit-recheck.js +0 -274
  251. package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
  252. package/.agents/scripts/epic-deliver-preflight.js +0 -462
  253. package/.agents/scripts/epic-deliver-prepare.js +0 -590
  254. package/.agents/scripts/epic-execute-record-wave.js +0 -449
  255. package/.agents/scripts/epic-plan-clarity.js +0 -211
  256. package/.agents/scripts/epic-plan-decompose.js +0 -54
  257. package/.agents/scripts/epic-plan-healthcheck.js +0 -581
  258. package/.agents/scripts/epic-plan-spec.js +0 -64
  259. package/.agents/scripts/epic-reconcile.js +0 -625
  260. package/.agents/scripts/lib/baseline-snapshot.js +0 -979
  261. package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
  262. package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
  263. package/.agents/scripts/lib/config/lifecycle.js +0 -40
  264. package/.agents/scripts/lib/config/preflight.js +0 -58
  265. package/.agents/scripts/lib/config/retro.js +0 -77
  266. package/.agents/scripts/lib/epic-merge-lock.js +0 -322
  267. package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
  268. package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
  269. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -660
  270. package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
  271. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
  272. package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
  273. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
  274. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
  275. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
  276. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
  277. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
  278. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
  279. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
  280. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
  281. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
  282. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
  283. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
  284. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
  285. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
  286. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
  287. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
  288. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -388
  289. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
  290. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
  291. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
  292. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
  293. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
  294. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
  295. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
  296. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
  297. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
  298. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
  299. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
  300. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
  301. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
  302. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
  303. package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
  304. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
  305. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
  306. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
  307. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
  308. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
  309. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
  310. package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
  311. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
  312. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
  313. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -384
  314. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
  315. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
  316. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
  317. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -278
  318. package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
  319. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
  320. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
  321. package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
  322. package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
  323. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
  324. package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
  325. package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
  326. package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
  327. package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
  328. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
  329. package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
  330. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
  331. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
  332. package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
  333. package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
  334. package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
  335. package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +0 -109
  336. package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
  337. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
  338. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
  339. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
  340. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
  341. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
  342. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
  343. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
  344. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
  345. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
  346. package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
  347. package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
  348. package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
  349. package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
  350. package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
  351. package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
  352. package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
  353. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
  354. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
  355. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
  356. package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
  357. package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
  358. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
  359. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
  360. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
  361. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -301
  362. package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
  363. package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
  364. package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
  365. package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
  366. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
  367. package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
  368. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
  369. package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
  370. package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
  371. package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
  372. package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
  373. package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
  374. package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
  375. package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
  376. package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
  377. package/.agents/scripts/lib/push-epic-retry.js +0 -209
  378. package/.agents/scripts/lib/spec/index.js +0 -36
  379. package/.agents/scripts/lib/spec/loader.js +0 -425
  380. package/.agents/scripts/lib/spec/state.js +0 -208
  381. package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
  382. package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
  383. package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
  384. package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
  385. package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
  386. package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
  387. package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
  388. package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
  389. package/.agents/scripts/lib/wave-runner/tick.js +0 -754
  390. package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
  391. package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
  392. package/.agents/scripts/lifecycle-emit.js +0 -510
  393. package/.agents/scripts/plan-critics.js +0 -199
  394. package/.agents/scripts/retro-run.js +0 -218
  395. package/.agents/scripts/standalone-feedback-rollup.js +0 -188
  396. package/.agents/scripts/story-close.js +0 -294
  397. package/.agents/scripts/story-init.js +0 -599
  398. package/.agents/scripts/story-phase.js +0 -369
  399. package/.agents/scripts/wave-tick.js +0 -335
  400. package/.agents/skills/core/baseline-refresh/SKILL.md +0 -181
  401. package/.agents/skills/core/ci-cd-and-automation/SKILL.md +0 -274
  402. package/.agents/skills/core/ci-cd-and-automation/examples.md +0 -211
  403. package/.agents/skills/core/code-simplification/SKILL.md +0 -389
  404. package/.agents/skills/core/context-engineering/SKILL.md +0 -309
  405. package/.agents/skills/core/context-engineering/examples.md +0 -58
  406. package/.agents/skills/core/deprecation-and-migration/SKILL.md +0 -250
  407. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
  408. package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
  409. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
  410. package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
  411. package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
  412. package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
  413. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -413
  414. package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
  415. package/.agents/skills/core/frontend-ui-engineering/SKILL.md +0 -357
  416. package/.agents/skills/core/hydrate-context/SKILL.md +0 -123
  417. package/.agents/skills/core/idea-refinement/examples.md +0 -437
  418. package/.agents/skills/core/idea-refinement/frameworks.md +0 -135
  419. package/.agents/skills/core/incremental-implementation/SKILL.md +0 -271
  420. package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +0 -213
  421. package/.agents/skills/core/knowledge-transfer/SKILL.md +0 -180
  422. package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +0 -117
  423. package/.agents/skills/core/performance-optimization/SKILL.md +0 -314
  424. package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +0 -277
  425. package/.agents/skills/core/property-based-testing/SKILL.md +0 -148
  426. package/.agents/skills/core/refactoring-discipline/SKILL.md +0 -111
  427. package/.agents/skills/core/shipping-and-launch/SKILL.md +0 -328
  428. package/.agents/skills/core/spec-driven-development/SKILL.md +0 -252
  429. package/.agents/skills/core/test-driven-development/SKILL.md +0 -475
  430. package/.agents/skills/core/using-agent-skills/SKILL.md +0 -232
  431. package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +0 -31
  432. package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +0 -51
  433. package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +0 -76
  434. package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +0 -31
  435. package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +0 -33
  436. package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +0 -31
  437. package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +0 -51
  438. package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +0 -54
  439. package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +0 -29
  440. package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +0 -30
  441. package/.agents/skills/stack/backend/stripe-integration/SKILL.md +0 -57
  442. package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +0 -9
  443. package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +0 -48
  444. package/.agents/skills/stack/frontend/astro/SKILL.md +0 -62
  445. package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +0 -30
  446. package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +0 -29
  447. package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +0 -50
  448. package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +0 -58
  449. package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +0 -34
  450. package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +0 -51
  451. package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +0 -199
  452. package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +0 -68
  453. package/.agents/workflows/helpers/deliver-epic-reference.md +0 -534
  454. package/.agents/workflows/helpers/deliver-epic.md +0 -955
  455. package/.agents/workflows/helpers/deliver-stories.md +0 -440
  456. package/.agents/workflows/helpers/epic-audit.md +0 -189
  457. package/.agents/workflows/helpers/epic-deliver-story.md +0 -427
  458. package/.agents/workflows/helpers/epic-testing.md +0 -125
  459. package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
  460. package/.agents/workflows/helpers/plan-epic.md +0 -351
  461. package/.agents/workflows/helpers/plan-story.md +0 -251
  462. package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
  463. /package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +0 -0
@@ -1,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,278 +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
- 'story.dispatch.end',
85
- ]);
86
-
87
- /**
88
- * Resolve the pointer-file path for a given Epic. Exported so tests
89
- * can target the same file without re-deriving the layout.
90
- */
91
- export function resolvePointerPath({ tempRoot, epicId }) {
92
- if (typeof tempRoot !== 'string' || tempRoot.length === 0) {
93
- throw new TypeError(
94
- 'resolvePointerPath: tempRoot must be a non-empty string',
95
- );
96
- }
97
- if (!Number.isInteger(epicId) || epicId < 1) {
98
- throw new TypeError(
99
- 'resolvePointerPath: epicId must be a positive integer',
100
- );
101
- }
102
- return path.join(tempRoot, `epic-${epicId}`, POINTER_FILENAME);
103
- }
104
-
105
- /**
106
- * Build the pointer payload. Pulled out so tests can assert the exact
107
- * on-disk shape without parsing JSON every time.
108
- */
109
- export function buildPointerPayload({ lastCompletedSeqId, phase }) {
110
- return {
111
- lastCompletedSeqId,
112
- phase,
113
- };
114
- }
115
-
116
- /**
117
- * CheckpointPointerWriter listener.
118
- */
119
- export class CheckpointPointerWriter {
120
- /**
121
- * @param {object} opts
122
- * @param {object} opts.bus Lifecycle bus exposing `on()` + `emit()`.
123
- * @param {number} opts.epicId Epic ticket id.
124
- * @param {string} opts.tempRoot Absolute or repo-relative path; the
125
- * listener resolves `<tempRoot>/epic-<id>/checkpoint.json`.
126
- * @param {typeof writeFileSync} [opts.writeFn] Injectable writer for
127
- * tests.
128
- * @param {typeof mkdirSync} [opts.mkdirFn] Injectable directory
129
- * creator for tests.
130
- * @param {{ info?: Function, warn?: Function, debug?: Function }} [opts.logger]
131
- */
132
- constructor(opts = {}) {
133
- if (
134
- !opts.bus ||
135
- typeof opts.bus.on !== 'function' ||
136
- typeof opts.bus.emit !== 'function'
137
- ) {
138
- throw new TypeError(
139
- 'CheckpointPointerWriter requires a bus with on() and emit()',
140
- );
141
- }
142
- if (!Number.isInteger(opts.epicId) || opts.epicId < 1) {
143
- throw new TypeError('CheckpointPointerWriter requires a numeric epicId');
144
- }
145
- if (typeof opts.tempRoot !== 'string' || opts.tempRoot.length === 0) {
146
- throw new TypeError(
147
- 'CheckpointPointerWriter requires a non-empty tempRoot string',
148
- );
149
- }
150
- this.bus = opts.bus;
151
- this.epicId = opts.epicId;
152
- this.tempRoot = opts.tempRoot;
153
- this._writeFn = opts.writeFn ?? writeFileSync;
154
- this._mkdirFn = opts.mkdirFn ?? mkdirSync;
155
- this.logger = opts.logger ?? console;
156
- this._pointerPath = resolvePointerPath({
157
- tempRoot: this.tempRoot,
158
- epicId: this.epicId,
159
- });
160
- this._epicDir = path.dirname(this._pointerPath);
161
- /** @type {Set<string>} `${event}:${seqId}` idempotency cache. */
162
- this._seen = new Set();
163
- /**
164
- * Monotonic seqId guard. The pointer's `lastCompletedSeqId` MUST
165
- * be non-decreasing — observing a lower seqId after a higher one
166
- * means we are replaying an out-of-order event (resume window or
167
- * test misuse). The listener short-circuits on the regression and
168
- * logs a debug line; it does NOT throw, because a resume cycle
169
- * can legitimately replay older `emitted` lines before catching
170
- * up.
171
- */
172
- this._lastSeqId = 0;
173
- this.events = SUBSCRIBED_END_EVENTS;
174
- }
175
-
176
- /**
177
- * Resolved on-disk path for the pointer file. Exposed for tests.
178
- */
179
- get pointerPath() {
180
- return this._pointerPath;
181
- }
182
-
183
- /**
184
- * Register the listener on every subscribed `*.end` event. Returns
185
- * the array of unsubscribe callbacks the bus produced (parity with
186
- * `signals-appender.register()`).
187
- */
188
- register() {
189
- return this.events.map((event) =>
190
- this.bus.on(event, async (ctx) => this.handle(ctx)),
191
- );
192
- }
193
-
194
- /**
195
- * Bus listener body. Idempotent on `(event, seqId)`; emits
196
- * `checkpoint.written` exactly once after the pointer write
197
- * succeeds.
198
- */
199
- async handle({ event, seqId, payload: _payload }) {
200
- const key = `${event}:${seqId}`;
201
- if (this._seen.has(key)) {
202
- this.logger.debug?.(
203
- `[CheckpointPointerWriter] skip duplicate ${key} (idempotent)`,
204
- );
205
- return;
206
- }
207
- this._seen.add(key);
208
-
209
- // Resume / out-of-order guard. The on-disk pointer is the
210
- // canonical "highest seqId observed so far" — when a replay
211
- // delivers a seqId lower than what we already wrote, we keep the
212
- // pointer untouched and do NOT re-emit `checkpoint.written` for
213
- // the stale event. This makes the listener safe to register
214
- // BEFORE the resume coordinator has fully consumed the prior
215
- // ledger.
216
- if (seqId <= this._lastSeqId) {
217
- this.logger.debug?.(
218
- `[CheckpointPointerWriter] skip non-advancing seqId=${seqId} (lastCompletedSeqId=${this._lastSeqId})`,
219
- );
220
- return;
221
- }
222
-
223
- // The `phase` carried in the pointer is the event name itself —
224
- // every `*.end` event is by convention a phase boundary, so the
225
- // event name is the human-readable phase label the resume
226
- // coordinator displays ("we crashed after wave.end seqId=42").
227
- // Embedding the event name keeps the pointer self-describing
228
- // without requiring an extra `payload.phase` field on every
229
- // schema.
230
- const phase = event;
231
- const pointerPayload = buildPointerPayload({
232
- lastCompletedSeqId: seqId,
233
- phase,
234
- });
235
-
236
- try {
237
- this._mkdirFn(this._epicDir, { recursive: true });
238
- // `writeFileSync` with the default flag truncates — exactly
239
- // what we want: the pointer is a single-line atomic snapshot,
240
- // not an append log. The ledger is the append log; this file
241
- // is the cursor.
242
- this._writeFn(
243
- this._pointerPath,
244
- `${JSON.stringify(pointerPayload)}\n`,
245
- 'utf8',
246
- );
247
- } catch (err) {
248
- // A failed pointer write is recoverable — the ledger still has
249
- // the full history, and the next `*.end` will retry the
250
- // pointer. Surface as a warning and bail before the self-emit
251
- // so we don't claim progress we didn't persist.
252
- this.logger.warn?.(
253
- `[CheckpointPointerWriter] pointer write failed for ${key}: ${err?.message ?? err}`,
254
- );
255
- // Leave the seqId guard advanced for this `(event, seqId)` so
256
- // the in-process retry path doesn't loop on the same failure,
257
- // but DO NOT bump `_lastSeqId` — the next event may still want
258
- // to advance past `seqId`.
259
- return;
260
- }
261
- this._lastSeqId = seqId;
262
-
263
- // Self-emit AFTER the pointer write succeeds. Per the listener
264
- // README, listeners MAY emit follow-up events; the seqId guard
265
- // above ensures `checkpoint.written` fires exactly once per
266
- // observed `*.end`.
267
- await this.bus.emit(CHECKPOINT_WRITTEN_EVENT, pointerPayload);
268
- }
269
-
270
- /**
271
- * Test-only — clear the seqId cache so a single instance can
272
- * exercise resume scenarios without re-constructing the listener.
273
- */
274
- resetSeen() {
275
- this._seen.clear();
276
- this._lastSeqId = 0;
277
- }
278
- }