
Refactor Module
- 42 installs
- 54 repo stars
- Updated July 22, 2026
- codeplain-ai/plain-forge
Split an oversized ***plain module into smaller domain-grouped modules linked by a requires chain, preserving all behavior.
About
Splits a large ***plain module into smaller modules grouped by logical domain, connected via a requires chain. A developer uses it when a module has grown too broad across distinct concerns.
- Splits a large ***plain module into smaller domain-grouped modules
- Connects them via a requires chain so functionality is fully preserved
Refactor Module by the numbers
- 42 all-time installs (skills.sh)
- Ranked #351 of 782 Skill Development skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
npx skills add https://github.com/codeplain-ai/plain-forge --skill refactor-moduleAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 42 |
|---|---|
| repo stars | ★ 54 |
| Last updated | July 22, 2026 |
| Repository | codeplain-ai/plain-forge ↗ |
What it does
Split an oversized ***plain module into smaller domain-grouped modules linked by a requires chain, preserving all behavior.
Files
Refactor Module
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
- A module has many functional specs spanning multiple distinct domains or feature areas.
- The module is hard to reason about because unrelated concerns are interleaved.
- New features are difficult to add because the module's scope is too broad.
- The user explicitly asks to split or reorganize a module.
Guiding Principle
The refactoring is purely structural. The combined behavior of the resulting modules must be identical to the original module. No functional spec is added, removed, or weakened. The split is semantic — grouping related specs together — not behavioral.
Input
The .plain file to refactor, plus guidance from the user on the desired grouping (or ask the user to confirm your proposed grouping).
Phase 1 — Analyze the Current Module
1. Read the entire `.plain` file — frontmatter, definitions, implementation reqs, test reqs, and all functional specs. Also read any import and requires chains to understand the full context. 2. Inventory the functional specs. Number each spec and note which :Concepts: it references. Build a dependency map: which specs depend on earlier specs (by referencing behavior or state they introduced)? 3. Inventory the definitions. For each concept, note which functional specs reference it. Identify concepts that are used across multiple logical groups vs. concepts used only within one group. 4. Identify logical groups. Look for natural seams — clusters of functional specs that share concepts, represent a cohesive domain, or describe a single feature area. Common groupings:
- Data model setup and CRUD operations
- Business logic and processing rules
- UI screens and navigation
- Integrations and external interfaces
- Statistics, reporting, and analytics
5. Verify group independence. Each group's specs should form a contiguous or near-contiguous block in chronological order. If a group's specs are scattered and interleaved with other groups, the split boundary may need adjustment.
Phase 2 — Plan the Split
Present the proposed split to the user and get explicit confirmation before making any changes.
2a. Define the module chain
The modules form a requires chain that preserves the original chronological ordering of functional specs. The first module in the chain contains the earliest specs; each subsequent module requires the previous one and adds the next logical group.
original-module
↓ splits into
module-group-a (no requires — this is the new base)
module-group-b (requires: module-group-a)
module-group-c (requires: module-group-b)If the original module already had requires or import dependencies, the first new module inherits them.
2b. Assign functional specs to modules
Place each functional spec in exactly one module. The placement must respect chronological ordering:
- Within each module, the specs appear in the same relative order as in the original.
- Across the chain, the ordering is preserved: all specs in module A come before all specs in module B, which come before all specs in module C.
- A spec cannot move to an earlier module than a spec it depends on.
2c. Assign definitions to modules
For each concept, determine where it belongs:
| Concept usage | Placement |
|---|---|
| Used only within one module's specs | Define in that module |
| Used across multiple modules in the chain | Define in the first module that uses it, and add to that module's exported_concepts |
| Already defined in an import template | Leave in the import — no change needed |
If many concepts are shared across all modules, consider creating a new import module (template) to hold them. This avoids long exported_concepts lists and keeps definitions centralized. Use the create-import-module skill for this.
2d. Assign implementation reqs and test reqs
- Reqs that apply to all modules should live in a shared import template. If one already exists, keep them there.
- Reqs specific to a single module's domain move to that module.
- When in doubt, keep reqs in the shared template — duplication across modules is worse than a slightly broad template.
2e. Present the plan
Summarize for the user:
- Number of resulting modules and their names
- Which functional specs go in each module (listed by number or short description)
- The
requireschain order - Any new import module being created
- Which concepts are exported from each module
- Confirmation that all original specs are accounted for (none lost)
Get explicit user confirmation before proceeding.
Phase 3 — Execute the Split
Create the new modules in order, from the base of the chain upward.
3a. Create or update the import template (if needed)
If shared definitions or reqs are being moved to a new import template, create it first using the create-import-module skill.
3b. Create the base module
Create the first module in the chain: 1. Set the YAML frontmatter — inherit the original module's import references. Add exported_concepts for any concepts that downstream modules need. 2. Add the ***definitions*** section with concepts used by this module's specs and concepts that need to be exported. 3. Add ***implementation reqs*** and ***test reqs*** specific to this module (if not fully covered by the import template). 4. Add the ***functional specs*** assigned to this module, preserving their original order and exact wording. 5. Carry over any ***acceptance tests*** nested under the moved functional specs.
3c. Create subsequent modules
For each subsequent module in the chain: 1. Set requires to point to the previous module in the chain. Set import if it uses shared templates. 2. Add exported_concepts for any concepts that later modules in the chain need. 3. Add ***definitions*** for concepts local to this module. Do not redefine concepts already available via requires (exported) or import. 4. Add ***implementation reqs*** and ***test reqs*** specific to this module. 5. Add the ***functional specs*** assigned to this module, preserving their original order and exact wording. 6. Carry over any ***acceptance tests***.
3d. Handle the original module file
After all new modules are created:
- If the original module is being fully replaced (all specs moved out), delete it or rename it to avoid confusion.
- If the original module was required by other modules, update those modules to
requirethe last module in the new chain instead (since it transitively includes all prior modules' specs and generated code).
Phase 4 — Verify
4a. Completeness check
This is the most critical verification. Walk through every functional spec from the original module and confirm it appears in exactly one of the new modules. Nothing may be lost, weakened, modified, or left implicit.
Checklist:
- [ ] Total spec count across all new modules equals the original spec count
- [ ] Each spec's text is identical to the original (no rewording)
- [ ] Each spec's acceptance tests (if any) are carried over intact
4b. Chronological ordering check
Verify that the chronological order of all functional specs — when read across the requires chain from base to leaf — matches the original ordering exactly. A spec must not appear before a spec it depends on.
4c. Concept availability check
For each module, verify:
- [ ] Every
:Concept:referenced in its specs is either defined locally, available viaimport, or available viaexported_conceptsfrom therequireschain - [ ]
exported_conceptsincludes every concept that downstream modules need - [ ] No concept name collisions between modules
4d. Structural validation per module
For each new module:
- [ ] Has at least one functional spec and one implementation req
- [ ] YAML frontmatter is correctly formatted
- [ ]
requiresandimportpaths are correct - [ ] Module file is at the repository root (not in
template/) - [ ] Specs are language-agnostic
- [ ] All external interfaces remain explicit
4e. Read all new modules
Read each new .plain file in full and present the final structure to the user for approval. If the user requests changes, apply them and re-verify.
Common Pitfalls
Splitting too aggressively
Creating many tiny modules with 1–2 specs each adds overhead without clarity. Aim for modules with 3–10 functional specs each, grouped around a cohesive theme.
Breaking chronological order
Specs that set up foundational behavior (entry point, database init, core CRUD) must stay in the base module even if they touch concepts from multiple domains. Only split when specs are cleanly separable.
Forgetting exported_concepts
If a concept defined in module A is referenced by a spec in module B (which requires A), the concept must be in A's exported_concepts. Missing exports cause rendering failures.
Modifying spec text during the split
This is a refactoring, not a rewrite. Spec text must be copied verbatim. If a spec needs rewording to work in its new module context, that is a sign the split boundary is wrong — adjust the grouping instead.
Losing acceptance tests
Acceptance tests are nested under their parent functional spec. When moving a spec to a new module, its acceptance tests must move with it.
Validation Checklist
- [ ] User confirmed the split plan before execution
- [ ] All original functional specs are present in exactly one new module — none lost
- [ ] Spec text is identical to the original — no rewording
- [ ] Acceptance tests moved with their parent specs
- [ ] Chronological order preserved across the requires chain
- [ ] Every referenced
:Concept:is available in each module (local, import, or exported) - [ ]
exported_conceptsare correctly set on each module - [ ] No concept name collisions
- [ ] Each module has at least one functional spec and one implementation req
- [ ]
requireschain is correctly ordered (base → leaf) - [ ] Original module removed or updated
- [ ] Downstream modules (if any) updated to require the correct module
- [ ] User approved the final result