mandrel 1.80.0 → 1.82.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 (101) hide show
  1. package/.agents/README.md +5 -5
  2. package/.agents/docs/SDLC.md +93 -80
  3. package/.agents/docs/configuration.md +11 -1
  4. package/.agents/docs/quality-gates.md +61 -0
  5. package/.agents/docs/workflows.md +1 -1
  6. package/.agents/instructions.md +9 -7
  7. package/.agents/personas/architect.md +8 -5
  8. package/.agents/personas/engineer-mobile.md +3 -2
  9. package/.agents/personas/engineer-web.md +3 -2
  10. package/.agents/personas/engineer.md +6 -5
  11. package/.agents/personas/product.md +19 -13
  12. package/.agents/personas/project-manager.md +9 -8
  13. package/.agents/personas/qa-engineer.md +10 -6
  14. package/.agents/personas/refactorer.md +3 -2
  15. package/.agents/personas/technical-writer.md +2 -1
  16. package/.agents/personas/ux-designer.md +2 -2
  17. package/.agents/schemas/agentrc.schema.json +10 -0
  18. package/.agents/scripts/acceptance-spec-reconciler.js +143 -59
  19. package/.agents/scripts/epic-deliver-prepare.js +0 -31
  20. package/.agents/scripts/epic-plan-decompose.js +2 -5
  21. package/.agents/scripts/epic-plan-spec.js +16 -19
  22. package/.agents/scripts/hierarchy-gate.js +11 -11
  23. package/.agents/scripts/lib/ITicketingProvider.js +4 -3
  24. package/.agents/scripts/lib/baselines/env-overrides.js +35 -0
  25. package/.agents/scripts/lib/bdd-runner-detect.js +1 -1
  26. package/.agents/scripts/lib/bdd-scenario-scanner.js +1 -1
  27. package/.agents/scripts/lib/cli-args.js +1 -5
  28. package/.agents/scripts/lib/codebase-snapshot.js +1 -1
  29. package/.agents/scripts/lib/config/temp-paths.js +1 -4
  30. package/.agents/scripts/lib/config-settings-schema.js +5 -0
  31. package/.agents/scripts/lib/epic-body-sections.js +222 -0
  32. package/.agents/scripts/lib/epic-plan-clarity.js +38 -1
  33. package/.agents/scripts/lib/epic-plan-ideation.js +15 -3
  34. package/.agents/scripts/lib/label-constants.js +7 -17
  35. package/.agents/scripts/lib/label-taxonomy.js +4 -21
  36. package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +47 -1
  37. package/.agents/scripts/lib/orchestration/check-baselines/phases/parse-args.js +7 -0
  38. package/.agents/scripts/lib/orchestration/check-baselines/phases/pipeline.js +1 -1
  39. package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +2 -1
  40. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +19 -8
  41. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +23 -22
  42. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +7 -10
  43. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +4 -38
  44. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +8 -9
  45. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/authoring-context.js +11 -5
  46. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/cli-args.js +26 -5
  47. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +102 -304
  48. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +32 -29
  49. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +19 -20
  50. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-authoring-grounding.js +1 -1
  51. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +6 -9
  52. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +3 -4
  53. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +1 -1
  54. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +20 -27
  55. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +11 -5
  56. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +22 -59
  57. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +1 -1
  58. package/.agents/scripts/lib/orchestration/planning-context-budget.js +1 -1
  59. package/.agents/scripts/lib/orchestration/preflight-cache.js +1 -1
  60. package/.agents/scripts/lib/orchestration/spec-freshness.js +3 -3
  61. package/.agents/scripts/lib/orchestration/spec-section-validator.js +1 -1
  62. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +122 -1
  63. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +5 -8
  64. package/.agents/scripts/lib/orchestration/ticketing/reads.js +2 -2
  65. package/.agents/scripts/lib/plan-phase-cleanup.js +1 -2
  66. package/.agents/scripts/lib/qa/qa-context-hydrator.js +6 -85
  67. package/.agents/scripts/lib/templates/decomposer-prompts.js +14 -8
  68. package/.agents/scripts/lifecycle-emit.js +1 -1
  69. package/.agents/scripts/lint-label-vocabulary.js +2 -3
  70. package/.agents/scripts/providers/github/mappers.js +0 -3
  71. package/.agents/scripts/providers/github/tickets.js +7 -18
  72. package/.agents/scripts/single-story-init.js +0 -1
  73. package/.agents/scripts/story-init.js +1 -29
  74. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +37 -18
  75. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +23 -18
  76. package/.agents/skills/core/epic-plan-premortem/SKILL.md +7 -6
  77. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +161 -109
  78. package/.agents/skills/core/hydrate-context/SKILL.md +10 -5
  79. package/.agents/skills/core/knowledge-transfer/SKILL.md +3 -2
  80. package/.agents/skills/core/scope-triage/SKILL.md +2 -1
  81. package/.agents/skills/skills.index.json +6 -6
  82. package/.agents/templates/epic-from-idea.md +4 -0
  83. package/.agents/workflows/audit-to-stories.md +2 -2
  84. package/.agents/workflows/helpers/code-review.md +11 -9
  85. package/.agents/workflows/helpers/deliver-epic.md +32 -44
  86. package/.agents/workflows/helpers/epic-audit.md +11 -8
  87. package/.agents/workflows/helpers/epic-deliver-story.md +10 -16
  88. package/.agents/workflows/helpers/epic-plan-decompose.md +17 -12
  89. package/.agents/workflows/helpers/epic-plan-spec.md +68 -68
  90. package/.agents/workflows/helpers/parallel-tooling.md +2 -1
  91. package/.agents/workflows/helpers/plan-epic.md +114 -99
  92. package/.agents/workflows/helpers/single-story-deliver.md +1 -1
  93. package/.agents/workflows/helpers/worktree-lifecycle.md +1 -1
  94. package/.agents/workflows/plan.md +8 -8
  95. package/.agents/workflows/qa-assist.md +2 -1
  96. package/docs/CHANGELOG.md +28 -0
  97. package/package.json +1 -1
  98. package/.agents/scripts/lib/issue-link-parser.js +0 -74
  99. package/.agents/scripts/lib/orchestration/finalize/close-planning-tickets.js +0 -116
  100. package/.agents/scripts/lib/orchestration/planning-state-manager.js +0 -318
  101. package/.agents/scripts/lib/story-init/hierarchy-tracer.js +0 -57
@@ -6,7 +6,7 @@ description: >-
6
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
- "Delivery Slicing" target via scope-preserving operations only.
9
+ "Delivery Slicing" ceiling via scope-preserving operations only.
10
10
  allowed_tools:
11
11
  - Read
12
12
  - Write
@@ -17,22 +17,22 @@ allowed_tools:
17
17
 
18
18
  ## Policy Capsule
19
19
 
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.
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 sectioned Epic body (which carries the folded Tech Spec sections) 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
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
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.
24
+ - Consume the Tech Spec **"Delivery Slicing"** section as a **ceiling, not a target**, when one is present: the Architect's proposed N shippable Stories is an *upper bound*, not a floor. Cluster the draft's Stories toward that grouping, and go **below** N when slices form dependent single-consumer chains — a slice whose "Independent? No" row carries no justification (parallelism, risk isolation, or delivery-envelope pressure) folds into its consumer. You **never** split above N. When the section is **absent**, degrade gracefully — apply only the cohesion rules below and leave the rest of the draft shape intact.
25
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.
26
26
  - **Missing reason-to-exist check (cohesion gate).** Every draft Story body MUST carry a non-empty `reason_to_exist` meta field (the parseable form of "one Story = one coherent change with one reason to exist", encoded in the `<!-- meta: {"reason_to_exist": "..."} -->` comment and surfaced as `body.reason_to_exist` by `lib/story-body/story-body.js`). Flag any Story whose body carries **no** non-empty reason to exist: a Story that cannot state its single reason in one sentence is a cohesion smell — it is probably two Stories, or two Stories that should be merged into one. Name each flagged Story in the consolidation report so the operator sees the cohesion gap at the HITL diff gate.
27
27
  - 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.
28
- - 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.
28
+ - 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. When the consolidated count drops **below** the Delivery-Slicing count (a below-ceiling coarsening), the report MUST surface that fact explicitly — e.g. `Below ceiling: N (Delivery Slicing) → M (consolidated)` — and attach a one-line rationale to each below-ceiling merge (which dependent single-consumer slice folded into which consumer, and why it was unjustified), so the operator sees the coarsening at the Phase 8.3 advisory diff.
29
29
 
30
30
  ## Role
31
31
 
32
32
  Senior Project Manager + Orchestrator, acting as a **holistic critic** with
33
33
  fresh context. This Skill is deliberately *separate* from
34
34
  `epic-plan-decompose-author` (the generator): a same-pass self-critique is the
35
- weak mode this is built to escape. The generator maps PRD capabilities to
35
+ weak mode this is built to escape. The generator maps Epic capabilities to
36
36
  Stories ~1:1; this critic steps back and looks at the *whole* decomposition
37
37
  against the Tech Spec's intentional grouping before any GitHub write.
38
38
 
@@ -54,10 +54,13 @@ reads:
54
54
  - `temp/epic-<Epic_ID>/tickets.json` — the **draft** Story array the
55
55
  `epic-plan-decompose-author` Skill wrote. This is the consolidation input.
56
56
  - `temp/epic-<Epic_ID>/decomposer-context.json` — the authoring envelope
57
- emitted by `epic-plan-decompose.js --emit-context`. Read `prd.body` /
58
- `prd` and `techSpec.body` / `techSpec` from it. The **"Delivery Slicing"**
59
- section (authored by `epic-plan-spec-author` in the Tech Spec) is the
60
- target grouping when present; degrade gracefully when it is absent.
57
+ emitted by `epic-plan-decompose.js --emit-context`. Read `epicBody`
58
+ from it the sectioned Epic body carrying the folded Tech Spec
59
+ sections (there is no separate `techSpec` key Story #4324). The
60
+ **"Delivery Slicing"**
61
+ section (authored by `epic-plan-spec-author`) is the
62
+ grouping **ceiling** when present (you may merge below it, never split above
63
+ it); degrade gracefully when it is absent.
61
64
 
62
65
  ## Outputs
63
66
 
@@ -74,16 +77,21 @@ Both files MUST exist before the Skill returns.
74
77
 
75
78
  ## Procedure
76
79
 
77
- ### Step 1 — Load the draft and the target
80
+ ### Step 1 — Load the draft and the ceiling
78
81
 
79
82
  Read `temp/epic-<Epic_ID>/tickets.json` (the draft array) and
80
- `temp/epic-<Epic_ID>/decomposer-context.json` (for the PRD / Tech Spec). Locate
81
- the Tech Spec **"Delivery Slicing"** section. Pin two facts before mutating
83
+ `temp/epic-<Epic_ID>/decomposer-context.json` (for the `epicBody`, which
84
+ carries the Tech Spec sections). Locate
85
+ the **"Delivery Slicing"** section. Pin two facts before mutating
82
86
  anything:
83
87
 
84
- 1. The **target grouping** — the N shippable Stories the Architect proposed in
88
+ 1. The **grouping ceiling** — the N shippable Stories the Architect proposed in
85
89
  Delivery Slicing, or `null` when the section is absent (graceful-degrade
86
- mode: cohesion rules only).
90
+ mode: cohesion rules only). Treat N as an upper bound you may go below, not a
91
+ floor you must hit. Note which slices are marked "Independent? No" and
92
+ whether each carries a justification (parallelism, risk isolation, or
93
+ delivery-envelope pressure) — an unjustified dependent slice is a
94
+ fold-into-consumer candidate.
87
95
  2. The **draft Story count** — so you can spot over-fragmented capability
88
96
  clusters.
89
97
 
@@ -92,17 +100,23 @@ anything:
92
100
  Across the draft Story array, decide which Stories merge:
93
101
 
94
102
  - **Over-fragmented capability** → when several draft Stories map to one
95
- Delivery-Slicing target (or one coherent reason to exist), merge them into a
103
+ Delivery-Slicing slice (or one coherent reason to exist), merge them into a
96
104
  single Story: union their `changes` / `acceptance` / `verify` / `references`,
97
105
  write one coherent `goal`, and keep the union of labels.
98
- - **Single-consumer Story** → merge into the one sibling that consumes it.
106
+ - **Single-consumer Story** → merge into the one sibling that consumes it. This
107
+ is the primary lever for going **below** the Delivery-Slicing ceiling: an
108
+ "Independent? No" slice whose only consumer is one sibling folds into that
109
+ sibling unless its row justifies staying separate (parallelism, risk
110
+ isolation, or delivery-envelope pressure). Coarsening below N here is
111
+ expected, not an over-reach — record it as a below-ceiling merge (see Step 4).
99
112
  - **Missing reason to exist** → flag any Story whose body carries no non-empty
100
113
  `reason_to_exist` meta field. A Story that cannot name its single coherent
101
114
  reason is a cohesion smell; record it in the report so the operator can
102
115
  re-scope it (merge, split, or have the author supply the reason) at the HITL
103
116
  gate.
104
117
 
105
- Record each decision with its one-line reason for the report.
118
+ Never split a draft Story to *reach* N N is a ceiling, and adding scope is
119
+ out of contract. Record each decision with its one-line reason for the report.
106
120
 
107
121
  ### Step 3 — Rewire dependencies and conserve scope
108
122
 
@@ -120,7 +134,12 @@ After applying the operations:
120
134
 
121
135
  Write the consolidated array to `temp/epic-<Epic_ID>/tickets.json` (2-space
122
136
  indent, machine-consumed) and the rationale + before/after diff to
123
- `temp/epic-<Epic_ID>/consolidation-report.md`.
137
+ `temp/epic-<Epic_ID>/consolidation-report.md`. When the consolidated count
138
+ landed **below** the Delivery-Slicing ceiling, the report MUST call that out
139
+ explicitly — a `Below ceiling: N (Delivery Slicing) → M (consolidated)` line
140
+ plus a one-line rationale per below-ceiling merge (which dependent
141
+ single-consumer slice folded into which consumer, and why it was unjustified) —
142
+ so the operator sees the coarsening at the Phase 8.3 advisory diff.
124
143
 
125
144
  ### Step 5 — Hand back to `/plan`
126
145
 
@@ -32,9 +32,10 @@ allowed_tools:
32
32
 
33
33
  ## Role
34
34
 
35
- Senior Project Manager + Orchestrator. The Skill's job is to take a PRD plus
36
- a Tech Spec and emit a flat Story backlog the orchestrator can execute
37
- autonomously.
35
+ Senior Project Manager + Orchestrator. The Skill's job is to take the
36
+ sectioned Epic body (whose managed sections carry the folded Tech Spec and
37
+ Acceptance Table — Story #4324) and emit a flat Story backlog the
38
+ orchestrator can execute autonomously.
38
39
 
39
40
  ## When to use
40
41
 
@@ -55,10 +56,12 @@ reads:
55
56
  `node .agents/scripts/epic-plan-decompose.js --epic <Epic_ID> --emit-context`.
56
57
  Fields:
57
58
  - `epic.id`, `epic.title`
58
- - `prd.body` (or `prd.bodySummary` when downgraded by the
59
- planning-context budget) required for User-Story extraction
60
- - `techSpec.body` (or `techSpec.bodySummary`) required for module
61
- boundary + dependency-DAG extraction
59
+ - `epicBody` the sectioned Epic body. It carries everything the
60
+ decomposer needs in one document: the `## User Stories` section
61
+ (User-Story extraction), the folded Tech Spec sections
62
+ (`## Delivery Slicing` onward — module boundary + dependency-DAG
63
+ extraction), and the `## Acceptance Table` AC-ID table. There is no
64
+ separate `techSpec` envelope key (Story #4324).
62
65
  - `heuristics[]` — risk heuristics surfaced from
63
66
  `agentSettings.planning.riskHeuristics`. Apply each one against the
64
67
  Stories you are emitting; flag matches via `risk::high` labels.
@@ -117,7 +120,7 @@ Pin three values explicitly before writing any tickets:
117
120
  Apply the fully-rendered decomposer system prompt — the `systemPrompt`
118
121
  field of the loaded context envelope, produced by
119
122
  [`decomposer-prompts.js`](../../../scripts/lib/templates/decomposer-prompts.js)
120
- — to the PRD + Tech Spec bodies. That rendered string is the authoritative
123
+ — to the sectioned Epic body (`epicBody`). That rendered string is the authoritative
121
124
  prompt body (with `maxTickets`, `maxTokenBudget`, and the sizing thresholds
122
125
  already interpolated); the authoring-guidance sections below complement it
123
126
  without restating it. Emit JSON only (no prose, no Markdown fence). The
@@ -224,6 +227,8 @@ They are NOT top-level ticket fields.
224
227
 
225
228
  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.
226
229
 
230
+ 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.
231
+
227
232
  - **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.
228
233
  - **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.
229
234
  - **Split independent, parallelizable work** into sibling Stories — but only when the pieces genuinely have separate reasons to exist.
@@ -237,11 +242,11 @@ The first question is **cohesion, not count**: *is this one coherent change with
237
242
 
238
243
  #### DELIVERY SLICING (consume the Tech Spec target grouping when present)
239
244
 
240
- The Tech Spec may carry a `## Delivery Slicing` section authored by the
241
- Architect, proposing how the PRD's enumerated capabilities cluster into N
245
+ The Epic body's Tech Spec sections may carry a `## Delivery Slicing` section authored by the
246
+ Architect, proposing how the Epic's enumerated capabilities cluster into N
242
247
  shippable Stories. When that section is **present**, treat it as the **target
243
248
  grouping**: prefer emitting Stories that match the Architect's proposed
244
- clusters rather than mapping PRD capabilities 1:1. When it is **absent**,
249
+ clusters rather than mapping Epic capabilities 1:1. When it is **absent**,
245
250
  degrade gracefully — decompose at deliverable granularity using the cohesion
246
251
  rules above, exactly as before. The Phase 8 holistic consolidation pass
247
252
  (`epic-plan-consolidate`) reconciles your draft against this same Delivery
@@ -263,7 +268,7 @@ Declaring `wide` with a non-empty reason **lifts the `hardFiles` rejection** —
263
268
 
264
269
  #### BRAND / COPY / STYLE WORK
265
270
 
266
- - 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 PRD §2"]`. Silence on style sourcing is a smell.
271
+ - 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.
267
272
 
268
273
  #### BINDING ACCEPTANCE vs ADVISORY CHANGES (authoring altitude)
269
274
 
@@ -281,11 +286,11 @@ When a Story's acceptance describes a **signed-in / authenticated** persona reac
281
286
  - 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"`.
282
287
  - 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.
283
288
 
284
- ### WAVE-0 BDD SCAFFOLD STORY (features-first; emit when the Acceptance Spec has `new`-disposition rows)
289
+ ### WAVE-0 BDD SCAFFOLD STORY (features-first; emit when the Acceptance Table has `new`-disposition rows)
285
290
 
286
- The Acceptance Spec's AC table (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).
291
+ 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).
287
292
 
288
- 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
+ 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:
289
294
 
290
295
  - **goal** (in body string): contains the literal token `bdd-scaffold`.
291
296
  - **depends_on**: EMPTY (`[]`) — the scaffold runs first, in wave 0.
@@ -295,9 +300,9 @@ When the Acceptance Spec contains **one or more `Disposition: new` rows**, you M
295
300
  - **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.
296
301
  - 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).
297
302
 
298
- When the Acceptance Spec contains **zero `new`-disposition rows** (every row is `updated` or `unchanged`), do NOT emit a scaffold Story — there is nothing to create.
303
+ 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.
299
304
 
300
- **Worked example.** Epic #42, Acceptance Spec with two `new` rows (`AC-1` -> `tests/features/billing/invoice.feature`, `AC-2` -> `tests/features/billing/refund.feature`). The scaffold Story below uses a serialized string `body`, top-level `acceptance`/`verify` arrays, an empty `depends_on`, and tags each scenario with both `@skip` and its namespaced `@epic-42-ac-N` tag:
305
+ **Worked example.** Epic #42, Acceptance Table with two `new` rows (`AC-1` -> `tests/features/billing/invoice.feature`, `AC-2` -> `tests/features/billing/refund.feature`). The scaffold Story below uses a serialized string `body`, top-level `acceptance`/`verify` arrays, an empty `depends_on`, and tags each scenario with both `@skip` and its namespaced `@epic-42-ac-N` tag:
301
306
 
302
307
  {
303
308
  "slug": "scaffold-billing-feature-files",
@@ -407,7 +412,7 @@ any logical ordering requirement via Story-level `depends_on`.
407
412
  - Do **not** call the GitHub API from this Skill. Persistence is the
408
413
  script's job; the Skill is pure JSON authoring.
409
414
  - Do **not** write outside `temp/epic-<Epic_ID>/`. Reads may cover the
410
- PRD/Tech Spec bodies plus any docs the context envelope cites.
415
+ Epic body plus any docs the context envelope cites.
411
416
  - The decomposer prompt's `${maxTickets}` value is the **reviewability
412
417
  budget** (Story #2798). Staying under is the default; exceeding it
413
418
  requires both an `over_budget_rationale` in the JSON output and the
@@ -5,7 +5,7 @@ description: >-
5
5
  ticket array an Epic's decompose phase produced. Use during Phase 8 of
6
6
  `/plan`, after `epic-plan-decompose-author` / `epic-plan-consolidate` write
7
7
  `temp/epic-<Epic_ID>/tickets.json` and before `epic-plan-decompose.js`
8
- validates and persists it. Reads the PRD / Tech Spec AND the actual cited
8
+ validates and persists it. Reads the sectioned Epic body AND the cited
9
9
  code surfaces, then emits predicted-rework findings before any GitHub write.
10
10
  allowed_tools:
11
11
  - Read
@@ -18,7 +18,7 @@ allowed_tools:
18
18
 
19
19
  ## Policy Capsule
20
20
 
21
- - Run only after a draft `temp/epic-<Epic_ID>/tickets.json` exists (authored by `epic-plan-decompose-author`, and consolidated by `epic-plan-consolidate` if that pass ran); 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
+ - Run only after a draft `temp/epic-<Epic_ID>/tickets.json` exists (authored by `epic-plan-decompose-author`, and consolidated by `epic-plan-consolidate` if that pass ran); fail loudly if the draft array is missing. Read the sectioned Epic body 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.
22
22
  - **You MUST read the actual cited code surfaces.** For every Story, open the files named in its `changes[]` / `references[]` (resolve each path against the repo root; use `Read` / `Grep`) and read enough of each to judge whether the Story's `acceptance[]` is verifiable against the real code and whether its `changes[]` assumptions hold. This is the load-bearing difference between this critic and the structural file-assumption gate: that gate proves a path **exists** (or does not); this critic reads what the file actually **contains**. A pre-mortem that did not open the cited files has not run.
23
23
  - Emit exactly one artifact: a human-readable `temp/epic-<Epic_ID>/premortem-report.md` — the predicted-rework findings the operator reviews at the Phase 8 HITL diff. It MUST exist before returning.
24
24
  - **This critic never writes to GitHub and never persists `tickets.json`.** It is read-and-report only: it does NOT mutate the draft array, does NOT create issues, and does NOT flip any label. Re-authoring on its findings is the author skill's job (the workflow re-runs `epic-plan-decompose-author` on the report before the persist call).
@@ -32,7 +32,7 @@ Senior Engineer + Architect, acting as a **fresh-context pre-mortem critic**.
32
32
  This Skill is deliberately *separate* from `epic-plan-decompose-author` (the
33
33
  generator) and from `epic-plan-consolidate` (the scope-preserving merge critic):
34
34
  a same-pass self-critique is the weak mode this is built to escape. The
35
- generator maps PRD capabilities to Stories against the spec text; this critic
35
+ generator maps Epic capabilities to Stories against the spec text; this critic
36
36
  opens the **actual cited code** and asks "if I tried to deliver this exact
37
37
  backlog, where would it rework?" — before any GitHub write makes the rework
38
38
  expensive.
@@ -56,8 +56,9 @@ The workflow passes the Epic ID as the Skill argument. The Skill itself reads:
56
56
  - `temp/epic-<Epic_ID>/tickets.json` — the **draft** (or consolidated) Story
57
57
  array. This is the pre-mortem subject.
58
58
  - `temp/epic-<Epic_ID>/decomposer-context.json` — the authoring envelope emitted
59
- by `epic-plan-decompose.js --emit-context`. Read `prd.body` / `prd` and
60
- `techSpec.body` / `techSpec` from it.
59
+ by `epic-plan-decompose.js --emit-context`. Read `epicBody` from it
60
+ the sectioned Epic body carrying the folded Tech Spec sections
61
+ (there is no separate `techSpec` key — Story #4324).
61
62
  - **The repository working tree** — the actual files each Story's `changes[]` /
62
63
  `references[]` name. Resolve each path against the repo root and read it.
63
64
 
@@ -78,7 +79,7 @@ artifact and mutates **no** GitHub state.
78
79
  ### Step 1 — Load the draft and the spec
79
80
 
80
81
  Read `temp/epic-<Epic_ID>/tickets.json` (the Story array) and
81
- `temp/epic-<Epic_ID>/decomposer-context.json` (for the PRD / Tech Spec). If the
82
+ `temp/epic-<Epic_ID>/decomposer-context.json` (for the `epicBody`). If the
82
83
  draft array is missing, fail loudly and instruct the caller to run the
83
84
  `epic-plan-decompose-author` Skill first.
84
85