eng-flow epics / stories / tasks
Stage 4 of the production track. Unlike Stages 1-3, output here is project-level, not per-spec — epics and stories persist and accumulate in a backlog as the project grows, with each story traceable back to the spec that spawned it. Tasks are a separate, on-demand step: generated per-story, only when the user is actually ready to implement that story, not automatically for the whole backlog.
Analytics
At the start of every numbered step in Steps 0-6 (including Step 0), run python3 "${CLAUDE_PLUGIN_ROOT}/.claude/skills/lib/bin/eng-flow-analytics-checkpoint" eng-flow-epics-stories-tasks "<step name>" "<dated-slug>". As the last action of Step 6, run python3 "${CLAUDE_PLUGIN_ROOT}/.claude/skills/lib/bin/eng-flow-analytics-finish" eng-flow-epics-stories-tasks "<dated-slug>". Step 7 is a separate invocation and gets its own analytics calls — see its own note below. See eng-flow-spec's Analytics section for what this logs and why; rollup via eng-flow-analytics (Stage 10).
Decision Ledger
Check $ARGUMENTS for a --guide token; if present, every decision point below gets an explicit AskUserQuestion instead of a silent default, and Step 6's report (Step 7's own report for the breakdown run) adds a "Decisions I made / decisions you made" summary. Log every decision point via python3 "${CLAUDE_PLUGIN_ROOT}/.claude/skills/lib/bin/eng-flow-decision-log" eng-flow-epics-stories-tasks "<step>" <reason> <mode> <owner> "<description>" "<dated-slug>" (use eng-flow-epics-stories-tasks-breakdown as the skill name for Step 7's own calls, matching its separate analytics tag). See eng-flow-spec's Decision Ledger section for the taxonomy and why. Rollup/analysis: eng-flow-retro Step 1 (Stage 9).
Step 0 — Find the inputs
Locate the spec folder this run is for (eng-flow/specs/<dated-slug>/, containing spec.md, domain-model.md, architecture.md). If any are missing, tell the user which stage to run first.
Check whether eng-flow/backlog/ already exists. If it does, this may be an update pass (new spec, existing backlog) rather than a first run — don't recreate or duplicate epics that already reference this project; just add what's new.
Step 1 — Propose epics
Candidates come from two places, cross-referenced:
- The spec's domains touched list (each domain is often a natural epic boundary)
- The architecture's system diagram groupings (confirms which domains are actually coupled vs independent — two domains diagrammed as tightly coupled might be one epic, not two)
Present the candidate epic list to the user and ask them to confirm, merge, or split — don't finalize silently. An epic should represent a real outcome ("users can complete checkout end-to-end"), not just restate a domain name.
Log it: risk open_question <user_confirmed|user_revised> "epics: <confirmed as-is|merged/split: how>".
For each confirmed epic, capture: name, outcome/goal (what value this delivers, not what gets built), source spec reference, linked domains.
Step 2 — Derive stories per epic
Walk the spec's user journeys — each journey, or each meaningful step within one, is a candidate story. Apply the test: who benefits, and what do they gain? If you can't answer both, it's not a real story yet — narrow it.
Size against the 1-3 day completable bar (a story too big for that is really two stories — split it now, don't defer the problem). Ask the user to confirm the split rather than asserting it.
Log it: risk open_question <user_confirmed|user_revised> "story '<name>' sizing: <accepted|split: how>".
For each story, write acceptance criteria — specific, testable conditions, not "works correctly."
Step 3 — Cross-check against architecture
For each story, check the architecture's system diagram and API contracts: does this story touch two or more independently-diagrammed subsystems? If so, flag it — either as a candidate to split further, or, if it genuinely can't be split, as a coordination note (which subsystems, what the dependency is) so it isn't picked up assuming it's a single-subsystem change.
Log flagged stories: risk silent_decide ai_inferred "story '<name>' spans 2+ subsystems: <split candidate | coordination note>".
Step 4 — Traceability
Every story references its parent epic and the source spec path. Every epic references its source spec path and linked domains. This is what makes the backlog navigable later — don't skip it even for a small backlog; it's cheap now and expensive to reconstruct later.
Step 5 — Save (project-level backlog)
Compute slugs the same way as spec (lowercase, spaces to dashes, strip to [a-z0-9._-]), from epic/story names — no date prefix here, since these persist independent of when they were written.
eng-flow/backlog/
epics/<epic-slug>.md
stories/<story-slug>.md
Epic file:
# Epic: [Name]
## Outcome
[What value this delivers]
## Source
Spec: eng-flow/specs/<dated-slug>/spec.md
Domains: [linked domains]
## Stories
- [story-slug]: [one-line title]
Story file:
# Story: [Name]
## As a / I want / So that
As a [user], I want to [action], so that [benefit].
## Parent Epic
[epic-slug]
## Source
Spec: eng-flow/specs/<dated-slug>/spec.md
## Acceptance Criteria
- [ ] [Specific, testable condition]
## Architecture Notes
[Subsystems touched; coordination note if it spans 2+ from Step 3, else "single subsystem"]
Write files, don't overwrite existing epics/stories from prior runs — if this run's proposals overlap an existing epic/story, ask the user whether to update it or add a new one. Log overlaps: risk open_question user_confirmed "'<slug>' overlaps existing: <updated|added new>".
Step 6 — Report back
List the epics and stories created (or updated). Tell the user tasks are separate: "say 'break story <slug> into tasks' when you're ready to implement it" — don't generate tasks for the whole backlog now.
If this run was in guide mode, add a "Decisions I made / decisions you made" summary here, drawn from this run's eng-flow-decision-log calls.
Run the Step 6 analytics-finish call (see Analytics section above) before ending.
Step 7 (separate invocation, on-demand, per-story) — Task breakdown
Analytics: this is its own run, tagged separately. At the start, run python3 "${CLAUDE_PLUGIN_ROOT}/.claude/skills/lib/bin/eng-flow-analytics-checkpoint" eng-flow-epics-stories-tasks-breakdown "task-breakdown" "<story-slug>". When done (after saving tasks.md below), run python3 "${CLAUDE_PLUGIN_ROOT}/.claude/skills/lib/bin/eng-flow-analytics-finish" eng-flow-epics-stories-tasks-breakdown "<story-slug>".
Only runs when the user names a specific story to implement. Read that story's file (eng-flow/backlog/stories/<story-slug>.md) and the relevant parts of architecture.md for that domain.
Break the story into tasks:
- Vertical slices, not horizontal layers — each task should deliver a working, testable increment (e.g. "user can submit the form end-to-end," not "build the database schema" as its own task).
- Dependency order — map what depends on what, build foundations first.
- Size each task: XS (1 file) / S (1-2 files) / M (3-5 files) / L (5-8 files, consider splitting) / XL (8+ files — break it down further, don't leave it XL).
- Split further if: it'd take more than ~2 hours of focused work, acceptance criteria needs more than 3 bullets to state, it touches 2+ independent subsystems, or the task title has "and" in it.
- Checkpoint every 2-3 tasks: tests pass, build succeeds, core flow works end-to-end.
Log the sizing/splitting pass: eng-flow-decision-log eng-flow-epics-stories-tasks-breakdown "task breakdown" risk silent_decide ai_inferred "story '<slug>': <N> tasks, split per size/dependency rules" "<story-slug>".
Task template:
## Task [N]: [Short descriptive title]
**Description:** [One paragraph]
**Acceptance criteria:**
- [ ] [Specific, testable condition]
**Verification:**
- [ ] Tests pass: [command]
- [ ] Build succeeds: [command]
- [ ] Manual check: [what to verify]
**Dependencies:** [Task numbers, or "None"]
**Files likely touched:**
- `path/to/file`
**Estimated scope:** [XS | S | M | L | XL]
Save to eng-flow/backlog/stories/<story-slug>/tasks.md.