mandrel 1.81.0 → 1.83.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 (121) hide show
  1. package/.agents/README.md +46 -5
  2. package/.agents/docs/SDLC.md +97 -82
  3. package/.agents/docs/agentrc-reference.json +10 -2
  4. package/.agents/docs/configuration.md +4 -1
  5. package/.agents/docs/execution-reference.md +52 -0
  6. package/.agents/docs/workflows.md +1 -1
  7. package/.agents/instructions.md +85 -45
  8. package/.agents/personas/architect.md +8 -5
  9. package/.agents/personas/engineer-mobile.md +3 -2
  10. package/.agents/personas/engineer-web.md +3 -2
  11. package/.agents/personas/engineer.md +6 -5
  12. package/.agents/personas/product.md +19 -13
  13. package/.agents/personas/project-manager.md +9 -8
  14. package/.agents/personas/qa-engineer.md +10 -6
  15. package/.agents/personas/refactorer.md +3 -2
  16. package/.agents/personas/technical-writer.md +2 -1
  17. package/.agents/personas/ux-designer.md +2 -2
  18. package/.agents/schemas/agentrc.schema.json +41 -3
  19. package/.agents/schemas/qa-ledger.schema.json +2 -2
  20. package/.agents/scripts/acceptance-spec-reconciler.js +143 -59
  21. package/.agents/scripts/epic-deliver-prepare.js +40 -31
  22. package/.agents/scripts/epic-plan-decompose.js +2 -5
  23. package/.agents/scripts/epic-plan-spec.js +16 -19
  24. package/.agents/scripts/hierarchy-gate.js +11 -11
  25. package/.agents/scripts/lib/ITicketingProvider.js +4 -3
  26. package/.agents/scripts/lib/bdd-runner-detect.js +1 -1
  27. package/.agents/scripts/lib/bdd-scenario-scanner.js +1 -1
  28. package/.agents/scripts/lib/cli-args.js +1 -5
  29. package/.agents/scripts/lib/codebase-snapshot.js +1 -1
  30. package/.agents/scripts/lib/config/explain.js +4 -1
  31. package/.agents/scripts/lib/config/temp-paths.js +1 -4
  32. package/.agents/scripts/lib/config-settings-schema.js +30 -1
  33. package/.agents/scripts/lib/epic-body-sections.js +310 -0
  34. package/.agents/scripts/lib/epic-plan-clarity.js +38 -1
  35. package/.agents/scripts/lib/epic-plan-ideation.js +15 -3
  36. package/.agents/scripts/lib/findings/promote-finding.js +3 -3
  37. package/.agents/scripts/lib/findings/severity.js +5 -6
  38. package/.agents/scripts/lib/label-constants.js +7 -17
  39. package/.agents/scripts/lib/label-taxonomy.js +4 -21
  40. package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +65 -2
  41. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +105 -9
  42. package/.agents/scripts/lib/orchestration/doc-reader.js +29 -0
  43. package/.agents/scripts/lib/orchestration/docs-digest.js +134 -0
  44. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/context.js +23 -22
  45. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/persist-helpers.js +7 -10
  46. package/.agents/scripts/lib/orchestration/epic-plan-decompose/phases/planning-artifacts.js +4 -38
  47. package/.agents/scripts/lib/orchestration/epic-plan-lease-guard.js +8 -9
  48. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/authoring-context.js +11 -5
  49. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/cli-args.js +26 -5
  50. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/plan-epic.js +102 -304
  51. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +32 -29
  52. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +19 -20
  53. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-authoring-grounding.js +1 -1
  54. package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/spec-freshness.js +6 -9
  55. package/.agents/scripts/lib/orchestration/epic-plan-state-store.js +3 -4
  56. package/.agents/scripts/lib/orchestration/epic-runner/phases/build-wave-dag.js +1 -1
  57. package/.agents/scripts/lib/orchestration/epic-runner/phases/snapshot.js +20 -27
  58. package/.agents/scripts/lib/orchestration/lifecycle/listeners/acceptance-reconciler.js +11 -5
  59. package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +22 -59
  60. package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +1 -1
  61. package/.agents/scripts/lib/orchestration/planning-context-budget.js +1 -1
  62. package/.agents/scripts/lib/orchestration/preflight-cache.js +1 -1
  63. package/.agents/scripts/lib/orchestration/spec-freshness.js +3 -3
  64. package/.agents/scripts/lib/orchestration/spec-section-validator.js +1 -1
  65. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +15 -1
  66. package/.agents/scripts/lib/orchestration/ticket-validator-sizing.js +122 -1
  67. package/.agents/scripts/lib/orchestration/ticketing/bulk.js +5 -8
  68. package/.agents/scripts/lib/orchestration/ticketing/reads.js +2 -2
  69. package/.agents/scripts/lib/plan-phase-cleanup.js +1 -2
  70. package/.agents/scripts/lib/qa/console-allowlist.js +5 -4
  71. package/.agents/scripts/lib/qa/qa-context-hydrator.js +6 -85
  72. package/.agents/scripts/lib/qa/resolve-qa-contract.js +144 -8
  73. package/.agents/scripts/lib/templates/decomposer-prompts.js +14 -8
  74. package/.agents/scripts/lifecycle-emit.js +1 -1
  75. package/.agents/scripts/lint-label-vocabulary.js +2 -3
  76. package/.agents/scripts/providers/github/mappers.js +0 -3
  77. package/.agents/scripts/providers/github/tickets.js +7 -18
  78. package/.agents/scripts/single-story-init.js +0 -1
  79. package/.agents/scripts/story-init.js +1 -29
  80. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +43 -22
  81. package/.agents/skills/core/epic-plan-consolidate/examples.md +51 -0
  82. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +27 -40
  83. package/.agents/skills/core/epic-plan-decompose-author/examples.md +47 -0
  84. package/.agents/skills/core/epic-plan-premortem/SKILL.md +15 -13
  85. package/.agents/skills/core/epic-plan-premortem/examples.md +53 -0
  86. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +143 -151
  87. package/.agents/skills/core/epic-plan-spec-author/examples.md +91 -0
  88. package/.agents/skills/core/hydrate-context/SKILL.md +10 -5
  89. package/.agents/skills/core/knowledge-transfer/SKILL.md +3 -2
  90. package/.agents/skills/core/scope-triage/SKILL.md +2 -1
  91. package/.agents/skills/skills.index.json +8 -8
  92. package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +52 -38
  93. package/.agents/templates/epic-from-idea.md +4 -0
  94. package/.agents/workflows/audit-to-stories.md +2 -2
  95. package/.agents/workflows/helpers/code-review.md +11 -9
  96. package/.agents/workflows/helpers/deliver-epic-reference.md +514 -0
  97. package/.agents/workflows/helpers/deliver-epic.md +173 -490
  98. package/.agents/workflows/helpers/epic-audit.md +11 -8
  99. package/.agents/workflows/helpers/epic-deliver-story.md +45 -27
  100. package/.agents/workflows/helpers/epic-plan-decompose.md +17 -12
  101. package/.agents/workflows/helpers/epic-plan-spec.md +68 -68
  102. package/.agents/workflows/helpers/parallel-tooling.md +2 -1
  103. package/.agents/workflows/helpers/plan-epic-reference.md +136 -0
  104. package/.agents/workflows/helpers/plan-epic.md +141 -256
  105. package/.agents/workflows/helpers/plan-story.md +31 -61
  106. package/.agents/workflows/helpers/qa-run-scenario.md +194 -0
  107. package/.agents/workflows/helpers/scope-triage-gate.md +97 -0
  108. package/.agents/workflows/helpers/single-story-deliver-reference.md +423 -0
  109. package/.agents/workflows/helpers/single-story-deliver.md +129 -393
  110. package/.agents/workflows/helpers/worktree-lifecycle.md +1 -1
  111. package/.agents/workflows/plan.md +8 -8
  112. package/.agents/workflows/qa-assist.md +2 -1
  113. package/.agents/workflows/qa-explore.md +63 -32
  114. package/.agents/workflows/qa-run.md +293 -130
  115. package/docs/CHANGELOG.md +35 -0
  116. package/package.json +1 -1
  117. package/.agents/schemas/qa-finding.schema.json +0 -133
  118. package/.agents/scripts/lib/issue-link-parser.js +0 -74
  119. package/.agents/scripts/lib/orchestration/finalize/close-planning-tickets.js +0 -116
  120. package/.agents/scripts/lib/orchestration/planning-state-manager.js +0 -318
  121. package/.agents/scripts/lib/story-init/hierarchy-tracer.js +0 -57
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description:
3
- Orchestrates end-to-end Epic planning (PRD, Tech Spec, Acceptance Spec, and
3
+ Orchestrates end-to-end Epic planning (Tech Spec, Acceptance Spec, and
4
4
  Work Breakdown) for a GitHub Epic.
5
5
  ---
6
6
 
@@ -22,7 +22,7 @@ phase helpers — [`helpers/epic-plan-spec.md`](epic-plan-spec.md) and
22
22
  both phases sequentially with a human confirmation gate between them. The Epic
23
23
  ID is the single positional argument.
24
24
 
25
- As of v5.6, planning artifacts (PRD, Tech Spec, ticket decomposition) are
25
+ As of v5.6, planning artifacts (Tech Spec, ticket decomposition) are
26
26
  authored **directly by you, the host LLM** — no external Gemini / Anthropic /
27
27
  OpenAI API is called. The Node scripts are deterministic GitHub I/O wrappers
28
28
  that (a) emit the authoring context you need and (b) validate and persist the
@@ -92,54 +92,25 @@ Phase 5 (Re-Plan Detection).
92
92
 
93
93
  ## Phase 1.5: Scope Triage (ideation path only)
94
94
 
95
- This phase runs **only** on the ideation path, immediately after Phase 1
96
- produces the sharpened one-pager. It is **skipped entirely** when an Epic ID
97
- argument was supplied (the existing-Epic path jumps straight to Phase 5), and
98
- it is **skipped** when `/plan` was entered via a scope-triage handoff from
99
- [`/plan`](plan-story.md) a handoff is a triage decision already made,
100
- and re-triaging it would re-litigate a settled call (the no-re-triage rule the
101
- skill states once).
102
-
103
- 1. **Activate the scope-triage skill**: Read
104
- [`<agentRoot>/skills/core/scope-triage/SKILL.md`](../../skills/core/scope-triage/SKILL.md)
105
- via the `Read` tool (resolve `<agentRoot>` from `project.paths.agentRoot`
106
- default `.agents`) and apply its rubric to the Phase 1 one-pager. The skill
107
- anchors its sizing judgment **by reference** to
108
- `DELIVERABLE_GRANULARITY_GUIDANCE` / `DEFAULT_TASK_SIZING` in
109
- [`ticket-validator-sizing.js`](../../scripts/lib/orchestration/ticket-validator-sizing.js)
110
- and emits one verdict: `epic` | `story` | `borderline`. The verdict is
111
- host-LLM judgment there is **no `--flag`**, no scorer, no schema, and no
112
- label transition.
113
-
114
- 2. **Fold the verdict into the existing Phase 1 HITL stop** — do **not** add a
115
- second stop:
116
- - **`epic` verdict** → no extra prompt. The Phase 1 confirmation proceeds
117
- as a plain one-pager confirm and the run continues to Phase 2.
118
- - **`story` or `borderline` verdict** → the Phase 1 confirmation prompt
119
- presents a **three-way operator choice**:
120
- - **Recommended: single Story** (with the triage rationale) — persist the
121
- one-pager to a notes file and hand off to
122
- `/plan --from-notes <path>`, identifying the invocation as a
123
- scope-triage handoff so `/plan` skips its own gate. Then **exit
124
- `/plan`**.
125
- - **Plan as Epic anyway** — ignore the recommendation and continue to
126
- Phase 2 with the one-pager.
127
- - **Abort** — stop planning entirely.
128
-
129
- **Never auto-route.** The verdict is advisory; the operator always decides.
130
- Being wrong in the `epic` direction is cheap (Phase 8.3 consolidation and
131
- the sizing validator catch an over-planned Story later); the gate exists to
132
- avoid the ceremony tax of pushing a story-sized scope through the full Epic
133
- pipeline.
134
-
135
- > **`--yes` (headless) exception.** "Never auto-route" is the interactive
136
- > contract. Under `--yes` the operator has *pre-authorized* the
137
- > recommendation: the three-way choice resolves to its **Recommended**
138
- > branch deterministically — `single Story` hands off to
139
- > `/plan --from-notes <path>` (carrying `--yes` so the receiving story
140
- > path also auto-proceeds), and an `epic` verdict simply continues to
141
- > Phase 2. No operator wait. This is the only sanctioned auto-route, and it
142
- > exists solely to make `/plan` driveable headlessly.
95
+ This phase runs the shared scope-triage gate over the Phase 1 one-pager. The
96
+ gate mechanics verdict meanings, the three-way operator choice, the `--yes`
97
+ resolution, and the no-re-triage rule live in the single-homed fragment
98
+ [`scope-triage-gate.md`](scope-triage-gate.md); read it and follow it. This
99
+ phase supplies only its path-specific firing conditions:
100
+
101
+ - **When it runs**: only on the ideation path, immediately after Phase 1
102
+ produces the sharpened one-pager. The rubric is applied to the **Phase 1
103
+ one-pager**, and the verdict folds into the **existing Phase 1 HITL stop**
104
+ (do **not** add a second stop).
105
+ - **When it is skipped**: entirely, when an Epic ID argument was supplied (the
106
+ existing-Epic path jumps straight to Phase 5); and when `/plan` was entered
107
+ via a scope-triage handoff from [`/plan`](plan-story.md) (the no-re-triage
108
+ rule in the fragment).
109
+ - **Recommended branch on a `story` / `borderline` verdict**: persist the
110
+ one-pager to a notes file and hand off to `/plan --from-notes <path>`,
111
+ identifying the invocation as a scope-triage handoff so `/plan` skips its
112
+ own gate, then **exit `/plan`**. The alternative branches are **plan as Epic
113
+ anyway** (continue to Phase 2) and **abort**.
143
114
 
144
115
  ## Phase 2: Cross-Epic Duplicate Search
145
116
 
@@ -207,7 +178,7 @@ new Epic is genuinely distinct).
207
178
 
208
179
  2. **Label discipline**: The Issue is opened with **only** the
209
180
  `type::epic` label. **Do not** add any `state::*` label at creation
210
- time — the Epic carries only `type::epic` until PRD authoring
181
+ time — the Epic carries only `type::epic` until spec authoring
211
182
  advances it to `agent::review-spec` in Phase 7. The
212
183
  `openEpicFromOnePager` helper already enforces this; the workflow
213
184
  prose codifies the intent so future label-set tweaks don't silently
@@ -215,30 +186,36 @@ new Epic is genuinely distinct).
215
186
 
216
187
  3. **Continue to Phase 5**: The captured Epic ID becomes the new
217
188
  `[Epic_ID]` for the rest of the planning pipeline. Re-Plan Detection
218
- (Phase 5) will short-circuit because no PRD/Tech Spec is linked yet,
219
- so the run flows naturally into Phase 6 (Epic Clarity Gate) and then
220
- Phase 7.
189
+ (Phase 5) will short-circuit because the fresh Epic body carries no
190
+ Tech Spec sections yet, so the run flows naturally into Phase 6
191
+ (Epic Clarity Gate) and then Phase 7.
221
192
 
222
193
  ## Phase 5: Re-Plan Detection
223
194
 
224
195
  Before generating any artifacts, check whether the Epic has already been
225
196
  planned.
226
197
 
227
- 1. **Fetch Epic**: Read the Epic issue body and check for a
228
- `## Planning Artifacts` section containing PRD and Tech Spec references.
229
- 2. **If already planned**: Inform the user that this Epic already has planning
230
- artifacts. Ask:
231
-
232
- > "Epic #[ID] already has PRD (#XX) and Tech Spec (#XX) with YY decomposed
233
- > tickets. Do you want to **re-plan**? This will **overwrite the PRD,
234
- > Tech Spec, and Acceptance Spec in place** (same issue numbers, refreshed
235
- > bodies, comment history preserved) and **close-and-recreate** all
236
- > child Story tickets."
198
+ 1. **Fetch Epic**: Read the Epic issue body and check for Tech Spec
199
+ content the managed `<!-- mandrel:tech-spec:start/end -->` section or
200
+ a bare `## Delivery Slicing` heading (`hasTechSpecContent` in
201
+ [`lib/epic-body-sections.js`](../../scripts/lib/epic-body-sections.js)).
202
+ The Tech Spec sections alone are the already-planned signal. Historical
203
+ Epics may still carry a legacy `## Planning Artifacts` section linking
204
+ retired `context::*` tickets those links are **ignored** (never
205
+ fetched); only the body sections count.
206
+ 2. **If already planned**: Inform the user that this Epic already carries
207
+ planning sections. Ask:
208
+
209
+ > "Epic #[ID] already carries a Tech Spec (`## Delivery Slicing`) with
210
+ > YY decomposed tickets. Do you want to **re-plan**? This will
211
+ > **overwrite the Tech Spec and Acceptance Table sections of the Epic
212
+ > body in place** (comment history preserved) and **close-and-recreate**
213
+ > all child Story tickets."
237
214
 
238
215
  3. **If user confirms re-plan**: Pass `--force` to all subsequent script
239
- invocations. Under `--force`, the three context tickets (PRD, Tech Spec,
240
- Acceptance Spec) are overwritten in place — their issue numbers, Epic
241
- sub-issue links, and prior discussion are preserved, and each receives a
216
+ invocations. Under `--force`, the Epic body's managed sections (Tech
217
+ Spec, Acceptance Table) are overwritten in place — the Epic's issue
218
+ number and prior discussion are preserved, and the Epic receives a
242
219
  one-line regeneration audit comment. Child Story tickets are still
243
220
  closed and recreated, because a re-decomposition can legitimately produce a
244
221
  different ticket set.
@@ -257,51 +234,36 @@ clarity gate does not make.
257
234
 
258
235
  The advisory runs **only** when **both** hold:
259
236
 
260
- 1. **Phase 5 found no planning artifacts** — the Epic body has no
261
- `## Planning Artifacts` section linking a PRD / Tech Spec (i.e. Phase 5
262
- did **not** enter its re-plan branch).
237
+ 1. **Phase 5 found no planning sections** — the Epic body carries no Tech
238
+ Spec content (no managed section, no `## Delivery Slicing` heading
239
+ i.e. Phase 5 did **not** enter its re-plan branch).
263
240
  2. **The Epic has no open Story children** — no open `type::story`
264
241
  sub-issues are linked to this Epic.
265
242
 
266
243
  If **either** condition fails, **skip this phase silently** and continue to
267
244
  Phase 6. It must **never** fire on the re-plan path: recommending a "downgrade
268
- to a Story" on an Epic that already carries a PRD and a ticket tree is
269
- nonsense and would collide with the `--force` re-plan flow. The advisory also
245
+ to a Story" on an Epic that already carries folded Tech Spec sections and a
246
+ ticket tree is nonsense and would collide with the `--force` re-plan flow. The advisory also
270
247
  does not fire on the ideation path — that path already ran the Phase 1.5 scope
271
248
  triage on the one-pager before the Epic existed.
272
249
 
273
250
  ### Triage
274
251
 
275
- 1. **Activate the scope-triage skill**: Read
276
- [`<agentRoot>/skills/core/scope-triage/SKILL.md`](../../skills/core/scope-triage/SKILL.md)
277
- via the `Read` tool (resolve `<agentRoot>` from `project.paths.agentRoot` —
278
- default `.agents`) and apply its rubric to the **Epic body**. The skill is
279
- artifact-agnostic — it reads the same against an Epic body as against a
280
- one-pager or a Story draft — and anchors its sizing judgment **by
281
- reference** to `DELIVERABLE_GRANULARITY_GUIDANCE` / `DEFAULT_TASK_SIZING`
282
- in
283
- [`ticket-validator-sizing.js`](../../scripts/lib/orchestration/ticket-validator-sizing.js).
284
- It emits one verdict: `epic` | `story` | `borderline`. The verdict is
285
- host-LLM judgment there is **no `--flag`**, no scorer, no schema, and no
286
- label transition behind this gate. Do **not** restate the skill's rubric or
287
- its sizing thresholds here.
288
-
289
- 2. **`epic` verdict** → proceed silently. No extra prompt, no HITL stop. The
290
- run continues straight to Phase 6. Being wrong in the `epic` direction is
291
- cheap (Phase 8.3 consolidation and the sizing validator catch an
292
- over-planned Story later), so an `epic` verdict never costs the operator a
293
- stop.
294
-
295
- 3. **`story` or `borderline` verdict** → **STOP** and present a **three-way
296
- operator choice**. Never auto-route; the verdict is advisory and the
297
- operator always decides.
298
-
299
- - **Recommended: convert to a standalone Story** (with the triage
300
- rationale) — run the conversion path below.
301
- - **Proceed as Epic anyway** — ignore the recommendation and continue to
302
- Phase 6 with the Epic unchanged.
303
- - **Abort** — stop planning entirely. The Epic is left exactly as it was;
304
- no labels move and nothing is closed.
252
+ Run the shared scope-triage gate over the **Epic body** — the gate mechanics
253
+ (verdict meanings, the three-way operator choice, the `--yes` resolution, and
254
+ the no-re-triage rule) live in [`scope-triage-gate.md`](scope-triage-gate.md);
255
+ read it and follow it. The scope-triage skill is artifact-agnostic, so it
256
+ reads the same against an Epic body as against a one-pager or a Story draft.
257
+ The path-specific bindings for this advisory:
258
+
259
+ - **`epic` verdict** → proceed silently to Phase 6. No extra prompt, no HITL
260
+ stop.
261
+ - **`story` / `borderline` verdict** **STOP** and present the three-way
262
+ choice, whose **Recommended** branch here is **convert to a standalone
263
+ Story** via the conversion path below. The alternative branches are
264
+ **proceed as Epic anyway** (continue to Phase 6 with the Epic unchanged) and
265
+ **abort** (the Epic is left exactly as it was; no labels move and nothing is
266
+ closed).
305
267
 
306
268
  ### Conversion path (close-and-recreate)
307
269
 
@@ -352,11 +314,13 @@ via [`/single-story-deliver`](single-story-deliver.md) or
352
314
 
353
315
  Runs on every existing-Epic invocation, after Phase 5 (Re-Plan
354
316
  Detection) and the Phase 5.5 story-sized advisory, and before Phase 7
355
- (PRD, Tech Spec & Acceptance Spec). The gate scores the Epic body
356
- against the five canonical
317
+ (Tech Spec & Acceptance Spec). The gate scores the Epic body
318
+ against the five clarity-scored canonical
357
319
  sections from
358
320
  [`.agents/templates/epic-from-idea.md`](../../templates/epic-from-idea.md)
359
- (Context, Goal, Non-Goals, Scope, Acceptance Criteria) and either
321
+ (Context, Goal, Non-Goals, Scope, Acceptance Criteria the template
322
+ also carries a `## User Stories` section, which the clarity rubric does
323
+ not score) and either
360
324
  skips fast (when the Epic body is already clear) or drops into a
361
325
  refinement loop seeded from the current Epic body. The scorer also
362
326
  accepts common heading variants for back-compat (e.g. `## Problem`,
@@ -406,8 +370,8 @@ for the scoring logic.
406
370
  5. **HITL stop — confirm the diff**: Display the diff between the
407
371
  current Epic body and the sharpened body and **STOP**. Operator
408
372
  approves, edits, or aborts. Flag the blast radius in the
409
- confirmation prompt: an approved body change feeds **three**
410
- downstream artifacts (PRD, Tech Spec, Acceptance Spec) — treat
373
+ confirmation prompt: an approved body change feeds **two**
374
+ downstream artifacts (Tech Spec, Acceptance Spec) — treat
411
375
  this gate as a one-shot rewrite, not an iterative draft. The
412
376
  Constraint ("Do not modify existing issues without explicit
413
377
  permission") is honored — no `gh issue edit` call until the
@@ -443,72 +407,17 @@ for the scoring logic.
443
407
  remediation hint to the operator. Do not loop — one refinement
444
408
  pass per invocation, matching the `--force` re-plan pattern.
445
409
 
446
- ## Phase 7: Epic Planning (PRD, Tech Spec & Acceptance Spec)
447
-
448
- > **Epic-lease preflight (workflow guard).** Before any Phase 7 mutation,
449
- > `epic-plan-spec.js` acquires the Epic-lease via the assignee-as-lease
450
- > primitive (`lib/orchestration/ticket-lease.js`, wired through
451
- > `lib/orchestration/epic-plan-lease-guard.js`). The lease rides the Epic's
452
- > single assignee: the operator (`github.operatorHandle` in `.agentrc.json`)
453
- > claims the Epic for the duration of the plan. The guard **fails closed**:
454
- > `/plan` emits no `story.heartbeat` during its run (heartbeats are a
455
- > delivery-time signal), so there is no live-heartbeat source to judge a
456
- > concurrent plan's liveness from. Any **foreign assignee** is therefore
457
- > treated as a live claim — the persist half **exits non-zero and names the
458
- > current owner**, so two `/plan` runs cannot drive the same Epic
459
- > concurrently. Pass **`--steal`** to forcibly transfer a foreign claim once
460
- > you have confirmed the other run is dead. An **unassigned** Epic, or one
461
- > **already held by this operator**, is taken (or re-affirmed) silently. The
462
- > lease is **released after Phase 8** (decompose) completes; see the Phase 8
463
- > note.
464
-
465
- <!-- separator: adjacent blockquotes -->
466
-
467
- > **Idempotent context tickets.** The persist half is find-or-create keyed on
468
- > the Epic's `linkedIssues`: a re-run **reuses the already-linked PRD and Tech
469
- > Spec issues** (and Acceptance Spec, when present) instead of creating
470
- > duplicates. Pass `--force` to overwrite the canonical context tickets in
471
- > place (same issue numbers, refreshed bodies).
472
-
473
- <!-- separator: adjacent blockquotes -->
474
-
475
- > **Three context tickets, not two.** Every Epic carries three planning
476
- > artifacts as linked GitHub sub-issues: PRD (`context::prd`), Tech Spec
477
- > (`context::tech-spec`), and Acceptance Spec
478
- > (`context::acceptance-spec`). The Acceptance Spec captures the
479
- > stable-ID acceptance criteria table (`| AC ID | Outcome | Feature
480
- > File | Scenario | Disposition |`) that drives close-time
481
- > reconciliation during `/deliver` Phase 6. Operators may opt out
482
- > for refactor-only or docs-only Epics by applying the
483
- > `acceptance::n-a` label to the Epic ticket — when present, the
484
- > `epic-plan-spec-author` skill skips the Acceptance Spec output and
485
- > the runtime gates (start gate, finalize reconciler) honour the
486
- > waiver — the spec ticket itself need not be authored or approved when
487
- > the waiver is set. See [SDLC § Acceptance Spec — the third planning
488
- > context ticket](../../docs/SDLC.md#acceptance-spec--the-third-planning-context-ticket)
489
- > for the full lifecycle.
490
-
491
- <!-- separator: adjacent blockquotes -->
410
+ ## Phase 7: Epic Planning (Tech Spec & Acceptance Spec)
492
411
 
493
- > **Parallel-safe file naming (per-Epic tree).** Multiple Epics may be
494
- > planned or decomposed concurrently. Every temp file written in this
495
- > workflow lives under the per-Epic tree
496
- > (`temp/epic-[Epic_ID]/<artifact>`) e.g.
497
- > `temp/epic-[Epic_ID]/planner-context.json`,
498
- > `temp/epic-[Epic_ID]/prd.md`, `temp/epic-[Epic_ID]/techspec.md`,
499
- > `temp/epic-[Epic_ID]/decomposer-context.json`,
500
- > `temp/epic-[Epic_ID]/tickets.json`. The directory namespace is the
501
- > isolation boundary; basenames inside it are stable. Do **not** reuse
502
- > bare flat names like `temp/prd.md` or the legacy
503
- > `temp/<artifact>-epic-<id>.<ext>` shape — both have been retired.
504
- >
505
- > **Durability.** The per-Epic tree is durable across runs: only the
506
- > wrapper scripts perform intra-phase cleanup of files they wrote in
507
- > the same invocation (see
508
- > [`lib/plan-phase-cleanup.js`](../../scripts/lib/plan-phase-cleanup.js)).
509
- > Nothing else garbage-collects the tree, so cross-Epic artifacts —
510
- > retros, perf reports, signals, manifests — accumulate until an
511
- > operator explicitly removes them.
412
+ > **Phase-7 guards & managed-section rationale (reference).** This phase runs
413
+ > behind an **Epic-lease preflight** (`--steal` transfers a confirmed-dead
414
+ > claim; the lease releases after Phase 8), writes **idempotent managed
415
+ > sections** (`--force` overwrites them in place), lands **one planning
416
+ > document** (Tech Spec + Acceptance Table folded into the Epic body;
417
+ > `acceptance::n-a` waives the table), and namespaces every temp file under
418
+ > the durable **per-Epic tree** (`temp/epic-[Epic_ID]/…`). The full rationale
419
+ > for each guard is in
420
+ > [`plan-epic-reference.md` § Phase 7 background rationale](plan-epic-reference.md#phase-7--background-rationale).
512
421
 
513
422
  1. **Gather Authoring Context**: Run the spec-phase CLI in context-emission
514
423
  mode to fetch the Epic body, scraped project docs, and the recommended
@@ -523,18 +432,18 @@ for the scoring logic.
523
432
  via the `Read` tool (resolve `<agentRoot>` from
524
433
  `project.paths.agentRoot` — default `.agents`) and execute its
525
434
  procedure with `[Epic_ID]` as input. The skill reads
526
- `temp/epic-[Epic_ID]/planner-context.json`, authors the PRD, Tech
435
+ `temp/epic-[Epic_ID]/planner-context.json`, authors the Tech
527
436
  Spec, **risk verdict**, and **Acceptance Spec** against the embedded
528
- system prompts, and writes them to `temp/epic-[Epic_ID]/prd.md`,
437
+ system prompts, and writes them to
529
438
  `temp/epic-[Epic_ID]/techspec.md`,
530
439
  `temp/epic-[Epic_ID]/risk-verdict.json`, and
531
440
  `temp/epic-[Epic_ID]/acceptance-spec.md`. The skill is the
532
- authoritative authoring step — do **not** inline the PRD / Tech
441
+ authoritative authoring step — do **not** inline the Tech
533
442
  Spec / risk-verdict / Acceptance Spec drafting in the workflow
534
443
  body. The skill front-matter declares
535
444
  `allowed_tools: [Read, Write, Bash]`; it never calls GitHub.
536
445
 
537
- The skill body carries the authoritative PRD, Tech Spec, and
446
+ The skill body carries the authoritative Tech Spec and
538
447
  Acceptance Spec system prompts. The `systemPrompts` field on the
539
448
  `--emit-context` envelope is a backstop for legacy callers; the
540
449
  skill body wins when the two surfaces diverge.
@@ -546,59 +455,55 @@ for the scoring logic.
546
455
  (`deriveRiskEnvelope`), records a `risk-verdict` structured comment
547
456
  on the Epic, flips the Epic to `agent::review-spec`, and writes the
548
457
  `epic-plan-state` checkpoint (including the `riskVerdict` field).
549
- The `--acceptance-spec` flag persists the third planning ticket
550
- (`context::acceptance-spec`) alongside the PRD and Tech Spec; the
551
- persist half fails loudly if any file is missing or empty. Omit
552
- `--acceptance-spec` only when the Epic carries the `acceptance::n-a`
553
- waiver label.
458
+ The `--acceptance-table` flag persists the AC-ID table as the Epic
459
+ body's `## Acceptance Table` managed section alongside the Tech Spec
460
+ sections; the persist half fails loudly if any file is missing or
461
+ empty. Omit `--acceptance-table` only when the Epic carries the
462
+ `acceptance::n-a` waiver label.
554
463
 
555
464
  ```bash
556
- # Normal planning (three context tickets)
465
+ # Normal planning (both managed sections)
557
466
  node .agents/scripts/epic-plan-spec.js --epic [Epic_ID] \
558
- --prd temp/epic-[Epic_ID]/prd.md \
559
- --techspec temp/epic-[Epic_ID]/techspec.md \
467
+ --tech-spec temp/epic-[Epic_ID]/techspec.md \
560
468
  --risk-verdict temp/epic-[Epic_ID]/risk-verdict.json \
561
- --acceptance-spec temp/epic-[Epic_ID]/acceptance-spec.md
469
+ --acceptance-table temp/epic-[Epic_ID]/acceptance-spec.md
562
470
 
563
- # Re-planning (--force overwrites the three context tickets IN PLACE —
564
- # same PRD / Tech Spec / Acceptance Spec issue numbers, refreshed bodies,
565
- # tickets kept open, one regeneration audit comment each. Child Story
566
- # tickets are still close-and-recreate at decomposition time.)
471
+ # Re-planning (--force overwrites the Epic body's managed sections
472
+ # IN PLACE same Epic issue, refreshed section bodies, one
473
+ # regeneration audit comment on the Epic. Child Story tickets are
474
+ # still close-and-recreate at decomposition time.)
567
475
  node .agents/scripts/epic-plan-spec.js --epic [Epic_ID] \
568
- --prd temp/epic-[Epic_ID]/prd.md \
569
- --techspec temp/epic-[Epic_ID]/techspec.md \
476
+ --tech-spec temp/epic-[Epic_ID]/techspec.md \
570
477
  --risk-verdict temp/epic-[Epic_ID]/risk-verdict.json \
571
- --acceptance-spec temp/epic-[Epic_ID]/acceptance-spec.md --force
478
+ --acceptance-table temp/epic-[Epic_ID]/acceptance-spec.md --force
572
479
 
573
- # Waived (acceptance::n-a label on Epic — no spec authored)
480
+ # Waived (acceptance::n-a label on Epic — no acceptance table authored)
574
481
  node .agents/scripts/epic-plan-spec.js --epic [Epic_ID] \
575
- --prd temp/epic-[Epic_ID]/prd.md \
576
- --techspec temp/epic-[Epic_ID]/techspec.md \
482
+ --tech-spec temp/epic-[Epic_ID]/techspec.md \
577
483
  --risk-verdict temp/epic-[Epic_ID]/risk-verdict.json
578
484
  ```
579
485
 
580
486
  4. **Verification and review routing**:
581
- - Verify that the PRD, Technical Specification, and (when not waived)
582
- Acceptance Specification have been posted as linked issues under
583
- the Epic.
487
+ - Verify that the Technical Specification sections and (when not
488
+ waived) the `## Acceptance Table` section have landed as managed
489
+ sections of the Epic body.
584
490
  - Read `planningRisk` from the persist stdout JSON (or the
585
491
  `epic-plan-state` checkpoint). Branch on
586
492
  `planningRisk.requiresReview` unless the operator passed
587
493
  `--force-review`:
588
494
  - **High risk** (`requiresReview === true`) or **operator override**
589
495
  (`--force-review`) — **gate #2**: **STOP**. Ask the USER to review the
590
- generated PRD, Tech Spec, and Acceptance Spec on GitHub. Approval is
591
- the user's verbal OK in this session — the three context tickets stay
592
- **open** through delivery and are closed automatically by
593
- `/deliver` when the Epic PR opens. Do NOT proceed
496
+ updated Epic body (its Tech Spec sections and `## Acceptance
497
+ Table`) on GitHub. Approval is the user's verbal OK in this
498
+ session the sections live on the Epic itself, so there is
499
+ nothing to close at delivery time. Do NOT proceed
594
500
  to decomposition until the user confirms the plan is accurate.
595
501
 
596
502
  > **`--yes` (headless) auto-proceed.** When `/plan` was invoked with
597
503
  > `--yes`, this review gate does **not** STOP, even when
598
504
  > `requiresReview === true` or `--force-review` was also passed: the
599
505
  > review resolves as **approved** and the run **continues directly to
600
- > Phase 8**, exactly as the low-risk auto-proceed branch below. The
601
- > three context tickets stay **open** through delivery as usual; only
506
+ > Phase 8**, exactly as the low-risk auto-proceed branch below; only
602
507
  > the operator *wait* is suppressed. This is `/plan`'s **gate #2** —
603
508
  > the second and last HITL STOP `--yes` suppresses. `--yes` does
604
509
  > **not** alter risk routing or the review criteria themselves; it
@@ -612,8 +517,8 @@ for the scoring logic.
612
517
  decision is recorded in the `epic-plan-state` checkpoint. (`--yes` is
613
518
  a no-op on this branch — there is no STOP to suppress.)
614
519
 
615
- 5. **Tech Spec freshness check (advisory)**: After the Tech Spec issue
616
- is created, `epic-plan-spec.js` runs
520
+ 5. **Tech Spec freshness check (advisory)**: After the Tech Spec sections
521
+ are persisted, `epic-plan-spec.js` runs
617
522
  [`validateSpecFreshness`](../../scripts/lib/orchestration/spec-freshness.js)
618
523
  against the authored Tech Spec body, probing every cited path-shape
619
524
  reference (backticked paths, `// header` lines in code blocks, and
@@ -628,14 +533,14 @@ for the scoring logic.
628
533
  reference the Architect inherited from drift-stale docs.
629
534
 
630
535
  When ≥1 stale reference is detected, a `spec-freshness` structured
631
- comment is upserted on the Tech Spec issue listing each citation
536
+ comment is upserted on the **Epic** listing each citation
632
537
  with its line number. The full report is also written to
633
538
  `<tempRoot>/epic-<id>-spec-freshness.json` for downstream tooling.
634
539
  The check is **advisory and non-blocking** — Phase 7 completes even
635
540
  when stale references are present, so the operator retains final
636
541
  judgment on edge cases. If the run summary shows
637
- `⚠️ Spec freshness: N stale / M ambiguous`, review the Tech Spec
638
- issue's `spec-freshness` comment and correct the cited spec body
542
+ `⚠️ Spec freshness: N stale / M ambiguous`, review the Epic's
543
+ `spec-freshness` comment and correct the cited spec sections
639
544
  before approving the plan for Phase 8.
640
545
 
641
546
  6. **BDD scenario cross-reference (advisory)**: When the project has
@@ -716,8 +621,8 @@ node .agents/scripts/epic-plan-spec-validate.js \
716
621
 
717
622
  **STOP** on a non-zero exit: do not advance to Phase 8. Re-author the Tech
718
623
  Spec (re-run the Phase 7 spec-author step) or add a `## Delivery Slicing`
719
- section to the Tech Spec issue body by hand, then re-run the gate until it
720
- exits 0.
624
+ section by hand (to the temp spec file and the Epic body's tech-spec
625
+ section), then re-run the gate until it exits 0.
721
626
 
722
627
  ## Phase 8: Work Breakdown Decomposition
723
628
 
@@ -735,7 +640,7 @@ node .agents/scripts/epic-plan-spec-validate.js \
735
640
  > **Hierarchy.** The decomposer emits a flat Story backlog under the Epic.
736
641
  > Acceptance criteria and verification steps are inlined on each Story
737
642
  > body (`acceptance[]` / `verify[]` fields) and resolved against the
738
- > Acceptance Spec context ticket at close time. See
643
+ > Epic body's `## Acceptance Table` section at close time. See
739
644
  > [`.agents/instructions.md` § 5.D](../../instructions.md) for the full
740
645
  > contract.
741
646
 
@@ -750,8 +655,9 @@ node .agents/scripts/epic-plan-spec-validate.js \
750
655
  via the `Read` tool (resolve `<agentRoot>` from
751
656
  `project.paths.agentRoot` — default `.agents`) and execute its
752
657
  procedure with `[Epic_ID]` as input. The skill reads
753
- `temp/epic-[Epic_ID]/decomposer-context.json` (PRD body, Tech Spec
754
- body, risk heuristics, `maxTickets` cap, `contextMode`), applies its
658
+ `temp/epic-[Epic_ID]/decomposer-context.json` (`epicBody` carrying
659
+ the folded Tech Spec sections and Acceptance Table — risk
660
+ heuristics, `maxTickets` cap, `contextMode`), applies its
755
661
  embedded decomposer system prompt + ticket schema, and writes the
756
662
  ticket array to `temp/epic-[Epic_ID]/tickets.json`. Do **not** inline
757
663
  the JSON authoring in the workflow body.
@@ -781,8 +687,9 @@ node .agents/scripts/epic-plan-spec-validate.js \
781
687
  [`epic-plan-consolidate`](../../skills/core/epic-plan-consolidate/SKILL.md)
782
688
  skill with `[Epic_ID]` as input. This is a **separate critic pass with
783
689
  fresh context** (not a self-review appended to the author skill): it reads
784
- the draft array plus the PRD / Tech Spec, reconciles the draft against the
785
- Tech Spec `## Delivery Slicing` target, and emits a **consolidated**
690
+ the draft array plus the Epic body (which carries the Tech Spec
691
+ sections), reconciles the draft against
692
+ the Tech Spec `## Delivery Slicing` target, and emits a **consolidated**
786
693
  `tickets.json` plus a human-readable
787
694
  `temp/epic-[Epic_ID]/consolidation-report.md`. Its operations are
788
695
  scope-preserving only — **merge sibling Stories and rewire
@@ -838,8 +745,9 @@ node .agents/scripts/epic-plan-spec-validate.js \
838
745
  reachability critic (8.4) and **before** the persist call below, activate the
839
746
  [`epic-plan-premortem`](../../skills/core/epic-plan-premortem/SKILL.md)
840
747
  skill with `[Epic_ID]` as input. This is a **fresh-context critic** sibling
841
- to `epic-plan-consolidate`: it reads the drafted `tickets.json`, the PRD /
842
- Tech Spec, **and the actual cited code surfaces** (the files each Story's
748
+ to `epic-plan-consolidate`: it reads the drafted `tickets.json`, the Epic
749
+ body (with its folded Tech Spec sections), **and the actual cited code
750
+ surfaces** (the files each Story's
843
751
  `changes[]` / `references[]` name), then emits predicted-rework findings —
844
752
  unverifiable acceptance criteria, over- or under-specified Stories, and
845
753
  semantically-wrong assumptions the structural file-assumption gate (step 7)
@@ -868,6 +776,11 @@ node .agents/scripts/epic-plan-spec-validate.js \
868
776
  --tickets temp/epic-[Epic_ID]/tickets.json --force
869
777
  ```
870
778
 
779
+ > On a large Epic (~60+ tickets) the persist can trip GitHub's secondary
780
+ > rate limit mid-run. Resume from the partial backlog with `--resume` — the
781
+ > full recovery contract is in
782
+ > [`plan-epic-reference.md` § Phase 8 — `--resume` recovery (secondary rate limit)](plan-epic-reference.md#phase-8----resume-recovery-secondary-rate-limit).
783
+
871
784
  7. **Cross-Validation**:
872
785
  - Hierarchy completeness, dependency-DAG acyclicity, and `risk::high`
873
786
  labelling are deterministic invariants enforced by
@@ -1032,8 +945,8 @@ forcing the walkthrough.
1032
945
 
1033
946
  Activate the
1034
947
  [`core/knowledge-transfer`](../../skills/core/knowledge-transfer/SKILL.md) skill
1035
- with the **plan** as the subject — the Epic body, the linked PRD / Tech Spec
1036
- context tickets, the decomposition (Stories with inline
948
+ with the **plan** as the subject — the Epic body (whose managed sections
949
+ carry the Tech Spec), the decomposition (Stories with inline
1037
950
  `acceptance[]` / `verify[]`), and the Phase 9 wave roadmap. The skill owns the
1038
951
  method (restate-first, the why-ladder, mastery gates, depth levels, optional
1039
952
  quizzing, the persistent `temp/comprehension-*.md` checklist).
@@ -1060,40 +973,12 @@ condition.
1060
973
  node .agents/scripts/notify.js [Epic_ID] "Planning complete, review tickets. Backlog decomposition complete. Epic is ready for /deliver." --action
1061
974
  ```
1062
975
 
1063
- ## Troubleshooting
1064
-
1065
- - If `epic-plan-spec.js --emit-context` fails, confirm the Epic exists and
1066
- has a body with enough initial context.
1067
- - If `epic-plan-decompose.js` rejects the tickets file, re-read the
1068
- validator's error message the most common causes are a ticket whose
1069
- `type` is not `story`, a Story missing its inline `acceptance[]` /
1070
- `verify[]` contract, or a dependency cycle in the Story `depends_on`
1071
- graph.
1072
- - If decomposition persisted the tickets but the Epic is not on `agent::ready`,
1073
- you likely called `runDecomposePhase` from `epic-plan-decompose.js`
1074
- directly without completing the persist flow — only the CLI surface
1075
- (`node epic-plan-decompose.js --tickets ...`) drives the full
1076
- reconciler pipeline and flips the lifecycle label. Apply `agent::ready`
1077
- by hand and re-run via the CLI next time.
1078
- - **Secondary rate limit on large Epics**: For backlogs over ~60 tickets,
1079
- GitHub's secondary rate limit (HTTP 403, body contains "secondary rate
1080
- limit") can trip mid-decomposition after ~80 issue creations. The
1081
- http-client retries automatically with a 30–120s backoff and the
1082
- decomposer drops `concurrencyCap` to 1 for the rest of the run on the
1083
- first observation. If the run still aborts (network drop, exhausted
1084
- retries, etc.), resume from the partial backlog with:
1085
-
1086
- ```bash
1087
- node .agents/scripts/epic-plan-decompose.js --epic [Epic_ID] \
1088
- --tickets temp/epic-[Epic_ID]/tickets.json --resume
1089
- ```
976
+ ## Troubleshooting & recovery
977
+
978
+ Troubleshooting symptoms (emit-context failures, tickets-file rejections, a
979
+ decomposition that persisted but left the Epic off `agent::ready`) and the
980
+ large-Epic **secondary-rate-limit `--resume`** recovery path live in the
981
+ reference companionthey are consulted only when a run hits the edge:
1090
982
 
1091
- `--resume` is idempotent: the reconciler recovers the slug→issue map
1092
- from `temp/epic-[Epic_ID]/[Epic_ID].state.json`, and when that file is
1093
- missing or incomplete it **reseeds the map from live GitHub state** by
1094
- matching each spec slug against the open children of the Epic by title.
1095
- Slugs that resolve to an existing open child diff as Updates/no-ops;
1096
- only the genuinely-missing children are created — the existing tree is
1097
- never duplicated. To force-throttle from the first call on a known-large
1098
- Epic, set `(framework constant: decomposer concurrency): 1` in
1099
- `.agentrc.json`.
983
+ - [`plan-epic-reference.md` § Troubleshooting](plan-epic-reference.md#troubleshooting)
984
+ - [`plan-epic-reference.md` § Phase 8 `--resume` recovery (secondary rate limit)](plan-epic-reference.md#phase-8----resume-recovery-secondary-rate-limit)