| name | cpm:epics |
| description | Break a spec into epic documents with stories and tasks. Reads a specification and produces multiple epic docs, each containing stories with sub-tasks. Triggers on "/cpm:epics". |
Work Breakdown into Epics
Turn a specification into a set of epic documents — each representing a major work area containing stories (meaningful deliverables with acceptance criteria) and tasks (implementation steps). Epic documents are the plan of record — task creation in Claude Code's native system happens later during execution via cpm:do.
Input
Check for input in this order:
- If
$ARGUMENTS references a file path, read that file as the source.
- If
$ARGUMENTS contains a description, use that as the source.
- Look for planning docs — check
docs/specifications/ first, then docs/plans/.
- If nothing found, ask the user what work they want to break down.
Dependency-view mode (on request). If $ARGUMENTS asks for a dependency / readiness / "what's ready to pick up" view of the existing epics (e.g. contains dependency view, dependencies, unblocked, ready to pick up, or "what can I work on") rather than naming work to break down, do not run the production process below. Instead run the Dependency View (on request) section (after ## Output) — a read-only HTML projection over the epic docs that already exist. The two modes are mutually exclusive: breaking a spec into epics writes epic docs; the dependency view only reads them.
Process
State tracking: Create the progress file before Step 1 and update it after each step completes. See State Management below for the format and rationale. Delete the file once the final epic docs have been saved.
Termination
- Success: The user confirms the final task tree in Step 4 — save the epic documents and finish.
- Blocker: The user identifies a spec gap, missing requirement, or dependency that cannot be resolved in this session. Note the gap, save the epic documents with what's confirmed, and flag the gap for resolution via
cpm:pivot or a spec update.
- Ambiguity: The user is uncertain about epic grouping, story scope, or task breakdown after one clarification round. Present a recommended structure with rationale. If the user still cannot decide, use the recommended default and note the decision as provisional — it can be revised before
cpm:do begins execution.
Facilitation depth: Each presentation-and-refine gate (Step 2 epics, Step 3 stories, Step 3b tasks) converges in 1-2 rounds of AskUserQuestion. When the user approves, move on. Step 3d coverage matrix and Step 4 confirmation are single-pass gates — present once, refine once if needed, then proceed.
Retro Check (Startup)
Follow the shared Retro Awareness procedure before beginning Step 1.
Retro incorporation (this skill):
- Scope surprises: Inform Step 3 (story sizing) — past stories that ran larger or smaller than expected suggest sizing rules to apply this round (e.g. "split stories that touch more than N components").
- Patterns worth reusing: Inform Step 3b (task lists) — surfaced abstractions and approaches become candidate tasks rather than re-discovered work.
- Testing gaps: Inform Step 3 acceptance criteria tagging — past untestable criteria become explicitly tagged this round.
- Codebase discoveries: Inform Step 3c (integration testing story) — surfaced integration points may need explicit cross-story coverage.
Library Check (Startup)
Follow the shared Library Check procedure with scope keyword epics. Deep-read selectively during Step 2 epic grouping when architecture or coding-standards docs affect epic boundaries or dependency identification.
Template Hint (Startup)
After startup checks and before Step 1, display:
Output format is fixed (used by downstream skills). Run /cpm:templates preview epics to see the format.
ADR Discovery (Startup)
After the Template Hint and before Step 1, discover existing Architecture Decision Records:
- Glob
docs/architecture/[0-9]*-adr-*.md. If no files found or directory doesn't exist, skip silently.
- If ADRs exist, read each one and note the architectural decisions and their dependencies. Report to the user: "Found {N} existing ADRs: {titles}. I'll reference these when breaking down architectural work into epics and stories."
- During Step 2 (Identify Epics) and Step 3 (Break into Stories), use ADR context to inform epic grouping — e.g. if an ADR identifies separate concerns or bounded contexts, these may map naturally to epics. Reference specific ADRs in story descriptions when they constrain or inform the implementation approach.
Graceful degradation: If ADRs are absent, epic breakdown works as before — deriving structure purely from the spec. The skill works with or without cpm:architect having been run.
Step 1: Read Source
Read and understand the source document. Summarise the key work areas to the user.
Step 2: Identify Epics
Analyse the source to identify major work areas. Each epic will become its own document at docs/epics/{parent}-{seq}-epic-{slug}.md. See the Epic Filename Convention subsection below for the parent-extraction and sub-number rules.
For each epic, determine:
- Name: A concise label for the work area (e.g. "Authentication System", "API Layer")
- Filename prefix (
{parent}-{seq}): Assigned per the Epic Filename Convention subsection below — {parent} comes from the source spec number (or 00 for orphans), {seq} increments within that parent.
- Slug (
{slug}): Kebab-case derived from the epic name (e.g. "authentication-system", "api-layer")
- Summary: One-sentence description of what this epic covers
Render the epic grouping (names, summaries, proposed filenames) in the message body so the user can see the full output plan. Then use AskUserQuestion as a short gate (e.g. "Approve this grouping?" with options Approve / Request changes / Stop) and refine. See the shared Gate Presentation convention.
Keep epics practical:
- 2-5 epics for a small feature
- 5-10 for a larger project
- Only create an epic when the work genuinely warrants one
Epic Filename Convention
Epic documents use a two-part numeric prefix: {parent}-{seq}-epic-{slug}.md. This makes the parent spec discoverable at the filename level — a reader scanning ls docs/epics/ can identify an epic's source without opening the file.
Transition note: Epics created before the numbering update used flat {nn}-epic-{slug}.md. New epics use parent-scoped {parent}-{seq}-epic-{slug}.md. Both shapes coexist permanently — old epics are not migrated. Readers must handle both shapes; writers produce only the two-part shape.
Parent extraction:
- Spec-linked epics (the default — input is a spec):
{parent} is the numeric prefix of the source spec's filename. For example, input docs/specifications/28-spec-foo.md yields {parent} = 28, producing 28-01-epic-foo.md, 28-02-epic-bar.md, and so on.
- Orphan epics (input is a brief, discussion, description, or bare prompt — no parent spec):
{parent} is the literal string 00. Orphan epics are written as 00-{seq}-epic-{slug}.md. Every new epic produced by this skill uses the two-part shape.
Sub-number assignment ({seq}):
Assign {seq} per parent using the shared Numbering procedure — glob both docs/epics/{parent}-[0-9]*-epic-*.md and docs/archive/epics/{parent}-[0-9]*-epic-*.md, extract the second numeric field from each match, parse as integer (always integer comparison, never lexical), take max + 1 across the union. If both sets are empty, start at 01. Format using the shared Numbering width rule. Flat-shape files (e.g. 15-epic-consult-skill-core.md) are naturally excluded from the scoped glob.
Sub-numbers are identifiers, not ordinals — gaps from deleted sub-numbers are preserved (the max-lookup skips them), keeping cross-references stable.
General epic listings: Operations that enumerate all epics (for dependency resolution, batch status checks, cross-epic references) must use the general glob docs/epics/[0-9]*-epic-*.md, which matches both flat and two-part shapes. Only the sub-number assignment above uses the scoped glob. Always use the general glob for listings — narrowing to the two-part shape would hide legacy epics from readers.
Production loop: After epics are confirmed, Steps 3, 3b, 3c, and 3d iterate per epic — break each epic into stories, then tasks, then assess integration testing, then verify requirement coverage. Save each epic document and its coverage matrix after they are finalised (before moving to the next epic). This means epic docs are written incrementally, not all at once at the end.
Progress note: capture epic names, numbers, slugs, and output paths in the Step 2 summary.
Step 3: Break into Stories
For each epic, break into stories — meaningful deliverables that represent a coherent unit of value. A story answers "what are we delivering?" not "what file are we editing?"
Each story should have:
- A clear, actionable title (imperative form: "Set up compaction hook infrastructure")
- Acceptance criteria that describe the deliverable outcome
- An activeForm for progress display (present continuous: "Setting up compaction hook infrastructure")
- Spec traceability (when input is a spec): Which functional requirements from the spec this story satisfies. Use the requirement text or a short label. This enables verification that the spec is fully covered across all epics — every must-have requirement should appear in at least one story.
Acceptance criteria fidelity (when input is a spec): When deriving acceptance criteria from a spec, use the spec's language verbatim where it provides specific thresholds, values, or behaviours. Use the spec's language verbatim — preserve thresholds, values, and behaviours exactly. If the spec says "concurrent session limit of 3 per user", the story criterion says "concurrent session limit of 3 per user". The spec's specificity must survive intact into the stories.
Testability standard: Each acceptance criterion must be testable as written — it describes a specific, observable, verifiable outcome. Flag any criterion that relies on subjective judgement or cannot be verified through code, tests, or inspection. Criteria that fail this standard must be rewritten before the story is finalised.
Examples:
- Fails: "Users can log in" — no observable outcome defined
- Passes: "User with valid credentials receives a 200 response with a session token and is redirected to /dashboard"
- Fails: "Error handling works correctly" — subjective and unverifiable
- Passes: "Invalid OAuth token returns 401 with error body
{\"error\": \"invalid_token\"} and no session is created"
Test approach tag propagation (when the input spec has a Testing Strategy section with tagged criteria):
- Read the spec's Testing Strategy section — specifically the Acceptance Criteria Coverage table which maps requirements to criteria with
[tag] annotations.
- When writing story acceptance criteria, apply matching tags inline. For each acceptance criterion, append the appropriate tags from the spec's testing strategy:
[unit], [integration], [feature], [manual], and [tdd]. Match by tracing the story's **Satisfies** field back to the spec requirement, then looking up that requirement's tag assignments. The [tdd] tag is a workflow mode tag (orthogonal to level tags) — propagate it alongside any level tag when present (e.g. [tdd] [unit]).
- If a story's criteria go beyond a spec requirement's tagged criteria (e.g. the story introduces new criteria beyond the spec), default to an automated tag —
[unit], [integration], or [feature]. Propose [manual] only when automation is genuinely infeasible, and when you do, include a one-line justification stating what blocks automation (e.g. "requires human visual judgement", "third-party OAuth flow we don't control"). See the Default to automation guideline below.
- Tags appear at the end of the acceptance criteria line, e.g.:
- User can log in via OAuth [integration] or - Payment processor validates card [tdd] [integration]
Mockup-referencing criteria: When a spec or architect artifact references an HTML companion asset (a UI mockup or diagram — see the shared HTML Output convention), a story criterion that says "build to match this asset" describes visual conformance, whose only oracle is human judgement. Tag such a criterion [manual] (or [feature] when the match is exercised through a user-facing workflow) — never an automated markup-parsing test. The companion asset is a design target, not data: epics treats it as "build to match this," never as a source of requirements to extract. The Markdown acceptance criteria remain the machine-readable specification; the asset only shows what the result should look like. This is the named case where [manual]/[feature] is correct because the oracle is visual — record the one-line justification the Default to automation guideline requires (e.g. "match the referenced mockup — visual conformance, no markup oracle").
Graceful degradation: If the spec has no Testing Strategy section, no Acceptance Criteria Coverage table, or no tags, skip tag propagation entirely — write acceptance criteria without tags. The skill must work without cpm:spec's enhanced Section 6 having been used.
Must-NOT clause propagation (when the input spec has must NOT lines from Section 6b):
- Read the spec's Acceptance Criteria Coverage table for
must NOT lines paired with positive criteria.
- When writing story acceptance criteria, include the
must NOT lines alongside their paired positive criteria. Preserve the spec's wording verbatim — these are defensive boundaries, not suggestions.
- If a story's criteria go beyond the spec (new criteria without spec-originating must-NOTs), assess whether must-NOT clauses are warranted based on the story's domain (see below).
Must-NOT clause suggestion (when the spec has no must-NOT lines, or for criteria without them):
When a story touches any of these domains, propose must NOT clauses for the user to confirm:
- Security: authentication, authorization, session management, credential handling
- Data integrity: database writes, financial calculations, user data mutations
- External systems: API calls, webhook handling, third-party integrations
Propose 1-2 must-NOT clauses per relevant criterion. Present them via AskUserQuestion alongside the story's acceptance criteria for the user to accept, modify, or reject. If the user rejects all proposed must-NOTs, proceed without them — must-NOT clauses are advisory, not mandatory.
Graceful degradation: If the spec has no must-NOT lines and the story does not touch security, data integrity, or external systems, skip must-NOT suggestion entirely.
[plan] tag suggestion: After defining a story's acceptance criteria, assess whether it warrants formal plan mode during execution. The [plan] tag forces an EnterPlanMode pause before implementation — it's a workflow lock, not a signal that the story is hard. Append [plan] to the story's ## heading (e.g. ## Set up OAuth provider integration [plan]) when the story involves:
- Data model changes: New or modified database schemas, entity relationships, or data structures that affect persistence
- API contract changes: New or modified public APIs, webhook schemas, or inter-service contracts where the design needs upfront agreement
- Cross-system integration: Coordination across multiple external systems, APIs, or services where the interaction design needs upfront thought
These are the default assignment categories. The user can also add [plan] manually to any story they want gated — these categories are defaults, not restrictions. Stories that follow existing patterns, are fully specified by their acceptance criteria, or are straightforward config/documentation changes use inline planning (the default in cpm:do).
Stories vs tasks: A story groups related implementation work under a single deliverable with shared acceptance criteria. If you find yourself writing a story title that describes a single file change or a single function — that's a task, not a story. Push it down to Step 3b.
Render the stories for each epic (titles, summaries, acceptance criteria) in the message body. After the stories, render a tag distribution summary showing per-story counts so any drift toward manual is visible at a glance. Format:
Tag distribution:
- Story 1 — {N} automated ([unit] x{a}, [integration] x{b}, [feature] x{c}), {M} manual
- Story 2 — {N} automated, {M} manual
- ...
If any story has zero automated tags, flag it explicitly under the table (e.g. "⚠ Story 2 is fully manual — confirm this is intentional"). Then use AskUserQuestion as a short gate (e.g. "Approve these stories?" with options Approve / Request changes / Stop). Refine before moving to the next epic. See the shared Gate Presentation convention.
Progress note: record which tags were propagated to which stories in the Step 3 summary.
Step 3b: Identify Tasks within Stories
For each story, identify the tasks — concrete implementation steps needed to deliver the story. Each task should have:
- A clear, actionable title (imperative form: "Create hooks.json configuration")
- A dot-notation number linking it to its parent story (e.g. Task 1.1, 1.2, 1.3 for Story 1)
- A one-sentence description that scopes the task within its parent story — which acceptance criteria or concern this task addresses
Task descriptions: Write a description for every task in stories with multiple tasks. Descriptions eliminate the three-hop lookup (title → story criteria → spec) by anchoring each task to the acceptance criteria it addresses — e.g. "Covers the error handling criteria for roster loading" or "Produces the interface that Task 2.3 consumes." For single-task stories, omit the description when the title is self-evident — but when in doubt, write one.
Descriptions should state scope boundaries, not implementation steps. Good descriptions reference criteria, relationships, or constraints; bad descriptions prescribe how to build it.
- Good: "Add roster loading section — project override (
docs/agents/roster.yaml) then plugin default (../../agents/roster.yaml), error if neither found. Present selected agent to the user."
- Good: "Addresses the error handling path, not the happy path — covers criteria 3 and 4."
- Bad: "Edit SKILL.md line 45 to add a YAML parsing block with error handling."
- Bad: "Create a function called loadRoster() that reads the file and returns an array."
Tasks are the actual work items. They should be specific enough that an implementer knows exactly what to do.
A single task per story is fine when the work is straightforward. Decompose only when it makes complex stories manageable.
Auto-generated testing tasks: After identifying implementation tasks for a story, check whether any of the story's acceptance criteria carry [unit], [integration], or [feature] tags. If at least one automated test tag is present:
- Auto-generate a testing task titled "Write tests for {story title}".
- Placement depends on
[tdd]:
- If the story's acceptance criteria include
[tdd], place the testing task before all implementation tasks (as the first task in the story). This enables the TDD red-green-refactor workflow — tests are written first, then implementation makes them pass. The testing task gets dot-notation number {story}.1, and implementation tasks follow sequentially.
- If the story does not carry
[tdd], place the testing task after all implementation tasks (as the last task in the story, before the verification gate that cpm:do will create). The testing task's dot-notation number follows the last implementation task (e.g. if implementation tasks are 1.1, 1.2, 1.3, the testing task is 1.4).
- Give it a description: "Write automated tests covering the story's acceptance criteria tagged
[unit], [integration], or [feature]."
If all of a story's criteria are tagged [manual] (or have no tags), do not generate a testing task — there's nothing to automate.
Graceful degradation: If no tags were propagated during Step 3 (e.g. the spec had no testing strategy), skip testing task generation entirely.
Render the tasks for each story in the message body. Then use AskUserQuestion as a short gate (e.g. "Approve these tasks?" with options Approve / Request changes / Stop). Refine before moving to the next story. See the shared Gate Presentation convention.
Step 3c: Integration Testing Story (when warranted)
After all implementation stories and their tasks are defined for an epic, assess whether the epic warrants a dedicated integration testing story. This is separate from per-story testing tasks (which test a single story's criteria) — an integration testing story verifies cross-story behaviour and integration points.
When to generate: Create an integration testing story when the epic has:
- Multiple stories with
[integration] tagged criteria that interact with each other
- Cross-story data flows, API contracts, or event-driven interactions
- Stories that produce components which must work together as a system
When to skip: Skip if the epic has only 1-2 stories, no [integration] tags, or stories that are independent of each other.
How to generate:
- Title: "Verify cross-story integration for {epic name}"
- Story number: the next sequential number after the last implementation story
**Blocked by**: all implementation stories in the epic (comma-separated)
- Acceptance criteria: specific cross-story integration points that need verification. These should describe observable behaviour that spans multiple stories — not just "everything works together." Confirm with the user via AskUserQuestion.
- Tasks: typically a single task — "Write integration tests for {epic name}" — unless the integration points are complex enough to warrant separate tasks.
Graceful degradation: If no tags were propagated during Step 3, skip this step entirely.
Progress note: capture whether an integration story was generated or skipped, with the rationale, in the Step 3c summary.
Step 3d: Requirement Coverage Matrix (when input is a spec)
After stories, tasks, and integration testing are defined for the current epic, verify that the spec requirements this epic claims to satisfy are properly covered. This runs per-epic as part of the production loop (after Step 3c, before saving the epic doc and moving to the next epic).
The coverage matrix is procedural, not evaluative. Your job is to extract and present verbatim text from both the spec and the stories so the user can judge fidelity. Present the side-by-side text and let the human judge fidelity — the assessment is theirs to make.
- Identify which spec requirements this epic covers. Scan the epic's stories'
**Satisfies** fields to find all referenced spec requirements.
- Read the source spec's requirement text. For each referenced requirement, extract the number, label, and the specific text that defines thresholds, values, or behaviours. Quote from the requirements section, not the testing strategy table (these can differ — the requirements text is authoritative).
- Build a side-by-side coverage table. For each referenced requirement, quote both the spec's requirement text and the matching story acceptance criterion text verbatim — preserve the exact wording on both sides.
If the spec's Testing Strategy section includes test approach tags, add a Spec Test Approach column showing the tag(s) from the spec's Acceptance Criteria Coverage table. This lets the user verify tag propagation in the same view.
Present the coverage matrix to the user:
| # | Spec Requirement | Spec Text (verbatim) | Story Criterion (verbatim) | Covered by | Spec Test Approach | Verified |
|---|------------------|----------------------|----------------------------|------------|--------------------|----------|
| 1 | {requirement label} | {exact text from spec requirements section} | {exact criterion text from story} | Story {N} | `[tag]` | |
The "Verified" column is empty for all rows at creation time — it is populated later by /cpm:do during verification gates.
Where a single spec requirement maps to multiple story criteria, include one row per criterion so each mapping is independently visible.
If the user identifies a fidelity problem (story criterion is weaker than or contradicts spec text), update the affected story's acceptance criteria in the epic doc before proceeding.
Persist the matrix: After the user confirms, save the coverage matrix as docs/epics/{parent}-{seq}-coverage-{slug}.md — using the same two-part prefix and slug as the epic it covers (see Output section). Save the epic doc and coverage matrix together before moving to the next epic.
Regeneration awareness: Before saving, check whether a coverage matrix file already exists at the target path (e.g. from a previous /cpm:epics run). If an existing matrix is found and contains ✓ markers in the Verified column, the new matrix must clear verification for any rows whose "Story Criterion (verbatim)" text has changed — replace ✓ with empty for those rows. Rows whose criterion text is unchanged retain their ✓ status. If the existing matrix has no ✓ markers, or if no existing matrix is found, save the new matrix directly.
Graceful degradation: If the input is not a spec (e.g. a brief or description without structured requirements), skip this step — there's no requirement list to verify against.
Progress note: capture the matrix presentation, any fidelity issues identified and corrected, and user confirmation in the Step 3d summary.
Step 4: Confirm
Cross-epic gap check (when input is a spec): Before presenting the task tree, read all per-epic coverage matrices produced in Step 3d. Compare the union of covered requirements against the spec's full "Must Have" list. Any must-have requirement that doesn't appear in any coverage matrix is a GAP — flag it to the user. Gaps must be resolved (add to an existing epic, create a new story, or defer with justification) before proceeding. Should-have requirements not covered are warnings, not blockers.
Present the full task tree to the user showing:
- All epics with their stories and tasks (using story numbers and task dot-notation)
- Dependencies between epics (cross-epic) and between stories (cross-story)
- Suggested implementation order
- Cross-epic gap check result (all must-haves covered, or list unresolved gaps)
Use AskUserQuestion for final confirmation.
Output
Save each epic document to docs/epics/{parent}-{seq}-epic-{slug}.md. Create the docs/epics/ directory if it doesn't exist.
{parent}-{seq} is the two-part numeric prefix assigned during Step 2 — see the Epic Filename Convention subsection.
{slug} is the kebab-case name derived from the epic name.
# {Epic Name}
**Source spec**: {path to spec}
**Date**: {today's date}
**Status**: Pending
**Blocked by**: —
## {Story Title}
**Story**: {N}
**Status**: Pending
**Blocked by**: —
**Satisfies**: {spec requirement label(s) this story addresses — omit if no spec input}
**Acceptance Criteria**:
- {criterion}
- {criterion}
### {Task Title}
**Task**: {N.1}
**Description**: {Scope within parent story — which acceptance criteria this task covers, or what constraint/boundary it addresses}
**Status**: Pending
### {Task Title}
**Task**: {N.2}
**Description**: {Scope within parent story — which acceptance criteria this task covers, or what constraint/boundary it addresses}
**Status**: Pending
---
Epic-level metadata:
**Source spec**: Back-reference to the specification that produced this epic. Enables traceability from implementation back to requirements.
**Status**: Derived from stories — Pending when no stories are started, In Progress when any story is in progress, Complete when all stories are complete.
**Blocked by**: Cross-epic dependency. References another epic by its filename prefix (e.g. Epic 28-01-epic-setup for new two-part epics or Epic 15-epic-data-model for legacy flat epics — both shapes are valid). Leave as — when the epic has no upstream dependencies. Multiple dependencies are comma-separated (e.g. Epic 28-01-epic-setup, Epic 15-epic-data-model).
Story numbers are sequential per epic document, starting at 1. They provide stable references within the doc, independent of Claude Code's task system. The **Blocked by** field on stories references story numbers for intra-epic deps (e.g. Story 1 or Story 1, Story 2).
Task numbers use dot notation: {story number}.{task sequence}. Task 1.1 is the first task of Story 1, Task 2.3 is the third task of Story 2.
After saving each epic doc, tell the user the document path so they can reference it later.
Coverage Matrix Artifacts
Each epic gets a companion coverage matrix file saved alongside it during the production loop (Step 3d). The file uses the same two-part prefix and slug as its epic: docs/epics/{parent}-{seq}-coverage-{slug}.md. For legacy flat-shape epics, the coverage file retains the flat shape it was created with (docs/epics/{nn}-coverage-{slug}.md); both shapes coexist in the directory.
# Coverage Matrix: {Epic Name}
**Source spec**: {path to spec}
**Epic**: {path to epic doc}
**Date**: {today's date}
> **Verification rule**: Verification status (✓) is bound to criterion text. Any change to a story criterion or its spec mapping resets that row to unverified.
| # | Spec Requirement | Spec Text (verbatim) | Story Criterion (verbatim) | Covered by | Spec Test Approach | Verified |
|---|------------------|----------------------|----------------------------|------------|--------------------|----------|
| {rows from confirmed Step 3d matrix for this epic} |
Save each coverage matrix at the same time as its epic doc. Tell the user both file paths together.
When starting implementation of a task, read the relevant epic document first to understand the full context: all stories, tasks, dependencies, acceptance criteria, and where the current task fits in the broader plan. Also read the epic's coverage matrix when available — its path follows the epic doc's own shape (docs/epics/{parent}-{seq}-coverage-{slug}.md for new two-part epics, or docs/epics/{nn}-coverage-{slug}.md for legacy flat epics). It provides requirement-level traceability that connects each task back to the spec.
Dependency View (on request)
cpm:epics writes epic docs from a spec; the dependency view is the inverse — a read-only HTML projection over the epic docs that already exist, showing what is ready to pick up versus what is still blocked. It runs only when requested (see Dependency-view mode under Input), never as part of the production loop. Follow the shared HTML Output convention for the template mechanics; this section states only the epics-specific particulars.
The epic docs are the read-only source of truth. This mode parses them but must never modify, rewrite, or re-save any epic doc — no Edit/Write to anything under docs/epics/. The only file written is the HTML view itself, at a separate path. Mutation of epic docs stays exclusively with cpm:do.
- Scan all epics with the general glob
docs/epics/[0-9]*-epic-*.md (matches both two-part and legacy flat shapes — never narrow this, or legacy epics vanish from the view). Read each read-only. From each, parse the epic-level **Status** and, for every ## story, its **Status** and **Blocked by** fields.
- Compute readiness using the same rule
cpm:do hydration applies, so the view agrees with what do would actually pick up:
- A story's dependency is satisfied when the referenced story/epic has
**Status**: Complete (or the **Blocked by** field is —).
- A Pending story whose dependencies are all satisfied is Ready to pick up (unblocked). A Pending story with any unsatisfied dependency is Blocked — record what it waits on.
- In progress and Complete stories are shown in their own groups.
- Render via the shared template — substitute the
CPM: tokens, never fork the <style> block. Use unblocked-first ordering with these sections (give each an id for the .cpm-toc nav): Ready to pick up (unblocked Pending stories, each with its parent epic and a /cpm:do {epic path} next-step), Blocked (each with the unmet dependency named, as .cpm-callout--note), In progress, Complete. Use the template's .sev-* badges for the readiness colour language and a <table> or callouts for grouping.
- Tier 2 — optional export affordances. The view may include inline vanilla JS for copy-as-prompt / copy-as-JSON export — follow the shared HTML Output → Tier 2 export affordances convention for the canonical pattern and rules (inline-only, read-only/export-only, data embedded at generation time). Useful here: copy-as-prompt on each ready item (e.g.
/cpm:do docs/epics/05-…) and copy-as-JSON of the ready-to-pick-up list for downstream tooling. A purely static view is an equally valid deliverable.
- Self-contained — a single file: inline CSS/SVG and inline JS only, no external CSS/JS/images/fonts, no build step.
- Write to the ephemeral scratch path
docs/plans/epics-dependency-view.html — a regenerated-on-demand projection, not a numbered/tracked artifact (no {nn} prefix, never committed by the skill). Re-running overwrites it in place. Tell the user the path and that it is ephemeral. If the user asks to keep it durably, save a copy to a location they specify (or offer a sensible default and confirm).
Schema tolerance — render what parsed, flag the rest, never error out. Epic docs drift: a story may be missing its **Status** or **Blocked by** field, an epic may lack a parseable header, or a file may have no ## stories at all. A single malformed doc must never abort the whole view or blank a section. Degrade gracefully:
- Missing
**Status** on a story — do not guess a readiness bucket. Render the story in a dedicated Needs attention group, visibly flagged (a .sev-major "status unparsed" badge inside a .cpm-callout--warn), so the gap is obvious rather than silently mis-bucketed.
- Missing or unparseable
**Blocked by** — treat dependencies as undetermined for ordering, render the story, and flag it "dependencies unparsed" rather than assuming it is ready.
- An epic file that cannot be parsed (no recognisable stories, malformed structure) — list it by filename under a Could not parse entry in the Needs-attention group and continue with every other epic. One bad file costs one line, not the view.
- Always emit a valid, self-contained document. Even if every epic is malformed, the view renders its shell and the Needs-attention group; it does not throw, abort, or produce a broken file.
The flagged gaps are visible by design — the view shows what it could read and names what it couldn't, so the reader trusts the parts that rendered.
State Management
Follow the shared Progress File Management procedure.
Lifecycle:
- Create: before starting Step 1 (ensure
docs/plans/ exists).
- Update: after each step completes.
- Delete: only after confirming the final epic documents are saved and written.
Format:
# CPM Session State
**Skill**: cpm:epics
**Step**: {N} of 4 — {Step Name}
**Input source**: {path to spec or brief used as input}
## Epic Files
| # | Slug | Path | Status |
|---|------|------|--------|
| 28-01 | {slug} | docs/epics/28-01-epic-{slug}.md | {Pending/Written} |
| 28-02 | {slug} | docs/epics/28-02-epic-{slug}.md | {Pending/Written} |
## Completed Steps
### Step 1: Read Source
{Concise summary — what document was read, key work areas identified}
### Step 2: Identify Epics
{Epic names, numbers, slugs, and output paths as confirmed by user}
### Step 3: Break into Stories
{List of stories per epic — titles and acceptance criteria summaries. Include tag propagation status:
- Tags propagated from spec: yes/no/skipped (no testing strategy in spec)
- Per-story tags: Story 1 criteria tagged [unit] x2, [integration] x1; Story 2 criteria tagged [manual] x3; etc.}
### Step 3b: Identify Tasks within Stories
{List of tasks per story — titles and dot-notation numbers. Note which stories got auto-generated testing tasks.}
### Step 3c: Integration Testing Story
{Integration testing story generated or skipped, with rationale. If generated: story title, blocked-by list, acceptance criteria summary.}
### Step 3d: Requirement Coverage Matrix
{Per-epic: coverage matrix presented to user — requirements this epic covers, fidelity issues identified and corrected. Matrix saved to docs/epics/{parent}-{seq}-coverage-{slug}.md.}
{...include only completed steps...}
## Next Action
{What to ask or do next in the facilitation}
The "Epic Files" table tracks which epic documents have been written. Mark each as "Written" after saving it during the production loop in Steps 3/3b. This enables post-compaction recovery to know which files exist and which still need to be produced.
The "Completed Steps" section grows as steps complete. Epic state is more structured than other skills because it accumulates concrete artifacts — epic names, story titles, task titles, and dependency declarations that must survive compaction for the remaining steps to work.
The "Next Action" field tells the post-compaction context exactly where to pick up.
Guidelines
-
Epics are work areas, stories are deliverables, tasks are steps. An epic represents a major area of work ("Authentication System"). Stories within it represent meaningful outcomes ("Set up OAuth provider integration"). Tasks are the implementation work to get there ("Create OAuth callback handler", "Write token refresh logic"). If an epic has only one story, it's probably not an epic.
-
Right-sized stories. Each story should be completable in a focused session. Not too big (vague multi-day effort), not too small (a single trivial change). A story with 2-5 tasks is typical.
-
Acceptance criteria live on stories. Tasks inherit meaning from their parent story — acceptance criteria belong at the story level. The story is done when its acceptance criteria pass, not necessarily when every task checkbox is ticked.
-
Right-size task decomposition. A single task per story is fine when the work is straightforward. The value of task-level breakdown is making complex stories manageable, not adding bureaucracy to simple ones.
-
Dependencies between stories or epics, not tasks. Use **Blocked by**: Story N for intra-epic story dependencies. Use **Blocked by**: Epic {filename-prefix}-epic-{slug} for cross-epic dependencies — e.g. Epic 28-01-epic-foo for new two-part epics, or Epic 15-epic-bar for legacy flat epics (both shapes are valid). Keep dependencies at the story level — if tasks in different stories are interdependent, the stories themselves should carry the dependency.
-
One epic, one document. Each epic produces its own markdown file. This keeps documents focused and allows parallel work on independent epics.
-
Default to automation. When proposing tags for new criteria, the default is automation — [unit], [integration], or [feature]. [manual] is the exception, not a peer of the automated tags. Reach for an automated tag whenever the criterion describes:
- CRUD operations, validation rules, or business logic
- API contracts, request/response shape, or status code behaviour
- Authentication / authorisation flows (sessions, tokens, permission checks)
- Data transformations, calculations, or state machines
- Persistence behaviour (database writes, migrations, query results)
- Event flows or message handling between components
- User-visible workflows that can be driven by a feature/E2E test runner
Reach for [manual] only when the criterion describes:
- Visual or UX judgement (chart legibility, copy quality, layout polish)
- Third-party UI you don't control (an external OAuth provider's login page, a payment processor's hosted form)
- Content review of generated text, images, or media
- Observability checks against external systems (e.g. confirming an email actually arrived in a real inbox)
- Behaviour that is genuinely infeasible to exercise from code in the current test infrastructure
Every [manual] tag carries a one-line justification stating which of the above (or a comparable reason) applies. If you can't write the justification, the criterion probably belongs in an automated tag.
-
Testing tasks are auto-generated, not manually created. When story criteria carry [unit], [integration], or [feature] tags, Step 3b auto-generates a "Write tests" task. Let the automation handle testing tasks — it ensures consistency. Stories with only [manual] criteria get no testing task.
-
[tdd] reverses testing task order. When a story's criteria include [tdd], the auto-generated testing task is placed before implementation tasks — enabling the red-green-refactor workflow where tests are written first. Stories without [tdd] retain the default order (testing task after implementation). Both modes can coexist in the same epic.
-
[plan] opts into formal plan mode. When a story heading carries [plan], cpm:do enters formal plan mode (EnterPlanMode/ExitPlanMode) for that story's tasks — enforcing read-only exploration and user approval before implementation. Without [plan], cpm:do uses inline planning (brief text plan, then straight to implementation) which keeps the task loop uninterrupted. Suggest [plan] for stories involving architectural decisions, security-sensitive areas, or multi-system integration. Most stories work well with inline planning.
-
Integration testing stories are for cross-story verification. They're distinct from per-story testing tasks. Create them only when the epic has genuine cross-story integration points.
-
Coverage matrix is procedural, not evaluative. Step 3d runs per-epic and quotes spec text and story criterion text side-by-side — verbatim, not summarised. Your job is extraction and presentation; the user judges fidelity. Leave "exact" vs "partial" judgement to the human — they make that call by reading the two columns. Each matrix is saved as docs/epics/{parent}-{seq}-coverage-{slug}.md alongside its epic. Step 4 then runs a cross-epic gap check to catch requirements that no epic covers.
-
Facilitate the grouping. The user knows their domain better than you. Present a suggested structure and let them reshape it.