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,140 +0,0 @@
1
- /**
2
- * ledger-diff.js — structural-diff and ordering-assertion helpers over a
3
- * lifecycle ledger (`temp/epic-<id>/lifecycle.ndjson`) for the
4
- * repeatability invariants.
5
- *
6
- * Relocated from the retired `.agents/scripts/lifecycle-diff.js` CLI
7
- * (#4482): the assertion helpers are the live surface — they pin the
8
- * cross-listener ordering contracts in the lifecycle invariant tests —
9
- * while the CLI wrapper had no workflow, script, or CI consumer.
10
- *
11
- * Invariants are derived from Tech Spec #2189 § Repeatability Acceptance
12
- * Criteria.
13
- */
14
-
15
- /**
16
- * Parse an NDJSON lifecycle ledger into an array of records. Blank
17
- * lines tolerated; malformed JSON throws with line number. Duplicated
18
- * from `trace-logger.js` to keep the diff surface decoupled from the
19
- * listener surface.
20
- */
21
- export function parseLedgerText(text) {
22
- const out = [];
23
- const lines = String(text || '').split('\n');
24
- for (let i = 0; i < lines.length; i += 1) {
25
- const line = lines[i].trim();
26
- if (line.length === 0) continue;
27
- try {
28
- out.push(JSON.parse(line));
29
- } catch (_err) {
30
- throw new Error(
31
- `ledger-diff: malformed JSON in ledger on line ${i + 1}: ${line.slice(0, 80)}`,
32
- );
33
- }
34
- }
35
- return out;
36
- }
37
-
38
- /**
39
- * Project a single record into a comparison key. `ts` and `seqId` are
40
- * intentionally elided; the rest of the record is included so that the
41
- * structural shape (event order, payload contents, listener attribution
42
- * on failed records) is the diff surface.
43
- *
44
- * Exported for unit tests that pin the diff contract.
45
- */
46
- export function projectRecord(rec) {
47
- if (!rec || typeof rec !== 'object') return rec;
48
- const { ts: _ts, seqId: _seqId, ...rest } = rec;
49
- return rest;
50
- }
51
-
52
- /**
53
- * Structural diff of two ledger arrays. Returns an array of mismatch
54
- * descriptors (empty when identical modulo `ts`/`seqId`).
55
- */
56
- export function diff(ledgerA, ledgerB) {
57
- const a = ledgerA.map(projectRecord);
58
- const b = ledgerB.map(projectRecord);
59
- const out = [];
60
- const max = Math.max(a.length, b.length);
61
- for (let i = 0; i < max; i += 1) {
62
- const left = a[i];
63
- const right = b[i];
64
- const leftJson = JSON.stringify(left);
65
- const rightJson = JSON.stringify(right);
66
- if (leftJson !== rightJson) {
67
- out.push({ index: i, left: left ?? null, right: right ?? null });
68
- }
69
- }
70
- return out;
71
- }
72
-
73
- /**
74
- * Assert: epic.merge.armed must be preceded by epic.merge.ready
75
- * (same run). Returns `{ ok: true }` or `{ ok: false, reason }`.
76
- */
77
- export function assertMergeGateOrdering(records) {
78
- let sawReady = false;
79
- let sawReadySeq = null;
80
- for (const rec of records) {
81
- if (rec.kind !== 'emitted') continue;
82
- if (rec.event === 'epic.merge.ready') {
83
- sawReady = true;
84
- sawReadySeq = rec.seqId;
85
- } else if (rec.event === 'epic.merge.armed') {
86
- if (!sawReady) {
87
- return {
88
- ok: false,
89
- reason: `epic.merge.armed at seqId=${rec.seqId} without preceding epic.merge.ready`,
90
- };
91
- }
92
- if (sawReadySeq != null && rec.seqId <= sawReadySeq) {
93
- return {
94
- ok: false,
95
- reason: `epic.merge.armed seqId=${rec.seqId} must be > epic.merge.ready seqId=${sawReadySeq}`,
96
- };
97
- }
98
- }
99
- }
100
- return { ok: true };
101
- }
102
-
103
- /**
104
- * Assert: pr.created must be preceded by either acceptance.reconcile.ok
105
- * or acceptance.reconcile.waived in the same run. Story #2893 split the
106
- * waiver path out of `.skipped` so the Finalizer now subscribes to both
107
- * `.ok` and `.waived`; either is a valid predecessor for pr.created.
108
- * A reconcile.skipped (empty-spec only after #2893) or reconcile.failed
109
- * before pr.created remains a violation.
110
- */
111
- export function assertReconcileOrdering(records) {
112
- let sawReconcileGate = false;
113
- let sawReconcileGateSeq = null;
114
- let sawReconcileGateEvent = null;
115
- for (const rec of records) {
116
- if (rec.kind !== 'emitted') continue;
117
- if (
118
- rec.event === 'acceptance.reconcile.ok' ||
119
- rec.event === 'acceptance.reconcile.waived'
120
- ) {
121
- sawReconcileGate = true;
122
- sawReconcileGateSeq = rec.seqId;
123
- sawReconcileGateEvent = rec.event;
124
- } else if (rec.event === 'pr.created') {
125
- if (!sawReconcileGate) {
126
- return {
127
- ok: false,
128
- reason: `pr.created at seqId=${rec.seqId} without preceding acceptance.reconcile.ok or acceptance.reconcile.waived`,
129
- };
130
- }
131
- if (sawReconcileGateSeq != null && rec.seqId <= sawReconcileGateSeq) {
132
- return {
133
- ok: false,
134
- reason: `pr.created seqId=${rec.seqId} must be > ${sawReconcileGateEvent} seqId=${sawReconcileGateSeq}`,
135
- };
136
- }
137
- }
138
- }
139
- return { ok: true };
140
- }
@@ -1,465 +0,0 @@
1
- // .agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js
2
- /**
3
- * AcceptanceReconciler — lifecycle listener that gates Finalize on the
4
- * close-time acceptance-spec reconciliation. Story #2253 (Epic #2172):
5
- * the reconciliation moves *ahead* of the push + `gh pr create` call so
6
- * that AC coverage gaps block PR creation (review High-2).
7
- *
8
- * Subscribes to:
9
- * - `epic.close.end` → emit `acceptance.reconcile.start`, run the
10
- * `reconcileAcceptanceSpec` helper, emit one of
11
- * `acceptance.reconcile.ok | .waived | .skipped | .failed`, and on
12
- * `.failed` also emit `epic.blocked` so the LabelTransitioner /
13
- * StructuredCommentPoster / NotifyDispatcher trio fire the blocker
14
- * side effects exactly as a `story.blocked` cascade would.
15
- *
16
- * The Finalizer listener subscribes ONLY to `acceptance.reconcile.ok`,
17
- * so this listener is the authoritative safety gate ahead of any push
18
- * or PR-create work. The legacy `epic-deliver-finalize.js` shim still
19
- * exists for backwards compatibility, but its in-line reconciliation
20
- * call is replaced by the event-driven path.
21
- *
22
- * Idempotency contract (Acceptance Spec AC-10):
23
- * - Per-instance `Set<string>` of `${event}:${seqId}` keys. A repeat
24
- * `(event, seqId)` short-circuits without re-running reconciliation
25
- * and emits no events.
26
- * - The reconciler helper's only write is the section-scoped
27
- * disposition record inside the Epic body's ## Acceptance Table
28
- * region (Story #4324) — itself idempotent — so the seqId guard is
29
- * the only defence the listener needs.
30
- *
31
- * Side-effect firewall: the listener owns the reconciliation call and
32
- * the four outcome emits. It does NOT mutate labels, post comments, or
33
- * call `notify` directly — those are downstream listener concerns.
34
- */
35
-
36
- import { reconcileAcceptanceSpec as defaultReconcileAcceptanceSpec } from '../../../../acceptance-spec-reconciler.js';
37
- import { DELIVERY_SINGLE_LABEL } from '../../deliver-route.js';
38
- import { read as readEpicRunState } from '../../epic-run-state-store.js';
39
-
40
- /**
41
- * Default single-delivery resolver (Epic #4475, M4-B, design §2c). Decides
42
- * whether the Epic under reconciliation is the single-delivery shape — the
43
- * signal that flips a `waived` reconcile into a hard failure (the back gate
44
- * of the non-waivable epic-level acceptance contract). Two sources, primary
45
- * first:
46
- *
47
- * 1. `epic-run-state.deliveryShape === 'single'` — the durable checkpoint
48
- * the single-delivery prepare writes.
49
- * 2. The `delivery::single` label on the Epic ticket — the plan-time marker.
50
- *
51
- * Best-effort + fail-open-to-fan-out: any probe failure (null provider in a
52
- * unit fixture, a GitHub read error) degrades to `false` (treat as fan-out),
53
- * so the defence-in-depth back gate never *invents* a block — the front gate
54
- * (prepare refusing `acceptance::n-a`) is the primary guard. Tests inject
55
- * `resolveSingleFn` directly to bypass the probes.
56
- *
57
- * @param {{ provider?: object|null, epicId: number, config?: object|null }} args
58
- * @returns {Promise<boolean>}
59
- */
60
- export async function defaultResolveSingle({ provider, epicId }) {
61
- if (!provider) return false;
62
- try {
63
- const checkpoint = await readEpicRunState({ provider, epicId });
64
- if (checkpoint?.deliveryShape === 'single') return true;
65
- } catch {
66
- // Fall through to the label probe.
67
- }
68
- try {
69
- const epic = await provider.getTicket(epicId);
70
- const labels = Array.isArray(epic?.labels) ? epic.labels : [];
71
- return labels.some(
72
- (l) => (typeof l === 'string' ? l : l?.name) === DELIVERY_SINGLE_LABEL,
73
- );
74
- } catch {
75
- return false;
76
- }
77
- }
78
-
79
- /**
80
- * Classify a `reconcileAcceptanceSpec` result envelope into the typed
81
- * outcome event the listener should emit. Pure function — exported so
82
- * unit tests can drive every branch without a bus instance.
83
- *
84
- * The reconciler exposes a four-value `status` discriminant:
85
- * - `'waived'` → the Epic carries `acceptance::n-a` (or no linked
86
- * spec under `--skip-when-waived`). Emit
87
- * `acceptance.reconcile.waived` with reason
88
- * `'waiver'`. Story #2893 split this out from
89
- * `.skipped` so the Finalizer can subscribe to
90
- * `.waived` and route waived Epics through to PR
91
- * creation, while empty-spec Epics still
92
- * terminate without a PR via `.skipped`.
93
- * **Non-waivable under single delivery (Epic #4475,
94
- * M4-B, design §2c):** when `opts.single` is true the
95
- * epic-level reconcile is the ONLY acceptance gate
96
- * left, so a `waived` status is treated as a hard
97
- * `failed` (reason `single-delivery-non-waivable`)
98
- * instead of passing through — the back gate that
99
- * forecloses the cohort's dilution (waived reconcile
100
- * as the sole gate). The front gate (prepare refusing
101
- * `acceptance::n-a`) already blocks this at seed time;
102
- * this is defence in depth.
103
- * - `'empty-spec'` → the linked spec exists but declares zero AC IDs.
104
- * Treated as "no work to do"; emit `.skipped` with
105
- * reason `'empty-spec'` so operators see the
106
- * outcome explicitly (no silent skip).
107
- * - `'ok'` → the spec has AC IDs and every one is covered by
108
- * a non-pending scenario. Emit `.ok`.
109
- * - `'gap'` → at least one AC is pending or missing. Emit
110
- * `.failed` carrying a compact reason summary;
111
- * the listener then emits `epic.blocked` to flip
112
- * the Epic ticket.
113
- *
114
- * @param {object|undefined|null} result reconciler envelope.
115
- * @param {{ single?: boolean }} [opts] `single: true` flips a `waived` status
116
- * into a hard `failed` (the non-waivable epic reconcile back gate).
117
- * @returns {{ outcome: 'ok'|'waived'|'skipped'|'failed', reason?: string }}
118
- */
119
- export function classifyReconcileResult(result, opts = {}) {
120
- const single = opts?.single === true;
121
- if (!result || typeof result !== 'object') {
122
- return { outcome: 'failed', reason: 'reconciler-no-result' };
123
- }
124
- const status = result.status;
125
- if (status === 'waived') {
126
- if (single) {
127
- return {
128
- outcome: 'failed',
129
- reason: 'single-delivery-non-waivable',
130
- };
131
- }
132
- return { outcome: 'waived', reason: 'waiver' };
133
- }
134
- if (status === 'empty-spec') {
135
- return { outcome: 'skipped', reason: 'empty-spec' };
136
- }
137
- if (status === 'ok') {
138
- return { outcome: 'ok' };
139
- }
140
- if (status === 'gap') {
141
- const missing = Array.isArray(result.missing) ? result.missing : [];
142
- const pending = Array.isArray(result.pending) ? result.pending : [];
143
- const parts = [];
144
- if (missing.length > 0) parts.push(`missing=${missing.join(',')}`);
145
- if (pending.length > 0) parts.push(`pending=${pending.join(',')}`);
146
- const reason =
147
- parts.length > 0 ? `gap:${parts.join(';')}` : 'gap:unspecified';
148
- return { outcome: 'failed', reason };
149
- }
150
- // Unknown status — fail closed so the operator sees the surprise.
151
- return { outcome: 'failed', reason: `unknown-status:${String(status)}` };
152
- }
153
-
154
- /**
155
- * AcceptanceReconciler — instantiate one per Epic run and call
156
- * `register()` to wire it onto the bus. Stateless w.r.t. the system
157
- * under orchestration; per-run state is the `(event, seqId)`
158
- * idempotency cache + the classification log.
159
- */
160
- export class AcceptanceReconciler {
161
- /**
162
- * @param {object} opts
163
- * @param {object} opts.bus Lifecycle bus instance (must expose
164
- * `on()` and `emit()`).
165
- * @param {number} opts.epicId Epic ticket id.
166
- * @param {string} [opts.cwd] Working directory passed through to the
167
- * reconciler helper. Defaults to `process.cwd()`.
168
- * @param {object} [opts.provider] Ticketing provider — injected into
169
- * the reconciler call so the lifecycle bus does not need to
170
- * construct one itself.
171
- * @param {object} [opts.config] Resolved orchestration config —
172
- * injected for the same reason.
173
- * @param {Function} [opts.reconcileAcceptanceSpecFn] Override of the
174
- * helper for tests; defaults to the production export.
175
- * @param {Function} [opts.resolveSingleFn] Override of the single-delivery
176
- * resolver for tests (Epic #4475, M4-B); defaults to `defaultResolveSingle`
177
- * (checkpoint `deliveryShape` → `delivery::single` label).
178
- * @param {{ info?: Function, warn?: Function, debug?: Function }} [opts.logger]
179
- */
180
- constructor(opts = {}) {
181
- if (
182
- !opts.bus ||
183
- typeof opts.bus.on !== 'function' ||
184
- typeof opts.bus.emit !== 'function'
185
- ) {
186
- throw new TypeError(
187
- 'AcceptanceReconciler requires a bus with on() and emit()',
188
- );
189
- }
190
- if (!Number.isInteger(opts.epicId) || opts.epicId < 1) {
191
- throw new TypeError('AcceptanceReconciler requires a numeric epicId');
192
- }
193
- this.bus = opts.bus;
194
- this.epicId = opts.epicId;
195
- this.cwd = opts.cwd ?? process.cwd();
196
- this.provider = opts.provider ?? null;
197
- this.config = opts.config ?? null;
198
- this.reconcileAcceptanceSpecFn =
199
- opts.reconcileAcceptanceSpecFn ?? defaultReconcileAcceptanceSpec;
200
- this.resolveSingleFn = opts.resolveSingleFn ?? defaultResolveSingle;
201
- this.logger = opts.logger ?? console;
202
- /** @type {Set<string>} `${event}:${seqId}` keys we've handled. */
203
- this._seen = new Set();
204
- /**
205
- * Classification log — mirrors the BlockerHandler "no silent skip"
206
- * surface so tests can confirm every `epic.close.end` we observed
207
- * was classified into exactly one outcome.
208
- *
209
- * @type {Array<{ event: string, seqId: number, outcome: string, reason?: string }>}
210
- */
211
- this.classifications = [];
212
- this.events = Object.freeze(['epic.close.end']);
213
- }
214
-
215
- /**
216
- * Register this listener on the bus. Returns an array of unsubscribe
217
- * functions (one per event) for test teardown.
218
- */
219
- register() {
220
- return this.events.map((event) =>
221
- this.bus.on(event, async (ctx) => this.handle(ctx)),
222
- );
223
- }
224
-
225
- /**
226
- * Bus listener body. The bus passes `{ event, seqId, payload }`. The
227
- * listener:
228
- * 1. Idempotently short-circuits a repeat `(event, seqId)`.
229
- * 2. Emits `acceptance.reconcile.start`.
230
- * 3. Runs `reconcileAcceptanceSpec` with injected provider/config.
231
- * 4. Emits exactly one of `.ok` / `.skipped` / `.failed`.
232
- * 5. On `.failed`, additionally emits `epic.blocked` so the
233
- * downstream listener trio (label flip + structured comment +
234
- * notify) fires the operator-visible blocker side effects.
235
- *
236
- * The listener does NOT throw on reconciler failures: the bus's
237
- * `onFailed` boundary already persists the originating
238
- * `epic.close.end` record; surfacing a throw here would short-circuit
239
- * other `epic.close.end` listeners (e.g. trace logger) and is not
240
- * needed for correctness — the `acceptance.reconcile.failed` +
241
- * `epic.blocked` emits are the cascade contract.
242
- *
243
- * @param {{ event: string, seqId: number, payload: object }} ctx
244
- */
245
- async handle({ event, seqId, payload }) {
246
- const key = `${event}:${seqId}`;
247
- if (this._seen.has(key)) {
248
- this.classifications.push({
249
- event,
250
- seqId,
251
- outcome: 'skipped',
252
- reason: 'duplicate-seqId',
253
- });
254
- this.logger.debug?.(
255
- `[AcceptanceReconciler] skip duplicate ${key} (idempotent)`,
256
- );
257
- return;
258
- }
259
- this._seen.add(key);
260
-
261
- const epicIdFromPayload = Number(payload?.epicId);
262
- const epicId = Number.isInteger(epicIdFromPayload)
263
- ? epicIdFromPayload
264
- : this.epicId;
265
-
266
- // 1. Start emit. The downstream ledger-diff `reconcile-ordering`
267
- // assert checks for `acceptance.reconcile.ok` before `pr.created`,
268
- // but operators want to see the `.start` marker in the trace too.
269
- try {
270
- await this.bus.emit('acceptance.reconcile.start', { epicId });
271
- } catch (err) {
272
- // Schema validation against a known-good payload should never
273
- // throw; if it does, surface and bail — there's no point running
274
- // the reconciler when we cannot announce its outcome.
275
- this.classifications.push({
276
- event,
277
- seqId,
278
- outcome: 'failed',
279
- reason: `start-emit-failed:${err?.message ?? err}`,
280
- });
281
- this.logger.warn?.(
282
- `[AcceptanceReconciler] acceptance.reconcile.start emit failed: ${err?.message ?? err}`,
283
- );
284
- return;
285
- }
286
-
287
- // 2. Run the reconciler. The helper itself throws on hard errors
288
- // (no linked spec + no waiver, etc.); convert those into
289
- // `.failed` emits rather than re-propagating, so the cascade
290
- // contract holds even when the spec is malformed.
291
- let result;
292
- let thrown = null;
293
- try {
294
- result = await this.reconcileAcceptanceSpecFn({
295
- epicId,
296
- cwd: this.cwd,
297
- injectedProvider: this.provider ?? undefined,
298
- injectedConfig: this.config ?? undefined,
299
- loggerImpl: this.logger,
300
- // Honour `acceptance::n-a` — the helper already returns
301
- // `status: 'waived'` for that label, but `skipWhenWaived: true`
302
- // additionally tolerates a missing acceptance-table section under
303
- // the waiver (we want the same forgiving stance the inline
304
- // finalize call had).
305
- skipWhenWaived: true,
306
- // Close time is the one place the verification outcome is
307
- // recorded into the Epic body's ## Acceptance Table section
308
- // (section-scoped write, Story #4324).
309
- writeDispositions: true,
310
- });
311
- } catch (err) {
312
- thrown = err;
313
- }
314
-
315
- const baseRead = thrown == null && result != null;
316
-
317
- if (thrown != null) {
318
- const reason = `reconcile-threw:${thrown?.message ?? thrown}`;
319
- await this._emitFailure({ event, seqId, baseRead, reason });
320
- return;
321
- }
322
-
323
- // Resolve the delivery shape before classifying: under single delivery a
324
- // `waived` reconcile is non-waivable (design §2c). Best-effort — a probe
325
- // failure degrades to `false` (fan-out pass-through), never inventing a
326
- // block.
327
- let single = false;
328
- try {
329
- single = await this.resolveSingleFn({
330
- provider: this.provider,
331
- epicId,
332
- config: this.config,
333
- });
334
- } catch (err) {
335
- this.logger.warn?.(
336
- `[AcceptanceReconciler] single-delivery probe failed (treating as fan-out): ${err?.message ?? err}`,
337
- );
338
- }
339
-
340
- const classification = classifyReconcileResult(result, { single });
341
- if (classification.outcome === 'ok') {
342
- await this._emitOk({ event, seqId, baseRead });
343
- return;
344
- }
345
- if (classification.outcome === 'waived') {
346
- await this._emitWaived({
347
- event,
348
- seqId,
349
- baseRead,
350
- reason: classification.reason ?? 'waiver',
351
- });
352
- return;
353
- }
354
- if (classification.outcome === 'skipped') {
355
- await this._emitSkipped({
356
- event,
357
- seqId,
358
- baseRead,
359
- reason: classification.reason ?? 'skipped',
360
- });
361
- return;
362
- }
363
- await this._emitFailure({
364
- event,
365
- seqId,
366
- baseRead,
367
- reason: classification.reason ?? 'gap',
368
- });
369
- }
370
-
371
- /**
372
- * Emit `acceptance.reconcile.ok` and record the classification.
373
- * Helper carved out so each branch in `handle()` reads as a single
374
- * decision.
375
- */
376
- async _emitOk({ event, seqId, baseRead }) {
377
- this.classifications.push({ event, seqId, outcome: 'ok' });
378
- try {
379
- await this.bus.emit('acceptance.reconcile.ok', { baseRead });
380
- } catch (err) {
381
- this.logger.warn?.(
382
- `[AcceptanceReconciler] acceptance.reconcile.ok emit failed (swallowed): ${err?.message ?? err}`,
383
- );
384
- }
385
- }
386
-
387
- /**
388
- * Emit `acceptance.reconcile.waived` for the `acceptance::n-a` path.
389
- * Story #2893 split this out of `.skipped` so the Finalizer can
390
- * subscribe to `.waived` and route waived Epics through to PR
391
- * creation. The schema pins `reason` to `'waiver'`.
392
- */
393
- async _emitWaived({ event, seqId, baseRead, reason }) {
394
- this.classifications.push({ event, seqId, outcome: 'waived', reason });
395
- try {
396
- await this.bus.emit('acceptance.reconcile.waived', {
397
- baseRead,
398
- reason,
399
- });
400
- } catch (err) {
401
- this.logger.warn?.(
402
- `[AcceptanceReconciler] acceptance.reconcile.waived emit failed (swallowed): ${err?.message ?? err}`,
403
- );
404
- }
405
- }
406
-
407
- /**
408
- * Emit `acceptance.reconcile.skipped` carrying a typed `reason`. The
409
- * schema requires `reason` to be non-empty so callers always pass one
410
- * (no silent skip).
411
- */
412
- async _emitSkipped({ event, seqId, baseRead, reason }) {
413
- this.classifications.push({ event, seqId, outcome: 'skipped', reason });
414
- try {
415
- await this.bus.emit('acceptance.reconcile.skipped', {
416
- baseRead,
417
- reason,
418
- });
419
- } catch (err) {
420
- this.logger.warn?.(
421
- `[AcceptanceReconciler] acceptance.reconcile.skipped emit failed (swallowed): ${err?.message ?? err}`,
422
- );
423
- }
424
- }
425
-
426
- /**
427
- * Emit `acceptance.reconcile.failed` and then `epic.blocked`, in that
428
- * order. The `epic.blocked` emit drives the LabelTransitioner /
429
- * StructuredCommentPoster / NotifyDispatcher trio so the operator
430
- * sees the blocker label flip + structured comment + webhook,
431
- * exactly as a `story.blocked` cascade would.
432
- *
433
- * Failures inside the `epic.blocked` emit are swallowed (the
434
- * `.failed` record is already on the ledger; double-throwing here
435
- * would mask the original reason).
436
- */
437
- async _emitFailure({ event, seqId, baseRead, reason }) {
438
- this.classifications.push({ event, seqId, outcome: 'failed', reason });
439
- try {
440
- await this.bus.emit('acceptance.reconcile.failed', {
441
- baseRead,
442
- reason,
443
- });
444
- } catch (err) {
445
- this.logger.warn?.(
446
- `[AcceptanceReconciler] acceptance.reconcile.failed emit failed (swallowed): ${err?.message ?? err}`,
447
- );
448
- }
449
- try {
450
- await this.bus.emit('epic.blocked', {
451
- reason: `acceptance-reconcile:${reason}`,
452
- });
453
- } catch (err) {
454
- this.logger.warn?.(
455
- `[AcceptanceReconciler] epic.blocked emit failed (swallowed): ${err?.message ?? err}`,
456
- );
457
- }
458
- }
459
-
460
- /** Test helper — wipe the idempotency cache. */
461
- reset() {
462
- this._seen.clear();
463
- this.classifications = [];
464
- }
465
- }