| name | prd-to-beads |
| model | opus |
| description | Convert implementation plans into actionable beads with proper structure, acceptance criteria, dependencies, and test requirements. Use after completing an implementation plan and before starting development. |
| triggers | ["create beads from plan","plan to beads","convert plan to beads","make beads"] |
| argument-hint | <plan-file-or-dir> [--epic-prefix E] [--dry-run] |
Plan-to-Beads Skill
Convert implementation plans into self-contained, implementation-ready beads.
When to Use
- After completing an implementation plan (feature doc, PDR, design doc)
- When a reviewed plan needs to become actionable work items
- To break a large feature into parallelizable units
Arguments
- First argument: path to plan file or directory of plan files
--epic-prefix E: override epic label prefix (default: auto from plan)
--dry-run: preview beads without creating them
Workflow
Step 1: Read & Analyze Plan
Read the plan file(s) and extract:
- Epics/phases — high-level groupings
- Changes per file — which files are modified, what changes
- Cross-cutting concerns — l10n, a11y, error handling, perf, security
- Test requirements — unit, integration, UI tests
- Dependencies — ordering constraints between changes
fd '\.md$' <plan-dir> --exec cat {}
Step 2: Identify Bead Boundaries
Split work into beads following these sizing rules:
| Rule | Rationale |
|---|
| 1-3 files per bead | Keeps diffs reviewable, avoids merge conflicts |
| Single responsibility | Each bead does ONE thing completely |
| Test bead per feature bead | Tests are separate beads unless trivial |
| Cross-cutting embedded | Don't make separate "add l10n" beads; embed in each bead |
Splitting heuristics:
- VM with >3 new properties → split into core + extended
- New model + VM + view → 3 beads (model first, VM depends on model, view depends on VM)
- Migration/schema change → always its own bead (P0)
- Bug fix discovered during planning → separate P0 bead
Step 3: Write Bead Descriptions
Each bead description MUST include these sections:
## Contract Reference
<!-- Required for beads with area:vm or area:xaml labels. Omit section only for
infrastructure/tooling beads that touch no VM logic or XAML bindings. -->
<relative/path/from/repo/root/to/contract-file.yaml> — <state, element, or
action being implemented, e.g. "state: OverrideMismatch, transition: KeepOverride">
## Context
Why this change exists. Link to plan section.
## Acceptance Criteria
Given/When/Then format ONLY. No prose criteria.
- **Given** <precondition>
**When** <action>
**Then** <observable outcome>
## Files
- `path/to/File.cs` — what changes and why
- `path/to/Other.cs` — what changes and why
## Cross-Cutting
- [ ] Localization: <specific resx keys needed, or "N/A">
- [ ] Error handling: <specific error states, or "N/A">
- [ ] Accessibility: <specific a11y reqs, or "N/A">
- [ ] Performance: <specific constraints, or "N/A">
## Test Requirements
- Unit: <what to test, expected count>
- Integration: <what to test, or "N/A">
- UI: <what to test, or "N/A">
## Dependencies
- Depends on: <bead IDs or "none">
- Blocks: <bead IDs or "none">
## Notes
Implementation hints, gotchas, links to relevant code.
Step 4: Self-Containment Checklist
Before creating each bead, verify:
Contract Reference Validation (non-blocking warning)
For each bead with label area:vm or area:xaml:
-
Check that ## Contract Reference section is present and non-empty.
-
If the referenced path looks like a file path (contains /), check whether it exists under foundation/product/features/ (or anywhere in the repo):
fd --type f "<contract-filename>" foundation/product/features/
-
Emit a warning if missing — do not block bead creation:
⚠ WARNING: bead <id> has area:vm/area:xaml but no contract_ref. Agents
implementing this bead will infer behavior from prose and may get it wrong.
Add a ## Contract Reference pointing to the relevant state-machine state,
UI-contract element, or status-action entry in foundation/product/features/.
If referenced file not found:
⚠ WARNING: contract_ref path <path> not found in repo. Contract may be
in-progress; proceeding. Verify path once contract is authored.
Step 5: Create Beads
Create beads using br CLI:
br epic create "Epic Name" --prefix E1
br create "Bead title" \
-t task \
-p <0-4> \
-d "$(cat <<'EOF'
<full description from Step 3>
EOF
)" \
--parent <epic-id> \
-l "track-a,phase-1"
br dep add <child-id> <parent-id>
Step 6: Verify Dependency Graph
br dep cycles
br graph
br ready
br lint
Step 7: Priority Labeling
Apply two-track priority labels:
| Track | Priority | What |
|---|
| A | P0-P1 | Data integrity, safety, correctness — ships first |
| B | P2 | Architecture, UX, features — ships second |
| C | P3-P4 | Polish, terminology, nice-to-have — ships last |
br update <id> -l "track-a" -p 0
br update <id> -l "track-b" -p 2
Given/When/Then Conversion Patterns
Transform prose acceptance criteria into testable GWT:
| Prose AC | GWT AC |
|---|
| "User can see device status" | Given a station with 2 plates, When settings opens, Then each plate shows status icon matching DeviceStatus enum |
| "Error shown for invalid config" | Given plate count > station.MaxPlates, When user clicks Save, Then validation error "Maximum {max} plates" appears AND save is blocked |
| "Supports composite plates" | Given a CompositeDevice with 4 quadrants, When layout detection runs, Then all 4 quadrants resolve to the same physical position |
Rules:
- Given = setup/precondition (specific values, not "some data")
- When = single action (not "user does various things")
- Then = observable assertion (UI text, return value, state change)
- Use AND for multiple assertions in one scenario
- Separate NEGATIVE cases into their own GWT
Cross-Cutting Embedding Pattern
Do NOT create standalone beads like "Add localization for feature X". Instead, embed cross-cutting requirements into each bead:
## Cross-Cutting
- Localization: Add keys `Settings_Plate_Status_Online`, `Settings_Plate_Status_Offline`
to `Strings.resx`. Use `Loc["Settings_Plate_Status_Online"]` in VM.
- Error handling: Wrap `DetectLayout()` in try/catch; show toast on
`DeviceException`; log with `Log.Hardware.Error`.
- Performance: Layout detection must complete in <2s for 4 plates.
Output
After creating all beads, report:
## Beads Created: <count>
### By Epic
| Epic | Beads | Track |
|------|-------|-------|
| E1: ... | bd-xxx, bd-yyy | A |
| E2: ... | bd-zzz | B |
### Dependency Summary
- Root beads (no deps): <list>
- Leaf beads (nothing depends on them): <list>
- Critical path: <longest chain>
- Parallel tracks: <independent groups>
### Quality Check
- [x] br lint: 0 issues
- [x] br dep cycles: 0 cycles
- [x] All ACs in Given/When/Then
- [x] All cross-cutting embedded
- [x] Self-containment checklist passed for all beads
- [x] Contract references present for all area:vm / area:xaml beads (or warnings noted)
Contract Reference Field — Quick Reference
| Bead type | ## Contract Reference required? |
|---|
| area:vm | Yes — state-machine state, property, or command from contract YAML |
| area:xaml | Yes — UI-contract element or binding from contract YAML |
| area:model | Recommended — relevant entity or schema section |
| area:test | Recommended — test scenario from contract |
| infra/tooling | No |
Format:
foundation/product/features/<feature>/<file>.yaml — <specific element>
Examples:
foundation/product/features/bbox/config-source.yaml — state: OverrideMismatch, transition: KeepOverride
foundation/product/features/bbox/ui-contract.yaml — element: DismissButton, visible-when: OverrideMismatch
foundation/product/features/multistation/status-actions.yaml — action: SetActiveStation
Contract files live under foundation/product/features/. If the contract has not been
authored yet, provide the expected path and note "(in-progress)" — the skill will warn
but still create the bead.