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
@@ -1,441 +0,0 @@
1
- ---
2
- name: epic-plan-decompose-author
3
- description: >-
4
- Author the Story ticket JSON for an Epic from the decomposer
5
- authoring context emitted by `plan-context.js --epic <Epic_ID>`. Use
6
- during Phase 8 of `/plan` when the host LLM needs to write the ticket
7
- array before `plan-persist.js` validates and persists it.
8
- allowed_tools:
9
- - Read
10
- - Write
11
- - Bash
12
- ---
13
-
14
- # epic-plan-decompose-author
15
-
16
- ## Policy Capsule
17
-
18
- - Run only after `plan-context.js --epic <Epic_ID>` has written `temp/epic-<Epic_ID>/decomposer-context.json`; fail loudly if the file is missing.
19
- - Emit exactly one artifact: `temp/epic-<Epic_ID>/tickets.json` (a JSON array). Do not write anywhere else, and never call the GitHub API from this Skill — persistence belongs to the script.
20
- - Output is JSON only — no prose, no Markdown fence. The downstream validator (`lib/orchestration/ticket-validator.js`) is the authoritative gate.
21
- - **Re-emit rule (amend, don't regenerate — Story #4431).** On a re-emit — the validator rejecting the draft, or a Phase 8.3/8.4/8.5 critic flagging specific Stories — apply **targeted edits** to the existing `temp/epic-<Epic_ID>/tickets.json`, fixing only the rejected or flagged Stories, rather than re-authoring the whole array from scratch. `helpers/plan-epic.md` bounds each critic's feedback to **one refinement pass** — apply the edit and re-run the downstream step once; do not loop.
22
- - Treat **`maxTickets`** from the context envelope as a **reviewability budget**, not a hard authoring cap (Story #2798). Merge narrow, single-module Stories into their capability first; if the plan genuinely needs more, emit the full plan and add a compact `over_budget_rationale` note inside the first Story's `## Goal` section explaining why the plan exceeds the budget. Operator persistence then requires the explicit `--allow-over-budget` override on `plan-persist.js`; without it the persist step rejects the over-budget array. Never truncate the JSON array to fit.
23
- - Honour the 2-tier hierarchy: every ticket is a **Story** attached directly to the Epic. Stories carry the implementation scope inline; no Feature and no lower ticket tier exists. Thematic grouping is prose in the Epic body / Tech Spec, never a ticket.
24
- - **Decompose at deliverable granularity, not module/task level.** A Story is a capability slice a frontier model delivers and self-verifies in one pass — a shippable slice a reviewer would accept as a single PR — not a single module or file. See the STORY SIZING section for the full guidance and the single-consumer merge rule.
25
- - Every ticket carries `type::story` and `persona::*` labels. Every Story ticket object MUST carry top-level `acceptance: string[]` and `verify: string[]` arrays (read by `hasInlineAcceptanceAndVerify` in the validator) and `body` MUST be a **string** produced by `serialize()` from `lib/story-body/story-body.js` — an object body causes `createOp` in `epic-spec-reconciler-ops.js` to throw `StoryBodyParseError` (Story #3302), and is also silently discarded by `composeStoryBody` in the GitHub provider, producing an empty issue body.
26
- - **New-File Contract**: any path referenced in `goal`, `acceptance`, or `verify` that does not exist on `main` MUST appear in the Story's `changes[]` with `assumption: "creates"`; otherwise the freshness validator rejects the decompose.
27
- - Acceptance items MUST be **observable from outside the agent** (command exits 0, file exists, snapshot matches, testid resolves). Items like "verify by reading the diff" or "looks good" are forbidden — push them into `verify` commands instead.
28
- - Acceptance MUST NOT prescribe a commit subject starting with a non-Conventional-Commits prefix; the literal `baseline-refresh:` leading token is forbidden (use a body trailer instead — see Epic #2501).
29
- - A legitimately broad Story (files > `hardFiles`) MUST declare `wide` with a one-line reason (encoded in the serialized body string via the `<!-- meta -->` comment) to lift the `hardFiles` rejection; lead the sizing decision with cohesion, not count. UI-touching Stories MUST end `changes` with a `data-testid invariance:` or `data-testid changes: <old> -> <new>` declaration.
30
- - A Story's `depends_on` references only **sibling Stories within the same Epic**. Apply the cross-cutting-config-file rule (sequential `depends_on` or a late-wave wiring Story) whenever multiple Stories edit a shared root config file.
31
- - **Authoring-contract altitude (Epic #4131 F8).** `acceptance[]` and `verify[]` are the Story's **binding contract** — the executor MUST satisfy them exactly, and they are the only definition of "done." `changes[]` and `references[]` are an **advisory implementation sketch**: a best-effort prediction of which files the work touches that the executor MAY revise when the codebase tells a different story. Author `acceptance[]`/`verify[]` so they capture the outcome independently of any particular file layout — never bake an incidental implementation detail into them that the advisory sketch is free to change. This does **not** weaken the file-assumption gate: `changes[]` paths are still validated structurally against the base branch (a `creates` against an existing path still fails), the New-File Contract still holds, and the executor's revised approach stays bounded by the inviolable `acceptance[]`/`verify[]` contract and `rules/security-baseline.md`.
32
- - **Navigate-don't-deep-link acceptance standard (Epic #4131 F5).** For any Story whose acceptance describes a **signed-in** (authenticated) scenario reaching a feature surface, author the acceptance so the persona starts from their authenticated home and **reaches the feature through navigation** (clicking a nav door, menu item, or link the UI exposes) — never by asserting against a hardcoded deep-link URL. A scenario that drops the user straight onto `/some/feature/path` proves the page renders but not that the feature is reachable, masking orphaned surfaces with no nav owner. Phrase signed-in acceptance as "from the signed-in home, the persona navigates to … and sees …", not "loading `/feature/path` shows the feature."
33
-
34
- ## Role
35
-
36
- Senior Project Manager + Orchestrator. The Skill's job is to take the
37
- sectioned Epic body (whose managed sections carry the folded Tech Spec and
38
- Acceptance Table — Story #4324) and emit a flat Story backlog the
39
- orchestrator can execute autonomously.
40
-
41
- ## When to use
42
-
43
- `/plan` Phase 8, immediately after
44
- `plan-context.js --epic <Epic_ID>` writes
45
- `temp/epic-<Epic_ID>/decomposer-context.json`. The Skill replaces the
46
- inline "Author the Ticket Array" step in the legacy workflow body —
47
- the caller dispatches this Skill via the `Skill` tool, supplies the Epic
48
- ID, and on completion has `temp/epic-<Epic_ID>/tickets.json` ready for
49
- the persist + validate half of the script.
50
-
51
- ## Inputs
52
-
53
- The dispatcher passes the Epic ID as the Skill argument. The Skill itself
54
- reads:
55
-
56
- - `temp/epic-<Epic_ID>/decomposer-context.json` — produced by
57
- `node .agents/scripts/plan-context.js --epic <Epic_ID>`.
58
- Fields:
59
- - `epic.id`, `epic.title`
60
- - `epicBody` — the sectioned Epic body. It carries everything the
61
- decomposer needs in one document: the `## User Stories` section
62
- (User-Story extraction), the folded Tech Spec sections
63
- (`## Delivery Slicing` onward — module boundary + dependency-DAG
64
- extraction), and the `## Acceptance Table` AC-ID table. There is no
65
- separate `techSpec` envelope key (Story #4324).
66
- - `heuristics[]` — risk heuristics surfaced from
67
- `agentSettings.planning.riskHeuristics`. Apply each one against the
68
- Stories you are emitting; flag matches via `risk::high` labels.
69
- - `maxTickets` — reviewability budget; a framework constant
70
- (`LIMITS_DEFAULTS.maxTickets` in `.agents/scripts/lib/config/limits.js`,
71
- not operator-configurable — Story #2798, Story #4163). Default: stay
72
- under. When the plan genuinely needs more, emit the full plan with
73
- an `over_budget_rationale` and rely on the operator's
74
- `--allow-over-budget` override at persist time. The script logs the
75
- resolved value to stderr.
76
- - `contextMode` — `"full"` or `"summary"`. When `"summary"`, work
77
- from the `bodySummary` fields rather than re-fetching the bodies.
78
-
79
- - `systemPrompt` — the **authoritative, fully-rendered decomposer system
80
- prompt** (Story #4162). It is produced by `renderDecomposerSystemPrompt`
81
- in
82
- [`decomposer-prompts.js`](../../../scripts/lib/templates/decomposer-prompts.js),
83
- the single source of the prompt body, with `maxTickets`,
84
- `maxTokenBudget`, and the sizing thresholds already interpolated. Apply
85
- **this** string as your system prompt — this SKILL deliberately does NOT
86
- embed a second verbatim copy of the prompt body, so the two surfaces
87
- cannot drift. The sections below are authoring guidance that complements
88
- the rendered prompt; they are not a replacement copy of it.
89
-
90
- ## Outputs
91
-
92
- - `temp/epic-<Epic_ID>/tickets.json` — JSON array of Story
93
- objects conforming to the schema in this Skill's body.
94
-
95
- The file MUST exist before the Skill returns. The caller will then run
96
- `node .agents/scripts/plan-persist.js --epic <Epic_ID> --tickets
97
- temp/epic-<Epic_ID>/tickets.json`, which validates the array, persists
98
- the hierarchy as GitHub issues, and transitions the Epic to
99
- `agent::ready`. The script's validator is the final gate — author for
100
- its rules, not for "looks right."
101
-
102
- ## Procedure
103
-
104
- ### Step 1 — Load the context
105
-
106
- Read `temp/epic-<Epic_ID>/decomposer-context.json` with the `Read` tool.
107
- Pin three values explicitly before writing any tickets:
108
-
109
- 1. `maxTickets` — your reviewability budget. Merge narrow slices into
110
- capability Stories rather than spilling over the budget; if the plan
111
- genuinely needs more, emit the full plan with an
112
- `over_budget_rationale` (Story #2798).
113
- 2. `contextMode` — if `"summary"`, the body strings are bounded; trust
114
- them, but keep Tasks more conservative because the upstream context
115
- is partial.
116
- 3. `heuristics[]` — render the active risk heuristics in front of you
117
- so the planning persona can mention them as Stories are emitted.
118
-
119
- ### Step 2 — Decompose against the rendered system prompt
120
-
121
- Apply the fully-rendered decomposer system prompt — the `systemPrompt`
122
- field of the loaded context envelope, produced by
123
- [`decomposer-prompts.js`](../../../scripts/lib/templates/decomposer-prompts.js)
124
- — to the sectioned Epic body (`epicBody`). That rendered string is the authoritative
125
- prompt body (with `maxTickets`, `maxTokenBudget`, and the sizing thresholds
126
- already interpolated); the authoring-guidance sections below complement it
127
- without restating it. Emit JSON only (no prose, no Markdown fence). The
128
- downstream validator in
129
- [`lib/orchestration/ticket-validator.js`](../../../scripts/lib/orchestration/ticket-validator.js)
130
- will reject anything off-shape. Merge narrow, single-module slices into
131
- their capability first; emit one Story per capability slice a frontier
132
- model can deliver and self-verify in one pass.
133
-
134
- ### Step 3 — Write the file
135
-
136
- Write the final JSON array to `temp/epic-<Epic_ID>/tickets.json` with
137
- the `Write` tool. Do not pretty-print past 2-space indent — the file is
138
- machine-consumed.
139
-
140
- ### Step 4 — Hand back to `/plan`
141
-
142
- Return control. The caller invokes
143
- `node .agents/scripts/plan-persist.js --epic <Epic_ID> --tickets
144
- temp/epic-<Epic_ID>/tickets.json`, which validates, persists, and flips
145
- the Epic to `agent::ready`.
146
-
147
- ## Decomposer system prompt — single-sourced (Story #4162)
148
-
149
- The authoritative decomposer system-prompt **body** is single-sourced in
150
- [`decomposer-prompts.js`](../../../scripts/lib/templates/decomposer-prompts.js)
151
- (`renderDecomposerSystemPrompt`) and delivered to you fully rendered in the
152
- `systemPrompt` field of `temp/epic-<Epic_ID>/decomposer-context.json` — with
153
- `maxTickets`, `maxTokenBudget`, the `DEFAULT_TASK_SIZING` thresholds, and the
154
- risk heuristics already interpolated. **Apply that rendered string as your
155
- system prompt.** This SKILL deliberately does **not** embed a second verbatim
156
- copy of the prompt body (the preamble, the JSON output schema, the hierarchy /
157
- label / output-format rules); duplicating it here is exactly the drift the
158
- single-source contract exists to prevent, and the guard test in
159
- `tests/ticket-decomposer.test.js` fails if a second full copy reappears on
160
- either surface.
161
-
162
- The value `${maxTickets}` in the rendered prompt is substituted at runtime
163
- from the `maxTickets` field of the loaded context. Treat it as the
164
- **reviewability budget** (Story #2798) — stay under by default; over-budget
165
- plans need an `over_budget_rationale` plus operator `--allow-over-budget` to
166
- persist. It is **not** a hard authoring cap: the prompt no longer carries any
167
- ticket-count limit directive, and you MUST never truncate the JSON array to fit
168
- (Story #4162). The rendered prompt also names the delivery token
169
- budget (`maxTokenBudget`) as the real one-pass sizing envelope — size each
170
- Story so a single agent can deliver and self-verify it within that budget.
171
-
172
- ## Authoring guidance (complements the rendered prompt)
173
-
174
- The sections below are the SKILL's authoring guidance. They do **not** restate
175
- the rendered prompt body — they record the contract details and sizing
176
- heuristics you apply when shaping the ticket array. Where a number appears it
177
- is the `DEFAULT_TASK_SIZING` default; the rendered prompt interpolates the live
178
- value, which always wins.
179
-
180
- ### STORY BODY SHAPE (string body, top-level acceptance/verify)
181
-
182
- For Stories, `body` MUST be a **string** — the serialized markdown produced by
183
- calling `serialize()` from `lib/story-body/story-body.js`. Do NOT emit `body`
184
- as a JSON object: `createOp` in `epic-spec-reconciler-ops.js` will throw
185
- `StoryBodyParseError` when it receives an object body (Story #3302
186
- serialize-or-throw contract), and `composeStoryBody` in the GitHub provider
187
- also discards non-string bodies producing an empty issue. The freshness gate
188
- (`collectTaskChangesPaths`) and the assumption gate
189
- (`collectStoryAssumptionEntries`) both parse the string body via
190
- `story-body.js#parse` to recover `changes[]`/`references[]` — they operate
191
- correctly only on the serialized string form.
192
-
193
- The `acceptance[]` and `verify[]` arrays live at the **top level** of the
194
- Story ticket object (not nested inside `body`). The validator's
195
- `hasInlineAcceptanceAndVerify(story)` reads `story.acceptance` and
196
- `story.verify` directly — nesting them inside a body object makes them
197
- invisible to the validator, causing the backlog to be treated as the legacy
198
- 4-tier shape and producing a `Cross-Validation Failed: Backlog must contain at
199
- least one Task.` error.
200
-
201
- The serialized `body` string renders these markdown sections in order: `##
202
- Goal` (one sentence), `## Changes` (object-form `{ "path", "assumption" }`
203
- bullets), `## Acceptance` (checkbox items), `## Verify` (command + tier), and
204
- `## References` (read-only `{ "path", "assumption": "exists" }` bullets).
205
- Fields `wide` and `estimated_test_files` are encoded as a `<!-- meta: {...}
206
- -->` comment appended to the serialized body string (handled by `serialize()`).
207
- They are NOT top-level ticket fields.
208
-
209
- #### STORY BODY RULES
210
-
211
- - **slug**: MUST be hyphen-case (`^[a-z0-9][a-z0-9-]*$`). Do not use underscores.
212
- - **goal** (in body string): One sentence stating WHY this Story exists within the Epic.
213
- - **reason_to_exist** (REQUIRED, encoded in the body `<!-- meta: {...} -->` comment — NOT a top-level ticket field): One sentence stating the single coherent reason this Story exists, distinct from the broader `goal` prose. Every Story MUST carry a non-empty `reason_to_exist`; it is the machine-checkable form of the cohesion rule (**one Story = one coherent change with one reason to exist**). The `epic-plan-consolidate` critic flags any Story whose body carries no non-empty reason, and the sizing validator (`ticket-validator-sizing.js`) emits a deterministic **soft** `missing-reason-to-exist` finding as the runtime backstop. Encode it as `<!-- meta: {"reason_to_exist": "..."} -->`.
214
- - **changes** (in body string): Each entry is an object `{ path, assumption }` where `assumption` is one of `creates | refactors-existing | deletes`. The Phase 8 validator probes the base branch for every declared path and rejects the decompose when the declared assumption contradicts reality: `creates` against an existing path is an error, `refactors-existing` / `deletes` against a missing path is an error. Use `refactors-existing` for in-place edits to a file already on `main`; `creates` for net-new files; `deletes` for removals. Acceptable path shapes include explicit files (`src/components/Foo.tsx`), glob patterns (`tests/e2e/*.spec.ts`, `**/*.astro`), and module identifiers that resolve to files.
215
- - **references** (in body string, optional): Object-form entries `{ path, assumption: "exists" }` for paths the Story **reads** but does not modify (test fixtures it relies on, sibling modules it imports, feature files it scans). The validator probes these like `changes` and rejects the decompose when an `exists` path is absent on the base branch. Use this list to make read-dependencies explicit so a hallucinated or stale assumption surfaces at planning time rather than execution time.
216
- - **NEW-FILE CONTRACT (must-follow)**: Any path the Story references in `goal`, `acceptance`, or `verify` that does **not** already exist on `main` MUST also appear in the same Story's `changes` array with `assumption: "creates"`. The freshness validator probes `main` for every referenced code path and rejects the decompose when a missing path is absent from `changes` — even when the Story is the one authoring the file. Example: a Story creating `tests/lib/foo.test.js` whose `verify` runs `node --test tests/lib/foo.test.js` MUST include `{ "path": "tests/lib/foo.test.js", "assumption": "creates" }` in `changes`, otherwise the validator emits a freshness miss and the decompose round trips for a re-emit.
217
- - **acceptance** (top-level array on ticket object): Items MUST be observable from outside the agent. Acceptable shapes: a specific command exits 0, a file exists at a given path, a snapshot test matches, a `data-testid` resolves under a given selector, a row count in a fixture matches. UNACCEPTABLE: "verify by reading the diff", "looks good", "matches the spec" — push these down into a `verify` command instead.
218
- - **verify** (top-level array on ticket object): Each entry MUST name a testing tier in parentheses, drawn from `unit` / `contract` / `e2e` / `validate`. Example: `npm run test -- src/x.test.ts (unit)`, `npm run validate (validate)`. Stories with zero verify entries SHOULD fail validation; if a Story is genuinely unverifiable in isolation (e.g., a copy edit auditor will eyeball), the literal entry `manual:<reason>` is allowed so the absence is intentional, not lazy. Manual entries without a reason are rejected.
219
- - **estimated_test_files** (optional, encoded in body meta comment): Integer estimate of how many test files this Story creates or modifies. Omit when the number is not estimable. Informational only — it does not gate the decompose.
220
-
221
- #### FORBIDDEN SUBJECT-PREFIX PRESCRIPTIONS (Conventional-Commits only)
222
-
223
- - `acceptance` items MUST NOT prescribe a commit subject that begins with a non-Conventional-Commits prefix. The allowed leading types are `feat|fix|chore|refactor|perf|docs|style|test|build|ci|revert` (matching `commitlint.config.js` and `release-please-config.json`). Historic ad-hoc subject prefixes — such as the legacy `baseline-refresh` token used as a leading prefix — are FORBIDDEN as subject prescriptions, because they fail the local `commit-msg` hook and the close-time validator (`ticket-validator.js` → `validateAcceptanceSubjectPrefix`) will reject the decompose with `code: 'forbidden-subject-prefix'`. When a Story needs a baseline-refresh-style classification, prescribe a Conventional-Commits subject (e.g. `chore(baselines): refresh maintainability snapshot`) and, if a machine-readable marker is required, prescribe a body trailer such as `baseline-refresh: true` (note the trailing space and value, not a subject prefix). See Epic #2501 for the rationale.
224
-
225
- #### STORY SIZING — DELIVERABLE GRANULARITY, COHESION FIRST (the numeric ceiling is only a backstop)
226
-
227
- **Decompose at deliverable granularity, not module/task level.** A Story is a **capability slice a frontier model delivers and self-verifies in one pass** — a shippable slice a reviewer would accept as a single PR, a capability or user-visible surface, **not a single module or file**. Fold module-level slices into the capability they belong to rather than emitting one Story per module. (This definition is the single source of truth in `DELIVERABLE_GRANULARITY_GUIDANCE` in `ticket-validator-sizing.js`; the rendered decomposer prompt interpolates the same string — do not restate a divergent version here.)
228
-
229
- The first question is **cohesion, not count**: *is this one coherent change with one reason to exist?* File count cannot tell a trivial 10-file mechanical rename from a hard 3-file parser+caller+config change — so lead with the change's reason, not its size. Size against the real one-pass delivery envelope (`maxTokenBudget`): a Story is correctly sized when a single agent can hold its full change, acceptance, and verification in one pass within that budget.
230
-
231
- The envelope also has a **floor**, not just a ceiling: a Story that would plausibly use well under a third of `maxTokenBudget` and is neither parallel-deliverable nor orthogonal to its siblings is a **merge candidate** — modern frontier models one-shot capability-sized changes, so a chain of small dependent Stories needlessly pays a full per-Story delivery session (hydration, branch, PR, review, CI) per link. This is soft guidance, not a threshold or validator finding; the canonical phrasing lives in `DELIVERABLE_GRANULARITY_GUIDANCE.envelopeFloor` in `ticket-validator-sizing.js`, which the decomposer prompt interpolates — do not restate a divergent version here.
232
-
233
- - **One Story = one coherent change with one reason to exist.** If you cannot state that reason in a sentence, the Story is probably two Stories.
234
- - **Single-consumer merge rule.** A Story whose only consumer is one sibling Story should be **merged into that sibling** rather than emitted separately — a single-consumer downstream slice is not its own unit of work.
235
- - **Split independent, parallelizable work** into sibling Stories — but only when the pieces genuinely have separate reasons to exist.
236
- - **Declare `wide` with a one-line reason when a change is legitimately broad** (a cohesive cutover that spans many files for one reason).
237
-
238
- **Numeric backstop.** The thresholds are defined **once**, in the `DEFAULT_TASK_SIZING` constant in `ticket-validator-sizing.js` (operator-overridable via `agentSettings.planning.taskSizing`). They are a backstop, not the primary rule — do not restate divergent numbers anywhere else. The defaults:
239
-
240
- - A Story touching more than **`softFiles` (15)** files emits an advisory width finding — a nudge to check cohesion or declare `wide`.
241
- - A Story touching more than **`hardFiles` (30)** files is **rejected** unless it declares `wide` with a reason.
242
- - Acceptance mass is **advisory only**: more than **`softAcceptanceCount` (10)** acceptance items emits an advisory warning. There is NO hard acceptance ceiling — a long binding contract is a signal to re-check cohesion, never a reason to fragment one coherent capability into dependent slices.
243
-
244
- #### DELIVERY-SCHEDULE SIMULATION (the story count must earn itself)
245
-
246
- Before emitting, simulate the delivery schedule the plan implies and judge the
247
- plan by its schedule, not by how tidy the taxonomy looks. The canonical rules
248
- live in the rendered decomposer prompt (`decomposer-prompts.js`) — in brief:
249
-
250
- 1. **Build the wave schedule.** A Story runs only after every `depends_on`
251
- completes, and two Stories that name the same file in `changes[]` cannot
252
- run in the same wave (the scheduler serializes file-overlapping Stories
253
- even when no `depends_on` edge links them).
254
- 2. **Compute the parallelism yield** — story count ÷ critical-path length in
255
- waves. A yield near 1.0 means the plan is a serial chain: N Stories that
256
- deliver no faster than one Story while paying N delivery sessions.
257
- 3. **Every Story must earn its slot** by at least one of **(a) parallelism**
258
- (it runs concurrently with a sibling in the schedule just built — not
259
- merely "logically independent"), **(b) risk isolation** (it isolates a
260
- consumer-facing behavior change or high-risk cutover into its own
261
- reviewable, revertable unit), or **(c) envelope pressure** (merged into its
262
- neighbor it would exceed the one-pass delivery envelope).
263
- 4. **A dependent link with none of those justifications merges into its
264
- consumer** — the single-consumer merge rule generalized from pairs to
265
- chains.
266
- 5. **Hot-file rule.** When one file appears in the `changes[]` of more than a
267
- third of the Stories, the slicing axis cuts across a shared seam — merge
268
- the Stories that co-edit it, or re-slice along the seam.
269
-
270
- End each Story's `reason_to_exist` with its justification letter and one
271
- clause, e.g. "… (a: runs in wave 1 alongside <slug>)" or "(b: isolates the
272
- auto-merge default change)". A reason that names only a topic ("config work",
273
- "docs") with no justification is a merge signal.
274
-
275
- #### DELIVERY SLICING (consume the Tech Spec target grouping when present)
276
-
277
- The Epic body's Tech Spec sections may carry a `## Delivery Slicing` section authored by the
278
- Architect, proposing how the Epic's enumerated capabilities cluster into N
279
- shippable Stories. When that section is **present**, treat it as the **target
280
- grouping**: prefer emitting Stories that match the Architect's proposed
281
- clusters rather than mapping Epic capabilities 1:1. When it is **absent**,
282
- degrade gracefully — decompose at deliverable granularity using the cohesion
283
- rules above, exactly as before. The Phase 8 holistic consolidation pass
284
- (`epic-plan-consolidate`) reconciles your draft against this same Delivery
285
- Slicing target before persist, so aligning to it here reduces the work the
286
- consolidation critic has to do.
287
-
288
- #### `wide` DECLARATION (optional — for legitimately broad changes)
289
-
290
- A Story whose footprint is legitimately broad declares `wide` carrying a one-line human-readable reason. Encode it in the `<!-- meta: {"wide": {"reason": "..."}} -->` comment that `serialize()` appends to the body string — e.g. `"wide": { "reason": "hard contract cutover: migrate every <X> call site in one PR" }`.
291
-
292
- Declaring `wide` with a non-empty reason **lifts the `hardFiles` rejection** — no Story is rejected for width when it states why it is broad. Omit `wide` for ordinary Stories; a wide footprint with no `wide` declaration emits only an advisory nudge (check cohesion or declare `wide`), never a rejection on its own. Glob entries in `changes[]` (bullets containing `*`) are `unknown-width`: the numeric ceiling is skipped, and a glob Story with no `wide` declaration emits the same advisory nudge.
293
-
294
- #### UI / TESTID INVARIANCE (per CLAUDE.md safety rule)
295
-
296
- - Stories that touch UI (`*.tsx`, `*.astro`, `*.svelte`, `*.vue`, components folders) MUST end `changes` with one of:
297
- - `data-testid invariance: <list of testids that MUST be preserved>`, or
298
- - `data-testid changes: <old> -> <new>` paired with a corresponding `tests/e2e/*.spec.ts` edit in the same Story or a depends_on Story.
299
- - Renaming a testid without the matching e2e edit is FORBIDDEN.
300
-
301
- #### BRAND / COPY / STYLE WORK
302
-
303
- - Stories that touch user-visible copy, brand assets, or visual style MUST cite the relevant section of `docs/style-guide.md` in `acceptance` (e.g. `"acceptance": ["Hero copy matches docs/style-guide.md §3 (voice & tone)"]`). If `docs/style-guide.md` does not exist or has no relevant section, state that explicitly: `"acceptance": ["docs/style-guide.md absent — copy reviewed against the inline brand brief in the Epic body"]`. Silence on style sourcing is a smell.
304
-
305
- #### BINDING ACCEPTANCE vs ADVISORY CHANGES (authoring altitude)
306
-
307
- The canonical altitude + New-File Contract wording is single-sourced in `AUTHORING_ALTITUDE_GUIDANCE` in `ticket-validator-sizing.js` (Story #4272); the rendered decomposer prompt interpolates the same strings, so do not restate a divergent version here. The three canonical statements:
308
-
309
- - **Binding contract vs advisory sketch.** `acceptance[]` and `verify[]` are the Story's **binding contract** — the executor MUST satisfy them exactly, and they are the only definition of "done." `changes[]` and `references[]` are an **advisory implementation sketch**: your best prediction of the file footprint, which the executor MAY revise when the real codebase diverges from the sketch. Author `acceptance[]` / `verify[]` to assert the **outcome** independent of any one file layout — never pin an incidental implementation detail (an internal helper name, a private file path) into an acceptance item that the advisory `changes[]` is free to reshape; assert the observable behaviour instead.
310
- - **New-File Contract.** Any path named in a Story's `goal`, `acceptance`, or `verify` that does NOT already exist on `main` MUST also appear in that Story's `changes[]` with `assumption: "creates"`; otherwise the freshness validator rejects the decompose — even when the Story is the one authoring the file.
311
- - **Advisory does not mean unvalidated.** `changes[]` paths still pass the base-branch file-assumption probes (a `creates` against an existing path still fails), the New-File Contract still holds, and the executor's latitude to revise the approach never licenses skipping `acceptance[]` / `verify[]` or relaxing any `rules/security-baseline.md` MUST.
312
-
313
- #### NAVIGATE-DON'T-DEEP-LINK (signed-in acceptance scenarios)
314
-
315
- When a Story's acceptance describes a **signed-in / authenticated** persona reaching a feature surface, author it so the persona starts from their authenticated home and **reaches the feature through navigation** — clicking a nav door, menu entry, or link the UI actually exposes — **never** via a hardcoded deep-link URL.
316
-
317
- - A deep-link scenario (`load /reports/export and assert the export button`) proves the page renders but NOT that it is reachable; it masks an orphaned surface that no navigation door points to.
318
- - Phrase it as: `"From the signed-in home, the persona navigates to Reports → Export and sees the export button"` — not `"GET /reports/export returns the export view"`.
319
- - This applies to signed-in journeys only; an unauthenticated landing page or a deliberately deep-linkable share URL is exempt — say so in the acceptance item when you take that exemption.
320
-
321
- ### WAVE-0 BDD SCAFFOLD STORY (features-first; emit when the Acceptance Table has `new`-disposition rows)
322
-
323
- The Epic body's `## Acceptance Table` section (columns `AC ID | Outcome | Feature File | Scenario | Disposition`) tags each row's `Disposition` with one of `new | updated | unchanged`. A `new` row names a `.feature` file + scenario that does NOT yet exist on `main`. The framework is features-first: implementation Stories reference those `.feature` paths in their `verify[]` lines, so the files MUST already exist when those Stories run — otherwise verification fails mid-delivery on a missing file (observed gap: Epic #18 in `dsj1984/athportal` had 9 `new` rows and no Story tasked with creating the feature files Stories #1457 / #1466 verified against).
324
-
325
- When the Acceptance Table contains **one or more `Disposition: new` rows**, you MUST emit **exactly one** dedicated wave-0 scaffold Story whose sole job is to create those `.feature` files with `@skip`-tagged scenarios BEFORE any implementation Story runs:
326
-
327
- - **goal** (in body string): contains the literal token `bdd-scaffold`.
328
- - **depends_on**: EMPTY (`[]`) — the scaffold runs first, in wave 0.
329
- - **changes** (in body string): one `{ path, assumption: "creates" }` entry per distinct `.feature` file named in a `new` row.
330
- - **acceptance** (top-level array): MUST assert (a) every new `.feature` file exists, (b) every new scenario within them carries an `@skip` tag, AND (c) every new scenario also carries its **namespaced per-Epic AC tag** `@epic-<id>-ac-N` (one tag per AC ID the scenario satisfies). Keep items observable (a command exits 0; a file exists at a path).
331
- - **The namespaced AC tag is REQUIRED at scaffold time, not only at de-skip time.** Phase 7 finalize's `acceptance-spec-reconciler.js` matches AC IDs only against `@epic-<id>-ac-*` / `@pending` tags under `tests/features/**` — a bare `@ac-N` tag is deliberately ignored to prevent cross-Epic collision (Story #3362). A scaffolded scenario carrying `@skip` but no `@epic-<id>-ac-N` tag reads as `missing[]` at finalize and throws, aborting close, even after the implementation Story de-skips it — the tag was never added in either pass. Tag each scenario with both `@skip` AND `@epic-<id>-ac-N` (substituting the Epic's real ID and the scenario's own AC number) in this SAME wave-0 commit; do not defer the AC tag to the later de-skip edit.
332
- - **verify** (top-level array): a grep/validate command (tier `validate`), NOT an e2e runner — verifying that a file exists with the required tags needs no browser/playwright run. Include a check that each new AC ID's namespaced tag is present in the scaffolded files, alongside the `@skip` check.
333
- - Each implementation Story whose `verify[]` references a scaffolded `.feature` path MUST add `depends_on: ["<scaffold-slug>"]` so the scaffold lands in an earlier wave. Omitting the link trips the soft `missing-bdd-scaffold` finding in `ticket-validator-conflicts.js` (advisory, not a hard block).
334
-
335
- When the Acceptance Table contains **zero `new`-disposition rows** (every row is `updated` or `unchanged`), do NOT emit a scaffold Story — there is nothing to create.
336
-
337
- > **Read [`examples.md`](./examples.md) on demand** for a fully worked wave-0
338
- > scaffold Story (Epic #42, two `new` rows) showing the serialized string
339
- > `body`, the top-level `acceptance`/`verify` arrays, the empty `depends_on`,
340
- > and the paired `@skip` + `@epic-<id>-ac-N` tagging.
341
-
342
- ### SCOPE-OVERLAP FLAGGING (docs/runbook downstream of config work)
343
-
344
- When a "docs update" / "runbook" / "README" Story appears downstream of an earlier Story in the same Epic whose AC already covers updating the same document (e.g. a "config + runbook" Story followed by a "docs" Story touching the same runbook), the downstream Story's deliverable may be fully absorbed by the earlier Story. Flag the risk directly in the Story `body.acceptance` by appending an item of the form:
345
- "Scope verification note: this Story's deliverable may already be satisfied by Story #<slug-or-id>'s AC — before implementing, `git diff main -- <path>` against the upstream Story branch and confirm whether a substantive edit is still required, or whether only a cross-reference remains."
346
- This prevents the executing agent from redoing work the upstream Story already merged.
347
-
348
- ### CROSS-CUTTING CONFIG FILE EDITS (shared root files across Stories)
349
-
350
- If two or more Stories in the same decomposition edit any of the shared
351
- configuration files enumerated below, you MUST either:
352
-
353
- 1. Add explicit `depends_on` links chaining the affected Stories so they
354
- merge sequentially (preferred when the Stories share thematic scope and
355
- the second Story's edits build on the first), OR
356
- 2. Split the cross-cutting edits into a single dedicated late-wave "wiring"
357
- Story that runs after the dependents land (preferred when the dependent
358
- Stories are otherwise unrelated and would only collide at the wiring
359
- point).
360
-
361
- Trade-offs: option (1) keeps each Story end-to-end coherent but serializes
362
- their delivery; option (2) keeps the dependents parallel but introduces a
363
- narrow extra Story whose AC is purely integration. Pick (1) when the shared
364
- file edit is small and thematically owned by one of the Stories; pick (2)
365
- when several otherwise-independent Stories all need to register themselves
366
- in the same manifest.
367
-
368
- Shared configuration files (non-exhaustive):
369
-
370
- - `.github/workflows/*.yml` — any single workflow file edited by multiple
371
- Stories
372
- - `package.json` at the repo root (dependency or script edits)
373
- - `pnpm-workspace.yaml`, `turbo.json`, `nx.json`, `lerna.json` — monorepo
374
- manifests
375
- - `tsconfig.base.json`, `tsconfig.json` at the repo root
376
- - `.gitignore`, `.npmrc`, `.nvmrc` at the repo root
377
- - Any single file under a `schemas/` directory if it is the only producer
378
- of a contract consumed by other Stories — those consumers MUST
379
- `depends_on` the producer
380
- - **Registry / barrel files** (Story #2962). Files whose primary purpose
381
- is to wire siblings together (listener registries, handler maps,
382
- manifest barrels) collide whenever two concurrent Stories *create new
383
- files* that the registry must import. The validator recognises this
384
- class via `planning.crossCuttingRegistries` (extender-shaped). The
385
- framework default list is:
386
- - `lib/orchestration/lifecycle/listeners/index.js`
387
- - `**/listeners/index.js`
388
- - `**/handlers/index.js`
389
-
390
- Trigger: two or more concurrent Stories either edit a registry path
391
- directly **or** declare `assumption: creates` for a file in the
392
- registry's parent directory. Remediation is the same as the shared
393
- configuration files above — sequential `depends_on` between the
394
- Stories, or a dedicated late-wave wiring Story. Consumers extend the
395
- list per-project via `planning.crossCuttingRegistries` in
396
- `.agentrc.json` (accepts `["…"]` to replace or `{ append: [...] }` to
397
- add to the framework default).
398
-
399
- ### WIDELY-USED SYMBOL DELETION (Story #2962)
400
-
401
- When a Story's `body.changes` declares `{ path, assumption: "deletes" }`,
402
- the decomposer probes the base branch at plan time via `git grep -l`
403
- for files that reference the deleted module's basename. When the count
404
- exceeds `planning.largeFanOutThreshold` (default `10`), the validator
405
- emits a `fan-out-warning` finding and `epic-plan-decompose` refuses to
406
- persist unless the operator passes `--allow-large-fan-out`.
407
-
408
- This gate exists because re-prompting the planner cannot reduce a
409
- deletion's call-site count — the only safe remediations are to split
410
- the deletion into a subsystem-by-subsystem migration across multiple
411
- Stories or to confirm the deletion is intentional and bypass the gate
412
- with the flag. The threshold is configurable per-project via
413
- `planning.largeFanOutThreshold` in `.agentrc.json`.
414
-
415
- Do NOT silently allow two Stories to write the same root configuration
416
- file in the same wave; parallel dispatch would produce a merge conflict
417
- on every Story-to-Epic close after the first.
418
-
419
- CRITICAL: Dependencies should follow execution blockers. Stories attach
420
- directly to the Epic — never emit a `parent_slug` field. A Story's
421
- `depends_on` MUST only reference other Stories within the SAME Epic; express
422
- any logical ordering requirement via Story-level `depends_on`.
423
-
424
- ## Constraints
425
-
426
- - Do **not** call the GitHub API from this Skill. Persistence is the
427
- script's job; the Skill is pure JSON authoring.
428
- - Do **not** write outside `temp/epic-<Epic_ID>/`. Reads may cover the
429
- Epic body plus any docs the context envelope cites.
430
- - The decomposer prompt's `${maxTickets}` value is the **reviewability
431
- budget** (Story #2798). Staying under is the default; exceeding it
432
- requires both an `over_budget_rationale` in the JSON output and the
433
- operator's `--allow-over-budget` flag at persist time. Silently
434
- exceeding the budget — or truncating the plan to fit — is forbidden.
435
- - If `temp/epic-<Epic_ID>/decomposer-context.json` is missing, fail
436
- loudly. Instruct the caller to run `--emit-context` first.
437
- - The validator
438
- ([`lib/orchestration/ticket-validator.js`](../../../scripts/lib/orchestration/ticket-validator.js))
439
- is the authoritative gate. On rejection, apply the re-emit rule above —
440
- a targeted edit to the existing `tickets.json` fixing only what was
441
- rejected — rather than re-authoring the array from scratch.
@@ -1,47 +0,0 @@
1
- # epic-plan-decompose-author — examples & extended rationale
2
-
3
- Read this file on demand while authoring the ticket array. The SKILL.md carries
4
- the operating contract (Policy Capsule, Inputs / Outputs, Procedure, the
5
- authoring guidance that complements the rendered decomposer prompt, and
6
- Constraints); this file carries the worked WAVE-0 BDD scaffold Story and the
7
- extended reasoning behind it.
8
-
9
- ## WAVE-0 BDD scaffold Story — worked example
10
-
11
- The contract lives in SKILL.md under **WAVE-0 BDD SCAFFOLD STORY**: when the
12
- Epic body's `## Acceptance Table` carries one or more `Disposition: new` rows,
13
- emit **exactly one** dedicated wave-0 scaffold Story whose sole job is to create
14
- those `.feature` files with `@skip`-tagged scenarios (each also carrying its
15
- namespaced `@epic-<id>-ac-N` tag) BEFORE any implementation Story runs.
16
-
17
- **Worked example.** Epic #42, Acceptance Table with two `new` rows
18
- (`AC-1` -> `tests/features/billing/invoice.feature`,
19
- `AC-2` -> `tests/features/billing/refund.feature`). The scaffold Story below
20
- uses a serialized string `body`, top-level `acceptance`/`verify` arrays, an
21
- empty `depends_on`, and tags each scenario with both `@skip` and its namespaced
22
- `@epic-42-ac-N` tag:
23
-
24
- {
25
- "slug": "scaffold-billing-feature-files",
26
- "type": "story",
27
- "title": "Scaffold @skip-tagged billing feature files",
28
- "depends_on": [],
29
- "labels": ["type::story", "persona::qa-engineer"],
30
- "acceptance": [
31
- "tests/features/billing/invoice.feature and tests/features/billing/refund.feature both exist on the branch",
32
- "every Scenario in the two new feature files is preceded by an @skip tag (grep for un-skipped scenarios returns zero matches)",
33
- "the invoice.feature scenario carries @epic-42-ac-1 and the refund.feature scenario carries @epic-42-ac-2"
34
- ],
35
- "verify": [
36
- "test -f tests/features/billing/invoice.feature && test -f tests/features/billing/refund.feature (validate)",
37
- "test -z \"$(grep -rL '@skip' tests/features/billing/*.feature)\" (validate)",
38
- "grep -q '@epic-42-ac-1' tests/features/billing/invoice.feature && grep -q '@epic-42-ac-2' tests/features/billing/refund.feature (validate)"
39
- ],
40
- "body": "## Goal\nbdd-scaffold: create the @skip-tagged, @epic-42-ac-N-tagged feature files the billing-flows implementation Stories verify against, so wave-0 lands them before any implementation Story runs.\n\n## Changes\n- {\"path\": \"tests/features/billing/invoice.feature\", \"assumption\": \"creates\"}\n- {\"path\": \"tests/features/billing/refund.feature\", \"assumption\": \"creates\"}\n\n## Acceptance\n- [ ] tests/features/billing/invoice.feature and tests/features/billing/refund.feature both exist on the branch\n- [ ] every Scenario in the two new feature files is preceded by an @skip tag\n- [ ] the invoice.feature scenario carries @epic-42-ac-1 and the refund.feature scenario carries @epic-42-ac-2\n\n## Verify\n- test -f tests/features/billing/invoice.feature && test -f tests/features/billing/refund.feature (validate)\n- test -z \"$(grep -rL '@skip' tests/features/billing/*.feature)\" (validate)\n- grep -q '@epic-42-ac-1' tests/features/billing/invoice.feature && grep -q '@epic-42-ac-2' tests/features/billing/refund.feature (validate)\n"
41
- }
42
-
43
- The implementation Stories that later un-skip and flesh out these scenarios each
44
- carry `depends_on: ["scaffold-billing-feature-files"]`, placing them in a later
45
- wave than the scaffold. They MUST NOT add the `@epic-42-ac-N` tag themselves —
46
- it is already present from the scaffold pass; their job is to remove `@skip`
47
- once the scenario passes.