mandrel 1.57.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 (843) hide show
  1. package/.agents/README.md +954 -0
  2. package/.agents/docs/SDLC.md +1420 -0
  3. package/.agents/docs/agentrc-reference.json +278 -0
  4. package/.agents/docs/configuration.md +1040 -0
  5. package/.agents/docs/workflows.md +59 -0
  6. package/.agents/instructions.md +384 -0
  7. package/.agents/personas/architect.md +107 -0
  8. package/.agents/personas/devops-engineer.md +36 -0
  9. package/.agents/personas/engineer-mobile.md +119 -0
  10. package/.agents/personas/engineer-web.md +110 -0
  11. package/.agents/personas/engineer.md +90 -0
  12. package/.agents/personas/product.md +88 -0
  13. package/.agents/personas/project-manager.md +110 -0
  14. package/.agents/personas/qa-engineer.md +91 -0
  15. package/.agents/personas/refactorer.md +110 -0
  16. package/.agents/personas/security-engineer.md +112 -0
  17. package/.agents/personas/sre.md +86 -0
  18. package/.agents/personas/technical-writer.md +100 -0
  19. package/.agents/personas/ux-designer.md +95 -0
  20. package/.agents/rules/api-conventions.md +75 -0
  21. package/.agents/rules/changelog-style.md +238 -0
  22. package/.agents/rules/gherkin-standards.md +146 -0
  23. package/.agents/rules/git-conventions.md +146 -0
  24. package/.agents/rules/orchestration-error-handling.md +35 -0
  25. package/.agents/rules/security-baseline.md +92 -0
  26. package/.agents/rules/shell-conventions.md +70 -0
  27. package/.agents/rules/test-seams.md +59 -0
  28. package/.agents/rules/testing-standards.md +177 -0
  29. package/.agents/runtime-deps.json +18 -0
  30. package/.agents/schemas/acceptance-eval-verdict.schema.json +93 -0
  31. package/.agents/schemas/agentrc.schema.json +1583 -0
  32. package/.agents/schemas/audit-results.schema.json +69 -0
  33. package/.agents/schemas/audit-rules.json +134 -0
  34. package/.agents/schemas/audit-rules.schema.json +69 -0
  35. package/.agents/schemas/baselines/baseline-envelope.schema.json +44 -0
  36. package/.agents/schemas/baselines/bundle-size.schema.json +47 -0
  37. package/.agents/schemas/baselines/coverage.schema.json +50 -0
  38. package/.agents/schemas/baselines/crap.schema.json +52 -0
  39. package/.agents/schemas/baselines/duplication.schema.json +62 -0
  40. package/.agents/schemas/baselines/lighthouse.schema.json +59 -0
  41. package/.agents/schemas/baselines/lint.schema.json +47 -0
  42. package/.agents/schemas/baselines/maintainability.schema.json +71 -0
  43. package/.agents/schemas/baselines/mutation.schema.json +52 -0
  44. package/.agents/schemas/crap-baseline.schema.json +57 -0
  45. package/.agents/schemas/crap-report.schema.json +102 -0
  46. package/.agents/schemas/dispatch-manifest.json +232 -0
  47. package/.agents/schemas/epic-perf-report.schema.json +89 -0
  48. package/.agents/schemas/epic-spec.schema.json +183 -0
  49. package/.agents/schemas/friction-event.schema.json +56 -0
  50. package/.agents/schemas/lifecycle/README.md +18 -0
  51. package/.agents/schemas/lifecycle/acceptance.reconcile.failed.schema.json +13 -0
  52. package/.agents/schemas/lifecycle/acceptance.reconcile.ok.schema.json +13 -0
  53. package/.agents/schemas/lifecycle/acceptance.reconcile.skipped.schema.json +13 -0
  54. package/.agents/schemas/lifecycle/acceptance.reconcile.start.schema.json +12 -0
  55. package/.agents/schemas/lifecycle/acceptance.reconcile.waived.schema.json +13 -0
  56. package/.agents/schemas/lifecycle/checkpoint.written.schema.json +13 -0
  57. package/.agents/schemas/lifecycle/close-validate.end.schema.json +18 -0
  58. package/.agents/schemas/lifecycle/close-validate.start.schema.json +13 -0
  59. package/.agents/schemas/lifecycle/code-review.end.schema.json +30 -0
  60. package/.agents/schemas/lifecycle/code-review.start.schema.json +12 -0
  61. package/.agents/schemas/lifecycle/epic.automerge.end.schema.json +14 -0
  62. package/.agents/schemas/lifecycle/epic.automerge.start.schema.json +13 -0
  63. package/.agents/schemas/lifecycle/epic.blocked.schema.json +13 -0
  64. package/.agents/schemas/lifecycle/epic.cleanup.end.schema.json +12 -0
  65. package/.agents/schemas/lifecycle/epic.cleanup.start.schema.json +12 -0
  66. package/.agents/schemas/lifecycle/epic.close.end.schema.json +12 -0
  67. package/.agents/schemas/lifecycle/epic.complete.schema.json +13 -0
  68. package/.agents/schemas/lifecycle/epic.finalize.end.schema.json +13 -0
  69. package/.agents/schemas/lifecycle/epic.finalize.start.schema.json +12 -0
  70. package/.agents/schemas/lifecycle/epic.merge.armed.schema.json +13 -0
  71. package/.agents/schemas/lifecycle/epic.merge.blocked.schema.json +14 -0
  72. package/.agents/schemas/lifecycle/epic.merge.confirmed.schema.json +17 -0
  73. package/.agents/schemas/lifecycle/epic.merge.ready.schema.json +15 -0
  74. package/.agents/schemas/lifecycle/epic.plan.end.schema.json +18 -0
  75. package/.agents/schemas/lifecycle/epic.plan.start.schema.json +12 -0
  76. package/.agents/schemas/lifecycle/epic.snapshot.end.schema.json +16 -0
  77. package/.agents/schemas/lifecycle/epic.snapshot.start.schema.json +12 -0
  78. package/.agents/schemas/lifecycle/epic.watch.end.schema.json +28 -0
  79. package/.agents/schemas/lifecycle/epic.watch.start.schema.json +16 -0
  80. package/.agents/schemas/lifecycle/intervention.recorded.schema.json +15 -0
  81. package/.agents/schemas/lifecycle/ledger-record.schema.json +59 -0
  82. package/.agents/schemas/lifecycle/notification.emitted.schema.json +18 -0
  83. package/.agents/schemas/lifecycle/pr.created.schema.json +14 -0
  84. package/.agents/schemas/lifecycle/retro.end.schema.json +16 -0
  85. package/.agents/schemas/lifecycle/retro.start.schema.json +12 -0
  86. package/.agents/schemas/lifecycle/story.blocked.schema.json +13 -0
  87. package/.agents/schemas/lifecycle/story.dispatch.end.schema.json +17 -0
  88. package/.agents/schemas/lifecycle/story.dispatch.start.schema.json +15 -0
  89. package/.agents/schemas/lifecycle/story.heartbeat.schema.json +20 -0
  90. package/.agents/schemas/lifecycle/story.merged.schema.json +13 -0
  91. package/.agents/schemas/mi-report.schema.json +58 -0
  92. package/.agents/schemas/model-attribution.schema.json +49 -0
  93. package/.agents/schemas/qa-finding.schema.json +133 -0
  94. package/.agents/schemas/qa-ledger.schema.json +89 -0
  95. package/.agents/schemas/risk-verdict.schema.json +53 -0
  96. package/.agents/schemas/signal-event.schema.json +58 -0
  97. package/.agents/schemas/skill.schema.json +31 -0
  98. package/.agents/schemas/skills-index.schema.json +81 -0
  99. package/.agents/schemas/story-perf-summary.schema.json +73 -0
  100. package/.agents/schemas/validation-evidence.schema.json +78 -0
  101. package/.agents/scripts/README.md +93 -0
  102. package/.agents/scripts/acceptance-eval.js +284 -0
  103. package/.agents/scripts/acceptance-spec-reconciler.js +556 -0
  104. package/.agents/scripts/agents-bootstrap-github.js +634 -0
  105. package/.agents/scripts/analyze-execution.js +369 -0
  106. package/.agents/scripts/assert-branch.js +83 -0
  107. package/.agents/scripts/audit-labels-bootstrap.js +253 -0
  108. package/.agents/scripts/audit-to-stories.js +257 -0
  109. package/.agents/scripts/bootstrap.js +1378 -0
  110. package/.agents/scripts/check-baselines.js +81 -0
  111. package/.agents/scripts/check-dead-exports.js +311 -0
  112. package/.agents/scripts/check-doc-links.js +401 -0
  113. package/.agents/scripts/check-gherkin-placeholders.js +663 -0
  114. package/.agents/scripts/check-lifecycle-doc-drift.js +402 -0
  115. package/.agents/scripts/check-lifecycle-lint.js +379 -0
  116. package/.agents/scripts/check-prepush-recovery.js +90 -0
  117. package/.agents/scripts/check-windows-git-perf.js +138 -0
  118. package/.agents/scripts/cleanup-repo-test-temp.js +67 -0
  119. package/.agents/scripts/coverage-capture.js +112 -0
  120. package/.agents/scripts/detect-merges.js +111 -0
  121. package/.agents/scripts/diagnose-friction.js +257 -0
  122. package/.agents/scripts/diagnose.js +240 -0
  123. package/.agents/scripts/dispatcher.js +295 -0
  124. package/.agents/scripts/drain-pending-cleanup.js +147 -0
  125. package/.agents/scripts/epic-audit-prepare.js +419 -0
  126. package/.agents/scripts/epic-audit-recheck.js +241 -0
  127. package/.agents/scripts/epic-deliver-note-intervention.js +192 -0
  128. package/.agents/scripts/epic-deliver-preflight.js +407 -0
  129. package/.agents/scripts/epic-deliver-prepare.js +383 -0
  130. package/.agents/scripts/epic-execute-record-wave.js +463 -0
  131. package/.agents/scripts/epic-plan-clarity.js +201 -0
  132. package/.agents/scripts/epic-plan-decompose.js +79 -0
  133. package/.agents/scripts/epic-plan-healthcheck.js +363 -0
  134. package/.agents/scripts/epic-plan-spec-validate.js +111 -0
  135. package/.agents/scripts/epic-plan-spec.js +198 -0
  136. package/.agents/scripts/epic-reconcile.js +637 -0
  137. package/.agents/scripts/evidence-gate.js +235 -0
  138. package/.agents/scripts/generate-config-docs.js +516 -0
  139. package/.agents/scripts/generate-lifecycle-docs.js +224 -0
  140. package/.agents/scripts/generate-skills-index.js +252 -0
  141. package/.agents/scripts/generate-workflows-doc.js +168 -0
  142. package/.agents/scripts/git-cleanup.js +124 -0
  143. package/.agents/scripts/git-pr-quality-gate.js +203 -0
  144. package/.agents/scripts/git-rebase-and-resolve.js +234 -0
  145. package/.agents/scripts/hierarchy-gate.js +176 -0
  146. package/.agents/scripts/hydrate-context.js +179 -0
  147. package/.agents/scripts/install-matrix-assert.js +282 -0
  148. package/.agents/scripts/lib/Graph.js +326 -0
  149. package/.agents/scripts/lib/ITicketingProvider.js +349 -0
  150. package/.agents/scripts/lib/Logger.js +194 -0
  151. package/.agents/scripts/lib/audit-suite/cli.js +64 -0
  152. package/.agents/scripts/lib/audit-suite/findings.js +164 -0
  153. package/.agents/scripts/lib/audit-suite/frontmatter-lint.js +32 -0
  154. package/.agents/scripts/lib/audit-suite/frontmatter.js +110 -0
  155. package/.agents/scripts/lib/audit-suite/index.js +22 -0
  156. package/.agents/scripts/lib/audit-suite/runner.js +233 -0
  157. package/.agents/scripts/lib/audit-suite/selector.js +235 -0
  158. package/.agents/scripts/lib/audit-suite/substitutions.js +124 -0
  159. package/.agents/scripts/lib/audit-suite/workflow-loader.js +49 -0
  160. package/.agents/scripts/lib/audit-to-stories/build-story-body.js +130 -0
  161. package/.agents/scripts/lib/audit-to-stories/dedupe-against-github.js +114 -0
  162. package/.agents/scripts/lib/audit-to-stories/finding-adapter.js +93 -0
  163. package/.agents/scripts/lib/audit-to-stories/group-findings.js +265 -0
  164. package/.agents/scripts/lib/audit-to-stories/parse-audit-md.js +246 -0
  165. package/.agents/scripts/lib/audit-to-stories/seed-epic-from-findings.js +160 -0
  166. package/.agents/scripts/lib/auto-refresh-baselines.js +308 -0
  167. package/.agents/scripts/lib/baseline-loader.js +0 -0
  168. package/.agents/scripts/lib/baseline-schema-registry.js +69 -0
  169. package/.agents/scripts/lib/baseline-snapshot.js +716 -0
  170. package/.agents/scripts/lib/baselines/component-matcher.js +21 -0
  171. package/.agents/scripts/lib/baselines/components.js +126 -0
  172. package/.agents/scripts/lib/baselines/diff-scope-cli.js +203 -0
  173. package/.agents/scripts/lib/baselines/duplication-scanner.js +220 -0
  174. package/.agents/scripts/lib/baselines/env-overrides.js +129 -0
  175. package/.agents/scripts/lib/baselines/envelope.js +368 -0
  176. package/.agents/scripts/lib/baselines/exit-codes.js +89 -0
  177. package/.agents/scripts/lib/baselines/git-base.js +0 -0
  178. package/.agents/scripts/lib/baselines/kernel.js +111 -0
  179. package/.agents/scripts/lib/baselines/kinds/_shared-metric.js +220 -0
  180. package/.agents/scripts/lib/baselines/kinds/bundle-size.js +157 -0
  181. package/.agents/scripts/lib/baselines/kinds/coverage.js +194 -0
  182. package/.agents/scripts/lib/baselines/kinds/crap.js +555 -0
  183. package/.agents/scripts/lib/baselines/kinds/duplication.js +197 -0
  184. package/.agents/scripts/lib/baselines/kinds/lighthouse.js +185 -0
  185. package/.agents/scripts/lib/baselines/kinds/lint.js +172 -0
  186. package/.agents/scripts/lib/baselines/kinds/maintainability.js +340 -0
  187. package/.agents/scripts/lib/baselines/kinds/mutation.js +153 -0
  188. package/.agents/scripts/lib/baselines/path-canon.js +279 -0
  189. package/.agents/scripts/lib/baselines/preview-gates.js +298 -0
  190. package/.agents/scripts/lib/baselines/reader.js +321 -0
  191. package/.agents/scripts/lib/baselines/refresh-service.js +733 -0
  192. package/.agents/scripts/lib/baselines/scope.js +291 -0
  193. package/.agents/scripts/lib/baselines/writer.js +312 -0
  194. package/.agents/scripts/lib/bdd-runner-detect.js +417 -0
  195. package/.agents/scripts/lib/bdd-scenario-scanner.js +310 -0
  196. package/.agents/scripts/lib/bootstrap/baselines-layout-migration.js +202 -0
  197. package/.agents/scripts/lib/bootstrap/branch-protection.js +222 -0
  198. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +171 -0
  199. package/.agents/scripts/lib/bootstrap/commit-push.js +146 -0
  200. package/.agents/scripts/lib/bootstrap/gh-list.js +153 -0
  201. package/.agents/scripts/lib/bootstrap/gh-preflight.js +306 -0
  202. package/.agents/scripts/lib/bootstrap/hitl-confirm.js +89 -0
  203. package/.agents/scripts/lib/bootstrap/install-ledger.js +174 -0
  204. package/.agents/scripts/lib/bootstrap/manifest.js +272 -0
  205. package/.agents/scripts/lib/bootstrap/merge-methods.js +108 -0
  206. package/.agents/scripts/lib/bootstrap/preflight.js +195 -0
  207. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +801 -0
  208. package/.agents/scripts/lib/bootstrap/prompt.js +480 -0
  209. package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +370 -0
  210. package/.agents/scripts/lib/bootstrap/summary.js +75 -0
  211. package/.agents/scripts/lib/bootstrap/workflow-audit.js +256 -0
  212. package/.agents/scripts/lib/branch-name-guard.js +98 -0
  213. package/.agents/scripts/lib/c8-cli-path.js +21 -0
  214. package/.agents/scripts/lib/changed-files.js +184 -0
  215. package/.agents/scripts/lib/checks/baseline-drift-main-checkout.js +104 -0
  216. package/.agents/scripts/lib/checks/core-bare-clean.js +48 -0
  217. package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +54 -0
  218. package/.agents/scripts/lib/checks/index.js +288 -0
  219. package/.agents/scripts/lib/checks/push-hook-parity.js +106 -0
  220. package/.agents/scripts/lib/checks/stale-origin-epic.js +49 -0
  221. package/.agents/scripts/lib/checks/state.js +558 -0
  222. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +186 -0
  223. package/.agents/scripts/lib/checks/subagent-agent-tool-required.js +182 -0
  224. package/.agents/scripts/lib/checks/windows-coverage-noise-floor.js +92 -0
  225. package/.agents/scripts/lib/checks/worktree-bootstrap-env.js +81 -0
  226. package/.agents/scripts/lib/checks/worktree-residue-biome.js +55 -0
  227. package/.agents/scripts/lib/cli/parse-numeric.js +60 -0
  228. package/.agents/scripts/lib/cli/standard-args.js +351 -0
  229. package/.agents/scripts/lib/cli-args.js +286 -0
  230. package/.agents/scripts/lib/cli-utils.js +69 -0
  231. package/.agents/scripts/lib/close-validation/projections/head-sha.js +44 -0
  232. package/.agents/scripts/lib/close-validation/projections/inputs.js +86 -0
  233. package/.agents/scripts/lib/close-validation/projections/maintainability.js +286 -0
  234. package/.agents/scripts/lib/close-validation.js +897 -0
  235. package/.agents/scripts/lib/codebase-snapshot.js +513 -0
  236. package/.agents/scripts/lib/command-header.js +33 -0
  237. package/.agents/scripts/lib/config/acceptance-eval.js +95 -0
  238. package/.agents/scripts/lib/config/baselines.js +60 -0
  239. package/.agents/scripts/lib/config/ci.js +30 -0
  240. package/.agents/scripts/lib/config/commands.js +36 -0
  241. package/.agents/scripts/lib/config/defaults.js +119 -0
  242. package/.agents/scripts/lib/config/explain.js +348 -0
  243. package/.agents/scripts/lib/config/gates/bundle-size.schema.js +23 -0
  244. package/.agents/scripts/lib/config/gates/coverage.schema.js +18 -0
  245. package/.agents/scripts/lib/config/gates/crap.schema.js +33 -0
  246. package/.agents/scripts/lib/config/gates/duplication.schema.js +26 -0
  247. package/.agents/scripts/lib/config/gates/index.js +36 -0
  248. package/.agents/scripts/lib/config/gates/lighthouse.schema.js +23 -0
  249. package/.agents/scripts/lib/config/gates/lint.schema.js +9 -0
  250. package/.agents/scripts/lib/config/gates/maintainability.schema.js +20 -0
  251. package/.agents/scripts/lib/config/gates/mutation.schema.js +12 -0
  252. package/.agents/scripts/lib/config/gates/shared.js +117 -0
  253. package/.agents/scripts/lib/config/github.js +122 -0
  254. package/.agents/scripts/lib/config/lifecycle.js +40 -0
  255. package/.agents/scripts/lib/config/limits.js +211 -0
  256. package/.agents/scripts/lib/config/paths.js +73 -0
  257. package/.agents/scripts/lib/config/preflight.js +58 -0
  258. package/.agents/scripts/lib/config/quality.js +665 -0
  259. package/.agents/scripts/lib/config/retro.js +77 -0
  260. package/.agents/scripts/lib/config/runners.js +105 -0
  261. package/.agents/scripts/lib/config/runtime.js +167 -0
  262. package/.agents/scripts/lib/config/shared.js +46 -0
  263. package/.agents/scripts/lib/config/sync-agentrc.js +243 -0
  264. package/.agents/scripts/lib/config/temp-paths.js +373 -0
  265. package/.agents/scripts/lib/config/validate-orchestration.js +81 -0
  266. package/.agents/scripts/lib/config/worktree-isolation.js +80 -0
  267. package/.agents/scripts/lib/config-resolver.js +298 -0
  268. package/.agents/scripts/lib/config-schema-shared.js +32 -0
  269. package/.agents/scripts/lib/config-schema.js +20 -0
  270. package/.agents/scripts/lib/config-settings-schema-delivery.js +332 -0
  271. package/.agents/scripts/lib/config-settings-schema-quality.js +165 -0
  272. package/.agents/scripts/lib/config-settings-schema.js +420 -0
  273. package/.agents/scripts/lib/coverage-baseline.js +352 -0
  274. package/.agents/scripts/lib/coverage-capture.js +195 -0
  275. package/.agents/scripts/lib/coverage-utils.js +239 -0
  276. package/.agents/scripts/lib/cpu-pool.js +223 -0
  277. package/.agents/scripts/lib/crap-engine.js +119 -0
  278. package/.agents/scripts/lib/crap-utils.js +479 -0
  279. package/.agents/scripts/lib/degraded-mode.js +69 -0
  280. package/.agents/scripts/lib/dependency-parser.js +129 -0
  281. package/.agents/scripts/lib/duplicate-search.js +189 -0
  282. package/.agents/scripts/lib/dynamic-workflow/architecture-report-contract.js +70 -0
  283. package/.agents/scripts/lib/dynamic-workflow/audit-orchestrator.js +197 -0
  284. package/.agents/scripts/lib/dynamic-workflow/capability.js +396 -0
  285. package/.agents/scripts/lib/dynamic-workflow/clean-code-report-contract.js +80 -0
  286. package/.agents/scripts/lib/dynamic-workflow/performance-report-contract.js +72 -0
  287. package/.agents/scripts/lib/dynamic-workflow/quality-report-contract.js +90 -0
  288. package/.agents/scripts/lib/dynamic-workflow/report-contract-core.js +43 -0
  289. package/.agents/scripts/lib/dynamic-workflow/security-report-contract.js +83 -0
  290. package/.agents/scripts/lib/env-loader.js +52 -0
  291. package/.agents/scripts/lib/epic-merge-lock.js +239 -0
  292. package/.agents/scripts/lib/epic-plan-clarity.js +142 -0
  293. package/.agents/scripts/lib/epic-plan-ideation.js +228 -0
  294. package/.agents/scripts/lib/error-redactor.js +125 -0
  295. package/.agents/scripts/lib/errors/index.js +67 -0
  296. package/.agents/scripts/lib/feedback-loop/audit-results-graduator.js +230 -0
  297. package/.agents/scripts/lib/feedback-loop/code-review-graduator.js +207 -0
  298. package/.agents/scripts/lib/feedback-loop/graduator-core.js +421 -0
  299. package/.agents/scripts/lib/feedback-loop/memory-freshness.js +480 -0
  300. package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +229 -0
  301. package/.agents/scripts/lib/findings/classify-finding.js +195 -0
  302. package/.agents/scripts/lib/findings/promote-finding.js +353 -0
  303. package/.agents/scripts/lib/findings/route-finding.js +283 -0
  304. package/.agents/scripts/lib/findings/semantic-issue-search.js +179 -0
  305. package/.agents/scripts/lib/findings/severity.js +102 -0
  306. package/.agents/scripts/lib/gates/baseline-store.js +106 -0
  307. package/.agents/scripts/lib/gates/friction.js +43 -0
  308. package/.agents/scripts/lib/gh-exec.js +553 -0
  309. package/.agents/scripts/lib/git/cached-fetch.js +0 -0
  310. package/.agents/scripts/lib/git/sync-from-base.js +162 -0
  311. package/.agents/scripts/lib/git-branch-cleanup.js +213 -0
  312. package/.agents/scripts/lib/git-branch-lifecycle.js +353 -0
  313. package/.agents/scripts/lib/git-merge-orchestrator.js +261 -0
  314. package/.agents/scripts/lib/git-utils.js +363 -0
  315. package/.agents/scripts/lib/github-url.js +29 -0
  316. package/.agents/scripts/lib/install-cmd-parser.js +51 -0
  317. package/.agents/scripts/lib/issue-link-parser.js +74 -0
  318. package/.agents/scripts/lib/json-utils.js +60 -0
  319. package/.agents/scripts/lib/label-constants.js +169 -0
  320. package/.agents/scripts/lib/label-taxonomy.js +200 -0
  321. package/.agents/scripts/lib/maintainability-engine.js +164 -0
  322. package/.agents/scripts/lib/maintainability-utils.js +343 -0
  323. package/.agents/scripts/lib/mandrel-catalog.js +170 -0
  324. package/.agents/scripts/lib/mutation/baseline-snapshot.js +238 -0
  325. package/.agents/scripts/lib/mutation/config-detector.js +119 -0
  326. package/.agents/scripts/lib/mutation/stryker-runner.js +306 -0
  327. package/.agents/scripts/lib/mutation/survivor-report.js +160 -0
  328. package/.agents/scripts/lib/notifications/notifier.js +75 -0
  329. package/.agents/scripts/lib/observability/active-story-env.js +182 -0
  330. package/.agents/scripts/lib/observability/baseline-refresh-rate.js +221 -0
  331. package/.agents/scripts/lib/observability/perf-aggregator.js +887 -0
  332. package/.agents/scripts/lib/observability/perf-report-readers.js +319 -0
  333. package/.agents/scripts/lib/observability/perf-report-render.js +182 -0
  334. package/.agents/scripts/lib/observability/signals-writer.js +296 -0
  335. package/.agents/scripts/lib/observability/source-classifier.js +103 -0
  336. package/.agents/scripts/lib/observability/tool-trace-hook.js +417 -0
  337. package/.agents/scripts/lib/onboard/detect-stack.js +300 -0
  338. package/.agents/scripts/lib/onboard/scaffold-docs.js +128 -0
  339. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +173 -0
  340. package/.agents/scripts/lib/orchestration/cascade-grouping.js +275 -0
  341. package/.agents/scripts/lib/orchestration/check-baselines/phases/compare.js +131 -0
  342. package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +80 -0
  343. package/.agents/scripts/lib/orchestration/check-baselines/phases/floors.js +132 -0
  344. package/.agents/scripts/lib/orchestration/check-baselines/phases/friction.js +142 -0
  345. package/.agents/scripts/lib/orchestration/check-baselines/phases/parse-args.js +149 -0
  346. package/.agents/scripts/lib/orchestration/check-baselines/phases/pipeline.js +158 -0
  347. package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +56 -0
  348. package/.agents/scripts/lib/orchestration/code-review.js +652 -0
  349. package/.agents/scripts/lib/orchestration/column-sync.js +286 -0
  350. package/.agents/scripts/lib/orchestration/context-envelope.js +280 -0
  351. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +581 -0
  352. package/.agents/scripts/lib/orchestration/dependency-analyzer.js +88 -0
  353. package/.agents/scripts/lib/orchestration/detectors-phase.js +188 -0
  354. package/.agents/scripts/lib/orchestration/dispatch-engine.js +144 -0
  355. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +206 -0
  356. package/.agents/scripts/lib/orchestration/doc-reader.js +94 -0
  357. package/.agents/scripts/lib/orchestration/epic-cleanup.js +473 -0
  358. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +310 -0
  359. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/cli.js +167 -0
  360. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +151 -0
  361. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +74 -0
  362. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +78 -0
  363. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +72 -0
  364. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +155 -0
  365. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +321 -0
  366. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +75 -0
  367. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +86 -0
  368. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +235 -0
  369. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/authoring-context.js +197 -0
  370. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/cli-args.js +48 -0
  371. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +94 -0
  372. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +414 -0
  373. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +55 -0
  374. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/risk-verdict.js +105 -0
  375. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +235 -0
  376. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +120 -0
  377. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +118 -0
  378. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +295 -0
  379. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +186 -0
  380. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +50 -0
  381. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +146 -0
  382. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +110 -0
  383. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +392 -0
  384. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +217 -0
  385. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +235 -0
  386. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter.js +69 -0
  387. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +32 -0
  388. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +291 -0
  389. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +175 -0
  390. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +37 -0
  391. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +127 -0
  392. package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +400 -0
  393. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +285 -0
  394. package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +66 -0
  395. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +797 -0
  396. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +619 -0
  397. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +335 -0
  398. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +230 -0
  399. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +363 -0
  400. package/.agents/scripts/lib/orchestration/error-journal.js +139 -0
  401. package/.agents/scripts/lib/orchestration/file-assumption-enum.js +31 -0
  402. package/.agents/scripts/lib/orchestration/file-assumptions.js +506 -0
  403. package/.agents/scripts/lib/orchestration/finalize/close-planning-tickets.js +116 -0
  404. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +241 -0
  405. package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +489 -0
  406. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +88 -0
  407. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches-reap.js +219 -0
  408. package/.agents/scripts/lib/orchestration/git-cleanup/phases/branches.js +309 -0
  409. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +99 -0
  410. package/.agents/scripts/lib/orchestration/git-cleanup/phases/fast-forward.js +123 -0
  411. package/.agents/scripts/lib/orchestration/git-cleanup/phases/filters.js +57 -0
  412. package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes-ff.js +114 -0
  413. package/.agents/scripts/lib/orchestration/git-cleanup/phases/git-probes.js +426 -0
  414. package/.agents/scripts/lib/orchestration/git-cleanup/phases/parse-args.js +84 -0
  415. package/.agents/scripts/lib/orchestration/git-cleanup/phases/phase-drivers.js +365 -0
  416. package/.agents/scripts/lib/orchestration/git-cleanup/phases/prompts.js +72 -0
  417. package/.agents/scripts/lib/orchestration/git-cleanup/phases/prune.js +69 -0
  418. package/.agents/scripts/lib/orchestration/git-cleanup/phases/render.js +214 -0
  419. package/.agents/scripts/lib/orchestration/git-cleanup/phases/stashes.js +137 -0
  420. package/.agents/scripts/lib/orchestration/label-transitions.js +43 -0
  421. package/.agents/scripts/lib/orchestration/lifecycle/bus.js +309 -0
  422. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +147 -0
  423. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +155 -0
  424. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +226 -0
  425. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +69 -0
  426. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +378 -0
  427. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +248 -0
  428. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +527 -0
  429. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +259 -0
  430. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +278 -0
  431. package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +355 -0
  432. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +647 -0
  433. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +331 -0
  434. package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +140 -0
  435. package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +421 -0
  436. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +168 -0
  437. package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +668 -0
  438. package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +322 -0
  439. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +114 -0
  440. package/.agents/scripts/lib/orchestration/manifest-builder.js +216 -0
  441. package/.agents/scripts/lib/orchestration/model-attribution.js +390 -0
  442. package/.agents/scripts/lib/orchestration/parked-follow-ons.js +147 -0
  443. package/.agents/scripts/lib/orchestration/phase-runner.js +87 -0
  444. package/.agents/scripts/lib/orchestration/plan-review-routing.js +63 -0
  445. package/.agents/scripts/lib/orchestration/plan-runner/plan-router.js +86 -0
  446. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +212 -0
  447. package/.agents/scripts/lib/orchestration/planning-context-budget.js +213 -0
  448. package/.agents/scripts/lib/orchestration/planning-risk.js +155 -0
  449. package/.agents/scripts/lib/orchestration/planning-state-manager.js +318 -0
  450. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +56 -0
  451. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +33 -0
  452. package/.agents/scripts/lib/orchestration/post-merge/phases/notification.js +78 -0
  453. package/.agents/scripts/lib/orchestration/post-merge/phases/temp-cleanup.js +68 -0
  454. package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +118 -0
  455. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +396 -0
  456. package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +205 -0
  457. package/.agents/scripts/lib/orchestration/pr-base-guard.js +47 -0
  458. package/.agents/scripts/lib/orchestration/preflight-cache.js +164 -0
  459. package/.agents/scripts/lib/orchestration/reassert-status-column.js +202 -0
  460. package/.agents/scripts/lib/orchestration/reconciler.js +137 -0
  461. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +152 -0
  462. package/.agents/scripts/lib/orchestration/recut.js +56 -0
  463. package/.agents/scripts/lib/orchestration/resolves-token.js +127 -0
  464. package/.agents/scripts/lib/orchestration/retro/phases/checks.js +94 -0
  465. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +448 -0
  466. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +335 -0
  467. package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +133 -0
  468. package/.agents/scripts/lib/orchestration/retro-heuristics.js +57 -0
  469. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +275 -0
  470. package/.agents/scripts/lib/orchestration/retro-proposals.js +395 -0
  471. package/.agents/scripts/lib/orchestration/retro-runner.js +171 -0
  472. package/.agents/scripts/lib/orchestration/review-depth.js +93 -0
  473. package/.agents/scripts/lib/orchestration/review-providers/codex.js +363 -0
  474. package/.agents/scripts/lib/orchestration/review-providers/findings-renderer.js +205 -0
  475. package/.agents/scripts/lib/orchestration/review-providers/native.js +805 -0
  476. package/.agents/scripts/lib/orchestration/review-providers/review-depth.js +73 -0
  477. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +396 -0
  478. package/.agents/scripts/lib/orchestration/review-providers/security-review.js +373 -0
  479. package/.agents/scripts/lib/orchestration/review-providers/types.js +89 -0
  480. package/.agents/scripts/lib/orchestration/review-providers/ultrareview.js +107 -0
  481. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +159 -0
  482. package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +194 -0
  483. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +81 -0
  484. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +190 -0
  485. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +70 -0
  486. package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +106 -0
  487. package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +42 -0
  488. package/.agents/scripts/lib/orchestration/single-story-close/phases/worktree-reap.js +73 -0
  489. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +225 -0
  490. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +315 -0
  491. package/.agents/scripts/lib/orchestration/single-story-lease-guard.js +149 -0
  492. package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +110 -0
  493. package/.agents/scripts/lib/orchestration/spec-freshness.js +320 -0
  494. package/.agents/scripts/lib/orchestration/spec-renderer.js +456 -0
  495. package/.agents/scripts/lib/orchestration/spec-section-validator.js +80 -0
  496. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +797 -0
  497. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +163 -0
  498. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +152 -0
  499. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +387 -0
  500. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +266 -0
  501. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +48 -0
  502. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +67 -0
  503. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +161 -0
  504. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +117 -0
  505. package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +86 -0
  506. package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +147 -0
  507. package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +142 -0
  508. package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +62 -0
  509. package/.agents/scripts/lib/orchestration/story-close/format-autofix-scoped.js +221 -0
  510. package/.agents/scripts/lib/orchestration/story-close/format-autofix-shared.js +123 -0
  511. package/.agents/scripts/lib/orchestration/story-close/format-autofix.js +216 -0
  512. package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +636 -0
  513. package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +198 -0
  514. package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +105 -0
  515. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +222 -0
  516. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +220 -0
  517. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +291 -0
  518. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +234 -0
  519. package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +110 -0
  520. package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +86 -0
  521. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +112 -0
  522. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +157 -0
  523. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +434 -0
  524. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +290 -0
  525. package/.agents/scripts/lib/orchestration/story-close-recovery.js +643 -0
  526. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +67 -0
  527. package/.agents/scripts/lib/orchestration/task-body-validator.js +391 -0
  528. package/.agents/scripts/lib/orchestration/ticket-lease.js +358 -0
  529. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +783 -0
  530. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +367 -0
  531. package/.agents/scripts/lib/orchestration/ticket-validator.js +691 -0
  532. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +723 -0
  533. package/.agents/scripts/lib/orchestration/ticketing/reads.js +474 -0
  534. package/.agents/scripts/lib/orchestration/ticketing/state.js +559 -0
  535. package/.agents/scripts/lib/orchestration/ticketing.js +55 -0
  536. package/.agents/scripts/lib/orchestration/wave-marker.js +28 -0
  537. package/.agents/scripts/lib/orchestration/wave-record-io.js +277 -0
  538. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +189 -0
  539. package/.agents/scripts/lib/orchestration/wave-record-projection.js +423 -0
  540. package/.agents/scripts/lib/path-security.js +25 -0
  541. package/.agents/scripts/lib/plan-phase-cleanup.js +125 -0
  542. package/.agents/scripts/lib/preflight-runner.js +196 -0
  543. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +95 -0
  544. package/.agents/scripts/lib/presentation/manifest-builder.js +245 -0
  545. package/.agents/scripts/lib/presentation/manifest-formatter.js +243 -0
  546. package/.agents/scripts/lib/presentation/manifest-helpers.js +213 -0
  547. package/.agents/scripts/lib/presentation/manifest-persistence.js +262 -0
  548. package/.agents/scripts/lib/presentation/manifest-procedures.js +55 -0
  549. package/.agents/scripts/lib/presentation/manifest-render-waves.js +252 -0
  550. package/.agents/scripts/lib/presentation/manifest-renderer.js +188 -0
  551. package/.agents/scripts/lib/presentation/manifest-story-views.js +119 -0
  552. package/.agents/scripts/lib/provider-factory.js +80 -0
  553. package/.agents/scripts/lib/push-epic-retry.js +209 -0
  554. package/.agents/scripts/lib/qa/console-allowlist.js +151 -0
  555. package/.agents/scripts/lib/qa/coverage-report.js +181 -0
  556. package/.agents/scripts/lib/qa/coverage-verdict.js +296 -0
  557. package/.agents/scripts/lib/qa/propose-missing-test.js +95 -0
  558. package/.agents/scripts/lib/qa/qa-context-hydrator.js +296 -0
  559. package/.agents/scripts/lib/qa/qa-session.js +197 -0
  560. package/.agents/scripts/lib/qa/redact-evidence.js +245 -0
  561. package/.agents/scripts/lib/qa/resolve-qa-contract.js +190 -0
  562. package/.agents/scripts/lib/qa/resolve-selection.js +373 -0
  563. package/.agents/scripts/lib/runtime-deps/ensure-installed.js +100 -0
  564. package/.agents/scripts/lib/runtime-deps/manifest.js +96 -0
  565. package/.agents/scripts/lib/runtime-deps/preflight.js +78 -0
  566. package/.agents/scripts/lib/runtime-deps/scan-imports.js +202 -0
  567. package/.agents/scripts/lib/signals/detectors/common.js +36 -0
  568. package/.agents/scripts/lib/signals/detectors/hotspot.js +298 -0
  569. package/.agents/scripts/lib/signals/detectors/index.js +14 -0
  570. package/.agents/scripts/lib/signals/detectors/retry.js +289 -0
  571. package/.agents/scripts/lib/signals/detectors/rework.js +204 -0
  572. package/.agents/scripts/lib/signals/index.js +39 -0
  573. package/.agents/scripts/lib/signals/read.js +268 -0
  574. package/.agents/scripts/lib/signals/schema.js +225 -0
  575. package/.agents/scripts/lib/signals/span-tree.js +290 -0
  576. package/.agents/scripts/lib/signals/write.js +19 -0
  577. package/.agents/scripts/lib/single-story/confirm-merge.js +201 -0
  578. package/.agents/scripts/lib/single-story/story-merged-notify.js +126 -0
  579. package/.agents/scripts/lib/single-story-sweep/protection.js +274 -0
  580. package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +169 -0
  581. package/.agents/scripts/lib/single-story-sweep.js +329 -0
  582. package/.agents/scripts/lib/skills/parse-skill.js +202 -0
  583. package/.agents/scripts/lib/skills/walk-skill-files.js +56 -0
  584. package/.agents/scripts/lib/spec/index.js +36 -0
  585. package/.agents/scripts/lib/spec/loader.js +425 -0
  586. package/.agents/scripts/lib/spec/state.js +217 -0
  587. package/.agents/scripts/lib/story-body/story-body.js +743 -0
  588. package/.agents/scripts/lib/story-init/blocker-validator.js +68 -0
  589. package/.agents/scripts/lib/story-init/branch-initializer.js +422 -0
  590. package/.agents/scripts/lib/story-init/context-resolver.js +92 -0
  591. package/.agents/scripts/lib/story-init/donor-precheck.js +207 -0
  592. package/.agents/scripts/lib/story-init/hierarchy-tracer.js +36 -0
  593. package/.agents/scripts/lib/story-init/state-transitioner.js +80 -0
  594. package/.agents/scripts/lib/story-init/task-graph-builder.js +114 -0
  595. package/.agents/scripts/lib/story-init/transition-summary.js +34 -0
  596. package/.agents/scripts/lib/story-lifecycle.js +186 -0
  597. package/.agents/scripts/lib/story-plan.js +246 -0
  598. package/.agents/scripts/lib/task-utils.js +26 -0
  599. package/.agents/scripts/lib/templates/decomposer-prompts.js +168 -0
  600. package/.agents/scripts/lib/test-env.js +30 -0
  601. package/.agents/scripts/lib/test-isolate/env-snapshot-loader.js +52 -0
  602. package/.agents/scripts/lib/test-isolate/list-files.js +90 -0
  603. package/.agents/scripts/lib/test-isolate/parse-tap.js +75 -0
  604. package/.agents/scripts/lib/test-isolate/runner.js +483 -0
  605. package/.agents/scripts/lib/test-profile/parse-tap.js +136 -0
  606. package/.agents/scripts/lib/test-profile/render-report.js +45 -0
  607. package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +35 -0
  608. package/.agents/scripts/lib/test-tiers.js +94 -0
  609. package/.agents/scripts/lib/util/concurrent-map.js +59 -0
  610. package/.agents/scripts/lib/util/phase-timer-state.js +72 -0
  611. package/.agents/scripts/lib/util/phase-timer.js +163 -0
  612. package/.agents/scripts/lib/util/poll-loop.js +86 -0
  613. package/.agents/scripts/lib/util/with-timeout.js +32 -0
  614. package/.agents/scripts/lib/validation-evidence.js +323 -0
  615. package/.agents/scripts/lib/wave-runner/tick.js +665 -0
  616. package/.agents/scripts/lib/wave-runner/wave-checkpoint.js +91 -0
  617. package/.agents/scripts/lib/wave-runner/wave-runner-error.js +19 -0
  618. package/.agents/scripts/lib/workers/crap-worker.js +197 -0
  619. package/.agents/scripts/lib/workers/maintainability-report-worker.js +137 -0
  620. package/.agents/scripts/lib/workers/maintainability-worker.js +79 -0
  621. package/.agents/scripts/lib/workspace-provisioner.js +189 -0
  622. package/.agents/scripts/lib/worktree/bootstrapper.js +48 -0
  623. package/.agents/scripts/lib/worktree/inspector.js +140 -0
  624. package/.agents/scripts/lib/worktree/lifecycle/creation.js +118 -0
  625. package/.agents/scripts/lib/worktree/lifecycle/drift-detection.js +62 -0
  626. package/.agents/scripts/lib/worktree/lifecycle/force-drain.js +276 -0
  627. package/.agents/scripts/lib/worktree/lifecycle/gc.js +49 -0
  628. package/.agents/scripts/lib/worktree/lifecycle/merge-reachability.js +178 -0
  629. package/.agents/scripts/lib/worktree/lifecycle/pending-cleanup.js +264 -0
  630. package/.agents/scripts/lib/worktree/lifecycle/precheck.js +100 -0
  631. package/.agents/scripts/lib/worktree/lifecycle/reap.js +588 -0
  632. package/.agents/scripts/lib/worktree/lifecycle/registry-sync.js +124 -0
  633. package/.agents/scripts/lib/worktree/lifecycle/shared.js +26 -0
  634. package/.agents/scripts/lib/worktree/lifecycle-manager.js +40 -0
  635. package/.agents/scripts/lib/worktree/node-modules-strategy.js +349 -0
  636. package/.agents/scripts/lib/worktree-manager.js +243 -0
  637. package/.agents/scripts/lifecycle-diff.js +206 -0
  638. package/.agents/scripts/lifecycle-emit-story-dispatch.js +194 -0
  639. package/.agents/scripts/lifecycle-emit.js +479 -0
  640. package/.agents/scripts/lint-baseline.js +507 -0
  641. package/.agents/scripts/lint-label-vocabulary.js +237 -0
  642. package/.agents/scripts/loc-delta.js +205 -0
  643. package/.agents/scripts/notify.js +307 -0
  644. package/.agents/scripts/package.json +3 -0
  645. package/.agents/scripts/post-structured-comment.js +127 -0
  646. package/.agents/scripts/pr-watch-with-update.js +152 -0
  647. package/.agents/scripts/providers/github/auth.js +65 -0
  648. package/.agents/scripts/providers/github/board-add.js +63 -0
  649. package/.agents/scripts/providers/github/branch-protection.js +186 -0
  650. package/.agents/scripts/providers/github/cache.js +72 -0
  651. package/.agents/scripts/providers/github/comments.js +131 -0
  652. package/.agents/scripts/providers/github/compose.js +111 -0
  653. package/.agents/scripts/providers/github/errors.js +242 -0
  654. package/.agents/scripts/providers/github/issues.js +242 -0
  655. package/.agents/scripts/providers/github/labels.js +179 -0
  656. package/.agents/scripts/providers/github/mappers.js +126 -0
  657. package/.agents/scripts/providers/github/merge-methods.js +82 -0
  658. package/.agents/scripts/providers/github/project-board.js +47 -0
  659. package/.agents/scripts/providers/github/projects-v2-graphql.js +472 -0
  660. package/.agents/scripts/providers/github/prs.js +103 -0
  661. package/.agents/scripts/providers/github/request-helpers.js +110 -0
  662. package/.agents/scripts/providers/github/sub-issues.js +369 -0
  663. package/.agents/scripts/providers/github/tickets.js +381 -0
  664. package/.agents/scripts/providers/github/transient-retry.js +62 -0
  665. package/.agents/scripts/providers/github.js +157 -0
  666. package/.agents/scripts/quality-preview.js +327 -0
  667. package/.agents/scripts/quality-watch.js +223 -0
  668. package/.agents/scripts/render-manifest.js +143 -0
  669. package/.agents/scripts/resync-status-column.js +176 -0
  670. package/.agents/scripts/retro-run.js +167 -0
  671. package/.agents/scripts/run-audit-suite.js +97 -0
  672. package/.agents/scripts/run-coverage.js +103 -0
  673. package/.agents/scripts/run-lint.js +94 -0
  674. package/.agents/scripts/run-test-profile.js +126 -0
  675. package/.agents/scripts/run-tests.js +185 -0
  676. package/.agents/scripts/run-verify.js +56 -0
  677. package/.agents/scripts/select-audits.js +155 -0
  678. package/.agents/scripts/signals-view.js +294 -0
  679. package/.agents/scripts/single-story-close.js +83 -0
  680. package/.agents/scripts/single-story-confirm-merge.js +183 -0
  681. package/.agents/scripts/single-story-init.js +692 -0
  682. package/.agents/scripts/stories-wave-tick.js +415 -0
  683. package/.agents/scripts/story-close.js +246 -0
  684. package/.agents/scripts/story-deliver-prepare.js +267 -0
  685. package/.agents/scripts/story-init.js +516 -0
  686. package/.agents/scripts/story-phase.js +327 -0
  687. package/.agents/scripts/story-plan.js +284 -0
  688. package/.agents/scripts/sync-agentrc.js +71 -0
  689. package/.agents/scripts/sync-branch-from-base.js +138 -0
  690. package/.agents/scripts/sync-claude-commands.js +151 -0
  691. package/.agents/scripts/test-isolate.js +222 -0
  692. package/.agents/scripts/test-wrapper.js +108 -0
  693. package/.agents/scripts/update-coverage-baseline.js +129 -0
  694. package/.agents/scripts/update-crap-baseline.js +177 -0
  695. package/.agents/scripts/update-duplication-baseline.js +134 -0
  696. package/.agents/scripts/update-maintainability-baseline.js +183 -0
  697. package/.agents/scripts/update-mutation-baseline.js +189 -0
  698. package/.agents/scripts/update-ticket-state.js +107 -0
  699. package/.agents/scripts/validate-docs-freshness.js +259 -0
  700. package/.agents/scripts/validate-skills.js +278 -0
  701. package/.agents/scripts/wave-tick.js +335 -0
  702. package/.agents/skills/core/analyze-execution/SKILL.md +98 -0
  703. package/.agents/skills/core/api-and-interface-design/SKILL.md +327 -0
  704. package/.agents/skills/core/baseline-refresh/SKILL.md +181 -0
  705. package/.agents/skills/core/browser-testing-with-devtools/SKILL.md +352 -0
  706. package/.agents/skills/core/ci-cd-and-automation/SKILL.md +274 -0
  707. package/.agents/skills/core/ci-cd-and-automation/examples.md +211 -0
  708. package/.agents/skills/core/code-review-and-quality/SKILL.md +421 -0
  709. package/.agents/skills/core/code-simplification/SKILL.md +389 -0
  710. package/.agents/skills/core/context-engineering/SKILL.md +309 -0
  711. package/.agents/skills/core/context-engineering/examples.md +58 -0
  712. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +338 -0
  713. package/.agents/skills/core/deprecation-and-migration/SKILL.md +250 -0
  714. package/.agents/skills/core/diagnose-friction/SKILL.md +79 -0
  715. package/.agents/skills/core/documentation-and-adrs/SKILL.md +323 -0
  716. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +145 -0
  717. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +425 -0
  718. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +393 -0
  719. package/.agents/skills/core/frontend-ui-engineering/SKILL.md +357 -0
  720. package/.agents/skills/core/git-workflow-and-versioning/SKILL.md +352 -0
  721. package/.agents/skills/core/hydrate-context/SKILL.md +118 -0
  722. package/.agents/skills/core/idea-refinement/SKILL.md +317 -0
  723. package/.agents/skills/core/idea-refinement/examples.md +437 -0
  724. package/.agents/skills/core/idea-refinement/frameworks.md +135 -0
  725. package/.agents/skills/core/idea-refinement/refinement-criteria.md +155 -0
  726. package/.agents/skills/core/idea-refinement/scripts/idea-refine.sh +15 -0
  727. package/.agents/skills/core/incremental-implementation/SKILL.md +271 -0
  728. package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +213 -0
  729. package/.agents/skills/core/knowledge-transfer/SKILL.md +175 -0
  730. package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +117 -0
  731. package/.agents/skills/core/performance-optimization/SKILL.md +314 -0
  732. package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +277 -0
  733. package/.agents/skills/core/property-based-testing/SKILL.md +148 -0
  734. package/.agents/skills/core/qa-coverage-mapping/SKILL.md +105 -0
  735. package/.agents/skills/core/refactoring-discipline/SKILL.md +111 -0
  736. package/.agents/skills/core/scope-triage/SKILL.md +127 -0
  737. package/.agents/skills/core/security-and-hardening/SKILL.md +400 -0
  738. package/.agents/skills/core/shipping-and-launch/SKILL.md +328 -0
  739. package/.agents/skills/core/spec-driven-development/SKILL.md +252 -0
  740. package/.agents/skills/core/test-driven-development/SKILL.md +475 -0
  741. package/.agents/skills/core/using-agent-skills/SKILL.md +232 -0
  742. package/.agents/skills/skills.index.json +596 -0
  743. package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +31 -0
  744. package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +51 -0
  745. package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +48 -0
  746. package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +31 -0
  747. package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +33 -0
  748. package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +31 -0
  749. package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +51 -0
  750. package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +54 -0
  751. package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +29 -0
  752. package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +30 -0
  753. package/.agents/skills/stack/backend/stripe-integration/SKILL.md +57 -0
  754. package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +9 -0
  755. package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +48 -0
  756. package/.agents/skills/stack/frontend/astro/SKILL.md +62 -0
  757. package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +30 -0
  758. package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +29 -0
  759. package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +50 -0
  760. package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +58 -0
  761. package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +34 -0
  762. package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +51 -0
  763. package/.agents/skills/stack/qa/gherkin-authoring/SKILL.md +257 -0
  764. package/.agents/skills/stack/qa/gherkin-authoring/examples/invoice-issue.feature +41 -0
  765. package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +199 -0
  766. package/.agents/skills/stack/qa/playwright/SKILL.md +50 -0
  767. package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +188 -0
  768. package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +142 -0
  769. package/.agents/skills/stack/qa/qa-harness/SKILL.md +220 -0
  770. package/.agents/skills/stack/qa/vitest/SKILL.md +51 -0
  771. package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +68 -0
  772. package/.agents/starter-agentrc.json +22 -0
  773. package/.agents/templates/agent-protocol.md +72 -0
  774. package/.agents/templates/docs/architecture.md +30 -0
  775. package/.agents/templates/docs/decisions.md +24 -0
  776. package/.agents/templates/epic-from-idea.md +21 -0
  777. package/.agents/templates/single-story-body.md +17 -0
  778. package/.agents/workflows/agents-update.md +415 -0
  779. package/.agents/workflows/audit-architecture.md +312 -0
  780. package/.agents/workflows/audit-clean-code.md +179 -0
  781. package/.agents/workflows/audit-dependencies.md +91 -0
  782. package/.agents/workflows/audit-devops.md +110 -0
  783. package/.agents/workflows/audit-lighthouse.md +260 -0
  784. package/.agents/workflows/audit-performance.md +161 -0
  785. package/.agents/workflows/audit-privacy.md +104 -0
  786. package/.agents/workflows/audit-quality.md +191 -0
  787. package/.agents/workflows/audit-security.md +156 -0
  788. package/.agents/workflows/audit-seo.md +118 -0
  789. package/.agents/workflows/audit-sre.md +139 -0
  790. package/.agents/workflows/audit-to-stories.md +257 -0
  791. package/.agents/workflows/audit-ux-ui.md +102 -0
  792. package/.agents/workflows/epic-deliver.md +864 -0
  793. package/.agents/workflows/epic-plan.md +998 -0
  794. package/.agents/workflows/explain.md +118 -0
  795. package/.agents/workflows/git-cleanup.md +250 -0
  796. package/.agents/workflows/git-commit-all.md +15 -0
  797. package/.agents/workflows/git-merge-pr.md +377 -0
  798. package/.agents/workflows/git-pr-all.md +278 -0
  799. package/.agents/workflows/git-push.md +60 -0
  800. package/.agents/workflows/helpers/_merge-conflict-template.md +54 -0
  801. package/.agents/workflows/helpers/acceptance-self-eval.md +74 -0
  802. package/.agents/workflows/helpers/agents-sync-config.md +129 -0
  803. package/.agents/workflows/helpers/code-quality-guardrails.md +101 -0
  804. package/.agents/workflows/helpers/code-review.md +370 -0
  805. package/.agents/workflows/helpers/diagnose.md +117 -0
  806. package/.agents/workflows/helpers/epic-audit.md +295 -0
  807. package/.agents/workflows/helpers/epic-deliver-story.md +370 -0
  808. package/.agents/workflows/helpers/epic-plan-decompose.md +199 -0
  809. package/.agents/workflows/helpers/epic-plan-spec.md +184 -0
  810. package/.agents/workflows/helpers/epic-testing.md +125 -0
  811. package/.agents/workflows/helpers/parallel-tooling.md +88 -0
  812. package/.agents/workflows/helpers/signals.md +112 -0
  813. package/.agents/workflows/helpers/single-story-deliver.md +636 -0
  814. package/.agents/workflows/helpers/worktree-lifecycle.md +317 -0
  815. package/.agents/workflows/onboard.md +207 -0
  816. package/.agents/workflows/qa-assist.md +293 -0
  817. package/.agents/workflows/qa-explore.md +350 -0
  818. package/.agents/workflows/qa-run-harness.md +288 -0
  819. package/.agents/workflows/story-deliver.md +327 -0
  820. package/.agents/workflows/story-plan.md +233 -0
  821. package/LICENSE +21 -0
  822. package/README.md +193 -0
  823. package/bin/mandrel.js +56 -0
  824. package/bin/postinstall.js +195 -0
  825. package/lib/cli/__tests__/migrate.test.js +268 -0
  826. package/lib/cli/__tests__/sync-local-zone.test.js +247 -0
  827. package/lib/cli/__tests__/sync.test.js +372 -0
  828. package/lib/cli/__tests__/update-major.test.js +217 -0
  829. package/lib/cli/__tests__/update.test.js +696 -0
  830. package/lib/cli/__tests__/version-check.test.js +398 -0
  831. package/lib/cli/doctor.js +124 -0
  832. package/lib/cli/explain.js +107 -0
  833. package/lib/cli/migrate.js +260 -0
  834. package/lib/cli/registry.js +830 -0
  835. package/lib/cli/sync-commands.js +50 -0
  836. package/lib/cli/sync.js +200 -0
  837. package/lib/cli/uninstall.js +795 -0
  838. package/lib/cli/update.js +854 -0
  839. package/lib/cli/version-check.js +206 -0
  840. package/lib/migrations/README.md +69 -0
  841. package/lib/migrations/__tests__/index.test.js +216 -0
  842. package/lib/migrations/index.js +164 -0
  843. package/package.json +105 -0
@@ -0,0 +1,1420 @@
1
+ # Software Development Life Cycle (SDLC) Workflow
2
+
3
+ Mandrel uses **Epic-Centric GitHub Orchestration** — GitHub Issues,
4
+ Labels, and Projects V2 are the Single Source of Truth, fronted by a
5
+ declarative `epic.yaml` artifact that makes plans diff-able and
6
+ reconcilable. No per-iteration directories, no JSON state files for
7
+ ticket data.
8
+
9
+ The framework is **Claude Code-first**: `.claude/`, hooks, skills, and
10
+ the slash-command surface lean in on Claude Code as the reference
11
+ runtime, and the dispatcher (`.agents/scripts/`) treats the dispatch
12
+ manifest (md + structured comment) as the cross-runtime contract. See
13
+ ADR 20260512-coupling-stance in [`../docs/decisions.md`](../../docs/decisions.md).
14
+
15
+ ---
16
+
17
+ ## The simple flow
18
+
19
+ From zero to shipped:
20
+
21
+ 1. **Plan the work.** Run `/epic-plan` in your agentic IDE. The framework
22
+ generates a PRD, a Tech Spec, and an Acceptance Spec, decomposes the
23
+ work into the full Feature → Story hierarchy under the Epic, and
24
+ transitions the Epic to `agent::ready`.
25
+
26
+ The entry point you use selects where the run begins:
27
+ - With **no arguments** (or `--idea "<seed>"`), the workflow enters at
28
+ Phase 1 and runs the ideation phases (1–4) to open a fresh
29
+ `type::epic` Issue before authoring.
30
+ - With **`<epicId>`**, the workflow skips ideation and enters at
31
+ Phase 5 for an Epic Issue you have already opened.
32
+
33
+ > **Phase numbering note.** The numbered phases below are
34
+ > `/epic-plan`'s **internal** phases (1–11), not the SDLC-level
35
+ > Phase 0–4 used by the Mermaid diagram in [§ End-to-End
36
+ > Process](#end-to-end-process). Phases 1–4 run **only** on the
37
+ > ideation entry; an existing-Epic invocation starts at Phase 5.
38
+
39
+ 1. **Phase 1 — idea refinement** *(ideation entry only)* — the
40
+ `idea-refinement` skill drives a divergent → convergent → sharpen
41
+ loop and emits a one-pager with the five canonical Epic sections.
42
+ Stops for operator confirmation of the one-pager.
43
+ 2. **Phase 2 — cross-Epic duplicate search** *(ideation entry only)*
44
+ — `lib/duplicate-search.js` ranks open Epics whose scope overlaps
45
+ the one-pager; the operator confirms the idea is distinct or folds
46
+ it into an existing Epic (in which case `/epic-plan` exits).
47
+ 3. **Phase 3 — render Epic body** *(ideation entry only)* — renders
48
+ the confirmed one-pager into the canonical Epic-from-idea template
49
+ and stops for a final wording confirmation.
50
+ 4. **Phase 4 — open the Epic Issue** *(ideation entry only)* — opens
51
+ the GitHub Issue with **only** the `type::epic` label; the captured
52
+ id flows into the rest of the pipeline.
53
+ 5. **Phase 5 — re-plan detection** — checks whether the Epic already
54
+ carries planning artifacts and, if so, prompts before overwriting
55
+ the PRD / Tech Spec / Acceptance Spec in place and recreating the
56
+ Feature/Story tickets.
57
+ 6. **Phase 6 — Epic clarity gate** — scores the Epic body against the
58
+ five canonical sections. A `clear` verdict requires ≥ 4 of 5
59
+ sections present **and** the Acceptance Criteria section present (AC
60
+ is required, not optional). A `clear` verdict proceeds silently;
61
+ `needs-refinement` drops into a one-shot refinement loop with a HITL
62
+ diff before persisting the sharpened body.
63
+ 7. **Phase 7 — PRD, Tech Spec & Acceptance Spec** — the
64
+ `epic-plan-spec-author` skill authors all three planning artifacts
65
+ as linked context tickets, flips the Epic to `agent::review-spec`,
66
+ and routes high-risk Epics to a HITL review stop (low-risk Epics
67
+ auto-proceed).
68
+ 8. **Phase 8 — work-breakdown decomposition** — the
69
+ `epic-plan-decompose-author` skill emits the Epic → Feature → Story
70
+ tree (with inline `acceptance[]` / `verify[]` per Story); the
71
+ validator enforces hierarchy, DAG acyclicity, and file-assumption
72
+ invariants.
73
+ 9. **Phase 9 — execution roadmap** — runs the dispatcher in dry-run to
74
+ compute waves and posts the `dispatch-manifest` structured comment
75
+ that `/epic-deliver` consumes.
76
+ 10. **Phase 10 — readiness health check** — `epic-plan-healthcheck.js`
77
+ runs the default config + git-remote checks; a non-OK result is a
78
+ **blocking** exit condition for the `agent::ready` flip (overridable
79
+ only via the `planning::healthcheck-waived` label).
80
+ 11. **Phase 11 — plan comprehension gate** — an opt-in, advisory
81
+ walkthrough of the planned backlog driven by the
82
+ `core/knowledge-transfer` skill. Offered by LM judgment only on
83
+ non-trivial plans, runs **after** the `agent::ready` flip, and is
84
+ interruptible at every checkpoint — it never blocks the hand-off.
85
+ 12. **Phase 12 — notification & hand-off** — posts the backlog summary
86
+ comment, @mentions the operator, and names `/epic-deliver` as the
87
+ next step.
88
+
89
+ 2. **Deliver the Epic.** Run `/epic-deliver <epicId>` in your IDE. The
90
+ skill drives the merged execute + close flow end-to-end.
91
+
92
+ > **Phase numbering note.** The numbered phases below refer to
93
+ > `/epic-deliver`'s **internal** phases (1–9), not the SDLC-level
94
+ > Phase 0–4 used by the Mermaid diagram in [§ End-to-End
95
+ > Process](#end-to-end-process). When prose elsewhere in this
96
+ > document says "Phase 7", it always means the internal
97
+ > `/epic-deliver` phase unless explicitly prefixed with "SDLC".
98
+
99
+ 1. **Phase 1 — prepare** — snapshot the Epic, build the wave DAG,
100
+ initialise the `epic-run-state` checkpoint.
101
+ 2. **Phase 2 — wave loop** — fan one `/story-deliver` Agent-tool
102
+ sub-agent out per Story per wave (capped at `concurrencyCap`).
103
+ Stories run in parallel inside the operator's Claude session
104
+ against your Max subscription quota; no subprocess worker sessions
105
+ for Story execution, no GitHub Actions minutes. Deterministic
106
+ Node CLIs remain the state-mutation contract.
107
+ 3. **Phase 3 — close-validation** — lint, test, and the project's
108
+ ratcheted baselines run against the Epic branch. Evidence is
109
+ cached by HEAD SHA so re-runs short-circuit.
110
+ 4. **Phase 4 — audit** — runs the change-set audit lenses against
111
+ the Epic diff; findings flow through as advisory signal.
112
+ 5. **Phase 5 — code-review** — auto-invokes the in-process
113
+ `lib/orchestration/code-review.js` (extracted from the old
114
+ `helpers/code-review.md` helper); findings persist as a
115
+ `code-review` structured comment on the Epic. Critical findings
116
+ halt the run.
117
+ 6. **Phase 6 — retro** — auto-invokes the in-process
118
+ `lib/orchestration/retro-runner.js` (extracted from the old
119
+ retro helper) and posts the structured retro comment on the
120
+ Epic. The retro fires **before** the PR is opened so it has
121
+ full env access in the operator's local session.
122
+ 7. **Phase 7 — finalize** — pushes `epic/<epicId>` to `origin`,
123
+ opens a pull request to `main`, sets the required-checks
124
+ expectation from `github.branchProtection.requiredChecks`, and
125
+ posts the hand-off comment naming the PR URL. The Epic stays
126
+ at `agent::executing` until the PR merges; the standard
127
+ label-transition pathway flips it to `agent::done` on merge.
128
+ Finalize hands off to the watch / auto-merge / cleanup tail
129
+ below — it does **not** stop the run.
130
+ 8. **Phase 8 — watch-and-iterate** — watches CI on the open PR
131
+ until checks turn green (or a failure surfaces for human
132
+ remediation).
133
+ 9. **Phase 8.5 — auto-merge** — arms GitHub native auto-merge
134
+ (`gh pr merge --auto --squash --delete-branch`) once the
135
+ required checks have passed so the PR lands without a second
136
+ operator visit. The operator can disarm auto-merge in the
137
+ GitHub UI if they want to gate the merge manually.
138
+ 10. **Phase 9 — cleanup** — reaps local Story/Epic branch refs and
139
+ worktrees after the PR merges so the workspace returns to a
140
+ clean state for the next Epic.
141
+
142
+ For a single Epic-attached Story (re-driving a hotfix, resuming after
143
+ a halt), re-run `/epic-deliver <epicId>` — the wave loop picks up
144
+ incomplete Stories from the dispatch manifest automatically. Standalone
145
+ Stories (no `Epic: #N` reference) use `/story-deliver <storyId>` instead.
146
+
147
+ That is the whole happy path. Everything below is **detail** — branching
148
+ conventions, HITL escalation, audit gates — that you only need when the
149
+ default flow requires adjustment.
150
+
151
+ ---
152
+
153
+ ## Core Principles
154
+
155
+ - **Layered state stores with explicit precedence.** Project logic, work
156
+ breakdown, and ticket status live in GitHub Issues and Labels; the
157
+ lifecycle bus (`temp/epic-<id>/lifecycle.ndjson`) is the canonical
158
+ resume target for in-flight runs; structured comments
159
+ (`epic-run-state`, `story-run-progress`) are the operator-visible
160
+ rollup. The seven stores, their owners, and their conflict-resolution
161
+ rules are listed in [§ State stores](#state-stores) — that matrix is
162
+ the single source of truth for "who owns which write" and supersedes
163
+ the earlier "GitHub as SSOT" / "lifecycle ledger canonical" prose.
164
+ - **Provider Abstraction.** Orchestration flows through `ITicketingProvider`, an
165
+ abstract interface with a shipped GitHub implementation.
166
+ - **Story-Level Branching.** All work for a Story lands on the shared
167
+ `story-<id>` branch. Stories merge into `epic/<epicId>`; the Epic
168
+ branch reaches `main` only via a pull request the operator merges
169
+ through the GitHub UI.
170
+ - **Hierarchy-aligned skills.** Execution is split along the ticket
171
+ hierarchy: `/epic-plan` builds the backlog (with optional ideation
172
+ entry), `/epic-deliver` owns the merged wave-loop + close-tail, and
173
+ `/story-deliver` delivers one or more standalone Stories end-to-end.
174
+ `helpers/epic-deliver-story` and `helpers/single-story-deliver` are the
175
+ per-Story workers called by those two commands respectively. All share
176
+ the same primitives (`Graph.computeWaves`, `cascadeCompletion`,
177
+ `ticketing.js`, `WorktreeManager`).
178
+ - **Single-session fan-out.** `/epic-deliver` launches Story sub-agents via
179
+ the Agent tool — every Story runs inside the operator's Claude session,
180
+ with no subprocess boundary. Worktree filesystem isolation is preserved;
181
+ only the process boundary is gone.
182
+ - **PR is the sole promotion gate.** `/epic-deliver` ends with a PR open
183
+ against `main` and (by default) GitHub native auto-merge armed; the
184
+ workflow itself never executes `git merge` against `main`. Branch
185
+ protection on `main` enforces required-checks before the merge button
186
+ (auto or manual) fires. The operator can disarm auto-merge in the
187
+ GitHub UI to make the merge an explicit human action.
188
+ - **HITL-minimal by default.** Exactly one mandatory operator touchpoint on
189
+ the happy path — blocker resolution mid-run. PR merge is autonomous via
190
+ the armed auto-merge; the operator becomes a second touchpoint only when
191
+ they disarm auto-merge or when required checks fail and need
192
+ remediation.
193
+
194
+ ---
195
+
196
+ ## State stores
197
+
198
+ Mandrel writes orchestration state across seven distinct stores. Each
199
+ store has exactly one canonical writer and one well-defined idempotency
200
+ key; conflicts between stores are resolved in the **Conflict
201
+ resolution** column. When the same fact appears in more than one store
202
+ (common during a run — labels mirror lifecycle events, comments mirror
203
+ ledger entries) the entry below names the authoritative reader for that
204
+ fact so downstream code does not have to guess.
205
+
206
+ | State Store | Owner (canonical writer) | Mutation API | Idempotency key | Conflict resolution |
207
+ | --------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
208
+ | GitHub labels | `transitionTicketState` via `ticketing.js` | `gh issue edit --add-label / --remove-label`, wrapped in `update-ticket-state.js` | `(ticketId, label-set)` — set-equality check before write | Authoritative for current ticket lifecycle state; if the label disagrees with the lifecycle ledger, the **ledger wins on resume** and the label is re-derived. |
209
+ | `epic-run-state` comment | `checkpointer` submodule in the Epic Deliver Runner | `post-structured-comment.js` (upsert by `kind`) | `(epicId, kind='epic-run-state')` | Operator-visible rollup of phase progress; on conflict with the lifecycle ledger, the ledger is authoritative and the comment is re-rendered. |
210
+ | `story-run-progress` comment | `story-phase.js` (per Story, per phase transition) | `post-structured-comment.js` (upsert by `kind`) | `(storyId, kind='story-run-progress')` | Authoritative for Story-level phase progress; the wave aggregator reads this comment, not labels. |
211
+ | Lifecycle ledger NDJSON | `lifecycle-emit.js` (single append-only writer per Epic run) | Append-only line write to `temp/epic-<id>/lifecycle.ndjson` | `(epicId, eventId)` — `eventId` is a content hash of `{type, ts, payload}` | **Canonical resume target.** When labels / comments disagree with the ledger, the ledger wins and the others are re-derived from it. |
212
+ | Validation evidence cache | `evidence-gate.js` | JSON cache file under `temp/epic-<id>/evidence/<gate>/<sha>.json` | `(gate, git rev-parse HEAD)` | Pure cache: a missing entry triggers a re-run; presence is a fast-path skip. Cache eviction is safe. |
213
+ | PR / auto-merge state | `AutomergeArmer` listener (sole authorized caller of `gh pr merge`) | `gh pr merge --auto --squash --delete-branch`; PR open via `openOrLocatePr` in `Finalizer` | `(prNumber, head-branch SHA)` — `gh pr view` probes existing PR before create | GitHub is authoritative for PR + auto-merge arming state; the lifecycle ledger records the *intent* to arm, GitHub records the outcome. |
214
+ | Worktree cleanup state | `WorktreeManager.reap` (via `story-close.js` / cleanup state) | `git worktree remove` + on-disk pending-cleanup JSON under `temp/epic-<id>/worktree-cleanup.json` | `(storyId, worktree-path)` | Filesystem is authoritative for "is the worktree gone?"; the pending-cleanup JSON only tracks Windows stale-registry entries that need a follow-up sweep. |
215
+
216
+ ---
217
+
218
+ ## End-to-End Process
219
+
220
+ ```mermaid
221
+ graph LR
222
+ classDef manual fill:#f9d0c4,stroke:#333,stroke-width:2px,color:#000;
223
+ classDef agentic fill:#c4f9d0,stroke:#333,stroke-width:2px,color:#000;
224
+ classDef artifact fill:#ececec,stroke:#333,stroke-width:1px,stroke-dasharray: 5 5,color:#000;
225
+
226
+ subgraph Phase0 ["Phase 0: Bootstrap"]
227
+ direction TB
228
+ Z["👤 npx create-mandrel<br/>(install → sync → bootstrap.js)"]:::manual
229
+ Z2["👤 /onboard (guided first run)"]:::manual
230
+ Z --> Z2
231
+ end
232
+
233
+ subgraph Phase1 ["Phase 1: Initiation"]
234
+ direction TB
235
+ A["👤 /epic-plan (ideation)<br/>or 👤 Create GitHub Epic + /epic-plan &lt;id&gt;"]:::manual
236
+ end
237
+
238
+ subgraph Phase2 ["Phase 2: Planning"]
239
+ direction TB
240
+ C["🤖 PRD + Tech Spec authoring"]:::agentic
241
+ D["🤖 Ticket Decomposer"]:::agentic
242
+ C --> D
243
+ D -.-> D_Art["📄 GitHub Issue Hierarchy"]:::artifact
244
+ end
245
+
246
+ subgraph Phase3 ["Phase 3: Delivery"]
247
+ direction TB
248
+ E["👤 /epic-deliver &lt;epicId&gt;"]:::manual
249
+ F["🤖 wave loop (one /story-deliver sub-agent per Story per wave)"]:::agentic
250
+ G["🤖 close-validation → code-review → retro → open PR"]:::agentic
251
+ E --> F --> G
252
+ G -.-> G_Art["📄 PR open against main"]:::artifact
253
+ end
254
+
255
+ subgraph Phase4 ["Phase 4: PR merge (auto by default)"]
256
+ direction TB
257
+ H["🤖 Auto-merge armed → PR lands when checks pass<br/>(👤 operator may disarm to merge manually)"]:::agentic
258
+ end
259
+
260
+ Z2 --> A
261
+ A --> C
262
+ D --> E
263
+ G --> H
264
+ ```
265
+
266
+ ---
267
+
268
+ ## Phase 0: Bootstrap (One-Time Setup)
269
+
270
+ Before any Epic workflow, bootstrap your project to seed `.agentrc.json`,
271
+ wire the framework system prompt, and create the GitHub labels, Projects V2
272
+ fields, and (when enabled) main-branch protection the orchestration engine
273
+ depends on.
274
+
275
+ The canonical cold-start path is a single launcher command:
276
+
277
+ ```bash
278
+ npx create-mandrel
279
+ ```
280
+
281
+ `create-mandrel` installs `mandrel`, materializes `./.agents/` via
282
+ `mandrel sync`, and runs `node .agents/scripts/bootstrap.js`, forwarding any
283
+ flags you pass. `bootstrap.js`:
284
+
285
+ 1. **Provisions a cold start.** Initializes the local git repo (with a first
286
+ commit) when absent, creates the GitHub repo (`gh repo create --source=.
287
+ --push`; choose visibility with `--visibility private|public|internal`,
288
+ default `private`), and creates the Projects V2 board (`gh project
289
+ create`) when it doesn't exist. No pre-created repo or remote is required.
290
+ 2. **Seeds `.agentrc.json`** from `.agents/starter-agentrc.json` (the `github`
291
+ section carries owner, repo, base branch, operator handle, and project
292
+ number — inferred from your local `git` config where possible). See
293
+ `.agents/docs/agentrc-reference.json` for the exhaustive reference of every
294
+ available key.
295
+ 3. **Creates the label taxonomy and Projects V2 fields**, and — when
296
+ `github.branchProtection.enforce` is `true` (default) — creates or merges
297
+ branch protection on `main` with the project's
298
+ `github.branchProtection.requiredChecks` as required status checks. This
299
+ step is load-bearing for the SDL because PR merges to `main` are the sole
300
+ promotion gate.
301
+
302
+ When `.agents/` is already materialized you can run the bootstrap directly
303
+ (`node .agents/scripts/bootstrap.js`). After bootstrap, run **`/onboard`**
304
+ inside Claude Code for the guided first run — stack detection, docs
305
+ scaffolding, a `mandrel doctor` readiness gate, and a started `/epic-plan`.
306
+
307
+ > [!NOTE] Bootstrap runs once per repository. It is safe to re-run — existing
308
+ > labels, fields, and branch-protection entries are preserved; missing ones
309
+ > are added.
310
+
311
+ ---
312
+
313
+ ## Phase 1: Initiation
314
+
315
+ The product lead defines the objective and triggers planning.
316
+
317
+ ### 1a. Ideation entry (optional)
318
+
319
+ Run `/epic-plan` with no arguments (or `--idea "<seed>"`) to enter ideation
320
+ mode:
321
+
322
+ 1. **Sharpen the idea.** The `idea-refinement` skill drives a divergent →
323
+ convergent → sharpen loop and emits a markdown one-pager with the
324
+ five canonical Epic sections (Context, Goal, Non-Goals, Scope,
325
+ Acceptance Criteria).
326
+ 2. **Scope triage (Phase 1.5).** Before the ceremony is paid for, the
327
+ one-pager is judged against the story-vs-epic rubric (see the
328
+ subsection below). On a `story` / `borderline` verdict the operator may
329
+ route the work to `/story-plan` instead of opening an Epic.
330
+ 3. **Cross-Epic duplicate search.** `lib/duplicate-search.js` queries the
331
+ open Epics in the repo, scores by title + body keyword overlap, and
332
+ surfaces matches above a threshold. The operator either confirms the
333
+ new idea is genuinely distinct or folds it into an existing Epic
334
+ (`/epic-plan` exits and the operator resumes work on the existing
335
+ id).
336
+ 4. **Render and confirm the Epic body.** The one-pager is rendered into
337
+ the canonical Epic-from-idea template; the operator confirms before
338
+ the GitHub Issue is opened.
339
+ 5. **Open the Epic.** The Issue is opened with **only** the `type::epic`
340
+ label — no `state::*` label is applied at creation. PRD authoring in
341
+ Phase 1b advances it to `agent::review-spec`.
342
+
343
+ #### Scope triage
344
+
345
+ `/epic-plan` Phase 1.5 runs the
346
+ [`core/scope-triage`](../skills/core/scope-triage/SKILL.md) rubric over the
347
+ sharpened one-pager so a story-sized scope is not pushed through the full Epic
348
+ ceremony (PRD + Tech Spec + Acceptance Spec + Feature/Story tree +
349
+ `epic/<id>` integration branch) only to land as a degenerate one-Feature,
350
+ one-Story output. The rubric anchors its sizing judgment **by reference** to
351
+ the existing sizing SSOT (`DELIVERABLE_GRANULARITY_GUIDANCE` /
352
+ `DEFAULT_TASK_SIZING` in `ticket-validator-sizing.js`) and emits one of three
353
+ verdicts — `epic` | `story` | `borderline`.
354
+
355
+ The verdict is **host-LLM judgment** (no scorer, no schema, no label
356
+ transition) and **advisory** — the operator always decides. It folds into the
357
+ existing Phase 1 HITL confirmation rather than adding a second stop: an `epic`
358
+ verdict proceeds with a plain confirm, while a `story` / `borderline` verdict
359
+ offers a three-way choice (single Story / plan as Epic anyway / abort). On an
360
+ accepted `story`, `/epic-plan` hands the one-pager off to
361
+ `/story-plan --from-notes` as a scope-triage handoff and exits. Phase 1.5 is
362
+ skipped when `/epic-plan` is itself entered via a scope-triage handoff, so the
363
+ two workflows never ping-pong a settled decision.
364
+
365
+ The same rubric also guards the **existing-Epic entry** (1b) as the
366
+ **Phase 5.5 story-sized advisory**, which catches a story-sized scope that was
367
+ hand-opened directly as a `type::epic` issue (the Phase 6 Epic Clarity Gate
368
+ scores section *presence*, not scope *size*, so a clear-but-thin Epic would
369
+ otherwise sail through). The advisory fires **only** when Phase 5 found no
370
+ linked PRD / Tech Spec **and** the Epic has no open Feature/Story children, so
371
+ it never re-triages an Epic that is being re-planned. An `epic` verdict
372
+ proceeds silently; a `story` / `borderline` verdict STOPs with the same
373
+ three-way choice (convert to a standalone Story / proceed as Epic anyway /
374
+ abort). Converting is **close-and-recreate** — a `type::epic` body cannot
375
+ satisfy `validateStoryBody`, and editing the issue in place would violate the
376
+ "do not modify existing issues without explicit permission" rule — so, only
377
+ after the operator confirms, the Epic body seeds a notes file,
378
+ `/story-plan --from-notes` opens a replacement Story (identified as a
379
+ scope-triage handoff so it skips its own gate, with a `## Notes` back-link to
380
+ the Epic), and the Epic is closed with `gh issue close --comment` cross-linking
381
+ the replacement. No deterministic scorer, no schema, and no label transition
382
+ sit behind either gate.
383
+
384
+ The rubric also runs in the **escalation direction** — the symmetric
385
+ counterpart in [`/story-plan`](../workflows/story-plan.md). After `/story-plan`
386
+ Phase 2 drafts a standalone Story body (the draft, not the seed, is the honest
387
+ basis for the judgment), the same `core/scope-triage` rubric judges whether the
388
+ scope is actually Epic-sized. The verdict folds into the existing Phase 2
389
+ draft-confirmation HITL stop with no extra stop on a `story` verdict; an `epic`
390
+ verdict offers a three-way choice (escalate to `/epic-plan --idea` as a
391
+ scope-triage handoff / persist as a standalone Story anyway / abort). On an
392
+ accepted escalation, `/story-plan` abandons the draft and hands the notes off to
393
+ `/epic-plan --idea`, marked as a handoff so `/epic-plan` skips its own Phase 1.5
394
+ gate. This gate is itself skipped when `/story-plan` was entered via a
395
+ scope-triage handoff (from `/epic-plan` Phase 1.5 or the Phase 5.5 conversion
396
+ path), so the two workflows never ping-pong a settled decision. As with the
397
+ inbound gates, the verdict is advisory and host-LLM judgment — no auto-routing,
398
+ no scorer, no schema, and no label transition.
399
+
400
+ ### 1b. Existing-Epic entry
401
+
402
+ Run `/epic-plan <epicId>` directly when the Epic Issue already exists. The
403
+ ideation phases (1a) are skipped.
404
+
405
+ In both modes the planning flow continues into Phase 2 with the captured
406
+ Epic id.
407
+
408
+ ---
409
+
410
+ ## Phase 2: Planning (Autonomous)
411
+
412
+ The framework reads the Epic and autonomously builds the entire work breakdown.
413
+
414
+ > **Epic Clarity Gate (`/epic-plan` `planning.clarity-gate` state).** Before PRD / Tech Spec /
415
+ > Acceptance Spec authoring kicks off, `/epic-plan` scores the Epic body
416
+ > against the five canonical sections from
417
+ > [`templates/epic-from-idea.md`](../templates/epic-from-idea.md) (Context,
418
+ > Goal, Non-Goals, Scope, Acceptance Criteria). Common legacy heading
419
+ > variants (`Problem`, `Direction`, `MVP Scope`, `Not Doing`,
420
+ > `Out of Scope`) are accepted by the scorer's regex for back-compat.
421
+ > The rubric is deterministic (section-presence): `clear` requires ≥ 4 of 5
422
+ > sections present **and** the Acceptance Criteria section present (AC is
423
+ > required). A
424
+ > `clear` verdict
425
+ > skips fast with no prompt; a `needs-refinement` verdict drops into the
426
+ > `idea-refinement` skill seeded from the current Epic body, surfaces a
427
+ > HITL diff, and on approval persists the sharpened body via
428
+ > `gh issue edit` before the `planning.spec-authoring` state begins.
429
+ > The gate honours the
430
+ > "do not modify existing issues without permission" Constraint — every
431
+ > body rewrite is operator-confirmed.
432
+
433
+ 1. **Epic Planner** (`epic-plan-spec.js`):
434
+ - Synthesizes the Epic body with project documentation.
435
+ - Generates a **PRD** (`context::prd`), **Tech Spec**
436
+ (`context::tech-spec`), and **Acceptance Spec**
437
+ (`context::acceptance-spec`) as linked GitHub Issues.
438
+
439
+ > [!TIP] **PRD authoring — acceptance criteria phrasing.** Write acceptance
440
+ > criteria in Gherkin-compatible `Given / When / Then` form so the QA
441
+ > acceptance suite can lift them directly into executable `.feature` files. See
442
+ > [`rules/gherkin-standards.md`](../rules/gherkin-standards.md) for the canonical
443
+ > clause grammar, tag taxonomy, and forbidden patterns.
444
+
445
+ ### Acceptance Spec — the third planning context ticket
446
+
447
+ Every Epic carries **three** planning context tickets, not two:
448
+
449
+ | Label | Artifact | Authored by | Drives |
450
+ | --------------------------- | ---------------- | --------------------------------------------------- | -------------------------------------------------------- |
451
+ | `context::prd` | PRD | `epic-plan-spec-author` skill (PRD persona) | What we're shipping and why. |
452
+ | `context::tech-spec` | Tech Spec | `epic-plan-spec-author` skill (Architect persona) | How we're shipping it. |
453
+ | `context::acceptance-spec` | Acceptance Spec | `epic-plan-spec-author` skill (Acceptance Engineer) | The AC ID table that gates close-time reconciliation. |
454
+
455
+ The Acceptance Spec body is a single Markdown table —
456
+ `| AC ID | Outcome | Feature File | Scenario | Disposition |` — with
457
+ stable `AC-<n>` IDs assigned in document order. IDs are reused across
458
+ re-plans when an Outcome is materially unchanged so scenario tags
459
+ (`@ac-N`) stay aligned with the spec. Each row's `Disposition` is one
460
+ of `new | updated | unchanged`. The skill also renders a **Runner
461
+ Verification** line directly under the table that records the verified
462
+ BDD runner + pending-tag (e.g. `playwright-bdd supports @skip`) for the
463
+ features-first Story to consume.
464
+
465
+ The spec is persisted by
466
+ `epic-plan-spec.js --epic [Epic_ID] --prd ... --techspec ... --acceptance-spec ...`
467
+ — the persist half writes all three artifacts in one atomic step and
468
+ fails loudly if any is missing or empty.
469
+
470
+ #### Adaptive planning risk routing
471
+
472
+ `/epic-plan`'s `planning.spec-authoring` state derives a deterministic
473
+ **`planningRisk`** envelope from a **planner-authored risk verdict**
474
+ (`risk-verdict.json`, the fourth planning artifact the
475
+ `epic-plan-spec-author` Skill writes from the PRD / Tech Spec it just
476
+ authored). The persist half of `epic-plan-spec.js` validates the verdict
477
+ against `risk-verdict.schema.json` — a malformed verdict fails closed —
478
+ then derives the envelope via `deriveRiskEnvelope`
479
+ (`lib/orchestration/planning-risk.js`). The verdict is recorded as a
480
+ `risk-verdict` structured comment on the Epic, and both the verdict and
481
+ the envelope land in the `epic-plan-state` checkpoint, consumed by two
482
+ downstream decisions:
483
+
484
+ - **Acceptance disposition** — `acceptanceDisposition` is one of
485
+ `required`, `recommended`, or `not-applicable`. The `not-applicable`
486
+ case is the planner-selected route to the `acceptance::n-a` waiver
487
+ (see the section below); the other two cause the Acceptance Spec to
488
+ be authored normally.
489
+ - **Gate routing** — `gateDecision` is either `review-required`
490
+ (paired with `requiresReview: true`) or `auto-proceed`. High-risk
491
+ Epics (visible behavior, public API, security, billing, data
492
+ migration, destructive mutation, critical workflow) trigger a HITL
493
+ stop after `planning.spec-authoring` so the operator can read the
494
+ PRD / Tech Spec / Acceptance Spec on GitHub before decomposition
495
+ starts. Low-risk Epics (docs-only, internal refactor, pure test
496
+ harness, cleanup) print the auto-proceed message from
497
+ `reviewRouting.operatorMessage` and chain directly into the
498
+ `planning.decompose` state. The operator can force the review
499
+ stop on low-risk work by passing `--force-review` to `/epic-plan`.
500
+
501
+ The risk envelope is also threaded into the `planning.decompose` state's decomposer context
502
+ so the ticket array can cite the relevant axes when assigning
503
+ `risk::high` labels to Stories. The split is "judgment proposes, harness
504
+ gates": the planner supplies the axes (with per-axis rationale), and the
505
+ envelope derivation — overall level, review requirement, acceptance
506
+ disposition, gate decision — is local and deterministic.
507
+
508
+ #### Opting out — the `acceptance::n-a` waiver
509
+
510
+ Not every Epic warrants a formal Acceptance Spec (pure refactors,
511
+ framework maintenance, docs-only churn). The **`acceptance::n-a`** label
512
+ on the Epic ticket records the waiver. There are two routes to the label:
513
+
514
+ - **Operator-applied** — the operator labels the Epic before or during
515
+ `/epic-plan`'s `planning.spec-authoring` state when they already
516
+ know the work does not need a spec.
517
+ - **Planner-selected** — `/epic-plan`'s `planning.spec-authoring` state derives a
518
+ `planningRisk` envelope from the planner-authored risk verdict
519
+ (see § Adaptive planning risk routing) and,
520
+ when `acceptanceDisposition === 'not-applicable'`, the persist half
521
+ of `epic-plan-spec.js` applies `acceptance::n-a` on the Epic and skips
522
+ the Acceptance Spec artifact for that run. The disposition is also
523
+ recorded in the `epic-plan-state` checkpoint so the decision is
524
+ auditable.
525
+
526
+ Either route produces the same runtime behavior. The waiver is respected
527
+ by both runtime gates:
528
+
529
+ - The `/epic-deliver` **start gate** (`delivery.snapshot` state) skips
530
+ the acceptance-spec presence check when the label is set.
531
+ - The finalize-time **acceptance-spec reconciler** returns
532
+ `status: 'waived'` without scanning `tests/features/**` and the
533
+ finalize step proceeds.
534
+
535
+ The waiver is binary — there is no partial opt-out. If an Epic later
536
+ warrants spec coverage, remove the label and run `/epic-plan`'s
537
+ `planning.spec-authoring` state to author the spec.
538
+
539
+ 1. **Ticket Decomposer** (`epic-plan-decompose.js`):
540
+ - Recursively decomposes specs into the **3-tier hierarchy**
541
+ (Epic → Feature → Story):
542
+
543
+ ```text
544
+ Epic (type::epic)
545
+ ├── PRD (context::prd)
546
+ ├── Tech Spec (context::tech-spec)
547
+ ├── Feature (type::feature)
548
+ │ ├── Story (type::story)
549
+ │ │ ├── acceptance[] ← inline on Story body
550
+ │ │ └── verify[] ← inline on Story body
551
+ │ └── Story (type::story)
552
+ └── Feature (type::feature)
553
+ ```
554
+
555
+ - **Wiring.** Each ticket is linked using `blocked by #NNN` syntax and
556
+ GitHub's native sub-issues API.
557
+ - **Metadata.** Each Story is stamped with persona, estimated files,
558
+ and agent prompts, plus the inline `acceptance[]` / `verify[]`
559
+ arrays the executing sub-agent reads.
560
+
561
+ `/story-deliver` runs a **single** Story-implementation phase per
562
+ Story. The wave-loop fan-out in `/epic-deliver`, the Epic → Feature
563
+ thematic frame, and the Story-branch → Epic-branch merge model are
564
+ unchanged from the prior 4-tier shape; only the Task layer is gone.
565
+
566
+ When decomposition completes the Epic flips to `agent::ready` and the
567
+ dispatch manifest is posted as a structured comment on the Epic. That
568
+ manifest is the source of truth for the wave layout `/epic-deliver`
569
+ consumes in the `delivery.snapshot` state.
570
+
571
+ ### `agent::ready` exit conditions
572
+
573
+ The planning → delivery handoff is governed by an explicit checklist.
574
+ The persist half of `epic-plan-decompose.js` refuses to flip the Epic
575
+ to `agent::ready` unless **every** condition below is true. The
576
+ contract is enforced at the planner boundary so `/epic-deliver` can
577
+ treat `agent::ready` as a load-bearing precondition rather than a
578
+ hopeful signal.
579
+
580
+ - **Planning artifacts linked or waived.** The Epic body lists a
581
+ linked `context::prd` and `context::tech-spec` ticket, and either a
582
+ linked `context::acceptance-spec` ticket **or** the
583
+ `acceptance::n-a` waiver label. Missing-without-waiver fails the
584
+ handoff.
585
+ - **Decomposition persisted.** The structural reconciler has applied
586
+ the Feature/Story/Task hierarchy and written the spec to
587
+ `.agents/epics/<epicId>.yaml`. The `epic-plan-state` checkpoint
588
+ comment records `phase: ready`.
589
+ - **Dispatch manifest posted.** A single `epic-dispatch` structured
590
+ comment exists on the Epic and validates against
591
+ `.agents/schemas/dispatch-manifest.json`. The dispatch manifest is
592
+ the source of truth `/epic-deliver` reads during
593
+ `delivery.snapshot`.
594
+ - **Healthcheck green.** `epic-plan-healthcheck.js` (run during
595
+ `/epic-plan` Phase 10) returned `ok: true`. A failing healthcheck
596
+ blocks the handoff — there is no advisory degrade-mode for
597
+ `agent::ready`.
598
+ - **Notification posted.** The planner has posted the
599
+ `planning.handoff` notification on the Epic so the operator and any
600
+ subscribed listeners know the Epic is ready to fan out.
601
+
602
+ **Operator override.** The `planning::healthcheck-waived` label, applied
603
+ to the Epic by the operator, is the documented escape hatch for cases
604
+ where the healthcheck reports `ok: false` for an environmental reason
605
+ the operator has triaged and accepted (for example: a transient
606
+ `origin` outage during a known maintenance window). When the label is
607
+ present, the persist half allows the `agent::ready` flip even though
608
+ the healthcheck failed. Every other exit condition above still
609
+ applies — the waiver scopes to the healthcheck check alone. Remove
610
+ the label to re-arm the gate.
611
+
612
+ ---
613
+
614
+ ## Phase 3: Delivery (Agentic)
615
+
616
+ Delivery is driven by the **`/epic-deliver`** slash command for whole-Epic
617
+ flows and the **Story Init/Close** scripts for individual Stories. All entry
618
+ points share the same primitives — DAG computation, context hydration,
619
+ worktree isolation, and cascade closure. The lifecycle bus listener
620
+ chain inside the session is the single runtime; it owns wave fan-out,
621
+ finalize, automerge, and cleanup. The `delivery.finalize`,
622
+ `delivery.automerge`, and `delivery.complete` states each fire one
623
+ typed event via `lifecycle-emit.js` (`epic.close.end`,
624
+ `epic.automerge.start`, `epic.merge.armed`); the matching listeners run
625
+ the side effects. See
626
+ [`docs/LIFECYCLE.md`](../../docs/LIFECYCLE.md) for the bus contract,
627
+ event taxonomy, ledger format, and listener model — every phase
628
+ transition, ticket-state flip, and webhook fan-out now flows through
629
+ that bus, and the on-disk ledger at `temp/epic-<id>/lifecycle.ndjson`
630
+ is the canonical resume target. Safety gates (auto-merge arming,
631
+ acceptance-spec reconciliation, blocker handling) are listener
632
+ side-effects rather than inline calls at phase boundaries; the
633
+ "merge-lockout" lint rule keeps `gh pr merge` confined to the
634
+ `AutomergeArmer` listener.
635
+
636
+ > **Acceptance-spec start gate.** Before a single wave fans out,
637
+ > `/epic-deliver`'s `delivery.snapshot` state
638
+ > ([`lib/orchestration/epic-runner/phases/snapshot.js`](../scripts/lib/orchestration/epic-runner/phases/snapshot.js))
639
+ > asserts that the Epic either (a) carries the `acceptance::n-a`
640
+ > waiver label, or (b) has a linked `context::acceptance-spec`
641
+ > ticket. The ticket's GitHub state (open / closed) is not checked
642
+ > — presence is sufficient, matching the PRD and Tech Spec contract.
643
+ > The reviewer's OK during `/epic-plan`'s `planning.spec-authoring`
644
+ > state is the approval
645
+ > signal, not a manual ticket-close action; the three planning
646
+ > context tickets are closed automatically by the
647
+ > `Finalizer` listener subscribed to `epic.close.end` once the
648
+ > Epic PR opens. Neither
649
+ > condition met → the snapshot throws a clear error naming the
650
+ > missing precondition and `runAsCli` maps it to `process.exit(1)`.
651
+ > This refuses to launch Epics that skipped acceptance-spec
652
+ > authoring, surfacing the gap at delivery time rather than letting
653
+ > Story dispatch race ahead.
654
+
655
+ ### Invocation modes
656
+
657
+ | Mode | Entry point | When to use |
658
+ | -------------------------------- | -------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
659
+ | **Whole Epic** | `/epic-deliver <epicId>` | Drive an Epic end-to-end. Owns the wave loop and the close-tail; ends with a PR open to main. |
660
+ | **Epic-attached Story (worker)** | *helper* `helpers/epic-deliver-story <storyId>` | Per-Story sub-agent called internally by `/epic-deliver`'s wave fan-out; not an operator slash command. |
661
+ | **Standalone Story — plan** | `/story-plan` | Plan a one-off Story that does not belong to an Epic backlog. |
662
+ | **Standalone Story — deliver** | `/story-deliver <storyId> [<storyId>...]` | Deliver one or more standalone Stories authored by `/story-plan`. |
663
+ | **Standalone Story (worker)** | *helper* `helpers/single-story-deliver <storyId>` | Per-Story sub-agent called internally by `/story-deliver`; not an operator slash command. |
664
+
665
+ The operator-facing entry points are `/epic-deliver` (for Epics) and
666
+ `/story-deliver` (for standalone Stories). The `helpers/` layer sits below
667
+ both and is never invoked directly by the operator.
668
+
669
+ ### Story-centric branching
670
+
671
+ - **Format**: `story-<storyId>` (merges into `epic/<epicId>`).
672
+ - **Goal**: minimize merge conflicts and consolidation waves by grouping
673
+ related work on one context slice.
674
+
675
+ ### Story execution lifecycle
676
+
677
+ Whether the Story is launched directly by the operator or fanned out by
678
+ `/epic-deliver`'s wave loop, the same three phases run:
679
+
680
+ 1. **Initialization** (`story-init.js`):
681
+ - Verifies all upstream dependencies are satisfied.
682
+ - Syncs the Epic base branch with `main`.
683
+ - Creates or seeds the Story branch (in a worktree when
684
+ `delivery.worktreeIsolation.enabled: true`).
685
+ - Transitions the Story to `agent::executing`. `story-phase.js`
686
+ upserts the initial `story-run-progress` snapshot at the `init`
687
+ phase.
688
+ 2. **Story implementation.** The agent executes the Story's inline
689
+ `acceptance[]` / `verify[]` contract on the shared Story branch,
690
+ authoring one or more commits referencing the parent Story via
691
+ `(refs #<storyId>)`. Each phase transition (`implementing`,
692
+ `closing`, `done`, `blocked`) is recorded via `story-phase.js`.
693
+
694
+ After the implementation commits land and **before** the phase flips
695
+ to `closing`, a **bounded acceptance self-eval loop** runs (Story
696
+ #3819). An independent, fresh-context critic pass scores the working
697
+ diff against **each** `acceptance[]` item — `met | partial | unmet`
698
+ plus a short evidence string, consuming the Story's `verify[]`
699
+ commands as **required evidence** (the `verify[]` commands are no
700
+ longer optional advisory pre-flight). The critic writes its verdict to
701
+ a verdict file
702
+ (`.agents/schemas/acceptance-eval-verdict.schema.json`); the
703
+ `acceptance-eval.js` gate validates it, enforces the bounded round
704
+ cap, and decides the next action:
705
+ - **all `met`** → the phase flips to `closing`.
706
+ - **any `partial`/`unmet`, rounds remaining** → the agent redrafts
707
+ the flagged criteria and re-runs the critic pass for the next round.
708
+ - **round cap reached, criteria still unmet** → the Story transitions
709
+ to `agent::blocked` (not `closing`), posts a `friction` comment
710
+ naming the unmet criteria and their evidence, and exits non-zero. It
711
+ never silently proceeds to close.
712
+
713
+ The loop is **always on** (a hard cutover — there is no flag toggling
714
+ it off) and **bounded**: the redraft ceiling is
715
+ `delivery.acceptanceEval.maxRounds` (default 2), clamped by the
716
+ resolver into `[1, hard ceiling]` so no configuration can disable the
717
+ cap or let the loop spin unbounded. Each terminus emits a
718
+ per-criterion `acceptance-eval` signal into the retro / feedback
719
+ substrate so the retro and `/epic-plan` Phase 0 feedback fetch see
720
+ which acceptance items needed rework and the round count. The loop is
721
+ **additive** and sits below the Epic-level acceptance-spec
722
+ reconciliation (`/epic-deliver` Phase 7.1) — it evaluates the actual
723
+ work product per Story mid-delivery, not test-tag presence at
724
+ finalize.
725
+ 3. **Closure** (`story-close.js`):
726
+ - Runs shift-left validation (lint, format, test).
727
+ - Merges the Story branch into `epic/<epicId>`.
728
+ - Transitions the Story → `agent::done`; cascades up Story → Feature
729
+ (Epics and context tickets are excluded from auto-cascade).
730
+ - Reaps the Story worktree and cleans up the merged Story branch.
731
+
732
+ ### Context hydration
733
+
734
+ When a sub-agent runs `helpers/epic-deliver-story <storyId>` (for
735
+ Epic-attached Stories) or `helpers/single-story-deliver <storyId>` (for
736
+ standalone Stories), the Context Hydrator assembles a self-contained prompt:
737
+
738
+ 1. `agent-protocol.md` (universal rules).
739
+ 2. Persona and skill directives (from Task labels).
740
+ 3. Hierarchy context (Story → Feature → Epic → PRD → Tech Spec).
741
+ 4. **Story branch context.** Automatic checkouts to the Story branch. Under
742
+ worktree isolation, each Story runs in its own `.worktrees/story-<id>/` so
743
+ branch swaps, staging, and reflog activity are isolated per-story. See
744
+ [`workflows/helpers/worktree-lifecycle.md`](../workflows/helpers/worktree-lifecycle.md).
745
+ 5. Task-specific instructions and subtask checklist.
746
+
747
+ ### State sync
748
+
749
+ Agents update their state in real-time on GitHub:
750
+
751
+ - **Labels**: `agent::ready` → `agent::executing` → `agent::done`. The
752
+ intermediate review label is not part of the label taxonomy; the
753
+ PR opened by `/epic-deliver`'s `delivery.finalize` state is the equivalent "ready to merge"
754
+ signal at the Epic level. The `WaveObserver` submodule additionally
755
+ syncs a GitHub Projects v2 Status column on each transition when a
756
+ `projectNumber` is configured.
757
+ - **Tasklists**: subtasks are checked off in the ticket body (`- [ ]` →
758
+ `- [x]`).
759
+ - **Friction**: friction logs are posted as structured comments on the Task.
760
+ - **Wave transitions**: the Epic Deliver Runner emits `wave-N-start` and
761
+ `wave-N-end` structured comments on the Epic, each carrying the wave
762
+ manifest, story outcomes, and timing.
763
+
764
+ ### Dependency unblocking
765
+
766
+ When a Task reaches `agent::done`, the runner re-evaluates the DAG and
767
+ dispatches any newly-unblocked Tasks. This continues until all waves complete.
768
+
769
+ ### Story assignment (deterministic)
770
+
771
+ `helpers/epic-deliver-story` requires an explicit Story id. The parent
772
+ `/epic-deliver` wave loop picks Story ids off the frozen dispatch manifest
773
+ deterministically and launches one Agent-tool sub-agent (calling
774
+ `helpers/epic-deliver-story`) per id per wave; sibling sub-agents never
775
+ race on the same Story.
776
+
777
+ `runtime.sessionId` survives as a stable per-process identity surfaced in
778
+ the startup `[ENV]` log line for operator correlation. It is a 12-char
779
+ short-id derived from hostname+pid+random.
780
+
781
+ ### Launch-time dependency guard
782
+
783
+ Before any branch operation, `story-init.js` reads the Epic's
784
+ dispatch manifest and verifies the target story's blockers are all merged.
785
+ Unmerged blockers print each blocker's id, state, and URL; the session exits
786
+ 0 (operator-error, not a system error) without touching any branches. A
787
+ missing or stale-format manifest emits a warning and proceeds — the guard is
788
+ a footgun-prevention layer, not a strict gate.
789
+
790
+ The guard runs identically on web and local.
791
+
792
+ ### Concurrent close — push retry
793
+
794
+ `story-close.js` merges the Story branch into `epic/<epicId>` locally
795
+ and pushes. With multiple sessions closing into the same Epic branch from
796
+ separate clones, a non-fast-forward rejection is expected. The push step is
797
+ wrapped in a bounded retry: on rejection the script fetches
798
+ `origin/epic/<id>`, replays the Story merge on top of the new remote tip,
799
+ and pushes again. Bounds:
800
+
801
+ - `DEFAULT_STORY_MERGE_RETRY.maxAttempts` (framework-internal constant in
802
+ `.agents/scripts/lib/config/runners.js`) — 3.
803
+ - `DEFAULT_STORY_MERGE_RETRY.backoffMs` (same module) — `[250, 500, 1000]`.
804
+
805
+ A real content conflict (both stories touched the same lines) aborts the
806
+ loop with a clear error, leaves the local tree clean, and exits non-zero for
807
+ manual resolution. The retry path is a wrapper around the existing happy path.
808
+
809
+ ### Cross-clone coordination
810
+
811
+ Concurrent runs are serialised by **two distinct layers**, and the
812
+ distinction matters: getting it wrong leaves two clones racing on the same
813
+ Epic with no guard between them.
814
+
815
+ **Filesystem locks are same-machine-only.** The Epic merge lock
816
+ (`.agents/scripts/lib/epic-merge-lock.js`) lives at
817
+ `<gitCommonDir>/epic-<epicId>.merge.lock` inside `.git/`, and the
818
+ single-story sweep lock (`.agents/scripts/lib/single-story-sweep/sweep-lock.js`)
819
+ is a single-file rendezvous on the local filesystem. Both decide staleness
820
+ by probing a recorded **process PID** with `process.kill(pid, 0)` and by
821
+ comparing a local-filesystem mtime against a TTL. Because a PID is only
822
+ meaningful on the machine that owns it and `.git/` is never committed,
823
+ **these locks coordinate only the worktrees and sessions on a single
824
+ machine/clone. They do NOT coordinate across clones.** Two operators on
825
+ two separate clones (or two CI runners) will each acquire their *own*
826
+ merge lock and never see the other's — the locks are invisible to each
827
+ other. The only cross-clone safety the merge step itself has is the
828
+ bounded push-retry described above, which recovers from the
829
+ non-fast-forward rejection *after* the race has already happened.
830
+
831
+ **The assignee-as-lease is the cross-clone layer.** To stop two clones
832
+ from both *starting* to drive the same Epic or Story, the framework takes
833
+ an exclusive, time-bounded claim on the ticket via
834
+ [`ticket-lease.js`](../scripts/lib/orchestration/ticket-lease.js). The lease
835
+ rides the ticket's GitHub `assignees` field — a substrate every clone can
836
+ read — so a live foreign claim is visible to, and refuses, a second
837
+ operator regardless of which machine they are on. All three delivery and
838
+ planning entry points take the claim: `/epic-plan` acquires the Epic lease
839
+ before Phase 7 (spec) and releases it after Phase 8 (decompose),
840
+ `/epic-deliver` acquires the Epic lease in its prepare guard, and
841
+ `/single-story-deliver` acquires the Story lease at init. For
842
+ `/epic-deliver` and `/single-story-deliver`, liveness is decided by the
843
+ owner's most-recent `story.heartbeat` against `delivery.lease.ttlMs`;
844
+ because planning emits no `story.heartbeat`, `/epic-plan` has no
845
+ live-heartbeat source and treats **any** foreign assignee as a live claim.
846
+ A live foreign claim fails the preflight closed (refuse-and-exit, naming
847
+ the owner); `--steal` is the only override. See
848
+ [`README.md` § Multi-developer coordination](../README.md#multi-developer-coordination)
849
+ for the full lease behaviour table.
850
+
851
+ The two layers are complementary, not redundant: the lease prevents two
852
+ clones from racing in the first place, while the same-machine merge lock
853
+ serialises the parallel-wave story closures *within* the one clone that
854
+ holds the lease.
855
+
856
+ ### Close-tail (`delivery.close-validation` through `delivery.complete` of `/epic-deliver`)
857
+
858
+ After the wave loop returns `complete`, `/epic-deliver` runs the
859
+ remaining phases against the Epic branch — close-validation, audit,
860
+ code-review, retro, and finalize — before handing off to the
861
+ watch / auto-merge / cleanup tail that drives the PR to merge:
862
+
863
+ 1. **Close-validation (Phase 3).** Lint + test + project-extended ratchets
864
+ (maintainability, CRAP, lint baseline) run via `evidence-gate.js` keyed
865
+ on `git rev-parse HEAD`. A clean tree on a re-run short-circuits in
866
+ milliseconds. A failing gate halts the workflow until the regression is
867
+ fixed on a hotfix branch and re-merged into the Epic.
868
+ 2. **Audit (Phase 4).** The change-set audit lenses run against the Epic
869
+ diff; findings flow through as advisory signal to inform the code
870
+ review that follows.
871
+ 3. **Code-review (Phase 5).** `lib/orchestration/code-review.js` (extracted
872
+ from the `code-review.md` helper) audits the diff and posts the
873
+ findings as a `code-review` structured comment on the Epic. 🔴 Critical
874
+ findings halt the run; 🟠/🟡/🟢 findings flow through as non-blocking.
875
+ 4. **Retro (Phase 6).** `lib/orchestration/retro-runner.js` (extracted from the old
876
+ retro helper) aggregates perf signals, friction counts, hotfix counts,
877
+ recut counts, parked counts, and HITL count using
878
+ `retro-heuristics.js`. The structured retro comment is posted on the
879
+ Epic. The retro fires **before** the PR opens — this keeps it inside
880
+ the operator's local session with full env access (env vars,
881
+ credentials, MCP servers); pushing it after PR-open would deny it
882
+ that access. After the GitHub upsert succeeds, the retro body is
883
+ also **mirrored locally** to the per-Epic temp tree at
884
+ `temp/epic-<id>/retro.md` (path resolved via
885
+ [`lib/config/temp-paths.js`](../scripts/lib/config/temp-paths.js)'s
886
+ `epicRetroMirrorPath`) so operators can read the retro without
887
+ re-fetching from GitHub. GitHub remains the source of truth; the
888
+ mirror write is best-effort and a failure only logs a warn.
889
+ 5. **Finalize (Phase 7).** `/epic-deliver` fires `epic.close.end` via
890
+ `lifecycle-emit.js`; the `AcceptanceReconciler` → `Finalizer`
891
+ listener chain owns every close-time side effect end to end
892
+ (Story #2894 — bus-owned finalize). The chain runs three
893
+ responsibilities in order:
894
+ 1. **Acceptance-spec reconciliation.** Invokes
895
+ `acceptance-spec-reconciler.js` to diff the AC IDs declared in
896
+ the linked `context::acceptance-spec` body against `@ac-*` /
897
+ `@pending` tags in `tests/features/**`. A non-OK reconciliation
898
+ throws (per `.agents/rules/orchestration-error-handling.md`),
899
+ aborting finalize **before** the planning artifacts are closed —
900
+ so the PRD / Tech Spec / Acceptance Spec stay open until the AC
901
+ coverage gap is fixed. Skipped (`status: 'waived'`) when the Epic
902
+ carries `acceptance::n-a`.
903
+ 2. **PR open (bus-owned, Story #2894).** On
904
+ `acceptance.reconcile.ok`, the `Finalizer` listener invokes
905
+ `openOrLocatePr({ epicId, headBranch: 'epic/<id>', baseBranch:
906
+ 'main' })`. The helper probes for an existing open PR on the
907
+ head branch first (idempotent locate path) and only runs
908
+ `gh pr create` when the head branch has no open PR. The
909
+ Finalizer does **not** arm auto-merge — it emits
910
+ `epic.merge.ready` carrying `{ prNumber, epicId, prUrl }` and
911
+ hands off to the auto-merge gate. The sole production caller
912
+ authorised to shell `gh pr merge` in the entire codebase is
913
+ the `AutomergeArmer` listener at the `delivery.automerge` state
914
+ (enforced by the merge-lockout rule in
915
+ `.agents/scripts/check-lifecycle-lint.js`); the
916
+ `delivery.finalize` state never shells the merge command.
917
+ 3. **Planning-artifact close + hand-off (bus-owned, Story #2894).**
918
+ The `Finalizer` chains `closePlanningTickets({ epicId,
919
+ provider })` to close the three planning context tickets
920
+ (`context::prd`, `context::tech-spec`,
921
+ `context::acceptance-spec`) so the Epic's `Closes #<id>`
922
+ auto-close path is not blocked by open sub-issues, then
923
+ `postHandoffComment({ epicId, prNumber, prUrl, provider })` to
924
+ upsert the canonical `epic-handoff` structured comment naming
925
+ the PR. Both helpers are idempotent — re-running finalize
926
+ after a crash counts already-closed tickets under
927
+ `alreadyClosed` and edits the existing handoff comment in
928
+ place rather than appending a duplicate. The Epic stays at
929
+ `agent::executing` until the PR merges.
930
+ 6. **Watch-and-iterate (Phase 8).** `/epic-deliver` watches the open PR's
931
+ required checks until they turn green. Transient failures trigger an
932
+ automated re-run loop; durable failures surface for human remediation
933
+ on the Epic branch.
934
+ 7. **Auto-merge (Phase 8.5).** Once the watch loop reports all required
935
+ checks passing, the auto-merge gate arms GitHub native auto-merge via
936
+ `gh pr merge --auto --squash --delete-branch` so the PR lands without
937
+ a second operator visit.
938
+ 8. **Cleanup (Phase 9).** After the PR merges, the cleanup phase reaps
939
+ local Story/Epic branch refs and any lingering worktrees so the
940
+ workspace returns to a clean state for the next Epic.
941
+
942
+ `/epic-deliver` exits cleanly once auto-merge is armed (or sooner if the
943
+ operator declines auto-merge). The operator can merge through the GitHub UI
944
+ at any time; the `delivery.complete` state handles the post-merge branch reap.
945
+
946
+ ---
947
+
948
+ ## HITL (Human-in-the-Loop) model
949
+
950
+ On the happy path there is exactly **one** mandatory operator touchpoint
951
+ after `/epic-deliver` fires (blocker resolution). PR merge is autonomous
952
+ via armed auto-merge; the operator can opt in as a second touchpoint by
953
+ disarming auto-merge in the GitHub UI, or is pulled in by exception when
954
+ required checks fail.
955
+
956
+ 1. **Blocker resolution (mandatory when triggered).** If the orchestrator
957
+ hits an unresolvable condition, `BlockerHandler` flips the Epic to
958
+ `agent::blocked`, posts a structured friction comment, fires the
959
+ notification webhook (fire-and-forget), and halts wave N+1 (letting
960
+ wave N's in-flight stories finish naturally). The operator resolves
961
+ the underlying issue (e.g. a hand-fix commit on the Story branch or a
962
+ scope edit on the blocking ticket), then flips the Epic back to
963
+ `agent::executing` to resume.
964
+ 2. **PR merge (autonomous by default; operator-gated by exception).** At
965
+ the end of `/epic-deliver`, the workflow opens a PR to `main` and
966
+ arms GitHub native auto-merge (the `delivery.automerge` state). When required checks pass,
967
+ the PR lands without a second operator visit; the standard
968
+ label-transition pathway flips the Epic to `agent::done` on merge.
969
+ The operator becomes a touchpoint here only when they (a) disarm
970
+ auto-merge in the GitHub UI to inspect required-checks, the
971
+ `code-review` comment, and the retro before merging by hand, or
972
+ (b) checks fail and need remediation on the Epic branch. There is
973
+ no separate close command — the close-out side effects (PR open,
974
+ planning-ticket close, handoff comment) are owned by `/epic-deliver`'s
975
+ `delivery.finalize` state (the lifecycle Finalizer listener), whose
976
+ replay is idempotent.
977
+
978
+ ### What triggers `agent::blocked`
979
+
980
+ - Unresolvable merge conflict that automated strategies cannot reconcile.
981
+ - Test failures that persist after one automated remediation attempt.
982
+ - Ambiguity in a ticket requiring a product/scope decision the orchestrator
983
+ cannot make from ticket context alone.
984
+ - A destructive action not pre-authorized by the ticket body (e.g. dropping a
985
+ table, deleting user data, force-pushing to a protected branch).
986
+ - External service failure preventing progress (GitHub API 5xx loop, npm
987
+ registry down).
988
+ - Wave concurrency exhausted for an unbounded time (possible deadlock).
989
+
990
+ ### What is *not* gated at runtime
991
+
992
+ - `risk::high` tasks **run without pause.** The label remains as planning
993
+ metadata and retro telemetry, but it does **not** halt the dispatcher
994
+ or `/epic-deliver`. Branch protection on `main` and
995
+ `BlockerHandler`-driven escalation are the runtime defenses for
996
+ destructive actions.
997
+ - Wave boundaries — the runner advances as soon as wave N completes.
998
+ - Individual story completion — no per-story approval prompt.
999
+
1000
+ > [!NOTE] Legacy `risk::high` runtime gating has been retired. `risk::high`
1001
+ > remains planning/audit metadata only; the sole runtime pause point is
1002
+ > `agent::blocked`.
1003
+
1004
+ ---
1005
+
1006
+ ## Epic Deliver Runner internals
1007
+
1008
+ `/epic-deliver` drives the long-running coordinator inside the operator's
1009
+ Claude session. The slash command composes the submodules listed below;
1010
+ `helpers/epic-deliver-story` is launched as an Agent-tool sub-agent of
1011
+ `/epic-deliver`'s wave loop — no subprocess worker sessions for Story
1012
+ execution, no GitHub Actions runner. Deterministic Node CLIs remain the
1013
+ state-mutation contract.
1014
+
1015
+ | Submodule | Role |
1016
+ | ------------------- | ----------------------------------------------------------------------------------------------------------------------- |
1017
+ | `wave-scheduler` | Iterates waves from `Graph.computeWaves()`. |
1018
+ | `story-launcher` | Fans out up to `concurrencyCap` Agent-tool Story sub-agents per wave. |
1019
+ | `checkpointer` | Upserts the `epic-run-state` structured comment; handles phase-granular resume across all six phases. |
1020
+ | `blocker-handler` | The sole runtime pause point — halts on `agent::blocked`. |
1021
+ | `notification-hook` | Fire-and-forget webhook for blocker / wave-transition events. |
1022
+ | `wave-observer` | Emits `wave-N-start` / `wave-N-end` comments and reads each Story's `story-run-progress` snapshot. |
1023
+ | `column-sync` | Syncs the Projects v2 Status column from `agent::` labels. |
1024
+ | `code-review` | `lib/orchestration/code-review.js` — `delivery.code-review` inline audit; halts on critical findings. |
1025
+ | `retro-runner` | `lib/orchestration/retro-runner.js` — `delivery.retro` authoring; posts structured retro comment. |
1026
+
1027
+ ### Claude Max quota
1028
+
1029
+ `/epic-deliver` consumes Max subscription quota (5-hour rolling window with
1030
+ overage disabled at the org level by default). If a long Epic exceeds the
1031
+ 5-hour window, `BlockerHandler` surfaces the rate-limit error as
1032
+ `agent::blocked` so you can resume after the quota rolls.
1033
+
1034
+ ### Skipping CI/CD on orchestrator commits
1035
+
1036
+ The orchestrator pushes many commits during a run, each potentially triggering
1037
+ the project's `CI / CD` workflow. Two mitigations:
1038
+
1039
+ - Add `[skip ci]` to orchestrator commit messages (requires a small tweak in
1040
+ `story-close.js`), OR
1041
+ - Add a `paths-ignore` or branch filter to `ci.yml` that excludes `epic/*` and
1042
+ `story-*` branches. Only `main` pushes trigger CI.
1043
+
1044
+ ---
1045
+
1046
+ ## Phase 4: PR merge (auto by default)
1047
+
1048
+ Once the wave loop, close-validation, code-review, and retro have all
1049
+ completed, `/epic-deliver` opens a pull request from `epic/<epicId>` to
1050
+ `main` and arms GitHub native auto-merge. When the required checks pass
1051
+ the PR lands without further intervention; the operator can disarm
1052
+ auto-merge in the GitHub UI to make the final merge an explicit human
1053
+ action.
1054
+
1055
+ 1. **Story merging.** Stories merge into `epic/<epicId>` automatically
1056
+ during Story closure (`story-close.js`). The Epic branch is the rolling
1057
+ integration target.
1058
+ 2. **Completion cascade.** When the last Task in a Story reaches
1059
+ `agent::done`, status cascades upward:
1060
+
1061
+ ```text
1062
+ Task Done → Story Done → Feature Done
1063
+ ```
1064
+
1065
+ Epics, PRDs, and Tech Specs are explicitly excluded from auto-cascade —
1066
+ the Epic only flips to `agent::done` when the operator merges the PR
1067
+ to `main`.
1068
+
1069
+ 3. **PR merge — the sole promotion gate.** When the PR merges (auto or
1070
+ manual):
1071
+ - the Epic-to-`main` merge lands as a real PR merge with a real
1072
+ reviewer-trail and required-checks history;
1073
+ - the standard label-transition pathway flips the Epic to
1074
+ `agent::done`;
1075
+ - branch cleanup runs out-of-band: the `delivery.complete` state of
1076
+ `/epic-deliver` reaps local refs after the merge; the rare "scrap
1077
+ and reset" case for an unmerged Epic is handled manually.
1078
+
1079
+ If the operator chooses not to merge (rolling back, deferring, re-scoping),
1080
+ `/epic-deliver` has not poisoned `main`. The Epic branch can be amended
1081
+ in place; re-running `/epic-deliver <epicId>` re-runs the
1082
+ `delivery.close-validation` / `delivery.audit` / `delivery.code-review`
1083
+ states against the new HEAD (the evidence wrapper picks up the new SHA) and
1084
+ updates the same PR — no duplicate PRs are opened against the same Epic
1085
+ branch.
1086
+
1087
+ ---
1088
+
1089
+ ## Testing strategy
1090
+
1091
+ Tests are **pyramid-aware**. Every test written during Story delivery
1092
+ belongs to exactly one tier — **unit**, **contract**, or **e2e / acceptance** —
1093
+ and each tier has distinct scope, dependency, and assertion rules. The canonical
1094
+ tier definitions, assertion-placement rules, and coverage thresholds live in
1095
+ [`rules/testing-standards.md`](../rules/testing-standards.md); Gherkin authoring
1096
+ for the acceptance tier is governed by
1097
+ [`rules/gherkin-standards.md`](../rules/gherkin-standards.md).
1098
+
1099
+ The acceptance tier is executed and reported via
1100
+ [`workflows/qa-run-harness.md`](../workflows/qa-run-harness.md) and consumed as
1101
+ epic evidence by
1102
+ [`workflows/helpers/epic-testing.md`](../workflows/helpers/epic-testing.md).
1103
+
1104
+ ### QA workflows: explore, assist, and run-harness
1105
+
1106
+ Three complementary QA workflows sit alongside the automated test pyramid, all
1107
+ adopting the `qa-engineer` persona and all reading the consumer's `qa.*`
1108
+ project contract from `.agentrc.json`. The first two are exploratory siblings
1109
+ that differ on **who drives** the session; the third steps a known scenario
1110
+ set:
1111
+
1112
+ - **[`workflows/qa-explore.md`](../workflows/qa-explore.md)** (`/qa-explore`) — an
1113
+ **agent-led**, open-ended **Plan → Capture → Triage** exploratory sweep.
1114
+ The operator names a surface; the **agent drives** it (through the browser
1115
+ MCP by default, or statically as a documented interim), probing for product
1116
+ bugs, environment-setup friction, tooling/DX gaps, missing tests, and
1117
+ enhancement ideas. Each observation is recorded as a `QaLedgerItem` against
1118
+ [`schemas/qa-ledger.schema.json`](../schemas/qa-ledger.schema.json) and appended
1119
+ to a **session ledger** at `temp/qa/<sessionId>.ndjson` (one item per ndjson
1120
+ line, under `project.paths.tempRoot`, gitignored, never committed). Capture
1121
+ is strictly **read-only** — the ledger append is its only write — so every
1122
+ state-changing action (filing a follow-up ticket, mutating a label) lands in
1123
+ Triage, and only after explicit operator confirmation. The session is
1124
+ HITL-gated: every phase transition is operator-gated. Deterministic Node
1125
+ helpers under `scripts/lib/qa/` (session resolution, evidence redaction,
1126
+ coverage verdict, missing-test proposal) and `scripts/lib/findings/`
1127
+ (classification, dedup/route — the same dedup implementation shared with
1128
+ `audit-to-stories`) make the decisions; the agent never re-derives them in
1129
+ prose. A resumed session appends and carries its un-triaged backlog forward
1130
+ as a rolling backlog.
1131
+ - **[`workflows/qa-assist.md`](../workflows/qa-assist.md)** (`/qa-assist`) — the
1132
+ **human-led** sibling of `/qa-explore`: a single-observation
1133
+ **Intake → Enrich → Record** loop. Here the **human drives** — the operator
1134
+ reports one observation they hit (a bug, a flaky behavior, a "this feels
1135
+ off") and the agent enriches it into a triage-ready `QaLedgerItem` (a clean
1136
+ repro, a `file:line` root-cause locus, a coverage verdict), asking clarifying
1137
+ questions when the observation is ambiguous, then appends it — after explicit
1138
+ operator confirmation — to a persistent, resumable rolling session under
1139
+ `temp/qa/`. It produces the **same** ledger contract `/qa-explore` writes
1140
+ (`qa-ledger.schema.json`) and reuses the same `scripts/lib/qa/` and
1141
+ `scripts/lib/findings/` decision seams, so a `/qa-assist` item flows through
1142
+ the identical dedup, classification, and promotion machinery later.
1143
+ - **[`workflows/qa-run-harness.md`](../workflows/qa-run-harness.md)**
1144
+ (`/qa-run-harness`) — the **automated complement**: it steps a *known* set of
1145
+ Gherkin `.feature` scenarios through a real browser, asserting `Then`
1146
+ outcomes semantically against the accessibility snapshot and bundling
1147
+ console/network problems into structured `F#` findings for operator sign-off.
1148
+
1149
+ All three workflows resolve the `qa.*` contract through the single seam
1150
+ [`scripts/lib/qa/resolve-qa-contract.js`](../scripts/lib/qa/resolve-qa-contract.js).
1151
+ The block is **optional in the schema** (so config validation never breaks a
1152
+ non-QA consumer) but enforced at run time: the resolver fails **loudly** with
1153
+ "this project has not bound the QA harness" when no `qa` block is present —
1154
+ there is no silent fallback. The contract's four required keys are
1155
+ `qa.featureRoot` (the `.feature` discovery root), `qa.fixturesManifest`
1156
+ (persona → seed-data binding), `qa.signInSeam` (the dev-only sign-in seam,
1157
+ either `{ urlTemplate }` or `{ skill }`), and `qa.personas` (the persona set,
1158
+ authored as a name-only array under a url-template seam or as a per-persona
1159
+ credential/skill map under a skill seam); the two optional keys
1160
+ `qa.consoleAllowlist` and `qa.designTokens` default to `[]` and `null`.
1161
+ Consumer adoption steps are in
1162
+ [`README.md` § Adopting the QA harness](../README.md#adopting-the-qa-harness).
1163
+
1164
+ ---
1165
+
1166
+ ## Static analysis & audit orchestration
1167
+
1168
+ An automated, gate-based static-analysis and audit orchestration pipeline
1169
+ replaces manual auditing with a CLI-driven system.
1170
+
1171
+ ### Audit triggering
1172
+
1173
+ Audits are selectively invoked by the orchestrator at four Epic lifecycle
1174
+ gates (`gate1` through `gate4`). The audit orchestrator
1175
+ (`lib/dynamic-workflow/audit-orchestrator.js`) evaluates rules
1176
+ defined in `.agents/schemas/audit-rules.json` (schema:
1177
+ `.agents/schemas/audit-rules.schema.json`) based on:
1178
+
1179
+ 1. **Gate configuration** — which gate is currently firing.
1180
+ 2. **Contextual keywords** — the Epic or Task body contents (e.g., `auth` or
1181
+ `encrypt` triggers security audits).
1182
+ 3. **File patterns** — which files changed compared to the base branch (e.g.,
1183
+ `user-profile` files trigger privacy audits).
1184
+
1185
+ ### Epic lifecycle gates
1186
+
1187
+ The matrix lists every quality gate the framework fires during an Epic
1188
+ run. **Blocking?** is `blocking` when a non-OK result aborts the
1189
+ workflow, `advisory` when findings are surfaced but execution proceeds.
1190
+ **Idempotency key** names the on-disk or in-ticket marker the gate keys
1191
+ on so re-runs short-circuit when state has not changed.
1192
+
1193
+ | Gate | When | What Runs | Blocking? | Idempotency key |
1194
+ | ------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------ |
1195
+ | Gate 1 | After Story completion | Content-triggered audits (clean-code, etc.) | advisory | Audit-report comment per Story (`audit-<lens>` structured comment) |
1196
+ | Gate 2 | Pre-integration | Dependency + DevOps audits | advisory | Audit-report comment per Epic (`audit-<lens>` structured comment) |
1197
+ | Gate 3 | `/epic-deliver` `delivery.code-review` state | Full automated audit pass | blocking | `code-review` structured comment on Epic, keyed by Epic HEAD SHA |
1198
+ | Gate 4 | `/epic-deliver` `delivery.finalize` state (pre-PR) | `audit-sre` production readiness gate | blocking | `audit-sre` structured comment on Epic, keyed by Epic HEAD SHA |
1199
+ | Close-validation | `/epic-deliver` `delivery.close-validation` state | lint + test + maintainability + CRAP + coverage ratchets via `evidence-gate.js` | blocking | `evidence-gate` cache entry keyed by `git rev-parse HEAD` |
1200
+ | Pre-push | Local `.husky/pre-push` hook on every push | Diff-scoped quality preview + coverage/CRAP ratchet | blocking | Working-tree SHA + staged-diff hash (per push) |
1201
+ | Acceptance reconciliation | `/epic-deliver` `delivery.finalize` state | `acceptance-spec-reconciler.js` diffs AC IDs against `@ac-*` / `@pending` feature tags | blocking | `acceptance-reconcile` structured comment on Epic, keyed by spec-body SHA |
1202
+ | Spec freshness | `/epic-plan` `planning.spec-authoring` state | Re-derives PRD / Tech Spec / Acceptance Spec staleness against Epic body checksum | advisory | `epic-plan-state` checkpoint entry per spec artifact body SHA |
1203
+
1204
+ ### Review & feedback loop
1205
+
1206
+ When audits produce findings, the orchestrator compiles a structured Markdown
1207
+ report and posts it as a ticket comment via the `ITicketingProvider`.
1208
+
1209
+ - **Maintainability ratchet.** The orchestrator enforces code quality by relying
1210
+ on maintainability checks (`check-maintainability.js`), which fail if the
1211
+ composite score drops below the established baseline.
1212
+ - **CRAP gate.** Sibling per-method gate (`check-crap.js`) wired
1213
+ into `close-validation` after `check-maintainability`, the `ci.yml` step
1214
+ after `test:coverage`, and `.husky/pre-push`. Tracks complexity × coverage
1215
+ risk per method against `baselines/crap.json`. Self-skips when
1216
+ `delivery.quality.gates.crap.enabled` is `false`. The
1217
+ `baseline-refresh:`-tagged commit convention for baseline edits is the
1218
+ project standard; the operator is the gate during `/epic-deliver`
1219
+ `delivery.finalize` state (the prior CI guardrail that enforced the tag was removed).
1220
+ - **Human review on High/Critical.** If High or Critical findings are detected,
1221
+ the workflow halts for human review at the corresponding `/epic-deliver`
1222
+ phase. Approval is given by the operator advancing the phase (the
1223
+ auto-approve webhook listener was never wired into CI and was removed during the rebrand).
1224
+ - **Implementation.** Once the operator approves the fixes, the ticket
1225
+ transitions to `agent::executing` and `/epic-deliver` dispatches an agent to
1226
+ implement and verify them.
1227
+
1228
+ ---
1229
+
1230
+ ## Notification system
1231
+
1232
+ Two independent notification surfaces, both living in `.agents/` so they ship to
1233
+ consuming projects:
1234
+
1235
+ ### 1. Unified `notify()` dispatcher
1236
+
1237
+ Every notification — whether a manual orchestration milestone (story merged,
1238
+ HITL gate triggered) or an auto-fired ticket-state transition — routes through
1239
+ [`notify.js`](../scripts/notify.js). Two delivery channels:
1240
+
1241
+ | Channel | What it does |
1242
+ | ----------------- | ------------------------------------------------------------------------- |
1243
+ | GitHub comment | Posts to the targeted ticket; @mentions operator for `medium`/`high`. |
1244
+ | Webhook | Fire-and-forget POST to the configured URL (Make.com / Slack / Discord). |
1245
+
1246
+ Severity vocabulary (assigned by callers; `eventSeverity()` in
1247
+ `lib/notifications/notifier.js` derives it for state transitions):
1248
+
1249
+ | Severity | Used for | Webhook prefix |
1250
+ | -------- | --------------------------------------------------------------------------------------------------------------------- | -------------------- |
1251
+ | `low` | Task transitions, `story-run-progress` upserts, intermediate state transitions, audit reports. | `[low]` |
1252
+ | `medium` | Operator-visible milestones: Story state transitions, `wave-run-progress`, `epic-run-progress`, story merged, epic complete. | `[medium]` |
1253
+ | `high` | Operator must act (HITL gates, epic blockers, autonomous-chain failures). Message body should also lead with `🚨 Action Required:`. | `[Action Required]` |
1254
+
1255
+ Two independent event-allowlist knobs in `github.notifications`
1256
+ (both mandatory):
1257
+
1258
+ - `commentEvents` — event-name allowlist for GitHub-ticket comment
1259
+ posting. Default:
1260
+ `["state-transition", "story-merged", "operator-message"]`.
1261
+ - `webhookEvents` — event-name allowlist for `NOTIFICATION_WEBHOOK_URL`
1262
+ deliveries. Default:
1263
+ `["epic-started", "epic-progress", "epic-blocked", "epic-unblocked", "epic-complete"]`.
1264
+
1265
+ Each channel filters independently; there is no fallback chain.
1266
+ Severity is carried as envelope metadata (and still drives `@mention`
1267
+ behavior on the comment channel — high always @mentions, medium
1268
+ @mentions when `mentionOperator: true`) but is no longer a routing
1269
+ factor for either channel. `transitionTicketState` suppresses the
1270
+ `notify()` dispatch entirely for low-severity transitions (task-level,
1271
+ non-terminal story / epic flips) so the comment channel sees only the
1272
+ medium-severity story-level events operators expect on the ticket
1273
+ timeline. To suppress either channel entirely, set its array to `[]`.
1274
+ The schema enums pin closed vocabularies — adding custom event names
1275
+ requires loosening the enum in `.agents/scripts/lib/config-schema.js`.
1276
+
1277
+ Webhook URL resolution:
1278
+
1279
+ - `NOTIFICATION_WEBHOOK_URL` process env var only — loaded from `.env` at the
1280
+ project root. The webhook URL is **not** sourced from `.agentrc.json`, and
1281
+ (as of Epic #702) is no longer sourced from `.mcp.json`.
1282
+
1283
+ Because `notify()` is called in-band from the orchestration SDK, it captures
1284
+ changes from:
1285
+
1286
+ - The Epic Deliver Runner (coordinator-driven state flips).
1287
+ - Per-story scripts (`story-init.js`, `story-close.js`).
1288
+ - Any script that routes state changes through `transitionTicketState`.
1289
+
1290
+ It does **not** capture manual label clicks in the GitHub UI (no webhook
1291
+ receiver). For programmatic orchestration workflows this covers >95% of
1292
+ lifecycle transitions.
1293
+
1294
+ ### 2. Deliver-runner blocker / HITL notifications
1295
+
1296
+ The `NotificationHook` inside the Epic Deliver Runner fires on
1297
+ blocker-escalation events (`agent::blocked`) and operator-attention events
1298
+ (PR-open hand-off, run cancellation). Fire-and-forget by design; webhook
1299
+ failures never block execution.
1300
+
1301
+ | Event | Type | Channel | Operator Action |
1302
+ | ------------------ | ---------- | ------------------ | ---------------------- |
1303
+ | `task-complete` | **INFO** | @mention | Review when convenient |
1304
+ | `feature-complete` | **INFO** | @mention | Informational only |
1305
+ | `epic-complete` | **INFO** | @mention + webhook | Final review |
1306
+ | `pr-opened` | **ACTION** | @mention + webhook | Inspect checks + merge |
1307
+ | `epic-blocked` | **ACTION** | webhook | Resolve and re-flip |
1308
+ | `wave-transition` | **INFO** | webhook | Informational only |
1309
+
1310
+ ---
1311
+
1312
+ ## Troubleshooting
1313
+
1314
+ ### Sub-agent CI workflow editing
1315
+
1316
+ Sub-agents (any agent operating under the framework's default
1317
+ `GITHUB_TOKEN`) **cannot edit files under `.github/workflows/**`**. The
1318
+ framework's token does not carry the `workflows` permission scope by
1319
+ default, so a push that touches a workflow file is rejected by GitHub
1320
+ with an error of the shape:
1321
+
1322
+ > refusing to allow a GitHub App to create or update workflow
1323
+ > `.github/workflows/<file>.yml` without `workflows` permission
1324
+
1325
+ This is a hard constraint, not a transient failure. Re-running the same
1326
+ push will not succeed.
1327
+
1328
+ **When a Story plans a new CI gate**, route the check through a
1329
+ `package.json` script rather than adding it directly to the workflow
1330
+ YAML. Examples:
1331
+
1332
+ - Add the new check to `npm run lint`, `npm run docs:check`, or
1333
+ `npm test` so an existing CI job picks it up by transitivity.
1334
+ - Wire a new `package.json` script and chain it from one of the
1335
+ existing scripts the workflow already invokes.
1336
+ - For a check that genuinely cannot be expressed as an npm script,
1337
+ surface it as a script anyway (e.g. `npm run check:<name>` →
1338
+ `node .agents/scripts/<name>.js`) and call the script from the
1339
+ existing `Validate and Test` job's `run:` block — but the YAML edit
1340
+ itself must be made by an operator.
1341
+
1342
+ Precedent: Epic #2880 Story #2895 Task #2916 intended to add
1343
+ `check-lifecycle-doc-drift.js` directly to `.github/workflows/ci.yml`,
1344
+ hit this constraint, and worked around it by chaining the check into
1345
+ `npm run docs:check`. The functional outcome is identical; the
1346
+ workaround is the canonical pattern.
1347
+
1348
+ **When a workflow file genuinely must change** (a new top-level job, a
1349
+ trigger change, a runner-image bump, etc.), the edit must be made by an
1350
+ operator with `Workflows: Read and write` PAT permissions. See
1351
+ [§ One-time PAT setup](../../AGENTS.md#one-time-pat-setup) in the root
1352
+ `AGENTS.md` for how to provision a PAT with the required scope. The same
1353
+ operator surface that release-please relies on is the one that authorizes
1354
+ workflow edits.
1355
+
1356
+ ### Worktree config shadow
1357
+
1358
+ `helpers/epic-deliver-story` and `helpers/single-story-deliver` run inside
1359
+ per-Story worktrees under `.worktrees/story-<id>/`. A git worktree checks out the
1360
+ **Story branch's own copy** of every repo-tracked file — including
1361
+ `.agentrc.json`, `package.json`, `release-please-config.json`, and any
1362
+ other config under version control. **Operator edits made in the main
1363
+ checkout do NOT propagate to an already-active worktree.** The worktree
1364
+ sees the branch's committed contents until the operator either re-edits
1365
+ inside the worktree or merges the change into the Story branch.
1366
+
1367
+ Symptom: you bump a runtime knob in `<main-repo>/.agentrc.json` (e.g.
1368
+ raise `delivery.quality.gates.coverage.timeoutMs`), re-run
1369
+ `story-close.js --cwd <worktree>`, and the script still uses the old
1370
+ value. The script resolved config from the worktree's stale
1371
+ `.agentrc.json`, not the main checkout's edited one. Precedent: Epic
1372
+ \#2880 friction note F-W0-6 (Story \#2896 recovery debugging time).
1373
+
1374
+ When tuning runtime knobs **mid-Story**:
1375
+
1376
+ 1. **Prefer an env-var override** when the knob exposes one (e.g.
1377
+ timeouts, log level via `AGENT_LOG_LEVEL`, concurrency caps). Env
1378
+ vars are read from the operator's actual shell, not from the
1379
+ checked-out config, so they bypass worktree shadow entirely.
1380
+ 2. **Edit the file inside the worktree** —
1381
+ `.worktrees/<story-id>/.agentrc.json` — so the script sees the bump
1382
+ on its next read. Either commit the change on the Story branch (if
1383
+ the bump is project-wide and should land with the Story) or leave
1384
+ it uncommitted as a scratch tweak that gets discarded when the
1385
+ worktree is reaped.
1386
+ 3. **Use `.agentrc.local.json`** for per-machine tuning you never want
1387
+ to commit. The file is gitignored and layered on top of
1388
+ `.agentrc.json` by the config resolver
1389
+ (see [`.agents/docs/configuration.md`](configuration.md#per-machine-local-overrides)).
1390
+ Note: the local override is still read relative to the script's
1391
+ cwd, so for worktree-bound scripts you must place
1392
+ `.agentrc.local.json` inside the worktree directory — or invoke the
1393
+ script with `--cwd <main-repo>` so the resolver reads from the main
1394
+ checkout's local override.
1395
+
1396
+ Editing the main checkout's `.agentrc.json` only affects **the next**
1397
+ `story-init.js` invocation, because new Story branches fork from
1398
+ `main`'s current tip and therefore see the new config from the start.
1399
+ For Stories already in flight, use one of the three options above.
1400
+
1401
+ ---
1402
+
1403
+ ## Quick reference
1404
+
1405
+ | Command | Purpose |
1406
+ | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1407
+ | `npx create-mandrel` | Cold-start launcher — install `mandrel`, `mandrel sync`, then run `bootstrap.js` (provisions repo + Projects V2 board, labels, branch protection). |
1408
+ | `/onboard` | Guided first run after bootstrap — stack detection, docs scaffolding, `mandrel doctor` readiness gate, started `/epic-plan` handoff. |
1409
+ | `/epic-plan` | Ideation entry — sharpen idea, search duplicates, open Epic, then PRD + Tech Spec + decomposition. |
1410
+ | `/epic-plan --idea "<seed>"` | Same ideation entry with pre-supplied seed. |
1411
+ | `/epic-plan <epicId>` | Existing-Epic mode — PRD + Tech Spec + decomposition for an Epic Issue already opened. |
1412
+ | `/epic-deliver <epicId>` | Drive an Epic end-to-end. Wave loop → close-validation → code-review → retro → opens PR to `main` with auto-merge armed. |
1413
+ | `/story-deliver <storyId> [<storyId>...]` | Deliver one or more standalone Stories (no `Epic: #N` reference). Builds a dependency-aware wave plan and fans out one worker per Story per wave. |
1414
+ | `/story-plan` | Plan a one-off Story outside an Epic backlog. |
1415
+ | *helper* `workflows/helpers/epic-deliver-story` | Per-Story worker called by `/epic-deliver`'s wave loop; not an operator slash command. See [`helpers/epic-deliver-story.md`](../workflows/helpers/epic-deliver-story.md). |
1416
+ | *helper* `workflows/helpers/single-story-deliver` | Per-Story worker called by `/story-deliver`; not an operator slash command. See [`helpers/single-story-deliver.md`](../workflows/helpers/single-story-deliver.md). |
1417
+ | *helper* `workflows/helpers/code-review.md` | Auto-invoked by `/epic-deliver`'s `delivery.code-review` state (scope: epic); not a slash command. |
1418
+ | `/git-commit-all` | Stage and commit all changes |
1419
+ | `/git-push` | Stage, commit, and push to remote |
1420
+ | `epic-reconcile.js --explicit-delete` | Hard reset — close orphaned Epic-scoped issues per `.agents/epics/<id>.yaml` |