mandrel 1.94.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 (393) hide show
  1. package/.agents/README.md +59 -73
  2. package/.agents/agents/story-worker.md +12 -13
  3. package/.agents/docs/SDLC.md +489 -1285
  4. package/.agents/docs/agentrc-reference.json +177 -67
  5. package/.agents/docs/configuration.md +104 -138
  6. package/.agents/docs/execution-reference.md +17 -20
  7. package/.agents/docs/quality-gates.md +13 -19
  8. package/.agents/docs/workflows.md +3 -3
  9. package/.agents/instructions.md +70 -81
  10. package/.agents/rules/ci-remediation.md +8 -12
  11. package/.agents/rules/git-conventions-reference.md +6 -7
  12. package/.agents/rules/git-conventions.md +16 -22
  13. package/.agents/schemas/acceptance-eval-verdict.schema.json +1 -1
  14. package/.agents/schemas/agentrc.schema.json +54 -214
  15. package/.agents/schemas/lifecycle/ledger-record.schema.json +1 -1
  16. package/.agents/schemas/lifecycle/retro.end.schema.json +1 -1
  17. package/.agents/schemas/risk-verdict.schema.json +0 -13
  18. package/.agents/scripts/analyze-execution.js +1 -1
  19. package/.agents/scripts/audit-to-stories.js +7 -7
  20. package/.agents/scripts/boot-sweep.js +1 -1
  21. package/.agents/scripts/check-lifecycle-lint.js +6 -9
  22. package/.agents/scripts/check-prepush-recovery.js +1 -1
  23. package/.agents/scripts/cleanup-repo-test-temp.js +6 -1
  24. package/.agents/scripts/lib/Logger.js +6 -10
  25. package/.agents/scripts/lib/audit-suite/runner.js +2 -2
  26. package/.agents/scripts/lib/audit-suite/selector.js +5 -5
  27. package/.agents/scripts/lib/audit-to-stories/{seed-epic-from-findings.js → seed-from-findings.js} +9 -9
  28. package/.agents/scripts/lib/baselines/kernel.js +206 -18
  29. package/.agents/scripts/lib/baselines/kinds/maintainability.js +0 -4
  30. package/.agents/scripts/lib/baselines/reader.js +1 -6
  31. package/.agents/scripts/lib/bdd-runner-detect.js +5 -9
  32. package/.agents/scripts/lib/bootstrap/issue-forms-template.js +32 -33
  33. package/.agents/scripts/lib/checks/core-bare-clean.js +2 -2
  34. package/.agents/scripts/lib/checks/index.js +2 -1
  35. package/.agents/scripts/lib/checks/story-init-not-backgrounded.js +23 -21
  36. package/.agents/scripts/lib/cli/standard-args.js +13 -22
  37. package/.agents/scripts/lib/cli-args.js +16 -7
  38. package/.agents/scripts/lib/close-validation/gates.js +2 -2
  39. package/.agents/scripts/lib/config/ci.js +6 -31
  40. package/.agents/scripts/lib/config/delivery-routing.js +45 -29
  41. package/.agents/scripts/lib/config/explain.js +55 -36
  42. package/.agents/scripts/lib/config/limits.js +17 -58
  43. package/.agents/scripts/lib/config/paths.js +0 -2
  44. package/.agents/scripts/lib/config/quality.js +1 -1
  45. package/.agents/scripts/lib/config/runners.js +17 -50
  46. package/.agents/scripts/lib/config/temp-paths.js +19 -14
  47. package/.agents/scripts/lib/config/worktree-isolation.js +0 -5
  48. package/.agents/scripts/lib/config-resolver.js +2 -7
  49. package/.agents/scripts/lib/config-settings-schema-delivery.js +24 -148
  50. package/.agents/scripts/lib/config-settings-schema-quality.js +8 -14
  51. package/.agents/scripts/lib/config-settings-schema.js +52 -38
  52. package/.agents/scripts/lib/dependency-parser.js +3 -2
  53. package/.agents/scripts/lib/doc-tiers.js +2 -2
  54. package/.agents/scripts/lib/duplicate-search.js +211 -41
  55. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +1 -1
  56. package/.agents/scripts/lib/findings/promote-finding.js +5 -5
  57. package/.agents/scripts/lib/framework-version.js +2 -3
  58. package/.agents/scripts/lib/git-branch-cleanup.js +1 -10
  59. package/.agents/scripts/lib/git-branch-lifecycle.js +17 -22
  60. package/.agents/scripts/lib/git-utils.js +32 -6
  61. package/.agents/scripts/lib/github/framework-repo.js +6 -0
  62. package/.agents/scripts/lib/label-constants.js +10 -23
  63. package/.agents/scripts/lib/label-taxonomy.js +9 -43
  64. package/.agents/scripts/lib/observability/active-story-env.js +1 -1
  65. package/.agents/scripts/lib/observability/hook-heartbeat.js +20 -52
  66. package/.agents/scripts/lib/observability/source-classifier.js +3 -3
  67. package/.agents/scripts/lib/onboard/init-tail.js +1 -3
  68. package/.agents/scripts/lib/orchestration/audit-lens-routing.js +128 -0
  69. package/.agents/scripts/lib/orchestration/bookkeeping-outbox.js +8 -5
  70. package/.agents/scripts/lib/orchestration/ceremony-routing.js +83 -20
  71. package/.agents/scripts/lib/orchestration/code-review.js +20 -268
  72. package/.agents/scripts/lib/orchestration/column-sync.js +1 -1
  73. package/.agents/scripts/lib/orchestration/consolidation-precondition.js +1 -1
  74. package/.agents/scripts/lib/orchestration/context-envelope.js +2 -5
  75. package/.agents/scripts/lib/orchestration/docs-digest.js +8 -8
  76. package/.agents/scripts/lib/orchestration/file-assumptions.js +7 -13
  77. package/.agents/scripts/lib/orchestration/git-cleanup/phases/cli.js +1 -1
  78. package/.agents/scripts/lib/orchestration/lifecycle/emit-loop-tick.js +8 -8
  79. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +2 -2
  80. package/.agents/scripts/lib/orchestration/lifecycle/ledger-writer.js +6 -3
  81. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +17 -43
  82. package/.agents/scripts/lib/orchestration/lint-baseline-service.js +4 -4
  83. package/.agents/scripts/lib/orchestration/merge-block-class.js +1 -1
  84. package/.agents/scripts/lib/orchestration/phase-runner.js +3 -2
  85. package/.agents/scripts/lib/orchestration/plan-context.js +248 -266
  86. package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +1 -1
  87. package/.agents/scripts/lib/orchestration/plan-navigation.js +92 -0
  88. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +61 -0
  89. package/.agents/scripts/lib/orchestration/plan-persist/persist-helpers.js +97 -0
  90. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +223 -854
  91. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +361 -0
  92. package/.agents/scripts/lib/orchestration/plan-persist/summary.js +35 -108
  93. package/.agents/scripts/lib/orchestration/plan-reachability.js +9 -14
  94. package/.agents/scripts/lib/orchestration/plan-runner/worktree-sweep.js +1 -1
  95. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/authoring-context.js +13 -13
  96. package/.agents/scripts/lib/orchestration/planning/decomposer-context.js +27 -0
  97. package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/risk-verdict.js +3 -4
  98. package/.agents/scripts/lib/orchestration/post-merge/phases/branch-cleanup.js +2 -2
  99. package/.agents/scripts/lib/orchestration/post-merge/phases/dashboard-refresh.js +8 -20
  100. package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +3 -2
  101. package/.agents/scripts/lib/orchestration/pr-base-guard.js +18 -28
  102. package/.agents/scripts/lib/orchestration/preflight-cache.js +5 -5
  103. package/.agents/scripts/lib/orchestration/remote-verifier.js +1 -1
  104. package/.agents/scripts/lib/orchestration/resolve-plan-run.js +155 -0
  105. package/.agents/scripts/lib/orchestration/resolves-token.js +1 -1
  106. package/.agents/scripts/lib/orchestration/retro-perf-heuristics.js +8 -8
  107. package/.agents/scripts/lib/orchestration/retro-proposals.js +140 -79
  108. package/.agents/scripts/lib/orchestration/review-depth.js +26 -12
  109. package/.agents/scripts/lib/orchestration/review-providers/codex.js +2 -2
  110. package/.agents/scripts/lib/orchestration/review-providers/review-provider-factory.js +21 -56
  111. package/.agents/scripts/lib/orchestration/run-epilogue.js +426 -0
  112. package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +1 -1
  113. package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +95 -41
  114. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +16 -13
  115. package/.agents/scripts/lib/orchestration/single-story-close/phases/review-block.js +40 -0
  116. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +11 -3
  117. package/.agents/scripts/lib/orchestration/spec-freshness.js +14 -205
  118. package/.agents/scripts/lib/orchestration/spec-section-validator.js +4 -5
  119. package/.agents/scripts/lib/orchestration/spec-spill.js +60 -0
  120. package/.agents/scripts/lib/orchestration/split-policy-validator.js +188 -0
  121. package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +49 -0
  122. package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +15 -12
  123. package/.agents/scripts/lib/orchestration/story-follow-ups.js +237 -0
  124. package/.agents/scripts/lib/orchestration/story-init-remote.js +47 -0
  125. package/.agents/scripts/lib/orchestration/story-plan-state.js +48 -0
  126. package/.agents/scripts/lib/orchestration/{epic-runner → story-progress}/story-run-progress-writer.js +3 -3
  127. package/.agents/scripts/lib/orchestration/structured-comment-parser.js +1 -1
  128. package/.agents/scripts/lib/orchestration/task-body-validator.js +8 -18
  129. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +11 -61
  130. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +189 -373
  131. package/.agents/scripts/lib/orchestration/ticket-validator.js +2 -7
  132. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +0 -25
  133. package/.agents/scripts/lib/orchestration/ticketing/reads.js +29 -26
  134. package/.agents/scripts/lib/orchestration/ticketing/transition.js +5 -5
  135. package/.agents/scripts/lib/planning-corpus.js +16 -11
  136. package/.agents/scripts/lib/preflight-runner.js +2 -2
  137. package/.agents/scripts/lib/qa/coverage-verdict.js +5 -5
  138. package/.agents/scripts/lib/single-story/confirm-merge-follow-ups.js +36 -0
  139. package/.agents/scripts/lib/single-story-sweep/protection-ctx.js +1 -1
  140. package/.agents/scripts/lib/story-adjacency.js +11 -14
  141. package/.agents/scripts/lib/story-body/story-body.js +124 -70
  142. package/.agents/scripts/lib/story-plan.js +2 -4
  143. package/.agents/scripts/lib/templates/decomposer-prompts.js +46 -45
  144. package/.agents/scripts/lib/templates/spec-author-prompts.js +47 -45
  145. package/.agents/scripts/lib/{epic-body-sections.js → ticket-body-sections.js} +26 -26
  146. package/.agents/scripts/lib/validation-evidence.js +1 -1
  147. package/.agents/scripts/lib/wave-runner/ready-set.js +6 -6
  148. package/.agents/scripts/lib/workspace-provisioner.js +1 -1
  149. package/.agents/scripts/lib/worktree/lifecycle/reap.js +5 -7
  150. package/.agents/scripts/lint-issue-body.js +71 -40
  151. package/.agents/scripts/mandrel-update-preflight.js +1 -1
  152. package/.agents/scripts/notify.js +4 -3
  153. package/.agents/scripts/plan-context.js +64 -74
  154. package/.agents/scripts/plan-persist.js +121 -280
  155. package/.agents/scripts/plan-run-epilogue.js +97 -0
  156. package/.agents/scripts/providers/github/issues.js +17 -33
  157. package/.agents/scripts/providers/github/mappers.js +0 -12
  158. package/.agents/scripts/providers/github/tickets.js +2 -5
  159. package/.agents/scripts/resolve-plan-run.js +117 -0
  160. package/.agents/scripts/signals-view.js +24 -19
  161. package/.agents/scripts/single-story-close.js +11 -14
  162. package/.agents/scripts/single-story-confirm-merge.js +39 -23
  163. package/.agents/scripts/single-story-init.js +29 -20
  164. package/.agents/scripts/stories-wave-tick.js +6 -6
  165. package/.agents/scripts/story-plan.js +26 -47
  166. package/.agents/scripts/update-ticket-state.js +6 -15
  167. package/.agents/skills/core/analyze-execution/SKILL.md +21 -18
  168. package/.agents/skills/core/idea-refinement/SKILL.md +6 -6
  169. package/.agents/skills/core/scope-triage/SKILL.md +28 -172
  170. package/.agents/skills/skills.index.json +3 -43
  171. package/.agents/starter-agentrc.json +0 -5
  172. package/.agents/templates/agent-protocol.md +9 -10
  173. package/.agents/workflows/audit-architecture.md +3 -3
  174. package/.agents/workflows/audit-clean-code.md +3 -3
  175. package/.agents/workflows/audit-dependencies.md +3 -3
  176. package/.agents/workflows/audit-devops.md +3 -3
  177. package/.agents/workflows/audit-documentation.md +5 -5
  178. package/.agents/workflows/audit-lighthouse.md +3 -3
  179. package/.agents/workflows/audit-navigability.md +3 -2
  180. package/.agents/workflows/audit-performance.md +3 -3
  181. package/.agents/workflows/audit-privacy.md +3 -3
  182. package/.agents/workflows/audit-quality.md +3 -3
  183. package/.agents/workflows/audit-security.md +3 -3
  184. package/.agents/workflows/audit-seo.md +3 -3
  185. package/.agents/workflows/audit-sre.md +3 -3
  186. package/.agents/workflows/audit-to-stories.md +20 -20
  187. package/.agents/workflows/audit-ux-ui.md +3 -3
  188. package/.agents/workflows/deliver.md +122 -174
  189. package/.agents/workflows/git-cleanup.md +3 -4
  190. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  191. package/.agents/workflows/helpers/acceptance-self-eval.md +16 -29
  192. package/.agents/workflows/helpers/code-review.md +70 -193
  193. package/.agents/workflows/helpers/{single-story-deliver-reference.md → deliver-story-reference.md} +12 -14
  194. package/.agents/workflows/helpers/{single-story-deliver.md → deliver-story.md} +113 -139
  195. package/.agents/workflows/helpers/diagnose.md +10 -10
  196. package/.agents/workflows/helpers/parallel-tooling.md +1 -1
  197. package/.agents/workflows/helpers/signals.md +16 -16
  198. package/.agents/workflows/helpers/worktree-lifecycle.md +48 -64
  199. package/.agents/workflows/mandrel-update.md +2 -1
  200. package/.agents/workflows/plan.md +112 -145
  201. package/.agents/workflows/qa-assist.md +24 -30
  202. package/.agents/workflows/qa-explore.md +29 -38
  203. package/.agents/workflows/qa-run.md +2 -2
  204. package/README.md +9 -8
  205. package/docs/CHANGELOG.md +30 -0
  206. package/lib/migrations/index.js +6 -5
  207. package/package.json +2 -2
  208. package/.agents/agents/retro.md +0 -42
  209. package/.agents/personas/architect.md +0 -113
  210. package/.agents/personas/devops-engineer.md +0 -38
  211. package/.agents/personas/engineer.md +0 -33
  212. package/.agents/personas/project-manager.md +0 -114
  213. package/.agents/personas/qa-engineer.md +0 -95
  214. package/.agents/personas/security-engineer.md +0 -111
  215. package/.agents/personas/technical-writer.md +0 -101
  216. package/.agents/schemas/dispatch-manifest.json +0 -232
  217. package/.agents/schemas/epic-spec.schema.json +0 -153
  218. package/.agents/schemas/lifecycle/slice.end.schema.json +0 -21
  219. package/.agents/schemas/lifecycle/slice.heartbeat.schema.json +0 -20
  220. package/.agents/schemas/lifecycle/slice.start.schema.json +0 -17
  221. package/.agents/scripts/acceptance-spec-reconciler.js +0 -642
  222. package/.agents/scripts/bookkeeping-reconcile.js +0 -117
  223. package/.agents/scripts/dispatcher.js +0 -295
  224. package/.agents/scripts/epic-audit-prepare.js +0 -497
  225. package/.agents/scripts/epic-audit-recheck.js +0 -274
  226. package/.agents/scripts/epic-deliver-note-intervention.js +0 -192
  227. package/.agents/scripts/epic-deliver-preflight.js +0 -462
  228. package/.agents/scripts/epic-deliver-prepare.js +0 -852
  229. package/.agents/scripts/epic-execute-record-wave.js +0 -449
  230. package/.agents/scripts/epic-plan-clarity.js +0 -211
  231. package/.agents/scripts/epic-plan-healthcheck.js +0 -581
  232. package/.agents/scripts/epic-reconcile.js +0 -625
  233. package/.agents/scripts/lib/baseline-snapshot.js +0 -979
  234. package/.agents/scripts/lib/checks/epic-merge-lock-stale.js +0 -54
  235. package/.agents/scripts/lib/checks/stale-origin-epic.js +0 -49
  236. package/.agents/scripts/lib/config/lifecycle.js +0 -40
  237. package/.agents/scripts/lib/config/preflight.js +0 -58
  238. package/.agents/scripts/lib/config/retro.js +0 -77
  239. package/.agents/scripts/lib/epic-merge-lock.js +0 -322
  240. package/.agents/scripts/lib/epic-plan-clarity.js +0 -181
  241. package/.agents/scripts/lib/epic-plan-ideation.js +0 -261
  242. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +0 -539
  243. package/.agents/scripts/lib/orchestration/deliver-route.js +0 -173
  244. package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -134
  245. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +0 -183
  246. package/.agents/scripts/lib/orchestration/epic-cleanup.js +0 -801
  247. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +0 -310
  248. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +0 -163
  249. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +0 -140
  250. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +0 -64
  251. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +0 -72
  252. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +0 -156
  253. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist.js +0 -345
  254. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +0 -41
  255. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/reconcile-spawn.js +0 -86
  256. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +0 -391
  257. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/drain.js +0 -94
  258. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +0 -236
  259. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +0 -307
  260. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +0 -117
  261. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +0 -117
  262. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +0 -621
  263. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +0 -186
  264. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +0 -50
  265. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +0 -129
  266. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +0 -103
  267. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -267
  268. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +0 -210
  269. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +0 -238
  270. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/_bullet-format.js +0 -32
  271. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/component-drift.js +0 -203
  272. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/crap-drift.js +0 -227
  273. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/maintainability-drift.js +0 -117
  274. package/.agents/scripts/lib/orchestration/epic-runner/progress-signals/stalled-worktree.js +0 -37
  275. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +0 -127
  276. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +0 -276
  277. package/.agents/scripts/lib/orchestration/epic-runner/wave-scheduler.js +0 -66
  278. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +0 -789
  279. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +0 -676
  280. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-discriminator.js +0 -389
  281. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-format.js +0 -230
  282. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +0 -361
  283. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +0 -306
  284. package/.agents/scripts/lib/orchestration/finalize/post-handoff-comment.js +0 -489
  285. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +0 -88
  286. package/.agents/scripts/lib/orchestration/lifecycle/emit-slice-lifecycle.js +0 -270
  287. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +0 -147
  288. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +0 -465
  289. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +0 -501
  290. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +0 -984
  291. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +0 -264
  292. package/.agents/scripts/lib/orchestration/lifecycle/listeners/checkpoint-pointer-writer.js +0 -284
  293. package/.agents/scripts/lib/orchestration/lifecycle/listeners/cleaner.js +0 -355
  294. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +0 -673
  295. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +0 -378
  296. package/.agents/scripts/lib/orchestration/lifecycle/listeners/intervention-recorder.js +0 -140
  297. package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +0 -144
  298. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +0 -174
  299. package/.agents/scripts/lib/orchestration/manifest-builder.js +0 -222
  300. package/.agents/scripts/lib/orchestration/plan-persist/amend.js +0 -359
  301. package/.agents/scripts/lib/orchestration/plan-persist/delivery-mode.js +0 -127
  302. package/.agents/scripts/lib/orchestration/post-merge-pipeline.js +0 -205
  303. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +0 -152
  304. package/.agents/scripts/lib/orchestration/retro/phases/checks.js +0 -94
  305. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +0 -571
  306. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +0 -450
  307. package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +0 -191
  308. package/.agents/scripts/lib/orchestration/retro-heuristics.js +0 -57
  309. package/.agents/scripts/lib/orchestration/retro-runner.js +0 -197
  310. package/.agents/scripts/lib/orchestration/spec-renderer.js +0 -447
  311. package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +0 -747
  312. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/gate-failure.js +0 -211
  313. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/pre-merge-attribution.js +0 -158
  314. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +0 -446
  315. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/regression-projection.js +0 -297
  316. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/scope-discovery.js +0 -48
  317. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution-wiring.js +0 -67
  318. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution.js +0 -161
  319. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +0 -117
  320. package/.agents/scripts/lib/orchestration/story-close/cd-out-guard.js +0 -86
  321. package/.agents/scripts/lib/orchestration/story-close/cleanup-reconciler.js +0 -147
  322. package/.agents/scripts/lib/orchestration/story-close/close-inputs.js +0 -142
  323. package/.agents/scripts/lib/orchestration/story-close/comment-bodies.js +0 -62
  324. package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +0 -658
  325. package/.agents/scripts/lib/orchestration/story-close/merge-subject.js +0 -198
  326. package/.agents/scripts/lib/orchestration/story-close/phases/branch-restore.js +0 -105
  327. package/.agents/scripts/lib/orchestration/story-close/phases/close.js +0 -222
  328. package/.agents/scripts/lib/orchestration/story-close/phases/gates.js +0 -292
  329. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +0 -270
  330. package/.agents/scripts/lib/orchestration/story-close/phases/preflight.js +0 -110
  331. package/.agents/scripts/lib/orchestration/story-close/phases/refresh.js +0 -86
  332. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked-emitter.js +0 -112
  333. package/.agents/scripts/lib/orchestration/story-close/phases/timeout-blocked.js +0 -157
  334. package/.agents/scripts/lib/orchestration/story-close/post-merge-close.js +0 -421
  335. package/.agents/scripts/lib/orchestration/story-close/pre-merge-validation.js +0 -302
  336. package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +0 -163
  337. package/.agents/scripts/lib/orchestration/story-close-recovery.js +0 -690
  338. package/.agents/scripts/lib/orchestration/wave-marker.js +0 -28
  339. package/.agents/scripts/lib/orchestration/wave-record-io.js +0 -218
  340. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +0 -145
  341. package/.agents/scripts/lib/orchestration/wave-record-projection.js +0 -212
  342. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +0 -111
  343. package/.agents/scripts/lib/presentation/manifest-builder.js +0 -239
  344. package/.agents/scripts/lib/presentation/manifest-formatter.js +0 -242
  345. package/.agents/scripts/lib/presentation/manifest-helpers.js +0 -213
  346. package/.agents/scripts/lib/presentation/manifest-persistence.js +0 -261
  347. package/.agents/scripts/lib/presentation/manifest-procedures.js +0 -55
  348. package/.agents/scripts/lib/presentation/manifest-render-waves.js +0 -306
  349. package/.agents/scripts/lib/presentation/manifest-renderer.js +0 -188
  350. package/.agents/scripts/lib/presentation/manifest-story-views.js +0 -110
  351. package/.agents/scripts/lib/push-epic-retry.js +0 -209
  352. package/.agents/scripts/lib/spec/index.js +0 -36
  353. package/.agents/scripts/lib/spec/loader.js +0 -425
  354. package/.agents/scripts/lib/spec/state.js +0 -208
  355. package/.agents/scripts/lib/story-init/blocker-validator.js +0 -68
  356. package/.agents/scripts/lib/story-init/branch-initializer.js +0 -408
  357. package/.agents/scripts/lib/story-init/context-resolver.js +0 -92
  358. package/.agents/scripts/lib/story-init/donor-precheck.js +0 -207
  359. package/.agents/scripts/lib/story-init/state-transitioner.js +0 -80
  360. package/.agents/scripts/lib/story-init/task-graph-builder.js +0 -124
  361. package/.agents/scripts/lib/story-init/transition-summary.js +0 -34
  362. package/.agents/scripts/lib/test-reserved-epic-temp-ids.js +0 -35
  363. package/.agents/scripts/lib/wave-runner/tick.js +0 -754
  364. package/.agents/scripts/lib/wave-runner/wave-runner-error.js +0 -20
  365. package/.agents/scripts/lifecycle-emit-story-dispatch.js +0 -194
  366. package/.agents/scripts/lifecycle-emit.js +0 -510
  367. package/.agents/scripts/retro-run.js +0 -218
  368. package/.agents/scripts/slice-phase.js +0 -361
  369. package/.agents/scripts/standalone-feedback-rollup.js +0 -188
  370. package/.agents/scripts/story-close.js +0 -294
  371. package/.agents/scripts/story-init.js +0 -599
  372. package/.agents/scripts/story-phase.js +0 -369
  373. package/.agents/scripts/wave-tick.js +0 -464
  374. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +0 -172
  375. package/.agents/skills/core/epic-plan-consolidate/examples.md +0 -51
  376. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +0 -441
  377. package/.agents/skills/core/epic-plan-decompose-author/examples.md +0 -47
  378. package/.agents/skills/core/epic-plan-premortem/SKILL.md +0 -146
  379. package/.agents/skills/core/epic-plan-premortem/examples.md +0 -53
  380. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +0 -383
  381. package/.agents/skills/core/epic-plan-spec-author/examples.md +0 -91
  382. package/.agents/workflows/helpers/deliver-epic-reference.md +0 -547
  383. package/.agents/workflows/helpers/deliver-epic-single.md +0 -331
  384. package/.agents/workflows/helpers/deliver-epic.md +0 -998
  385. package/.agents/workflows/helpers/deliver-stories.md +0 -450
  386. package/.agents/workflows/helpers/epic-audit.md +0 -189
  387. package/.agents/workflows/helpers/epic-deliver-story.md +0 -436
  388. package/.agents/workflows/helpers/epic-testing.md +0 -125
  389. package/.agents/workflows/helpers/plan-epic-reference.md +0 -160
  390. package/.agents/workflows/helpers/plan-epic.md +0 -353
  391. package/.agents/workflows/helpers/plan-story.md +0 -251
  392. package/.agents/workflows/helpers/scope-triage-gate.md +0 -108
  393. /package/.agents/scripts/lib/orchestration/{epic-plan-spec/phases → planning}/spec-authoring-grounding.js +0 -0
@@ -2,10 +2,12 @@
2
2
  * phases/code-review.js — Story-scope code-review phase
3
3
  * (Story #2840, Epic #2815 — Pluggable Code Review + Story-Level Review).
4
4
  *
5
- * Sits between the close-validation gate chain and the merge into
6
- * `epic/<id>` inside `runStoryCloseLocked` (locked-pipeline.js). The
7
- * configured ReviewProvider runs against the
8
- * `epic/<id>`…`story-<id>` diff. The unified `verification-results`
5
+ * Sits between the close-validation gate chain and merge in the deleted
6
+ * pre-v2 Epic close path (`runStoryCloseLocked` / `locked-pipeline.js`,
7
+ * merge target `epic/<id>`). The v2 `/deliver` path
8
+ * (`single-story-close.js`) reviews `main`…`story-<id>` instead. The
9
+ * configured ReviewProvider runs against the supplied base…head diff. The
10
+ * unified `verification-results`
9
11
  * structured comment is posted to the Story issue (default
10
12
  * `commentTargetId === ticketId` inside `runCodeReview`). Outcomes:
11
13
  *
@@ -39,7 +41,7 @@ import {
39
41
  import { gitSpawn } from '../../../git-utils.js';
40
42
  import { Logger } from '../../../Logger.js';
41
43
  import { runCodeReview } from '../../code-review.js';
42
- import { emitBlockedCloseResult } from '../merge-runner.js';
44
+ import { emitBlockedCloseResult } from '../emit-blocked.js';
43
45
 
44
46
  /**
45
47
  * The review depth the Story-scope local-lens pass runs at. Shift-left
@@ -282,17 +284,18 @@ export async function runStoryReviewCore({
282
284
  }
283
285
 
284
286
  /**
285
- * Run a Story-scope code review against the `epic/<id>`…`story-<id>`
286
- * diff and post the structured `code-review` comment to the Story
287
- * issue. Returns `{ blocked }` where `blocked` is either `null`
288
- * (caller proceeds to merge) or the blocked-envelope (caller returns
289
- * it verbatim and the CLI exits 1).
287
+ * Run a Story-scope code review against the supplied base…head diff
288
+ * (v2: `main`…`story-<id>` via `single-story-close.js`; pre-v2 Epic
289
+ * close: `epic/<id>`…`story-<id>`) and post the structured
290
+ * `code-review` comment to the Story issue. Returns `{ blocked }` where
291
+ * `blocked` is either `null` (caller proceeds to open/merge the PR) or the
292
+ * blocked-envelope (caller returns it verbatim and the CLI exits 1).
290
293
  *
291
294
  * The optional `planningRisk` envelope (Story #3940) is the parent Epic's
292
295
  * judged risk, read best-effort off the `epic-plan-state` checkpoint by the
293
296
  * locked pipeline. It is forwarded into `runCodeReview` so the review depth is
294
- * resolved from BOTH the Epic-judged risk and the Story's own
295
- * `epic/<id>...story-<id>` changed-file count — a small Story under a
297
+ * resolved from BOTH the parent Epic's judged risk (pre-v2) and the Story's own
298
+ * base…head changed-file count — a small Story under a
296
299
  * high-risk Epic still earns `deep`, a small Story under a low-risk Epic gets
297
300
  * `light`, and an absent envelope resolves `standard` (today's behaviour).
298
301
  * Depth is input-only: it never changes `{ blocked }` or the posted comment.
@@ -0,0 +1,237 @@
1
+ /**
2
+ * story-follow-ups.js — capture actionable follow-ups from a landed Story.
3
+ *
4
+ * Replaces the unwired Epic retro as the default closeout for v2: after a
5
+ * Story merges, read its standalone `signals.ndjson` friction stream, compose
6
+ * routed proposals, auto-file follow-up issues (when enabled), and upsert a
7
+ * structured `follow-ups` comment on the Story.
8
+ *
9
+ * @module lib/orchestration/story-follow-ups
10
+ */
11
+
12
+ import { graduateRetroProposals } from '../feedback-loop/retro-proposals-graduator.js';
13
+ import { DEFAULT_FRAMEWORK_REPO } from '../github/framework-repo.js';
14
+ import { Logger } from '../Logger.js';
15
+ import { forEachLine } from '../observability/signals-writer.js';
16
+ import { composeRoutedProposals } from './retro-proposals.js';
17
+ import { upsertStructuredComment } from './ticketing.js';
18
+
19
+ export const FOLLOW_UPS_COMMENT_TYPE = 'follow-ups';
20
+
21
+ /**
22
+ * @param {object} [config]
23
+ * @returns {{ frameworkRepo: string, consumerRepo: string, currentRepo: { owner: string, repo: string } }}
24
+ */
25
+ export function resolveFollowUpRepos(config) {
26
+ const owner =
27
+ typeof config?.github?.owner === 'string' ? config.github.owner.trim() : '';
28
+ const repo =
29
+ typeof config?.github?.repo === 'string' ? config.github.repo.trim() : '';
30
+ const consumerRepo =
31
+ owner && repo ? `${owner}/${repo}` : DEFAULT_FRAMEWORK_REPO;
32
+ const frameworkRepo =
33
+ typeof config?.github?.frameworkRepo === 'string' &&
34
+ config.github.frameworkRepo.trim()
35
+ ? config.github.frameworkRepo.trim()
36
+ : DEFAULT_FRAMEWORK_REPO;
37
+ const [cOwner, cRepo] = consumerRepo.split('/');
38
+ return {
39
+ frameworkRepo,
40
+ consumerRepo,
41
+ currentRepo: {
42
+ owner: cOwner || 'unknown',
43
+ repo: cRepo || 'unknown',
44
+ },
45
+ };
46
+ }
47
+
48
+ /**
49
+ * @param {number} storyId
50
+ * @param {object} [config]
51
+ * @returns {Promise<Array<{ category: string, source: 'framework'|'consumer' }>>}
52
+ */
53
+ export async function gatherStoryFrictionSignals(storyId, config) {
54
+ const signals = [];
55
+ await forEachLine(
56
+ null,
57
+ storyId,
58
+ (parsed) => {
59
+ if (!parsed || typeof parsed !== 'object') return;
60
+ const kind = parsed.kind;
61
+ if (kind !== 'friction' && kind !== undefined) {
62
+ // Prefer friction records; also accept category-bearing rows.
63
+ }
64
+ const category =
65
+ typeof parsed.category === 'string' ? parsed.category.trim() : '';
66
+ if (!category) return;
67
+ const source = parsed.source === 'framework' ? 'framework' : 'consumer';
68
+ signals.push({ category, source });
69
+ },
70
+ config,
71
+ );
72
+ return signals;
73
+ }
74
+
75
+ /**
76
+ * @param {{
77
+ * storyId: number,
78
+ * proposals: object,
79
+ * graduated: object,
80
+ * }} args
81
+ * @returns {string}
82
+ */
83
+ export function buildFollowUpsCommentBody({ storyId, proposals, graduated }) {
84
+ const filed = Array.isArray(graduated?.filed) ? graduated.filed : [];
85
+ const framework = proposals?.framework ?? [];
86
+ const consumer = proposals?.consumer ?? [];
87
+ const discarded = proposals?.discarded ?? [];
88
+ const lines = [
89
+ '### follow-ups',
90
+ '',
91
+ `Actionable follow-ups captured from Story #${storyId} after merge.`,
92
+ '',
93
+ ];
94
+ if (filed.length > 0) {
95
+ lines.push('**Filed**');
96
+ for (const item of filed) {
97
+ lines.push(
98
+ `- ${item.source}: ${item.title}${item.url ? ` — ${item.url}` : ''}`,
99
+ );
100
+ }
101
+ lines.push('');
102
+ }
103
+ if (framework.length + consumer.length > 0 && filed.length === 0) {
104
+ lines.push('**Actionable (not auto-filed)**');
105
+ for (const item of [...framework, ...consumer]) {
106
+ lines.push(`- ${item.source}: ${item.title}`);
107
+ lines.push('');
108
+ lines.push('```bash');
109
+ lines.push(item.command);
110
+ lines.push('```');
111
+ }
112
+ lines.push('');
113
+ }
114
+ if (discarded.length > 0) {
115
+ lines.push('**Single-occurrence (not filed)**');
116
+ for (const item of discarded) {
117
+ lines.push(`- ${item.source}: \`${item.category}\` ×${item.occurrences}`);
118
+ }
119
+ lines.push('');
120
+ }
121
+ if (
122
+ filed.length === 0 &&
123
+ framework.length === 0 &&
124
+ consumer.length === 0 &&
125
+ discarded.length === 0
126
+ ) {
127
+ lines.push('_No friction signals — nothing to follow up._');
128
+ lines.push('');
129
+ }
130
+ lines.push('```json');
131
+ lines.push(
132
+ JSON.stringify(
133
+ {
134
+ storyId,
135
+ framework: framework.map((i) => i.category),
136
+ consumer: consumer.map((i) => i.category),
137
+ discarded: discarded.map((i) => i.category),
138
+ filed: filed.map((i) => ({
139
+ category: i.category,
140
+ url: i.url ?? null,
141
+ })),
142
+ },
143
+ null,
144
+ 2,
145
+ ),
146
+ );
147
+ lines.push('```');
148
+ return lines.join('\n');
149
+ }
150
+
151
+ /**
152
+ * Capture and persist Story follow-ups. Never throws — close must not fail
153
+ * because follow-up filing flaked.
154
+ *
155
+ * @param {object} args
156
+ * @param {number} args.storyId
157
+ * @param {object} args.provider
158
+ * @param {object} [args.config]
159
+ * @param {string} [args.cwd]
160
+ * @param {(tag: string, msg: string) => void} [args.progress]
161
+ * @returns {Promise<object>}
162
+ */
163
+ /**
164
+ * Capture follow-ups only when merge confirm landed (`action === 'done'`).
165
+ * One-liner seam for the confirm-merge CLI.
166
+ */
167
+ export async function captureFollowUpsAfterConfirm(confirmation, ctx) {
168
+ if (confirmation?.action !== 'done') return null;
169
+ return captureStoryFollowUps(ctx);
170
+ }
171
+
172
+ export async function captureStoryFollowUps({
173
+ storyId,
174
+ provider,
175
+ config,
176
+ cwd,
177
+ progress,
178
+ }) {
179
+ const sid = Number(storyId);
180
+ if (!Number.isInteger(sid) || sid <= 0) {
181
+ return { ok: false, reason: 'invalid-story-id' };
182
+ }
183
+ try {
184
+ const signals = await gatherStoryFrictionSignals(sid, config);
185
+ const repos = resolveFollowUpRepos(config);
186
+ const proposals = composeRoutedProposals({
187
+ anchorId: sid,
188
+ anchorKind: 'story',
189
+ frameworkRepo: repos.frameworkRepo,
190
+ consumerRepo: repos.consumerRepo,
191
+ signals,
192
+ unresolvedBlockedEvents: [],
193
+ });
194
+ const graduated = await graduateRetroProposals({
195
+ epicId: sid,
196
+ provider,
197
+ config,
198
+ currentRepo: repos.currentRepo,
199
+ frameworkRepo: (() => {
200
+ const [owner, repo] = repos.frameworkRepo.split('/');
201
+ return { owner, repo };
202
+ })(),
203
+ routedProposals: proposals,
204
+ cwd,
205
+ });
206
+ const body = buildFollowUpsCommentBody({
207
+ storyId: sid,
208
+ proposals,
209
+ graduated,
210
+ });
211
+ await upsertStructuredComment(provider, sid, FOLLOW_UPS_COMMENT_TYPE, body);
212
+ progress?.(
213
+ 'FOLLOW-UPS',
214
+ `Captured follow-ups for Story #${sid} (filed=${graduated.filed?.length ?? 0}).`,
215
+ );
216
+ return {
217
+ ok: true,
218
+ storyId: sid,
219
+ proposals,
220
+ graduated,
221
+ signalCount: signals.length,
222
+ };
223
+ } catch (err) {
224
+ Logger.warn(
225
+ `[story-follow-ups] capture failed for #${sid}: ${err?.message ?? err}`,
226
+ );
227
+ progress?.(
228
+ 'FOLLOW-UPS',
229
+ `⚠️ Follow-up capture failed (close continues): ${err?.message ?? err}`,
230
+ );
231
+ return {
232
+ ok: false,
233
+ reason: 'capture-failed',
234
+ error: String(err?.message ?? err),
235
+ };
236
+ }
237
+ }
@@ -0,0 +1,47 @@
1
+ import { Logger } from '../Logger.js';
2
+ import { AGENT_LABELS } from '../label-constants.js';
3
+ import { upsertStructuredComment } from './ticketing.js';
4
+
5
+ /**
6
+ * Fail closed when the repository remote cannot be verified. The Story is
7
+ * blocked before lease/branch/worktree mutation so a host that misses the
8
+ * result envelope cannot strand an executing Story.
9
+ */
10
+ export async function handleRemoteVerificationFailure({
11
+ provider,
12
+ storyId,
13
+ remote,
14
+ dryRun = false,
15
+ }) {
16
+ if (remote?.remoteVerified) return;
17
+ const message =
18
+ `[single-story-init] remote verification failed for Story #${storyId}: ` +
19
+ `${remote?.detail ?? 'origin is unavailable'}`;
20
+ if (!dryRun) {
21
+ try {
22
+ await upsertStructuredComment(
23
+ provider,
24
+ storyId,
25
+ 'friction',
26
+ `### Remote verification blocked delivery\n\n${message}`,
27
+ );
28
+ } catch (err) {
29
+ Logger.warn(
30
+ `[single-story-init] failed to post remote-verification friction: ${err?.message ?? err}`,
31
+ );
32
+ }
33
+ try {
34
+ await provider.updateTicket(storyId, {
35
+ labels: {
36
+ add: [AGENT_LABELS.BLOCKED],
37
+ remove: [AGENT_LABELS.READY, AGENT_LABELS.EXECUTING],
38
+ },
39
+ });
40
+ } catch (err) {
41
+ Logger.warn(
42
+ `[single-story-init] failed to block Story after remote verification: ${err?.message ?? err}`,
43
+ );
44
+ }
45
+ }
46
+ throw new Error(message);
47
+ }
@@ -0,0 +1,48 @@
1
+ import { parseFencedJsonComment } from './structured-comment-parser.js';
2
+ import { findStructuredComment } from './ticketing.js';
3
+
4
+ /**
5
+ * Read the v2 Story planning checkpoint. Missing/malformed comments degrade
6
+ * to null so unplanned Stories still receive the neutral review posture.
7
+ */
8
+ export async function readStoryPlanState({
9
+ provider,
10
+ storyId,
11
+ findCommentFn = findStructuredComment,
12
+ }) {
13
+ const comment = await findCommentFn(
14
+ provider,
15
+ Number(storyId),
16
+ 'story-plan-state',
17
+ );
18
+ const state = parseFencedJsonComment(comment);
19
+ return state && typeof state === 'object' ? state : null;
20
+ }
21
+
22
+ export async function readStoryPlanningRisk(args) {
23
+ const state = await readStoryPlanState(args);
24
+ return state?.planningRisk ?? null;
25
+ }
26
+
27
+ export async function readStoryPlanningRiskSafe(args) {
28
+ try {
29
+ return await readStoryPlanningRisk(args);
30
+ } catch {
31
+ return null;
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Prefer an explicit `planningRisk` override; otherwise load the Story
37
+ * checkpoint. Callers that omit the field (or pass `undefined`) get the
38
+ * persisted plan risk; callers that pass `null` keep the neutral posture.
39
+ */
40
+ export async function resolveStoryPlanningRisk({
41
+ provider,
42
+ storyId,
43
+ planningRisk,
44
+ findCommentFn,
45
+ }) {
46
+ if (planningRisk !== undefined) return planningRisk;
47
+ return readStoryPlanningRiskSafe({ provider, storyId, findCommentFn });
48
+ }
@@ -13,9 +13,9 @@
13
13
  *
14
14
  * The renderer survives because its `{ body, payload }` output still feeds
15
15
  * two non-comment contracts: the `renderedBody` markdown the `/deliver`
16
- * and `single-story-deliver` CLIs (`story-phase.js`, the inline `story-init.js` prepare step)
17
- * relay to chat so the operator sees the phase table inline, and the snapshot
18
- * payload returned in those CLIs' JSON envelopes. `upsertStoryRunProgress`
16
+ * workflow (`helpers/deliver-story.md`, `story-phase.js`) relays to chat so
17
+ * the operator sees the phase table inline, and the snapshot payload returned
18
+ * in those CLIs' JSON envelopes. `upsertStoryRunProgress`
19
19
  * therefore renders-only: it computes the body/payload and (optionally) mirrors
20
20
  * a low-severity webhook event, but writes no GitHub comment.
21
21
  *
@@ -2,7 +2,7 @@
2
2
  * structured-comment-parser.js — shared parser for fenced-JSON structured
3
3
  * comments.
4
4
  *
5
- * Several callers (epic-runner Checkpointer, ProgressReporter
5
+ * Several callers (the deleted epic-runner Checkpointer/ProgressReporter,
6
6
  * `parseStoryRunProgressComment` / `parsePhaseTimingsComment`, wave-gate's
7
7
  * local `extractJsonBlock`) need to extract the `{...}` payload from the
8
8
  * fenced ```json``` block of a structured comment body. They had each open-
@@ -24,16 +24,14 @@
24
24
  * name at least one path-shaped token so vague verbs ("clean up",
25
25
  * "refactor") can't slip through.
26
26
  *
27
- * `body.changes` items may be either:
28
- * 1. A string bullet (legacy shape, e.g. `"src/foo.ts: extract handler"`).
29
- * 2. An object `{ path: string, assumption: enum }` (Story #2636 shape).
27
+ * `body.changes` items must be object-form `{ path: string, assumption: enum }`
28
+ * entries (Story #2636 shape). Plain string bullets are rejected at parse
29
+ * time and by this validator.
30
30
  *
31
31
  * Object-form items must declare an `assumption` ∈ `creates |
32
32
  * refactors-existing | exists | deletes`. The optional `body.references`
33
33
  * array uses the same object shape and is the home for paths the Story
34
34
  * reads but does not modify (test fixtures, sibling modules, etc.).
35
- * String-form `changes` items remain legal so legacy plans keep parsing,
36
- * but they emit a deprecation signal via `validateStoryFileAssumptions`.
37
35
  *
38
36
  * `body.verify` entries must either name a testing tier in parentheses
39
37
  * drawn from `VERIFY_TIER_VALUES` (e.g. `npm run test (unit)`) or be the
@@ -248,25 +246,17 @@ function collectChangesErrors(prefix, rawChanges) {
248
246
  return [`${prefix}: body.changes must list at least one bullet.`];
249
247
  }
250
248
  const errors = [];
251
- // An entry "names a path" when it is either a path-shaped bullet
252
- // string OR an object-form entry that passed the assumption schema.
253
- const namesPath = (c) => {
254
- if (typeof c === 'string') return bulletNamesPath(c);
255
- return isObjectPathEntry(c);
256
- };
249
+ const namesPath = (c) => isObjectPathEntry(c);
257
250
  if (changes.every((c) => !namesPath(c))) {
258
251
  errors.push(
259
- `${prefix}: body.changes bullets name no path-shaped token. Use "<path>: <verb> <object>" — e.g. "src/components/Foo.tsx: extract handleSubmit". Object-form entries may also declare { path, assumption } directly.`,
252
+ `${prefix}: body.changes must declare at least one { path, assumption } object entry.`,
260
253
  );
261
254
  }
262
255
  for (const entry of changes) {
263
256
  if (typeof entry === 'string') {
264
- const verb = vagueVerbWithoutTarget(entry);
265
- if (verb) {
266
- errors.push(
267
- `${prefix}: body.changes bullet uses vague verb "${verb}" without a named target: "${entry}".`,
268
- );
269
- }
257
+ errors.push(
258
+ `${prefix}: body.changes entry must be a { path, assumption } object; plain string bullets are no longer accepted: "${entry}".`,
259
+ );
270
260
  continue;
271
261
  }
272
262
  if (isMalformedObjectPathEntry(entry)) {
@@ -10,8 +10,7 @@ import { computeStoryReachability } from './story-reachability.js';
10
10
  *
11
11
  * The decomposer emits `body` as the canonical serialized **string**, but
12
12
  * the conflict passes (`indexConsumers`, `indexAssumptionEntries`,
13
- * `computeMissingBddScaffoldFindings`, the sibling-create scan in
14
- * `computeRegistryFindings`, and the legacy-bullet branch of
13
+ * `computeMissingBddScaffoldFindings`, and the producer path scan in
15
14
  * `collectStoryProducerPaths`) historically read `story.body` only when it
16
15
  * was already an object — so on the production string shape the
17
16
  * `implicit-cross-story-dep`, `fan-out`, registry, and `missing-bdd-scaffold`
@@ -144,71 +143,26 @@ const WRITE_IMPLYING_ASSUMPTIONS = Object.freeze(
144
143
  new Set(['creates', 'refactors-existing', 'deletes']),
145
144
  );
146
145
 
147
- /**
148
- * Extract the path-shaped head from a single legacy string-form
149
- * `body.changes` bullet.
150
- *
151
- * Conventional shape is `"<path>: <verb> <object>"`; we slice on the first
152
- * colon and return the head when it contains a slash or a dot, otherwise
153
- * `null`. Mirrors the heuristic in `ticket-validator-sizing.js` so producer
154
- * extraction and `fileCount` accounting agree on what counts as a path.
155
- *
156
- * Object-form entries (`{ path, assumption }`) are *not* handled here — they
157
- * are extracted via `collectStoryAssumptionEntries` in `indexProducers`. This
158
- * helper only understands the legacy string shape and returns `null` for any
159
- * non-string input.
160
- */
161
- function extractChangeBulletPath(bullet) {
162
- if (typeof bullet !== 'string') return null;
163
- const colonIdx = bullet.indexOf(':');
164
- if (colonIdx <= 0) return null;
165
- const head = bullet.slice(0, colonIdx).trim();
166
- if (!/[\\/.]/.test(head)) return null;
167
- return head;
168
- }
169
-
170
146
  /**
171
147
  * Collect the write-implying producer paths a single Story declares.
172
148
  *
173
- * Two shapes are honoured so the modern object-form `changes` contract and
174
- * the legacy string-bullet contract both feed the producer index:
175
- *
176
- * - **Object form** (`{ path, assumption }`) — reuses
177
- * `collectStoryAssumptionEntries` (the same extractor the Phase-8
178
- * file-assumption gate uses), then keeps only `changes`-sourced entries
179
- * whose assumption writes the path (`creates` / `refactors-existing` /
180
- * `deletes`). `exists` reads and `references` entries are dropped.
181
- * - **Legacy string bullets** (`"<path>: <verb> ..."`) — slice the
182
- * colon-head via `extractChangeBulletPath`. Legacy bullets carry no
183
- * assumption, so they are treated as writes (preserving pre-migration
184
- * behaviour).
149
+ * Uses object-form `{ path, assumption }` entries via
150
+ * `collectStoryAssumptionEntries` (the same extractor the Phase-8
151
+ * file-assumption gate uses), keeping only `changes`-sourced entries
152
+ * whose assumption writes the path (`creates` / `refactors-existing` /
153
+ * `deletes`). `exists` reads and `references` entries are dropped.
185
154
  *
186
155
  * Returns a de-duplicated array of producer paths for the Story.
187
156
  */
188
157
  function collectStoryProducerPaths(story) {
189
158
  const paths = new Set();
190
159
 
191
- // Object-form entries via the shared extractor. Only `changes`-sourced
192
- // write-implying assumptions count as producers.
193
160
  for (const entry of collectStoryAssumptionEntries(story)) {
194
161
  if (entry.source !== 'changes') continue;
195
162
  if (!WRITE_IMPLYING_ASSUMPTIONS.has(entry.assumption)) continue;
196
163
  paths.add(entry.path);
197
164
  }
198
165
 
199
- // Legacy string bullets — extract the colon-head path. Skip non-string
200
- // entries (object-form already handled above).
201
- const body = story?.body;
202
- const changes =
203
- body && typeof body === 'object' && Array.isArray(body.changes)
204
- ? body.changes
205
- : [];
206
- for (const bullet of changes) {
207
- if (typeof bullet !== 'string') continue;
208
- const path = extractChangeBulletPath(bullet);
209
- if (path) paths.add(path);
210
- }
211
-
212
166
  return Array.from(paths);
213
167
  }
214
168
 
@@ -223,11 +177,9 @@ function storySlugOf(story) {
223
177
 
224
178
  /**
225
179
  * Build the producers index — `Map<path, Array<{storySlug, taskSlug}>>` —
226
- * by walking every Story's declared writes. Both object-form
227
- * `{ path, assumption }` entries and legacy `"<path>: <verb> ..."` string
228
- * bullets are honoured via `collectStoryProducerPaths`; only write-implying
229
- * assumptions (and legacy bullets, which carry no assumption) count as
230
- * producers.
180
+ * by walking every Story's declared writes. Only object-form
181
+ * `{ path, assumption }` entries count as producers via
182
+ * `collectStoryProducerPaths`; only write-implying assumptions count.
231
183
  *
232
184
  * `taskSlug` is retained in the entry shape for finding/render
233
185
  * compatibility; in the 2-tier model it carries the Story's own slug since
@@ -519,9 +471,8 @@ function computeRegistryFindings({
519
471
  existing.push(entry);
520
472
  perStory.set(entry.storySlug, existing);
521
473
  }
522
- // (a) direct registry edits — accept both legacy string-form producers
523
- // (from `indexProducers`) and modern object-form `{ path, assumption }`
524
- // entries (from `indexAssumptionEntries`).
474
+ // (a) direct registry edits — object-form `{ path, assumption }` entries
475
+ // from `indexAssumptionEntries` (and the producer index built from them).
525
476
  for (const [path, entries] of producers.entries()) {
526
477
  if (!isRegistryPath(path, patterns)) continue;
527
478
  for (const e of entries) {
@@ -778,7 +729,6 @@ export function renderHardConflictError(finding) {
778
729
 
779
730
  // Internal helpers exposed for unit tests; not part of the public surface.
780
731
  export const _internal = {
781
- extractChangeBulletPath,
782
732
  collectStoryProducerPaths,
783
733
  WRITE_IMPLYING_ASSUMPTIONS,
784
734
  indexProducers,