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,302 +0,0 @@
1
- /**
2
- * pre-merge-validation.js — shift-left close-validation gate runner +
3
- * maintainability projection advisory.
4
- *
5
- * Extracted from story-close.js (Story #956, Theme A finishing touch) so the
6
- * close orchestrator becomes a thin CLI shell. Two responsibilities:
7
- *
8
- * - runPreMergeGates — drives `runCloseValidation` over the
9
- * canonical gate list (typecheck, lint, test,
10
- * format, maintainability, crap), routes
11
- * `lint`/`test` start events into the supplied
12
- * phase-timer, and throws on the first failed
13
- * gate with the gate-specific hint embedded in
14
- * the error message.
15
- * - emitMaintainabilityProjection — runs the per-file MI ceiling projection
16
- * and emits the `baseline-refresh:` advisory
17
- * before the merge so the operator can ship the
18
- * refresh atomically with the Story PR.
19
- *
20
- * Both helpers take their dependencies as injectable seams so unit tests
21
- * pin behaviour without spawning the close script.
22
- */
23
-
24
- // Story #1973 / Task #1985 — direct import from the maintainability per-kind
25
- // module under `.agents/scripts/lib/baselines/kinds/`. Replaces the historical
26
- // `child_process.spawn(node check-maintainability.js)` arm of this helper:
27
- // the kernel-version label that used to come from the CLI's stdout is now
28
- // resolved in-process from the per-kind module, and the test suite's
29
- // no-spawn spy proves the projection path never reaches a per-kind CLI
30
- // subprocess.
31
- import * as maintainabilityKind from '../../baselines/kinds/maintainability.js';
32
- import { buildDefaultGates as defaultBuildDefaultGates } from '../../close-validation/gates.js';
33
- import {
34
- formatMaintainabilityProjection as defaultFormatMaintainabilityProjection,
35
- projectMaintainabilityRegressions as defaultProjectMaintainabilityRegressions,
36
- } from '../../close-validation/projections/maintainability.js';
37
- import { runCloseValidation as defaultRunCloseValidation } from '../../close-validation/runner.js';
38
- import { getBaselines as defaultGetBaselines } from '../../config-resolver.js';
39
- import { Logger as DefaultLogger } from '../../Logger.js';
40
-
41
- /**
42
- * Story #2250 — lifecycle emits fire only when both a positive epicId and a
43
- * positive storyId are present (the schema requires both) and a bus exists.
44
- * Legacy resume fixtures pass `storyId: null` and must run without emits.
45
- * Story #4075 — extracted from `runPreMergeGates`.
46
- */
47
- export function lifecycleEmitsActive({ epicId, storyId, bus }) {
48
- return (
49
- Number.isInteger(epicId) &&
50
- epicId > 0 &&
51
- Number.isInteger(storyId) &&
52
- storyId > 0 &&
53
- !!bus
54
- );
55
- }
56
-
57
- /**
58
- * Build the typed `PRE_MERGE_GATE_FAILED` Error from the first failed gate.
59
- * Story #2136 / Task #2143 — failure metadata is surfaced as typed Error
60
- * properties so callers (notably `runPreMergeGatesWithAttribution`)
61
- * pattern-match exit codes without parsing the human message; the message
62
- * format is preserved byte-for-byte so existing regex consumers keep
63
- * matching. Story #4075 — extracted from `runPreMergeGates`.
64
- */
65
- export function buildGateFailureError({ gate, status, gateCwd }) {
66
- const err = new Error(
67
- `Pre-merge validation failed at "${gate.name}" (exit ${status})${gateCwd ? ` in ${gateCwd}` : ''}.` +
68
- (gate.hint ? ` ${gate.hint}` : ''),
69
- );
70
- err.code = 'PRE_MERGE_GATE_FAILED';
71
- err.gateName = gate.name;
72
- err.exitCode = status;
73
- err.gateCwd = gateCwd ?? null;
74
- return err;
75
- }
76
-
77
- /**
78
- * Run the pre-merge validation gate chain. On failure throws an `Error`
79
- * whose message embeds the first failed gate's name, exit code, hint, and
80
- * the working directory the gate ran in — the `runAsCli` boundary in
81
- * `story-close.js` maps the throw to `process.exit(1)`. (See Story #959 —
82
- * close-tail scripts must throw rather than route through the logger's
83
- * fatal sink, so a mocked `process.exit` cannot swallow the failure
84
- * silently.)
85
- *
86
- * Story #1120: pass `worktreePath` (`.worktrees/story-<id>/`) so every
87
- * gate runs against the Story branch's post-rebase tree, not the main
88
- * checkout. Without it, gate spawn falls back to `cwd` (the main
89
- * checkout) — the legacy single-tree path remains intact.
90
- *
91
- * `phaseTimer` may be omitted; when present, lint/test starts are timed.
92
- *
93
- * Story #2250 — the gate chain is the canonical close-validate sub-phase
94
- * of the close-tail; this helper emits `close-validate.start` /
95
- * `close-validate.end` events on the supplied lifecycle bus so the
96
- * lifecycle ledger captures the sub-phase boundary with non-zero
97
- * `durationMs`. On gate failure the helper also emits `story.blocked`
98
- * with a typed `close-validate-failed:<gateName>` reason BEFORE throwing
99
- * — the existing BlockerHandler listener (Story #2241 / Task #2246)
100
- * cascades that to `epic.blocked`, so a failed validator routes through
101
- * the lifecycle cascade rather than being silently swallowed by the
102
- * caller's try/catch. The throw shape is preserved byte-for-byte so the
103
- * regex consumers in `runPreMergeGatesWithAttribution` keep matching.
104
- */
105
- export async function runPreMergeGates({
106
- cwd,
107
- worktreePath,
108
- epicBranch,
109
- config,
110
- storyId,
111
- epicId,
112
- useEvidence = true,
113
- phaseTimer,
114
- bus,
115
- now = Date.now,
116
- logger = DefaultLogger,
117
- buildDefaultGates = defaultBuildDefaultGates,
118
- runCloseValidation = defaultRunCloseValidation,
119
- }) {
120
- // Epic #2646 Story C (Task #2700) — `bus` is a hard input. The
121
- // previous guarded `emitLifecycleSafe` helper that tolerated a null
122
- // bus is gone. The `emitsActive` outer guard below still skips emits
123
- // for legacy resume fixtures that pass `storyId: null` (those rows
124
- // have no Story-scoped lifecycle), but bus must be present.
125
- if (!bus || typeof bus.emit !== 'function') {
126
- throw new TypeError(
127
- 'runPreMergeGates: bus is required (object with emit()).',
128
- );
129
- }
130
- logger.info?.(
131
- `[close-validation] Running pre-merge gates (typecheck, lint, test, format, maintainability, crap, baselines)${worktreePath ? ` in ${worktreePath}` : ''}${epicBranch ? ` against baseline ref ${epicBranch}` : ''}...`,
132
- );
133
- // `buildDefaultGates` reads the canonical resolved config directly:
134
- // gate commands resolve from `project.commands` and the CRAP toggle
135
- // from `delivery.quality.gates.crap.enabled`.
136
- // Probe the coverage script from the gate execution directory (the Story
137
- // worktree when present) so coverage-capture is only registered when the
138
- // consumer ships `test:coverage` (#4473).
139
- const gates = buildDefaultGates({
140
- config,
141
- epicBranch,
142
- cwd: worktreePath || cwd,
143
- log: (m) => logger.info?.(m),
144
- });
145
- const gateCount = Array.isArray(gates) ? gates.length : 0;
146
- // Story #2250 — emit `close-validate.start` only when both an epicId
147
- // and a storyId are present; the schema requires both, and unit
148
- // fixtures that drive the helper with `storyId: null` (legacy resume
149
- // tests) must continue to operate without lifecycle observability.
150
- const emitsActive = lifecycleEmitsActive({ epicId, storyId, bus });
151
- const startedAt = typeof now === 'function' ? now() : Date.now();
152
-
153
- // Emit the `close-validate.end` boundary, plus the `story.blocked`
154
- // cascade trigger on failure (Story #2250). No-op when emits are
155
- // inactive (legacy resume fixtures with `storyId: null`).
156
- const emitEnd = async ({ ok, extra = {}, blockedReason } = {}) => {
157
- if (!emitsActive) return;
158
- const endedAt = typeof now === 'function' ? now() : Date.now();
159
- await bus.emit('close-validate.end', {
160
- epicId,
161
- storyId,
162
- ok,
163
- gateCount,
164
- ...extra,
165
- durationMs: Math.max(0, endedAt - startedAt),
166
- });
167
- if (blockedReason) {
168
- await bus.emit('story.blocked', { storyId, reason: blockedReason });
169
- }
170
- };
171
-
172
- if (emitsActive) {
173
- await bus.emit('close-validate.start', { epicId, storyId });
174
- }
175
- let validation;
176
- try {
177
- validation = await runCloseValidation({
178
- cwd,
179
- worktreePath,
180
- gates,
181
- log: (m) => logger.info(m),
182
- onGateStart: (gate) => {
183
- // Only the canonical phase-enum gates drive `mark()`. Non-enum gates
184
- // (`typecheck`, `format`, `check-maintainability`) share the
185
- // currently-open phase's wall clock — a deliberate choice so the
186
- // `phase-timings` schema stays stable against future gate churn.
187
- if (phaseTimer && (gate.name === 'lint' || gate.name === 'test')) {
188
- phaseTimer.mark(gate.name);
189
- }
190
- },
191
- storyId,
192
- epicId,
193
- useEvidence,
194
- });
195
- } catch (err) {
196
- // Reach this branch only when `runCloseValidation` itself throws
197
- // (spawn-level catastrophe — the per-gate failures route through
198
- // `validation.failed` below). Emit the matching `close-validate.end`
199
- // with `ok:false` so the ledger always carries the boundary, then
200
- // re-throw.
201
- await emitEnd({
202
- ok: false,
203
- extra: { failedGate: 'runner-error' },
204
- blockedReason: 'close-validate-failed:runner-error',
205
- });
206
- throw err;
207
- }
208
- if (!validation.ok) {
209
- const { gate, status, cwd: gateCwd } = validation.failed[0];
210
- // Story #2250 — emit the boundary + `story.blocked` cascade BEFORE
211
- // throwing so the lifecycle ledger captures the boundary even when the
212
- // caller's try/catch swallows the throw, and the BlockerHandler
213
- // listener cascades to `epic.blocked`.
214
- await emitEnd({
215
- ok: false,
216
- extra: { failedGate: gate.name, exitCode: status },
217
- blockedReason: `close-validate-failed:${gate.name}`,
218
- });
219
- throw buildGateFailureError({ gate, status, gateCwd });
220
- }
221
- await emitEnd({ ok: true });
222
- return validation;
223
- }
224
-
225
- /**
226
- * Resolve the maintainability kernel version from the per-kind module so
227
- * the projection log header can name the kernel currently in scope. Reads
228
- * are best-effort — a sentinel `'0.0.0'` from the kernel-version
229
- * resolver (e.g. when typhonjs-escomplex is missing under a partial
230
- * install) collapses to `null` so the helper never injects a misleading
231
- * label into the log.
232
- *
233
- * Story #1973 / Task #1985 — this is the only call site outside the
234
- * `baselines/` tree that touches `kinds/maintainability.js` directly; the
235
- * import is the load-bearing acceptance hook for "no per-kind CLI spawn"
236
- * because referencing `kindModule.kernelVersion` proves the helper does
237
- * not need to fork a subprocess to learn what kernel it is running under.
238
- *
239
- * @param {object} kindModule - Per-kind maintainability module.
240
- * @returns {string | null}
241
- */
242
- function resolveKernelLabel(kindModule) {
243
- try {
244
- const v = kindModule?.kernelVersion?.();
245
- if (typeof v !== 'string' || v === '0.0.0') return null;
246
- return v;
247
- } catch {
248
- return null;
249
- }
250
- }
251
-
252
- /**
253
- * Emit the per-file MI ceiling projection advisory. Failure is non-fatal
254
- * (logged through `logger.warn`) — the projection is informational only,
255
- * and a missing baseline path skips the helper entirely.
256
- *
257
- * Story #1973 / Task #1985 — the projection no longer fans out a
258
- * per-kind `child_process.spawn(node check-maintainability.js)` to learn
259
- * the kernel context: the per-kind module under `baselines/kinds/` is
260
- * imported directly. The `kindModule` collaborator is injectable so unit
261
- * tests can pin the kernel label without touching the on-disk module.
262
- */
263
- export function emitMaintainabilityProjection({
264
- cwd,
265
- epicBranch,
266
- storyBranch,
267
- config,
268
- logger = DefaultLogger,
269
- getBaselines = defaultGetBaselines,
270
- projectMaintainabilityRegressions = defaultProjectMaintainabilityRegressions,
271
- formatMaintainabilityProjection = defaultFormatMaintainabilityProjection,
272
- kindModule = maintainabilityKind,
273
- }) {
274
- try {
275
- const baselinePath = getBaselines(config)?.maintainability?.path;
276
- if (!baselinePath) return;
277
- const projection = projectMaintainabilityRegressions({
278
- cwd,
279
- epicBranch,
280
- storyBranch,
281
- baselinePath,
282
- });
283
- const advisory = formatMaintainabilityProjection(projection);
284
- if (advisory) {
285
- const kernel = resolveKernelLabel(kindModule);
286
- if (kernel) {
287
- logger.info(
288
- `[close-validation] Pre-merge MI projection (kernel=${kernel}):`,
289
- );
290
- }
291
- for (const line of advisory.split('\n')) logger.info(line);
292
- } else if (projection.skipped) {
293
- logger.info(
294
- `[close-validation] Pre-merge MI projection skipped (${projection.skipped}).`,
295
- );
296
- }
297
- } catch (err) {
298
- logger.warn?.(
299
- `[close-validation] Pre-merge MI projection failed: ${err?.message ?? err}`,
300
- );
301
- }
302
- }
@@ -1,163 +0,0 @@
1
- /**
2
- * shared-checkout-guard.js — cross-epic contention guard for the merge
3
- * phase's `git checkout <epicBranch>` in the shared main checkout
4
- * (Story #4460).
5
- *
6
- * `story-close.js`'s merge phase (`runFinalizeMerge` in `merge-runner.js`)
7
- * runs `git checkout <epicBranch>` directly in the shared main repo
8
- * checkout — `close-inputs.js` resolves `cwd` to `PROJECT_ROOT`, not an
9
- * isolated worktree. The only exclusivity guard around that shared
10
- * checkout is the per-Epic `epic-merge-lock.js` mutex, which only
11
- * serializes concurrent runs for the SAME epic. Nothing stops a
12
- * DIFFERENT epic's concurrently-running `story-close.js` from treating
13
- * the same shared checkout as scratch space at the same time.
14
- *
15
- * This was observed live: while delivering Epic #4425 Stories #4427/#4428,
16
- * the shared checkout repeatedly carried uncommitted stray changes
17
- * belonging to a concurrently-running Epic #4405 delivery (parked on
18
- * `epic/4405` with dirty edits), which blocked the `git checkout epic/4425`
19
- * merge step with a raw `error: Your local changes ... would be
20
- * overwritten by checkout`.
21
- *
22
- * `assertSharedCheckoutAvailable` runs immediately before that checkout
23
- * and fails fast with an actionable, story-close-specific diagnostic
24
- * instead of letting the raw git error surface. It COMPOSES with (does
25
- * not replace) the per-Epic lock: by the time this guard runs, the
26
- * caller's own epic lock is already held (acquired around the whole
27
- * close flow in `story-close.js`), so this guard only inspects OTHER
28
- * epics' lock files plus the tree's overall dirty state — it never
29
- * contends with same-epic concurrent runs, which continue to serialize
30
- * solely via `withEpicMergeLock` before this guard ever executes.
31
- *
32
- * Breadth trade-off (deliberate): the foreign-lock probe keys on the
33
- * OTHER epic's per-epic merge lock, which that run holds for its WHOLE
34
- * close flow — so any overlapping story-close of another epic trips this
35
- * guard even when that run never actually touches the shared checkout
36
- * during the overlap. The refusal is deterministic and loud (throws with
37
- * a diagnostic naming the holder pid), never a deadlock (no waiting),
38
- * and stale/dead-pid foreign locks are ignored via the pid-liveness
39
- * probe. Narrowing the window (a dedicated checkout-phase lock) was
40
- * considered and rejected: the coarse refusal is rare, cheap to retry,
41
- * and far simpler than a second lock tier.
42
- */
43
-
44
- import { findForeignActiveEpicLock as defaultFindForeignActiveEpicLock } from '../../epic-merge-lock.js';
45
- import { gitSpawn as defaultGitSpawn } from '../../git-utils.js';
46
-
47
- const MAX_LISTED_DIRTY_FILES = 20;
48
-
49
- function describeForeignLock(foreign) {
50
- const acquired = Number.isFinite(foreign.acquiredAt)
51
- ? new Date(foreign.acquiredAt).toISOString()
52
- : 'an unknown time';
53
- return (
54
- `[story-close] shared-checkout guard: refusing to touch the shared main checkout — ` +
55
- `it is currently held by epic #${foreign.epicId}'s story-close merge phase ` +
56
- `(lock ${foreign.filePath}, pid ${foreign.pid}, acquired ${acquired}). ` +
57
- `Wait for that epic's story-close run to finish before retrying this merge. ` +
58
- `If you have independently confirmed that process is no longer running, remove ` +
59
- `the lock file by hand — never force a checkout past a live foreign lock. ` +
60
- `See .agents/rules/git-conventions.md § Shared-checkout contention (Story #4460).`
61
- );
62
- }
63
-
64
- function listDirtyFiles(porcelainOutput) {
65
- // `git status --porcelain` lines are `XY <path>` — a fixed 2-char status
66
- // column, a space, then the path. Strip only a trailing `\r` (Windows)
67
- // before slicing off that 3-char prefix; trimming the whole line first
68
- // would shift the slice offset whenever the status column starts with a
69
- // space (the common "unstaged modification" case), truncating the path.
70
- const lines = porcelainOutput
71
- .split('\n')
72
- .map((line) => line.replace(/\r$/, ''))
73
- .filter((line) => line.length > 0);
74
- const shown = lines
75
- .slice(0, MAX_LISTED_DIRTY_FILES)
76
- .map((line) => line.slice(3).trim() || line);
77
- const overflow = lines.length - shown.length;
78
- return overflow > 0
79
- ? `${shown.join(', ')}, … (+${overflow} more)`
80
- : shown.join(', ');
81
- }
82
-
83
- function describeDirtyCheckout({ cwd, epicId, currentBranch, dirtyFiles }) {
84
- return (
85
- `[story-close] shared-checkout guard: refusing to check out the epic branch for ` +
86
- `epic #${epicId} — the shared main checkout at ${cwd} is dirty (currently on ` +
87
- `\`${currentBranch}\`). Dirty files: ${dirtyFiles}. This usually means another ` +
88
- `epic's story-close run left uncommitted work in the shared checkout, or a prior ` +
89
- `run crashed mid-merge. Resolve manually (stash/commit/reset in ${cwd}) before ` +
90
- `retrying. See .agents/rules/git-conventions.md § Shared-checkout contention ` +
91
- `(Story #4460).`
92
- );
93
- }
94
-
95
- /**
96
- * Fail fast when the shared main checkout is not safely available for this
97
- * epic's merge-phase `git checkout <epicBranch>` — either because another
98
- * epic's story-close merge phase currently holds it (a live foreign lock),
99
- * or because it is simply dirty (regardless of whose branch is checked
100
- * out). Silent no-op when the checkout is clean and uncontended.
101
- *
102
- * @param {{
103
- * cwd: string,
104
- * epicId: number|string,
105
- * gitSpawn?: typeof defaultGitSpawn,
106
- * findForeignActiveEpicLock?: typeof defaultFindForeignActiveEpicLock,
107
- * }} opts
108
- * @throws {Error} with an actionable, story-close-specific diagnostic.
109
- */
110
- /**
111
- * Foreign-lock-only variant for the RESUME merge path (Story #4460
112
- * follow-up): a resume legitimately re-enters a shared checkout that is
113
- * dirty with THIS story's own in-progress merge, so the dirty-tree half
114
- * of `assertSharedCheckoutAvailable` would false-positive there. The
115
- * cross-epic hazard — another epic's live merge phase holding the
116
- * checkout — still applies and is the only probe this variant runs.
117
- */
118
- export function assertNoForeignEpicLock({
119
- cwd,
120
- epicId,
121
- findForeignActiveEpicLock = defaultFindForeignActiveEpicLock,
122
- }) {
123
- const foreign = findForeignActiveEpicLock(epicId, { repoRoot: cwd });
124
- if (foreign) {
125
- throw new Error(describeForeignLock(foreign));
126
- }
127
- }
128
-
129
- export function assertSharedCheckoutAvailable({
130
- cwd,
131
- epicId,
132
- gitSpawn = defaultGitSpawn,
133
- findForeignActiveEpicLock = defaultFindForeignActiveEpicLock,
134
- }) {
135
- const foreign = findForeignActiveEpicLock(epicId, { repoRoot: cwd });
136
- if (foreign) {
137
- throw new Error(describeForeignLock(foreign));
138
- }
139
-
140
- const statusRes = gitSpawn(cwd, 'status', '--porcelain');
141
- if (statusRes.status !== 0) {
142
- // Can't determine dirtiness from here — let the downstream checkout
143
- // surface whatever git itself reports rather than guessing.
144
- return;
145
- }
146
- const porcelain = statusRes.stdout || '';
147
- if (porcelain.trim().length === 0) return;
148
-
149
- const branchRes = gitSpawn(cwd, 'rev-parse', '--abbrev-ref', 'HEAD');
150
- const currentBranch =
151
- branchRes.status === 0
152
- ? (branchRes.stdout || '').trim() || 'unknown'
153
- : 'unknown';
154
-
155
- throw new Error(
156
- describeDirtyCheckout({
157
- cwd,
158
- epicId,
159
- currentBranch,
160
- dirtyFiles: listDirtyFiles(porcelain),
161
- }),
162
- );
163
- }