skills/code-quality/code-refactoring-assistant/SKILL.md
Executes refactorings — extract method, inline, rename, move — in small, behavior-preserving steps with a test between each. Use when the user wants to restructure working code, when cleaning up after a feature lands, or when a smell has been identified and needs fixing.
npx skillsauth add santosomar/general-secure-coding-agent-skills code-refactoring-assistantInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Refactoring is changing structure without changing behavior. The discipline: every step is small enough that if the tests break, you know exactly which change did it.
| Precondition | Why | If missing |
| ---------------------- | ---------------------------------------------------- | ------------------------------------ |
| Tests pass | You need a green baseline to detect breakage | Fix the tests first; don't refactor red |
| Tests cover the code | Uncovered code = undetected breakage | Add characterization tests first |
| You know the target | Refactoring without a goal is churn | → code-smell-detector to pick a target |
| Refactoring | When | Mechanics | Gotcha | | ------------------- | ---------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------- | | Extract method | Chunk of a long method has one job | Copy out → add params for free vars → replace original with call | Free vars: everything the chunk reads but doesn't define | | Inline method | Method body is clearer than its name | Replace all calls with body → delete method | Only if callers ≤ 3 and no polymorphism | | Rename | Name lies about what the thing does | IDE rename (finds all refs). Manual rename = missed callers | Strings, reflection, config files — IDE misses these | | Move method | Method uses another class's data more | Copy to target → delegate from old → update callers → delete delegate | Do it in two commits: add+delegate, then remove delegate | | Introduce parameter object | 4+ params that travel together | New class with those fields → one call site at a time | Don't convert all call sites at once — one per commit | | Replace conditional with polymorphism | Switch on type code | One subclass per case → move each branch into its subclass | Only if the switch repeats 3+ times — otherwise the switch is simpler | | Extract class | Class has two responsibilities | New class → move one responsibility's fields+methods → delegate | Don't move everything at once; one method per step |
run tests (green) → one small mechanical step → run tests → commit
↓ red?
revert that one step. rethink.
Every commit is a safe point. If you get interrupted, you're never more than one step from green.
Before (process_order, 50 lines):
def process_order(order, user):
# ... 20 lines ...
subtotal = sum(item.price * item.qty for item in order.items)
discount = 0
if user.tier == "gold":
discount = subtotal * 0.1
elif user.tier == "silver":
discount = subtotal * 0.05
total = subtotal - discount
# ... 20 more lines using `total` ...
Step 1 — identify the chunk. Lines computing total from order.items and user.tier. Free variables read: order.items, user.tier. Output: total.
Step 2 — copy out, don't cut.
def _compute_total(items, tier):
subtotal = sum(item.price * item.qty for item in items)
discount = 0
if tier == "gold":
discount = subtotal * 0.1
elif tier == "silver":
discount = subtotal * 0.05
return subtotal - discount
Step 3 — test. Run. Green? Good. (We haven't changed process_order yet — this is a pure addition.)
Step 4 — replace in place.
def process_order(order, user):
# ... 20 lines ...
total = _compute_total(order.items, user.tier)
# ... 20 more lines using `total` ...
Step 5 — test. Green → commit. Red → revert step 4, check: did you miss a free variable? Does _compute_total have a side effect the original inline code had?
self.cache — and the original code mutated self.cache three lines earlier. You just changed the ordering.behavior-preservation-checker if tests are thin.When executing a refactor:
## Target
<smell/goal — why this refactor>
## Steps
1. <mechanical step> → test → commit <sha>
2. <mechanical step> → test → commit <sha>
...
## Safe points
Every commit above is independently revertible.
## Behavior check
<→ behavior-preservation-checker result, or: "tests green, N tests cover the changed region">
development
Extracts human-readable pseudocode from a verified formal artifact (Dafny, Lean, TLA+) while preserving the verified properties as annotations, so the proof-carrying logic can be reimplemented in a production language. Use when porting verified code to an unverified target, when documenting what a formal spec actually does, or when handing a verified algorithm to an implementer.
development
Translates natural-language or pseudocode descriptions of concurrent and distributed systems into TLA+ specifications ready for the TLC model checker. Identifies state variables, actions, type invariants, safety properties, and liveness properties from the description. Use when formalizing a protocol, when the user describes a distributed algorithm to verify, when designing a consensus or locking scheme, or when starting formal verification of a concurrent system.
testing
Reduces a TLA+ model so TLC can actually check it — shrinks constants, adds state constraints, abstracts data, or applies symmetry — when the state space is too large to enumerate. Use when TLC runs out of memory, when checking takes hours, or when a spec works at N=2 and you need confidence at larger scale.
development
TLA+-specific instance of model-guided repair — reads a TLC error trace, identifies the enabling condition that should have been false, strengthens the corresponding action, and maps the fix to source code. Use when TLC reports an invariant violation or deadlock and you have the code-to-TLA+ mapping from extraction.