| name | refactoring |
| description | Guide behavior-preserving code refactoring with a language-agnostic core, Fowler-aligned catalog references, and team-specific extension patterns. Use during the TDD REFACTOR phase, when code smells are detected, when preparing for later behavior changes, or when discussing structural improvements. |
Apply behavior-preserving transformations to improve the internal design of existing code, including tests.
"Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior." -- Martin Fowler
Refactoring is not "code cleanup" in the broad sense. It is a sequence of small, safe transformations that preserve observable behavior while improving readability, modularity, and changeability.
Do not mix these concepts:
- Refactoring: preserve behavior, improve structure
- Behavior change: intentionally change outputs, contracts, or side effects
- Operational workflow: commits, checkpoints, sequencing rules
Treat all external contracts as behavior, not only public function signatures.
Examples of observable behavior:
- Public APIs and exported types
- HTTP, RPC, CLI, and event contracts
- Database schemas and persisted data formats
- Error semantics and exception types
- Logs, metrics, and audit outputs when consumers depend on them
- Performance or concurrency guarantees when they are part of the contract
See library-application-criteria.md for boundary guidance.
Prefer small, behavior-preserving steps
Use the strongest available safety net before changing structure
Address one smell or structural problem at a time
Separate refactoring from feature work and bug fixes
Stop and reassess if an intended refactor changes an external contract
Do not assume that "all unit tests are green" is the only valid safety condition.
Acceptable safety nets include:
- Existing automated tests
- Characterization tests added before refactoring legacy code
- Compiler/type-system guarantees
- Contract tests, snapshot tests, or property tests
- Incremental rollout or compatibility layers when boundaries are sensitive
1. Identify the smell, friction, or structural mismatch
2. Identify the relevant external contracts and safety net
3. Choose a pattern from `patterns-core.md` or `patterns-team.md`
4. Apply the change mechanically in small steps
5. Re-run the relevant checks after each meaningful step
6. Only then make the intended behavior change, if any
Use the catalogs in this order:
1. `patterns-core.md` for language-agnostic, Fowler-aligned patterns
2. `patterns-team.md` for team-specific extension patterns
3. `language-specific-guidance.md` for selecting the relevant language-specific reference
Load language-specific references only when the task language clearly matters:
- Rust:
references/rust-refactoring.md
- TypeScript / JavaScript:
references/typescript-refactoring.md
patterns.md is kept as an index for compatibility and quick navigation.
Keep refactoring separate from intentional behavior changes
Prefer names and boundaries that encode understanding in the code
Consider external contracts before reorganizing modules or APIs
Calling a breaking API change "refactoring"
Bundling multiple unrelated structural changes together
Smuggling new features into refactoring-only work
<related_skills>
Refactoring is the third phase of the TDD cycle
Tidying is a narrow subset of small, safe structural changes
Use refactoring to reduce complexity and coupling before extending behavior
</related_skills>
See `patterns-core.md` for the main catalog, `patterns-team.md` for team-specific extensions, `patterns.md` for a compact index, `library-application-criteria.md` for external-contract boundaries, `language-specific-guidance.md` for language-specific layering, and `references/` for language-specific reference files.