mandrel 1.93.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/.agents/README.md +59 -73
  2. package/.agents/agents/acceptance-critic.md +129 -0
  3. package/.agents/agents/story-worker.md +161 -0
  4. package/.agents/docs/SDLC.md +489 -1285
  5. package/.agents/docs/agentrc-reference.json +177 -67
  6. package/.agents/docs/configuration.md +108 -136
  7. package/.agents/docs/execution-reference.md +44 -22
  8. package/.agents/docs/quality-gates.md +13 -19
  9. package/.agents/docs/workflows.md +3 -3
  10. package/.agents/instructions.md +107 -108
  11. package/.agents/rules/ci-remediation.md +8 -12
  12. package/.agents/rules/git-conventions-reference.md +224 -0
  13. package/.agents/rules/git-conventions.md +42 -223
  14. package/.agents/rules/security-baseline.md +5 -0
  15. package/.agents/rules/testing-standards.md +106 -13
  16. package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
  17. package/.agents/schemas/agentrc.schema.json +71 -201
  18. package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
  19. package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
  20. package/.agents/schemas/risk-verdict.schema.json +0 -13
  21. package/.agents/scripts/acceptance-eval.js +62 -18
  22. package/.agents/scripts/agents-bootstrap-github.js +1 -1
  23. package/.agents/scripts/analyze-execution.js +1 -1
  24. package/.agents/scripts/audit-to-stories.js +7 -7
  25. package/.agents/scripts/boot-sweep.js +1 -1
  26. package/.agents/scripts/check-context-budget.js +62 -5
  27. package/.agents/scripts/check-lifecycle-lint.js +6 -9
  28. package/.agents/scripts/check-prepush-recovery.js +1 -1
  29. package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
  30. package/.agents/scripts/diagnose-friction.js +0 -6
  31. package/.agents/scripts/lib/Logger.js +6 -10
  32. package/.agents/scripts/lib/audit-suite/runner.js +2 -2
  33. package/.agents/scripts/lib/audit-suite/selector.js +5 -5
  34. package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
  35. package/.agents/scripts/lib/baselines/kernel.js +206 -18
  36. package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -4
  37. package/.agents/scripts/lib/baselines/reader.js +1 -6
  38. package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
  39. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
  40. package/.agents/scripts/lib/bootstrap/project-bootstrap.js +56 -18
  41. package/.agents/scripts/lib/checks/core-bare-clean.js +2 -2
  42. package/.agents/scripts/lib/checks/index.js +2 -1
  43. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +23 -21
  44. package/.agents/scripts/lib/cli/standard-args.js +13 -22
  45. package/.agents/scripts/lib/cli-args.js +16 -7
  46. package/.agents/scripts/lib/close-validation/gates.js +160 -22
  47. package/.agents/scripts/lib/config/acceptance-eval.js +52 -5
  48. package/.agents/scripts/lib/config/ci.js +6 -31
  49. package/.agents/scripts/lib/config/delivery-routing.js +103 -0
  50. package/.agents/scripts/lib/config/explain.js +57 -36
  51. package/.agents/scripts/lib/config/limits.js +17 -58
  52. package/.agents/scripts/lib/config/paths.js +0 -2
  53. package/.agents/scripts/lib/config/quality.js +1 -1
  54. package/.agents/scripts/lib/config/runners.js +17 -50
  55. package/.agents/scripts/lib/config/temp-paths.js +19 -14
  56. package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
  57. package/.agents/scripts/lib/config-resolver.js +3 -8
  58. package/.agents/scripts/lib/config-settings-schema-delivery.js +46 -136
  59. package/.agents/scripts/lib/config-settings-schema-quality.js +17 -14
  60. package/.agents/scripts/lib/config-settings-schema.js +52 -38
  61. package/.agents/scripts/lib/dependency-parser.js +3 -2
  62. package/.agents/scripts/lib/doc-tiers.js +39 -4
  63. package/.agents/scripts/lib/duplicate-search.js +211 -41
  64. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
  65. package/.agents/scripts/lib/findings/promote-finding.js +5 -5
  66. package/.agents/scripts/lib/framework-version.js +2 -3
  67. package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
  68. package/.agents/scripts/lib/git-branch-lifecycle.js +17 -22
  69. package/.agents/scripts/lib/git-utils.js +32 -6
  70. package/.agents/scripts/lib/github/framework-repo.js +6 -0
  71. package/.agents/scripts/lib/label-constants.js +10 -23
  72. package/.agents/scripts/lib/label-taxonomy.js +9 -43
  73. package/.agents/scripts/lib/observability/active-story-env.js +112 -3
  74. package/.agents/scripts/lib/observability/hook-heartbeat.js +187 -0
  75. package/.agents/scripts/lib/observability/source-classifier.js +3 -3
  76. package/.agents/scripts/lib/observability/tool-trace-hook.js +15 -4
  77. package/.agents/scripts/lib/onboard/init-tail.js +1 -3
  78. package/.agents/scripts/lib/orchestration/acceptance-clusters.js +111 -0
  79. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +32 -4
  80. package/.agents/scripts/lib/orchestration/audit-lens-routing.js +128 -0
  81. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +273 -0
  82. package/.agents/scripts/lib/orchestration/ceremony-routing.js +204 -0
  83. package/.agents/scripts/lib/orchestration/code-review.js +20 -268
  84. package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
  85. package/.agents/scripts/lib/orchestration/consolidation-precondition.js +1 -1
  86. package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
  87. package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
  88. package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
  89. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
  90. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +8 -8
  91. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +2 -2
  92. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
  93. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +17 -43
  94. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
  95. package/.agents/scripts/lib/orchestration/merge-block-class.js +1 -1
  96. package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
  97. package/.agents/scripts/lib/orchestration/plan-context.js +248 -266
  98. package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +3 -2
  99. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +1 -1
  100. package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
  101. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +61 -0
  102. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +97 -0
  103. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +223 -854
  104. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +361 -0
  105. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +35 -108
  106. package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
  107. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
  108. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +14 -14
  109. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
  110. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/risk-verdict.js +3 -4
  111. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +2 -2
  112. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +8 -20
  113. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +3 -2
  114. package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
  115. package/.agents/scripts/lib/orchestration/preflight-cache.js +5 -5
  116. package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
  117. package/.agents/scripts/lib/orchestration/resolve-plan-run.js +155 -0
  118. package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
  119. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +8 -8
  120. package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
  121. package/.agents/scripts/lib/orchestration/review-depth.js +26 -12
  122. package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
  123. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
  124. package/.agents/scripts/lib/orchestration/run-epilogue.js +426 -0
  125. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +1 -1
  126. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +1 -0
  127. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +95 -41
  128. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +16 -13
  129. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +40 -0
  130. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +11 -3
  131. package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
  132. package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
  133. package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
  134. package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
  135. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
  136. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +15 -12
  137. package/.agents/scripts/lib/orchestration/story-follow-ups.js +237 -0
  138. package/.agents/scripts/lib/orchestration/story-init-remote.js +47 -0
  139. package/.agents/scripts/lib/orchestration/story-plan-state.js +48 -0
  140. package/.agents/scripts/lib/orchestration/{epic-runner → story-progress}/story-run-progress-writer.js +3 -3
  141. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
  142. package/.agents/scripts/lib/orchestration/task-body-validator.js +8 -18
  143. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +11 -61
  144. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +189 -373
  145. package/.agents/scripts/lib/orchestration/ticket-validator.js +3 -8
  146. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +0 -25
  147. package/.agents/scripts/lib/orchestration/ticketing/reads.js +29 -26
  148. package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -5
  149. package/.agents/scripts/lib/planning-corpus.js +16 -11
  150. package/.agents/scripts/lib/preflight-runner.js +2 -2
  151. package/.agents/scripts/lib/provider-factory.js +1 -1
  152. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
  153. package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +36 -0
  154. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
  155. package/.agents/scripts/lib/story-adjacency.js +11 -14
  156. package/.agents/scripts/lib/story-body/story-body.js +124 -70
  157. package/.agents/scripts/lib/story-plan.js +2 -4
  158. package/.agents/scripts/lib/templates/decomposer-prompts.js +46 -45
  159. package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
  160. package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +26 -26
  161. package/.agents/scripts/lib/validation-evidence.js +1 -1
  162. package/.agents/scripts/lib/wave-runner/ready-set.js +6 -6
  163. package/.agents/scripts/lib/workspace-provisioner.js +1 -1
  164. package/.agents/scripts/lib/worktree/lifecycle/reap.js +5 -7
  165. package/.agents/scripts/lint-issue-body.js +71 -40
  166. package/.agents/scripts/mandrel-update-preflight.js +1 -1
  167. package/.agents/scripts/notify.js +4 -3
  168. package/.agents/scripts/plan-context.js +64 -74
  169. package/.agents/scripts/plan-persist.js +121 -280
  170. package/.agents/scripts/plan-run-epilogue.js +97 -0
  171. package/.agents/scripts/post-structured-comment.js +38 -0
  172. package/.agents/scripts/providers/github/issues.js +17 -33
  173. package/.agents/scripts/providers/github/mappers.js +0 -12
  174. package/.agents/scripts/providers/github/tickets.js +2 -5
  175. package/.agents/scripts/resolve-plan-run.js +117 -0
  176. package/.agents/scripts/signals-view.js +24 -19
  177. package/.agents/scripts/single-story-close.js +11 -14
  178. package/.agents/scripts/single-story-confirm-merge.js +39 -23
  179. package/.agents/scripts/single-story-init.js +29 -20
  180. package/.agents/scripts/stories-wave-tick.js +6 -6
  181. package/.agents/scripts/story-plan.js +26 -47
  182. package/.agents/scripts/sync-claude-agents.js +165 -0
  183. package/.agents/scripts/update-ticket-state.js +37 -15
  184. package/.agents/skills/core/analyze-execution/SKILL.md +21 -18
  185. package/.agents/skills/core/api-and-interface-design/SKILL.md +5 -3
  186. package/.agents/skills/core/code-review-and-quality/SKILL.md +63 -7
  187. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +1 -1
  188. package/.agents/skills/core/gates-and-baselines/SKILL.md +149 -0
  189. package/.agents/skills/core/idea-refinement/SKILL.md +8 -14
  190. package/.agents/skills/core/qa-coverage-mapping/SKILL.md +7 -7
  191. package/.agents/skills/core/scope-triage/SKILL.md +28 -172
  192. package/.agents/skills/skills.index.json +8 -418
  193. package/.agents/starter-agentrc.json +0 -5
  194. package/.agents/templates/agent-protocol.md +9 -10
  195. package/.agents/workflows/audit-architecture.md +3 -3
  196. package/.agents/workflows/audit-clean-code.md +3 -3
  197. package/.agents/workflows/audit-dependencies.md +3 -3
  198. package/.agents/workflows/audit-devops.md +3 -3
  199. package/.agents/workflows/audit-documentation.md +5 -5
  200. package/.agents/workflows/audit-lighthouse.md +3 -3
  201. package/.agents/workflows/audit-navigability.md +3 -2
  202. package/.agents/workflows/audit-performance.md +3 -3
  203. package/.agents/workflows/audit-privacy.md +3 -3
  204. package/.agents/workflows/audit-quality.md +3 -3
  205. package/.agents/workflows/audit-security.md +3 -3
  206. package/.agents/workflows/audit-seo.md +3 -3
  207. package/.agents/workflows/audit-sre.md +3 -3
  208. package/.agents/workflows/audit-to-stories.md +20 -20
  209. package/.agents/workflows/audit-ux-ui.md +3 -3
  210. package/.agents/workflows/deliver.md +122 -131
  211. package/.agents/workflows/git-cleanup.md +3 -4
  212. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  213. package/.agents/workflows/helpers/acceptance-self-eval.md +52 -40
  214. package/.agents/workflows/helpers/code-review.md +70 -193
  215. package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +12 -14
  216. package/.agents/workflows/helpers/{single-story-deliver.md → deliver-story.md} +113 -139
  217. package/.agents/workflows/helpers/diagnose.md +10 -10
  218. package/.agents/workflows/helpers/mandrel-sync-config.md +1 -1
  219. package/.agents/workflows/helpers/parallel-tooling.md +1 -1
  220. package/.agents/workflows/helpers/signals.md +16 -16
  221. package/.agents/workflows/helpers/worktree-lifecycle.md +48 -64
  222. package/.agents/workflows/mandrel-update.md +3 -2
  223. package/.agents/workflows/plan.md +112 -145
  224. package/.agents/workflows/qa-assist.md +24 -30
  225. package/.agents/workflows/qa-explore.md +29 -38
  226. package/.agents/workflows/qa-run.md +2 -2
  227. package/README.md +9 -8
  228. package/docs/CHANGELOG.md +46 -0
  229. package/lib/cli/registry.js +95 -0
  230. package/lib/migrations/index.js +6 -5
  231. package/package.json +5 -3
  232. package/.agents/personas/architect.md +0 -113
  233. package/.agents/personas/devops-engineer.md +0 -38
  234. package/.agents/personas/engineer-mobile.md +0 -120
  235. package/.agents/personas/engineer-web.md +0 -111
  236. package/.agents/personas/engineer.md +0 -119
  237. package/.agents/personas/product.md +0 -94
  238. package/.agents/personas/project-manager.md +0 -114
  239. package/.agents/personas/qa-engineer.md +0 -95
  240. package/.agents/personas/refactorer.md +0 -113
  241. package/.agents/personas/security-engineer.md +0 -112
  242. package/.agents/personas/sre.md +0 -86
  243. package/.agents/personas/technical-writer.md +0 -101
  244. package/.agents/personas/ux-designer.md +0 -95
  245. package/.agents/schemas/dispatch-manifest.json +0 -232
  246. package/.agents/schemas/epic-spec.schema.json +0 -153
  247. package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
  248. package/.agents/scripts/dispatcher.js +0 -295
  249. package/.agents/scripts/epic-audit-prepare.js +0 -497
  250. package/.agents/scripts/epic-audit-recheck.js +0 -274
  251. package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
  252. package/.agents/scripts/epic-deliver-preflight.js +0 -462
  253. package/.agents/scripts/epic-deliver-prepare.js +0 -590
  254. package/.agents/scripts/epic-execute-record-wave.js +0 -449
  255. package/.agents/scripts/epic-plan-clarity.js +0 -211
  256. package/.agents/scripts/epic-plan-decompose.js +0 -54
  257. package/.agents/scripts/epic-plan-healthcheck.js +0 -581
  258. package/.agents/scripts/epic-plan-spec.js +0 -64
  259. package/.agents/scripts/epic-reconcile.js +0 -625
  260. package/.agents/scripts/lib/baseline-snapshot.js +0 -979
  261. package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
  262. package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
  263. package/.agents/scripts/lib/config/lifecycle.js +0 -40
  264. package/.agents/scripts/lib/config/preflight.js +0 -58
  265. package/.agents/scripts/lib/config/retro.js +0 -77
  266. package/.agents/scripts/lib/epic-merge-lock.js +0 -322
  267. package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
  268. package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
  269. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -660
  270. package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
  271. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
  272. package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
  273. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
  274. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
  275. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
  276. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
  277. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
  278. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
  279. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
  280. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
  281. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
  282. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
  283. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
  284. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
  285. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
  286. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
  287. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
  288. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -388
  289. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
  290. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
  291. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
  292. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
  293. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
  294. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
  295. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
  296. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
  297. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
  298. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
  299. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
  300. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
  301. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
  302. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
  303. package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
  304. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
  305. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
  306. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
  307. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
  308. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
  309. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
  310. package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
  311. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
  312. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
  313. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -384
  314. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
  315. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
  316. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
  317. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -278
  318. package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
  319. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
  320. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
  321. package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
  322. package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
  323. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
  324. package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
  325. package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
  326. package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
  327. package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
  328. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
  329. package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
  330. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
  331. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
  332. package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
  333. package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
  334. package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
  335. package/.agents/scripts/lib/orchestration/skill-capsule-loader.js +0 -109
  336. package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
  337. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
  338. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
  339. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
  340. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
  341. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
  342. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
  343. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
  344. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
  345. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
  346. package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
  347. package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
  348. package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
  349. package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
  350. package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
  351. package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
  352. package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
  353. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
  354. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
  355. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
  356. package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
  357. package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
  358. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
  359. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
  360. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
  361. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -301
  362. package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
  363. package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
  364. package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
  365. package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
  366. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
  367. package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
  368. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
  369. package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
  370. package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
  371. package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
  372. package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
  373. package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
  374. package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
  375. package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
  376. package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
  377. package/.agents/scripts/lib/push-epic-retry.js +0 -209
  378. package/.agents/scripts/lib/spec/index.js +0 -36
  379. package/.agents/scripts/lib/spec/loader.js +0 -425
  380. package/.agents/scripts/lib/spec/state.js +0 -208
  381. package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
  382. package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
  383. package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
  384. package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
  385. package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
  386. package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
  387. package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
  388. package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
  389. package/.agents/scripts/lib/wave-runner/tick.js +0 -754
  390. package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
  391. package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
  392. package/.agents/scripts/lifecycle-emit.js +0 -510
  393. package/.agents/scripts/plan-critics.js +0 -199
  394. package/.agents/scripts/retro-run.js +0 -218
  395. package/.agents/scripts/standalone-feedback-rollup.js +0 -188
  396. package/.agents/scripts/story-close.js +0 -294
  397. package/.agents/scripts/story-init.js +0 -599
  398. package/.agents/scripts/story-phase.js +0 -369
  399. package/.agents/scripts/wave-tick.js +0 -335
  400. package/.agents/skills/core/baseline-refresh/SKILL.md +0 -181
  401. package/.agents/skills/core/ci-cd-and-automation/SKILL.md +0 -274
  402. package/.agents/skills/core/ci-cd-and-automation/examples.md +0 -211
  403. package/.agents/skills/core/code-simplification/SKILL.md +0 -389
  404. package/.agents/skills/core/context-engineering/SKILL.md +0 -309
  405. package/.agents/skills/core/context-engineering/examples.md +0 -58
  406. package/.agents/skills/core/deprecation-and-migration/SKILL.md +0 -250
  407. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
  408. package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
  409. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
  410. package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
  411. package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
  412. package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
  413. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -413
  414. package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
  415. package/.agents/skills/core/frontend-ui-engineering/SKILL.md +0 -357
  416. package/.agents/skills/core/hydrate-context/SKILL.md +0 -123
  417. package/.agents/skills/core/idea-refinement/examples.md +0 -437
  418. package/.agents/skills/core/idea-refinement/frameworks.md +0 -135
  419. package/.agents/skills/core/incremental-implementation/SKILL.md +0 -271
  420. package/.agents/skills/core/introducing-a-baseline-gate/SKILL.md +0 -213
  421. package/.agents/skills/core/knowledge-transfer/SKILL.md +0 -180
  422. package/.agents/skills/core/mutation-survivor-remediation/SKILL.md +0 -117
  423. package/.agents/skills/core/performance-optimization/SKILL.md +0 -314
  424. package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +0 -277
  425. package/.agents/skills/core/property-based-testing/SKILL.md +0 -148
  426. package/.agents/skills/core/refactoring-discipline/SKILL.md +0 -111
  427. package/.agents/skills/core/shipping-and-launch/SKILL.md +0 -328
  428. package/.agents/skills/core/spec-driven-development/SKILL.md +0 -252
  429. package/.agents/skills/core/test-driven-development/SKILL.md +0 -475
  430. package/.agents/skills/core/using-agent-skills/SKILL.md +0 -232
  431. package/.agents/skills/stack/architecture/monorepo-path-strategist/SKILL.md +0 -31
  432. package/.agents/skills/stack/architecture/structured-output-zod/SKILL.md +0 -51
  433. package/.agents/skills/stack/architecture/subagent-orchestration/SKILL.md +0 -76
  434. package/.agents/skills/stack/backend/cloudflare-hono-architect/SKILL.md +0 -31
  435. package/.agents/skills/stack/backend/cloudflare-hono-architect/examples/route-template.ts +0 -33
  436. package/.agents/skills/stack/backend/cloudflare-queue-manager/SKILL.md +0 -31
  437. package/.agents/skills/stack/backend/cloudflare-workers/SKILL.md +0 -51
  438. package/.agents/skills/stack/backend/highlevel-crm/SKILL.md +0 -54
  439. package/.agents/skills/stack/backend/sqlite-drizzle-expert/SKILL.md +0 -29
  440. package/.agents/skills/stack/backend/sqlite-drizzle-expert/examples/schema-template.ts +0 -30
  441. package/.agents/skills/stack/backend/stripe-integration/SKILL.md +0 -57
  442. package/.agents/skills/stack/backend/stripe-integration/scripts/listen-stripe.sh +0 -9
  443. package/.agents/skills/stack/backend/turso-sqlite/SKILL.md +0 -48
  444. package/.agents/skills/stack/frontend/astro/SKILL.md +0 -62
  445. package/.agents/skills/stack/frontend/astro-react-island-strategist/SKILL.md +0 -30
  446. package/.agents/skills/stack/frontend/expo-react-native-developer/SKILL.md +0 -29
  447. package/.agents/skills/stack/frontend/google-analytics-v4/SKILL.md +0 -50
  448. package/.agents/skills/stack/frontend/tailwind-v4/SKILL.md +0 -58
  449. package/.agents/skills/stack/frontend/ui-accessibility-engineer/SKILL.md +0 -34
  450. package/.agents/skills/stack/qa/audit-accessibility/SKILL.md +0 -51
  451. package/.agents/skills/stack/qa/lighthouse-baseline/SKILL.md +0 -199
  452. package/.agents/skills/stack/security/backend-security-patterns/SKILL.md +0 -68
  453. package/.agents/workflows/helpers/deliver-epic-reference.md +0 -534
  454. package/.agents/workflows/helpers/deliver-epic.md +0 -955
  455. package/.agents/workflows/helpers/deliver-stories.md +0 -440
  456. package/.agents/workflows/helpers/epic-audit.md +0 -189
  457. package/.agents/workflows/helpers/epic-deliver-story.md +0 -427
  458. package/.agents/workflows/helpers/epic-testing.md +0 -125
  459. package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
  460. package/.agents/workflows/helpers/plan-epic.md +0 -351
  461. package/.agents/workflows/helpers/plan-story.md +0 -251
  462. package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
  463. /package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +0 -0
@@ -1,117 +0,0 @@
1
- /**
2
- * epic-plan-state-store — stateless functions for reading and writing the
3
- * `epic-plan-state` structured comment on the Epic issue.
4
- *
5
- * This module is the function-based replacement for the legacy
6
- * `PlanCheckpointer` class that previously lived at
7
- * `./plan-runner/plan-checkpointer.js`. Bodies were lifted verbatim from
8
- * the corresponding `PlanCheckpointer` methods so the structured-comment
9
- * shape is preserved byte-for-byte. Story #2423 (Epic #2307) deleted
10
- * the class file; the class API survives as a tests-only fixture at
11
- * `tests/fixtures/epic-plan-state-store.js`.
12
- *
13
- * Schema (see Tech Spec #351):
14
- *
15
- * ```json
16
- * {
17
- * "version": 1,
18
- * "epicId": 349,
19
- * "startedAt": "...",
20
- * "lastUpdatedAt": "...",
21
- * "spec": { "techSpecPersisted": false, "acceptanceTable": "none", "completedAt": null },
22
- * "decompose": { "ticketCount": null, "completedAt": null },
23
- * "planningRisk": { "overallLevel": "...", "requiresReview": true, "gateDecision": "..." },
24
- * "reviewRouting": { "decision": "review-required|auto-proceed|operator-override-review", "requiresStop": true, "forceReviewApplied": false },
25
- * "manifestCommentId": null
26
- * }
27
- * ```
28
- *
29
- * The checkpoint no longer carries a write-only `phase` field (Story #3909):
30
- * the lifecycle phase is already authoritative on the Epic's `agent::*` labels,
31
- * so the duplicate `phase` telemetry (and its `setPhase` round-trips) was
32
- * deleted. The fields that survive — `spec`, `decompose`, `planningRisk`,
33
- * `reviewRouting`, `manifestCommentId` — are the ones `/plan --resume`
34
- * reads to skip already-completed work.
35
- */
36
-
37
- import { parseFencedJsonComment } from './structured-comment-parser.js';
38
- import { findStructuredComment, upsertStructuredComment } from './ticketing.js';
39
-
40
- export const EPIC_PLAN_STATE_TYPE = 'epic-plan-state';
41
- export const PLAN_CHECKPOINT_SCHEMA_VERSION = 1;
42
-
43
- function assertProvider(provider) {
44
- if (!provider)
45
- throw new TypeError('epic-plan-state-store requires a provider');
46
- }
47
-
48
- function assertEpicId(epicId) {
49
- if (!Number.isInteger(epicId)) {
50
- throw new TypeError('epic-plan-state-store requires a numeric epicId');
51
- }
52
- }
53
-
54
- /**
55
- * Read and parse the checkpoint. Returns null if the comment is missing or
56
- * unparseable (callers treat null as "start fresh").
57
- *
58
- * @param {{ provider: import('../ITicketingProvider.js').ITicketingProvider, epicId: number }} opts
59
- * @returns {Promise<object | null>}
60
- */
61
- export async function read({ provider, epicId } = {}) {
62
- assertProvider(provider);
63
- assertEpicId(epicId);
64
- const comment = await findStructuredComment(
65
- provider,
66
- epicId,
67
- EPIC_PLAN_STATE_TYPE,
68
- );
69
- return parseFencedJsonComment(comment);
70
- }
71
-
72
- /**
73
- * Overwrite the checkpoint with the supplied merged state.
74
- *
75
- * @param {{ provider: import('../ITicketingProvider.js').ITicketingProvider, epicId: number, state: object }} opts
76
- */
77
- export async function write({ provider, epicId, state } = {}) {
78
- assertProvider(provider);
79
- assertEpicId(epicId);
80
- const payload = {
81
- version: PLAN_CHECKPOINT_SCHEMA_VERSION,
82
- ...state,
83
- lastUpdatedAt: new Date().toISOString(),
84
- };
85
- const body = `\`\`\`json\n${JSON.stringify(payload, null, 2)}\n\`\`\``;
86
- await upsertStructuredComment(provider, epicId, EPIC_PLAN_STATE_TYPE, body);
87
- return payload;
88
- }
89
-
90
- /**
91
- * Initialize the checkpoint. Idempotent — returns the existing state if one
92
- * is present, otherwise writes a fresh skeleton. Overrides from `seed` are
93
- * merged into a freshly-written skeleton; an already-present checkpoint is
94
- * returned unchanged.
95
- *
96
- * @param {{ provider: import('../ITicketingProvider.js').ITicketingProvider, epicId: number, seed?: object }} opts
97
- * @returns {Promise<object>}
98
- */
99
- export async function initialize({ provider, epicId, seed = {} } = {}) {
100
- assertProvider(provider);
101
- assertEpicId(epicId);
102
- const existing = await read({ provider, epicId });
103
- if (existing) return existing;
104
- const now = new Date().toISOString();
105
- const skeleton = {
106
- epicId,
107
- startedAt: now,
108
- spec: {
109
- techSpecPersisted: false,
110
- acceptanceTable: 'none',
111
- completedAt: null,
112
- },
113
- decompose: { ticketCount: null, completedAt: null },
114
- manifestCommentId: null,
115
- };
116
- return write({ provider, epicId, state: { ...skeleton, ...seed } });
117
- }
@@ -1,388 +0,0 @@
1
- /**
2
- * epic-run-state-store — stateless functions for reading and writing the
3
- * `epic-run-state` structured comment used by `/deliver`.
4
- *
5
- * Story #4155 (Epic #4151) — the Epic `/deliver` runtime cut over from
6
- * the wave-batch scheduler to the continuous ready-set core
7
- * (`lib/wave-runner/ready-set.js`). The checkpoint shrank with it: it no
8
- * longer carries `currentWave`, `plan[][]`, `totalWaves`, or the
9
- * per-wave `waves[]` aggregation. The durable run state is now a flat
10
- * **per-Story status map** (`stories: { [storyId]: { status, title?,
11
- * blockerCommentId? } }`) plus the run-level `concurrencyCap` (the
12
- * GLOBAL in-flight cap the ready-set selector honours), `phase`,
13
- * `startedAt`, and `manualInterventions[]`. There is no resume-pointer
14
- * to reconcile — the ready-set core re-derives adjacency and readiness
15
- * from live Story bodies/labels on every tick, so the checkpoint only
16
- * records terminal Story outcomes (for the auto-merge predicate, branch
17
- * cleanup, and the operator rollup) and the run-level knobs.
18
- *
19
- * This module is the function-based replacement for the legacy
20
- * `Checkpointer` class that previously lived at
21
- * `./epic-runner/checkpointer.js`. Story #2423 (Epic #2307) deleted the
22
- * class file; the class API survives as a tests-only fixture at
23
- * `tests/fixtures/epic-run-state-store.js`.
24
- *
25
- * The comment is identified by a stable HTML marker so it can be overwritten
26
- * idempotently across orchestrator restarts. The body is a fenced JSON block.
27
- */
28
-
29
- import { assertValidDeliverPhase } from './epic-runner/deliver-phases.js';
30
- import { parseFencedJsonComment } from './structured-comment-parser.js';
31
- import { findStructuredComment, upsertStructuredComment } from './ticketing.js';
32
-
33
- export const EPIC_RUN_STATE_TYPE = 'epic-run-state';
34
- export const CHECKPOINT_SCHEMA_VERSION = 2;
35
-
36
- /** Terminal / in-progress per-Story statuses persisted on the checkpoint. */
37
- export const STORY_STATUSES = Object.freeze([
38
- 'pending',
39
- 'done',
40
- 'blocked',
41
- 'failed',
42
- ]);
43
-
44
- // Re-export the phase enum + index helper so downstream importers continue
45
- // to use this module as a single import target.
46
- export {
47
- DELIVER_PHASES,
48
- phaseIndex,
49
- } from './epic-runner/deliver-phases.js';
50
-
51
- function assertProvider(provider) {
52
- if (!provider)
53
- throw new TypeError('epic-run-state-store requires a provider');
54
- }
55
-
56
- function assertEpicId(epicId) {
57
- if (!Number.isInteger(epicId)) {
58
- throw new TypeError('epic-run-state-store requires a numeric epicId');
59
- }
60
- }
61
-
62
- /**
63
- * Normalize an inbound Story id (accepts the ticket `id` shape, the raw
64
- * GitHub `number` shape, and a bare integer) to a positive integer, or
65
- * `null` when it is absent / non-positive / non-integer.
66
- *
67
- * @param {object|number|string} entry
68
- * @returns {number|null}
69
- */
70
- function storyIdOf(entry) {
71
- if (typeof entry === 'number') {
72
- return Number.isInteger(entry) && entry > 0 ? entry : null;
73
- }
74
- if (!entry || typeof entry !== 'object') {
75
- const n = Number(entry);
76
- return Number.isInteger(n) && n > 0 ? n : null;
77
- }
78
- const raw = entry.id ?? entry.storyId ?? entry.number;
79
- const id = Number(raw);
80
- return Number.isInteger(id) && id > 0 ? id : null;
81
- }
82
-
83
- /**
84
- * Build the initial per-Story status map from a list of Story records (or
85
- * ids). Every Story seeds at `status: 'pending'`; an optional `title` is
86
- * carried through when the record supplies one so the operator rollup and
87
- * branch-cleanup surfaces have a label without a second fetch. Keys are the
88
- * positive-integer Story ids as strings (JSON object keys are strings);
89
- * shapeless / non-positive entries are dropped.
90
- *
91
- * Pure helper — exported for unit tests.
92
- *
93
- * @param {Array<object|number>} stories
94
- * @returns {Record<string, { status: string, title?: string }>}
95
- */
96
- export function buildStoryStatusMap(stories) {
97
- const out = {};
98
- for (const entry of Array.isArray(stories) ? stories : []) {
99
- const id = storyIdOf(entry);
100
- if (id === null) continue;
101
- const record = { status: 'pending' };
102
- const title =
103
- entry && typeof entry === 'object' && typeof entry.title === 'string'
104
- ? entry.title
105
- : undefined;
106
- if (title) record.title = title;
107
- out[String(id)] = record;
108
- }
109
- return out;
110
- }
111
-
112
- /**
113
- * Read and parse the checkpoint. Returns null if the comment is missing or
114
- * unparseable (callers treat null as "start fresh").
115
- *
116
- * @param {{ provider: import('../ITicketingProvider.js').ITicketingProvider, epicId: number }} opts
117
- * @returns {Promise<object | null>}
118
- */
119
- export async function read({ provider, epicId } = {}) {
120
- assertProvider(provider);
121
- assertEpicId(epicId);
122
- const comment = await findStructuredComment(
123
- provider,
124
- epicId,
125
- EPIC_RUN_STATE_TYPE,
126
- );
127
- return parseFencedJsonComment(comment);
128
- }
129
-
130
- /**
131
- * Overwrite the checkpoint with `state`. Idempotent — callers may invoke
132
- * freely per tick; the marker-scoped upsert deletes the prior comment.
133
- *
134
- * @param {{ provider: import('../ITicketingProvider.js').ITicketingProvider, epicId: number, state: object }} opts
135
- */
136
- export async function write({ provider, epicId, state } = {}) {
137
- assertProvider(provider);
138
- assertEpicId(epicId);
139
- const payload = {
140
- version: CHECKPOINT_SCHEMA_VERSION,
141
- ...state,
142
- lastUpdatedAt: new Date().toISOString(),
143
- };
144
- const body = `\`\`\`json\n${JSON.stringify(payload, null, 2)}\n\`\`\``;
145
- await upsertStructuredComment(provider, epicId, EPIC_RUN_STATE_TYPE, body);
146
- return payload;
147
- }
148
-
149
- /**
150
- * Initial checkpoint for a brand-new run. Idempotent against re-dispatch:
151
- * when an existing checkpoint is found and the persisted `concurrencyCap`
152
- * matches the incoming value, the existing state is returned verbatim (no
153
- * rewrite) so a re-prepare preserves `startedAt`, prior Story statuses, and
154
- * `manualInterventions`. When the cap differs (an operator re-tuned the
155
- * global in-flight cap) it is refreshed in place; the Story status map is
156
- * **merged** so any Story that already reached a terminal status keeps it
157
- * while newly-discovered Stories are seeded at `pending`. Prepare owns the
158
- * Story set (it overwrites it on every run) but never clobbers recorded
159
- * progress.
160
- *
161
- * @param {{
162
- * provider: import('../ITicketingProvider.js').ITicketingProvider,
163
- * epicId: number,
164
- * storyIds: Array<object|number>,
165
- * concurrencyCap: number,
166
- * }} opts
167
- * `concurrencyCap` is the GLOBAL in-flight cap the ready-set selector
168
- * honours (`selectReadySet({ globalCap })`).
169
- */
170
- export async function initialize({
171
- provider,
172
- epicId,
173
- storyIds,
174
- concurrencyCap,
175
- } = {}) {
176
- assertProvider(provider);
177
- assertEpicId(epicId);
178
- const seededStories = buildStoryStatusMap(storyIds);
179
- const existing = await read({ provider, epicId });
180
- if (existing) {
181
- const mergedStories = mergeStoryStatuses(existing.stories, seededStories);
182
- if (
183
- existing.concurrencyCap === concurrencyCap &&
184
- storyMapsEqual(existing.stories, mergedStories)
185
- ) {
186
- return existing;
187
- }
188
- return write({
189
- provider,
190
- epicId,
191
- state: { ...existing, concurrencyCap, stories: mergedStories },
192
- });
193
- }
194
- return write({
195
- provider,
196
- epicId,
197
- state: {
198
- epicId,
199
- startedAt: new Date().toISOString(),
200
- concurrencyCap,
201
- phase: 'prepare',
202
- stories: seededStories,
203
- manualInterventions: [],
204
- },
205
- });
206
- }
207
-
208
- /**
209
- * Merge a freshly-seeded Story status map onto a persisted one. Every Story
210
- * present in either map appears in the result; when a Story exists in the
211
- * prior map its recorded status / blockerCommentId win (recorded progress is
212
- * never lost), while its `title` is refreshed from the incoming seed when the
213
- * seed supplies one. Stories present only in the incoming seed are added at
214
- * their seeded (`pending`) status. Pure — exported for unit tests.
215
- *
216
- * @param {Record<string, object>|undefined} prior
217
- * @param {Record<string, object>} incoming
218
- * @returns {Record<string, object>}
219
- */
220
- export function mergeStoryStatuses(prior, incoming) {
221
- const priorMap = prior && typeof prior === 'object' ? prior : {};
222
- const seedMap = incoming && typeof incoming === 'object' ? incoming : {};
223
- const out = {};
224
- for (const key of new Set([
225
- ...Object.keys(priorMap),
226
- ...Object.keys(seedMap),
227
- ])) {
228
- const priorEntry = priorMap[key];
229
- const seedEntry = seedMap[key];
230
- if (priorEntry && typeof priorEntry === 'object') {
231
- const merged = { ...priorEntry };
232
- if (seedEntry && typeof seedEntry.title === 'string') {
233
- merged.title = seedEntry.title;
234
- }
235
- out[key] = merged;
236
- } else {
237
- out[key] = seedEntry;
238
- }
239
- }
240
- return out;
241
- }
242
-
243
- /**
244
- * Structural equality on two Story status maps — same key set and, per key,
245
- * the same `status`, `title`, and `blockerCommentId`. Used by `initialize`
246
- * to decide whether an idempotent re-prepare needs a rewrite. Pure.
247
- *
248
- * @param {Record<string, object>|undefined} a
249
- * @param {Record<string, object>|undefined} b
250
- * @returns {boolean}
251
- */
252
- function storyMapsEqual(a, b) {
253
- const left = a && typeof a === 'object' ? a : {};
254
- const right = b && typeof b === 'object' ? b : {};
255
- const keys = Object.keys(left);
256
- if (keys.length !== Object.keys(right).length) return false;
257
- for (const key of keys) {
258
- const l = left[key] ?? {};
259
- const r = right[key];
260
- if (!r) return false;
261
- if (
262
- l.status !== r.status ||
263
- l.title !== r.title ||
264
- l.blockerCommentId !== r.blockerCommentId
265
- ) {
266
- return false;
267
- }
268
- }
269
- return true;
270
- }
271
-
272
- /**
273
- * Record a per-Story terminal (or in-progress) status on the checkpoint.
274
- * Reads the current state first, splices the single Story's record into the
275
- * `stories` map, and re-writes. Other Stories and all run-level fields are
276
- * preserved verbatim. Tolerant of a legacy/absent `stories` map (treated as
277
- * empty) so a checkpoint that predates a field is upgraded in place.
278
- *
279
- * @param {{
280
- * provider: import('../ITicketingProvider.js').ITicketingProvider,
281
- * epicId: number,
282
- * storyId: number,
283
- * status: string,
284
- * title?: string,
285
- * blockerCommentId?: string|number|null,
286
- * }} opts
287
- * @returns {Promise<object>} the persisted state
288
- */
289
- export async function recordStoryStatus({
290
- provider,
291
- epicId,
292
- storyId,
293
- status,
294
- title,
295
- blockerCommentId,
296
- } = {}) {
297
- assertProvider(provider);
298
- assertEpicId(epicId);
299
- const id = storyIdOf(storyId);
300
- if (id === null) {
301
- throw new TypeError(
302
- 'recordStoryStatus: storyId must be a positive integer',
303
- );
304
- }
305
- if (!STORY_STATUSES.includes(status)) {
306
- throw new RangeError(
307
- `recordStoryStatus: status "${status}" must be one of: ${STORY_STATUSES.join(', ')}`,
308
- );
309
- }
310
- const existing = (await read({ provider, epicId })) ?? {};
311
- const stories =
312
- existing.stories && typeof existing.stories === 'object'
313
- ? { ...existing.stories }
314
- : {};
315
- const prior = stories[String(id)] ?? {};
316
- const record = { ...prior, status };
317
- if (typeof title === 'string' && title) record.title = title;
318
- if (status === 'blocked' && blockerCommentId != null) {
319
- record.blockerCommentId = String(blockerCommentId);
320
- }
321
- stories[String(id)] = record;
322
- return write({
323
- provider,
324
- epicId,
325
- state: { ...existing, stories },
326
- });
327
- }
328
-
329
- /**
330
- * Append a manual-intervention record to the checkpoint. Out-of-band
331
- * recovery steps the host LLM performs during a delivery — `AskUserQuestion`
332
- * calls, `git restore`/`git reset` against the working tree, manual `--no-ff`
333
- * recovery merges, story-close `--skipValidation` overrides — disqualify the
334
- * Epic from auto-merge. The auto-merge predicate reads this array and only
335
- * fires when it is empty.
336
- *
337
- * @param {{ provider: import('../ITicketingProvider.js').ITicketingProvider, epicId: number, entry: { reason: string, source?: string, ts?: string } }} opts
338
- * @returns {Promise<object>} the persisted state
339
- */
340
- export async function appendIntervention({ provider, epicId, entry } = {}) {
341
- assertProvider(provider);
342
- assertEpicId(epicId);
343
- if (!entry || typeof entry.reason !== 'string' || entry.reason.length === 0) {
344
- throw new TypeError('appendIntervention: { reason: string } is required.');
345
- }
346
- const existing = (await read({ provider, epicId })) ?? {};
347
- const list = Array.isArray(existing.manualInterventions)
348
- ? existing.manualInterventions
349
- : [];
350
- const record = {
351
- reason: entry.reason,
352
- source: typeof entry.source === 'string' ? entry.source : 'host-llm',
353
- ts: typeof entry.ts === 'string' ? entry.ts : new Date().toISOString(),
354
- };
355
- return write({
356
- provider,
357
- epicId,
358
- state: {
359
- ...existing,
360
- manualInterventions: [...list, record],
361
- },
362
- });
363
- }
364
-
365
- /**
366
- * Advance the checkpoint's `phase` field to the next `/deliver`
367
- * phase. Reads the current state first so the caller does not need to
368
- * keep an in-memory copy. Other state fields are preserved verbatim.
369
- *
370
- * Story #1155 / Epic #1142 — phase-granular resume. The runner writes
371
- * the **next phase to run** here, not the phase that just finished, so
372
- * a resume can match `phase === 'code-review'` to mean "Phase D is the
373
- * next thing to do."
374
- *
375
- * @param {{ provider: import('../ITicketingProvider.js').ITicketingProvider, epicId: number, nextPhase: string }} opts
376
- * nextPhase - One of `DELIVER_PHASES` or `'done'`.
377
- */
378
- export async function setPhase({ provider, epicId, nextPhase } = {}) {
379
- assertProvider(provider);
380
- assertEpicId(epicId);
381
- assertValidDeliverPhase(nextPhase);
382
- const existing = (await read({ provider, epicId })) ?? {};
383
- return write({
384
- provider,
385
- epicId,
386
- state: { ...existing, phase: nextPhase },
387
- });
388
- }
@@ -1,186 +0,0 @@
1
- /**
2
- * Cross-Story conflict-finding gate for `epic-deliver-prepare.js`.
3
- *
4
- * Story #2297 — when the bounded `/plan` flow emitted concurrency
5
- * findings (Story #2296's validator pass), the operator may have shipped
6
- * them through to `/deliver` without resolving the underlying
7
- * `depends_on` gaps. This gate runs at Phase 1 of `/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 `/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
- }