mandrel 1.93.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/.agents/README.md +59 -73
  2. package/.agents/agents/acceptance-critic.md +129 -0
  3. package/.agents/agents/story-worker.md +161 -0
  4. package/.agents/docs/SDLC.md +489 -1285
  5. package/.agents/docs/agentrc-reference.json +177 -67
  6. package/.agents/docs/configuration.md +108 -136
  7. package/.agents/docs/execution-reference.md +44 -22
  8. package/.agents/docs/quality-gates.md +13 -19
  9. package/.agents/docs/workflows.md +3 -3
  10. package/.agents/instructions.md +107 -108
  11. package/.agents/rules/ci-remediation.md +8 -12
  12. package/.agents/rules/git-conventions-reference.md +224 -0
  13. package/.agents/rules/git-conventions.md +42 -223
  14. package/.agents/rules/security-baseline.md +5 -0
  15. package/.agents/rules/testing-standards.md +106 -13
  16. package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
  17. package/.agents/schemas/agentrc.schema.json +71 -201
  18. package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
  19. package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
  20. package/.agents/schemas/risk-verdict.schema.json +0 -13
  21. package/.agents/scripts/acceptance-eval.js +62 -18
  22. package/.agents/scripts/agents-bootstrap-github.js +1 -1
  23. package/.agents/scripts/analyze-execution.js +1 -1
  24. package/.agents/scripts/audit-to-stories.js +7 -7
  25. package/.agents/scripts/boot-sweep.js +1 -1
  26. package/.agents/scripts/check-context-budget.js +62 -5
  27. package/.agents/scripts/check-lifecycle-lint.js +6 -9
  28. package/.agents/scripts/check-prepush-recovery.js +1 -1
  29. package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
  30. package/.agents/scripts/diagnose-friction.js +0 -6
  31. package/.agents/scripts/lib/Logger.js +6 -10
  32. package/.agents/scripts/lib/audit-suite/runner.js +2 -2
  33. package/.agents/scripts/lib/audit-suite/selector.js +5 -5
  34. package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
  35. package/.agents/scripts/lib/baselines/kernel.js +206 -18
  36. package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -4
  37. package/.agents/scripts/lib/baselines/reader.js +1 -6
  38. package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
  39. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
  40. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +56 -18
  41. package/.agents/scripts/lib/checks/core-bare-clean.js +2 -2
  42. package/.agents/scripts/lib/checks/index.js +2 -1
  43. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +23 -21
  44. package/.agents/scripts/lib/cli/standard-args.js +13 -22
  45. package/.agents/scripts/lib/cli-args.js +16 -7
  46. package/.agents/scripts/lib/close-validation/gates.js +160 -22
  47. package/.agents/scripts/lib/config/acceptance-eval.js +52 -5
  48. package/.agents/scripts/lib/config/ci.js +6 -31
  49. package/.agents/scripts/lib/config/delivery-routing.js +103 -0
  50. package/.agents/scripts/lib/config/explain.js +57 -36
  51. package/.agents/scripts/lib/config/limits.js +17 -58
  52. package/.agents/scripts/lib/config/paths.js +0 -2
  53. package/.agents/scripts/lib/config/quality.js +1 -1
  54. package/.agents/scripts/lib/config/runners.js +17 -50
  55. package/.agents/scripts/lib/config/temp-paths.js +19 -14
  56. package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
  57. package/.agents/scripts/lib/config-resolver.js +3 -8
  58. package/.agents/scripts/lib/config-settings-schema-delivery.js +46 -136
  59. package/.agents/scripts/lib/config-settings-schema-quality.js +17 -14
  60. package/.agents/scripts/lib/config-settings-schema.js +52 -38
  61. package/.agents/scripts/lib/dependency-parser.js +3 -2
  62. package/.agents/scripts/lib/doc-tiers.js +39 -4
  63. package/.agents/scripts/lib/duplicate-search.js +211 -41
  64. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
  65. package/.agents/scripts/lib/findings/promote-finding.js +5 -5
  66. package/.agents/scripts/lib/framework-version.js +2 -3
  67. package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
  68. package/.agents/scripts/lib/git-branch-lifecycle.js +17 -22
  69. package/.agents/scripts/lib/git-utils.js +32 -6
  70. package/.agents/scripts/lib/github/framework-repo.js +6 -0
  71. package/.agents/scripts/lib/label-constants.js +10 -23
  72. package/.agents/scripts/lib/label-taxonomy.js +9 -43
  73. package/.agents/scripts/lib/observability/active-story-env.js +112 -3
  74. package/.agents/scripts/lib/observability/hook-heartbeat.js +187 -0
  75. package/.agents/scripts/lib/observability/source-classifier.js +3 -3
  76. package/.agents/scripts/lib/observability/tool-trace-hook.js +15 -4
  77. package/.agents/scripts/lib/onboard/init-tail.js +1 -3
  78. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +111 -0
  79. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +32 -4
  80. package/.agents/scripts/lib/orchestration/audit-lens-routing.js +128 -0
  81. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +273 -0
  82. package/.agents/scripts/lib/orchestration/ceremony-routing.js +204 -0
  83. package/.agents/scripts/lib/orchestration/code-review.js +20 -268
  84. package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
  85. package/.agents/scripts/lib/orchestration/consolidation-precondition.js +1 -1
  86. package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
  87. package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
  88. package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
  89. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
  90. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +8 -8
  91. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +2 -2
  92. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
  93. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +17 -43
  94. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
  95. package/.agents/scripts/lib/orchestration/merge-block-class.js +1 -1
  96. package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
  97. package/.agents/scripts/lib/orchestration/plan-context.js +248 -266
  98. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +3 -2
  99. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +1 -1
  100. package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
  101. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +61 -0
  102. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +97 -0
  103. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +223 -854
  104. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +361 -0
  105. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +35 -108
  106. package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
  107. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
  108. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +14 -14
  109. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
  110. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/risk-verdict.js +3 -4
  111. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +2 -2
  112. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +8 -20
  113. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +3 -2
  114. package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
  115. package/.agents/scripts/lib/orchestration/preflight-cache.js +5 -5
  116. package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
  117. package/.agents/scripts/lib/orchestration/resolve-plan-run.js +155 -0
  118. package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
  119. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +8 -8
  120. package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
  121. package/.agents/scripts/lib/orchestration/review-depth.js +26 -12
  122. package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
  123. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
  124. package/.agents/scripts/lib/orchestration/run-epilogue.js +426 -0
  125. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +1 -1
  126. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +1 -0
  127. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +95 -41
  128. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +16 -13
  129. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +40 -0
  130. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +11 -3
  131. package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
  132. package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
  133. package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
  134. package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
  135. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
  136. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +15 -12
  137. package/.agents/scripts/lib/orchestration/story-follow-ups.js +237 -0
  138. package/.agents/scripts/lib/orchestration/story-init-remote.js +47 -0
  139. package/.agents/scripts/lib/orchestration/story-plan-state.js +48 -0
  140. package/.agents/scripts/lib/orchestration/{epic-runner → story-progress}/story-run-progress-writer.js +3 -3
  141. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
  142. package/.agents/scripts/lib/orchestration/task-body-validator.js +8 -18
  143. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +11 -61
  144. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +189 -373
  145. package/.agents/scripts/lib/orchestration/ticket-validator.js +3 -8
  146. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +0 -25
  147. package/.agents/scripts/lib/orchestration/ticketing/reads.js +29 -26
  148. package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -5
  149. package/.agents/scripts/lib/planning-corpus.js +16 -11
  150. package/.agents/scripts/lib/preflight-runner.js +2 -2
  151. package/.agents/scripts/lib/provider-factory.js +1 -1
  152. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
  153. package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +36 -0
  154. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
  155. package/.agents/scripts/lib/story-adjacency.js +11 -14
  156. package/.agents/scripts/lib/story-body/story-body.js +124 -70
  157. package/.agents/scripts/lib/story-plan.js +2 -4
  158. package/.agents/scripts/lib/templates/decomposer-prompts.js +46 -45
  159. package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
  160. package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +26 -26
  161. package/.agents/scripts/lib/validation-evidence.js +1 -1
  162. package/.agents/scripts/lib/wave-runner/ready-set.js +6 -6
  163. package/.agents/scripts/lib/workspace-provisioner.js +1 -1
  164. package/.agents/scripts/lib/worktree/lifecycle/reap.js +5 -7
  165. package/.agents/scripts/lint-issue-body.js +71 -40
  166. package/.agents/scripts/mandrel-update-preflight.js +1 -1
  167. package/.agents/scripts/notify.js +4 -3
  168. package/.agents/scripts/plan-context.js +64 -74
  169. package/.agents/scripts/plan-persist.js +121 -280
  170. package/.agents/scripts/plan-run-epilogue.js +97 -0
  171. package/.agents/scripts/post-structured-comment.js +38 -0
  172. package/.agents/scripts/providers/github/issues.js +17 -33
  173. package/.agents/scripts/providers/github/mappers.js +0 -12
  174. package/.agents/scripts/providers/github/tickets.js +2 -5
  175. package/.agents/scripts/resolve-plan-run.js +117 -0
  176. package/.agents/scripts/signals-view.js +24 -19
  177. package/.agents/scripts/single-story-close.js +11 -14
  178. package/.agents/scripts/single-story-confirm-merge.js +39 -23
  179. package/.agents/scripts/single-story-init.js +29 -20
  180. package/.agents/scripts/stories-wave-tick.js +6 -6
  181. package/.agents/scripts/story-plan.js +26 -47
  182. package/.agents/scripts/sync-claude-agents.js +165 -0
  183. package/.agents/scripts/update-ticket-state.js +37 -15
  184. package/.agents/skills/core/analyze-execution/SKILL.md +21 -18
  185. package/.agents/skills/core/api-and-interface-design/SKILL.md +5 -3
  186. package/.agents/skills/core/code-review-and-quality/SKILL.md +63 -7
  187. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +1 -1
  188. package/.agents/skills/core/gates-and-baselines/SKILL.md +149 -0
  189. package/.agents/skills/core/idea-refinement/SKILL.md +8 -14
  190. package/.agents/skills/core/qa-coverage-mapping/SKILL.md +7 -7
  191. package/.agents/skills/core/scope-triage/SKILL.md +28 -172
  192. package/.agents/skills/skills.index.json +8 -418
  193. package/.agents/starter-agentrc.json +0 -5
  194. package/.agents/templates/agent-protocol.md +9 -10
  195. package/.agents/workflows/audit-architecture.md +3 -3
  196. package/.agents/workflows/audit-clean-code.md +3 -3
  197. package/.agents/workflows/audit-dependencies.md +3 -3
  198. package/.agents/workflows/audit-devops.md +3 -3
  199. package/.agents/workflows/audit-documentation.md +5 -5
  200. package/.agents/workflows/audit-lighthouse.md +3 -3
  201. package/.agents/workflows/audit-navigability.md +3 -2
  202. package/.agents/workflows/audit-performance.md +3 -3
  203. package/.agents/workflows/audit-privacy.md +3 -3
  204. package/.agents/workflows/audit-quality.md +3 -3
  205. package/.agents/workflows/audit-security.md +3 -3
  206. package/.agents/workflows/audit-seo.md +3 -3
  207. package/.agents/workflows/audit-sre.md +3 -3
  208. package/.agents/workflows/audit-to-stories.md +20 -20
  209. package/.agents/workflows/audit-ux-ui.md +3 -3
  210. package/.agents/workflows/deliver.md +122 -131
  211. package/.agents/workflows/git-cleanup.md +3 -4
  212. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  213. package/.agents/workflows/helpers/acceptance-self-eval.md +52 -40
  214. package/.agents/workflows/helpers/code-review.md +70 -193
  215. package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +12 -14
  216. package/.agents/workflows/helpers/{single-story-deliver.md → deliver-story.md} +113 -139
  217. package/.agents/workflows/helpers/diagnose.md +10 -10
  218. package/.agents/workflows/helpers/mandrel-sync-config.md +1 -1
  219. package/.agents/workflows/helpers/parallel-tooling.md +1 -1
  220. package/.agents/workflows/helpers/signals.md +16 -16
  221. package/.agents/workflows/helpers/worktree-lifecycle.md +48 -64
  222. package/.agents/workflows/mandrel-update.md +3 -2
  223. package/.agents/workflows/plan.md +112 -145
  224. package/.agents/workflows/qa-assist.md +24 -30
  225. package/.agents/workflows/qa-explore.md +29 -38
  226. package/.agents/workflows/qa-run.md +2 -2
  227. package/README.md +9 -8
  228. package/docs/CHANGELOG.md +46 -0
  229. package/lib/cli/registry.js +95 -0
  230. package/lib/migrations/index.js +6 -5
  231. package/package.json +5 -3
  232. package/.agents/personas/architect.md +0 -113
  233. package/.agents/personas/devops-engineer.md +0 -38
  234. package/.agents/personas/engineer-mobile.md +0 -120
  235. package/.agents/personas/engineer-web.md +0 -111
  236. package/.agents/personas/engineer.md +0 -119
  237. package/.agents/personas/product.md +0 -94
  238. package/.agents/personas/project-manager.md +0 -114
  239. package/.agents/personas/qa-engineer.md +0 -95
  240. package/.agents/personas/refactorer.md +0 -113
  241. package/.agents/personas/security-engineer.md +0 -112
  242. package/.agents/personas/sre.md +0 -86
  243. package/.agents/personas/technical-writer.md +0 -101
  244. package/.agents/personas/ux-designer.md +0 -95
  245. package/.agents/schemas/dispatch-manifest.json +0 -232
  246. package/.agents/schemas/epic-spec.schema.json +0 -153
  247. package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
  248. package/.agents/scripts/dispatcher.js +0 -295
  249. package/.agents/scripts/epic-audit-prepare.js +0 -497
  250. package/.agents/scripts/epic-audit-recheck.js +0 -274
  251. package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
  252. package/.agents/scripts/epic-deliver-preflight.js +0 -462
  253. package/.agents/scripts/epic-deliver-prepare.js +0 -590
  254. package/.agents/scripts/epic-execute-record-wave.js +0 -449
  255. package/.agents/scripts/epic-plan-clarity.js +0 -211
  256. package/.agents/scripts/epic-plan-decompose.js +0 -54
  257. package/.agents/scripts/epic-plan-healthcheck.js +0 -581
  258. package/.agents/scripts/epic-plan-spec.js +0 -64
  259. package/.agents/scripts/epic-reconcile.js +0 -625
  260. package/.agents/scripts/lib/baseline-snapshot.js +0 -979
  261. package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
  262. package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
  263. package/.agents/scripts/lib/config/lifecycle.js +0 -40
  264. package/.agents/scripts/lib/config/preflight.js +0 -58
  265. package/.agents/scripts/lib/config/retro.js +0 -77
  266. package/.agents/scripts/lib/epic-merge-lock.js +0 -322
  267. package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
  268. package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
  269. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -660
  270. package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
  271. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
  272. package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
  273. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
  274. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
  275. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
  276. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
  277. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
  278. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
  279. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
  280. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
  281. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
  282. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
  283. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
  284. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
  285. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
  286. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
  287. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
  288. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -388
  289. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
  290. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
  291. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
  292. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
  293. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
  294. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
  295. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
  296. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
  297. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
  298. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
  299. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
  300. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
  301. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
  302. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
  303. package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
  304. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
  305. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
  306. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
  307. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
  308. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
  309. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
  310. package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
  311. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
  312. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
  313. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -384
  314. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
  315. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
  316. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
  317. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -278
  318. package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
  319. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
  320. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
  321. package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
  322. package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
  323. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
  324. package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
  325. package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
  326. package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
  327. package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
  328. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
  329. package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
  330. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
  331. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
  332. package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
  333. package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
  334. package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
  335. package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +0 -109
  336. package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
  337. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
  338. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
  339. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
  340. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
  341. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
  342. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
  343. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
  344. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
  345. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
  346. package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
  347. package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
  348. package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
  349. package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
  350. package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
  351. package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
  352. package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
  353. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
  354. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
  355. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
  356. package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
  357. package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
  358. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
  359. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
  360. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
  361. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -301
  362. package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
  363. package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
  364. package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
  365. package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
  366. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
  367. package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
  368. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
  369. package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
  370. package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
  371. package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
  372. package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
  373. package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
  374. package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
  375. package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
  376. package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
  377. package/.agents/scripts/lib/push-epic-retry.js +0 -209
  378. package/.agents/scripts/lib/spec/index.js +0 -36
  379. package/.agents/scripts/lib/spec/loader.js +0 -425
  380. package/.agents/scripts/lib/spec/state.js +0 -208
  381. package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
  382. package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
  383. package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
  384. package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
  385. package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
  386. package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
  387. package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
  388. package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
  389. package/.agents/scripts/lib/wave-runner/tick.js +0 -754
  390. package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
  391. package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
  392. package/.agents/scripts/lifecycle-emit.js +0 -510
  393. package/.agents/scripts/plan-critics.js +0 -199
  394. package/.agents/scripts/retro-run.js +0 -218
  395. package/.agents/scripts/standalone-feedback-rollup.js +0 -188
  396. package/.agents/scripts/story-close.js +0 -294
  397. package/.agents/scripts/story-init.js +0 -599
  398. package/.agents/scripts/story-phase.js +0 -369
  399. package/.agents/scripts/wave-tick.js +0 -335
  400. package/.agents/skills/core/baseline-refresh/SKILL.md +0 -181
  401. package/.agents/skills/core/ci-cd-and-automation/SKILL.md +0 -274
  402. package/.agents/skills/core/ci-cd-and-automation/examples.md +0 -211
  403. package/.agents/skills/core/code-simplification/SKILL.md +0 -389
  404. package/.agents/skills/core/context-engineering/SKILL.md +0 -309
  405. package/.agents/skills/core/context-engineering/examples.md +0 -58
  406. package/.agents/skills/core/deprecation-and-migration/SKILL.md +0 -250
  407. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
  408. package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
  409. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
  410. package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
  411. package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
  412. package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
  413. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -413
  414. package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
  415. package/.agents/skills/core/frontend-ui-engineering/SKILL.md +0 -357
  416. package/.agents/skills/core/hydrate-context/SKILL.md +0 -123
  417. package/.agents/skills/core/idea-refinement/examples.md +0 -437
  418. package/.agents/skills/core/idea-refinement/frameworks.md +0 -135
  419. package/.agents/skills/core/incremental-implementation/SKILL.md +0 -271
  420. package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +0 -213
  421. package/.agents/skills/core/knowledge-transfer/SKILL.md +0 -180
  422. package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +0 -117
  423. package/.agents/skills/core/performance-optimization/SKILL.md +0 -314
  424. package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +0 -277
  425. package/.agents/skills/core/property-based-testing/SKILL.md +0 -148
  426. package/.agents/skills/core/refactoring-discipline/SKILL.md +0 -111
  427. package/.agents/skills/core/shipping-and-launch/SKILL.md +0 -328
  428. package/.agents/skills/core/spec-driven-development/SKILL.md +0 -252
  429. package/.agents/skills/core/test-driven-development/SKILL.md +0 -475
  430. package/.agents/skills/core/using-agent-skills/SKILL.md +0 -232
  431. package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +0 -31
  432. package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +0 -51
  433. package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +0 -76
  434. package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +0 -31
  435. package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +0 -33
  436. package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +0 -31
  437. package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +0 -51
  438. package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +0 -54
  439. package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +0 -29
  440. package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +0 -30
  441. package/.agents/skills/stack/backend/stripe-integration/SKILL.md +0 -57
  442. package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +0 -9
  443. package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +0 -48
  444. package/.agents/skills/stack/frontend/astro/SKILL.md +0 -62
  445. package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +0 -30
  446. package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +0 -29
  447. package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +0 -50
  448. package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +0 -58
  449. package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +0 -34
  450. package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +0 -51
  451. package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +0 -199
  452. package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +0 -68
  453. package/.agents/workflows/helpers/deliver-epic-reference.md +0 -534
  454. package/.agents/workflows/helpers/deliver-epic.md +0 -955
  455. package/.agents/workflows/helpers/deliver-stories.md +0 -440
  456. package/.agents/workflows/helpers/epic-audit.md +0 -189
  457. package/.agents/workflows/helpers/epic-deliver-story.md +0 -427
  458. package/.agents/workflows/helpers/epic-testing.md +0 -125
  459. package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
  460. package/.agents/workflows/helpers/plan-epic.md +0 -351
  461. package/.agents/workflows/helpers/plan-story.md +0 -251
  462. package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
  463. /package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +0 -0
@@ -1,301 +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
- });
144
- const gateCount = Array.isArray(gates) ? gates.length : 0;
145
- // Story #2250 — emit `close-validate.start` only when both an epicId
146
- // and a storyId are present; the schema requires both, and unit
147
- // fixtures that drive the helper with `storyId: null` (legacy resume
148
- // tests) must continue to operate without lifecycle observability.
149
- const emitsActive = lifecycleEmitsActive({ epicId, storyId, bus });
150
- const startedAt = typeof now === 'function' ? now() : Date.now();
151
-
152
- // Emit the `close-validate.end` boundary, plus the `story.blocked`
153
- // cascade trigger on failure (Story #2250). No-op when emits are
154
- // inactive (legacy resume fixtures with `storyId: null`).
155
- const emitEnd = async ({ ok, extra = {}, blockedReason } = {}) => {
156
- if (!emitsActive) return;
157
- const endedAt = typeof now === 'function' ? now() : Date.now();
158
- await bus.emit('close-validate.end', {
159
- epicId,
160
- storyId,
161
- ok,
162
- gateCount,
163
- ...extra,
164
- durationMs: Math.max(0, endedAt - startedAt),
165
- });
166
- if (blockedReason) {
167
- await bus.emit('story.blocked', { storyId, reason: blockedReason });
168
- }
169
- };
170
-
171
- if (emitsActive) {
172
- await bus.emit('close-validate.start', { epicId, storyId });
173
- }
174
- let validation;
175
- try {
176
- validation = await runCloseValidation({
177
- cwd,
178
- worktreePath,
179
- gates,
180
- log: (m) => logger.info(m),
181
- onGateStart: (gate) => {
182
- // Only the canonical phase-enum gates drive `mark()`. Non-enum gates
183
- // (`typecheck`, `format`, `check-maintainability`) share the
184
- // currently-open phase's wall clock — a deliberate choice so the
185
- // `phase-timings` schema stays stable against future gate churn.
186
- if (phaseTimer && (gate.name === 'lint' || gate.name === 'test')) {
187
- phaseTimer.mark(gate.name);
188
- }
189
- },
190
- storyId,
191
- epicId,
192
- useEvidence,
193
- });
194
- } catch (err) {
195
- // Reach this branch only when `runCloseValidation` itself throws
196
- // (spawn-level catastrophe — the per-gate failures route through
197
- // `validation.failed` below). Emit the matching `close-validate.end`
198
- // with `ok:false` so the ledger always carries the boundary, then
199
- // re-throw.
200
- await emitEnd({
201
- ok: false,
202
- extra: { failedGate: 'runner-error' },
203
- blockedReason: 'close-validate-failed:runner-error',
204
- });
205
- throw err;
206
- }
207
- if (!validation.ok) {
208
- const { gate, status, cwd: gateCwd } = validation.failed[0];
209
- // Story #2250 — emit the boundary + `story.blocked` cascade BEFORE
210
- // throwing so the lifecycle ledger captures the boundary even when the
211
- // caller's try/catch swallows the throw, and the BlockerHandler
212
- // listener cascades to `epic.blocked`.
213
- await emitEnd({
214
- ok: false,
215
- extra: { failedGate: gate.name, exitCode: status },
216
- blockedReason: `close-validate-failed:${gate.name}`,
217
- });
218
- throw buildGateFailureError({ gate, status, gateCwd });
219
- }
220
- await emitEnd({ ok: true });
221
- return validation;
222
- }
223
-
224
- /**
225
- * Resolve the maintainability kernel version from the per-kind module so
226
- * the projection log header can name the kernel currently in scope. Reads
227
- * are best-effort — a sentinel `'0.0.0'` from the kernel-version
228
- * resolver (e.g. when typhonjs-escomplex is missing under a partial
229
- * install) collapses to `null` so the helper never injects a misleading
230
- * label into the log.
231
- *
232
- * Story #1973 / Task #1985 — this is the only call site outside the
233
- * `baselines/` tree that touches `kinds/maintainability.js` directly; the
234
- * import is the load-bearing acceptance hook for "no per-kind CLI spawn"
235
- * because referencing `kindModule.kernelVersion` proves the helper does
236
- * not need to fork a subprocess to learn what kernel it is running under.
237
- *
238
- * @param {object} kindModule - Per-kind maintainability module.
239
- * @returns {string | null}
240
- */
241
- function resolveKernelLabel(kindModule) {
242
- try {
243
- const v = kindModule?.kernelVersion?.();
244
- if (typeof v !== 'string' || v === '0.0.0') return null;
245
- return v;
246
- } catch {
247
- return null;
248
- }
249
- }
250
-
251
- /**
252
- * Emit the per-file MI ceiling projection advisory. Failure is non-fatal
253
- * (logged through `logger.warn`) — the projection is informational only,
254
- * and a missing baseline path skips the helper entirely.
255
- *
256
- * Story #1973 / Task #1985 — the projection no longer fans out a
257
- * per-kind `child_process.spawn(node check-maintainability.js)` to learn
258
- * the kernel context: the per-kind module under `baselines/kinds/` is
259
- * imported directly. The `kindModule` collaborator is injectable so unit
260
- * tests can pin the kernel label without touching the on-disk module.
261
- */
262
- export function emitMaintainabilityProjection({
263
- cwd,
264
- epicBranch,
265
- storyBranch,
266
- config,
267
- logger = DefaultLogger,
268
- getBaselines = defaultGetBaselines,
269
- projectMaintainabilityRegressions = defaultProjectMaintainabilityRegressions,
270
- formatMaintainabilityProjection = defaultFormatMaintainabilityProjection,
271
- kindModule = maintainabilityKind,
272
- }) {
273
- try {
274
- const baselinePath = getBaselines(config)?.maintainability?.path;
275
- if (!baselinePath) return;
276
- const projection = projectMaintainabilityRegressions({
277
- cwd,
278
- epicBranch,
279
- storyBranch,
280
- baselinePath,
281
- });
282
- const advisory = formatMaintainabilityProjection(projection);
283
- if (advisory) {
284
- const kernel = resolveKernelLabel(kindModule);
285
- if (kernel) {
286
- logger.info(
287
- `[close-validation] Pre-merge MI projection (kernel=${kernel}):`,
288
- );
289
- }
290
- for (const line of advisory.split('\n')) logger.info(line);
291
- } else if (projection.skipped) {
292
- logger.info(
293
- `[close-validation] Pre-merge MI projection skipped (${projection.skipped}).`,
294
- );
295
- }
296
- } catch (err) {
297
- logger.warn?.(
298
- `[close-validation] Pre-merge MI projection failed: ${err?.message ?? err}`,
299
- );
300
- }
301
- }
@@ -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
- }