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,295 @@
1
+ /**
2
+ * epic-run-state-store — stateless functions for reading and writing the
3
+ * `epic-run-state` structured comment used by `/epic-deliver`.
4
+ *
5
+ * This module is the function-based replacement for the legacy
6
+ * `Checkpointer` class that previously lived at
7
+ * `./epic-runner/checkpointer.js`. Bodies were lifted verbatim from the
8
+ * corresponding `Checkpointer` methods so the structured-comment shape is
9
+ * preserved byte-for-byte. Story #2423 (Epic #2307) deleted the class
10
+ * file; the class API survives as a tests-only fixture at
11
+ * `tests/fixtures/epic-run-state-store.js`.
12
+ *
13
+ * The comment is identified by a stable HTML marker so it can be overwritten
14
+ * idempotently across orchestrator restarts. The body is a fenced JSON block
15
+ * following the schema in tech spec #323.
16
+ */
17
+
18
+ import { assertValidDeliverPhase } from './epic-runner/deliver-phases.js';
19
+ import { parseFencedJsonComment } from './structured-comment-parser.js';
20
+ import { findStructuredComment, upsertStructuredComment } from './ticketing.js';
21
+
22
+ export const EPIC_RUN_STATE_TYPE = 'epic-run-state';
23
+ export const CHECKPOINT_SCHEMA_VERSION = 1;
24
+
25
+ // Re-export the phase enum + index helper so downstream importers continue
26
+ // to use this module as a single import target.
27
+ export {
28
+ DELIVER_PHASES,
29
+ phaseIndex,
30
+ } from './epic-runner/deliver-phases.js';
31
+
32
+ function assertProvider(provider) {
33
+ if (!provider)
34
+ throw new TypeError('epic-run-state-store requires a provider');
35
+ }
36
+
37
+ function assertEpicId(epicId) {
38
+ if (!Number.isInteger(epicId)) {
39
+ throw new TypeError('epic-run-state-store requires a numeric epicId');
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Read and parse the checkpoint. Returns null if the comment is missing or
45
+ * unparseable (callers treat null as "start fresh").
46
+ *
47
+ * @param {{ provider: import('../ITicketingProvider.js').ITicketingProvider, epicId: number }} opts
48
+ * @returns {Promise<object | null>}
49
+ */
50
+ export async function read({ provider, epicId } = {}) {
51
+ assertProvider(provider);
52
+ assertEpicId(epicId);
53
+ const comment = await findStructuredComment(
54
+ provider,
55
+ epicId,
56
+ EPIC_RUN_STATE_TYPE,
57
+ );
58
+ return parseFencedJsonComment(comment);
59
+ }
60
+
61
+ /**
62
+ * Overwrite the checkpoint with `state`. Idempotent — callers may invoke
63
+ * freely per wave; the marker-scoped upsert deletes the prior comment.
64
+ *
65
+ * @param {{ provider: import('../ITicketingProvider.js').ITicketingProvider, epicId: number, state: object }} opts
66
+ */
67
+ export async function write({ provider, epicId, state } = {}) {
68
+ assertProvider(provider);
69
+ assertEpicId(epicId);
70
+ const payload = {
71
+ version: CHECKPOINT_SCHEMA_VERSION,
72
+ ...state,
73
+ lastUpdatedAt: new Date().toISOString(),
74
+ };
75
+ const body = `\`\`\`json\n${JSON.stringify(payload, null, 2)}\n\`\`\``;
76
+ await upsertStructuredComment(provider, epicId, EPIC_RUN_STATE_TYPE, body);
77
+ return payload;
78
+ }
79
+
80
+ /**
81
+ * Initial checkpoint for a brand-new run. Idempotent against re-dispatch
82
+ * when the wave shape is unchanged. When an existing checkpoint is found
83
+ * but the incoming `totalWaves` or `concurrencyCap` differs from the
84
+ * persisted values, refresh those fields in place — preserving
85
+ * `currentWave`, `waves[]`, `blockerHistory`, `manualInterventions`,
86
+ * `startedAt`, and any other already-persisted fields (e.g., `plan`,
87
+ * `phase`). The `plan` field is owned by the prepare caller, which
88
+ * overwrites it on every prepare run, so it does not need a delta check
89
+ * here.
90
+ *
91
+ * @param {{ provider: import('../ITicketingProvider.js').ITicketingProvider, epicId: number, totalWaves: number, concurrencyCap: number }} opts
92
+ */
93
+ export async function initialize({
94
+ provider,
95
+ epicId,
96
+ totalWaves,
97
+ concurrencyCap,
98
+ } = {}) {
99
+ assertProvider(provider);
100
+ assertEpicId(epicId);
101
+ const existing = await read({ provider, epicId });
102
+ if (existing) {
103
+ if (
104
+ existing.totalWaves === totalWaves &&
105
+ existing.concurrencyCap === concurrencyCap
106
+ ) {
107
+ return existing;
108
+ }
109
+ return write({
110
+ provider,
111
+ epicId,
112
+ state: { ...existing, totalWaves, concurrencyCap },
113
+ });
114
+ }
115
+ return write({
116
+ provider,
117
+ epicId,
118
+ state: {
119
+ epicId,
120
+ startedAt: new Date().toISOString(),
121
+ currentWave: 0,
122
+ totalWaves,
123
+ concurrencyCap,
124
+ phase: 'prepare',
125
+ waves: [],
126
+ blockerHistory: [],
127
+ manualInterventions: [],
128
+ },
129
+ });
130
+ }
131
+
132
+ /**
133
+ * Reconcile the resume pointer (`currentWave` + `waves[]` history) against
134
+ * a freshly-recomputed wave plan.
135
+ *
136
+ * Story #3358 — when `/epic-deliver` is resumed on a partially-complete
137
+ * Epic, `epic-deliver-prepare.js` recomputes the wave DAG over only the
138
+ * **not-done** Stories (`build-wave-dag.js#discoverOpenStories` drops the
139
+ * closed/merged Stories). The recomputed plan is therefore *shorter* and
140
+ * **re-indexed from 0** — `plan[0]` is the next ready wave. The preserved
141
+ * checkpoint, however, still carries the prior `currentWave` (e.g. `2`)
142
+ * and a `waves[]` history keyed to the *old* index space. `wave-tick.js`
143
+ * then indexes `plan[currentWave]` into the new plan and dispatches the
144
+ * wrong wave — silently skipping the Stories that are actually ready.
145
+ *
146
+ * Prepare already owns the `plan` field (it overwrites it on every run),
147
+ * so it must equally own the pointer that indexes into that plan. This
148
+ * helper is the single point of reconciliation:
149
+ *
150
+ * - When the recomputed `nextPlan` is **structurally identical** to the
151
+ * persisted `priorPlan` (an idempotent re-prepare with no Story
152
+ * completed since the last run), the pointer is preserved verbatim so
153
+ * in-flight wave progress is not lost.
154
+ * - When the recomputed `nextPlan` **differs** (a Story merged → the
155
+ * plan got shorter / re-indexed), the pointer is reset: `currentWave`
156
+ * to `0` (the new plan's index space starts at the first not-done
157
+ * wave) and `waves[]` to `[]` (the prior history references the old
158
+ * index space and would mis-key `readGateFailures`).
159
+ *
160
+ * Plan equality is compared on the Story-id matrix only — `title` /
161
+ * `worktree` churn on an otherwise-identical plan must not trip a reset.
162
+ *
163
+ * Pure function — no I/O, no provider, no side effects.
164
+ *
165
+ * @param {{
166
+ * currentWave?: number,
167
+ * waves?: Array<unknown>,
168
+ * }} checkpoint The persisted checkpoint fields to reconcile.
169
+ * @param {Array<Array<{ id?: number, storyId?: number, number?: number }>>} priorPlan
170
+ * The plan currently persisted on the checkpoint (may be undefined on a
171
+ * first run).
172
+ * @param {Array<Array<{ id?: number, storyId?: number, number?: number }>>} nextPlan
173
+ * The freshly-recomputed plan prepare is about to persist.
174
+ * @returns {{ currentWave: number, waves: Array<unknown> }} The reconciled
175
+ * pointer fields. Always returns concrete values so the caller can spread
176
+ * them onto the checkpoint payload unconditionally.
177
+ */
178
+ export function reconcileResumePointer(checkpoint, priorPlan, nextPlan) {
179
+ const safeWaves = Array.isArray(checkpoint?.waves) ? checkpoint.waves : [];
180
+ const currentWave = Number.isInteger(checkpoint?.currentWave)
181
+ ? checkpoint.currentWave
182
+ : 0;
183
+ if (planStoryMatrixEqual(priorPlan, nextPlan)) {
184
+ return { currentWave, waves: safeWaves };
185
+ }
186
+ // Plan was recomputed (resume after a completed wave): the new plan is
187
+ // 0-indexed over the remaining not-done waves. Reset the pointer and
188
+ // drop the stale history so `wave-tick.js` reads `plan[0]`.
189
+ return { currentWave: 0, waves: [] };
190
+ }
191
+
192
+ /**
193
+ * Compare two wave plans on their Story-id matrix only. Each plan is
194
+ * `Array<Array<{ id|storyId|number }>>`; equality requires the same wave
195
+ * count, the same per-wave Story count, and the same Story ids in the same
196
+ * positions. `title` / `worktree` fields are ignored so cosmetic churn on
197
+ * an otherwise-identical plan does not register as a change.
198
+ *
199
+ * Pure helper for {@link reconcileResumePointer}.
200
+ *
201
+ * @param {Array<Array<object>>|undefined} a
202
+ * @param {Array<Array<object>>|undefined} b
203
+ * @returns {boolean}
204
+ */
205
+ function planStoryMatrixEqual(a, b) {
206
+ const left = Array.isArray(a) ? a : [];
207
+ const right = Array.isArray(b) ? b : [];
208
+ if (left.length !== right.length) return false;
209
+ for (let i = 0; i < left.length; i += 1) {
210
+ const wl = Array.isArray(left[i]) ? left[i] : [];
211
+ const wr = Array.isArray(right[i]) ? right[i] : [];
212
+ if (wl.length !== wr.length) return false;
213
+ for (let j = 0; j < wl.length; j += 1) {
214
+ if (storyIdOf(wl[j]) !== storyIdOf(wr[j])) return false;
215
+ }
216
+ }
217
+ return true;
218
+ }
219
+
220
+ /**
221
+ * Extract the Story id from a plan entry. Mirrors the resolution order
222
+ * `wave-runner/tick.js#storyIdOf` uses so the equality check keys on the
223
+ * same identity the tick dispatches against. Returns `null` for shapeless
224
+ * entries so two `null`s never compare equal by accident.
225
+ *
226
+ * @param {object|number|null|undefined} entry
227
+ * @returns {number|null}
228
+ */
229
+ function storyIdOf(entry) {
230
+ if (typeof entry === 'number') return entry;
231
+ if (!entry || typeof entry !== 'object') return null;
232
+ const id = entry.id ?? entry.storyId ?? entry.number;
233
+ return Number.isInteger(id) ? id : null;
234
+ }
235
+
236
+ /**
237
+ * Append a manual-intervention record to the checkpoint. Out-of-band
238
+ * recovery steps the host LLM performs during a delivery — `AskUserQuestion`
239
+ * calls, `git restore`/`git reset` against the working tree, manual `--no-ff`
240
+ * recovery merges, story-close `--skipValidation` overrides — disqualify the
241
+ * Epic from auto-merge. The auto-merge predicate reads this array and only
242
+ * fires when it is empty.
243
+ *
244
+ * @param {{ provider: import('../ITicketingProvider.js').ITicketingProvider, epicId: number, entry: { reason: string, source?: string, ts?: string } }} opts
245
+ * @returns {Promise<object>} the persisted state
246
+ */
247
+ export async function appendIntervention({ provider, epicId, entry } = {}) {
248
+ assertProvider(provider);
249
+ assertEpicId(epicId);
250
+ if (!entry || typeof entry.reason !== 'string' || entry.reason.length === 0) {
251
+ throw new TypeError('appendIntervention: { reason: string } is required.');
252
+ }
253
+ const existing = (await read({ provider, epicId })) ?? {};
254
+ const list = Array.isArray(existing.manualInterventions)
255
+ ? existing.manualInterventions
256
+ : [];
257
+ const record = {
258
+ reason: entry.reason,
259
+ source: typeof entry.source === 'string' ? entry.source : 'host-llm',
260
+ ts: typeof entry.ts === 'string' ? entry.ts : new Date().toISOString(),
261
+ };
262
+ return write({
263
+ provider,
264
+ epicId,
265
+ state: {
266
+ ...existing,
267
+ manualInterventions: [...list, record],
268
+ },
269
+ });
270
+ }
271
+
272
+ /**
273
+ * Advance the checkpoint's `phase` field to the next `/epic-deliver`
274
+ * phase. Reads the current state first so the caller does not need to
275
+ * keep an in-memory copy. Other state fields are preserved verbatim.
276
+ *
277
+ * Story #1155 / Epic #1142 — phase-granular resume. The runner writes
278
+ * the **next phase to run** here, not the phase that just finished, so
279
+ * a resume can match `phase === 'code-review'` to mean "Phase D is the
280
+ * next thing to do."
281
+ *
282
+ * @param {{ provider: import('../ITicketingProvider.js').ITicketingProvider, epicId: number, nextPhase: string }} opts
283
+ * nextPhase - One of `DELIVER_PHASES` or `'done'`.
284
+ */
285
+ export async function setPhase({ provider, epicId, nextPhase } = {}) {
286
+ assertProvider(provider);
287
+ assertEpicId(epicId);
288
+ assertValidDeliverPhase(nextPhase);
289
+ const existing = (await read({ provider, epicId })) ?? {};
290
+ return write({
291
+ provider,
292
+ epicId,
293
+ state: { ...existing, phase: nextPhase },
294
+ });
295
+ }
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Cross-Story conflict-finding gate for `epic-deliver-prepare.js`.
3
+ *
4
+ * Story #2297 — when the bounded `/epic-plan` flow emitted concurrency
5
+ * findings (Story #2296's validator pass), the operator may have shipped
6
+ * them through to `/epic-deliver` without resolving the underlying
7
+ * `depends_on` gaps. This gate runs at Phase 1 of `/epic-deliver` and
8
+ * refuses to flip the Epic to `agent::executing` when the upcoming
9
+ * waves still contain unresolved conflicts — surfacing the exact
10
+ * remediation commands the operator should run before retrying.
11
+ *
12
+ * The gate is opt-in by default:
13
+ * - Advisory findings (severity 'soft') only log a summary.
14
+ * - Hard findings (severity 'hard') OR `delivery.failOnConcurrencyHazards: true`
15
+ * promote a hard-stop.
16
+ *
17
+ * `--ignore-concurrency-hazards` bypasses the gate; the flag use is
18
+ * recorded on the Epic checkpoint so retro tooling can flag a run that
19
+ * shipped despite an outstanding hazard.
20
+ *
21
+ * The module is pure: it consumes a findings array and a wave plan and
22
+ * returns either a `{ ok: true }` envelope or throws. No I/O.
23
+ */
24
+
25
+ /**
26
+ * Build the set of "pending" story identifiers from a wave plan. A Story
27
+ * is pending unless its labels carry `agent::done`. Identifiers are
28
+ * collected in three shapes — `id` (number), `number`, and `slug` — so
29
+ * the caller can match findings keyed by any of them.
30
+ *
31
+ * @param {Array<Array<{ id?: number|string, number?: number|string, slug?: string, labels?: string[] }>>} wavePlan
32
+ * @returns {Set<string>}
33
+ */
34
+ export function collectPendingStoryKeys(wavePlan) {
35
+ const pending = new Set();
36
+ if (!Array.isArray(wavePlan)) return pending;
37
+ for (const wave of wavePlan) {
38
+ if (!Array.isArray(wave)) continue;
39
+ for (const story of wave) {
40
+ if (!story || typeof story !== 'object') continue;
41
+ const labels = Array.isArray(story.labels) ? story.labels : [];
42
+ if (labels.includes('agent::done')) continue;
43
+ if (story.id != null) pending.add(String(story.id));
44
+ if (story.number != null) pending.add(String(story.number));
45
+ if (story.slug != null) pending.add(String(story.slug));
46
+ }
47
+ }
48
+ return pending;
49
+ }
50
+
51
+ /**
52
+ * Extract every story identifier a finding references. Both finding
53
+ * kinds in #2296's shape carry slugs; future persisted shapes may carry
54
+ * numeric IDs — accept both transparently.
55
+ */
56
+ function findingStoryKeys(finding) {
57
+ const keys = [];
58
+ if (Array.isArray(finding?.storySlugs)) {
59
+ for (const s of finding.storySlugs) keys.push(String(s));
60
+ }
61
+ if (finding?.producer?.storySlug != null) {
62
+ keys.push(String(finding.producer.storySlug));
63
+ }
64
+ if (finding?.consumer?.storySlug != null) {
65
+ keys.push(String(finding.consumer.storySlug));
66
+ }
67
+ return keys;
68
+ }
69
+
70
+ /**
71
+ * Filter findings to those that touch at least one pending Story. A
72
+ * finding all of whose referenced Stories are already `agent::done` is
73
+ * harmless — the conflict has already played out — and is dropped.
74
+ *
75
+ * When `pendingKeys` is empty (every wave is done) every finding is
76
+ * filtered out. When a finding carries no identifiers (shape drift),
77
+ * conservatively keep it so the operator sees the signal.
78
+ *
79
+ * @param {object[]} findings
80
+ * @param {Set<string>} pendingKeys
81
+ * @returns {object[]}
82
+ */
83
+ export function filterFindingsToPending(findings, pendingKeys) {
84
+ if (!Array.isArray(findings)) return [];
85
+ if (!(pendingKeys instanceof Set)) return findings;
86
+ return findings.filter((f) => {
87
+ const keys = findingStoryKeys(f);
88
+ if (keys.length === 0) return true;
89
+ return keys.some((k) => pendingKeys.has(k));
90
+ });
91
+ }
92
+
93
+ function isHardFinding(f) {
94
+ return f && f.severity === 'hard';
95
+ }
96
+
97
+ /**
98
+ * Render the operator-facing remediation block for a hard-gate trip.
99
+ * Produces a single multi-line string suitable for `throw new Error(...)`
100
+ * — names every offending path, the affected Stories, and the exact
101
+ * `gh issue edit` commands needed to add the missing `depends_on` links.
102
+ */
103
+ export function renderGateErrorMessage(findings, ownerRepo) {
104
+ const lines = [
105
+ 'Refusing to flip Epic to agent::executing — cross-Story concurrency hazards remain unresolved.',
106
+ '',
107
+ ];
108
+ const sharedEditors = findings.filter((f) => f.kind === 'shared-editor');
109
+ const implicit = findings.filter(
110
+ (f) => f.kind === 'implicit-cross-story-dep',
111
+ );
112
+ if (sharedEditors.length > 0) {
113
+ lines.push('Shared-editor conflicts:');
114
+ for (const f of sharedEditors) {
115
+ const stories = Array.isArray(f.storySlugs) ? f.storySlugs : [];
116
+ lines.push(
117
+ ` - "${f.path}" written by ${stories.length} concurrent Stories: ${stories.map((s) => `#${s}`).join(', ')}`,
118
+ );
119
+ lines.push(
120
+ ' Remediation: add a `depends_on` chain or split the edits into a dedicated late-wave wiring Story.',
121
+ );
122
+ }
123
+ lines.push('');
124
+ }
125
+ if (implicit.length > 0) {
126
+ lines.push('Implicit cross-Story dependencies:');
127
+ for (const f of implicit) {
128
+ const p = f.producer ?? {};
129
+ const c = f.consumer ?? {};
130
+ lines.push(
131
+ ` - "${f.path}" produced by Story #${p.storySlug ?? '?'} consumed by Story #${c.storySlug ?? '?'} (body.${c.sourceField ?? '?'})`,
132
+ );
133
+ const repoFlag = ownerRepo ? ` --repo ${ownerRepo}` : '';
134
+ lines.push(
135
+ ` Remediation: gh issue edit ${c.storySlug ?? '?'}${repoFlag} --add-body $'\\n\\nblocked by #${p.storySlug ?? '?'}'`,
136
+ );
137
+ }
138
+ lines.push('');
139
+ }
140
+ lines.push(
141
+ 'Resolve the listed conflicts and re-run `/epic-deliver`, or pass `--ignore-concurrency-hazards` to bypass this gate.',
142
+ );
143
+ return lines.join('\n');
144
+ }
145
+
146
+ /**
147
+ * Apply the gate to a findings array.
148
+ *
149
+ * @param {object} input
150
+ * @param {object[]} input.findings - Findings filtered to pending waves.
151
+ * @param {object} [input.policy] - Resolved `delivery.failOnConcurrencyHazards` (boolean).
152
+ * @param {boolean} [input.ignore] - `--ignore-concurrency-hazards` flag value.
153
+ * @param {string} [input.ownerRepo] - "owner/repo" string for `gh issue edit` hints.
154
+ * @returns {{ tripped: boolean, reason: 'hard-severity'|'config-fail-on'|null, findings: object[], bypassed: boolean }}
155
+ * When the gate trips and `ignore` is false the caller should
156
+ * throw `renderGateErrorMessage(findings, ownerRepo)`. The
157
+ * returned `bypassed` is true when `ignore` short-circuits a
158
+ * trip; record it on the checkpoint.
159
+ */
160
+ export function evaluateConcurrencyGate({
161
+ findings = [],
162
+ policy = {},
163
+ ignore = false,
164
+ ownerRepo,
165
+ } = {}) {
166
+ void ownerRepo;
167
+ const hardFindings = findings.filter(isHardFinding);
168
+ const failOnConcurrencyHazards = policy.failOnConcurrencyHazards === true;
169
+ if (hardFindings.length > 0) {
170
+ return {
171
+ tripped: true,
172
+ reason: 'hard-severity',
173
+ findings: hardFindings,
174
+ bypassed: ignore === true,
175
+ };
176
+ }
177
+ if (failOnConcurrencyHazards && findings.length > 0) {
178
+ return {
179
+ tripped: true,
180
+ reason: 'config-fail-on',
181
+ findings,
182
+ bypassed: ignore === true,
183
+ };
184
+ }
185
+ return { tripped: false, reason: null, findings: [], bypassed: false };
186
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * deliver-phases.js — phase enum and ordering utility for `/epic-deliver`.
3
+ *
4
+ * Story #1155 (Epic #1142, 5.40.0). Originally extracted from the
5
+ * legacy class-based checkpoint module so the phase enum and close-tail
6
+ * semantics live in a dedicated module that downstream tooling (the
7
+ * contract test) can import without dragging the provider-coupled
8
+ * checkpoint surface along. Story #2409 routes the runtime checkpoint
9
+ * read/write surface through `../epic-run-state-store.js`; this file
10
+ * remains the canonical home for the phase enum + validator.
11
+ */
12
+
13
+ /**
14
+ * Ordered list of `/epic-deliver` phases. The checkpoint's `phase` field
15
+ * stores the **next phase to run**, so a mid-flight crash during
16
+ * `code-review` resumes by reading `phase === 'code-review'` and re-
17
+ * entering Phase D from the start.
18
+ */
19
+ export const DELIVER_PHASES = Object.freeze([
20
+ 'prepare',
21
+ 'wave-loop',
22
+ 'close-validation',
23
+ 'code-review',
24
+ 'retro',
25
+ 'finalize',
26
+ ]);
27
+
28
+ /**
29
+ * Pure: index of `phase` in `DELIVER_PHASES`. Returns `-1` for unknown
30
+ * values (callers treat that as "start fresh"); `+Infinity` for the
31
+ * terminal `'done'` sentinel.
32
+ */
33
+ export function phaseIndex(phase) {
34
+ if (phase === 'done') return Number.POSITIVE_INFINITY;
35
+ return DELIVER_PHASES.indexOf(phase);
36
+ }
37
+
38
+ /**
39
+ * Pure: validate that `nextPhase` is a known phase tag (or the terminal
40
+ * `'done'` sentinel). Throws on invalid input — exported so the
41
+ * `setPhase` store function and downstream callers share one failure mode.
42
+ */
43
+ export function assertValidDeliverPhase(nextPhase) {
44
+ if (nextPhase === 'done') return;
45
+ if (phaseIndex(nextPhase) >= 0) return;
46
+ throw new Error(
47
+ `Invalid /epic-deliver phase ${JSON.stringify(nextPhase)}. ` +
48
+ `Expected one of ${DELIVER_PHASES.join(', ')} or 'done'.`,
49
+ );
50
+ }
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Build the wave DAG from the Epic's open child Stories.
3
+ *
4
+ * `getSubTickets` returns the **direct** children of a parent ticket via
5
+ * native sub-issues + checklist links + body reverse-lookup (despite an
6
+ * older docstring claiming "every descendant"). The v5 canonical Epic
7
+ * hierarchy is Epic → Feature → Story → Task, so Stories live as
8
+ * **grandchildren** of the Epic. We therefore walk one level deeper from
9
+ * each `type::feature` direct child to collect the real Story set, and
10
+ * union with any direct-child Stories (some Epics still carry Stories
11
+ * directly while migrating).
12
+ *
13
+ * We additionally filter out closed Stories — `getSubTickets`'s reverse-
14
+ * reference search can surface closed-as-obsolete tickets whose body
15
+ * still names the Epic (e.g. a Story replaced during a planning
16
+ * iteration). Dispatching against those would silently fan a sub-agent
17
+ * out at pre-replan work.
18
+ *
19
+ * Throws if no open Stories are found.
20
+ */
21
+
22
+ import { parseBlockedBy } from '../../../dependency-parser.js';
23
+ import { computeWaves } from '../../../Graph.js';
24
+ import { TYPE_LABELS } from '../../../label-constants.js';
25
+ import { WaveScheduler } from '../wave-scheduler.js';
26
+
27
+ /**
28
+ * Walk Epic → Feature → Story (one descent past the Epic's direct
29
+ * children) and return the open `type::story` tickets, deduped by id.
30
+ *
31
+ * Exported so `snapshot.js#discoverStoryIds` and `epic-deliver-preflight`
32
+ * can share the same enumeration contract — the snapshot.end payload,
33
+ * preflight Story count, and wave DAG input set must never disagree.
34
+ */
35
+ export async function discoverOpenStories({ epicId, provider }) {
36
+ const descendants = (await provider.getSubTickets(epicId)) ?? [];
37
+ const features = descendants.filter((t) =>
38
+ (t.labels ?? []).includes(TYPE_LABELS.FEATURE),
39
+ );
40
+ const grandchildren = (
41
+ await Promise.all(
42
+ features.map(async (f) => {
43
+ const id = f.id ?? f.number;
44
+ return id == null ? [] : ((await provider.getSubTickets(id)) ?? []);
45
+ }),
46
+ )
47
+ ).flat();
48
+ const seen = new Set();
49
+ const stories = [];
50
+ for (const t of [...descendants, ...grandchildren]) {
51
+ const labels = t.labels ?? [];
52
+ if (!labels.includes(TYPE_LABELS.STORY)) continue;
53
+ const rawState = t.state ?? 'open';
54
+ const norm = typeof rawState === 'string' ? rawState.toLowerCase() : 'open';
55
+ if (norm !== 'open') continue;
56
+ const id = t.id ?? t.number;
57
+ if (id == null || seen.has(id)) continue;
58
+ seen.add(id);
59
+ stories.push(t);
60
+ }
61
+ return stories;
62
+ }
63
+
64
+ export async function runBuildWaveDagPhase(ctx, collaborators, state) {
65
+ const { epicId, provider } = ctx;
66
+ const bus = collaborators?.bus ?? null;
67
+ if (bus) {
68
+ await bus.emit('epic.plan.start', { epicId });
69
+ }
70
+ const stories = await discoverOpenStories({ epicId, provider });
71
+ if (!stories.length) {
72
+ throw new Error(`Epic #${epicId} has no child stories to dispatch.`);
73
+ }
74
+ const { adjacency, taskMap } = buildStoryDag(stories);
75
+ const waves = computeWaves(adjacency, taskMap);
76
+ const scheduler = new WaveScheduler(waves);
77
+ if (bus) {
78
+ // epic.plan.end carries the computed waves as the array-of-arrays
79
+ // shape declared by the schema. Each inner array is the storyIds
80
+ // dispatched together in that wave. `computeWaves` may return
81
+ // entries that are objects (when fed `taskMap`); we normalize to a
82
+ // simple numeric matrix here so the payload validates and replays
83
+ // off the ledger without coupling readers to internal types.
84
+ await bus.emit('epic.plan.end', {
85
+ waves: normalizeWavesForEmit(waves),
86
+ });
87
+ }
88
+ return { ...state, stories, waves, scheduler };
89
+ }
90
+
91
+ /**
92
+ * Normalize the runner's wave representation into the
93
+ * `Array<Array<integer>>` shape declared by
94
+ * `.agents/schemas/lifecycle/epic.plan.end.schema.json`. `computeWaves`
95
+ * returns waves of `taskMap` entries (objects with `id`); the ledger
96
+ * needs only the IDs. Defensive number coercion mirrors the same id
97
+ * extraction used in `buildStoryDag` above so emit and DAG stay
98
+ * structurally aligned.
99
+ */
100
+ function normalizeWavesForEmit(waves) {
101
+ if (!Array.isArray(waves)) return [];
102
+ return waves.map((wave) => {
103
+ if (!Array.isArray(wave)) return [];
104
+ return wave
105
+ .map((entry) => {
106
+ if (entry == null) return null;
107
+ if (typeof entry === 'number') return entry;
108
+ const id = entry.id ?? entry.number ?? entry.storyId;
109
+ return id == null ? null : Number(id);
110
+ })
111
+ .filter((n) => Number.isInteger(n) && n > 0);
112
+ });
113
+ }
114
+
115
+ /**
116
+ * Convert an ordered list of story tickets into the adjacency/taskMap shape
117
+ * that `Graph.computeWaves()` expects.
118
+ *
119
+ * Dependency source order (must match manifest-builder.js so dispatch manifest
120
+ * and runtime wave scheduling never disagree):
121
+ * 1. Canonical: `blocked by #NNN` / `depends on #NNN` parsed from the story
122
+ * ticket body via `parseBlockedBy` (same parser the dispatcher uses).
123
+ * 2. Fallback: explicit `dependencies` array on the provider-returned story
124
+ * object (present in fixture / test payloads; optional in live GitHub
125
+ * payloads).
126
+ * Only edges to other stories in this Epic are retained — foreign IDs are
127
+ * dropped so the DAG stays closed over the scheduled set.
128
+ */
129
+ function buildStoryDag(stories) {
130
+ const adjacency = new Map();
131
+ const taskMap = new Map();
132
+ const storyIds = new Set(stories.map((s) => Number(s.id ?? s.number)));
133
+ for (const s of stories) {
134
+ const id = Number(s.id ?? s.number);
135
+ const fromBody = parseBlockedBy(s.body ?? '');
136
+ const fromField = Array.isArray(s.dependencies)
137
+ ? s.dependencies.map(Number)
138
+ : [];
139
+ const merged = [...new Set([...fromBody, ...fromField])]
140
+ .map(Number)
141
+ .filter((dep) => dep !== id && storyIds.has(dep));
142
+ adjacency.set(id, merged);
143
+ taskMap.set(id, { ...s, id });
144
+ }
145
+ return { adjacency, taskMap };
146
+ }