| name | refactoring |
|---|---|
| version | 0.3.0 |
| description | Safe refactoring protocol for AI agents — how to restructure code without breaking behavior. |
| extends | Project Workflow Protocol |
This skill defines how to refactor code safely. The cardinal rule: refactoring changes structure, never behavior. If behavior changes, it's not a refactor — it's a feature or a fix.
- Refactoring is not cleaning. It's restructuring code to make it easier to understand, extend, or maintain. It requires the same rigor as writing new features.
- Never refactor and change behavior in the same commit. Mixing structural changes with behavioral changes makes review impossible and debugging a nightmare.
- Tests are your safety net. If tests don't exist for the code you're refactoring, write them first. Refactoring untested code is high-risk.
- Approval required. Do not refactor code you weren't asked to touch. Flag ugly code, but don't fix it without explicit approval.
| Signal | Example | Action |
|---|---|---|
| Duplication | Same logic in 3+ places | Extract to shared function/component |
| Complexity | Function > 50 lines, deeply nested conditionals | Decompose into smaller functions |
| Naming | Misleading or abbreviated names | Rename for clarity |
| God files | File > 500 lines mixing concerns | Split by responsibility |
| Dead code | Unused imports, unreachable branches, commented-out blocks | Remove |
| Type weakness | any types, missing interfaces |
Add proper types |
- During a bug fix (fix the bug, then propose a refactor separately)
- Without tests for the affected code
- Without explicit approval from the user/team
- When you're "just making it better" without a concrete improvement goal
- In the same commit as a feature change
- State what you want to refactor and why
- Quantify the improvement: "Reduces duplication from 3 copies to 1" or "Splits 600-line file into 3 focused modules"
- Verify tests exist for the code being refactored
- If tests are missing: write them first, commit them separately, then refactor
- Tests should pass before AND after the refactor with identical results
- List every file that will change
- Identify the refactoring pattern (see below)
- Declare the scope boundary: "I will only touch files X, Y, Z"
- One refactoring pattern per commit
- Run tests after each step
- If tests break, the refactor introduced a behavior change — revert and investigate
# Before refactoring (baseline)
npm test → all pass
npm run build → exits 0
# After refactoring (must match)
npm test → all pass (same tests, same results)
npm run build → exits 0Before: Long function with embedded logic
After: Smaller functions with clear names
Commit: refactor({scope}): extract {functionName} from {parentFunction}
Before: Large component with mixed responsibilities
After: Focused components composed together
Commit: refactor({scope}): extract {ComponentName} from {ParentComponent}
Before: Misleading or unclear names
After: Descriptive, consistent names
Commit: refactor({scope}): rename {old} to {new} for clarity
Before: Code in the wrong file or directory
After: Code in the logical location
Commit: refactor({scope}): move {item} to {location}
Before: Unnecessary abstraction (function called once, adds indirection without clarity)
After: Logic inlined where it's used
Commit: refactor({scope}): inline {functionName} — single-use abstraction
Before: Deeply nested if/else chains
After: Guard clauses, early returns, or switch statements
Commit: refactor({scope}): simplify conditionals in {functionName}
| Anti-Pattern | Why It's Wrong |
|---|---|
| Refactoring while fixing a bug | Can't tell if the bug fix works or the refactor broke something else |
| Refactoring without tests | No safety net — behavior changes go undetected |
| "While I'm here" refactoring | Scope creep — stay within declared boundaries |
| Premature abstraction | Extracting a pattern seen only once is adding complexity, not reducing it |
| Renaming everything at once | High blast radius — rename incrementally and verify at each step |