phase-split skill
Decide whether a PRD, or any phase of one, is too large to implement in a single AI session and, if so, split it into independently verifiable phases. Decides the cut itself and proceeds without stopping for confirmation. Produces one lightweight phase document per phase at every depth (phase 2, phase 2a, phase 2a1), all flat in the PRD directory, referencing the PRD and the single technical design without duplicating them. The planning step between requirements-ready and implementation — it does not write code.
- GitHub stars
- 7
- Files
- 1
- Last commit
- Nov 14, 2026
- License
- MIT
- Allowed tools
- —
What does the phase-split skill do?
phase-split is an agent skill. Decide whether a PRD, or any phase of one, is too large to implement in a single AI session and, if so, split it into independently verifiable phases. Decides the cut itself and proceeds without stopping for confirmation. Produces one lightweight phase document per phase at every depth (phase 2, phase 2a, phase 2a1), all flat in the PRD directory, referencing the PRD and the single technical design without duplicating them. The planning step between requirements-ready and implementation — it does not write code.
How to install the phase-split skill
Each command copies the skill folder into the client's skills directory. Restart the client or start a new session to load it.Install the phase-split skill in Plugin
/plugin marketplace add EnsoDynamics/enso-method /plugin install enso-method@enso-method
Install the phase-split skill in Claude Code
~/.claude/skills/phase-split/SKILL.md
$ npx degit EnsoDynamics/enso-method/skills/phase-split ~/.claude/skills/phase-splitInstall the phase-split skill in Claude Code (project)
.claude/skills/phase-split/SKILL.md
$ npx degit EnsoDynamics/enso-method/skills/phase-split .claude/skills/phase-splitInstall the phase-split skill in Codex
~/.agents/skills/phase-split/SKILL.md
$ npx degit EnsoDynamics/enso-method/skills/phase-split ~/.agents/skills/phase-splitInstall the phase-split skill in Gemini CLI
~/.gemini/skills/phase-split/SKILL.md
$ npx degit EnsoDynamics/enso-method/skills/phase-split ~/.gemini/skills/phase-splitInstall the phase-split skill in Claude.ai
npx degit EnsoDynamics/enso-method/skills/phase-split phase-split && zip -r phase-split.zip phase-split # claude.ai → Customize → Skills → + → Create skill → Upload a skill → phase-split.zip
SKILL.md
View on GitHubPhase Split
Take an implementation-ready PRD — or a single phase of one, at any depth — that is too large to build in one AI session and break it into ordered, independently verifiable phases — each a defined subset of the PRD's acceptance criteria — then write a short phase document for each and hand off.
This skill owns three things:
- The sizing test — deciding whether the work fits in a single AI session.
- The phase-split procedure — finding seams, deciding the split, and writing the phase documents.
- The phase naming and file layout — how phases at every depth are identified and where their documents live, so that "implement phase 2a1" always points at exactly one file.
It is the planning step that sits between "the requirements are ready" and "go build it." It does not implement. It also does not stop to ask whether to split, or how: it decides the cut, declares it, writes the documents, and hands off. The user can redirect after the fact — the documents are cheap to rewrite, and a split is one commit to revert — but a session that stops to ask "shall I split as recommended?" loses the wall-clock time the user isn't there to give back, for a question whose answer is almost always yes.
When to Use
Use this skill when:
- Requirements are refined and you want to decide whether the PRD needs phases, and plan them before building anything.
implement-from-requirementssized the work, found it too large, and sent you here.- You want to re-evaluate or revise an existing phase split.
- A phase at any depth turned out bigger than the split above it assumed — discovered at sizing time or mid-implementation — and its remaining work needs to be cut into child phases.
Do NOT use this skill when:
- The PRD or technical design haven't been written or refined yet — do that first (
prd-writing-standards,technical-design-writing-standards, thenautonomous-design-refinement, orimplementation-readiness-checkfor an explicit human checkpoint). - The work is a single bounded fix with no requirements directory behind it —
implement-from-discoverybuilds that without phases. - The source is bigger than one PRD — a brief or idea that would run to dozens of phases before anything reaches production. Cut it into planned PRDs with
initiative-breakdownfirst; this skill then splits each PRD once it is written.
What This Skill Produces
The output is a set of phase documents colocated with the PRD, one file per phase at every depth, all in the same flat directory. A fresh plan is just phase-1 to phase-N; this example shows one after two later re-splits:
docs/prds/{prd-name}/ ← or docs/changes/{prd-name}/ — a bounded delivery, identical layout
{prd-name}-prd.md ← unchanged: the single source of truth
technical-design.md ← unchanged: ONE design covering all phases
phase-1-{short-name}.md
phase-2-{short-name}.md ← was split: now a short split record pointing at 2a-2c
phase-2a-{short-name}.md
phase-2b-{short-name}.md ← was split again: a split record pointing at 2b1-2b2
phase-2b1-{short-name}.md
phase-2b2-{short-name}.md
phase-2c-{short-name}.md
phase-3-{short-name}.md
Hard rules about the output:
- The PRD is not split. It stays whole. Phase docs reference its acceptance criteria by label; they never restate them.
- The technical design is not split. There is exactly one technical design document per PRD, covering the whole system across all phases. Each phase doc points into the relevant sections of that single design — it never gets its own technical design. The shared data model and interfaces are cross-phase contracts; duplicating them per phase guarantees drift. (See
technical-design-writing-standards.) - Every phase is one session. A phase is planned and sized as the work one implement chat builds — there is no separate "session" count. When a phase is split it stops being a phase: its file becomes a split record (a grouping that is never implemented), and each child is a phase. A plan's count is its phase documents that have no
## Split intotable; report it as that one number, never "N phases over M sessions." - One file per phase, at every depth. A phase that gets split produces one new file per child. A child is never a heading inside its parent's document, and a "plan" document never holds several phases as sections. When someone says "implement phase 2b1," that is one file, and
implement-from-requirementsis pointed at it and nothing else. (The measured failure this rule exists to stop: a long-running PRD grew per-track "plan" documents holding a dozen sub-phases as headings, each session had to be told which heading to read, and the headings were named inconsistently across tracks — see "Phase Identifiers and File Layout" below.) - Phase identifiers are positional, and only positional.
2,2a,2a1. Never a mnemonic, an owner initial, or a subject code.
A phase doc is born as a thin scope-setting overlay — not a mini-PRD and not a mini technical design. Over the project's life it legitimately grows into more: per implementation-lifecycle, a future phase doc is the preferred landing place for follow-up work discovered in other phases that survives its Materiality Gate, so "Carried forward from Phase N" / "Inherited from Phase N" sections accumulate in it as the project progresses. That growth is routed work, and it's the system working as designed. What a phase doc never accumulates is duplicated content from the PRD or technical design — or the scope of another phase.
Phase Identifiers and File Layout
This section is the naming standard. Every other section of this skill, and every skill that points at a phase, uses it.
The identifier
A phase id is its position in the tree, written by alternating digits and letters, one run per depth:
| Depth | Form | Example | Read as |
|---|---|---|---|
| 1 | digits | 2 |
the PRD's second phase |
| 2 | digits + letter | 2a |
the first child of phase 2 |
| 3 | digits + letter + digits | 2a1 |
the first child of phase 2a |
| 4 | + letter | 2a1a |
the first child of phase 2a1 |
The alternation is what makes an id parse without separators: each run is one depth, and the id of any ancestor is a prefix of the id (2 ⊂ 2a ⊂ 2a1). A run may be more than one character: 2a10 is the tenth child of 2a, and it cannot be misread as 2a1 + 0 because depth 4 is a letter run. Depth 4 is rare and depth 5 should not happen — a plan that deep is a sign the top-level phase was a whole program. Lifting its children up a level is the fix, and because that renumbers a referenced plan it is the user's deliberate reorganisation, never a session's. The id is short by construction — 2a1 is three characters — because it is the token that gets typed into prompts, chat names, commit messages, and grep, dozens of times.
In prose: "Phase 2a1". In a chat name (continuation-prompt): ph2a1. In a prompt's lineage block: Phase 2a1 — <full title>, em dash regardless of the H1's colon. In a commit message: (Phase 2a1 of {PRD name}), never a bare "Phase 2a1" or a bare "2a1" — the ordinal always travels with the name of the thing it is an ordinal of.
What never goes in the id:
- Not the owner. Two people each running a lane of the same PRD is a fact about who is doing the work, not about what the work is. It goes in an
Ownercolumn of the plan table, or of a split record's## Split intotable. An id that encodes the owner (S5,T-API) goes wrong the day a lane changes hands, and it loses the ordering an id exists to carry. - Not the subject. A PRD built one table at a time is the common case for this rule, and the temptation is to name the phases after the tables (
ORD,CUST). The table name goes in the short-name part of the filename and in the title, where it is readable; the id stays positional (3,4, or2a,2bafter a re-split), where it is short and sortable.phase-4-customers-table.mdcarries both. - Not a track or lane code, a date, or a status.
The filename
phase-{id}-{short-name}.md, all in the PRD directory, no subdirectories. The short-name is two to four kebab-case words naming what the phase delivers (event-pipeline, customers-table-build, review-page); it is for readers, and it may change without the id changing. Do not repeat the PRD name in the filename — the directory already says it.
Flat in one directory is deliberate: a directory listing groups a parent with its children (phase-2, phase-2a, phase-2b, phase-2b1, phase-2b2, phase-2c, phase-3), every pointer is one path with no directory to spell, and a phase that gets split later does not move. Execution order is the plan table's job, not the listing's — past nine siblings ls puts phase-10 before phase-2, and that is fine. Keep it flat even when a phase has many children; that is what the id is for.
What happens to a phase's document when the phase is split
The parent's file stays, and it becomes a split record: its summary, its acceptance-criteria labels, its out-of-scope list, its dependencies, and a ## Split into table listing the children in execution order with one plain-English sentence each and what each depends on. Everything else the parent doc carried — "Carried forward" items, phase-specific notes, work in progress — is moved into the specific child that will build it, and does not stay on the parent. Its title line says it was split, so anyone who opens it sees at once that it is not the thing to implement.
Rules the split record enforces:
- Every acceptance-criteria label on the parent appears in exactly one child, by the same rule and with the same two exceptions as a fresh plan (Step 3, "Every criterion lands in exactly one phase").
- The children partition the parent's scope and add none. Discoveries never become children (see the Materiality Gate in
implementation-lifecycle). - Only leaves are implemented.
implement-from-requirementsis always pointed at a phase that has no## Split intotable. Pointed at a split parent, it takes the first child not yet closed and says so. - Closure is one line on the leaf. When a leaf lands, the implement session's wrap-up writes
**Closed:** YYYY-MM-DDunder the leaf's title, in the feature commit. A leaf is closed only when its acceptance criteria are verified. A leaf whose criteria depend on an outstanding human action is "Awaiting a Human Action" (implementation-lifecycle), not closed; a human action no criterion depends on stays recorded and does not hold the leaf open. The line is the one completion marker a phase doc carries, and it is never written at creation; other work state (blocked work, owed items, pending human actions) goes in sections, perimplementation-lifecycle. A split record's## Split intotable may gain aStatuscolumn after creation for the same purpose. "First child not yet closed" means the first child without that line; when every child carries it the parent is complete — say so, andcontinuation-prompt's end-of-track rule decides whether a prompt follows.
The cross-phase plan table
If the PRD directory has a project-plan.md or any table that lists the phases, that table lists the top-level ids (1, 2, 3, …) with a "What it does" column of one plain-English sentence each and a "Depends on" column naming the phases each row directly needs, with what it needs from each ("None" when it needs none). A split record's ## Split into table carries its children's dependencies the same way, so the tree reads from these tables alone. On a fresh plan those are simply its phases; after a re-split, as in the example below, a row can be a split record, and its own ## Split into table is the plan for its children. Do not flatten a deep tree into the top-level table; walking parent → child is how the tree is read. A reader who wants "the next runnable leaf" starts at the top table and follows the first unfinished row down.
| Phase | What it does | Depends on |
|---|---|---|
| [1 event pipeline](./phase-1-event-pipeline.md) | Ingest domain events and store them as notification records — nothing reaches users yet. | None |
| [2 delivery channels](./phase-2-delivery-channels.md) | Send stored notifications out — split into 2a email, 2b in-app. | 1 (the notification records) |
Process
Pending feedback changes come first. If the PRD directory holds a {name}-pending-feedback-changes.md, a stakeholder round has changed what this PRD must say and its documents may not carry it yet. Apply it first with assumptions-document-feedback, which resumes from that file (its Step 4a, "Resuming"), and commit that amendment on its own before planning; then plan against the amended documents.
Step 1: Confirm the Work Is Too Large
Before splitting anything, confirm the work actually needs splitting. The unit is a single AI session, not human calendar time.
What "one session" means:
The work is happening right now, in this present AI session — one chat, which may run for hours. "Single session" means this immediate run, not some abstract future unit of scheduled work.
So the only sizing question worth asking is: Can I, this AI, complete this whole thing end-to-end in this run without losing coherent context? The constraint is your ability to hold the full design mentally as you build, test, and verify it — right here, right now.
Human-time framings ("a day's work," "a sprint," "a couple of days") measure something different — humans scheduling calendar work over future time. They aren't relevant here, because the work isn't being scheduled, it's being done. Skip that framing entirely. And use the word "phase," not "story" or "ticket" — phases are AI-session-sized chunks of one PRD, not human work units.
How to size honestly:
Walk through the implementation mentally. How many distinct capabilities does it hold? How many integration points? How many criteria and tests? How much investigation may be needed for edge cases discovered mid-implementation? The point is not a precise count — it's a gut check on whether the whole thing fits in one coherent run. Then check that gut read against the Session Capacity Calibration section below — it holds the current concrete anchors for what one session reliably carries, and the bias to correct for: plans have been cut too fine far more often than phases have overrun.
The decision:
- Fits in one session → report that no phases are needed. When invoked directly, stop with a
continuation-promptforimplement-from-requirementson the unsplit PRD; do not start building. When called from an implement session, return that decision to the caller. - Too large → continue to Step 2.
If you're genuinely unsure, keep it whole. Every phase carries a fixed cost (see Session Capacity Calibration), and work that does turn out too large is split mid-implementation in the same chat, keeping what is already built.
Files in this skill
1phase-split skill questions
How do I install the phase-split skill in Claude Code?
Run npx degit EnsoDynamics/enso-method/skills/phase-split ~/.claude/skills/phase-split. Claude Code loads skills from ~/.claude/skills (all projects) or .claude/skills (one project) and uses a skill when its description matches the task.
Which clients can use the phase-split skill?
Any client that reads the Agent Skills format: Claude Code, Codex, Gemini CLI and claude.ai (upload as a ZIP). Scripts in the skill run only where the client allows code execution.