mandrel 1.59.0 → 1.60.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 (240) hide show
  1. package/.agents/README.md +14 -14
  2. package/.agents/docs/SDLC.md +129 -134
  3. package/.agents/docs/configuration.md +16 -16
  4. package/.agents/docs/workflows.md +6 -8
  5. package/.agents/instructions.md +12 -11
  6. package/.agents/personas/architect.md +1 -1
  7. package/.agents/personas/product.md +1 -1
  8. package/.agents/personas/project-manager.md +14 -14
  9. package/.agents/personas/technical-writer.md +1 -1
  10. package/.agents/rules/changelog-style.md +5 -5
  11. package/.agents/rules/git-conventions.md +3 -3
  12. package/.agents/schemas/agentrc.schema.json +3 -3
  13. package/.agents/schemas/dispatch-manifest.json +4 -4
  14. package/.agents/schemas/epic-spec.schema.json +15 -45
  15. package/.agents/schemas/lifecycle/README.md +1 -1
  16. package/.agents/schemas/lifecycle/story.dispatch.end.schema.json +1 -1
  17. package/.agents/schemas/lifecycle/story.dispatch.start.schema.json +1 -1
  18. package/.agents/schemas/lifecycle/story.heartbeat.schema.json +1 -1
  19. package/.agents/schemas/validation-evidence.schema.json +1 -1
  20. package/.agents/scripts/README.md +1 -1
  21. package/.agents/scripts/acceptance-eval.js +1 -1
  22. package/.agents/scripts/acceptance-spec-reconciler.js +2 -2
  23. package/.agents/scripts/analyze-execution.js +2 -2
  24. package/.agents/scripts/audit-to-stories.js +1 -1
  25. package/.agents/scripts/check-doc-links.js +2 -3
  26. package/.agents/scripts/diagnose-friction.js +1 -1
  27. package/.agents/scripts/dispatcher.js +2 -2
  28. package/.agents/scripts/drain-pending-cleanup.js +1 -1
  29. package/.agents/scripts/epic-audit-prepare.js +3 -3
  30. package/.agents/scripts/epic-deliver-note-intervention.js +2 -2
  31. package/.agents/scripts/epic-deliver-preflight.js +6 -6
  32. package/.agents/scripts/epic-deliver-prepare.js +1 -1
  33. package/.agents/scripts/epic-execute-record-wave.js +4 -4
  34. package/.agents/scripts/epic-plan-healthcheck.js +6 -10
  35. package/.agents/scripts/epic-plan-spec-validate.js +1 -1
  36. package/.agents/scripts/epic-reconcile.js +11 -29
  37. package/.agents/scripts/evidence-gate.js +1 -1
  38. package/.agents/scripts/generate-workflows-doc.js +1 -1
  39. package/.agents/scripts/hierarchy-gate.js +7 -11
  40. package/.agents/scripts/lib/ITicketingProvider.js +1 -1
  41. package/.agents/scripts/lib/audit-suite/selector.js +1 -1
  42. package/.agents/scripts/lib/audit-to-stories/seed-epic-from-findings.js +2 -2
  43. package/.agents/scripts/lib/baseline-snapshot.js +7 -7
  44. package/.agents/scripts/lib/bdd-runner-detect.js +1 -1
  45. package/.agents/scripts/lib/bdd-scenario-scanner.js +3 -3
  46. package/.agents/scripts/lib/bootstrap/baselines-layout-migration.js +1 -1
  47. package/.agents/scripts/lib/bootstrap/branch-protection.js +1 -1
  48. package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +1 -1
  49. package/.agents/scripts/lib/bootstrap/commit-push.js +2 -2
  50. package/.agents/scripts/lib/codebase-snapshot.js +1 -1
  51. package/.agents/scripts/lib/config/explain.js +1 -1
  52. package/.agents/scripts/lib/config/runners.js +2 -2
  53. package/.agents/scripts/lib/config/runtime.js +1 -1
  54. package/.agents/scripts/lib/config/temp-paths.js +2 -2
  55. package/.agents/scripts/lib/config-settings-schema-delivery.js +2 -2
  56. package/.agents/scripts/lib/config-settings-schema-quality.js +1 -1
  57. package/.agents/scripts/lib/config-settings-schema.js +3 -3
  58. package/.agents/scripts/lib/duplicate-search.js +1 -1
  59. package/.agents/scripts/lib/dynamic-workflow/capability.js +1 -1
  60. package/.agents/scripts/lib/epic-plan-clarity.js +1 -1
  61. package/.agents/scripts/lib/epic-plan-ideation.js +1 -1
  62. package/.agents/scripts/lib/feedback-loop/memory-freshness.js +1 -1
  63. package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +1 -1
  64. package/.agents/scripts/lib/findings/classify-finding.js +1 -1
  65. package/.agents/scripts/lib/findings/promote-finding.js +10 -10
  66. package/.agents/scripts/lib/label-constants.js +3 -4
  67. package/.agents/scripts/lib/label-taxonomy.js +3 -8
  68. package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +1 -1
  69. package/.agents/scripts/lib/orchestration/code-review.js +5 -5
  70. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +8 -9
  71. package/.agents/scripts/lib/orchestration/dependency-analyzer.js +3 -3
  72. package/.agents/scripts/lib/orchestration/detectors-phase.js +2 -2
  73. package/.agents/scripts/lib/orchestration/dispatch-engine.js +30 -38
  74. package/.agents/scripts/lib/orchestration/dispatch-pipeline.js +9 -25
  75. package/.agents/scripts/lib/orchestration/epic-cleanup.js +1 -1
  76. package/.agents/scripts/lib/orchestration/epic-deliver-lease-guard.js +8 -8
  77. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/creation.js +1 -1
  78. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/dag.js +7 -21
  79. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/diagnostics.js +3 -3
  80. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +26 -13
  81. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +1 -1
  82. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +1 -1
  83. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +2 -2
  84. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +1 -1
  85. package/.agents/scripts/lib/orchestration/epic-run-state-store.js +3 -3
  86. package/.agents/scripts/lib/orchestration/epic-runner/concurrency-gate.js +4 -4
  87. package/.agents/scripts/lib/orchestration/epic-runner/deliver-phases.js +3 -3
  88. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +6 -21
  89. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +7 -7
  90. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +1 -1
  91. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +2 -2
  92. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/transport.js +4 -4
  93. package/.agents/scripts/lib/orchestration/epic-runner/story-launcher.js +4 -4
  94. package/.agents/scripts/lib/orchestration/epic-runner/story-run-progress-writer.js +8 -8
  95. package/.agents/scripts/lib/orchestration/epic-runner/sub-agent-return.js +4 -4
  96. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-apply.js +7 -15
  97. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-diff.js +72 -41
  98. package/.agents/scripts/lib/orchestration/epic-spec-reconciler-ops.js +2 -4
  99. package/.agents/scripts/lib/orchestration/file-assumptions.js +2 -2
  100. package/.agents/scripts/lib/orchestration/finalize/close-planning-tickets.js +1 -1
  101. package/.agents/scripts/lib/orchestration/finalize/open-or-locate-pr.js +2 -2
  102. package/.agents/scripts/lib/orchestration/finalize/sanitize-skip-ci.js +1 -1
  103. package/.agents/scripts/lib/orchestration/lease-guard-shared.js +3 -3
  104. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-dispatch-end.js +1 -1
  105. package/.agents/scripts/lib/orchestration/lifecycle/emit-story-heartbeat.js +1 -1
  106. package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +1 -1
  107. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +1 -1
  108. package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +1 -1
  109. package/.agents/scripts/lib/orchestration/lifecycle/listeners/branch-cleaner.js +1 -1
  110. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +1 -1
  111. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +1 -1
  112. package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +1 -1
  113. package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +1 -1
  114. package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +1 -1
  115. package/.agents/scripts/lib/orchestration/manifest-builder.js +5 -5
  116. package/.agents/scripts/lib/orchestration/parked-follow-ons.js +2 -2
  117. package/.agents/scripts/lib/orchestration/plan-runner/plan-router.js +5 -5
  118. package/.agents/scripts/lib/orchestration/post-merge/phases/ticket-closure.js +3 -3
  119. package/.agents/scripts/lib/orchestration/preflight-cache.js +1 -1
  120. package/.agents/scripts/lib/orchestration/recurring-failure-detector.js +1 -1
  121. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +1 -1
  122. package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +2 -2
  123. package/.agents/scripts/lib/orchestration/retro-runner.js +3 -3
  124. package/.agents/scripts/lib/orchestration/review-depth.js +1 -1
  125. package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +1 -1
  126. package/.agents/scripts/lib/orchestration/spec-freshness.js +1 -1
  127. package/.agents/scripts/lib/orchestration/spec-renderer.js +36 -73
  128. package/.agents/scripts/lib/orchestration/spec-section-validator.js +1 -1
  129. package/.agents/scripts/lib/orchestration/story-close/baseline-friction-body.js +1 -1
  130. package/.agents/scripts/lib/orchestration/story-close/phases/locked-pipeline.js +2 -2
  131. package/.agents/scripts/lib/orchestration/task-body-validator.js +6 -6
  132. package/.agents/scripts/lib/orchestration/ticket-lease.js +1 -1
  133. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +2 -2
  134. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +1 -10
  135. package/.agents/scripts/lib/orchestration/ticket-validator.js +25 -70
  136. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +5 -12
  137. package/.agents/scripts/lib/orchestration/ticketing/reads.js +8 -8
  138. package/.agents/scripts/lib/orchestration/ticketing/state.js +3 -3
  139. package/.agents/scripts/lib/orchestration/wave-record-notifications.js +2 -2
  140. package/.agents/scripts/lib/orchestration/wave-record-projection.js +1 -1
  141. package/.agents/scripts/lib/plan-phase-cleanup.js +1 -1
  142. package/.agents/scripts/lib/preflight-runner.js +1 -1
  143. package/.agents/scripts/lib/presentation/dispatch-manifest-render.js +4 -5
  144. package/.agents/scripts/lib/presentation/manifest-builder.js +28 -34
  145. package/.agents/scripts/lib/presentation/manifest-formatter.js +3 -4
  146. package/.agents/scripts/lib/presentation/manifest-helpers.js +1 -1
  147. package/.agents/scripts/lib/presentation/manifest-procedures.js +4 -4
  148. package/.agents/scripts/lib/presentation/manifest-render-waves.js +4 -23
  149. package/.agents/scripts/lib/presentation/manifest-renderer.js +1 -1
  150. package/.agents/scripts/lib/presentation/manifest-story-views.js +2 -11
  151. package/.agents/scripts/lib/signals/schema.js +1 -1
  152. package/.agents/scripts/lib/spec/index.js +1 -1
  153. package/.agents/scripts/lib/spec/loader.js +2 -2
  154. package/.agents/scripts/lib/spec/state.js +7 -16
  155. package/.agents/scripts/lib/story-init/context-resolver.js +3 -3
  156. package/.agents/scripts/lib/story-init/state-transitioner.js +2 -2
  157. package/.agents/scripts/lib/story-init/task-graph-builder.js +7 -7
  158. package/.agents/scripts/lib/story-lifecycle.js +8 -8
  159. package/.agents/scripts/lib/story-plan.js +1 -1
  160. package/.agents/scripts/lib/templates/decomposer-prompts.js +59 -52
  161. package/.agents/scripts/lib/wave-runner/tick.js +1 -1
  162. package/.agents/scripts/lifecycle-emit-story-dispatch.js +1 -1
  163. package/.agents/scripts/lifecycle-emit.js +1 -1
  164. package/.agents/scripts/providers/github/board-add.js +1 -1
  165. package/.agents/scripts/providers/github/errors.js +1 -1
  166. package/.agents/scripts/providers/github/mappers.js +2 -2
  167. package/.agents/scripts/providers/github/tickets.js +4 -4
  168. package/.agents/scripts/resync-status-column.js +1 -1
  169. package/.agents/scripts/retro-run.js +2 -2
  170. package/.agents/scripts/run-lint.js +1 -1
  171. package/.agents/scripts/single-story-init.js +1 -1
  172. package/.agents/scripts/stories-wave-tick.js +5 -5
  173. package/.agents/scripts/story-close.js +1 -1
  174. package/.agents/scripts/story-init.js +13 -16
  175. package/.agents/scripts/story-phase.js +5 -5
  176. package/.agents/scripts/story-plan.js +3 -3
  177. package/.agents/scripts/sync-branch-from-base.js +1 -1
  178. package/.agents/scripts/validate-docs-freshness.js +1 -1
  179. package/.agents/scripts/wave-tick.js +1 -1
  180. package/.agents/skills/core/analyze-execution/SKILL.md +2 -2
  181. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +21 -26
  182. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +23 -56
  183. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +4 -4
  184. package/.agents/skills/core/hydrate-context/SKILL.md +2 -2
  185. package/.agents/skills/core/idea-refinement/SKILL.md +4 -4
  186. package/.agents/skills/core/knowledge-transfer/SKILL.md +2 -2
  187. package/.agents/skills/core/planning-and-task-breakdown/SKILL.md +1 -1
  188. package/.agents/skills/core/scope-triage/SKILL.md +9 -10
  189. package/.agents/skills/core/using-agent-skills/SKILL.md +1 -1
  190. package/.agents/skills/skills.index.json +7 -7
  191. package/.agents/templates/agent-protocol.md +2 -2
  192. package/.agents/workflows/agents-update.md +2 -2
  193. package/.agents/workflows/audit-architecture.md +2 -2
  194. package/.agents/workflows/audit-clean-code.md +2 -2
  195. package/.agents/workflows/audit-dependencies.md +1 -1
  196. package/.agents/workflows/audit-devops.md +1 -1
  197. package/.agents/workflows/audit-documentation.md +2 -2
  198. package/.agents/workflows/audit-lighthouse.md +1 -1
  199. package/.agents/workflows/audit-performance.md +2 -2
  200. package/.agents/workflows/audit-privacy.md +1 -1
  201. package/.agents/workflows/audit-quality.md +2 -2
  202. package/.agents/workflows/audit-security.md +2 -2
  203. package/.agents/workflows/audit-seo.md +1 -1
  204. package/.agents/workflows/audit-sre.md +1 -1
  205. package/.agents/workflows/audit-to-stories.md +10 -10
  206. package/.agents/workflows/audit-ux-ui.md +1 -1
  207. package/.agents/workflows/deliver.md +85 -0
  208. package/.agents/workflows/explain.md +3 -3
  209. package/.agents/workflows/git-merge-pr.md +1 -1
  210. package/.agents/workflows/git-pr-all.md +13 -10
  211. package/.agents/workflows/git-push.md +6 -3
  212. package/.agents/workflows/helpers/_merge-conflict-template.md +1 -1
  213. package/.agents/workflows/helpers/acceptance-self-eval.md +1 -1
  214. package/.agents/workflows/helpers/code-review.md +5 -5
  215. package/.agents/workflows/{epic-deliver.md → helpers/deliver-epic.md} +43 -43
  216. package/.agents/workflows/{story-deliver.md → helpers/deliver-stories.md} +25 -25
  217. package/.agents/workflows/helpers/diagnose.md +1 -1
  218. package/.agents/workflows/helpers/epic-audit.md +6 -6
  219. package/.agents/workflows/helpers/epic-deliver-story.md +13 -13
  220. package/.agents/workflows/helpers/epic-plan-decompose.md +23 -23
  221. package/.agents/workflows/helpers/epic-plan-spec.md +6 -6
  222. package/.agents/workflows/helpers/epic-testing.md +3 -3
  223. package/.agents/workflows/helpers/parallel-tooling.md +1 -1
  224. package/.agents/workflows/{epic-plan.md → helpers/plan-epic.md} +84 -84
  225. package/.agents/workflows/{story-plan.md → helpers/plan-story.md} +43 -43
  226. package/.agents/workflows/helpers/signals.md +1 -1
  227. package/.agents/workflows/helpers/single-story-deliver.md +11 -11
  228. package/.agents/workflows/helpers/worktree-lifecycle.md +18 -18
  229. package/.agents/workflows/onboard.md +17 -17
  230. package/.agents/workflows/plan.md +89 -0
  231. package/.agents/workflows/qa-explore.md +1 -1
  232. package/.agents/workflows/qa-run-harness.md +1 -1
  233. package/README.md +4 -12
  234. package/docs/CHANGELOG.md +1149 -0
  235. package/lib/cli/__tests__/update-changelog-surface.test.js +357 -0
  236. package/lib/cli/__tests__/update-reexec.test.js +513 -0
  237. package/lib/cli/init.js +31 -29
  238. package/lib/cli/update.js +413 -52
  239. package/package.json +2 -1
  240. package/.agents/scripts/lib/orchestration/reconciler.js +0 -137
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * stories-wave-tick.js — DAG/wave engine for the top-level /story-deliver workflow.
4
+ * stories-wave-tick.js — DAG/wave engine for the top-level /deliver workflow.
5
5
  *
6
6
  * Consumes an operator-supplied dependency DAG of standalone Story IDs and
7
7
  * emits ordered execution waves. Analogous to wave-tick.js but for standalone
@@ -26,11 +26,11 @@
26
26
  * }
27
27
  *
28
28
  * The per-wave concurrency cap is resolved from the same config seam
29
- * `/epic-deliver` uses — `resolveConfig` + `getRunners` reading
29
+ * `/deliver` uses — `resolveConfig` + `getRunners` reading
30
30
  * `delivery.deliverRunner.concurrencyCap` (default 3) — so a
31
31
  * `.agentrc.local.json` override is honored. A `--concurrency <n>` CLI flag
32
32
  * overrides the config-resolved value for that run only. This puts both the
33
- * standalone (`/story-deliver`) and Epic (`/epic-deliver`) delivery paths on
33
+ * standalone (`/deliver`) and Epic (`/deliver`) delivery paths on
34
34
  * one deterministic config source.
35
35
  *
36
36
  * On cycle detection, exits with code 2 and sets cycleError in the envelope.
@@ -149,7 +149,7 @@ export function buildAdjacency(nodes) {
149
149
  /**
150
150
  * Resolve the per-wave concurrency cap.
151
151
  *
152
- * Mirrors the `/epic-deliver` seam (`epic-deliver-prepare.js`): resolve the
152
+ * Mirrors the `/deliver` seam (`epic-deliver-prepare.js`): resolve the
153
153
  * project config (which deep-merges `.agentrc.local.json` over `.agentrc.json`)
154
154
  * then read `delivery.deliverRunner.concurrencyCap` via `getRunners` (default
155
155
  * 3). An explicit `override` (the `--concurrency <n>` CLI flag) wins over
@@ -177,7 +177,7 @@ export function resolveConcurrencyCap({ cwd, config, override } = {}) {
177
177
  *
178
178
  * Uses detectCycle from Graph.js to validate the DAG before computing
179
179
  * layers via assignLayers. Returns the wave envelope, carrying the resolved
180
- * per-wave `concurrencyCap` so the `/story-deliver` workflow dispatches
180
+ * per-wave `concurrencyCap` so the `/deliver` workflow dispatches
181
181
  * `min(wave.stories.length, concurrencyCap)` from a deterministic field rather
182
182
  * than from recalled prose.
183
183
  *
@@ -22,7 +22,7 @@
22
22
  * 1 error
23
23
  * 2 prior-state (pass --resume / --restart) OR preflight refused
24
24
  *
25
- * @see .agents/workflows/story-deliver.md
25
+ * @see .agents/workflows/helpers/deliver-stories.md
26
26
  */
27
27
 
28
28
  import { runAsCli } from './lib/cli-utils.js';
@@ -15,7 +15,7 @@
15
15
  * 5. branch-initializer — materialise the story branch (single-tree
16
16
  * checkout or isolated worktree).
17
17
  * 6. state-transitioner — flip the Story to `agent::executing`. Under
18
- * the 3-tier hierarchy the Story has inline
18
+ * the 2-tier hierarchy the Story has inline
19
19
  * acceptance and no child Task lifecycle.
20
20
  *
21
21
  * Usage:
@@ -25,7 +25,7 @@
25
25
  * 0 — Initialization complete. Agent can start implementation.
26
26
  * 1 — Blocked or error (details in stderr).
27
27
  *
28
- * @see .agents/workflows/story-deliver.md
28
+ * @see .agents/workflows/helpers/deliver-stories.md
29
29
  */
30
30
 
31
31
  import path from 'node:path';
@@ -141,7 +141,7 @@ export async function runStoryInit({
141
141
  progress('INIT', `Initializing Story #${storyId}...`);
142
142
 
143
143
  // Stage 1 — context.
144
- const { story, body, epicId, featureId } = await resolveContext({
144
+ const { story, body, epicId, parentId } = await resolveContext({
145
145
  provider,
146
146
  logger: stageLogger,
147
147
  input: { storyId, recutOf, dryRun },
@@ -154,10 +154,7 @@ export async function runStoryInit({
154
154
  input: { epicId },
155
155
  });
156
156
 
157
- progress(
158
- 'CONTEXT',
159
- `Epic: #${epicId}, Feature/Parent: #${featureId ?? 'none'}`,
160
- );
157
+ progress('CONTEXT', `Epic: #${epicId}, Parent: #${parentId ?? 'none'}`);
161
158
  progress(
162
159
  'CONTEXT',
163
160
  `PRD: #${prdId ?? 'none'}, Tech Spec: #${techSpecId ?? 'none'}`,
@@ -192,8 +189,8 @@ export async function runStoryInit({
192
189
  progress('BLOCKERS', '✅ All blockers resolved');
193
190
 
194
191
  // Stage 4 — task graph. Pass the Story body so buildTaskGraph can detect
195
- // the inline-acceptance 3-tier shape. After Task #3154 collapsed the
196
- // hierarchy flag, 3-tier is the only supported shape.
192
+ // the inline-acceptance 2-tier shape. After Task #3154 collapsed the
193
+ // hierarchy flag, 2-tier is the only supported shape.
197
194
  const { sortedTasks, mode: hierarchyMode } = await buildTaskGraph({
198
195
  provider,
199
196
  logger: stageLogger,
@@ -327,7 +324,7 @@ export async function runStoryInit({
327
324
  worktreeCreated,
328
325
  installStatus,
329
326
  sortedTasks,
330
- featureId,
327
+ parentId,
331
328
  prdId,
332
329
  techSpecId,
333
330
  dryRun,
@@ -500,7 +497,7 @@ function buildStoryInitResult({
500
497
  worktreeCreated,
501
498
  installStatus,
502
499
  sortedTasks,
503
- featureId,
500
+ parentId,
504
501
  prdId,
505
502
  techSpecId,
506
503
  dryRun,
@@ -514,11 +511,11 @@ function buildStoryInitResult({
514
511
  storyBranch,
515
512
  epicBranch,
516
513
  storyTitle: story.title,
517
- // Hierarchy mode resolved by buildTaskGraph. 3-tier is the only
514
+ // Hierarchy mode resolved by buildTaskGraph. 2-tier is the only
518
515
  // supported shape after Task #3154 deleted the `planning.hierarchy`
519
516
  // flag; this is retained as a constant marker for downstream
520
517
  // consumers and persisted artefacts.
521
- hierarchy: hierarchy ?? '3-tier',
518
+ hierarchy: hierarchy ?? '2-tier',
522
519
  worktreeEnabled,
523
520
  workCwd,
524
521
  worktreeCreated,
@@ -534,7 +531,7 @@ function buildStoryInitResult({
534
531
  labels: t.labels,
535
532
  dependencies: t.dependsOn ?? parseBlockedBy(t.body ?? ''),
536
533
  })),
537
- context: { featureId, prdId, techSpecId },
534
+ context: { parentId, prdId, techSpecId },
538
535
  dryRun,
539
536
  };
540
537
  }
@@ -591,10 +588,10 @@ export function renderStoryInitCommentBody(result) {
591
588
  epicId: result.epicId,
592
589
  storyBranch: result.storyBranch,
593
590
  epicBranch: result.epicBranch,
594
- // Hierarchy mode is always `'3-tier'` after Task #3154 deleted the
591
+ // Hierarchy mode is always `'2-tier'` after Task #3154 deleted the
595
592
  // `planning.hierarchy` flag. Persisted so resumed runs can read it
596
593
  // without re-resolving anything in the worker.
597
- hierarchy: result.hierarchy ?? '3-tier',
594
+ hierarchy: result.hierarchy ?? '2-tier',
598
595
  worktreeEnabled: result.worktreeEnabled,
599
596
  workCwd: result.workCwd,
600
597
  worktreeCreated: result.worktreeCreated,
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * story-phase.js — phase snapshot + heartbeat writer (3-tier).
4
+ * story-phase.js — phase snapshot + heartbeat writer (2-tier).
5
5
  *
6
6
  * Replaces the deleted per-Task progress writer from the 4-tier era
7
- * (removed under #3157). `/story-deliver` calls this CLI at each Story-
7
+ * (removed under #3157). `/deliver` calls this CLI at each Story-
8
8
  * level phase transition (init → implementing → closing → done, or any
9
9
  * → blocked). Each call:
10
10
  *
@@ -14,7 +14,7 @@
14
14
  * longer posts a `story-run-progress` comment (the redundant mid-flight
15
15
  * progress surface was deleted); the snapshot is render-only.
16
16
  * 2. Appends one `story.heartbeat` lifecycle record to
17
- * `temp/epic-<epicId>/lifecycle.ndjson` so `/epic-deliver`'s
17
+ * `temp/epic-<epicId>/lifecycle.ndjson` so `/deliver`'s
18
18
  * §2e Idle Watchdog (`wave-tick.js --check-idle 30`) can confirm
19
19
  * forward progress without polling the Story comment.
20
20
  *
@@ -35,7 +35,7 @@
35
35
  *
36
36
  * `renderedBody` is the markdown body upserted onto the Story so the
37
37
  * caller can relay it to chat verbatim (mirrors the contract the deleted
38
- * per-Task progress writer exposed and that `/story-deliver` Step 1 / 3
38
+ * per-Task progress writer exposed and that `/deliver` Step 1 / 3
39
39
  * already documents).
40
40
  */
41
41
 
@@ -175,7 +175,7 @@ async function resolveStoryBranch({ provider, storyId }) {
175
175
  * lease-owner handle the SAME way the lease primitive does
176
176
  * (`normalizeOperatorHandle(github.operatorHandle)`) and stamps it as
177
177
  * `operator` so `latestHeartbeatForOwner({ epicId, owner })` resolves a real
178
- * heartbeat — without it `isClaimLive(null)` is false and /epic-deliver
178
+ * heartbeat — without it `isClaimLive(null)` is false and /deliver
179
179
  * silently reclaims a live foreign claim (audit #3513). The field is attached
180
180
  * only when a handle resolves, preserving the "omit when absent" shape for
181
181
  * repos that have not configured `github.operatorHandle`. A failed append is
@@ -2,9 +2,9 @@
2
2
  /* node:coverage ignore file */
3
3
 
4
4
  /**
5
- * story-plan.js — Local `/story-plan` wrapper.
5
+ * story-plan.js — Local `/plan` wrapper.
6
6
  *
7
- * Standalone counterpart to `/epic-plan` for Stories that do **not**
7
+ * Standalone counterpart to `/plan` for Stories that do **not**
8
8
  * attach to an Epic. The script is deliberately a thin CLI around the
9
9
  * pure helpers in `lib/story-plan.js`:
10
10
  *
@@ -24,7 +24,7 @@
24
24
  * GitHub. Echoes the rendered body and the `gh` argv it would
25
25
  * have run.
26
26
  *
27
- * Mirrors the `/epic-plan` pattern: deterministic Node I/O wrappers
27
+ * Mirrors the `/plan` pattern: deterministic Node I/O wrappers
28
28
  * with HITL gating handled by the host LLM in chat. No external LLM
29
29
  * APIs are called from this script.
30
30
  */
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * Use this from workflow markdown when the operator needs to sync a
8
8
  * working branch with `origin/<baseBranch>` before opening a PR — for
9
- * example as a pre-Phase-6 step in `/epic-deliver` so the Epic→main PR
9
+ * example as a pre-Phase-6 step in `/deliver` so the Epic→main PR
10
10
  * opens with the latest `main` commits already integrated.
11
11
  *
12
12
  * For `/single-story-deliver`, the sync runs in-process inside
@@ -201,7 +201,7 @@ export function renderFreshnessFailureMessage(epicId) {
201
201
  return (
202
202
  `[docs-freshness] ❌ Documentation freshness gate FAILED for Epic #${epicId}.\n\n` +
203
203
  `Update each failing file so its commit message or body references #${epicId}, ` +
204
- `then re-run /epic-deliver.`
204
+ `then re-run /deliver.`
205
205
  );
206
206
  }
207
207
 
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * Reads the `epic-run-state` checkpoint plus fresh Story labels and
8
8
  * prints one `WaveTickResult` envelope. The slash-command operator
9
- * (`/epic-deliver`) consumes the envelope to decide whether to dispatch
9
+ * (`/deliver`) consumes the envelope to decide whether to dispatch
10
10
  * the next wave, observe in-flight stories, or finalize the Epic.
11
11
  *
12
12
  * Usage:
@@ -4,7 +4,7 @@ description: >-
4
4
  Aggregate per-Story or per-Epic execution signals into a structured
5
5
  perf-summary or perf-report and upsert it onto the corresponding GitHub
6
6
  ticket. Use after a Story closes (Story mode) or as part of
7
- `/epic-deliver` Phase 6 (Epic mode). Reads NDJSON via
7
+ `/deliver` Phase 6 (Epic mode). Reads NDJSON via
8
8
  `lib/signals/read` and writes a single structured comment.
9
9
  allowed_tools:
10
10
  - Read
@@ -36,7 +36,7 @@ into the Epic dashboard.
36
36
  pipeline dispatches this Skill (or the wrapping script) to roll up the
37
37
  Story's NDJSON signals into a single `<!-- structured:story-perf-summary -->`
38
38
  marker comment on the Story ticket.
39
- - **Epic mode** — during `/epic-deliver` Phase 6.0 (or the retro
39
+ - **Epic mode** — during `/deliver` Phase 6.0 (or the retro
40
40
  composer), the Skill fans out across every Story under the Epic,
41
41
  reads each Story's structured perf summary, and posts a single
42
42
  `<!-- structured:epic-perf-report -->` marker on the Epic ticket.
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: epic-plan-consolidate
3
3
  description: >-
4
- Run a holistic, pre-persist consolidation pass over the draft Feature/Story
4
+ Run a holistic, pre-persist consolidation pass over the draft Story
5
5
  ticket array an Epic's decompose phase produced. Use during Phase 8 of
6
- `/epic-plan`, after `epic-plan-decompose-author` writes
6
+ `/plan`, after `epic-plan-decompose-author` writes
7
7
  `temp/epic-<Epic_ID>/tickets.json` and before `epic-plan-decompose.js`
8
8
  validates and persists it. Reconciles the draft against the Tech Spec
9
9
  "Delivery Slicing" target via scope-preserving operations only.
@@ -19,13 +19,12 @@ allowed_tools:
19
19
 
20
20
  - Run only after `epic-plan-decompose-author` has written `temp/epic-<Epic_ID>/tickets.json`; fail loudly if the draft array is missing. Read the PRD / Tech Spec from `temp/epic-<Epic_ID>/decomposer-context.json` (the same envelope the author skill consumed) — never re-fetch from GitHub, and never call the GitHub API from this Skill.
21
21
  - Emit exactly two artifacts inside `temp/epic-<Epic_ID>/`: the **consolidated** `tickets.json` (overwriting the draft array in place) and a human-readable `consolidation-report.md` (the rationale + before/after diff the operator reviews at the HITL gate). Both MUST exist before returning.
22
- - **Scope conservation is the load-bearing invariant.** You are a *critic*, not a second author: you MUST NOT add scope, invent tickets, or drop acceptance criteria. Every acceptance item and every `verify` entry present in the draft MUST survive into the consolidated array (possibly re-homed onto a merged Story). **This is your contract, not a machine guarantee:** there is **no runtime acceptance-union diff** on your output. The only deterministic runtime backstop the validator applies after you run is `assertNoSingleStoryFeature` (Story #3777) plus the standard ticket-structure validation — neither re-derives the pre-consolidation acceptance/verify union, so a critic that silently dropped an acceptance item would **not** be caught downstream. (The repo's unit test exercises a *pure model* of the merge over an over-fragmented fixture to document the intended invariant; it does not inspect this Skill's actual output.) Conserve scope yourself, deliberately, on every merge.
23
- - Your operations are constrained to exactly four shapes: **(1) merge two or more Stories** into one (union their `changes`/`acceptance`/`verify`/`references`, keep one coherent `goal`); **(2) collapse a single-Story Feature** into a sibling Feature (re-parent its lone Story, drop the empty Feature) — **never** by manufacturing a second Story; **(3) re-parent** a Story to a different sibling Feature; **(4) rewire `depends_on`** so the edges still reference surviving sibling-Story slugs. No other mutation is permitted.
24
- - Consume the Tech Spec **"Delivery Slicing"** section as the authoritative target grouping when one is present: cluster the draft's Stories toward the N shippable Stories the Architect proposed. When the section is **absent**, degrade gracefully — apply only the cohesion + single-Story-Feature rules below and leave the rest of the draft shape intact.
25
- - Implement rec #2: resolve every single-Story Feature by **collapsing** it into a sibling (operation 2), not by splitting its lone Story into two. The `assertNoSingleStoryFeature` validator from Story #3777 stays as the post-consolidation backstop — your output must already satisfy it.
22
+ - **Scope conservation is the load-bearing invariant.** You are a *critic*, not a second author: you MUST NOT add scope, invent tickets, or drop acceptance criteria. Every acceptance item and every `verify` entry present in the draft MUST survive into the consolidated array (possibly re-homed onto a merged Story). **This is your contract, not a machine guarantee:** there is **no runtime acceptance-union diff** on your output. The only deterministic runtime backstop the validator applies after you run is the standard ticket-structure validation — it does not re-derive the pre-consolidation acceptance/verify union, so a critic that silently dropped an acceptance item would **not** be caught downstream. (The repo's unit test exercises a *pure model* of the merge over an over-fragmented fixture to document the intended invariant; it does not inspect this Skill's actual output.) Conserve scope yourself, deliberately, on every merge.
23
+ - Your operations are constrained to exactly two shapes: **(1) merge two or more Stories** into one (union their `changes`/`acceptance`/`verify`/`references`, keep one coherent `goal`); **(2) rewire `depends_on`** so the edges still reference surviving sibling-Story slugs. No other mutation is permitted.
24
+ - Consume the Tech Spec **"Delivery Slicing"** section as the authoritative target grouping when one is present: cluster the draft's Stories toward the N shippable Stories the Architect proposed. When the section is **absent**, degrade gracefully — apply only the cohesion rules below and leave the rest of the draft shape intact.
26
25
  - Apply the same cohesion heuristic the author skill leads with: **one Story = one coherent change with one reason to exist**, and the **single-consumer merge rule** (a Story whose only consumer is one sibling Story is merged into that sibling). Lead every merge decision with the change's reason, not its file count.
27
- - After every merge / collapse / re-parent, **rewire `depends_on`**: drop self-edges, collapse edges that now point at the absorbing Story onto itself, and re-point any edge that named a now-deleted slug at its surviving successor. Never leave a `depends_on` referencing a slug absent from the consolidated array — the validator HARD-rejects unknown deps.
28
- - The consolidation report MUST name each operation applied (merged slugs → surviving slug, collapsed Feature → sibling, re-parented Story, rewired edges) with a one-line reason, plus a before/after Story-count line, so the operator can approve or reject at the HITL diff gate before the persist call.
26
+ - After every merge, **rewire `depends_on`**: drop self-edges, collapse edges that now point at the absorbing Story onto itself, and re-point any edge that named a now-deleted slug at its surviving successor. Never leave a `depends_on` referencing a slug absent from the consolidated array — the validator HARD-rejects unknown deps.
27
+ - The consolidation report MUST name each operation applied (merged slugs → surviving slug, rewired edges) with a one-line reason, plus a before/after Story-count line, so the operator can approve or reject at the HITL diff gate before the persist call.
29
28
 
30
29
  ## Role
31
30
 
@@ -38,7 +37,7 @@ against the Tech Spec's intentional grouping before any GitHub write.
38
37
 
39
38
  ## When to use
40
39
 
41
- `/epic-plan` Phase 8, as the **8.3 — Holistic Consolidation** sub-step:
40
+ `/plan` Phase 8, as the **8.3 — Holistic Consolidation** sub-step:
42
41
  immediately after `epic-plan-decompose-author` writes
43
42
  `temp/epic-<Epic_ID>/tickets.json` and **before**
44
43
  `epic-plan-decompose.js --tickets …` validates and persists. The pass operates
@@ -51,7 +50,7 @@ emit a plan the validator would reject.
51
50
  The dispatcher passes the Epic ID as the Skill argument. The Skill itself
52
51
  reads:
53
52
 
54
- - `temp/epic-<Epic_ID>/tickets.json` — the **draft** Feature/Story array the
53
+ - `temp/epic-<Epic_ID>/tickets.json` — the **draft** Story array the
55
54
  `epic-plan-decompose-author` Skill wrote. This is the consolidation input.
56
55
  - `temp/epic-<Epic_ID>/decomposer-context.json` — the authoring envelope
57
56
  emitted by `epic-plan-decompose.js --emit-context`. Read `prd.body` /
@@ -62,7 +61,7 @@ reads:
62
61
  ## Outputs
63
62
 
64
63
  - `temp/epic-<Epic_ID>/tickets.json` — the **consolidated** array, overwriting
65
- the draft. Same schema as the author skill emits (Feature Story; Stories
64
+ the draft. Same schema as the author skill emits (flat Story array; Stories
66
65
  carry top-level `acceptance[]` / `verify[]`; `body` is a serialized string).
67
66
  The downstream `epic-plan-decompose.js --tickets …` validator is the final
68
67
  gate — author for its rules, not for "looks right."
@@ -83,21 +82,18 @@ anything:
83
82
 
84
83
  1. The **target grouping** — the N shippable Stories the Architect proposed in
85
84
  Delivery Slicing, or `null` when the section is absent (graceful-degrade
86
- mode: cohesion + single-Story-Feature rules only).
87
- 2. The **draft Story count per Feature** — so you can spot single-Story
88
- Features and over-fragmented capability clusters.
85
+ mode: cohesion rules only).
86
+ 2. The **draft Story count** — so you can spot over-fragmented capability
87
+ clusters.
89
88
 
90
89
  ### Step 2 — Plan the consolidation
91
90
 
92
- For each Feature, decide which Stories merge, which collapse, which re-parent:
91
+ Across the draft Story array, decide which Stories merge:
93
92
 
94
- - **Single-Story Feature** → collapse its lone Story into a sibling Feature
95
- whose capability is closest (Delivery-Slicing target, else thematic
96
- proximity). Drop the now-empty Feature. Never split the lone Story.
97
93
  - **Over-fragmented capability** → when several draft Stories map to one
98
94
  Delivery-Slicing target (or one coherent reason to exist), merge them into a
99
95
  single Story: union their `changes` / `acceptance` / `verify` / `references`,
100
- write one `goal` naming the parent Feature, and keep the union of labels.
96
+ write one coherent `goal`, and keep the union of labels.
101
97
  - **Single-consumer Story** → merge into the one sibling that consumes it.
102
98
 
103
99
  Record each decision with its one-line reason for the report.
@@ -120,7 +116,7 @@ Write the consolidated array to `temp/epic-<Epic_ID>/tickets.json` (2-space
120
116
  indent, machine-consumed) and the rationale + before/after diff to
121
117
  `temp/epic-<Epic_ID>/consolidation-report.md`.
122
118
 
123
- ### Step 5 — Hand back to `/epic-plan`
119
+ ### Step 5 — Hand back to `/plan`
124
120
 
125
121
  Return control. The workflow shows the operator the consolidation report at the
126
122
  HITL diff gate; on approval it runs
@@ -133,13 +129,12 @@ persists the hierarchy, and flips the Epic to `agent::ready`.
133
129
  - Do **not** call the GitHub API from this Skill. It reads two temp artifacts
134
130
  and writes two temp artifacts; persistence belongs to the script.
135
131
  - Do **not** write outside `temp/epic-<Epic_ID>/`.
136
- - Do **not** add scope or invent tickets. The four permitted operations (merge
137
- Stories, collapse single-Story Features, re-parent, rewire `depends_on`) are
138
- exhaustive — anything else is out of contract.
132
+ - Do **not** add scope or invent tickets. The two permitted operations (merge
133
+ Stories, rewire `depends_on`) are exhaustive — anything else is out of
134
+ contract.
139
135
  - If `temp/epic-<Epic_ID>/tickets.json` is missing, fail loudly and instruct
140
136
  the caller to run the `epic-plan-decompose-author` Skill first.
141
137
  - The validator
142
138
  ([`lib/orchestration/ticket-validator.js`](../../../scripts/lib/orchestration/ticket-validator.js))
143
- is the authoritative post-consolidation gate including
144
- `assertNoSingleStoryFeature`. Re-consolidate when it rejects rather than
145
- patching tickets by hand.
139
+ is the authoritative post-consolidation gate. Re-consolidate when it
140
+ rejects rather than patching tickets by hand.
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: epic-plan-decompose-author
3
3
  description: >-
4
- Author the Feature/Story ticket JSON for an Epic from the decomposer
4
+ Author the Story ticket JSON for an Epic from the decomposer
5
5
  authoring context emitted by `epic-plan-decompose.js --emit-context`. Use
6
- during Phase 8 of `/epic-plan` when the host LLM needs to write the ticket
6
+ during Phase 8 of `/plan` when the host LLM needs to write the ticket
7
7
  array before `epic-plan-decompose.js` validates and persists it.
8
8
  allowed_tools:
9
9
  - Read
@@ -18,10 +18,10 @@ allowed_tools:
18
18
  - Run only after `epic-plan-decompose.js --emit-context` has written `temp/epic-<Epic_ID>/decomposer-context.json`; fail loudly if the file is missing.
19
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
20
  - Output is JSON only — no prose, no Markdown fence. The downstream validator (`lib/orchestration/ticket-validator.js`) is the authoritative gate; re-author rather than hand-patching when it rejects.
21
- - 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` field at the top of the first Feature's `body` explaining why the plan exceeds the budget. Operator persistence then requires the explicit `--allow-over-budget` override on `epic-plan-decompose.js`; without it the persist step rejects the over-budget array. Never truncate the JSON array to fit.
22
- - Honour the two-level hierarchy under each Epic: **Feature Story**. Stories carry the implementation scope inline; no lower ticket tier exists.
23
- - **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. Every Feature MUST decompose into at least TWO Stories; the validator HARD-rejects a single-Story Feature. See the STORY SIZING section for the full guidance and the single-consumer merge rule.
24
- - Every ticket carries `type::[feature|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.
21
+ - 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 `epic-plan-decompose.js`; without it the persist step rejects the over-budget array. Never truncate the JSON array to fit.
22
+ - 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.
23
+ - **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.
24
+ - 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.
25
25
  - **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.
26
26
  - 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.
27
27
  - 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).
@@ -31,12 +31,12 @@ allowed_tools:
31
31
  ## Role
32
32
 
33
33
  Senior Project Manager + Orchestrator. The Skill's job is to take a PRD plus
34
- a Tech Spec and emit a Feature Story ticket hierarchy the orchestrator
35
- can execute autonomously.
34
+ a Tech Spec and emit a flat Story backlog the orchestrator can execute
35
+ autonomously.
36
36
 
37
37
  ## When to use
38
38
 
39
- `/epic-plan` Phase 8, immediately after
39
+ `/plan` Phase 8, immediately after
40
40
  `epic-plan-decompose.js --emit-context` writes
41
41
  `temp/epic-<Epic_ID>/decomposer-context.json`. The Skill replaces the
42
42
  inline "Author the Ticket Array" step in the legacy workflow body —
@@ -74,7 +74,7 @@ Skill's body below is the authoritative version going forward.
74
74
 
75
75
  ## Outputs
76
76
 
77
- - `temp/epic-<Epic_ID>/tickets.json` — JSON array of Feature/Story
77
+ - `temp/epic-<Epic_ID>/tickets.json` — JSON array of Story
78
78
  objects conforming to the schema in this Skill's body.
79
79
 
80
80
  The file MUST exist before the Skill returns. The caller will then run
@@ -116,7 +116,7 @@ Write the final JSON array to `temp/epic-<Epic_ID>/tickets.json` with
116
116
  the `Write` tool. Do not pretty-print past 2-space indent — the file is
117
117
  machine-consumed.
118
118
 
119
- ### Step 4 — Hand back to `/epic-plan`
119
+ ### Step 4 — Hand back to `/plan`
120
120
 
121
121
  Return control. The caller invokes
122
122
  `node .agents/scripts/epic-plan-decompose.js --epic <Epic_ID> --tickets
@@ -132,17 +132,16 @@ budget (Story #2798) — stay under by default; over-budget plans need an
132
132
 
133
133
  ```text
134
134
  You are an expert Senior Project Manager and Orchestrator.
135
- Your job is to take a Product Requirements Document (PRD) and a Technical Specification and decompose them into a Feature Story ticket hierarchy for an AI Agent to execute.
135
+ Your job is to take a Product Requirements Document (PRD) and a Technical Specification and decompose them into a flat list of Story tickets for an AI Agent to execute.
136
136
 
137
137
  ### HIERARCHY RULES:
138
- 1. **Features**: Large functional milestones (e.g., "Authentication Provider Integration"). Features are navigational containers — no implementation work hangs off the Feature body itself.
139
- 2. **Stories**: Capability-sized, verifiable units of work (e.g., "Implement JWT Token Exchange").
140
- - MUST be nested under a Feature via `parent_slug`.
138
+ 1. **Stories**: Capability-sized, verifiable units of work (e.g., "Implement JWT Token Exchange").
139
+ - Attach directly to the Epic there is NO Feature tier; thematic grouping is prose in the Epic body / Tech Spec.
141
140
  - **Story-Level Execution**: Each Story is executed on a single Story branch (`story-<storyId>`), implemented in one Story-implementation phase, then merged into the Epic branch. The Story body carries the full execution contract (goal, changes, acceptance, verify).
142
- - Do NOT emit a lower ticket tier — the validator only accepts `type::feature` and `type::story`.
141
+ - Do NOT emit any other ticket tier — the validator only accepts `type::story`.
143
142
 
144
143
  ### LABEL CONVENTIONS:
145
- - Every ticket must have a `type::[feature|story]` label.
144
+ - Every ticket must have the `type::story` label.
146
145
  - Every ticket must have a `persona::[engineer|architect|qa-engineer|engineer-web|etc]` label indicating WHO should execute it.
147
146
 
148
147
  ### OUTPUT FORMAT:
@@ -152,48 +151,18 @@ You MUST respond ONLY with a valid JSON array of objects. No prose, no markdown
152
151
  [
153
152
  {
154
153
  "slug": "hyphen-case-id",
155
- "type": "feature" | "story",
154
+ "type": "story",
156
155
  "title": "Short descriptive title",
157
156
  "body": <string — see BODY RULES below>,
158
157
  "acceptance": ["<testable criterion>", ...], // STORIES ONLY — top-level, read by validator
159
158
  "verify": ["<exact command> (<tier>)", ...], // STORIES ONLY — top-level, read by validator
160
- "labels": ["type::...", "persona::..."],
161
- "parent_slug": "slug_of_parent_ticket" (leave empty for features to nest under epic; required for stories — must point at a sibling Feature),
159
+ "labels": ["type::story", "persona::..."],
162
160
  "depends_on": ["slug_of_blocking_dependency"] (optional array of Story slugs that block execution)
163
161
  }
164
162
  ]
165
163
 
166
164
  **Slug format**: `^[a-z0-9][a-z0-9-]*$` — hyphen-case only. Underscores are rejected by the validator.
167
165
 
168
- ### FEATURE BODY:
169
- For Features, `body` is a brief string under 2 sentences. Features are navigational — the work happens at the Story level — so dense bodies waste output budget.
170
-
171
- FEATURE GROUPING — CAPABILITY/STAKEHOLDER, NOT EXECUTION SHAPE:
172
-
173
- - Do not group Stories by technical execution shape (cron jobs, middleware, scripts). Group by the capability or stakeholder they serve. Two Stories that happen to share a delivery mechanism — both are cron sweeps, both are Express middleware, both are CLI scripts — do NOT belong in the same Feature just because of that shared shape. The Feature axis is the user-facing capability or the stakeholder served, never the implementation vehicle.
174
- - Operational/compliance work gets its own Feature. Retention purges, audit-log sweeps, scheduled cleanups, observability emitters, and other operational/compliance chores serve operators and compliance, not end users. Place them in a dedicated `compliance-and-observability` or `data-retention` Feature — do NOT fold them into a user-facing Feature (e.g. notification flows) merely because they share a cron/scheduled execution shape with user-facing Stories.
175
-
176
- ANTI-PATTERN (based on Epic #18 -> Feature #1446):
177
-
178
- A decomposition produced a Feature "Notification flows: reminders, schedule-change, retention" grouping three Stories. WRONG — grouped by execution shape (all three are cron sweeps):
179
-
180
- Feature: notification-flows ("Notification flows: reminders, schedule-change, retention")
181
- [X] Story: send-appointment-reminders (user-facing: emails patients)
182
- [X] Story: send-schedule-change-notices (user-facing: emails patients)
183
- [X] Story: purge-email-audit-log-retention (compliance: deletes audit rows past retention)
184
-
185
- The email audit-log retention purge was folded in only because all three run as scheduled cron jobs — a shared execution shape, not a shared capability. The purge serves compliance/operators, not the patients the other two Stories notify. CORRECT — regroup by capability/stakeholder:
186
-
187
- Feature: notification-flows ("Patient notification flows")
188
- Story: send-appointment-reminders (user-facing)
189
- Story: send-schedule-change-notices (user-facing)
190
- Feature: compliance-and-observability ("Data-retention and audit-log compliance")
191
- Story: purge-email-audit-log-retention (compliance)
192
-
193
- The cron shape is the false grouping signal. Once the retention purge has a sibling under a dedicated compliance Feature it ceases to be a lone-Story Feature (which the validator would reject); pair it with other operational/compliance sweeps (e.g. a session-token cleanup or a metrics-rollup job) under the same `compliance-and-observability` Feature.
194
-
195
- - Smell test: if the only thing two Stories have in common is how they run (a scheduled job, a request interceptor, a build step) rather than whom they serve or what capability they deliver, they are mis-grouped. Re-home the operational/compliance Story into its own capability Feature.
196
-
197
166
  ### STORY BODY SCHEMA (REQUIRED FOR EVERY STORY):
198
167
  For Stories, `body` MUST be a **string** — the serialized markdown produced by calling `serialize()` from `lib/story-body/story-body.js`. Do NOT emit `body` as a JSON object: `createOp` in `epic-spec-reconciler-ops.js` will throw `StoryBodyParseError` when it receives an object body (Story #3302 serialize-or-throw contract), and `composeStoryBody` in the GitHub provider also discards non-string bodies producing an empty issue. The canonical pipeline requires a serialized string body end-to-end. The freshness gate (`collectTaskChangesPaths`) and the assumption gate (`collectStoryAssumptionEntries`) both parse the string body via `story-body.js#parse` to recover `changes[]`/`references[]` — they operate correctly only on the serialized string form.
199
168
 
@@ -202,7 +171,7 @@ The `acceptance[]` and `verify[]` arrays live at the **top level** of the Story
202
171
  The serialized `body` string renders these markdown sections (in order):
203
172
 
204
173
  ## Goal
205
- <one sentence — why this Story exists; tie it to the parent Feature slug>
174
+ <one sentence — why this Story exists within the Epic>
206
175
 
207
176
  ## Changes
208
177
  - {"path": "<file path>", "assumption": "creates" | "refactors-existing" | "deletes"}
@@ -225,7 +194,7 @@ Fields `wide` and `estimated_test_files` are encoded as a `<!-- meta: {...} -->`
225
194
  #### STORY BODY RULES:
226
195
 
227
196
  - **slug**: MUST be hyphen-case (`^[a-z0-9][a-z0-9-]*$`). Do not use underscores.
228
- - **goal** (in body string): One sentence stating WHY this Story exists. SHOULD name the parent Feature slug.
197
+ - **goal** (in body string): One sentence stating WHY this Story exists within the Epic.
229
198
  - **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.
230
199
  - **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.
231
200
  - **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.
@@ -245,9 +214,8 @@ The first question is **cohesion, not count**: *is this one coherent change with
245
214
 
246
215
  - **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.
247
216
  - **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.
248
- - **Split independent, parallelizable work** into sibling Stories under the same Feature — but only when the pieces genuinely have separate reasons to exist.
217
+ - **Split independent, parallelizable work** into sibling Stories — but only when the pieces genuinely have separate reasons to exist.
249
218
  - **Declare `wide` with a one-line reason when a change is legitimately broad** (a cohesive cutover that spans many files for one reason).
250
- - **Every Feature MUST decompose into at least TWO Stories.** A Feature with a single Story is the work of a Story, not a Feature. **Resolve it by COLLAPSING, not splitting** — drop the Feature wrapper and attach its lone Story to a sibling Feature (or merge the Feature into another). Do NOT manufacture a second Story to satisfy the rule; splitting a lone Story into two inflates ticket count and defeats the "fewer, right-sized Stories" goal. The validator (`ticket-validator.js` → `assertNoSingleStoryFeature`) HARD-rejects a decomposition containing a Feature with fewer than two Stories, naming the offending Feature; the Phase 8 consolidation pass (`epic-plan-consolidate`) performs the collapse holistically before the validator runs.
251
219
 
252
220
  **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:
253
221
 
@@ -291,7 +259,7 @@ The Acceptance Spec's AC table (columns `AC ID | Outcome | Feature File | Scenar
291
259
 
292
260
  When the Acceptance Spec 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:
293
261
 
294
- - **goal** (in body string): contains the literal token `bdd-scaffold` and names the parent Feature slug.
262
+ - **goal** (in body string): contains the literal token `bdd-scaffold`.
295
263
  - **depends_on**: EMPTY (`[]`) — the scaffold runs first, in wave 0.
296
264
  - **changes** (in body string): one `{ path, assumption: "creates" }` entry per distinct `.feature` file named in a `new` row.
297
265
  - **acceptance** (top-level array): MUST assert (a) every new `.feature` file exists, and (b) every new scenario within them carries an `@skip` tag. Keep items observable (a command exits 0; a file exists at a path).
@@ -306,7 +274,6 @@ When the Acceptance Spec contains **zero `new`-disposition rows** (every row is
306
274
  "slug": "scaffold-billing-feature-files",
307
275
  "type": "story",
308
276
  "title": "Scaffold @skip-tagged billing feature files",
309
- "parent_slug": "billing-flows",
310
277
  "depends_on": [],
311
278
  "labels": ["type::story", "persona::qa-engineer"],
312
279
  "acceptance": [
@@ -398,7 +365,7 @@ Do NOT silently allow two Stories to write the same root configuration
398
365
  file in the same wave; parallel dispatch would produce a merge conflict
399
366
  on every Story-to-Epic close after the first.
400
367
 
401
- CRITICAL: Dependencies should follow execution blockers. For hierarchical grouping, strongly strictly use 'parent_slug' (Story parent MUST be a Feature). Features should have no 'parent_slug' (they attach to Epic).
368
+ CRITICAL: Dependencies should follow execution blockers. Stories attach directly to the Epic never emit a 'parent_slug' field.
402
369
  IMPORTANT DEPENDENCY RULE: A Story's `depends_on` MUST only reference other Stories within the SAME Epic. If two Stories have a logical ordering requirement, express it via Story-level `depends_on`.
403
370
  WARNING: You MUST conserve your output limit. Do NOT generate more than ${maxTickets} tickets in total. Merge narrow work into cohesive capability Stories. Do NOT cut off the JSON array prematurely!
404
371
 
@@ -3,7 +3,7 @@ name: epic-plan-spec-author
3
3
  description: >-
4
4
  Author the PRD, Tech Spec, Acceptance Spec markdown, and risk-verdict JSON
5
5
  for an Epic from the planner authoring context emitted by
6
- `epic-plan-spec.js --emit-context`. Use during Phase 7 of `/epic-plan` when
6
+ `epic-plan-spec.js --emit-context`. Use during Phase 7 of `/plan` when
7
7
  the host LLM needs to write the four artifacts before `epic-plan-spec.js`
8
8
  persists them.
9
9
  allowed_tools:
@@ -16,7 +16,7 @@ allowed_tools:
16
16
 
17
17
  ## Policy Capsule
18
18
 
19
- - Run only during `/epic-plan` Phase 7, after `epic-plan-spec.js --emit-context` has written `temp/epic-<Epic_ID>/planner-context.json`; fail loudly if the file is missing rather than fabricating context.
19
+ - Run only during `/plan` Phase 7, after `epic-plan-spec.js --emit-context` has written `temp/epic-<Epic_ID>/planner-context.json`; fail loudly if the file is missing rather than fabricating context.
20
20
  - Write exactly four artifacts and only inside `temp/epic-<Epic_ID>/`: `prd.md`, `techspec.md`, `risk-verdict.json`, `acceptance-spec.md`. All four MUST exist on disk before returning.
21
21
  - Start each markdown artifact at the correct `##` heading (PRD → `## Overview`, Tech Spec → `## Technical Overview`, Acceptance Spec → `## Acceptance Criteria`) — never emit a top-level `#` heading. `risk-verdict.json` is raw JSON conforming to `.agents/schemas/risk-verdict.schema.json`.
22
22
  - Judge risk from what the change *does* (the PRD / Tech Spec you just wrote), never from keyword presence — "out of scope: billing" is not a billing change; "rotate the credential vault" is high-risk even without a security keyword.
@@ -40,7 +40,7 @@ the Acceptance Spec).
40
40
 
41
41
  ## When to use
42
42
 
43
- `/epic-plan` Phase 7, immediately after `epic-plan-spec.js --emit-context`
43
+ `/plan` Phase 7, immediately after `epic-plan-spec.js --emit-context`
44
44
  writes `temp/epic-<Epic_ID>/planner-context.json`. This Skill replaces the
45
45
  inline "Author the PRD" / "Author the Tech Spec" steps from the legacy
46
46
  workflow body — the calling workflow dispatches this Skill via the `Skill`
@@ -366,7 +366,7 @@ CRITICAL REQUIREMENTS:
366
366
  - Acceptance Outcomes MUST NOT prescribe a commit subject that begins with a non-Conventional-Commits prefix (allowed leading types: feat|fix|chore|refactor|perf|docs|style|test|build|ci|revert). The legacy `baseline-refresh` token used as a leading subject prescription is forbidden — commitlint will reject it at commit time, and the decompose-time validator (`ticket-validator.js` → `validateAcceptanceSubjectPrefix`) will reject the decompose with `code: 'forbidden-subject-prefix'`. Use a Conventional-Commits subject (e.g. `chore(baselines): refresh ...`) and a body trailer (e.g. `baseline-refresh: true` — trailer with a value, not a subject prefix) when a machine-readable marker is needed. See Epic #2501 for rationale.
367
367
  ```
368
368
 
369
- ### Step 6 — Hand back to `/epic-plan`
369
+ ### Step 6 — Hand back to `/plan`
370
370
 
371
371
  All four files exist; return. The caller will run
372
372
  `node .agents/scripts/epic-plan-spec.js --epic <Epic_ID> --prd
@@ -25,8 +25,8 @@ allowed_tools:
25
25
 
26
26
  ## Role
27
27
 
28
- Context aggregator. Resolves a ticket's hierarchy (TaskStory →
29
- Feature → Epic) and stitches the linked planning artifacts into a
28
+ Context aggregator. Resolves a ticket's hierarchy (StoryEpic)
29
+ and stitches the linked planning artifacts into a
30
30
  single prompt the executor consumes.
31
31
 
32
32
  ## When to use