plan
Break an agreed spec into vertical slices with blocking edges, stacked branch names, and parallel waves.
What it does
/factory:plan turns spec.md into slices an implementer can take one at
a time, in parallel worktrees, each landing as one PR in a stack. It
fires when the user runs the skill, asks to plan a spec, asks to create
tickets or issues from a spec, or asks to split work into slices.
Publishing to a remote tracker happens only after the user approves the breakdown.
Reads
factory.tomlforspec_dir,base, and[tracker]. Without a tracker kind it defaults tolocaland says so.spec.md, which must haveStatus: agreed. A draft spec is refused with a pointer at/factory:spec.- The code around the seams the spec names, looking for prefactoring that makes the slices smaller.
Writes
<spec_dir>/<slug>/plan.md. Each slice is a tracer bullet: one narrow
path through every layer, demoable on its own, sized for one fresh
context window. A slice names its requirement ids, blockers, Branch,
Parent, what it delivers, observable acceptance checks, and its tracker
item. A waves block groups slices that can run in parallel.
Then, per tracker.kind: one issue file per slice for local, or a
tracking item and one item per slice on GitHub, GitLab, or Jira, blockers
before dependents, with the Tracker: lines filled in afterwards.
Rules
Branchis<slug>/NN-<task>. The root slice’s parent isbase. Each later slice’s parent is the branch of the slice it is blocked by.- Slices in one wave have disjoint write sets. Two slices that touch the same files go in different waves with one blocking the other.
- Prefactoring is scheduled as slice
01. - No file paths or code in slices; they go stale. A prototype snippet that encodes a decision is the one exception.
- Acceptance checks are observable: a test name, a command and its output, a screen state.
plan-check.pyin the skill’sscripts/reads the plan and fails on a slice blocked by two independent chains, aParentthat is notbaseor another slice’s branch, a parent slice missing fromBlocked by, or waves that disagree with the blockers. The breakdown is shown only when it exits 0, and verify runs it again whenever a plan changes.- After publishing, slice status lives in the tracker;
plan.mdis never edited to track progress, so the copy in every slice commit stays identical.
Steps
- Read the spec and the code around its seams.
- Draft the slices and compute waves. Write the draft and run
plan-check.pyuntil it exits 0. - Present the breakdown as a numbered list and ask three questions: granularity, blocking edges, merge or split. Iterate until the user approves. Do not publish before approval.
- Update
plan.mdwith what the user changed;plan-check.pyagain. - Publish.
- Reply with the plan path, the wave table, and the first frontier: the
slices with no blockers, ready for
/factory:implement.
Done when
plan.md exists with every slice traced to requirement ids, a valid
waves block, and a Tracker: line per slice.
Upstream
Wraps mattpocock-skills/to-tickets for tracer-bullet slices, blocking
edges, expand-contract for wide refactors, and the frontier;
addyosmani-agent-skills/planning for the dependency graph and
acceptance criteria per task; and the cursor-plugins/pstack
multi-phase plan playbook for one PR per section with its own evidence.