Convert a plan, requirements document, or design spec into a dependency-aware hierarchy of beads sized for AI-agent execution. Invoke when the user wants to turn a PRD, design doc, roadmap, or feature spec into tracked work items — phrases like 'break this plan into beads', 'decompose this spec', 'create beads from this doc', 'plan to beads'. Checks `bd formula list` for a matching molecule template before hand-decomposing (pour beats re-derive), decomposes into epics carrying the molecule-le...
Installs into .claude/skills of the current project.
Are you the author of Plan To Beads?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/kurofune-plan-to-beads-claudit)
---
# Generated by djinn-gen-adapters from theme=djinn. DO NOT EDIT — regenerate via djinn-gen-adapters.
# djinn-compat: 1
name: plan-to-beads
description: "Convert a plan, requirements document, or design spec into a dependency-aware hierarchy of beads sized for AI-agent execution. Invoke when the user wants to turn a PRD, design doc, roadmap, or feature spec into tracked work items — phrases like 'break this plan into beads', 'decompose this spec', 'create beads from this doc', 'plan to beads'. Checks `bd formula list` for a matching molecule template before hand-decomposing (pour beats re-derive), decomposes into epics carrying the molecule-level brief plus vertical-slice features and tasks ordered bead-to-bead by data flow with phase labels, defers to the /create-bead skill (one invocation per bead, AC-quality gate enforced, subagent-dispatched) in Execute Mode and files the whole tree in one atomic `bd create --graph` call, and offers to distill recurring shapes into gated formulas afterward."
---
<!-- djinn-compat-check: begin -->
**Before anything else:** run `djinn skills check --here` in the repo you are working in. If it exits non-zero, stop: relay its output to the user verbatim — it names the fix — and run no other step of this skill. On exit 0, continue.
<!-- djinn-compat-check: end -->
# Plan to Beads
Convert a plan, requirements document, or design spec into a dependency-aware hierarchy of work items sized for AI agent execution. Every bead must carry the plan's design intent through to the executing agent — an agent with no memory of this planning session must understand not just WHAT to build, but WHY it exists and what DONE looks like from the user's perspective.
## How to use
When invoked, follow these steps in order. Skip steps that don't apply (e.g., if the user pastes text directly, skip the file-reading step).
**Canonical bead-creation rules live in the `/create-bead` skill** — field separation, required fields (including the depth fields for feature beads: Diagnostic Question, Reference Standard, Interaction Inventory, Scalability Assumption), vertical slice sizing, the Capability Gate, the concrete-verification rule, and worked examples. This skill applies those rules in the context of decomposing a plan into many beads, then invokes `/create-bead` per bead in Execute Mode to author each one with the AC-quality gate enforced. When in doubt about what a good bead looks like, read the `/create-bead` skill; when in doubt about how to turn a plan into many beads, read this file.
### Step 1 — Ingest the Plan
Accept the input in any of these forms:
- A file path (read it)
- Pasted text in the conversation
- A GitHub issue URL (fetch via `gh issue view`)
- A reference to a recent product-requirements / PRD document
Read the full document. Identify its structure — section headings, user stories, implementation decisions, constraints, and anything marked as out of scope.
### Step 1b — Check for a Matching Formula (molecules)
Before decomposing by hand, run `bd formula list`. Beads has a template layer above individual issues: a **formula** (TOML/JSON source) cooks into a **proto** (a template epic with `{{…}}` variable placeholders — the "protomolecule"), which `bd mol pour` instantiates as a **molecule** of real beads with variables substituted.
If a formula already captures this plan's shape — e.g., a gated vertical-slice-feature template — prefer `bd mol pour <formula> --var name=...` over hand-authoring the beads. Pouring is cheaper (no per-bead authoring or gate passes) and more consistent than re-deriving the same decomposition from prose each time.
**Gate caveat — non-negotiable:** pouring bypasses `/create-bead`, so only formulas whose step templates passed `/ac-quality-review` at authoring or distill time qualify (see Step 7). Pouring an ungated formula skips the quality gate this pipeline exists to enforce — if in doubt, review the formula's acceptance templates (`bd formula show <name>`) before pouring.
If no formula matches, decompose by hand (Steps 2-6) and consider distilling the result afterward (Step 7).
### Step 2 — Identify Epics and Phase Order
Each major feature area or workstream becomes an **epic**. Map plan sections to epics:
- Solution sections, user story clusters, and implementation decision groups typically map to epics
- Problem statements and "out of scope" sections do not become epics (but inform constraints)
**If the plan has phases or sprints**, create a phase epic for each one. Phase epics are containers and reading aids, not the ordering mechanism: execution order is carried by bead-to-bead blocking edges (Step 5), and a bead's phase alone never creates a blocking edge.
**Ordering and urgency are different dimensions — encode them separately.** Order is enforced by the bead-to-bead blocking edges of Step 5: `bd ready` surfaces a bead the moment its own blockers close, so ordering needs no help from the priority field. Priority means URGENCY, and it means that project-wide — the review-follow-up filing floor, the reaper's MinPriority exemption, and operator triage queries all read it as urgency. Do NOT encode phase number as priority: a Phase-3 bead may be the most important work in the plan, and stamping it P3 silently files it with the backlog on every priority-driven surface.
- Carry the phase dimension as a `phase-{n}` label instead (Step 5b) — filterable, and true by construction.
- Assign priority from the plan's own urgency language:
| Signal | Priority |
|---|---|
| "must have", "critical", "required", "blocking" | P1 |
| "should have", "important", "expected" | P2 |
| "nice to have", "could have", "stretch goal" | P3 |
| "future", "backlog", "out of scope (for now)" | P4 |
If the plan uses MoSCoW or another prioritization scheme, map from that instead.
**Tiebreak only:** within equal urgency, give earlier-phase beads the lower number so `bd ready`'s sort favors them when several beads are ready at once — but this is a tiebreak, never the encoding.
### Step 3 — Decompose Epics into Vertical Features
Each user-visible capability within an epic becomes a **feature**. Features inherit the parent epic's priority unless the plan specifies otherwise.
**The vertical slice rule:** A feature must cut through all necessary layers (data → logic → UI → tests) to deliver one complete capability. "Customer detail dossier with activity, open tickets, tags, and relationships" is one feature. Do NOT decompose this horizontally into "create ActivityTimeline component" + "create TicketList component" + "create TagBadges component" — those are structural fragments that produce scaffolding without substance. The one exception is a **wide refactor**, whose blast radius no single slice can contain — see "Wide refactors — the exception to vertical slicing" at the end of this step.
A feature should represent something a user or stakeholder could **demo, verify, and get value from on its own.** If you can't describe what the user sees when the feature is done, it's not a feature — it's plumbing.
**The epic carries the molecule-level brief.** Write the shared design context ONCE, in the epic's description: the Diagnostic Question, the Reference Standard, the architecture overview, and the plan pointer (`Source: {plan-file-path} §{Section}`). Children then carry only their delta — 1-3 sentences of local what + why plus slice-specific design pointers (see "Children of an epic" in `/create-bead`). This is the single biggest lever on per-bead size: the executing agent recovers the brief with one `bd show <parent>` (work-contract §2 requires reading it), instead of every sibling repeating the same paragraph and paying for it in every downstream gate's context.
#### Wide refactors — the exception to vertical slicing
One class of work breaks the rule above. A **wide refactor** is a single mechanical change — rename a column, retype a shared symbol, move a package — whose **blast radius** fans across the codebase: one edit breaks call sites in every corner of the tree at once, so no vertical slice can land green and a planner who forces one emits beads that cannot pass their own gate. Recognize it by blast radius, not by size — the change itself is trivial; what makes it wide is how many callers it breaks simultaneously.
Do not force a wide refactor into vertical slices. Sequence it as **expand → migrate → contract**, and wire the phases with real blocking edges in the plan:
1. **Expand** — one bead that adds the new form *beside* the old one, touching no call sites. Nothing breaks, because nothing has moved yet. This bead blocks every bead below it.
2. **Migrate** — call sites move in **batches sized by blast radius** (per package, per directory, per module), and **each batch is its own bead, blocked by the expand bead**. The suite stays green batch to batch because the old form still exists — that is the whole reason to expand first. Batches run in parallel unless two of them touch the same file, where the Step 4 sibling-file check still applies.
3. **Contract** — one bead that deletes the old form once no caller remains, **blocked by every migrate batch**. Miss one of those edges and `bd ready` will surface the delete while a caller still points at the old form.
**Fallback when the batches cannot stay green alone.** Some refactors have no expand form that keeps each batch green in isolation — an exhaustive-match retype, a schema change the ORM validates at boot. Keep the same expand → migrate → contract sequence, but let the migrate batches **share an integration branch** and **all block a final integrate-and-verify bead**. Green is promised only at that integration bead: each batch's acceptance criteria describe its own call-site conversion, and the integrate-and-verify bead carries the suite-green criterion for the whole chain. Say so in the batch beads' `notes` — an executing agent that expects a green suite from its own bead will otherwise thrash against a failure the plan already accounted for.
Wide-refactor beads are plumbing, not features: structural acceptance criteria ("no reference to `old_column` remains under `internal/`") are correct here, and the feature-only depth fields (Diagnostic Question, Interaction Inventory, Scalability Assumption) do not apply.
### Step 4 — Decompose Features into Tasks
Sizing depends on the type of work. The goal is always a **complete deliverable** — something that works and has value on its own.
**Sizing rules are canonical in `/create-bead`** ("Task sizing — vertical slices" and "Context budget — the binding sizing constraint"): one bead per consumer-facing capability, plumbing included, with each endpoint/migration/method as its own acceptance line; feature beads sized by capability, not file count; ≤ ~10 acceptance lines and ≤ ~250-word description. Do not re-derive them here. The planner-specific reminder: the caps are per-bead ceilings on the *executing agent's* context, and the cheapest way to stay under them across many siblings is the epic-as-brief rule from Step 3 — hoist shared context up, don't split beads sideways.
What follows is only what's specific to decomposing MANY beads from ONE plan.
#### Anti-scaffolding rule — this is critical
The old failure mode was tasks so small they produced empty shells. The new rule: **if completing a task would produce a component with no meaningful data, the task is too small.** Merge it with its siblings until the task produces something a user can look at and get value from.
BAD decomposition (horizontal — produces scaffolding):
```
- "Create Sparkline.svelte component"
- "Create CustomerOverviewTab.svelte component"
- "Create CustomerActivityTab.svelte component"
- "Add getActivity to API client"
```
GOOD decomposition (vertical — produces features):
```
- "Customer detail dossier: activity as chronological timeline, open
tickets with priority and age, tags as badges with context tooltip,
relationships with role labels, parent account as clickable link"
- "Customer activity timeline: event history with timestamps and source
labels, agent interaction trail from support spans, volume/latency
sparkline trends"
```
The first decomposition produces four files that each compile but show nothing useful. The second produces two complete capabilities a user can work with immediately.
#### Plumbing is sized by capability
One plumbing bead per consumer-facing capability — the unit one feature bead consumes. Each endpoint, migration, or service method is its own `acceptance_criteria` line, not its own bead: "Views CRUD" is one bead with four endpoint lines. Split only where two units serve different consumers or neither needs the other.
#### Post-decomposition validation — the sibling-file check
After producing all beads for a feature, check: **do any two beads in the same phase target the same file or UI surface?** If bead A adds an "activity section" to CustomerDetail.svelte and bead B adds a "tickets section" to the same file, they are horizontal fragments of one vertical slice. Merge them.
The test: count beads per target component/file within each phase. If a file appears in 3+ beads, those beads are almost certainly horizontal fragments and should be merged into one vertical feature bead. The exception is genuinely independent capabilities that happen to share a container (e.g., two unrelated API endpoints in the same router file).
#### The sequential-chain test — one task cut into a chain
The horizontal-fragment test above catches beads that collide **in parallel**; the **sequential-chain** test catches the opposite failure, one task cut into a chain that nothing can drain in parallel. **Where each bead in a chain blocks the next and all of them share a `touches` path, file it as one bead — or as one feature worked by one worker.**
Splitting an inherently sequential task is measured at a 39–70% loss (`docs/research/2026-09-19-graph-engineering.md` §2), and the chain buys back no parallelism: the ready frontier is one bead wide the whole way down, and every link pays its own full review pass — where 59.4% of coding tokens already go.
BEFORE (a 3-link chain over one file — 3 review passes, frontier width 1):
```
- "Add the Config struct to internal/config/config.go"
- "Add Load() to internal/config/config.go" (blocked by: the struct)
- "Add Validate() to internal/config/config.go" (blocked by: Load)
```
AFTER (one bead — 1 review pass, the same frontier width):
```
- "Config load and validation: Config struct with the documented defaults,
Load() reading the TOML file and reporting a parse error with the line
number, Validate() rejecting an unset port and naming the field"
```
Unchained beads that share a `touches` path gain nothing from the split either: the summoner serializes them at dispatch, so the frontier stays one wide.
#### Plumbing must name its consumer
Every plumbing bead's `notes` field must name the feature bead that consumes it. If no feature bead will use this endpoint/store/migration, the plumbing bead is speculative infrastructure and should not be created. This prevents horizontal decomposition disguised as plumbing.
#### Component manifest reconciliation
Some plans enumerate deliverable artifacts by name — a list of files, modules, components, endpoints, or services the plan explicitly commits to producing. Those manifests are the plan author's contract with the executing agent. They must not be silently absorbed into higher-level feature descriptions.
When the source plan contains a named manifest:
1. **Extract** every named artifact into a checklist before decomposition.
2. **Reconcile** each artifact against the produced beads. An artifact is accounted for when either:
- It appears by name in some feature bead's acceptance criteria, OR
- It has a dedicated bead of its own, OR
- It is listed as deferred in the skill's final output with a one-sentence reason.
3. **Emit** a reconciliation table in the final output (see Step 6, Section 3). Any artifact that is neither accounted for nor explicitly deferred is a planning bug — stop and resolve before creating beads.
This prevents the failure mode where a feature-bead title absorbs several named components from the manifest and the executing agent silently ships the most obvious subset. Absorption into prose is not coverage.
**Acceptance criteria describe what the user sees, not what the test asserts.** For plumbing beads, structural criteria are fine ("endpoint returns 200", "migration runs without error"). For feature beads, criteria must describe the user experience: what data is visible, how it's presented, what interactions work. "Test: component renders with props" is NOT an acceptance criterion — it's a tautology. "Customer activity shown as chronological timeline with event icons, source labels, and color-coded severity levels" IS an acceptance criterion. **Format: one criterion per line in `acceptance_criteria` — newline-separated, no semicolons or paragraph prose. See the `/create-bead` skill for the canonical rule.**
**Source tracing** — every bead's `notes` field must reference both the source plan **file path** and the specific section it originated from. The file path is mandatory: an agent picking up the bead has no memory of the planning conversation and no way to know which file `§Section X` lives in. Format as: `Source: {plan-file-path} §{Section Name}, {detail}` (e.g., `Source: docs/prd-checkout.md §User Stories, item 7`). Citing only `§Section` without the file path is a defect — fix it before locking the bead.
**Self-containment principle — beads carry the plan's intent, frugally.** An agent picking up a bead has zero memory of the planning conversation. The bead's `description` must answer three questions:
1. **What** — what specifically needs to be built
2. **Why** — why this bead exists, what problem it solves, how it fits into the larger design
3. **Context** — what the user/developer will use this for, what it replaces or enables
The `description` is not a build instruction ("Write failing test then implement X"). It is a design brief ("This is the primary surface for support debugging. When an agent asks 'why is this customer stuck, and what have we already tried?', this view should answer it"). The agent that reads the brief understands the purpose and can make good decisions about depth and quality. The agent that reads a build instruction produces the minimum structure that satisfies it.
Self-containment does NOT mean everything inline. Shared WHY lives on the parent epic's brief (Step 3) and durable prose lives in the plan file the `Source:` line points to — the bead itself carries the 1-3 sentence local delta plus the pointers. Self-contained via a two-hop read (`bd show <parent>`, open the cited doc) is still self-contained, and it is paid only when followed instead of in every downstream gate's context.
### Step 4b — The Capability Gate (apply via /create-bead)
The canonical Capability Gate, the Minimum-Output Simulation, the Concrete-verification rule, the rejection criterion for abstract nouns, the worked good/bad AC tightening examples, and the case-file failure patterns all live in the **`/create-bead`** skill. This skill defers to that one source — do not duplicate the rules here.
The decomposition implication for the planner: before emitting bead drafts in Step 6, ensure each feature bead's draft criteria pass the two questions —
- **Capability test:** does each criterion describe what the user can DO, not just what they SEE?
- **Minimum-output simulation:** would the cheapest satisfying implementation embarrass you?
Categories that get omitted most often and almost always belong in feature criteria: hover affordances, scale behavior at 10x/100x realistic data, drill-down on click, empty/loading/error states, keyboard navigation.
The downstream `/create-bead` skill (invoked per bead in Execute Mode) runs `/ac-quality-review` on every draft and enforces the gate with a 2-iteration tightening budget. The planner's contract is to produce drafts that sail through `/ac-quality-review` on the first pass. If beads routinely roundtrip through tightening, the planner is leaning on the downstream gate to do its job — fold the gate's findings back into this skill's rubric.
### Step 5 — Map Dependencies Bead to Bead
Two kinds of ordering matter: **technical dependencies** (B literally cannot compile without A) and **logical sequencing** (B should not be started until A is done, even if B could technically compile). Both must be encoded, and both are encoded **bead-to-bead** — one bead blocks one bead, never one phase epic blocking another.
#### Why bead-to-bead, and not a phase barrier
`bd ready` and the summoner are frontier schedulers: they drain whatever has no open blocker, the moment it has none. The edges you file are therefore the whole answer to "does this plan drain in critical-path time, or in sum-of-phases time?"
Make Phase N+1's epic depend on Phase N's epic and every later-phase bead waits on the slowest earlier-phase bead — including the ones it never reads, never imports, and never touches. That is wave dispatch encoded at planning time, and nothing downstream can undo it: the scheduler can only move the frontier the plan gave it.
#### Infer the edges from the same two signals, inside and across phases
- **Data flow** — if bead B reads, parses, renders, or imports something bead A creates, A blocks B.
- **Architectural necessity** — schema before the service that queries it, service before the endpoint that calls it, endpoint before the UI that renders it.
- **Explicit plan signals** — "requires", "depends on", "after X is done", "prerequisite".
Apply them across phase boundaries exactly as you apply them inside one. A Phase 2 bead whose only blocker is one Phase 1 bead becomes ready the moment that one bead closes, while the rest of Phase 1 is still draining — that is the intended shape, not a mistake to correct.
**Default to parallel.** Add a blocking edge only when B genuinely cannot proceed without A. "B is in a later phase" is not such a reason.
#### The epic barrier — reserved for a synchronization point the plan names
Keep an epic-level barrier (an edge from the later phase's epic to the phase-N epic) for a synchronization point **the plan itself names**: a cutover, a schema flip, a public API freeze, a data migration that invalidates every earlier reader. Those are genuine all-or-nothing boundaries, and the barrier is their honest encoding.
Quote the plan's own words for the barrier in the epic's `notes`. A barrier you cannot quote is phase ordering wearing a costume — delete it and draw the bead-to-bead edges instead.
**Exception:** Infrastructure/plumbing that genuinely blocks everything (e.g., "install dependencies", "add shared types") is Phase 0 and P0 by urgency, done first regardless. Encode it as real edges to the beads that import it, not as a barrier.
#### Phase is a label, not an edge
Phase membership lives in the `phase-{n}` label (Step 5b) and nowhere else: **a bead's phase alone never creates a blocking edge.** Priority stays an urgency dimension (Step 2) — do not re-encode phase order as priority either. The only priority interaction is the Step 2 tiebreak: within equal urgency, earlier phases get the lower number.
#### Non-blocking relationships
- "similar to", "see also", shared domain concepts → mark as `related`
- Tasks in the same feature that can run in parallel → no dependency needed
**Audit trail** (`discovered-from`) — if decomposition reveals work not in the original plan, mark it.
**Validation:**
- Check for cycles — resolve by finding the incorrect edge
- Remove transitive redundancy — if A blocks B blocks C, don't also add A blocks C. This holds across phase boundaries exactly as it holds inside one.
- Every blocking edge names its reason: data flow, architectural necessity, or a plan-named synchronization point. An edge with no reason is the phase barrier growing back one pair at a time.
- Run the sequential-chain test (Step 4) over the finished edge list, not just over the drafts — dependency mapping is where a chain over one file usually appears.
**Architectural layering default** (when no phase ordering exists):
infrastructure → database schema → data models → services/business logic → API endpoints → UI components → integration tests
### Step 5b — Assign Labels
Every bead gets labels for filtering and grouping. Labels are free-form tags carried in each plan node's `labels` array.
**Foundation labels** (use on every project):
| Label | Purpose |
|---|---|
| `phase-{n}` | Which plan phase the bead belongs to (phase-0, phase-1, …). Static and true by construction — the phase dimension priority no longer carries (Step 2). |
| `layer-{name}` | Architectural layer: `schema`, `service`, `route`, `test`, `config`, `ui`, `migration`, etc. |
| `formula:claude` / `formula:codex` | Selects a PROVIDER variant, never a review weight: `formula:claude` moves the `implement` step back onto Claude when the codex adapter is unavailable; `formula:codex` runs every agent step on codex so a drain can proceed with no Claude quota. Both are operator calls — a plan decomposition stamps NEITHER, and no other `formula:*` name resolves. |
Do NOT stamp execution-wave labels (`wave-{n}`). A wave is a live property of the dependency graph — `bd ready` computes it on demand, and a stored label goes stale the moment beads are added, split, or closed out of order. Nothing reads it back; it is a silent declaration. The wave preview in the Step 6 output is a planning-time report, not persisted state.
**Project-specific labels** — infer additional label dimensions from the plan's structure. Common patterns include:
- Package or module names (e.g., `api`, `web`, `shared`, `mobile`)
- Business domains (e.g., `auth`, `payments`, `inventory`)
- Risk or complexity flags (e.g., `risk-high`, `god-object`)
- Cross-cutting concerns (e.g., `security`, `accessibility`, `performance`)
Choose labels that would be useful for filtering `bd list --label` and `bd ready --label` queries. Prefer short, lowercase, hyphenated names. Don't over-label — 2-4 labels per bead is typical.
### Step 6 — Format Output
Produce the output as a **Needs you** block followed by the sections below:
**Needs you** — first, before Section 1. One line each; `none` when empty:
- HALTed beads (Execute Mode), with their `findings[]` / `operator_required[]`
- Deferred manifest rows (Section 3), with the reason
- Beads with a non-empty `operator_required[]`
- Unlinked touches collisions from the Graph report
**Section 1: Dependency Tree** — a visual overview showing the full hierarchy with blocking relationships, execution waves, and the graph report:
```
bd-{id} Epic: {Name} P{n}
├─ bd-{id}.1 Feature: {Name} P{n}
│ ├─ bd-{id}.1.1 Task: {Name} P{n} phase-1 (no blockers)
│ ├─ bd-{id}.1.2 Task: {Name} P{n} phase-1 (no blockers)
│ └─ bd-{id}.1.3 Task: {Name} P{n} phase-1 (blocked by: .1.1, .1.2)
└─ bd-{id}.2 Feature: {Name} P{n}
Execution waves:
Wave 1: .1.1, .1.2 (parallel — no blockers)
Wave 2: .1.3 (needs .1.1 + .1.2)
Graph report:
Longest blocking chain: {n} beads — {id} → {id} → {id}
Widest ready frontier: {n} beads — {id}, {id}, {id}
Unlinked touches collisions: {id} + {id} share {path} (none → "none")
```
**How to read the Graph report — the three numbers that say whether this plan drains:**
- **Longest blocking chain** — the deepest path of blocking edges, as a length and the bead ids in order. This is the plan's floor: no number of workers finishes it sooner than those beads close one after another. A chain as long as the bead count means the plan was filed as a chain, not a graph — re-run the sequential-chain test (Step 4).
- **Widest ready frontier** — walk the blocking DAG in waves: wave 1 is every bead with no open blocker, wave N+1 is every bead those close. The number is the largest wave at any depth, counted and named; the earliest wave wins a tie. This is the most workers the plan can use at once, at its best moment — not the size of wave 1 alone, so a plan whose one plumbing bead unblocks ten reports 10, not 1. A widest wave of 1 or 2 on a 30-bead plan is the phase barrier's signature, even when no epic edge exists.
- **Unlinked touches collisions** — every pair of beads whose `touches` lists share a path and that have no blocking path between them in either direction (reachability through one or more blocking edges). In a chain A → B → C, A and C are already ordered: sharing a `touches` path does not make them a collision or require a redundant A → C edge. The summoner refuses to dispatch an unlinked colliding pair in parallel, so each one is parallelism the wave list claims and the drain will not deliver. Fix it by merging the pair (the horizontal-fragment test, Step 4) or by adding a justified blocking edge when one is genuinely ordered after the other and no blocking path already orders them. Report `none` when there are none — an omitted line reads as "not checked".
After the beads are filed (Execute Mode), `djinn graph report` recomputes the same three numbers from the live graph; Execute Mode's post-filing verification reconciles the two.
**Worked example** — a two-phase plan, filed bead-to-bead:
```
bd-k4f2 Epic: Saved views P1
├─ bd-k4f2.1 Feature: View persistence P1
│ ├─ bd-k4f2.1.1 Task: views table + migration P1 phase-1 (no blockers)
│ ├─ bd-k4f2.1.2 Task: store CRUD over views P1 phase-1 (blocked by: .1.1)
│ └─ bd-k4f2.1.3 Task: GET/PUT /views endpoints P1 phase-1 (blocked by: .1.2)
└─ bd-k4f2.2 Feature: View switching P2
├─ bd-k4f2.2.1 Task: view switcher menu P2 phase-2 (blocked by: .1.3)
└─ bd-k4f2.2.2 Task: command-palette shortcuts P2 phase-2 (no blockers)
Execution waves:
Wave 1: .1.1, .2.2 (parallel — no blockers)
Wave 2: .1.2
Wave 3: .1.3
Wave 4: .2.1
Graph report:
Longest blocking chain: 4 beads — bd-k4f2.1.1 → bd-k4f2.1.2 → bd-k4f2.1.3 → bd-k4f2.2.1
Widest ready frontier: 2 beads — bd-k4f2.1.1, bd-k4f2.2.2
Unlinked touches collisions: bd-k4f2.2.1 + bd-k4f2.2.2 share web/src/lib/Palette.svelte
```
`bd-k4f2.2.2` is a phase-2 bead in Wave 1: the command palette binds keys and reads no saved-view data, so no phase-1 bead blocks it. Under a phase-epic barrier it would have waited for all three phase-1 beads and bought nothing.
The collision is a real finding, not noise: the summoner serializes `.2.1` and `.2.2` at dispatch, so merge them or draw the edge before filing.
**Section 2: Full Bead Details** — one entry per bead:
```markdown
### bd-{id} — {Title}
- **Type:** epic | feature | task | chore
- **Priority:** P0-P4
- **Parent:** bd-{parent-id}
- **Blocks:** bd-{x}, bd-{y}
- **Labels:** {comma-separated labels}
- **Description:** {1-3 sentences explaining what + why}
- **Diagnostic Question:** *(features only)* The specific question this feature helps the user answer, in one sentence. If no single question can be stated, the feature is underspecified — stop and clarify with the plan before locking the bead.
- **Reference Standard:** *(features only, when the plan aspires to a known bar)* The external tool, pattern, or product whose affordances define "done at the intended quality." Name the tool and name the specific affordances being matched, so the executing agent knows what to compare against.
- **Acceptance Criteria:** *(capability-anchored; each criterion passed through the Capability Gate)*
- [ ] {Criterion 1}
- [ ] {Criterion 2}
- **Interaction Inventory:** *(features only — every user interaction the feature must support)*
- Hover {target} → {outcome}
- Click {target} → {outcome}
- Keyboard {key} → {outcome}
- **Scalability Assumption:** *(features only)* A realistic data size, throughput, or cardinality the feature must remain usable under. Forces zoom, pagination, filtering, or windowing into the design instead of leaving them implicit.
- **Design Notes:** {File paths, existing patterns to reuse, architectural context}
- **Touches:** {repo-relative paths and directories this bead will CHANGE — the subset of Design Notes paths it writes to, not the ones it only reads; directories end in a trailing slash}
- **Source:** {plan-file-path} §{Plan Section}, {specific reference}
```
**Section 3: Component Manifest Reconciliation** *(include when the source plan contained a named artifact manifest — see Step 4)* — a table showing every named artifact from the plan and its disposition. Any row marked "DROPPED" without a reason is a planning bug:
```markdown
| Manifest Artifact | Disposition | Reference |
|---|---|---|
| `{ArtifactName}` | covered | bd-{id} — acceptance criterion {n} |
| `{ArtifactName}` | dedicated bead | bd-{id} |
| `{ArtifactName}` | deferred | {one-sentence reason} |
```
### Execute Mode
If the user passes `--execute` or asks you to create the beads directly, gate every bead through `/create-bead`, then file the whole tree — epics, children, and every edge — in ONE `bd create --graph` call. Do NOT file beads one at a time: a bead created before its blocker edge is ready, and a loaded workshop dispatches it in that gap. bd applies a plan in one transaction, so the tree lands fully wired or not at all.
**Preflight — before dispatching anything:**
- Run `bd --version`. Below **1.3.0**, stop before any filing with an error naming the installed version and the 1.3.0 floor: older `bd create --graph` does not carry every bead field.
- Run `bd show <id> --json` for every EXISTING bead the plan points at (a parent outside the plan, a blocker outside the plan). Stop if any is missing: bd files a node whose `parent_id` or `to_id` names no bead, and a dangling blocker edge leaves the bead ready.
**1. Key every bead.** Give each Step 6 bead a plan-local `key`, unique in the plan (`e1`, `e1-f1`, `e1-f1-t2`).
**2. Gate every bead — collect nodes, not ids.** For each bead:
1. Assemble the args-mode payload (see the `/create-bead` skill for the schema): `key`, `title`, `type`, `priority`, `description`, `acceptance`, plus optional `design`, `notes`, `labels`, `touches`. Leave out `parent` and `blocked_by`: the planner wires every relationship in step 3.
**`touches` is optional to `/create-bead` but mandatory here — fill it for every bead this skill emits.** Derive it from the bead's own Design Notes (Step 6): the file paths and directories already named there are the list, minus anything the bead only reads. Directories keep their trailing slash; paths stay repo-relative. The summoner refuses to dispatch two ready beads whose lists overlap, so a bead filed without `touches` is treated as colliding with nothing and can be worked in parallel with a bead editing the same file. A planner that omits it is the only reason that happens — nothing downstream can recover the judgment, because nothing downstream has the plan.
2. Invoke `/create-bead` in args mode WITHOUT `--execute`. It runs the AC gate and returns its gate-approved node — `acceptance_criteria` as the gate approved it — and files nothing.
3. If `/create-bead` HALTs after the third UNDERSPEC, the planner has produced an under-spec'd bead. Fold the returned `findings[]` back into the Capability Gate rubric (Step 4b), re-draft the bead's criteria, and re-invoke. Do NOT bypass the gate by writing a node yourself.
File nothing until every bead has a gate-approved node. One HALT holds the whole plan.
**3. Assemble one plan.** Write it under `d="$(mktemp -d)"` as `$d/plan.json` = `{"commit_message": "...", "nodes": [...], "edges": [...]}`:
- `nodes` — every returned node, verbatim, plus its parent: `parent_key` when the parent is in the plan, `parent_id` when it already exists. Top-level epics carry neither.
- `edges` — every Step 5 blocking edge, from the waiting bead to its blocker: `{"from_key": "<blocked>", "to_key": "<blocker>", "type": "blocks"}`, or `"to_id": "<existing id>"` for a blocker outside the plan. A plan-named epic barrier is the same edge between two epic keys. Non-blocking relationships ride the same list with `"type": "related"` or `"type": "discovered-from"`.
Save each returned node to its own file and merge with `jq` (`jq -s` over the node files) rather than retyping them: retyping is where a gate-approved criterion silently changes.
**4. Dry-run, then file once.**
```bash
bd create --graph "$d/plan.json" --dry-run --json # stop on any error or unknown-field warning
bd create --graph "$d/plan.json" --json # → {"ids": {"<key>": "<new-id>", ...}}
```
bd drops an unknown node key with only a warning (`acceptance` is not a plan key — it is `acceptance_criteria`), so a warning on the dry-run is a stop. On an error nothing was filed: fix the plan and re-run the whole call — never fall back to filing nodes one at a time.
Graph-filed children get flat ids, not the `<parent>.N` ids the Step 6 preview sketches; `parent` still links them. Report the tree with the returned ids.
**Context discipline — keep the planner's own window lean.** Run inline, a 30-bead plan pays up to 90 AC-quality passes in this conversation's context. Instead:
- **Dispatch each `/create-bead` invocation to a subagent** (one per bead, or small batches of related beads), passing the structured payload and pinning the planning model (below). Planning is where the strongest model pays for itself. The subagent returns only its gate-approved node (JSON) or `{HALT, findings[]}` — the planner never sees the gate's intermediate passes, and the subagent never files.
- **Pre-gate plumbing beads as one batch.** Before dispatching, run a single `/ac-quality-review` pass over ALL plumbing drafts together (the gate is already lenient on structural criteria) and fold its findings in. Dispatch that batched pass to a subagent with the same planning-model pin. The in-skill gate then passes on attempt 1, and the per-bead 3-pass budget stays reserved for feature beads, where it earns its cost.
Every subagent is the djinn-planner agent `djinn init` writes: it drafts and gates, and never files a bead or edits a file. When its agent file is missing, run `djinn init --resync` first.
<!-- djinn-dispatch: claude-code -->
**Starting a subagent:** use the Agent tool with `subagent_type: djinn-planner` (`.claude/agents/djinn-planner.md`), and **`model: fable` on every Agent call**.
<!-- djinn-dispatch: end -->
**Post-filing verification — required.** Filed beads are claims until read back. After the `bd create --graph` call:
1. For every id in the returned `ids` map, run `bd show <id> --json` and confirm on `.[0]`:
- `acceptance_criteria` is non-empty and matches the gate-approved node — not the original draft; a gate rewrite is correct, never revert it.
- `metadata.touches` matches the drafted Touches.
- `parent` equals the drafted parent (the id its `parent_key` resolved to, or its `parent_id`); top-level epics have none.
- `dependencies` holds a `dependency_type: "blocks"` entry for every drafted blocker.
Fix a missing or wrong field with `bd update <id>` (`--metadata`, `--parent`). An `acceptance_criteria` repair must pass `/ac-quality-review` before it is written.
2. Run `bd ready --exclude-type=epic`: it lists only the plan's first-wave beads (plus pre-existing backlog). A later-wave bead there is a reversed or missing edge.
3. Run `djinn graph report --json` once over the whole backlog, never `--epic` (it drops edges leaving the epic, so cross-epic chains and touches collisions vanish). Reconcile the plan's beads — longest chain, widest frontier, touches collisions — against the drafted Graph report. A difference caused only by pre-existing backlog beads is scope, not a filing error: leave it. A difference among the plan's own beads is a filing error: fix the edges (`bd dep add` / `bd dep remove`) or the touches, then re-run until it matches.
**Field mapping from Step 6 output to `/create-bead` args payload:**
| Output field | `/create-bead` arg | Content |
|---|---|---|
| Description | `description` | WHAT + WHY + how it fits into the larger design. For features, the Diagnostic Question and Reference Standard are folded in here. Design brief, not build instruction. |
| Acceptance Criteria | `acceptance` | What DONE looks like from the user's perspective. **One criterion per line — newline-separated, no semicolons.** For features, include the Interaction Inventory and Scalability Assumption as individual lines. For plumbing, structural criteria are fine. The returned node carries it as `acceptance_criteria`. |
| Labels | `labels` | Labels from Step 5b (e.g., `phase-0,api,schema`); the node carries them as a `labels` array |
| Design Notes | `design` | File paths, existing patterns, data sources, API endpoints to call, architectural context. The HOW. |
| Source & Context | `notes` | Plan traceability (`Source: {plan-file-path} §{Section}` — file path is mandatory so agents can navigate to the source plan), relationship to sibling beads, constraints, what this enables downstream. |
| Touches | `touches` | The subset of the Design Notes paths this bead will CHANGE (not merely read), as a list of repo-relative strings. Directories carry a trailing slash. `/create-bead` renders it as `"metadata": {"touches": [...]}`; the summoner reads it at dispatch to serialize overlapping beads. |
| Parent | — | Not a `/create-bead` arg here: the planner adds `parent_key` / `parent_id` in step 3. |
| Blocks / blocked by | — | Not a `/create-bead` arg here: the planner adds every edge (`from_key` / `to_key` / `to_id`) in step 3. |
**Critical:** Keep each field separate. The description carries INTENT (what + why). Acceptance carries OUTCOMES (what done looks like). Design carries IMPLEMENTATION CONTEXT (how). Notes carry TRACEABILITY (where from, what's next).
Only file if `bd` is available and a beads project is initialized. If not, output the structured payloads as text the user can execute later via `/create-bead` interactively.
**When delegating to subagents:** Every subagent this skill starts pins the planning model, for bead authoring and the AC-quality gate alike, because an unpinned subagent inherits the chair's model. Pass the Step 6 bead list exactly as drafted; the subagent invokes `/create-bead` once per listed bead, without `--execute`, returns each gate-approved node, and neither merges nor splits them.
### Step 7 — Distill the Shape (after a successful decomposition)
If this decomposition's shape is likely to recur — and it usually is; "plumbing → feature → verification", wired bead-to-bead, is the standard vertical-slice molecule — offer to capture it as a reusable formula:
```bash
bd mol distill <epic-id> <formula-name> --var <concrete-value>=<variable>
```
Distill is the reverse of pour: it extracts a `.formula` file from the epic you just built, replacing concrete values with `{{…}}` variable placeholders. The formula lands in `.beads/formulas/` and shows up in the Step 1b check on every future plan.
**Gate the formula at distill time.** Run `/ac-quality-review` ONCE over the distilled step templates (placeholders intact — the gate judges criterion *shape*, which variables don't change). A formula gated at distill time means beads poured from it need only their substituted variable content sanity-checked, not the full criteria set re-reviewed: the gate runs once per template instead of up to three times per bead, per plan, forever. This is what makes the Step 1b pour path legitimate.
## Important principles
- **Intent is the north star — carried frugally.** The agent that executes a bead must understand WHY the work matters, not just WHAT to build. A bead without intent produces scaffolding. A bead with intent produces a feature. But inline prose is paid by every downstream gate: shared WHY belongs on the epic brief, durable prose belongs in the doc the `Source:` line cites, and the bead carries the local delta. When in doubt, add a pointer to the doc — not another paragraph.
- **Vertical slices over horizontal layers.** Every feature bead must deliver a complete user-visible capability that cuts through all necessary layers. "Create Sparkline component" is horizontal (one layer, no value alone). "Customer activity view with event timeline, interaction trail, and volume/latency trends" is vertical (data + logic + UI + tests = complete feature). Horizontal decomposition is only correct for plumbing (endpoints, migrations, schemas) — and for a **wide refactor**, whose blast radius no slice can contain: sequence that one expand → migrate → contract per "Wide refactors — the exception to vertical slicing" in Step 3.
- **One bead per consumer-facing capability.** Plumbing included: each endpoint, migration, and service method is its own acceptance line, not its own bead.
- **Source tracing is non-negotiable.** Every bead points back to its origin in the plan.
- **Descriptions are design briefs, not build instructions.** "Write failing test then implement X" tells the agent to produce the minimum. "This is the primary surface for support debugging — when an agent asks 'why is this customer stuck?', this view should answer it" tells the agent to produce something with depth and purpose.
- **Acceptance criteria describe user outcomes, not test structure.** For feature beads: what does the user SEE? What data is visible? What interactions work? For plumbing beads: structural criteria are fine ("endpoint returns 200").
- **Apply the depth requirements from /create-bead.** Every feature bead needs a Diagnostic Question, Interaction Inventory, and Scalability Assumption in its description and acceptance, plus a Reference Standard when aspiring to a known bar. Criteria must pass the Capability Gate. See the `/create-bead` skill for canonical definitions; Step 4b above for the procedural application.
- **No silent drops from named manifests.** When a plan enumerates artifacts by name, reconcile each one in the final output. Absorption into prose is not coverage.
- **Parallel by default.** Only add blocking dependencies when the work genuinely cannot proceed without the blocker being done, and draw every one of them bead-to-bead — a bead's phase alone never creates a blocking edge.
- **Fan out across beads, never inside one.** Every scaled practitioner surveyed in `docs/research/2026-09-19-graph-engineering.md` §5 fans out across independent nodes of a dependency graph, and splitting one inherently sequential task into parallel subtasks measures a 39–70% loss. Parallelism is a property of the graph you file, not of the bead a worker is holding.
- **A bead that produces scaffolding has failed.** If the output compiles but shows no meaningful data, the bead was written wrong — it lacked intent, lacked acceptance criteria, or was split too small. The fix is better beads, not more beads.
## Case files — moved
The anti-pattern catalog (CSS-div charts, silent manifest drops, aggregate-where-a-series-was-wanted, picture-of-a-tool, list-where-a-workspace-was-wanted) and the corresponding capability-anchored rewrites live in the **`/create-bead`** skill alongside the worked good/bad examples. Match draft feature criteria against those patterns before invoking `/create-bead` to emit the bead.