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,359 +0,0 @@
1
- /**
2
- * amend.js — the `--amend` change-request delta path of the collapsed
3
- * persist surface (Epic #4474 PR4, design §2 mode matrix, amend row).
4
- *
5
- * An amend run receives the full ticket set with every ticket carrying an
6
- * `op` field:
7
- *
8
- * - `add` — a new Story; created fresh.
9
- * - `modify` — an existing Story whose contract changed; closed and
10
- * recreated (close-and-recreate is scoped to modify/close
11
- * slugs ONLY — never the whole tree, which is `--force`'s
12
- * semantics).
13
- * - `keep` — an existing Story left byte-untouched; it participates in
14
- * the merged-set DAG validation but no provider mutation
15
- * ever targets it.
16
- * - `close` — an existing Story dropped from the plan; closed.
17
- *
18
- * The DAG (and the full ticket validator) runs over the MERGED set —
19
- * keeps + adds + modifies, closes excluded — so a cycle introduced by an
20
- * add that depends on a kept Story that depends on a modify is caught
21
- * before any GitHub call, and a dependency pointing at a closed slug fails
22
- * the unknown-slug check.
23
- *
24
- * Close ops are destructive, so they are gated behind the same explicit
25
- * confirmation contract as `epic-reconcile.js`: without `--explicit-delete`
26
- * the run stops BEFORE any mutation, prints the dry-run op diff, and exits
27
- * 2 ({@link AmendExplicitCloseError} carries the rendered diff; the CLI
28
- * maps it onto the exit code). Non-interactive callers pass the flag.
29
- *
30
- * Slug → issue resolution: an explicit `id` on the ticket (the authoring
31
- * envelope's open-children listing carries issue numbers) wins; otherwise
32
- * the reconciler state ledger (`.agents/epics/<id>.state.json`) resolves
33
- * the slug. A modify/keep/close slug that resolves nowhere is a hard error
34
- * — the amend never guesses which Story it is about to close.
35
- *
36
- * @module lib/orchestration/plan-persist/amend
37
- */
38
-
39
- import { Logger } from '../../Logger.js';
40
-
41
- /** Valid `op` values on an amend ticket. */
42
- const AMEND_OPS = Object.freeze(['add', 'modify', 'keep', 'close']);
43
-
44
- /**
45
- * Error carrying the rendered dry-run diff for the exit-2 confirmation
46
- * path (mirrors `epic-reconcile.js` EXIT_CODES.EXPLICIT_DELETE_REQUIRED).
47
- */
48
- export class AmendExplicitCloseError extends Error {
49
- /**
50
- * @param {string} message
51
- * @param {{ diff: string }} detail
52
- */
53
- constructor(message, { diff }) {
54
- super(message);
55
- this.name = 'AmendExplicitCloseError';
56
- this.code = 'PLAN_AMEND_EXPLICIT_DELETE_REQUIRED';
57
- this.diff = diff;
58
- }
59
- }
60
-
61
- /**
62
- * Partition an amend ticket set by `op`, validating the op vocabulary and
63
- * slug uniqueness. Every ticket MUST carry an op — a missing op on one
64
- * ticket of an amend payload is an authoring defect, not a default.
65
- *
66
- * @param {Array<{ slug?: string, op?: string }>} tickets
67
- * @returns {{ add: object[], modify: object[], keep: object[], close: object[] }}
68
- */
69
- export function partitionAmendTickets(tickets) {
70
- const partition = { add: [], modify: [], keep: [], close: [] };
71
- const seen = new Set();
72
- for (const ticket of tickets) {
73
- const slug = ticket?.slug;
74
- if (typeof slug !== 'string' || slug.length === 0) {
75
- throw new Error(
76
- '[plan-persist] amend ticket without a slug — every amend ticket ' +
77
- 'must carry both slug and op.',
78
- );
79
- }
80
- if (seen.has(slug)) {
81
- throw new Error(
82
- `[plan-persist] duplicate slug "${slug}" in the amend payload.`,
83
- );
84
- }
85
- seen.add(slug);
86
- const op = ticket?.op;
87
- if (!AMEND_OPS.includes(op)) {
88
- throw new Error(
89
- `[plan-persist] amend ticket "${slug}" carries invalid op ` +
90
- `"${op}" — expected one of ${AMEND_OPS.join(', ')}.`,
91
- );
92
- }
93
- partition[op].push(ticket);
94
- }
95
- return partition;
96
- }
97
-
98
- /**
99
- * Project the MERGED ticket set for validation and spec rendering:
100
- * keeps + adds + modifies in original authoring order, closes excluded,
101
- * with the amend-only `op`/`id` carrier fields stripped so the ticket
102
- * validator and `renderSpec` see the exact fan-out ticket shape.
103
- *
104
- * @param {Array<{ op?: string }>} tickets the full amend payload
105
- * @returns {object[]} merged set, op/id stripped
106
- */
107
- export function buildMergedTicketSet(tickets) {
108
- return tickets
109
- .filter((t) => t?.op !== 'close')
110
- .map(({ op: _op, id: _id, ...rest }) => rest);
111
- }
112
-
113
- /**
114
- * Resolve every modify/keep/close slug to its live issue number and
115
- * hard-error on any ambiguity (the "closing the wrong stories" risk):
116
- *
117
- * - modify/keep/close must resolve via explicit `id` or the state
118
- * ledger mapping — no resolution is a hard error;
119
- * - an add slug must NOT already resolve to an issue (a collision means
120
- * the author meant modify, or picked a stale slug);
121
- * - resolved modify/close targets are fetched and must exist; a target
122
- * already closed on GitHub is surfaced (skipped close, not an error —
123
- * re-running an interrupted amend must stay safe).
124
- *
125
- * @param {{
126
- * partition: ReturnType<typeof partitionAmendTickets>,
127
- * stateMapping: Record<string, { issueNumber?: number }>,
128
- * provider: { getTicket: (id: number) => Promise<object|null> },
129
- * }} args
130
- * @returns {Promise<{
131
- * modify: Array<{ ticket: object, issueNumber: number, alreadyClosed: boolean }>,
132
- * keep: Array<{ ticket: object, issueNumber: number }>,
133
- * close: Array<{ ticket: object, issueNumber: number, alreadyClosed: boolean }>,
134
- * }>}
135
- */
136
- export async function resolveAmendTargets({
137
- partition,
138
- stateMapping,
139
- provider,
140
- }) {
141
- const mapping = stateMapping ?? {};
142
- const resolveSlug = (ticket) => {
143
- if (Number.isInteger(ticket.id)) return ticket.id;
144
- const entry = mapping[ticket.slug];
145
- if (Number.isInteger(entry?.issueNumber)) return entry.issueNumber;
146
- return null;
147
- };
148
-
149
- for (const ticket of partition.add) {
150
- const collision = resolveSlug(ticket);
151
- if (collision !== null) {
152
- throw new Error(
153
- `[plan-persist] amend op "add" for slug "${ticket.slug}" collides ` +
154
- `with existing issue #${collision} — use op "modify" to replace ` +
155
- 'it, or pick a fresh slug.',
156
- );
157
- }
158
- }
159
-
160
- const resolveExisting = async (ticket, op) => {
161
- const issueNumber = resolveSlug(ticket);
162
- if (issueNumber === null) {
163
- throw new Error(
164
- `[plan-persist] amend op "${op}" for slug "${ticket.slug}" resolves ` +
165
- 'to no existing issue (no `id` on the ticket, no state-ledger ' +
166
- 'mapping). Refusing to guess — carry the issue number as `id`.',
167
- );
168
- }
169
- const issue = await provider.getTicket(issueNumber);
170
- if (!issue) {
171
- throw new Error(
172
- `[plan-persist] amend op "${op}" for slug "${ticket.slug}" points ` +
173
- `at issue #${issueNumber}, which does not exist.`,
174
- );
175
- }
176
- return { ticket, issueNumber, alreadyClosed: issue.state === 'closed' };
177
- };
178
-
179
- const modify = [];
180
- for (const t of partition.modify)
181
- modify.push(await resolveExisting(t, 'modify'));
182
- const close = [];
183
- for (const t of partition.close)
184
- close.push(await resolveExisting(t, 'close'));
185
- const keep = [];
186
- for (const t of partition.keep) {
187
- const { ticket, issueNumber } = await resolveExisting(t, 'keep');
188
- keep.push({ ticket, issueNumber });
189
- }
190
- return { modify, keep, close };
191
- }
192
-
193
- /**
194
- * Render the operator-facing dry-run diff of the amend plan — printed on
195
- * the exit-2 confirmation path and logged before an `--explicit-delete`
196
- * apply so the destructive set is always visible.
197
- *
198
- * @param {{
199
- * epicId: number,
200
- * targets: Awaited<ReturnType<typeof resolveAmendTargets>>,
201
- * adds: Array<{ slug: string, title?: string }>,
202
- * }} args
203
- * @returns {string}
204
- */
205
- export function renderAmendPlanDiff({ epicId, targets, adds }) {
206
- const rows = [
207
- ...targets.close.map(
208
- (t) =>
209
- `| close | \`${t.ticket.slug}\` | #${t.issueNumber} | closed${t.alreadyClosed ? ' (already closed)' : ''} |`,
210
- ),
211
- ...targets.modify.map(
212
- (t) =>
213
- `| modify | \`${t.ticket.slug}\` | #${t.issueNumber} | closed + recreated |`,
214
- ),
215
- ...adds.map((t) => `| add | \`${t.slug}\` | — | created |`),
216
- ...targets.keep.map(
217
- (t) => `| keep | \`${t.ticket.slug}\` | #${t.issueNumber} | untouched |`,
218
- ),
219
- ];
220
- return [
221
- `Amend plan for Epic #${epicId} (dry-run):`,
222
- '',
223
- '| Op | Slug | Issue | Effect |',
224
- '| --- | --- | --- | --- |',
225
- ...rows,
226
- ].join('\n');
227
- }
228
-
229
- /**
230
- * Enforce the close-op confirmation gate: when the amend plan carries
231
- * close ops (including the close half of modify) affecting live issues and
232
- * `--explicit-delete` was not passed, throw {@link AmendExplicitCloseError}
233
- * with the rendered diff — BEFORE any mutation. Mirrors the
234
- * `epic-reconcile.js` exit-2 contract.
235
- *
236
- * @param {{
237
- * epicId: number,
238
- * targets: Awaited<ReturnType<typeof resolveAmendTargets>>,
239
- * adds: object[],
240
- * explicitDelete: boolean,
241
- * }} args
242
- */
243
- export function enforceAmendCloseGate({
244
- epicId,
245
- targets,
246
- adds,
247
- explicitDelete,
248
- }) {
249
- const liveCloses = [
250
- ...targets.close.filter((t) => !t.alreadyClosed),
251
- ...targets.modify.filter((t) => !t.alreadyClosed),
252
- ];
253
- if (liveCloses.length === 0 || explicitDelete) return;
254
- const diff = renderAmendPlanDiff({ epicId, targets, adds });
255
- const named = liveCloses
256
- .map((t) => `#${t.issueNumber} (\`${t.ticket.slug}\`)`)
257
- .join(', ');
258
- throw new AmendExplicitCloseError(
259
- `[plan-persist] amend plan would close ${liveCloses.length} live ` +
260
- `issue(s): ${named}. Review the dry-run diff and re-run with ` +
261
- '--explicit-delete to apply.',
262
- { diff },
263
- );
264
- }
265
-
266
- /**
267
- * Apply the amend ops against the provider, in destructive-last order per
268
- * slug class: closes first (their disappearance is what the operator
269
- * confirmed), then modify (close old + create new), then adds. Keeps are
270
- * never touched by construction — no code path here receives them.
271
- *
272
- * @param {{
273
- * epicId: number,
274
- * provider: {
275
- * updateTicket: (id: number, patch: object) => Promise<object>,
276
- * createTicket: (parentId: number, payload: object) => Promise<{ id: number }>,
277
- * },
278
- * targets: Awaited<ReturnType<typeof resolveAmendTargets>>,
279
- * validatedBySlug: Map<string, { slug: string, title: string, body?: string, labels?: string[] }>,
280
- * }} args
281
- * @returns {Promise<{
282
- * closed: Array<{ slug: string, issueNumber: number }>,
283
- * recreated: Array<{ slug: string, oldIssueNumber: number, issueNumber: number }>,
284
- * created: Array<{ slug: string, issueNumber: number }>,
285
- * mapping: Record<string, { entity: 'story', issueNumber: number }>,
286
- * closedSlugs: string[],
287
- * }>}
288
- */
289
- export async function applyAmendOps({
290
- epicId,
291
- provider,
292
- targets,
293
- validatedBySlug,
294
- }) {
295
- const closed = [];
296
- const recreated = [];
297
- const created = [];
298
- const mapping = {};
299
- const closedSlugs = [];
300
-
301
- const createFromValidated = async (slug) => {
302
- const validated = validatedBySlug.get(slug);
303
- if (!validated) {
304
- throw new Error(
305
- `[plan-persist] amend apply: no validated ticket for slug "${slug}".`,
306
- );
307
- }
308
- const result = await provider.createTicket(epicId, {
309
- title: validated.title,
310
- body: validated.body ?? '',
311
- labels: validated.labels ?? [],
312
- });
313
- return result.id;
314
- };
315
-
316
- for (const target of targets.close) {
317
- if (!target.alreadyClosed) {
318
- await provider.updateTicket(target.issueNumber, { state: 'closed' });
319
- } else {
320
- Logger.info(
321
- `[plan-persist] amend close: #${target.issueNumber} ` +
322
- `(${target.ticket.slug}) already closed — skipping.`,
323
- );
324
- }
325
- closed.push({ slug: target.ticket.slug, issueNumber: target.issueNumber });
326
- closedSlugs.push(target.ticket.slug);
327
- }
328
-
329
- for (const target of targets.modify) {
330
- if (!target.alreadyClosed) {
331
- await provider.updateTicket(target.issueNumber, { state: 'closed' });
332
- }
333
- const newId = await createFromValidated(target.ticket.slug);
334
- recreated.push({
335
- slug: target.ticket.slug,
336
- oldIssueNumber: target.issueNumber,
337
- issueNumber: newId,
338
- });
339
- mapping[target.ticket.slug] = { entity: 'story', issueNumber: newId };
340
- }
341
-
342
- for (const [slug] of validatedBySlug) {
343
- const isModify = targets.modify.some((t) => t.ticket.slug === slug);
344
- const isKeep = targets.keep.some((t) => t.ticket.slug === slug);
345
- if (isModify || isKeep) continue;
346
- const newId = await createFromValidated(slug);
347
- created.push({ slug, issueNumber: newId });
348
- mapping[slug] = { entity: 'story', issueNumber: newId };
349
- }
350
-
351
- for (const target of targets.keep) {
352
- mapping[target.ticket.slug] = {
353
- entity: 'story',
354
- issueNumber: target.issueNumber,
355
- };
356
- }
357
-
358
- return { closed, recreated, created, mapping, closedSlugs };
359
- }
@@ -1,127 +0,0 @@
1
- /**
2
- * delivery-mode.js — delivery-shape mode resolution for the collapsed
3
- * persist surface (Epic #4474 PR4, design §2 mode matrix).
4
- *
5
- * The risk verdict's optional `deliveryShape` field ("fan-out" | "single",
6
- * absent → fan-out so every existing verdict stays valid) selects between
7
- * the three persist modes:
8
- *
9
- * - `fan-out` — the full mode: ticket validator + DAG + budget gates,
10
- * Story-tree creation via the structural reconciler.
11
- * - `single` — the spec-only single-delivery mode: NO tickets are
12
- * authored, the ticket validator + DAG are skipped (fenced by
13
- * construction — {@link resolveDeliveryMode} hard-refuses the
14
- * combination of `deliveryShape: "single"` with a tickets payload, so
15
- * the skip branch is unreachable when tickets are present), and the
16
- * persist applies the `delivery::single` routing marker instead of a
17
- * Story tree. Inert until #4475 lands the deliver-side reader.
18
- * - `amend` — the change-request delta path (`--amend`): tickets carry
19
- * `op: add|modify|keep|close` and the persist maps the ops onto the
20
- * existing Story tree (see `plan-persist/amend.js`).
21
- *
22
- * @module lib/orchestration/plan-persist/delivery-mode
23
- */
24
-
25
- import { parseDeliverySlicingTable } from '../consolidation-precondition.js';
26
-
27
- /** Canonical delivery-shape values the risk-verdict schema admits. */
28
- const DELIVERY_SHAPES = Object.freeze(['fan-out', 'single']);
29
-
30
- /**
31
- * Mode-coherence hard error (design §1 step 3 item 3, extended for PR4).
32
- *
33
- * Resolves the persist mode from the risk verdict's `deliveryShape` (absent
34
- * → `fan-out`), the tickets payload, and the `--amend` flag — and refuses
35
- * every incoherent combination loudly instead of silently coercing:
36
- *
37
- * - unknown `deliveryShape` values;
38
- * - `deliveryShape: "single"` WITH a tickets payload (the DAG-skip
39
- * leakage risk — the single mode's validator/DAG skip is only sound
40
- * when there are no tickets to validate);
41
- * - fan-out without a non-empty tickets array;
42
- * - `--amend` combined with `deliveryShape: "single"` (the delta path is
43
- * fan-out-shaped by definition — a single-delivery re-plan is a
44
- * `--force` re-persist);
45
- * - `--amend` without tickets (the delta IS the tickets-with-ops
46
- * payload);
47
- * - `op` fields present without `--amend` (a full persist must never
48
- * silently reinterpret an amend delta as a fresh tree).
49
- *
50
- * @param {{ deliveryShape?: string }} riskVerdict schema-validated verdict
51
- * @param {unknown} tickets parsed tickets payload (null when no file)
52
- * @param {{ amend?: boolean }} [opts]
53
- * @returns {'fan-out'|'single'|'amend'} the resolved persist mode
54
- */
55
- export function resolveDeliveryMode(riskVerdict, tickets, opts = {}) {
56
- const { amend = false } = opts;
57
- const shape = riskVerdict?.deliveryShape ?? 'fan-out';
58
- if (!DELIVERY_SHAPES.includes(shape)) {
59
- throw new Error(
60
- `[plan-persist] unknown deliveryShape "${shape}" — expected one of ` +
61
- `${DELIVERY_SHAPES.join(', ')} (or omit the field for fan-out).`,
62
- );
63
- }
64
- const hasTickets = Array.isArray(tickets) && tickets.length > 0;
65
-
66
- if (amend) {
67
- if (shape === 'single') {
68
- throw new Error(
69
- '[plan-persist] --amend is incoherent with deliveryShape "single" — ' +
70
- 'the amend delta maps ops onto an existing Story tree, and a ' +
71
- 'single-delivery plan has none. Re-author the verdict as fan-out, ' +
72
- 'or re-persist the single plan with --force.',
73
- );
74
- }
75
- if (!hasTickets) {
76
- throw new Error(
77
- '[plan-persist] --amend requires a tickets payload carrying ' +
78
- '`op: add|modify|keep|close` on every ticket — the delta IS the ' +
79
- 'tickets file (--tickets <file>).',
80
- );
81
- }
82
- return 'amend';
83
- }
84
-
85
- if (shape === 'single') {
86
- if (hasTickets) {
87
- throw new Error(
88
- '[plan-persist] mode-coherence: deliveryShape "single" with a ' +
89
- 'tickets payload is contradictory — the single-delivery mode ' +
90
- 'authors NO tickets (the Delivery Slicing table is the audit ' +
91
- 'trail). Remove the tickets file, or re-author the risk verdict ' +
92
- 'as fan-out.',
93
- );
94
- }
95
- return 'single';
96
- }
97
-
98
- if (!hasTickets) {
99
- throw new Error(
100
- '[plan-persist] fan-out persist requires a non-empty tickets array ' +
101
- '(--tickets <file>). A ticket-less spec-only plan must declare ' +
102
- 'deliveryShape: "single" in the risk verdict.',
103
- );
104
- }
105
- if (tickets.some((t) => t && typeof t === 'object' && 'op' in t)) {
106
- throw new Error(
107
- '[plan-persist] tickets carry `op` fields but --amend was not passed ' +
108
- '— refusing to reinterpret an amend delta as a full persist. Pass ' +
109
- '--amend, or strip the op fields for a fresh fan-out.',
110
- );
111
- }
112
- return 'fan-out';
113
- }
114
-
115
- /**
116
- * Count the slices of the authored Tech Spec's `## Delivery Slicing` table
117
- * — the single-mode plan summary's `sliceCount` (design §2: the slicing
118
- * table IS the single mode's audit trail). Returns `null` when the table
119
- * is absent or unparseable (fail-open, mirroring the parser's contract).
120
- *
121
- * @param {string} techSpecContent
122
- * @returns {number|null}
123
- */
124
- export function countDeliverySlices(techSpecContent) {
125
- const rows = parseDeliverySlicingTable(techSpecContent ?? '');
126
- return Array.isArray(rows) ? rows.length : null;
127
- }
@@ -1,205 +0,0 @@
1
- /**
2
- * post-merge-pipeline.js — sequencer for the post-merge phases of
3
- * `story-close`.
4
- *
5
- * After the Story branch is merged into the Epic branch, several best-effort
6
- * cleanup + reporting phases must run:
7
- *
8
- * 1. worktree-reap — remove the per-Story worktree.
9
- * 2. branch-cleanup — delete the Story branch (local + remote).
10
- * 3. ticket-closure — transition the Story to agent::done
11
- * and run cascade completion.
12
- * 4. notification — fire the story-complete webhook.
13
- * 5. dashboard-refresh — regenerate the dispatch manifest.
14
- * 6. temp-cleanup — delete the per-Story manifest pair under
15
- * `temp/epic-<eid>/stories/story-<sid>/manifest.{md,json}`
16
- * (Epic #1030 Story #1040). Falls back to the
17
- * legacy flat `temp/story-manifest-<id>.{md,json}`
18
- * layout when `epicId` is unknown — both paths
19
- * are tried so partial migrations don't leak
20
- * files in either layout.
21
- * 7. detectors — fire rework + retry signal detectors against
22
- * this Story's `traces.ndjson` and persist each
23
- * emission to `signals.ndjson` BEFORE the
24
- * analyzer renders the perf-summary comment.
25
- * 8. perf-summary — shell out to `analyze-execution.js` so the
26
- * analyzer is the single writer of the
27
- * `<!-- structured:story-perf-summary -->`
28
- * comment on the Story ticket.
29
- *
30
- * Each phase is wrapped by `runPhase` so a single failure does not abort
31
- * the rest of the close-out — the same best-effort contract that the
32
- * pre-extraction inline code provided. Phase return values are merged into
33
- * a `state` object whose shape `runStoryClose` consumes to build the final
34
- * structured result.
35
- *
36
- * The phase implementations live under `./post-merge/phases/` (one file
37
- * per phase) — this module is a pure sequencer that imports each phase,
38
- * re-exports them for backwards compatibility, and runs them in order
39
- * via `runPhase`.
40
- */
41
-
42
- import { execFileSync } from 'node:child_process';
43
- import path from 'node:path';
44
- import { Logger } from '../Logger.js';
45
- import { detectorsPhase } from './detectors-phase.js';
46
- import { runPhase } from './phase-runner.js';
47
- import { branchCleanupPhase } from './post-merge/phases/branch-cleanup.js';
48
- import { dashboardRefreshPhase } from './post-merge/phases/dashboard-refresh.js';
49
- import { notificationPhase } from './post-merge/phases/notification.js';
50
- import { tempCleanupPhase } from './post-merge/phases/temp-cleanup.js';
51
- import { ticketClosurePhase } from './post-merge/phases/ticket-closure.js';
52
- import {
53
- createWorktreeReapState,
54
- worktreeReapPhase,
55
- } from './post-merge/phases/worktree-reap.js';
56
-
57
- export {
58
- branchCleanupPhase,
59
- dashboardRefreshPhase,
60
- detectorsPhase,
61
- notificationPhase,
62
- tempCleanupPhase,
63
- ticketClosurePhase,
64
- worktreeReapPhase,
65
- };
66
-
67
- function reapPhaseLogger(progress) {
68
- return progress ?? (() => {});
69
- }
70
-
71
- /**
72
- * perfSummaryPhase — shells out to `analyze-execution.js --story <sid>
73
- * --epic <eid> --phase-timings <path>` so the analyzer is the single
74
- * writer of the `<!-- structured:story-perf-summary -->` comment on the
75
- * Story ticket (Epic #1030 Story #1046). Replaces the legacy
76
- * `<!-- structured:phase-timings -->` post that lived inline in
77
- * `post-merge-close.js`.
78
- *
79
- * Best-effort: any failure (missing analyzer, non-zero exit, no path
80
- * supplied) logs a warning and resolves — the merge has already
81
- * succeeded and we would rather lose the perf summary than roll back
82
- * closure.
83
- *
84
- * @param {{
85
- * storyId: number|string,
86
- * epicId: number|string,
87
- * phaseTimingsPath: string|null|undefined,
88
- * projectRoot?: string,
89
- * progress?: Function,
90
- * logger?: object,
91
- * spawnFn?: typeof execFileSync,
92
- * }} ctx
93
- * @returns {Promise<{ status: 'ok'|'skipped'|'failed', reason?: string }>}
94
- */
95
- export async function perfSummaryPhase(ctx) {
96
- const {
97
- storyId,
98
- epicId,
99
- phaseTimingsPath,
100
- projectRoot,
101
- progress,
102
- logger,
103
- spawnFn = execFileSync,
104
- } = ctx;
105
- const log = reapPhaseLogger(progress);
106
- if (!phaseTimingsPath) {
107
- log('PERF', '⏭️ Skipping perf-summary (no phase-timings path provided)');
108
- return { status: 'skipped', reason: 'no-phase-timings-path' };
109
- }
110
- const root = projectRoot ?? process.cwd();
111
- const analyzerPath = path.join(
112
- root,
113
- '.agents',
114
- 'scripts',
115
- 'analyze-execution.js',
116
- );
117
- const args = [
118
- analyzerPath,
119
- '--story',
120
- String(storyId),
121
- '--epic',
122
- String(epicId),
123
- '--phase-timings',
124
- phaseTimingsPath,
125
- ];
126
- log(
127
- 'PERF',
128
- `Running analyzer: analyze-execution.js --story ${storyId} --epic ${epicId}`,
129
- );
130
- try {
131
- spawnFn(process.execPath, args, {
132
- cwd: root,
133
- stdio: ['ignore', 'pipe', 'pipe'],
134
- });
135
- log('PERF', '✅ story-perf-summary posted');
136
- return { status: 'ok' };
137
- } catch (err) {
138
- const reason = err?.message ?? String(err);
139
- logger?.warn?.(
140
- `[post-merge-pipeline] ⚠️ analyze-execution failed (non-fatal): ${reason}`,
141
- );
142
- return { status: 'failed', reason };
143
- }
144
- }
145
-
146
- export const DEFAULT_POST_MERGE_PHASES = Object.freeze([
147
- {
148
- name: 'worktree-reap',
149
- fn: worktreeReapPhase,
150
- stateKey: 'worktreeReap',
151
- fallback: createWorktreeReapState({
152
- status: 'failed',
153
- reason: 'phase-error',
154
- }),
155
- },
156
- { name: 'branch-cleanup', fn: branchCleanupPhase, stateKey: 'branchCleanup' },
157
- { name: 'ticket-closure', fn: ticketClosurePhase, stateKey: 'ticketClosure' },
158
- { name: 'notification', fn: notificationPhase },
159
- {
160
- name: 'dashboard-refresh',
161
- fn: dashboardRefreshPhase,
162
- stateKey: 'manifestUpdated',
163
- },
164
- { name: 'temp-cleanup', fn: tempCleanupPhase },
165
- // Detectors MUST run before `perf-summary`. The perf phase shells out
166
- // to `analyze-execution.js`, which reads the per-Story signals stream
167
- // to author the `<!-- structured:story-perf-summary -->` comment;
168
- // emitting rework/retry events first ensures the rendered surface
169
- // reflects this Story's signals.
170
- { name: 'detectors', fn: detectorsPhase, stateKey: 'detectors' },
171
- { name: 'perf-summary', fn: perfSummaryPhase, stateKey: 'perfSummary' },
172
- ]);
173
-
174
- /**
175
- * Sequence the post-merge phases of `story-close`. Every phase runs
176
- * under `runPhase` so a single failure logs `[phase=<name>] <err>` and the
177
- * pipeline keeps going. Each phase's return value is recorded under its
178
- * `stateKey` (when defined) on the returned state object.
179
- *
180
- * @param {object} ctx Phase collaborators (provider, notify,
181
- * logger, progress, etc.).
182
- * @param {Array<{name: string, fn: Function, stateKey?: string, fallback?: any}>} [phases]
183
- * Phase descriptors. Defaults to `DEFAULT_POST_MERGE_PHASES`.
184
- * @returns {Promise<object>} Aggregated state from each phase.
185
- */
186
- export async function runPostMergePipeline(
187
- ctx,
188
- phases = DEFAULT_POST_MERGE_PHASES,
189
- ) {
190
- const logger = ctx.logger ?? Logger;
191
- const state = {
192
- worktreeReap: createWorktreeReapState(),
193
- branchCleanup: { localDeleted: false, remoteDeleted: false },
194
- ticketClosure: { closedTickets: [], cascadedTo: [], cascadeFailed: [] },
195
- manifestUpdated: false,
196
- };
197
- for (const phase of phases) {
198
- const value = await runPhase(phase.name, () => phase.fn(ctx, state), {
199
- logger,
200
- fallback: phase.fallback,
201
- });
202
- if (phase.stateKey && value !== undefined) state[phase.stateKey] = value;
203
- }
204
- return state;
205
- }