-
Run .specify/scripts/bash/check-prerequisites.sh --json --require-tasks from repo root and parse FEATURE_DIR from the JSON output. The --require-tasks flag makes the check require both plan.md and tasks.md to exist before splitting: the spec is decomposed only after the whole-feature plan and task list are in place, so the phase boundaries have been validated against the full implementation design rather than the spec alone. If either artifact is missing, the script reports it (e.g. "Run /speckit-plan first" or "Run /speckit-tasks first") and exits non-zero — stop and surface that message instead of proceeding. All paths must be absolute. For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'''m Groot' (or double-quote if possible: "I'm Groot").
-
Read the parent spec at FEATURE_DIR/spec.md.
-
Parse the ## Phases section from the parent spec:
a. Locate the ## Phases section. If no ## Phases section exists, report this error and STOP:
ERROR: No phase annotations found in spec.md.
Run `/speckit-phase` to generate phase annotations before splitting.
b. Parse each phase subsection (### Phase {N}: {slug}) and extract:
- Phase number (integer)
- Slug (kebab-case string)
- Assigned stories (from the
**Stories**: line)
- Release strategy (from the
**Release Strategy**: line)
- Rationale (from the
**Rationale**: line)
c. Validate phases:
-
Determine the parent directory name:
- Extract the directory name from FEATURE_DIR (e.g., if FEATURE_DIR is
specs/c31c-feat-billing-overhaul, the parent directory name is c31c-feat-billing-overhaul)
-
Check for existing manifest and child directories:
- Check if the parent spec already has a
## Manifest section (indicates a previous split)
- If a manifest exists, parse the existing status values for each phase entry
- Check which child directories already exist under
specs/
Detect added and removed phases (when a manifest exists from a previous split):
a. Added phases: Phases present in the current parent ## Phases annotations (from step 3) but absent from the existing manifest. These are new phases the developer added to the parent spec after the initial split. They will receive new child spec directories in step 6 and appear in the manifest with status "Draft" in step 7.
b. Removed phases: Phases present in the existing manifest but absent from the current parent ## Phases annotations. These are phases the developer removed from the parent spec. Their child directories are preserved on disk (never deleted). They will be marked as "Cancelled" in the manifest in step 7.
c. Continuing phases: Phases present in both the current annotations and the existing manifest. These proceed through the normal create-or-update logic in step 6.
-
For each phase, create or update the child spec directory (skip removed/cancelled phases):
Important: Only process phases that are present in the current parent ## Phases annotations (continuing phases and added phases). Do NOT create, update, or reconcile child specs for removed phases -- their directories remain on disk untouched, and they are handled solely through the manifest in step 7.
a. Compute the child directory name: {parent-directory-name}--p{N}-{phase-slug}
- If the total directory name exceeds 200 characters, truncate the slug portion to fit within 200 characters while preserving
{parent-directory-name}--p{N}-, and warn the developer about the truncation
b. Create the directory under specs/ if it does not exist: specs/{child-directory-name}/
c. Generate or update the child spec.md:
- If the child spec does not exist (first run), generate it fresh
- If the child spec already exists (re-run), run the reconciliation logic described in step 6e below
d. Child spec content (for new child specs): Generate a standard SpecKit spec structure populated with the content relevant to this phase. The child spec must be independently processable through the full SpecKit pipeline.
Structure the child spec as follows:
# Feature Specification: {feature name} - Phase {N}: {slug}
**Feature Branch**: `{parent-branch}--p{N}-{slug}`
**Created**: {current date}
**Status**: Draft
**Parent Spec**: `{parent-directory-name}/spec.md`
**Phase**: {N} of {total phases}
## User Scenarios & Testing *(mandatory)*
{Include only the user stories assigned to this phase from the Phases section.
Copy the full user story content (title, description, priority, acceptance scenarios)
from the parent spec for each assigned story.}
## Requirements *(mandatory)*
### Functional Requirements
{Include functional requirements relevant to this phase's stories.
Relevance is determined by story assignment:
- Include requirements that directly reference or support the user stories assigned to this phase
- Requirements not tied to any specific story are included in Phase 1's child spec only
- Each requirement appears in exactly one child spec}
### Key Entities *(include if feature involves data)*
{Include key entities relevant to this phase, if any}
## Success Criteria *(mandatory)*
### Measurable Outcomes
{Include success criteria that validate the requirements included in this phase.
Success criteria not tied to any specific story are included in Phase 1's child spec only.
Each criterion appears in exactly one child spec.}
## Assumptions
{Include assumptions relevant to this phase from the parent spec.
Add an assumption noting this is Phase {N} of a {total}-phase feature,
with a reference to the parent spec for the overall feature context.}
Independence requirement: Each child spec must be self-contained. Do not include references to sibling specs that would block pipeline execution. Do not use phrases like "after Phase 1 is complete" in requirements -- instead, state the prerequisite condition directly (e.g., "Given the schema has been expanded with X columns" rather than "After Phase 1 deploys the schema changes").
e. Reconciliation logic (for existing child specs on re-run):
When a child spec already exists on disk, reconcile it with the current state of the parent spec and earlier child specs. Process phases in order (P1 first, then P2, etc.) so that earlier-phase changes are available when reconciling later phases.
Step 1 -- Generate the baseline: For each child spec, regenerate what the child spec would contain if generated fresh from the current parent spec's phase annotations using the same generation logic as step 6d. This regenerated content is the "baseline" -- it represents the expected content without any manual edits.
Step 2 -- Detect manual edits: Compare the baseline (from Step 1) section-by-section against the actual child spec on disk. Use markdown heading boundaries (## and ### level headings) to identify sections. A section where the disk content differs from the baseline has been manually edited by the developer.
Step 3 -- Generate updated content for later phases: For child specs at phase 2 and above, regenerate the child spec content using the actual content from earlier child specs on disk (not the baseline). This "updated content" reflects what the child spec should contain given the current state of earlier phases. Compare this updated content against the baseline from Step 1 to identify which sections are affected by earlier-phase changes.
Step 4 -- Apply reconciliation per section:
Step 5 -- Report conflicts: After reconciliation, report any conflicts to the developer. For each conflict, include:
- The child spec file path
- The section heading where the conflict was inserted
- A brief description of the conflict (what changed in the earlier phase vs what the developer edited)
Phase 1 child specs: Phase 1 has no earlier phases, so Steps 3-4 simplify to: detect manual edits (Step 2), and preserve the child spec as-is. Phase 1 child specs are never updated by reconciliation -- they serve as input to later phases.
-
Create or update the ## Manifest section in the parent spec:
a. If no manifest exists, append a ## Manifest section at the end of the parent spec.
b. Before the manifest table, include this notice:
> **Note**: This spec has been split into phases. Pipeline steps (`/speckit-plan`, `/speckit-tasks`, etc.) should be run on individual child specs listed below, not on this parent spec.
c. Generate the manifest table with columns: Phase, Directory, Description, Status, Release Strategy
## Manifest
> **Note**: This spec has been split into phases. Pipeline steps (`/speckit-plan`, `/speckit-tasks`, etc.) should be run on individual child specs listed below, not on this parent spec.
| Phase | Directory | Description | Status | Release Strategy |
|-------|-----------|-------------|--------|------------------|
| P1: {slug} | {parent}--p1-{slug} | {brief description from rationale} | Draft | {strategy} |
| P2: {slug} | {parent}--p2-{slug} | {brief description from rationale} | Draft | {strategy} |
d. Status preservation and phase management: If a manifest already exists from a previous run:
- Continuing phases: Preserve manually-set status values for phases present in both the old manifest and the current annotations.
- Added phases: Phases present in the current annotations but absent from the old manifest get status "Draft".
- Removed phases: Phases present in the old manifest but absent from the current annotations are marked "Cancelled" in the updated manifest. Their child directories remain on disk untouched (never deleted). If a removed phase was already "Cancelled" in the old manifest, its status remains "Cancelled". If a removed phase had status "Complete", report an error per the status transition validation in step 7e (Complete -> Cancelled is invalid).
e. Manifest ordering: The manifest table lists all phases in phase-number order. Continuing and added phases appear at their position from the current annotations. Removed phases retain their original phase number from the old manifest and appear in order alongside the current phases. This provides a complete view of all phases -- active and cancelled -- in a single table.
f. Status transition validation: When a manifest already exists, validate that any status values in the existing manifest are consistent with the forward-only state machine before writing the updated manifest. For each phase present in both the old and new manifest:
Valid transitions (allowed):
- Draft -> In Progress
- In Progress -> Complete
- Draft -> Cancelled
- In Progress -> Cancelled
- Any status -> same status (no change)
Invalid transitions (rejected):
- In Progress -> Draft
- Complete -> Draft
- Complete -> In Progress
- Complete -> Cancelled
- Cancelled -> Draft
- Cancelled -> In Progress
- Cancelled -> Complete
Note: Complete is NOT an active state. Both Complete -> Cancelled and Cancelled -> Complete are invalid.
If the splitting skill would set a status that requires an invalid transition (e.g., a phase marked "Complete" by the developer would be overwritten with "Draft" by a fresh re-run), report an error and STOP:
ERROR: Invalid status transition for Phase {N} ({slug}): {old status} -> {new status}.
Status transitions must be forward-only: Draft -> In Progress -> Complete. Active states (Draft, In Progress) may transition to Cancelled. Backward transitions and transitions from terminal states (Complete, Cancelled) are not permitted.
Implementation detail: The splitting skill itself only ever sets status to "Draft" (for new phases) or preserves existing values (per step 7d). Invalid transitions arise when a developer manually sets a status value in the manifest and then the splitting skill re-runs. The validation catches cases where the developer set an invalid transition (e.g., moving a Complete phase back to Draft) before the manifest is written, providing an early error rather than silently accepting an invalid state.
g. Idempotency: Re-running on an unchanged spec with unchanged child specs must produce an identical manifest table.
-
Report results:
- List each child spec directory created or updated
- Show the manifest table
- If any directory names were truncated, repeat the truncation warnings
- If this was a re-run, note which phases were unchanged vs updated
- If phases were added, list the new child spec directories created
- If phases were removed, list the phases marked as "Cancelled" and confirm their directories were preserved on disk