| name | break-down-func-spec |
| description | Break down a functional spec that is too complex into smaller specs that each imply ≤ 200 lines of code. Use when analyze-if-func-spec-too-complex flags a spec as TOO COMPLEX, or when a spec is suspected of being too large. |
Break Down Functional Spec
Always use the skill load-plain-reference to retrieve the ***plain syntax rules — but only if you haven't done so yet.
When to Use
analyze-if-func-spec-too-complex flagged a spec as TOO COMPLEX.
- A spec is suspected of exceeding the 200 LOC limit and needs to be split preemptively.
- A spec bundles multiple behaviors, constructs, or concerns that should be separated.
Input
The functional spec to break down, plus the full .plain file it belongs to.
Workflow
- Read the full
.plain file — definitions, implementation reqs, and all functional specs (including requires modules) to understand context.
- Identify the spec to break down — the one flagged as too complex or pointed to by the user.
- Analyze why it is too complex — use the indicators from
analyze-if-func-spec-too-complex:
- Multiple distinct behaviors bundled together?
- Too many new constructs introduced at once?
- Complex branching logic or conditional paths?
- Cross-cutting concerns mixed with core functionality?
- A full UI screen described in one spec?
- Complex data transformations across multiple entities?
- Implies one substantial technical component (engine, parser, scheduler, algorithm, state machine, sync mechanism) that must be built in code?
- Identify the split boundaries — find the natural seams where the spec can be divided. Each resulting spec must be:
- Independently meaningful (makes sense on its own with previous specs as context)
- Self-contained (does not require a later spec to be useful)
- Within the 200 LOC limit
- Draft the replacement specs — write the smaller specs in chronological order. The first replacement spec typically sets up the foundation, and subsequent ones layer behavior on top.
- Verify functional completeness — this is critical. The replacement specs taken together must cover 100% of the functionality described in the original spec. Walk through every behavior, condition, and detail in the original and confirm it appears in exactly one of the replacement specs. Nothing may be lost, weakened, or left implicit. If any functionality from the original is missing, add it to the appropriate replacement spec or create an additional one.
- Verify each replacement spec — run
analyze-if-func-spec-too-complex on each to confirm it fits within the limit.
- Check for conflicts — run
analyze-func-specs once with the full set of replacement specs plus every existing spec in the file and its requires chain. The batched analyzer reports every conflicting pair (replacement × existing and replacement × replacement) in one call — do not loop over pairs. Resolve each reported pair with resolve-spec-conflict, then re-run analyze-func-specs over the touched set until the verdict is COMPATIBLE.
- Replace in the file — remove the original spec and insert the replacement specs in its position, preserving chronological order.
- Read the file again to confirm correct placement and syntax.
Splitting Strategies
Strategy 1: Separate Distinct Behaviors
If the spec bundles multiple independently testable actions, split each into its own spec.
Before:
***functional specs***
- A :User: can create, edit, and delete :Recipe: items, with validation on all fields.
After:
***functional specs***
- A :User: can create a :Recipe:. Only valid :Recipe: items can be created.
- A :User: can edit an existing :Recipe:. Validation rules apply to the edited fields.
- A :User: can delete a :Recipe:.
Strategy 2: Separate Setup from Behavior
If the spec introduces a new construct and immediately defines complex behavior on it, split into setup + behavior.
Before:
***functional specs***
- The :MealPlan: screen displays a weekly grid of :Slot: items, allows drag-and-drop reordering, and shows nutritional totals per day.
After:
***functional specs***
- The :MealPlan: screen displays a weekly grid of :Slot: items.
- A :User: can reorder :Slot: items within a day on the :MealPlan: screen using drag-and-drop.
- The :MealPlan: screen displays nutritional totals for each day.
Strategy 3: Separate Core Logic from Cross-Cutting Concerns
If the spec mixes primary functionality with error handling, retries, caching, pagination, or logging, pull cross-cutting concerns into their own specs.
Before:
***functional specs***
- :Ingredient: data is fetched from the external API with pagination, retry on transient errors, and caching for 10 minutes.
After:
***functional specs***
- :Ingredient: data is fetched from the external API.
- :Ingredient: data is fetched from the external API in pages.
- Fetching :Ingredient: data is retried on transient errors.
Strategy 4: Separate Conditional Paths
If the spec describes different modes or branches, give each its own spec.
Before:
***functional specs***
- :MealPlan: generation depends on :DietType:. Standard plans use round-robin assignment. Restrictive plans filter out excluded ingredients first, then apply round-robin. Custom plans allow manual slot-by-slot selection.
After:
***functional specs***
- A standard :MealPlan: is generated using round-robin :Recipe: assignment.
- A restrictive :MealPlan: is generated.
- Excluded :Ingredient: items are filtered out first.
- Round-robin :Recipe: assignment is then applied.
- A :User: can manually assign :Recipe: items to :Slot: items for a custom :MealPlan:.
Strategy 5: Build UI Incrementally
If the spec describes a full screen, split into layout + individual interactive elements.
Before:
***functional specs***
- The :Dashboard: screen shows a summary card with stats, a scrollable list of recent :MealPlan: items, a floating action button to create a new plan, and a bottom navigation bar.
After:
***functional specs***
- The :Dashboard: screen shows a summary card with :MealFrameStats:.
- The :Dashboard: screen shows a scrollable list of recent :MealPlan: items.
- The :Dashboard: screen includes a button to create a new :MealPlan:.
Strategy 6: Extract a Reusable Technical Component
Sometimes a spec is too complex not because it bundles many behaviors, but because it implies building one substantial technical component inline — an engine, parser, scheduler, layout algorithm, state machine, or sync mechanism. Splitting the behavior sideways does not help when the weight sits in that single component. Instead, pull the component out: define a concept for it, build it in its own dedicated spec placed earlier in the chain, then rewrite the original to use the component by reference. Because specs render incrementally top-to-bottom, the original now implies far less code — it wires up a component that already exists rather than implementing it from scratch.
Define the component concept in ***definitions*** (via add-concept) before the first spec that references it.
Before:
***functional specs***
- A :Report: is exported to PDF, laying out multi-page tables with repeating headers, page numbers, and charts rendered from :Report: data.
After:
***functional specs***
- :PdfRenderer: lays out multi-page tables from structured content.
- Table headers repeat at the top of each page.
- Each page shows its page number.
- A :Report: is exported to PDF using :PdfRenderer:, embedding charts rendered from :Report: data.
The extracted component spec and the rewritten original must together still cover 100% of the original functionality (step 6): the original must reference the component, never re-describe it. Keep the component's technology and architecture choices in ***implementation reqs***, not in the functional spec. If the component is a self-contained subsystem or will be reused across modules, promote it to its own module with create-requires-module / refactor-module instead of a sibling spec.
Preserving Chronological Order
The replacement specs take the position of the original spec. Earlier specs remain unchanged. The first replacement spec should make sense given only the specs above it. Each subsequent replacement spec can reference behavior from the ones before it.
If the original spec had acceptance tests, redistribute them to the most appropriate replacement spec — or drop tests that no longer apply to a single smaller spec and rewrite them.
Validation Checklist