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,310 @@
1
+ /**
2
+ * epic-deliver-lease-guard.js — preflight guards for `/epic-deliver`
3
+ * (Story #3482, Epic #3457).
4
+ *
5
+ * `/epic-deliver`'s prepare phase used to checkout `epic/<id>` over whatever
6
+ * the operator had checked out, yanking HEAD and resetting baselines under a
7
+ * live working session (the documented "epic-deliver shares the main checkout"
8
+ * footgun). This module supplies the two preflight guards the Tech Spec
9
+ * (#3476) wires into `epic-deliver-prepare.js` *before* any mutating git work:
10
+ *
11
+ * 1. **Epic-lease preflight.** Acquire the assignee-as-lease on the Epic
12
+ * ticket via `ticket-lease.acquireLease`. On a live foreign claim the
13
+ * guard **fails closed** — it throws a clear, operator-facing error that
14
+ * names the current owner (the `critical-workflow` risk axis demands
15
+ * refuse-and-exit, never warn-and-continue). `--steal` is the only
16
+ * override.
17
+ * 2. **Checkout-safety preflight.** Refuse to start when the working tree is
18
+ * dirty or HEAD is on a branch other than the expected one, instead of
19
+ * checking `epic/<id>` out over the operator's work.
20
+ *
21
+ * Both guards are pure over injected seams (a `git` shim with
22
+ * `statusPorcelain` / `currentBranch`, and the lease provider) so the unit
23
+ * suite exercises them without standing up a real repo or hitting GitHub.
24
+ * Liveness is threaded in via `heartbeatAt` exactly as `ticket-lease.js`
25
+ * documents — this module does not read the lifecycle ledger itself.
26
+ *
27
+ * Per `.agents/rules/orchestration-error-handling.md`, the composed guard
28
+ * surfaces unrecoverable failures with `throw new Error(...)` (mapped to
29
+ * `process.exit(1)` by the `runAsCli` boundary), never `Logger.fatal`.
30
+ */
31
+
32
+ import { acquireLease, normalizeOperatorHandle } from './ticket-lease.js';
33
+
34
+ /**
35
+ * Resolve the acquiring operator's identity. Precedence (Tech Spec #3476):
36
+ * 1. An explicit `--as <handle>` flag.
37
+ * 2. `github.operatorHandle` in `.agentrc.json`.
38
+ * 3. The local `git config user.email`.
39
+ *
40
+ * The `@`-prefix some operators carry on `operatorHandle` is stripped so the
41
+ * value matches the bare login written to a ticket's `assignees`.
42
+ *
43
+ * @param {object} args
44
+ * @param {string} [args.asFlag] Explicit `--as` value.
45
+ * @param {object} [args.config] Resolved config (reads github.operatorHandle).
46
+ * @param {string} [args.gitUserEmail] Fallback `git config user.email`.
47
+ * @returns {string|null} The resolved operator handle, or null when none could
48
+ * be determined.
49
+ */
50
+ export function resolveOperator({ asFlag, config, gitUserEmail } = {}) {
51
+ const candidates = [asFlag, config?.github?.operatorHandle, gitUserEmail];
52
+ for (const raw of candidates) {
53
+ const normalized = normalizeOperatorHandle(raw);
54
+ if (normalized !== null) return normalized;
55
+ }
56
+ return null;
57
+ }
58
+
59
+ /**
60
+ * Normalise the expected-branch argument into a non-empty list. `/epic-deliver`
61
+ * may legitimately start from either the Epic integration branch (`epic/<id>`,
62
+ * on a resume) or the project base branch (`main`, on a fresh run), so the
63
+ * guard accepts a set rather than a single name.
64
+ *
65
+ * @param {string|string[]} expectedBranch
66
+ * @returns {string[]}
67
+ */
68
+ function normaliseExpectedBranches(expectedBranch) {
69
+ const list = (
70
+ Array.isArray(expectedBranch) ? expectedBranch : [expectedBranch]
71
+ ).filter((b) => typeof b === 'string' && b.length > 0);
72
+ if (list.length === 0) {
73
+ throw new Error('checkCheckoutSafety: expectedBranch is required');
74
+ }
75
+ return list;
76
+ }
77
+
78
+ /**
79
+ * Pure checkout-safety classifier. The working tree must be clean and HEAD
80
+ * must sit on one of `expectedBranch` before prepare moves anything.
81
+ *
82
+ * @param {object} args
83
+ * @param {object} args.git Injected git shim.
84
+ * @param {() => { dirty: boolean, entries?: string }} args.git.statusPorcelain
85
+ * Returns whether the tree has uncommitted/untracked changes.
86
+ * @param {() => string|null} args.git.currentBranch Returns HEAD's branch (or
87
+ * null in detached-HEAD state).
88
+ * @param {string|string[]} args.expectedBranch The branch (or branches)
89
+ * prepare expects HEAD on (typically `epic/<id>` or the project base branch).
90
+ * @returns {{
91
+ * safe: boolean,
92
+ * reason: 'clean'|'dirty'|'wrong-branch'|'detached-head',
93
+ * currentBranch: string|null,
94
+ * expectedBranches: string[],
95
+ * dirtyEntries?: string,
96
+ * }}
97
+ */
98
+ export function checkCheckoutSafety({ git, expectedBranch }) {
99
+ if (!git || typeof git.statusPorcelain !== 'function') {
100
+ throw new Error(
101
+ 'checkCheckoutSafety: git shim with statusPorcelain/currentBranch is required',
102
+ );
103
+ }
104
+ const expectedBranches = normaliseExpectedBranches(expectedBranch);
105
+
106
+ const status = git.statusPorcelain();
107
+ if (status?.dirty) {
108
+ return {
109
+ safe: false,
110
+ reason: 'dirty',
111
+ currentBranch: git.currentBranch(),
112
+ expectedBranches,
113
+ dirtyEntries: status.entries,
114
+ };
115
+ }
116
+
117
+ const branch = git.currentBranch();
118
+ if (branch === null || branch === undefined || branch === '') {
119
+ return {
120
+ safe: false,
121
+ reason: 'detached-head',
122
+ currentBranch: null,
123
+ expectedBranches,
124
+ };
125
+ }
126
+ if (!expectedBranches.includes(branch)) {
127
+ return {
128
+ safe: false,
129
+ reason: 'wrong-branch',
130
+ currentBranch: branch,
131
+ expectedBranches,
132
+ };
133
+ }
134
+ return {
135
+ safe: true,
136
+ reason: 'clean',
137
+ currentBranch: branch,
138
+ expectedBranches,
139
+ };
140
+ }
141
+
142
+ /**
143
+ * Render the operator-facing message for a failed checkout-safety guard.
144
+ *
145
+ * @param {ReturnType<typeof checkCheckoutSafety>} result
146
+ * @returns {string}
147
+ */
148
+ export function renderCheckoutRefusal(result) {
149
+ const expected = result.expectedBranches.map((b) => `'${b}'`).join(' or ');
150
+ if (result.reason === 'dirty') {
151
+ return (
152
+ `[epic-deliver] Refusing to start: the working tree is dirty. ` +
153
+ `/epic-deliver will not check out ${expected} over uncommitted ` +
154
+ `or untracked changes — commit, stash, or clean them, then re-run.\n` +
155
+ `--- dirty entries ---\n${result.dirtyEntries ?? '(unavailable)'}`
156
+ );
157
+ }
158
+ if (result.reason === 'detached-head') {
159
+ return (
160
+ `[epic-deliver] Refusing to start: HEAD is detached. /epic-deliver ` +
161
+ `expects HEAD on ${expected}. Check one out before re-running.`
162
+ );
163
+ }
164
+ return (
165
+ `[epic-deliver] Refusing to start: HEAD is on '${result.currentBranch}', ` +
166
+ `not the expected ${expected}. /epic-deliver will not yank HEAD ` +
167
+ `away from your branch — switch to ${expected} yourself before re-running.`
168
+ );
169
+ }
170
+
171
+ /**
172
+ * Render the operator-facing message for a refused (live foreign) lease.
173
+ *
174
+ * @param {{ owner: string|null }} lease
175
+ * @param {number} epicId
176
+ * @returns {string}
177
+ */
178
+ export function renderLeaseRefusal(lease, epicId) {
179
+ return (
180
+ `[epic-deliver] Refusing to start: Epic #${epicId} is already claimed by ` +
181
+ `'${lease.owner}' with a live lease (recent heartbeat within the TTL). ` +
182
+ `Another /epic-deliver run is driving this Epic. Wait for it to finish, ` +
183
+ `or pass --steal to forcibly transfer the claim.`
184
+ );
185
+ }
186
+
187
+ /**
188
+ * Acquire the Epic lease for `operator`, failing closed on a live foreign
189
+ * claim. Returns the `acquireLease` result on success.
190
+ *
191
+ * @param {object} args
192
+ * @param {object} args.provider Ticketing provider.
193
+ * @param {number} args.epicId Epic ticket id.
194
+ * @param {string} args.operator Resolved operator handle.
195
+ * @param {number|null} [args.heartbeatAt] Current owner's last heartbeat (epoch ms).
196
+ * @param {boolean} [args.steal=false] Transfer a live foreign claim.
197
+ * @param {object} [args.config] Resolved config (TTL default).
198
+ * @param {number} [args.now] Injectable clock.
199
+ * @returns {Promise<{ acquired: boolean, owner: string, previousOwner: string|null, reason: string }>}
200
+ * @throws {Error} when the Epic carries a live foreign claim and `steal` is false.
201
+ */
202
+ export async function acquireEpicLease({
203
+ provider,
204
+ epicId,
205
+ operator,
206
+ heartbeatAt = null,
207
+ steal = false,
208
+ config,
209
+ now,
210
+ }) {
211
+ const result = await acquireLease({
212
+ provider,
213
+ ticketId: epicId,
214
+ operator,
215
+ heartbeatAt,
216
+ steal,
217
+ config,
218
+ now,
219
+ });
220
+ if (!result.acquired) {
221
+ throw new Error(renderLeaseRefusal(result, epicId));
222
+ }
223
+ return result;
224
+ }
225
+
226
+ /**
227
+ * Compose the two preflight guards in the order prepare needs them: the
228
+ * checkout-safety check first (cheap, local, no network), then the Epic-lease
229
+ * acquisition (a GitHub round-trip). Both fail closed by throwing.
230
+ *
231
+ * The checkout-safety guard runs first (cheap, local) and always executes. The
232
+ * Epic-lease step then **fails closed**: when `operator` cannot be resolved
233
+ * (null — `--as`, `github.operatorHandle`, and `git user.email` all empty, with
234
+ * the shipped `@[USERNAME]` placeholder normalised to null), this throws rather
235
+ * than running an ownerless, unguarded delivery. The lease is the cross-clone
236
+ * coordination layer; without an identity it cannot serialise concurrent runs,
237
+ * so silently skipping it would defeat the guard.
238
+ *
239
+ * @param {object} args
240
+ * @param {number} args.epicId
241
+ * @param {string|string[]} args.expectedBranch Branch(es) prepare expects HEAD on.
242
+ * @param {object} args.git Injected git shim (statusPorcelain/currentBranch).
243
+ * @param {object} args.provider Ticketing provider for the lease.
244
+ * @param {string|null} args.operator Resolved operator handle (null fails closed → throw).
245
+ * @param {number|null} [args.heartbeatAt] Current owner's last heartbeat (epoch ms).
246
+ * @param {boolean} [args.steal=false] Transfer a live foreign claim.
247
+ * @param {object} [args.config] Resolved config.
248
+ * @param {number} [args.now] Injectable clock.
249
+ * @param {object} [args.logger] Logger with info/warn.
250
+ * @returns {Promise<{
251
+ * checkout: ReturnType<typeof checkCheckoutSafety>,
252
+ * lease: { acquired: boolean, owner: string, reason: string },
253
+ * }>}
254
+ * @throws {Error} on a dirty/wrong-branch tree, an unresolvable operator
255
+ * identity, or a refused live foreign lease.
256
+ */
257
+ export async function runPrepareGuards({
258
+ epicId,
259
+ expectedBranch,
260
+ git,
261
+ provider,
262
+ operator,
263
+ heartbeatAt = null,
264
+ steal = false,
265
+ config,
266
+ now,
267
+ logger,
268
+ }) {
269
+ const log = logger ?? { info: () => {}, warn: () => {} };
270
+
271
+ const checkout = checkCheckoutSafety({ git, expectedBranch });
272
+ if (!checkout.safe) {
273
+ throw new Error(renderCheckoutRefusal(checkout));
274
+ }
275
+ log.info?.(
276
+ `[epic-deliver] ✅ Checkout-safety guard passed (clean tree on '${checkout.currentBranch}').`,
277
+ );
278
+
279
+ if (!operator) {
280
+ throw new Error(
281
+ '[epic-deliver] Refusing to start: no operator identity could be ' +
282
+ 'resolved. --as, github.operatorHandle (unset or still the shipped ' +
283
+ '`@[USERNAME]` placeholder), and git user.email are all empty, so the ' +
284
+ 'Epic-lease has no owner and concurrent /epic-deliver runs cannot be ' +
285
+ 'serialised. Set your own handle in .agentrc.local.json (e.g. ' +
286
+ '{ "github": { "operatorHandle": "@your-login" } }), pass --as <handle>, ' +
287
+ 'or configure git user.email, then re-run.',
288
+ );
289
+ }
290
+
291
+ const lease = await acquireEpicLease({
292
+ provider,
293
+ epicId,
294
+ operator,
295
+ heartbeatAt,
296
+ steal,
297
+ config,
298
+ now,
299
+ });
300
+ if (lease.reason === 'stolen') {
301
+ log.warn?.(
302
+ `[epic-deliver] ⚠️ Stole the Epic #${epicId} lease from '${lease.previousOwner}' via --steal (live claim forcibly transferred).`,
303
+ );
304
+ } else {
305
+ log.info?.(
306
+ `[epic-deliver] ✅ Acquired Epic #${epicId} lease for '${operator}' (reason=${lease.reason}).`,
307
+ );
308
+ }
309
+ return { checkout, lease };
310
+ }
@@ -0,0 +1,167 @@
1
+ /**
2
+ * cli.js — Phase 6 (CLI entry orchestration) of the epic-plan-decompose
3
+ * pipeline (Story #2466).
4
+ *
5
+ * Owns CLI flag parsing, the `--emit-context` JSON envelope path, and
6
+ * the tickets-file load → `runDecomposePhase` persist path. The
7
+ * partial-failure diagnostics emitter lives in the sibling
8
+ * `diagnostics.js` module.
9
+ *
10
+ * @module lib/orchestration/epic-plan-decompose/phases/cli
11
+ */
12
+
13
+ import { readFile } from 'node:fs/promises';
14
+ import { parseArgs } from 'node:util';
15
+
16
+ import { drainPendingCleanupAtBoot } from '../../../../epic-plan-spec.js';
17
+ import {
18
+ PROJECT_ROOT,
19
+ resolveConfig,
20
+ validateOrchestrationConfig,
21
+ } from '../../../config-resolver.js';
22
+ import {
23
+ Logger,
24
+ routeAllOutputToStderr,
25
+ STDERR_LOGGER,
26
+ } from '../../../Logger.js';
27
+ import { createProvider } from '../../../provider-factory.js';
28
+ import { buildDecompositionContext } from './context.js';
29
+ import { reportPartialFailure } from './diagnostics.js';
30
+ import { runDecomposePhase } from './persist.js';
31
+
32
+ const CLI_OPTIONS = {
33
+ epic: { type: 'string' },
34
+ tickets: { type: 'string' },
35
+ force: { type: 'boolean', default: false },
36
+ resume: { type: 'boolean', default: false },
37
+ 'allow-over-budget': { type: 'boolean', default: false },
38
+ 'allow-large-fan-out': { type: 'boolean', default: false },
39
+ 'emit-context': { type: 'boolean', default: false },
40
+ pretty: { type: 'boolean', default: false },
41
+ 'full-context': { type: 'boolean', default: false },
42
+ };
43
+
44
+ const USAGE =
45
+ 'Usage: epic-plan-decompose.js --epic <EpicId> (--emit-context [--pretty] [--full-context] | --tickets <file>) [--force | --resume] [--allow-over-budget] [--allow-large-fan-out]';
46
+
47
+ function parseEpicId(rawEpic) {
48
+ if (!rawEpic) throw new Error(USAGE);
49
+ const epicId = Number.parseInt(rawEpic, 10);
50
+ if (Number.isNaN(epicId)) {
51
+ throw new Error(`Invalid epic ID: "${rawEpic}" — must be a number.`);
52
+ }
53
+ return epicId;
54
+ }
55
+
56
+ function loadResolvedConfig() {
57
+ let config;
58
+ try {
59
+ config = resolveConfig();
60
+ // Epic #2880 / F14B: pass the canonical resolved config directly.
61
+ // The legacy `config.orchestration` pointer is gone; the validator
62
+ // reads `config.github` and `config.delivery.worktreeIsolation`.
63
+ validateOrchestrationConfig(config);
64
+ } catch (err) {
65
+ throw new Error(
66
+ `Orchestration config schema validation failed:\n${err.message}`,
67
+ );
68
+ }
69
+ return config;
70
+ }
71
+
72
+ async function driveDrainPendingCleanup({ config, provider, emitContext }) {
73
+ try {
74
+ await drainPendingCleanupAtBoot({
75
+ repoRoot: PROJECT_ROOT,
76
+ // Epic #2880 / F14B: drainPendingCleanupAtBoot now reads opts.config
77
+ // (canonical) and resolves the worktree root from
78
+ // config.delivery.worktreeIsolation.root.
79
+ config,
80
+ provider,
81
+ logger: emitContext ? STDERR_LOGGER : undefined,
82
+ });
83
+ } catch (err) {
84
+ Logger.warn(`[epic-plan-decompose] worktree sweep skipped: ${err.message}`);
85
+ }
86
+ }
87
+
88
+ async function runEmitContextPath({ epicId, provider, config, values }) {
89
+ const ctx = await buildDecompositionContext(epicId, provider, config, {
90
+ fullContext: values['full-context'],
91
+ });
92
+ // Surface the resolved budget on stderr so a misconfigured `.agentrc.json`
93
+ // (e.g. flat-key `maxTickets` instead of grouped `planning.maxTickets`) is
94
+ // visible to the operator. The decomposer prompt embeds the same value.
95
+ // Story #2798 — language changed from "prompt cap" to "reviewability
96
+ // budget" to match the new prompt/skill contract.
97
+ Logger.error(
98
+ `[epic-plan-decompose] Resolved planning.maxTickets = ${ctx.maxTickets} (reviewability budget).`,
99
+ );
100
+ const json = values.pretty
101
+ ? JSON.stringify(ctx, null, 2)
102
+ : JSON.stringify(ctx);
103
+ process.stdout.write(`${json}\n`);
104
+ }
105
+
106
+ async function loadTicketsFile(ticketsPath) {
107
+ if (!ticketsPath) {
108
+ throw new Error(
109
+ 'Missing --tickets <file>. (Use --emit-context first to gather authoring context.)',
110
+ );
111
+ }
112
+ const raw = await readFile(ticketsPath, 'utf8');
113
+ try {
114
+ return JSON.parse(raw);
115
+ } catch (err) {
116
+ throw new Error(
117
+ `Failed to parse tickets file "${ticketsPath}" as JSON: ${err.message}`,
118
+ );
119
+ }
120
+ }
121
+
122
+ async function runPersistPath({ epicId, provider, config, values }) {
123
+ const tickets = await loadTicketsFile(values.tickets);
124
+ let result;
125
+ try {
126
+ result = await runDecomposePhase(epicId, provider, { tickets }, config, {
127
+ force: values.force,
128
+ resume: values.resume,
129
+ allowOverBudget: values['allow-over-budget'],
130
+ allowLargeFanOut: values['allow-large-fan-out'],
131
+ });
132
+ } catch (err) {
133
+ await reportPartialFailure({ epicId, provider, err });
134
+ throw err;
135
+ }
136
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
137
+ }
138
+
139
+ /* node:coverage ignore next */
140
+ export async function main() {
141
+ const { values } = parseArgs({ options: CLI_OPTIONS });
142
+ const epicId = parseEpicId(values.epic);
143
+ if (values.force && values.resume) {
144
+ throw new Error('--force and --resume are mutually exclusive.');
145
+ }
146
+
147
+ const config = loadResolvedConfig();
148
+ // Epic #2880 / F14B: createProvider takes the canonical resolved config
149
+ // (it reads config.github). The legacy config.orchestration pointer is
150
+ // gone; passing it yields undefined and crashes the provider factory's
151
+ // hard guard.
152
+ const provider = createProvider(config);
153
+ const emitContext = values['emit-context'];
154
+
155
+ // Story #2278 — in --emit-context mode stdout is reserved for the JSON
156
+ // envelope. Flip every Logger sink that could land on stdout to stderr
157
+ // before any orchestration code runs.
158
+ if (emitContext) routeAllOutputToStderr();
159
+
160
+ await driveDrainPendingCleanup({ config, provider, emitContext });
161
+
162
+ if (emitContext) {
163
+ await runEmitContextPath({ epicId, provider, config, values });
164
+ return;
165
+ }
166
+ await runPersistPath({ epicId, provider, config, values });
167
+ }
@@ -0,0 +1,151 @@
1
+ /**
2
+ * context.js — Phase 3 of the epic-plan-decompose pipeline (Story #2466).
3
+ *
4
+ * Builds the authoring context (PRD + Tech Spec bodies, heuristics, system
5
+ * prompt, ticket cap) the host LLM / `epic-plan-decompose-author` Skill
6
+ * consumes when producing the ticket JSON array.
7
+ *
8
+ * Extracted verbatim from `epic-plan-decompose.js`; both
9
+ * `buildDecomposerSystemPrompt` and `buildDecompositionContext` retain
10
+ * their public-export contract for the existing unit tests.
11
+ *
12
+ * @module lib/orchestration/epic-plan-decompose/phases/context
13
+ */
14
+
15
+ import {
16
+ getLimits,
17
+ resolvePreflightCeilings,
18
+ } from '../../../config-resolver.js';
19
+ import { renderDecomposerSystemPrompt } from '../../../templates/decomposer-prompts.js';
20
+ import { read as readPlanState } from '../../epic-plan-state-store.js';
21
+ import { applyBudget } from '../../planning-context-budget.js';
22
+
23
+ export function buildDecomposerSystemPrompt(
24
+ heuristics = [],
25
+ { maxTickets } = {},
26
+ ) {
27
+ const base = renderDecomposerSystemPrompt({ maxTickets });
28
+ const heuristicsStr =
29
+ heuristics.length > 0
30
+ ? `### RISK HEURISTICS (planning metadata if any apply):\n- ${heuristics.join('\n- ')}`
31
+ : '';
32
+ return `${base}${heuristicsStr ? `\n\n${heuristicsStr}` : ''}`;
33
+ }
34
+
35
+ function resolveHeuristics(config) {
36
+ if (Array.isArray(config.planning?.riskHeuristics)) {
37
+ return config.planning.riskHeuristics;
38
+ }
39
+ return config.agentSettings?.planning?.riskHeuristics || [];
40
+ }
41
+
42
+ function projectBudgetedEntry(item, ticket, mode) {
43
+ if (mode === 'full') return { id: ticket.id, body: ticket.body };
44
+ return { id: ticket.id, body: null, bodySummary: item };
45
+ }
46
+
47
+ /**
48
+ * Read the persisted planning decision for the Epic so the decomposition
49
+ * authoring step (Phase 8) can cite the same risk classification the
50
+ * gate routing used in Phase 7. The decision lives in the `epic-plan-state`
51
+ * structured comment written by `epic-plan-spec.js`.
52
+ *
53
+ * Returns `{ planningRisk: null, reviewRouting: null }` when the comment
54
+ * is missing (older plans planned before Story #2801 landed) or when the
55
+ * payload predates the fields. The null sentinels are part of the
56
+ * decomposition context contract — callers MUST be able to JSON.stringify
57
+ * the result without losing the keys.
58
+ *
59
+ * @param {import('../../../ITicketingProvider.js').ITicketingProvider} provider
60
+ * @param {number} epicId
61
+ * @returns {Promise<{ planningRisk: object | null, reviewRouting: object | null }>}
62
+ */
63
+ async function readPlanningDecision(provider, epicId) {
64
+ let state = null;
65
+ try {
66
+ state = await readPlanState({ provider, epicId });
67
+ } catch (_err) {
68
+ // `read` already swallows JSON parse errors; a thrown error here
69
+ // means the provider couldn't fetch comments. Treat as null state —
70
+ // the decomposer can still author tickets without the risk envelope.
71
+ state = null;
72
+ }
73
+ if (!state || typeof state !== 'object') {
74
+ return { planningRisk: null, reviewRouting: null };
75
+ }
76
+ return {
77
+ planningRisk: state.planningRisk ?? null,
78
+ reviewRouting: state.reviewRouting ?? null,
79
+ };
80
+ }
81
+
82
+ async function fetchPlanningTickets(provider, epicId) {
83
+ const epic = await provider.getEpic(epicId);
84
+ if (!epic?.linkedIssues?.prd || !epic.linkedIssues.techSpec) {
85
+ throw new Error(
86
+ `[Decomposer] Epic #${epicId} is missing linked PRD or Tech Spec. Run the Epic Planner first.`,
87
+ );
88
+ }
89
+ const [prd, techSpec] = await Promise.all([
90
+ provider.getTicket(epic.linkedIssues.prd),
91
+ provider.getTicket(epic.linkedIssues.techSpec),
92
+ ]);
93
+ return { epic, prd, techSpec };
94
+ }
95
+
96
+ /**
97
+ * Build the authoring context the host LLM (or the
98
+ * `epic-plan-decompose-author` Skill) needs to produce the ticket JSON.
99
+ *
100
+ * PRD and Tech Spec bodies are bounded by the planning-context budget
101
+ * (Epic #817 Story 9). Pass `{ fullContext: true }` (CLI: `--full-context`)
102
+ * to restore the unbounded full bodies.
103
+ */
104
+ export async function buildDecompositionContext(
105
+ epicId,
106
+ provider,
107
+ config = {},
108
+ opts = {},
109
+ ) {
110
+ const { epic, prd, techSpec } = await fetchPlanningTickets(provider, epicId);
111
+ const { planningRisk, reviewRouting } = await readPlanningDecision(
112
+ provider,
113
+ epicId,
114
+ );
115
+ const heuristics = resolveHeuristics(config);
116
+ const limits = getLimits(config);
117
+ const maxTickets = limits.maxTickets;
118
+ const planningLimits = limits.planningContext;
119
+ const { fullContext = false } = opts;
120
+ const systemPrompt = buildDecomposerSystemPrompt(heuristics, { maxTickets });
121
+
122
+ const budgeted = applyBudget(
123
+ [
124
+ { path: `prd-${prd.id}.md`, content: prd.body ?? '' },
125
+ { path: `tech-spec-${techSpec.id}.md`, content: techSpec.body ?? '' },
126
+ ],
127
+ planningLimits,
128
+ { fullContext },
129
+ );
130
+ const [prdItem, techSpecItem] = budgeted.items;
131
+ return {
132
+ epic: { id: epic.id, title: epic.title },
133
+ prd: projectBudgetedEntry(prdItem, prd, budgeted.mode),
134
+ techSpec: projectBudgetedEntry(techSpecItem, techSpec, budgeted.mode),
135
+ heuristics,
136
+ systemPrompt,
137
+ maxTickets,
138
+ // Story #3875 — surface the real delivery envelope to the decomposer
139
+ // so Stories are sized against the hydration budget and the
140
+ // configured preflight ceilings rather than guessed.
141
+ maxTokenBudget: limits.maxTokenBudget,
142
+ preflightCeilings: resolvePreflightCeilings(config),
143
+ contextMode: budgeted.mode,
144
+ // Story #2801 — surface the Phase 7 planning decision so the
145
+ // decomposition authoring step can cite the same risk
146
+ // classification used by gate routing. Both fields are `null`
147
+ // when the Epic was planned before the decision contract existed.
148
+ planningRisk,
149
+ reviewRouting,
150
+ };
151
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * creation.js — sub-issue link reconciliation, Epic label transitions, and
3
+ * the advisory ticket-cap warning used by the reconciler-based persist flow
4
+ * (`persist.js`).
5
+ *
6
+ * Exports: `reconcileSubIssueLinks`, `setEpicLabel`,
7
+ * `warnTicketCapNearLimit`.
8
+ *
9
+ * @module lib/orchestration/epic-plan-decompose/phases/creation
10
+ */
11
+
12
+ import { Logger } from '../../../Logger.js';
13
+ import { AGENT_LABELS } from '../../../label-constants.js';
14
+
15
+ export async function reconcileSubIssueLinks(epicId, provider) {
16
+ if (typeof provider.reconcileSubIssueLinks !== 'function') return;
17
+ Logger.info(
18
+ `[Decomposer] Reconciling sub-issue API links for Epic #${epicId}...`,
19
+ );
20
+ const result = await provider.reconcileSubIssueLinks(epicId);
21
+ const { totalExpected, alreadyLinked, reconciled, failed, failures } = result;
22
+ if (failed === 0) {
23
+ const reconciledNote = reconciled > 0 ? ` (${reconciled} reconciled)` : '';
24
+ Logger.info(
25
+ `[Decomposer] linked ${alreadyLinked + reconciled}/${totalExpected} sub-issues${reconciledNote}`,
26
+ );
27
+ return;
28
+ }
29
+ for (const failure of failures) {
30
+ Logger.error(
31
+ `[Decomposer] sub-issue link gap: parent #${failure.parentId} ← child #${failure.childId}: ${failure.reason}`,
32
+ );
33
+ }
34
+ throw new Error(
35
+ `[Decomposer] Sub-issue reconciliation incomplete: ${failed}/${totalExpected} links could not be established (linked=${alreadyLinked}, reconciled=${reconciled}). See log for per-child reasons.`,
36
+ );
37
+ }
38
+
39
+ export async function setEpicLabel(provider, epicId, targetLabel) {
40
+ const planningLabels = [AGENT_LABELS.REVIEW_SPEC, AGENT_LABELS.READY];
41
+ await provider.updateTicket(epicId, {
42
+ labels: {
43
+ add: [targetLabel],
44
+ remove: planningLabels.filter((l) => l !== targetLabel),
45
+ },
46
+ });
47
+ }
48
+
49
+ /**
50
+ * Advisory-only ticket-count check (Story #2798).
51
+ *
52
+ * `maxTickets` is a **reviewability budget**, not a hard authoring cap.
53
+ * This helper emits a non-destructive warning when a decomposition meets
54
+ * or exceeds the budget so the operator can spot over-budget plans early
55
+ * in the persist flow. It never blocks — the hard gate lives in the
56
+ * `runDecomposePhase` over-budget check, which requires an explicit
57
+ * `allowOverBudget` (CLI: `--allow-over-budget`) override.
58
+ *
59
+ * @param {Array} tickets
60
+ * @param {number} maxTickets — the reviewability budget
61
+ * @param {string} [tag] — log prefix
62
+ * @param {{ logger?: Pick<typeof Logger, 'warn'> }} [opts]
63
+ */
64
+ export function warnTicketCapNearLimit(
65
+ tickets,
66
+ maxTickets,
67
+ tag = 'epic-plan-decompose',
68
+ { logger = Logger } = {},
69
+ ) {
70
+ if (tickets.length < maxTickets) return;
71
+ logger.warn(
72
+ `[${tag}] ⚠️ Received ${tickets.length} tickets against a reviewability budget of ${maxTickets}. Review the Feature/Story split before persisting; over-budget persistence requires --allow-over-budget.`,
73
+ );
74
+ }