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
@@ -0,0 +1,361 @@
1
+ /**
2
+ * story-ops.js — flat Story creation for v2 plan-persist (Stage 3).
3
+ *
4
+ * Under the Story collapse (`docs/roadmap.md` § Stage 3), `/plan` persists
5
+ * zero-or-more Story issues directly — no Epic parent, no reconciler tree,
6
+ * no `deliveryShape` mode matrix. Default is **one Story**; N>1 is gated by
7
+ * the Stage-1 split-policy validator (`assertAcceptancePartition`).
8
+ *
9
+ * Each Story body is the single executable document: Tech Spec stays inline
10
+ * under `## Spec`. Over-budget Specs fail closed (split / tighten) — never
11
+ * spill to `docs/`. Top-level `acceptance[]` / `verify[]` are the machine
12
+ * contract and are synced into the body so the GitHub issue stays complete
13
+ * without requiring the LLM to dual-author the same lists.
14
+ *
15
+ * @module lib/orchestration/plan-persist/story-ops
16
+ */
17
+
18
+ import { randomBytes } from 'node:crypto';
19
+
20
+ import { AGENT_LABELS, TYPE_LABELS } from '../../label-constants.js';
21
+ import {
22
+ parse as parseStoryBody,
23
+ serialize as serializeStoryBody,
24
+ } from '../../story-body/story-body.js';
25
+ import { assertSpecWithinBudget } from '../spec-spill.js';
26
+ import { assertAcceptancePartition } from '../split-policy-validator.js';
27
+
28
+ /** Label prefix grouping sibling Stories from one plan run (N>1). */
29
+ export const PLAN_RUN_LABEL_PREFIX = 'plan-run::';
30
+
31
+ /**
32
+ * Normalize a caller-supplied plan-run token. Persistence and resolution
33
+ * share this helper so human-readable ids map to one canonical label.
34
+ *
35
+ * @param {string} id
36
+ * @returns {string}
37
+ */
38
+ export function normalizePlanRunId(id) {
39
+ const token = String(id ?? '')
40
+ .trim()
41
+ .toLowerCase()
42
+ .replace(/^plan-run::/, '')
43
+ .replace(/[^a-z0-9._-]+/g, '-');
44
+ if (!token) {
45
+ throw new Error('plan-run id requires a non-empty planRunId');
46
+ }
47
+ return token;
48
+ }
49
+
50
+ /**
51
+ * Build a `plan-run::<id>` label. When `id` is omitted, generates a short
52
+ * random hex token (8 chars) suitable for a rare multi-Story plan.
53
+ *
54
+ * @param {string} [id]
55
+ * @returns {string}
56
+ */
57
+ export function planRunLabel(id) {
58
+ const token =
59
+ typeof id === 'string' && id.trim() !== ''
60
+ ? normalizePlanRunId(id)
61
+ : randomBytes(4).toString('hex');
62
+ return `${PLAN_RUN_LABEL_PREFIX}${token}`;
63
+ }
64
+
65
+ function bodyObjectFromTicket(ticket) {
66
+ if (typeof ticket.body === 'string') {
67
+ return parseStoryBody(ticket.body).body;
68
+ }
69
+ if (ticket.body && typeof ticket.body === 'object') {
70
+ return parseStoryBody(ticket.body).body;
71
+ }
72
+
73
+ // Allow top-level structured fields (goal/changes/…) without a `body` key.
74
+ return parseStoryBody({
75
+ goal: ticket.goal ?? '',
76
+ slicing: ticket.slicing ?? '',
77
+ spec: ticket.spec ?? '',
78
+ changes: ticket.changes ?? [],
79
+ acceptance: ticket.acceptance ?? [],
80
+ verify: ticket.verify ?? [],
81
+ references: ticket.references ?? [],
82
+ non_goals: ticket.non_goals ?? [],
83
+ wide: ticket.wide ?? null,
84
+ reason_to_exist: ticket.reason_to_exist ?? null,
85
+ depends_on: ticket.depends_on ?? [],
86
+ estimated_test_files: ticket.estimated_test_files ?? null,
87
+ }).body;
88
+ }
89
+
90
+ function normalizeDependsOn(ticket, bodyObject) {
91
+ if (Array.isArray(ticket.depends_on)) {
92
+ return ticket.depends_on.filter((d) => typeof d === 'string');
93
+ }
94
+ return Array.isArray(bodyObject.depends_on) ? bodyObject.depends_on : [];
95
+ }
96
+
97
+ function arraysEqual(a, b) {
98
+ return a.length === b.length && a.every((value, index) => value === b[index]);
99
+ }
100
+
101
+ /**
102
+ * Top-level `acceptance[]` / `verify[]` are the machine contract (validator
103
+ * SSOT). Sync them into the body so the persisted GitHub issue is complete.
104
+ * When the body already lists the same items, keep them; when the body is
105
+ * empty, fill from top-level; when both disagree, fail closed.
106
+ *
107
+ * @param {object} ticket
108
+ * @param {object} bodyObject
109
+ * @param {'acceptance'|'verify'} field
110
+ */
111
+ function syncContractFieldFromTopLevel(ticket, bodyObject, field) {
112
+ if (!Array.isArray(ticket[field])) return;
113
+ const topLevel = ticket[field].map(String);
114
+ const bodyValue = Array.isArray(bodyObject[field])
115
+ ? bodyObject[field].map(String)
116
+ : [];
117
+ if (bodyValue.length > 0 && !arraysEqual(topLevel, bodyValue)) {
118
+ throw new Error(
119
+ `[plan-persist] Story "${ticket.slug ?? ticket.title ?? 'unknown'}" has mismatched top-level and body ${field} arrays`,
120
+ );
121
+ }
122
+ bodyObject[field] = topLevel;
123
+ }
124
+
125
+ /**
126
+ * Normalize a plan Story ticket into `{ slug, title, bodyObject }`.
127
+ * Accepts either a serialized markdown `body` string or a structured body.
128
+ *
129
+ * @param {object} ticket
130
+ * @returns {{ slug: string, title: string, bodyObject: object, depends_on: string[] }}
131
+ */
132
+ export function normalizeStoryTicket(ticket) {
133
+ if (!ticket || typeof ticket !== 'object') {
134
+ throw new Error('[plan-persist] each story ticket must be an object');
135
+ }
136
+ const slug =
137
+ typeof ticket.slug === 'string' && ticket.slug.trim() !== ''
138
+ ? ticket.slug.trim()
139
+ : null;
140
+ if (!slug) {
141
+ throw new Error(
142
+ '[plan-persist] each story ticket requires a non-empty slug',
143
+ );
144
+ }
145
+ const title =
146
+ typeof ticket.title === 'string' && ticket.title.trim() !== ''
147
+ ? ticket.title.trim()
148
+ : `Story ${slug}`;
149
+ const bodyObject = bodyObjectFromTicket(ticket);
150
+ syncContractFieldFromTopLevel(ticket, bodyObject, 'acceptance');
151
+ syncContractFieldFromTopLevel(ticket, bodyObject, 'verify');
152
+ const depends_on = normalizeDependsOn(ticket, bodyObject);
153
+
154
+ return { slug, title, bodyObject, depends_on };
155
+ }
156
+
157
+ /**
158
+ * Fold optional shared Tech Spec prose into a Story body when the Story has
159
+ * no inline Spec. Specs stay inline; over-budget Specs throw.
160
+ *
161
+ * Precedence: per-Story `body.spec` wins; otherwise `sharedSpec` is used
162
+ * (N===1 convenience only — callers must not share one Spec across N>1).
163
+ *
164
+ * @param {object} bodyObject
165
+ * @param {string} slug
166
+ * @param {object} [opts]
167
+ * @param {string|null} [opts.sharedSpec]
168
+ * @returns {{ bodyObject: object }}
169
+ */
170
+ export function foldSpecIntoStoryBody(bodyObject, slug, opts = {}) {
171
+ const { sharedSpec = null } = opts;
172
+
173
+ const next = {
174
+ ...bodyObject,
175
+ references: Array.isArray(bodyObject.references)
176
+ ? [...bodyObject.references]
177
+ : [],
178
+ };
179
+
180
+ const inline =
181
+ typeof next.spec === 'string' && next.spec.trim() !== ''
182
+ ? next.spec.trim()
183
+ : typeof sharedSpec === 'string' && sharedSpec.trim() !== ''
184
+ ? sharedSpec.trim()
185
+ : '';
186
+
187
+ if (inline === '') {
188
+ return { bodyObject: next };
189
+ }
190
+
191
+ const { content } = assertSpecWithinBudget({ storyId: slug, spec: inline });
192
+ next.spec = content;
193
+ return { bodyObject: next };
194
+ }
195
+
196
+ function assembleOnePlanStory(ticket, opts) {
197
+ const { slug, title, bodyObject, depends_on } = normalizeStoryTicket(ticket);
198
+ const { bodyObject: folded } = foldSpecIntoStoryBody(bodyObject, slug, {
199
+ sharedSpec: opts.sharedSpec ?? null,
200
+ });
201
+ const body = serializeStoryBody({ ...folded, depends_on });
202
+ return {
203
+ story: {
204
+ slug,
205
+ title,
206
+ body,
207
+ bodyObject: { ...folded, depends_on },
208
+ acceptance: Array.isArray(folded.acceptance) ? folded.acceptance : [],
209
+ depends_on,
210
+ },
211
+ };
212
+ }
213
+
214
+ /**
215
+ * Shared techspec.md is an N===1 convenience only — folding one Spec into
216
+ * every sibling duplicates approach prose and breaks Story-as-SSOT.
217
+ *
218
+ * @param {object[]} tickets
219
+ * @param {string|null|undefined} sharedSpec
220
+ */
221
+ function assertSharedSpecAllowed(tickets, sharedSpec) {
222
+ if (tickets.length <= 1) return;
223
+ if (typeof sharedSpec !== 'string' || sharedSpec.trim() === '') return;
224
+ throw new Error(
225
+ '[plan-persist] a shared techspec.md cannot be folded into N>1 Stories — ' +
226
+ "put each Story's approach in its own ## Spec so every Story stays a " +
227
+ 'complete executable document.',
228
+ );
229
+ }
230
+
231
+ /**
232
+ * Assemble markdown bodies for every Story: normalize → fold spec →
233
+ * assertAcceptancePartition → serialize.
234
+ *
235
+ * @param {object[]} tickets
236
+ * @param {object} [opts]
237
+ * @param {string|null} [opts.sharedSpec]
238
+ * @param {string[]} [opts.planAcceptance]
239
+ * @returns {{ stories: Array<{ slug: string, title: string, body: string, acceptance: string[], depends_on: string[] }> }}
240
+ */
241
+ export function assemblePlanStories(tickets, opts = {}) {
242
+ if (!Array.isArray(tickets) || tickets.length === 0) {
243
+ throw new Error(
244
+ '[plan-persist] stories payload must be a non-empty array — author at least one Story (default-single).',
245
+ );
246
+ }
247
+
248
+ assertSharedSpecAllowed(tickets, opts.sharedSpec);
249
+
250
+ const stories = tickets.map(
251
+ (ticket) => assembleOnePlanStory(ticket, opts).story,
252
+ );
253
+
254
+ assertAcceptancePartition(stories, {
255
+ planAcceptance: opts.planAcceptance,
256
+ });
257
+
258
+ return { stories };
259
+ }
260
+
261
+ function orderStoriesByDependencies(stories) {
262
+ const list = Array.isArray(stories) ? stories : [];
263
+ const known = new Set(list.map((story) => story.slug));
264
+ for (const story of list) {
265
+ const unknown = story.depends_on.filter((slug) => !known.has(slug));
266
+ if (unknown.length > 0) {
267
+ throw new Error(
268
+ `[plan-persist] Story "${story.slug}" depends on unknown sibling(s): ${unknown.join(', ')}`,
269
+ );
270
+ }
271
+ }
272
+ const ordered = [];
273
+ const scheduled = new Set();
274
+ const pending = [...list];
275
+ while (pending.length > 0) {
276
+ const index = pending.findIndex((story) =>
277
+ story.depends_on.every((slug) => scheduled.has(slug)),
278
+ );
279
+ if (index === -1) {
280
+ throw new Error(
281
+ `[plan-persist] dependency cycle prevents Story creation: ${pending.map((story) => story.slug).join(', ')}`,
282
+ );
283
+ }
284
+ const [story] = pending.splice(index, 1);
285
+ ordered.push(story);
286
+ scheduled.add(story.slug);
287
+ }
288
+ return ordered;
289
+ }
290
+
291
+ /**
292
+ * Create Story issues via `provider.createIssue`. Applies `type::story`,
293
+ * `agent::ready`, and — when N>1 — a shared plan-run label.
294
+ *
295
+ * @param {object} args
296
+ * @param {object} args.provider
297
+ * @param {ReturnType<typeof assemblePlanStories>['stories']} args.stories
298
+ * @param {object} [args.opts]
299
+ * @param {string} [args.opts.planRunId]
300
+ * @param {boolean} [args.opts.dryRun=false]
301
+ * @returns {Promise<{ created: Array<{ slug: string, id: number, url?: string, title: string }>, planRunLabel: string|null }>}
302
+ */
303
+ export async function createStoryIssues({ provider, stories, opts = {} }) {
304
+ if (typeof provider?.createIssue !== 'function') {
305
+ throw new Error(
306
+ '[plan-persist] provider does not expose createIssue; cannot persist Stories.',
307
+ );
308
+ }
309
+
310
+ const list = Array.isArray(stories) ? stories : [];
311
+ const planLabel = list.length > 1 ? planRunLabel(opts.planRunId) : null;
312
+ const labels = [TYPE_LABELS.STORY, AGENT_LABELS.READY];
313
+ if (planLabel) labels.push(planLabel);
314
+
315
+ if (opts.dryRun) {
316
+ return {
317
+ created: list.map((s, i) => ({
318
+ slug: s.slug,
319
+ id: -(i + 1),
320
+ title: s.title,
321
+ url: undefined,
322
+ })),
323
+ planRunLabel: planLabel,
324
+ };
325
+ }
326
+
327
+ const created = [];
328
+ const createdBySlug = new Map();
329
+ for (const story of orderStoriesByDependencies(list)) {
330
+ const dependencyRefs = story.depends_on.map(
331
+ (slug) => `#${createdBySlug.get(slug)}`,
332
+ );
333
+ const body =
334
+ dependencyRefs.length === 0
335
+ ? story.body
336
+ : serializeStoryBody(
337
+ { ...story.bodyObject, depends_on: dependencyRefs },
338
+ { includeFooter: true },
339
+ );
340
+ const result = await provider.createIssue({
341
+ title: story.title,
342
+ body,
343
+ labels: [...labels],
344
+ });
345
+ const id = result?.id ?? result?.number;
346
+ if (!Number.isInteger(id)) {
347
+ throw new Error(
348
+ `[plan-persist] createIssue for slug "${story.slug}" did not return a numeric id`,
349
+ );
350
+ }
351
+ created.push({
352
+ slug: story.slug,
353
+ id,
354
+ title: story.title,
355
+ url: result.url,
356
+ });
357
+ createdBySlug.set(story.slug, id);
358
+ }
359
+
360
+ return { created, planRunLabel: planLabel };
361
+ }
@@ -1,21 +1,9 @@
1
1
  /**
2
- * summary.js — plan-persist terminal summary (Epic #4474, PR3).
2
+ * summary.js — plan-persist terminal summary (v2 Stage 3).
3
3
  *
4
- * Owns the single `plan-summary` structured comment the collapsed persist
5
- * surface upserts at terminal success, closing with the dry-run wave table.
6
- * This replaces two retired round-trips of the 12-phase pipeline:
7
- *
8
- * - the Phase 9 plan-time `dispatch-manifest` comment, whose claimed
9
- * consumer ("Wave Completeness Gate, /deliver Step 0.5") does not exist
10
- * — the live manifest is written at deliver time by `wave-record-io.js`
11
- * (#4474 design §3: DROP, keep the wave table as summary text only);
12
- * - the Phase 12 notify round-trip ("informational — no webhook for
13
- * planning").
14
- *
15
- * The wave table is computed from the validated ticket set's `depends_on`
16
- * slug edges via the same `computeStoryWaves` layering the deliver-time
17
- * dispatch pipeline uses, so the preview matches what `/deliver` will
18
- * actually fan out (barring later manual ticket edits).
4
+ * Upserts a single `plan-summary` structured comment on the primary Story
5
+ * at terminal success. Carries risk / routing receipts and the dry-run
6
+ * `depends_on` ordering table for the rare N>1 plan.
19
7
  *
20
8
  * @module lib/orchestration/plan-persist/summary
21
9
  */
@@ -23,23 +11,15 @@
23
11
  import { computeStoryWaves } from '../dependency-analyzer.js';
24
12
 
25
13
  /**
26
- * Structured-comment type for the persist summary. Registered in
27
- * `ticketing/reads.js` `STRUCTURED_COMMENT_TYPES`; upsert-idempotent so a
28
- * `--force`/`--resume` re-persist replaces the prior summary in place.
14
+ * Structured-comment type for the persist summary.
29
15
  */
30
16
  export const PLAN_SUMMARY_COMMENT_TYPE = 'plan-summary';
31
17
 
32
18
  /**
33
19
  * Compute the dry-run wave assignment for a validated ticket set.
34
20
  *
35
- * Adapts the slug-keyed ticket shape onto `computeStoryWaves`' storyGroups
36
- * contract (slug → { storyId, tasks: [] }; explicit deps from `depends_on`).
37
- * Under the 2-tier hierarchy Stories carry no tasks, so all edges are
38
- * explicit.
39
- *
40
21
  * @param {Array<{ slug: string, title?: string, depends_on?: string[] }>} tickets
41
22
  * @returns {Array<{ wave: number, stories: Array<{ slug: string, title: string }> }>}
42
- * Waves in execution order.
43
23
  */
44
24
  export function buildWaveTable(tickets) {
45
25
  const list = Array.isArray(tickets) ? tickets : [];
@@ -66,53 +46,24 @@ export function buildWaveTable(tickets) {
66
46
  }
67
47
 
68
48
  /**
69
- * Render the dry-run wave table as GitHub-flavoured markdown.
70
- *
71
49
  * @param {ReturnType<typeof buildWaveTable>} waveTable
72
- * @returns {string[]} markdown lines
50
+ * @returns {string[]}
73
51
  */
74
52
  function renderWaveTableLines(waveTable) {
75
53
  if (!Array.isArray(waveTable) || waveTable.length === 0) {
76
- return ['_No stories to wave (empty plan)._'];
54
+ return ['_No stories to sequence (empty plan)._'];
77
55
  }
78
56
  const rows = waveTable.map(
79
57
  ({ wave, stories }) =>
80
58
  `| ${wave + 1} | ${stories.map((s) => `\`${s.slug}\``).join(', ')} |`,
81
59
  );
82
- return ['| Wave | Stories |', '| --- | --- |', ...rows];
60
+ return ['| Order | Stories |', '| --- | --- |', ...rows];
83
61
  }
84
62
 
85
63
  /**
86
- * Build the `plan-summary` structured-comment body: risk + routing +
87
- * freshness + healthcheck receipts, closing with the mode-specific tail —
88
- * the dry-run wave table for fan-out/amend, or the single-delivery routing
89
- * record `{ deliveryShape, sliceCount, routingReasons }` (Epic #4474 PR4)
90
- * for the spec-only mode.
91
- *
92
- * Every auto-waiver the persist derived is printed WITH its reason
93
- * (#4496 fix 2) — e.g. the no-BDD-runner acceptance-disposition waiver
94
- * (`planningRisk.acceptanceWaivedReason`) — so the summary is
95
- * self-explanatory and a headless reader never has to re-derive a persist
96
- * outcome from framework source.
64
+ * Build the `plan-summary` structured-comment body.
97
65
  *
98
- * @param {{
99
- * epicId: number,
100
- * ticketCount: number,
101
- * planningRisk: { overallLevel?: string, gateDecision?: string, acceptanceDisposition?: string, acceptanceWaivedReason?: string },
102
- * reviewRouting: { decision?: string },
103
- * freshness?: { stale?: number, ambiguous?: number },
104
- * healthcheck?: { ok?: boolean, waived?: boolean, skipped?: boolean },
105
- * waveTable: ReturnType<typeof buildWaveTable>,
106
- * mode?: 'fan-out'|'single'|'amend',
107
- * planMetricsLine?: string|null,
108
- * single?: { deliveryShape: 'single', sliceCount: number|null, routingReasons: string[] }|null,
109
- * amend?: {
110
- * closed: Array<{ slug: string, issueNumber: number }>,
111
- * recreated: Array<{ slug: string, oldIssueNumber: number, issueNumber: number }>,
112
- * created: Array<{ slug: string, issueNumber: number }>,
113
- * keptCount: number,
114
- * }|null,
115
- * }} input
66
+ * @param {object} input
116
67
  * @returns {string}
117
68
  */
118
69
  export function buildPlanSummaryCommentBody({
@@ -123,84 +74,60 @@ export function buildPlanSummaryCommentBody({
123
74
  freshness,
124
75
  healthcheck,
125
76
  waveTable,
126
- mode = 'fan-out',
77
+ mode = 'stories',
127
78
  planMetricsLine = null,
79
+ stories = null,
80
+ planRunLabel = null,
81
+ // legacy unused knobs kept so older test call sites don't crash mid-migration
128
82
  single = null,
129
83
  amend = null,
130
84
  }) {
85
+ void mode;
86
+ void single;
87
+ void amend;
88
+
131
89
  const freshnessLine =
132
90
  (freshness?.stale ?? 0) > 0 || (freshness?.ambiguous ?? 0) > 0
133
- ? `- ⚠️ Spec freshness: ${freshness.stale} stale / ${freshness.ambiguous} ambiguous reference(s) — see the spec-freshness comment.`
91
+ ? `- ⚠️ Spec freshness: ${freshness.stale} stale / ${freshness.ambiguous} ambiguous reference(s).`
134
92
  : '- Spec freshness: clean.';
135
93
  const healthcheckLine = healthcheck?.skipped
136
- ? '- Healthcheck: skipped (test seam).'
94
+ ? '- Healthcheck: skipped (v2 flat Story persist — ticket validators are the gate).'
137
95
  : healthcheck?.ok
138
96
  ? '- Healthcheck: passed.'
139
97
  : `- Healthcheck: failed, waived by operator label.`;
140
98
 
141
- const headLine =
142
- mode === 'single'
143
- ? `- Single-delivery plan (\`delivery::single\`): no Story tree — the Delivery Slicing table is the audit trail.`
144
- : `- ${ticketCount} Story ticket(s) persisted across ${waveTable.length} wave(s).`;
99
+ const storyList =
100
+ Array.isArray(stories) && stories.length > 0
101
+ ? stories.map((s) => `#${s.id} (\`${s.slug}\`)`).join(', ')
102
+ : `${ticketCount} Story(ies)`;
145
103
 
146
- // Auto-waivers always ship with their reason (#4496 fix 2): the summary
147
- // is authoritative, so the line must be self-explanatory on its own.
148
104
  const waiverLines = planningRisk?.acceptanceWaivedReason
149
105
  ? [
150
106
  `- ⚠️ Acceptance disposition auto-waived to \`not-applicable\` — ${planningRisk.acceptanceWaivedReason}`,
151
107
  ]
152
108
  : [];
153
109
 
154
- const amendLines = amend
155
- ? [
156
- `- Amend delta: ${amend.created.length} added, ${amend.recreated.length} modified (closed + recreated), ${amend.closed.length} closed, ${amend.keptCount} kept untouched.`,
157
- ]
158
- : [];
159
-
160
- const tail =
161
- mode === 'single'
162
- ? [
163
- '#### Delivery routing record',
164
- '',
165
- '```json',
166
- JSON.stringify(
167
- {
168
- deliveryShape: 'single',
169
- sliceCount: single?.sliceCount ?? null,
170
- routingReasons: single?.routingReasons ?? [],
171
- },
172
- null,
173
- 2,
174
- ),
175
- '```',
176
- '',
177
- '_Marker is inert until #4475 lands the deliver-side reader — `/deliver` still treats this Epic as fan-out until then._',
178
- ]
179
- : [
180
- '#### Dry-run wave table',
181
- '',
182
- ...renderWaveTableLines(waveTable),
183
- '',
184
- '_Preview only — the authoritative dispatch manifest is written at deliver time (`wave-record-io.js`)._',
185
- ];
110
+ const runLine = planRunLabel
111
+ ? `- Plan-run label: \`${planRunLabel}\` (N>1 — deliver with \`/deliver --run <planRunId>\`).`
112
+ : '- Plan-run: single Story (default).';
186
113
 
187
114
  return [
188
- `### 📋 Plan Summary — Epic #${epicId} is \`agent::ready\``,
115
+ `### 📋 Plan Summary — Story #${epicId} is \`agent::ready\``,
189
116
  '',
190
- headLine,
191
- ...amendLines,
117
+ `- ${ticketCount} Story ticket(s) persisted: ${storyList}.`,
118
+ runLine,
192
119
  `- Risk: ${planningRisk?.overallLevel ?? 'unknown'} · ${planningRisk?.gateDecision ?? 'unknown'} (review routing: ${reviewRouting?.decision ?? 'unknown'}).`,
193
120
  ...waiverLines,
194
121
  freshnessLine,
195
122
  healthcheckLine,
196
- // G2 measurement receipt (Epic #4474 PR1/PR7): the plan-CLI invocation
197
- // ledger roll-up (turns-per-plan proxy, per-mode counts, critic skips)
198
- // rides the summary comment so the cohort reader never has to pull the
199
- // temp ledger off the runner's disk. Omitted when the ledger is empty.
200
123
  ...(typeof planMetricsLine === 'string' && planMetricsLine.length > 0
201
124
  ? [`- ${planMetricsLine}`]
202
125
  : []),
203
126
  '',
204
- ...tail,
127
+ '#### Delivery order (`depends_on`)',
128
+ '',
129
+ ...renderWaveTableLines(waveTable),
130
+ '',
131
+ '_Deliver with `/deliver <storyId>` (N=1) or `/deliver --run <planRunId>` (N>1)._',
205
132
  ].join('\n');
206
133
  }
@@ -3,13 +3,11 @@
3
3
  * the persist surface (Epic #4474 PR6, design §4: the 8.4 reachability
4
4
  * critic demoted from a fresh-context sub-agent to a persist-side scan).
5
5
  *
6
- * Mirrors the mechanics of the existing `--paranoid` F7 healthcheck
7
- * (`epic-plan-healthcheck.js#checkReachability`) route-glob scan of the
8
- * paths a Story declares vs the `planning.navigation.navRegistry` token
9
- * list but runs it over the **draft** ticket set inside `plan-persist.js`
10
- * step 4.5, before any provider call, so an orphaned surface is caught
11
- * while a one-line targeted amend is still free (nothing has been written
12
- * to GitHub yet).
6
+ * Route-glob scan of the paths a Story declares vs the
7
+ * `planning.navigation.navRegistry` token list, run over the **draft**
8
+ * ticket set inside `plan-persist.js` step 4.5, before any provider call,
9
+ * so an orphaned surface is caught while a one-line targeted amend is
10
+ * still free (nothing has been written to GitHub yet).
13
11
  *
14
12
  * Plan-level coverage semantics (the convergence contract): a route-adding
15
13
  * story that never references the nav registry produces orphan surfaces —
@@ -20,9 +18,8 @@
20
18
  * registry) in one targeted amend, and the re-run persist passes.
21
19
  *
22
20
  * Silent no-op when `planning.navigation` is unconfigured (`routeGlobs`
23
- * empty) — same opt-in contract as F7 / AC-13 reported as
24
- * `status: 'skipped'` so the caller can append the audit record to the
25
- * plan-metrics ledger.
21
+ * empty) — reported as `status: 'skipped'` so the caller can append the
22
+ * audit record to the plan-metrics ledger.
26
23
  *
27
24
  * Pure over its inputs (tickets + resolved config), no I/O.
28
25
  */
@@ -31,12 +28,10 @@ import {
31
28
  extractStoryPaths,
32
29
  globToRegExp,
33
30
  resolveNavConfig,
34
- } from '../../epic-plan-healthcheck.js';
31
+ } from './plan-navigation.js';
35
32
 
36
33
  /**
37
- * Fallback tokens when `navRegistry` is unconfigured but `routeGlobs` is
38
- * identical to the F7 healthcheck's fallback, so the two checks agree on
39
- * what counts as a registry reference.
34
+ * Fallback tokens when `navRegistry` is unconfigured but `routeGlobs` is.
40
35
  */
41
36
  const FALLBACK_REGISTRY_TOKENS = ['nav registry', 'navigation'];
42
37
 
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * The `--force` flag is intentional. By the time a Story is `agent::done`
11
11
  * its branch has already been merged into the Epic branch (via
12
- * `story-close.js`), so any residue left in the worktree — dirty
12
+ * `single-story-close.js`), so any residue left in the worktree — dirty
13
13
  * build artifacts, an interrupted rebase, a stray Windows lock — is noise.
14
14
  * The safety rails in `WorktreeManager.reap` exist for the _active_ close
15
15
  * path; at plan time we already know the Story is done and want the
@@ -12,17 +12,17 @@ import path from 'node:path';
12
12
  import {
13
13
  resolveFeatureRoots,
14
14
  verifyBddRunnerPendingTag,
15
- } from '../../../bdd-runner-detect.js';
16
- import { scanBddScenarios } from '../../../bdd-scenario-scanner.js';
17
- import { buildCodebaseSnapshot } from '../../../codebase-snapshot.js';
18
- import { getLimits, getPaths, PROJECT_ROOT } from '../../../config-resolver.js';
19
- import { hasEpicSection } from '../../../epic-body-sections.js';
20
- import { scanMemoryFreshness } from '../../../feedback-loop/memory-freshness.js';
21
- import { fetchPriorFeedback } from '../../../feedback-loop/prior-feedback-fetcher.js';
22
- import { Logger } from '../../../Logger.js';
23
- import { ensureDocsDigest } from '../../docs-digest.js';
24
- import { applyBudget } from '../../planning-context-budget.js';
25
- import { collectReferences, hasNewFileCue } from '../../spec-freshness.js';
15
+ } from '../../bdd-runner-detect.js';
16
+ import { scanBddScenarios } from '../../bdd-scenario-scanner.js';
17
+ import { buildCodebaseSnapshot } from '../../codebase-snapshot.js';
18
+ import { getLimits, getPaths, PROJECT_ROOT } from '../../config-resolver.js';
19
+ import { scanMemoryFreshness } from '../../feedback-loop/memory-freshness.js';
20
+ import { fetchPriorFeedback } from '../../feedback-loop/prior-feedback-fetcher.js';
21
+ import { Logger } from '../../Logger.js';
22
+ import { hasTicketSection } from '../../ticket-body-sections.js';
23
+ import { ensureDocsDigest } from '../docs-digest.js';
24
+ import { applyBudget } from '../planning-context-budget.js';
25
+ import { collectReferences, hasNewFileCue } from '../spec-freshness.js';
26
26
  import { buildAuthoringGrounding } from './spec-authoring-grounding.js';
27
27
 
28
28
  /**
@@ -41,7 +41,7 @@ import { buildAuthoringGrounding } from './spec-authoring-grounding.js';
41
41
  * @param {{ github?: { owner?: string, repo?: string }|null }} opts
42
42
  * @returns {string|null}
43
43
  */
44
- export function resolveMemoryDir({ github } = {}) {
44
+ function resolveMemoryDir({ github } = {}) {
45
45
  if (
46
46
  typeof process.env.MANDREL_MEMORY_DIR === 'string' &&
47
47
  process.env.MANDREL_MEMORY_DIR.length > 0
@@ -256,8 +256,8 @@ export async function buildAuthoringContext(
256
256
  // inside `body` (managed sections), which is how the author keeps
257
257
  // AC IDs stable across re-plans.
258
258
  planningSections: {
259
- techSpec: hasEpicSection(epic.body ?? '', 'techSpec'),
260
- acceptanceTable: hasEpicSection(epic.body ?? '', 'acceptanceTable'),
259
+ techSpec: hasTicketSection(epic.body ?? '', 'techSpec'),
260
+ acceptanceTable: hasTicketSection(epic.body ?? '', 'acceptanceTable'),
261
261
  },
262
262
  },
263
263
  docsContext,