mandrel 1.58.0 → 1.60.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 (319) hide show
  1. package/.agents/README.md +100 -98
  2. package/.agents/docs/SDLC.md +140 -141
  3. package/.agents/docs/configuration.md +16 -16
  4. package/.agents/docs/workflows.md +7 -8
  5. package/.agents/instructions.md +12 -11
  6. package/.agents/personas/architect.md +1 -1
  7. package/.agents/personas/product.md +1 -1
  8. package/.agents/personas/project-manager.md +14 -14
  9. package/.agents/personas/technical-writer.md +1 -1
  10. package/.agents/rules/changelog-style.md +5 -5
  11. package/.agents/rules/git-conventions.md +3 -3
  12. package/.agents/schemas/agentrc.schema.json +3 -3
  13. package/.agents/schemas/audit-rules.json +20 -0
  14. package/.agents/schemas/dispatch-manifest.json +4 -4
  15. package/.agents/schemas/epic-spec.schema.json +15 -45
  16. package/.agents/schemas/lifecycle/README.md +1 -1
  17. package/.agents/schemas/lifecycle/story.dispatch.end.schema.json +1 -1
  18. package/.agents/schemas/lifecycle/story.dispatch.start.schema.json +1 -1
  19. package/.agents/schemas/lifecycle/story.heartbeat.schema.json +1 -1
  20. package/.agents/schemas/validation-evidence.schema.json +1 -1
  21. package/.agents/scripts/README.md +1 -1
  22. package/.agents/scripts/acceptance-eval.js +21 -4
  23. package/.agents/scripts/acceptance-spec-reconciler.js +2 -2
  24. package/.agents/scripts/analyze-execution.js +2 -2
  25. package/.agents/scripts/assert-branch.js +1 -3
  26. package/.agents/scripts/audit-to-stories.js +1 -1
  27. package/.agents/scripts/bootstrap.js +1 -1
  28. package/.agents/scripts/check-arch-cycles.js +360 -0
  29. package/.agents/scripts/check-doc-links.js +2 -3
  30. package/.agents/scripts/coverage-capture.js +24 -3
  31. package/.agents/scripts/diagnose-friction.js +1 -1
  32. package/.agents/scripts/dispatcher.js +2 -2
  33. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  34. package/.agents/scripts/epic-audit-prepare.js +3 -3
  35. package/.agents/scripts/epic-deliver-note-intervention.js +2 -2
  36. package/.agents/scripts/epic-deliver-preflight.js +11 -9
  37. package/.agents/scripts/epic-deliver-prepare.js +13 -5
  38. package/.agents/scripts/epic-execute-record-wave.js +5 -5
  39. package/.agents/scripts/epic-plan-healthcheck.js +6 -10
  40. package/.agents/scripts/epic-plan-spec-validate.js +1 -1
  41. package/.agents/scripts/epic-reconcile.js +11 -29
  42. package/.agents/scripts/evidence-gate.js +2 -2
  43. package/.agents/scripts/generate-workflows-doc.js +1 -1
  44. package/.agents/scripts/git-rebase-and-resolve.js +1 -1
  45. package/.agents/scripts/hierarchy-gate.js +40 -24
  46. package/.agents/scripts/lib/ITicketingProvider.js +1 -1
  47. package/.agents/scripts/lib/audit-suite/selector.js +1 -1
  48. package/.agents/scripts/lib/audit-to-stories/seed-epic-from-findings.js +2 -2
  49. package/.agents/scripts/lib/baseline-snapshot.js +7 -7
  50. package/.agents/scripts/lib/baselines/kinds/coverage.js +33 -149
  51. package/.agents/scripts/lib/baselines/kinds/duplication.js +27 -116
  52. package/.agents/scripts/lib/baselines/kinds/kind-factory.js +192 -0
  53. package/.agents/scripts/lib/baselines/kinds/lighthouse.js +34 -133
  54. package/.agents/scripts/lib/baselines/kinds/maintainability.js +31 -124
  55. package/.agents/scripts/lib/baselines/kinds/mutation.js +25 -111
  56. package/.agents/scripts/lib/baselines/maintainability-baseline-io.js +59 -0
  57. package/.agents/scripts/lib/baselines/maintainability-baseline-save.js +37 -0
  58. package/.agents/scripts/lib/baselines/writer.js +1 -1
  59. package/.agents/scripts/lib/bdd-runner-detect.js +1 -1
  60. package/.agents/scripts/lib/bdd-scenario-scanner.js +3 -3
  61. package/.agents/scripts/lib/bootstrap/baselines-layout-migration.js +1 -1
  62. package/.agents/scripts/lib/bootstrap/branch-protection.js +1 -1
  63. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +1 -1
  64. package/.agents/scripts/lib/bootstrap/commit-push.js +2 -2
  65. package/.agents/scripts/lib/close-validation/commands.js +188 -0
  66. package/.agents/scripts/lib/close-validation/gates.js +235 -0
  67. package/.agents/scripts/lib/close-validation/process.js +101 -0
  68. package/.agents/scripts/lib/close-validation/projections/maintainability.js +1 -1
  69. package/.agents/scripts/lib/close-validation/runner.js +325 -0
  70. package/.agents/scripts/lib/close-validation/telemetry.js +70 -0
  71. package/.agents/scripts/lib/codebase-snapshot.js +1 -1
  72. package/.agents/scripts/lib/config/explain.js +1 -1
  73. package/.agents/scripts/lib/config/quality.js +6 -6
  74. package/.agents/scripts/lib/config/runners.js +2 -2
  75. package/.agents/scripts/lib/config/runtime.js +1 -1
  76. package/.agents/scripts/lib/config/temp-paths.js +2 -2
  77. package/.agents/scripts/lib/config-resolver.js +2 -5
  78. package/.agents/scripts/lib/config-settings-schema-delivery.js +2 -2
  79. package/.agents/scripts/lib/config-settings-schema-quality.js +1 -1
  80. package/.agents/scripts/lib/config-settings-schema.js +3 -3
  81. package/.agents/scripts/lib/coverage-capture.js +147 -4
  82. package/.agents/scripts/lib/cpu-pool.js +14 -0
  83. package/.agents/scripts/lib/crap-utils.js +6 -11
  84. package/.agents/scripts/lib/duplicate-search.js +1 -1
  85. package/.agents/scripts/lib/dynamic-workflow/capability.js +1 -1
  86. package/.agents/scripts/lib/dynamic-workflow/documentation-report-contract.js +87 -0
  87. package/.agents/scripts/lib/epic-plan-clarity.js +1 -1
  88. package/.agents/scripts/lib/epic-plan-ideation.js +1 -1
  89. package/.agents/scripts/lib/feedback-loop/memory-freshness.js +1 -1
  90. package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +1 -1
  91. package/.agents/scripts/lib/findings/classify-finding.js +1 -1
  92. package/.agents/scripts/lib/findings/promote-finding.js +10 -10
  93. package/.agents/scripts/lib/git-utils.js +24 -22
  94. package/.agents/scripts/lib/label-constants.js +3 -4
  95. package/.agents/scripts/lib/label-taxonomy.js +3 -8
  96. package/.agents/scripts/lib/maintainability-engine.js +1 -1
  97. package/.agents/scripts/lib/maintainability-utils.js +4 -187
  98. package/.agents/scripts/lib/observability/perf-report-readers.js +32 -23
  99. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +81 -7
  100. package/.agents/scripts/lib/orchestration/code-review.js +95 -82
  101. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +8 -9
  102. package/.agents/scripts/lib/orchestration/dependency-analyzer.js +3 -3
  103. package/.agents/scripts/lib/orchestration/detectors-phase.js +2 -2
  104. package/.agents/scripts/lib/orchestration/dispatch-engine.js +30 -38
  105. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +14 -37
  106. package/.agents/scripts/lib/orchestration/epic-cleanup.js +1 -1
  107. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +22 -22
  108. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +1 -1
  109. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +7 -21
  110. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +3 -3
  111. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +2 -2
  112. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +206 -58
  113. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +1 -1
  114. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +27 -3
  115. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +1 -1
  116. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +28 -8
  117. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +1 -1
  118. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +3 -3
  119. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +4 -4
  120. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +3 -3
  121. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +13 -41
  122. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +7 -7
  123. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +2 -3
  124. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +2 -8
  125. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +4 -4
  126. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +103 -0
  127. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +22 -64
  128. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +38 -76
  129. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +4 -4
  130. package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +10 -10
  131. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +8 -20
  132. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +7 -15
  133. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +72 -41
  134. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +2 -4
  135. package/.agents/scripts/lib/orchestration/file-assumptions.js +6 -5
  136. package/.agents/scripts/lib/orchestration/finalize/close-planning-tickets.js +1 -1
  137. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +2 -2
  138. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +1 -1
  139. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +144 -0
  140. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +1 -1
  141. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +3 -3
  142. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +1 -1
  143. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +1 -1
  144. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +1 -1
  145. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +1 -1
  146. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +1 -1
  147. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +1 -1
  148. package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +1 -1
  149. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +1 -1
  150. package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +8 -8
  151. package/.agents/scripts/lib/orchestration/manifest-builder.js +5 -5
  152. package/.agents/scripts/lib/orchestration/parked-follow-ons.js +2 -2
  153. package/.agents/scripts/lib/orchestration/plan-runner/plan-router.js +5 -5
  154. package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +3 -3
  155. package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +3 -3
  156. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +7 -7
  157. package/.agents/scripts/lib/orchestration/preflight-cache.js +36 -13
  158. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +1 -1
  159. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +1 -1
  160. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +2 -2
  161. package/.agents/scripts/lib/orchestration/retro-runner.js +3 -3
  162. package/.agents/scripts/lib/orchestration/review-depth.js +1 -1
  163. package/.agents/scripts/lib/orchestration/review-providers/codex.js +5 -60
  164. package/.agents/scripts/lib/orchestration/review-providers/native.js +7 -6
  165. package/.agents/scripts/lib/orchestration/review-providers/parse-findings.js +105 -0
  166. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +7 -59
  167. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +2 -4
  168. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +1 -1
  169. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +1 -1
  170. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +2 -4
  171. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +32 -35
  172. package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +1 -2
  173. package/.agents/scripts/lib/orchestration/spec-freshness.js +1 -1
  174. package/.agents/scripts/lib/orchestration/spec-renderer.js +36 -73
  175. package/.agents/scripts/lib/orchestration/spec-section-validator.js +1 -1
  176. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +451 -503
  177. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +8 -2
  178. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +47 -2
  179. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +2 -2
  180. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +1 -1
  181. package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +358 -54
  182. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +1 -1
  183. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +3 -2
  184. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +32 -5
  185. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +5 -18
  186. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +3 -3
  187. package/.agents/scripts/lib/orchestration/story-close-recovery.js +33 -16
  188. package/.agents/scripts/lib/orchestration/story-reachability.js +47 -0
  189. package/.agents/scripts/lib/orchestration/task-body-validator.js +6 -6
  190. package/.agents/scripts/lib/orchestration/ticket-lease.js +1 -1
  191. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +4 -35
  192. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +1 -10
  193. package/.agents/scripts/lib/orchestration/ticket-validator.js +25 -70
  194. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +44 -73
  195. package/.agents/scripts/lib/orchestration/ticketing/reads.js +16 -7
  196. package/.agents/scripts/lib/orchestration/ticketing/state.js +53 -439
  197. package/.agents/scripts/lib/orchestration/ticketing/transition.js +471 -0
  198. package/.agents/scripts/lib/orchestration/ticketing.js +0 -1
  199. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +3 -3
  200. package/.agents/scripts/lib/orchestration/wave-record-projection.js +2 -8
  201. package/.agents/scripts/lib/plan-phase-cleanup.js +1 -1
  202. package/.agents/scripts/lib/preflight-runner.js +1 -1
  203. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +4 -5
  204. package/.agents/scripts/lib/presentation/manifest-builder.js +28 -34
  205. package/.agents/scripts/lib/presentation/manifest-formatter.js +3 -4
  206. package/.agents/scripts/lib/presentation/manifest-helpers.js +1 -1
  207. package/.agents/scripts/lib/presentation/manifest-procedures.js +4 -4
  208. package/.agents/scripts/lib/presentation/manifest-render-waves.js +4 -23
  209. package/.agents/scripts/lib/presentation/manifest-renderer.js +1 -1
  210. package/.agents/scripts/lib/presentation/manifest-story-views.js +2 -11
  211. package/.agents/scripts/lib/project-root.js +17 -0
  212. package/.agents/scripts/lib/signals/schema.js +1 -1
  213. package/.agents/scripts/lib/spec/index.js +1 -1
  214. package/.agents/scripts/lib/spec/loader.js +2 -2
  215. package/.agents/scripts/lib/spec/state.js +7 -16
  216. package/.agents/scripts/lib/story-adjacency.js +76 -0
  217. package/.agents/scripts/lib/story-init/context-resolver.js +3 -3
  218. package/.agents/scripts/lib/story-init/state-transitioner.js +2 -2
  219. package/.agents/scripts/lib/story-init/task-graph-builder.js +7 -7
  220. package/.agents/scripts/lib/story-lifecycle.js +9 -9
  221. package/.agents/scripts/lib/story-plan.js +1 -1
  222. package/.agents/scripts/lib/templates/decomposer-prompts.js +59 -52
  223. package/.agents/scripts/lib/transpile.js +93 -0
  224. package/.agents/scripts/lib/wave-runner/tick.js +4 -153
  225. package/.agents/scripts/lib/workers/crap-worker.js +1 -1
  226. package/.agents/scripts/lib/workers/maintainability-report-worker.js +1 -1
  227. package/.agents/scripts/lib/worktree/lifecycle/creation.js +20 -2
  228. package/.agents/scripts/lib/worktree/lifecycle/force-drain.js +90 -0
  229. package/.agents/scripts/lib/worktree/lifecycle/reap.js +26 -8
  230. package/.agents/scripts/lib/worktree/node-modules-strategy.js +74 -0
  231. package/.agents/scripts/lifecycle-emit-story-dispatch.js +1 -1
  232. package/.agents/scripts/lifecycle-emit.js +1 -1
  233. package/.agents/scripts/providers/github/board-add.js +1 -1
  234. package/.agents/scripts/providers/github/errors.js +1 -1
  235. package/.agents/scripts/providers/github/mappers.js +2 -2
  236. package/.agents/scripts/providers/github/tickets.js +114 -10
  237. package/.agents/scripts/resync-status-column.js +1 -1
  238. package/.agents/scripts/retro-run.js +2 -2
  239. package/.agents/scripts/run-lint.js +10 -1
  240. package/.agents/scripts/run-tests.js +24 -4
  241. package/.agents/scripts/single-story-init.js +1 -1
  242. package/.agents/scripts/stories-wave-tick.js +13 -10
  243. package/.agents/scripts/story-close.js +1 -1
  244. package/.agents/scripts/story-init.js +162 -26
  245. package/.agents/scripts/story-phase.js +5 -5
  246. package/.agents/scripts/story-plan.js +3 -3
  247. package/.agents/scripts/sync-branch-from-base.js +2 -2
  248. package/.agents/scripts/validate-docs-freshness.js +1 -1
  249. package/.agents/scripts/wave-tick.js +1 -1
  250. package/.agents/skills/core/analyze-execution/SKILL.md +2 -2
  251. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +21 -26
  252. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +23 -56
  253. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +4 -4
  254. package/.agents/skills/core/hydrate-context/SKILL.md +2 -2
  255. package/.agents/skills/core/idea-refinement/SKILL.md +4 -4
  256. package/.agents/skills/core/knowledge-transfer/SKILL.md +2 -2
  257. package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +1 -1
  258. package/.agents/skills/core/scope-triage/SKILL.md +9 -10
  259. package/.agents/skills/core/using-agent-skills/SKILL.md +1 -1
  260. package/.agents/skills/skills.index.json +7 -7
  261. package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +1 -1
  262. package/.agents/templates/agent-protocol.md +2 -2
  263. package/.agents/workflows/agents-update.md +2 -2
  264. package/.agents/workflows/audit-architecture.md +2 -2
  265. package/.agents/workflows/audit-clean-code.md +2 -2
  266. package/.agents/workflows/audit-dependencies.md +1 -1
  267. package/.agents/workflows/audit-devops.md +1 -1
  268. package/.agents/workflows/audit-documentation.md +226 -0
  269. package/.agents/workflows/audit-lighthouse.md +1 -1
  270. package/.agents/workflows/audit-performance.md +2 -2
  271. package/.agents/workflows/audit-privacy.md +1 -1
  272. package/.agents/workflows/audit-quality.md +2 -2
  273. package/.agents/workflows/audit-security.md +2 -2
  274. package/.agents/workflows/audit-seo.md +1 -1
  275. package/.agents/workflows/audit-sre.md +1 -1
  276. package/.agents/workflows/audit-to-stories.md +10 -10
  277. package/.agents/workflows/audit-ux-ui.md +1 -1
  278. package/.agents/workflows/deliver.md +85 -0
  279. package/.agents/workflows/explain.md +3 -3
  280. package/.agents/workflows/git-merge-pr.md +1 -1
  281. package/.agents/workflows/git-pr-all.md +13 -10
  282. package/.agents/workflows/git-push.md +6 -3
  283. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  284. package/.agents/workflows/helpers/acceptance-self-eval.md +1 -1
  285. package/.agents/workflows/helpers/code-review.md +5 -5
  286. package/.agents/workflows/{epic-deliver.md → helpers/deliver-epic.md} +59 -66
  287. package/.agents/workflows/{story-deliver.md → helpers/deliver-stories.md} +25 -25
  288. package/.agents/workflows/helpers/diagnose.md +1 -1
  289. package/.agents/workflows/helpers/epic-audit.md +6 -6
  290. package/.agents/workflows/helpers/epic-deliver-story.md +28 -39
  291. package/.agents/workflows/helpers/epic-plan-decompose.md +23 -23
  292. package/.agents/workflows/helpers/epic-plan-spec.md +6 -6
  293. package/.agents/workflows/helpers/epic-testing.md +3 -3
  294. package/.agents/workflows/helpers/parallel-tooling.md +1 -1
  295. package/.agents/workflows/{epic-plan.md → helpers/plan-epic.md} +84 -84
  296. package/.agents/workflows/{story-plan.md → helpers/plan-story.md} +43 -43
  297. package/.agents/workflows/helpers/signals.md +1 -1
  298. package/.agents/workflows/helpers/single-story-deliver.md +12 -11
  299. package/.agents/workflows/helpers/worktree-lifecycle.md +18 -18
  300. package/.agents/workflows/onboard.md +21 -20
  301. package/.agents/workflows/plan.md +89 -0
  302. package/.agents/workflows/qa-explore.md +1 -1
  303. package/.agents/workflows/qa-run-harness.md +1 -1
  304. package/README.md +17 -20
  305. package/docs/CHANGELOG.md +1149 -0
  306. package/lib/cli/__tests__/update-changelog-surface.test.js +357 -0
  307. package/lib/cli/__tests__/update-reexec.test.js +513 -0
  308. package/lib/cli/init.js +338 -0
  309. package/lib/cli/update.js +413 -52
  310. package/package.json +3 -1
  311. package/.agents/scripts/lib/auto-refresh-baselines.js +0 -308
  312. package/.agents/scripts/lib/close-validation.js +0 -897
  313. package/.agents/scripts/lib/orchestration/cascade-grouping.js +0 -275
  314. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter.js +0 -69
  315. package/.agents/scripts/lib/orchestration/reconciler.js +0 -137
  316. package/.agents/scripts/lib/orchestration/story-close/format-autofix-scoped.js +0 -221
  317. package/.agents/scripts/lib/orchestration/story-close/format-autofix-shared.js +0 -123
  318. package/.agents/scripts/lib/task-utils.js +0 -26
  319. package/.agents/scripts/story-deliver-prepare.js +0 -267
@@ -0,0 +1,325 @@
1
+ /**
2
+ * close-validation/runner.js — The `runCloseValidation` orchestrator.
3
+ *
4
+ * Runs typecheck, lint, test, format check, and maintainability/coverage/
5
+ * CRAP regression checks before the story merge so drift is caught in the
6
+ * worktree rather than at pre-push time on the Epic branch. All gates
7
+ * inherit stdio so the operator sees the raw output; the returned summary
8
+ * surfaces actionable hints on failure.
9
+ */
10
+
11
+ import {
12
+ recordPass as defaultRecordPass,
13
+ shouldSkip as defaultShouldSkip,
14
+ hashCommandConfig,
15
+ } from '../validation-evidence.js';
16
+ import {
17
+ isFormatterEligible,
18
+ listChangedFilesForFormatGate,
19
+ } from './commands.js';
20
+ import { DEFAULT_GATES, partitionGates } from './gates.js';
21
+ import { defaultGateRunner } from './process.js';
22
+ import { defaultGetHeadSha } from './projections/head-sha.js';
23
+
24
+ /** @typedef {import('./gates.js').Gate} Gate */
25
+
26
+ function applyChangedFileScope({ gate, spawnCwd, log }) {
27
+ if (!gate.changedFileScope) {
28
+ return { gate, cmd: gate.cmd, args: gate.args, skip: false };
29
+ }
30
+ const changedFiles = listChangedFilesForFormatGate({
31
+ cwd: spawnCwd,
32
+ baseRef: gate.changedFileScope.baseRef,
33
+ });
34
+ // Filter to the formatter-eligible subset before deciding to skip. A
35
+ // non-empty diff that contains zero formatter-eligible files (e.g. a
36
+ // docs-only Story) must take the skip path, not invoke biome with only
37
+ // ineligible paths — biome reports "No files were processed" and exits 1
38
+ // in that case (Story #3410).
39
+ const eligibleFiles = changedFiles.filter(isFormatterEligible);
40
+ if (eligibleFiles.length === 0) {
41
+ log(
42
+ `[close-validation] ⏭ ${gate.name} skipped (no formatter-eligible changed files)`,
43
+ );
44
+ return { gate, cmd: gate.cmd, args: gate.args, skip: true };
45
+ }
46
+ const args =
47
+ gate.args[gate.args.length - 1] === '.'
48
+ ? gate.args.slice(0, -1)
49
+ : gate.args;
50
+ log(
51
+ `[close-validation] ↳ ${gate.name} scoped to ${eligibleFiles.length} formatter-eligible changed file(s) from ${gate.changedFileScope.baseRef}...HEAD`,
52
+ );
53
+ return {
54
+ gate,
55
+ cmd: gate.cmd,
56
+ args: [...args, ...eligibleFiles],
57
+ skip: false,
58
+ };
59
+ }
60
+
61
+ /**
62
+ * Run every gate sequentially. Stops collecting after the first failure but
63
+ * still returns a summary so the caller decides how to surface the result.
64
+ *
65
+ * Worktree locality (Story #1120): when `worktreePath` is supplied, every
66
+ * gate runner is spawned with `cwd: worktreePath` so the gate sees the
67
+ * Story branch's post-rebase tree. Evidence reads/writes still key against
68
+ * `cwd` (the main checkout) because the per-Epic temp tree lives under
69
+ * the main `.git/`. Failure messages name the worktree path.
70
+ *
71
+ * Evidence-aware: when both `storyId` and `epicId` are provided and
72
+ * `useEvidence !== false`, each gate consults `validation-evidence
73
+ * .shouldSkip()` against current HEAD + the gate's command-config hash. A
74
+ * matching record skips the gate; a successful run is recorded so the
75
+ * next caller in the local hot path can skip in turn.
76
+ *
77
+ * `onGateStart` is invoked immediately before each gate's runner spawn.
78
+ * story-close uses it to drive `phaseTimer.mark(...)` for per-gate
79
+ * wall-clock telemetry. Errors thrown from the hook propagate.
80
+ *
81
+ * @param {{
82
+ * cwd: string,
83
+ * worktreePath?: string,
84
+ * gates?: Gate[],
85
+ * runner?: (cmd: string, args: string[], opts: { cwd: string, signal?: AbortSignal, gateName?: string, log?: (m: string) => void }) => Promise<{ status: number }> | { status: number },
86
+ * log?: (m: string) => void,
87
+ * onGateStart?: (gate: Gate) => void,
88
+ * storyId?: number|null,
89
+ * epicId?: number|null,
90
+ * useEvidence?: boolean,
91
+ * evidenceClock?: () => number,
92
+ * getHeadSha?: (cwd: string) => string|null,
93
+ * recordPass?: typeof defaultRecordPass,
94
+ * shouldSkip?: typeof defaultShouldSkip,
95
+ * }} opts
96
+ * @returns {{ ok: boolean, failed: Array<{ gate: Gate, status: number, cwd: string }>, skipped: Array<{ gate: Gate, reason: string }> }}
97
+ */
98
+ export async function runCloseValidation({
99
+ cwd,
100
+ worktreePath,
101
+ gates = DEFAULT_GATES,
102
+ runner = defaultGateRunner,
103
+ log = () => {},
104
+ onGateStart,
105
+ storyId = null,
106
+ epicId = null,
107
+ useEvidence = true,
108
+ evidenceClock = () => Date.now(),
109
+ getHeadSha = (resolvedCwd) => defaultGetHeadSha(resolvedCwd),
110
+ recordPass = defaultRecordPass,
111
+ shouldSkip = defaultShouldSkip,
112
+ } = {}) {
113
+ const failed = [];
114
+ const skipped = [];
115
+ const evidenceActive = useEvidence && storyId != null && epicId != null;
116
+ // Evidence keys against the main checkout's HEAD because the per-Epic
117
+ // evidence file lives under the main `.git/`. Gate spawn, in contrast,
118
+ // runs in the worktree when one is supplied — that's the whole point of
119
+ // Story #1120.
120
+ const spawnCwd = worktreePath ?? cwd;
121
+ const headSha = evidenceActive ? getHeadSha(spawnCwd) : null;
122
+
123
+ // Helper closures so the parallel and serial passes share evidence
124
+ // bookkeeping bit-for-bit.
125
+
126
+ /** Returns a `{ skip: true }` verdict when evidence makes the gate redundant. */
127
+ const evidenceVerdict = (gate, configHash) => {
128
+ if (!(evidenceActive && headSha)) return { skip: false };
129
+ const verdict = shouldSkip(
130
+ {
131
+ storyId,
132
+ gateName: gate.name,
133
+ currentSha: headSha,
134
+ configHash,
135
+ inputFingerprint: gate.inputFingerprint ?? null,
136
+ },
137
+ { cwd, epicId },
138
+ );
139
+ if (verdict.skip) {
140
+ const tsHint = verdict.record?.timestamp
141
+ ? ` recorded ${verdict.record.timestamp}`
142
+ : '';
143
+ log(
144
+ `[close-validation] ⏭ ${gate.name} skipped (${verdict.reason}: SHA=${headSha.slice(0, 7)}${tsHint})`,
145
+ );
146
+ }
147
+ return verdict;
148
+ };
149
+
150
+ const recordIfActive = (gate, configHash, durationMs) => {
151
+ if (!(evidenceActive && headSha)) return;
152
+ try {
153
+ recordPass(
154
+ {
155
+ storyId,
156
+ gateName: gate.name,
157
+ sha: headSha,
158
+ configHash,
159
+ exitCode: 0,
160
+ durationMs,
161
+ inputFingerprint: gate.inputFingerprint ?? null,
162
+ },
163
+ { cwd, epicId },
164
+ );
165
+ } catch (err) {
166
+ log(
167
+ `[close-validation] ⚠ failed to record evidence for ${gate.name}: ${err?.message ?? err}`,
168
+ );
169
+ }
170
+ };
171
+
172
+ /**
173
+ * Run a single gate. When `gate.run` is a function the gate executes
174
+ * **in process** (Story #1973 / Task #1984 — per-kind baseline gates
175
+ * removed their `child_process.spawn(node check-<kind>.js)` arm and
176
+ * call `compare(head, base)` directly). The `run` callable receives
177
+ * the same `(cmd, args, opts)` argv shape as `runner` so it slots into
178
+ * the existing contract without churn at the runner boundary.
179
+ * Otherwise the supplied `runner` is used (default: spawn).
180
+ *
181
+ * @returns {Promise<{ status: number }>}
182
+ */
183
+ const dispatchGate = async (gate, signal) => {
184
+ log(
185
+ `[close-validation] ▶ ${gate.name}${worktreePath ? ` (cwd=${worktreePath})` : ''}`,
186
+ );
187
+ if (typeof onGateStart === 'function') onGateStart(gate);
188
+ const dispatcher = typeof gate.run === 'function' ? gate.run : runner;
189
+ const result = await dispatcher(gate.cmd, gate.args, {
190
+ cwd: spawnCwd,
191
+ gateName: gate.name,
192
+ log,
193
+ signal,
194
+ ...(gate.env ? { env: gate.env } : {}),
195
+ });
196
+ return { status: result?.status ?? 1 };
197
+ };
198
+
199
+ const { independent, serial } = partitionGates(gates);
200
+
201
+ // ── Phase 1: independent gates in parallel ──────────────────────────
202
+ // First non-zero exit pins `firstFailure` and aborts every in-flight
203
+ // sibling via SIGTERM. Other gates' results are still awaited (so we
204
+ // never leak children) but their non-zero status is intentionally
205
+ // dropped: only one error surfaces.
206
+ const ac = new AbortController();
207
+ let firstIndepFailure = null;
208
+
209
+ const indepTasks = independent.map(async (gate) => {
210
+ let execution;
211
+ try {
212
+ execution = applyChangedFileScope({ gate, spawnCwd, log });
213
+ } catch (err) {
214
+ if (!firstIndepFailure) {
215
+ firstIndepFailure = { gate, status: 1, cwd: spawnCwd };
216
+ log(
217
+ `[close-validation] ✖ ${gate.name} failed to resolve changed-file scope: ${err?.message ?? err}`,
218
+ );
219
+ ac.abort();
220
+ }
221
+ return;
222
+ }
223
+ if (execution.skip) {
224
+ skipped.push({ gate, reason: 'no-changed-files' });
225
+ return;
226
+ }
227
+ const configHash = hashCommandConfig({
228
+ cmd: execution.cmd,
229
+ args: execution.args,
230
+ cwd: spawnCwd,
231
+ });
232
+ const verdict = evidenceVerdict(gate, configHash);
233
+ if (verdict.skip) {
234
+ skipped.push({ gate, reason: verdict.reason });
235
+ return;
236
+ }
237
+ const startedAt = evidenceActive ? evidenceClock() : 0;
238
+ let result;
239
+ try {
240
+ result = await dispatchGate(
241
+ { ...gate, cmd: execution.cmd, args: execution.args },
242
+ ac.signal,
243
+ );
244
+ } catch (err) {
245
+ result = { status: 1, error: err };
246
+ }
247
+ if (result.status !== 0) {
248
+ if (!firstIndepFailure) {
249
+ firstIndepFailure = { gate, status: result.status, cwd: spawnCwd };
250
+ ac.abort();
251
+ }
252
+ return;
253
+ }
254
+ log(`[close-validation] ✓ ${gate.name}`);
255
+ recordIfActive(
256
+ gate,
257
+ configHash,
258
+ evidenceActive ? evidenceClock() - startedAt : 0,
259
+ );
260
+ });
261
+
262
+ await Promise.all(indepTasks);
263
+
264
+ if (firstIndepFailure) {
265
+ failed.push(firstIndepFailure);
266
+ log(
267
+ `[close-validation] ✖ ${firstIndepFailure.gate.name} failed (exit ${firstIndepFailure.status}) in ${spawnCwd}`,
268
+ );
269
+ if (firstIndepFailure.gate.hint) {
270
+ log(`[close-validation] hint: ${firstIndepFailure.gate.hint}`);
271
+ }
272
+ return { ok: false, failed, skipped };
273
+ }
274
+
275
+ // ── Phase 2: serial gates in declared order ─────────────────────────
276
+ for (const gate of serial) {
277
+ let execution;
278
+ try {
279
+ execution = applyChangedFileScope({ gate, spawnCwd, log });
280
+ } catch (err) {
281
+ failed.push({ gate, status: 1, cwd: spawnCwd });
282
+ log(
283
+ `[close-validation] ✖ ${gate.name} failed to resolve changed-file scope: ${err?.message ?? err}`,
284
+ );
285
+ if (gate.hint) log(`[close-validation] hint: ${gate.hint}`);
286
+ break;
287
+ }
288
+ if (execution.skip) {
289
+ skipped.push({ gate, reason: 'no-changed-files' });
290
+ continue;
291
+ }
292
+ const configHash = hashCommandConfig({
293
+ cmd: execution.cmd,
294
+ args: execution.args,
295
+ cwd: spawnCwd,
296
+ });
297
+ const verdict = evidenceVerdict(gate, configHash);
298
+ if (verdict.skip) {
299
+ skipped.push({ gate, reason: verdict.reason });
300
+ continue;
301
+ }
302
+ const startedAt = evidenceActive ? evidenceClock() : 0;
303
+ const result = await dispatchGate({
304
+ ...gate,
305
+ cmd: execution.cmd,
306
+ args: execution.args,
307
+ });
308
+ if (result.status !== 0) {
309
+ failed.push({ gate, status: result.status, cwd: spawnCwd });
310
+ log(
311
+ `[close-validation] ✖ ${gate.name} failed (exit ${result.status}) in ${spawnCwd}`,
312
+ );
313
+ if (gate.hint) log(`[close-validation] hint: ${gate.hint}`);
314
+ break;
315
+ }
316
+ log(`[close-validation] ✓ ${gate.name}`);
317
+ recordIfActive(
318
+ gate,
319
+ configHash,
320
+ evidenceActive ? evidenceClock() - startedAt : 0,
321
+ );
322
+ }
323
+
324
+ return { ok: failed.length === 0, failed, skipped };
325
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * close-validation/telemetry.js — gh-spawn telemetry emitter.
3
+ */
4
+
5
+ import { writeFile as defaultWriteFile } from 'node:fs/promises';
6
+ import { storyArtifactPath } from '../config/temp-paths.js';
7
+ import { getSpawnCount as defaultGetSpawnCount } from '../gh-exec.js';
8
+
9
+ /**
10
+ * Throw-away ghSpawnCount emitter (Story #1795 / Epic #1788).
11
+ *
12
+ * Writes the current `gh-exec` spawn counter to
13
+ * `temp/epic-<eid>/stories/story-<sid>/gh-spawn-count.json` so the
14
+ * `analyze-execution.js` child process can read it and emit a
15
+ * `ghSpawnCount` field on the `story-perf-summary` payload. The Story-
16
+ * close orchestrator calls this inside `runPostMergeClose` right before
17
+ * the perf-summary phase, capturing every `gh` invocation from preflight
18
+ * through the merge in one counter snapshot.
19
+ *
20
+ * @param {object} opts
21
+ * @param {number|string} opts.epicId
22
+ * @param {number|string} opts.storyId
23
+ * @param {object} [opts.config] - Resolved config bag so `tempRoot`
24
+ * resolution honours the consumer's configured path.
25
+ * @param {() => number} [opts.getSpawnCountFn=defaultGetSpawnCount] - Test seam.
26
+ * @param {typeof defaultWriteFile} [opts.writeFileFn=defaultWriteFile] - Test seam.
27
+ * @param {{ warn?: (s: string) => void }} [opts.logger] - Best-effort
28
+ * failure-path logger; never throws.
29
+ * @returns {Promise<{ status: 'ok'|'failed', path?: string, ghSpawnCount?: number, reason?: string }>}
30
+ */
31
+ export async function emitGhSpawnCount({
32
+ epicId,
33
+ storyId,
34
+ config,
35
+ getSpawnCountFn = defaultGetSpawnCount,
36
+ writeFileFn = defaultWriteFile,
37
+ logger,
38
+ } = {}) {
39
+ const eid = Number(epicId);
40
+ const sid = Number(storyId);
41
+ if (!Number.isInteger(eid) || eid < 1 || !Number.isInteger(sid) || sid < 1) {
42
+ return { status: 'failed', reason: 'invalid-ids' };
43
+ }
44
+ let ghSpawnCount;
45
+ try {
46
+ ghSpawnCount = getSpawnCountFn();
47
+ } catch (err) {
48
+ logger?.warn?.(
49
+ `[close-validation] gh-spawn-count read failed: ${err?.message ?? err}`,
50
+ );
51
+ return { status: 'failed', reason: 'counter-read-failed' };
52
+ }
53
+ const targetPath = storyArtifactPath(eid, sid, 'gh-spawn-count.json', config);
54
+ const payload = {
55
+ kind: 'gh-spawn-count',
56
+ epicId: eid,
57
+ storyId: sid,
58
+ ghSpawnCount,
59
+ capturedAt: new Date().toISOString(),
60
+ };
61
+ try {
62
+ await writeFileFn(targetPath, JSON.stringify(payload, null, 2));
63
+ return { status: 'ok', path: targetPath, ghSpawnCount };
64
+ } catch (err) {
65
+ logger?.warn?.(
66
+ `[close-validation] gh-spawn-count emit failed: ${err?.message ?? err}`,
67
+ );
68
+ return { status: 'failed', reason: 'write-failed' };
69
+ }
70
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * codebase-snapshot.js — Bounded structural view of the consumer repo.
3
3
  *
4
- * Story #2634 (sibling to #2635 spec-freshness). `/epic-plan` Phase 7
4
+ * Story #2634 (sibling to #2635 spec-freshness). `/plan` Phase 7
5
5
  * authors PRD + Tech Spec from documentation alone — `architecture.md`,
6
6
  * `data-dictionary.md`, `decisions.md`, `patterns.md`. When those docs
7
7
  * drift from the real source tree, the Architect persona cites modules
@@ -113,7 +113,7 @@ const KEY_MEANINGS = Object.freeze({
113
113
 
114
114
  // planning.*
115
115
  'planning.maxTickets':
116
- 'Upper bound on tickets a single /epic-plan run may create.',
116
+ 'Upper bound on tickets a single /plan run may create.',
117
117
  'planning.context.maxBytes':
118
118
  'Byte budget for the planning-context payload before summary mode kicks in.',
119
119
  'planning.context.summaryMode':
@@ -121,7 +121,7 @@ export const MAINTAINABILITY_GATE_DEFAULTS = Object.freeze({
121
121
  * --write` autofix spawn. The SIGKILL → exit 124 mapping mirrors
122
122
  * `gates.coverage.timeoutMs` (Story #2142).
123
123
  */
124
- export const FORMAT_AUTOFIX_DEFAULTS = Object.freeze({
124
+ const FORMAT_AUTOFIX_DEFAULTS = Object.freeze({
125
125
  timeoutMs: 60_000,
126
126
  });
127
127
 
@@ -259,7 +259,7 @@ export function resolveMaintainabilityCrap(
259
259
  * `targetDirs` + a scalar `tolerance` (when set) + scoping inherited
260
260
  * from `gateScoping`.
261
261
  */
262
- export function resolveMaintainabilityQuality(userBlock, gateScoping) {
262
+ function resolveMaintainabilityQuality(userBlock, gateScoping) {
263
263
  const defaults = MAINTAINABILITY_GATE_DEFAULTS;
264
264
  const scoping = {
265
265
  defaultScope: gateScoping?.scope ?? DEFAULT_GATE_SCOPING.scope,
@@ -321,7 +321,7 @@ function resolvePositiveIntegerMs(value, defaultMs) {
321
321
  */
322
322
  const FORMAT_AUTOFIX_KEYS = new Set(['timeoutMs']);
323
323
 
324
- export function resolveFormatAutofix(userBlock) {
324
+ function resolveFormatAutofix(userBlock) {
325
325
  const defaults = FORMAT_AUTOFIX_DEFAULTS;
326
326
  if (userBlock == null || typeof userBlock !== 'object') {
327
327
  return { timeoutMs: defaults.timeoutMs };
@@ -336,7 +336,7 @@ export function resolveFormatAutofix(userBlock) {
336
336
  }
337
337
 
338
338
  /** Resolve the coverage gate. Owns `coveragePath` and `timeoutMs`. */
339
- export function resolveCoverageGate(userBlock) {
339
+ function resolveCoverageGate(userBlock) {
340
340
  const defaults = COVERAGE_GATE_DEFAULTS;
341
341
  if (userBlock == null || typeof userBlock !== 'object') {
342
342
  return {
@@ -402,7 +402,7 @@ export function resolveCodingGuardrails(userBlock) {
402
402
  };
403
403
  }
404
404
 
405
- export const AUTO_REFRESH_DEFAULTS = Object.freeze({
405
+ const AUTO_REFRESH_DEFAULTS = Object.freeze({
406
406
  enabled: true,
407
407
  miDropCap: 1.5,
408
408
  crapJumpCap: 5,
@@ -411,7 +411,7 @@ export const AUTO_REFRESH_DEFAULTS = Object.freeze({
411
411
 
412
412
  const AUTO_REFRESH_KEYS = new Set(Object.keys(AUTO_REFRESH_DEFAULTS));
413
413
 
414
- export function resolveAutoRefresh(userBlock) {
414
+ function resolveAutoRefresh(userBlock) {
415
415
  const defaults = AUTO_REFRESH_DEFAULTS;
416
416
  if (userBlock == null || typeof userBlock !== 'object') {
417
417
  return {
@@ -29,7 +29,7 @@ export const DEFAULT_DECOMPOSER = Object.freeze({
29
29
  * host has adequate parallel-agent quota, operators should raise
30
30
  * `delivery.deliverRunner.concurrencyCap` — wall-clock time falls
31
31
  * proportionally to the extra concurrency. The safe default is a tuning
32
- * knob, not a performance ceiling. See `epic-deliver.md` § Phase 2b and
32
+ * knob, not a performance ceiling. See `helpers/deliver-epic.md` § Phase 2b and
33
33
  * `agentrc-reference.json` `delivery.deliverRunner.concurrencyCap` for details.
34
34
  *
35
35
  * **`verifyConcurrencyCap`** (Epic #3019 Tech Spec §1.4 / Story #3024) is a
@@ -44,7 +44,7 @@ const DEFAULT_DELIVER_RUNNER = Object.freeze({
44
44
  });
45
45
 
46
46
  /**
47
- * Default auto-fix loop ceilings for /epic-deliver Phase 4 (epic-audit)
47
+ * Default auto-fix loop ceilings for /deliver Phase 4 (epic-audit)
48
48
  * and Phase 5 (code-review). Operators override via
49
49
  * `delivery.epicAudit.*` and `delivery.codeReview.*` in `.agentrc.json`
50
50
  * (Story #2611, Epic #2586).
@@ -77,7 +77,7 @@ export function resolveWorkingPath({
77
77
 
78
78
  /**
79
79
  * One-shot environment-aware runtime resolution. Returns the trio of runtime
80
- * signals consumed across `/epic-deliver`: whether worktree isolation is on
80
+ * signals consumed across `/deliver`: whether worktree isolation is on
81
81
  * for this process, the session id for claim labels, and whether we're in a
82
82
  * Claude Code web session. Each signal also records its **source** so the
83
83
  * `story-init` startup log can name why the value is what it is.
@@ -44,7 +44,7 @@
44
44
  * parent of `git rev-parse --git-common-dir`) rather than `process.cwd()`.
45
45
  * Without this, a story child that `cd`s into `.worktrees/story-<id>/` before
46
46
  * calling `story-phase.js` would append `story.heartbeat` records to
47
- * `<worktree>/temp/epic-N/lifecycle.ndjson`, while the `/epic-deliver` host
47
+ * `<worktree>/temp/epic-N/lifecycle.ndjson`, while the `/deliver` host
48
48
  * (running from the main checkout) reads the main-checkout copy — so the
49
49
  * idle-watchdog never sees heartbeats and the Epic-lease guard silently
50
50
  * reclaims live foreign claims (the audit-#3513 bug class). Anchoring the
@@ -335,7 +335,7 @@ export const epicPerfReportPath = (eid, config) =>
335
335
 
336
336
  /**
337
337
  * `temp/epic-<eid>/epic-perf-report.json` — canonical JSON snapshot of
338
- * the `epic-perf-report` payload persisted at /epic-deliver close
338
+ * the `epic-perf-report` payload persisted at /deliver close
339
339
  * (Epic #3019 / Story #3029 / Task #3040). When present alongside the
340
340
  * `epic-perf-report` structured comment, the report is discoverable
341
341
  * from the file system without round-tripping the ticketing provider,
@@ -24,7 +24,6 @@
24
24
 
25
25
  import fs from 'node:fs';
26
26
  import path from 'node:path';
27
- import { fileURLToPath } from 'node:url';
28
27
  import { getCiDelivery } from './config/ci.js';
29
28
  import { getCommands } from './config/commands.js';
30
29
  import { getGitHub } from './config/github.js';
@@ -34,6 +33,7 @@ import { validateOrchestrationConfig } from './config/validate-orchestration.js'
34
33
  import { getWorktreeIsolation } from './config/worktree-isolation.js';
35
34
  import { getAgentrcValidator } from './config-schema.js';
36
35
  import { loadEnv } from './env-loader.js';
36
+ import { PROJECT_ROOT } from './project-root.js';
37
37
 
38
38
  export { getAcceptanceEval } from './config/acceptance-eval.js';
39
39
  export { BASELINES_DEFAULTS, getBaselines } from './config/baselines.js';
@@ -64,10 +64,7 @@ export {
64
64
  export { resolveListValue } from './config/shared.js';
65
65
  export { validateOrchestrationConfig } from './config/validate-orchestration.js';
66
66
  export { WORKTREE_ISOLATION_DEFAULTS } from './config/worktree-isolation.js';
67
-
68
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
69
- // scripts/lib/ → scripts/ → .agents/ → project root
70
- export const PROJECT_ROOT = path.resolve(__dirname, '../../..');
67
+ export { PROJECT_ROOT } from './project-root.js';
71
68
 
72
69
  // Cache keyed by absolute root path so callers passing different cwds
73
70
  // (e.g. per-worktree) each get their own resolved config.
@@ -203,7 +203,7 @@ const MERGE_WATCH_SCHEMA = {
203
203
  };
204
204
 
205
205
  /**
206
- * `delivery.epicAudit` — bounded-retry knobs for /epic-deliver Phase 4
206
+ * `delivery.epicAudit` — bounded-retry knobs for /deliver Phase 4
207
207
  * (epic-audit). `maxFixAttempts` caps how many times the auto-fix loop
208
208
  * retries a single finding (Story #2611, Epic #2586). `maxFixScopeFiles`
209
209
  * caps how many files a single auto-fix may touch before escalating to
@@ -237,7 +237,7 @@ const CI_DELIVERY_SCHEMA = {
237
237
  // Story #2899 (Epic #2880) — `delivery.preflight.*` thresholds consumed
238
238
  // by `epic-deliver-preflight.js`. When any value is exceeded the CLI
239
239
  // surfaces a breach in its envelope and the workflow flips the Epic to
240
- // `agent::blocked` (see /epic-deliver Phase 1 prelude).
240
+ // `agent::blocked` (see /deliver Phase 1 prelude).
241
241
  const PREFLIGHT_SCHEMA = {
242
242
  type: 'object',
243
243
  properties: {
@@ -102,7 +102,7 @@ export const QUALITY_SCHEMA = {
102
102
 
103
103
  /**
104
104
  * `delivery.codeReview` — sibling to `delivery.epicAudit`. Same bounded
105
- * retry + scope cap, applied to /epic-deliver Phase 5 (code-review).
105
+ * retry + scope cap, applied to /deliver Phase 5 (code-review).
106
106
  */
107
107
  export const CODE_REVIEW_SCHEMA = {
108
108
  type: 'object',
@@ -205,7 +205,7 @@ const GITHUB_SCHEMA = {
205
205
  };
206
206
 
207
207
  // ---------------------------------------------------------------------------
208
- // planning.* — inputs to /epic-plan
208
+ // planning.* — inputs to /plan
209
209
  // ---------------------------------------------------------------------------
210
210
 
211
211
  /**
@@ -224,7 +224,7 @@ const PLANNING_CONTEXT_SCHEMA = {
224
224
 
225
225
  /**
226
226
  * Story #2634 — `planning.codebaseSnapshot` controls the structural
227
- * view of the consumer repo threaded into `/epic-plan` Phase 7 spec
227
+ * view of the consumer repo threaded into `/plan` Phase 7 spec
228
228
  * authoring. Absent / partial entries resolve to defaults inside
229
229
  * `lib/codebase-snapshot.js#resolveSnapshotConfig` — the schema only
230
230
  * enforces shape (correct enum value, well-formed glob arrays).
@@ -287,7 +287,7 @@ const PLANNING_SCHEMA = {
287
287
  };
288
288
 
289
289
  // ---------------------------------------------------------------------------
290
- // delivery.* — /epic-deliver + story-deliver consume. The full block of
290
+ // delivery.* — /deliver + story-deliver consume. The full block of
291
291
  // per-key sub-schemas lives in `config-settings-schema-delivery.js` (refs
292
292
  // #3457); DELIVERY_SCHEMA is imported above and referenced unchanged below.
293
293
  // ---------------------------------------------------------------------------