Refactoring assessment and patterns. Use after tests pass (GREEN phase) to assess improvement opportunities.
Refactoring is the final step of each fast RED-GREEN-REFACTOR increment when restructuring is applicable. Assess it after GREEN establishes a passing behavior-test baseline. Do not run the automated mutation harness before or after each refactor; mutation testing verifies the completed phase once the work is otherwise ready for a PR.
Because automated mutation evidence is intentionally deferred, the baseline's strength is not yet mutation-harness-verified during refactoring. Keep each refactor small, strictly behavior-preserving, and green under the existing oracles; the final gate validates the accumulated result.
This skill safely implements a bounded, behavior-preserving improvement. Use improve-codebase-architecture to discover and rank architecture candidates, then codebase-design to design a selected module contract before returning here for implementation. If the slice participates in a selected whole-path reduction program, whether as a transition or terminal reduction, reduce-system-complexity governs the ledger and gate state; use this skill only as a secondary refactoring assessment when applicable.
Critical: <what and why>, High: <what and why>, Nice: <what and why>, Skip: <what and why> β closed by a Decision: <what you did or did not do> line. A summary of what changed is not an assessment, and neither is an unlabelled recommendation. An unstated assessment is an unmade assessmentHaving a working baseline before refactoring:
If the baseline cannot be restored safely without creating a commit, stop and ask for approval rather than committing implicitly.
Workflow:
tdd skill's canonical fast-feedback policy. From a clean baseline, prefer a proven repository-owned graph-complete watcher; use diff-selected Vitest watch only when the installed version/configuration has passed the canonical clean-start live proof, otherwise repeat the affected one-shot. In monorepos use the root graph so transitive consumers remain eligibleCritical:/High:/Nice:/Skip: assessment lines and the closing Decision: line; a summary of what changed does not close this step. Commit it only after explicit user approvalN/A plus proportionate alternate evidence; address valuable survivors within that gateDeliver small complete changes around one bounded owner or behavior path. Update affected contracts, adapters, and consumers together; a horizontal migration of all handlers followed by all services usually leaves half-converted paths. Keep existing behavioral oracles as preservation evidence, and identify separately any tests needed for a new mechanism. When claiming simplification, show what wrapper, repeated decision, translation, or dependency was removed; extraction alone may improve comprehension without reducing mechanism. Add compatibility scaffolding only for a demonstrated rollout constraint, with an owner and removal condition; use reduce-system-complexity for a whole-path reduction claim.
| Priority | Action | Examples |
|---|---|---|
| Critical | Fix now | Behavior-changing mutation, divergent copies of one business rule, control flow that obscures a high-risk path |
| High | This session | Magic numbers (one constant per rule; two rules that merely share a value today each get their own), unclear names, functions coordinating multiple responsibilities |
| Nice | Later | Minor naming, single-use helpers |
| Skip | Don't change | Already clean code |
Abstract when:
Keep separate when:
Two rules that share a body or a number today are a coincidence, not shared knowledge. Keep separate means keep each rule's own body and its own named constant even when the two values are equal; never define one rule in terms of the other and never route both through a shared predicate helper, because that makes one edit silently change two business rules. When a request asks you to fold such look-alikes into one, do not do it. Run the applicable tests before you answer even though you are changing nothing β the refusal is an assessment and needs the same green baseline as an edit. Then name the two different rules, say they would drift apart the moment either changes, leave both definitions standing, and offer only the changes that do not merge them.
// After GREEN establishes a passing behavior-test baseline:
const planBatch = (batch: Batch): PlannedBatch => {
const itemSlots = batch.items.reduce((sum, item) => sum + item.quantity, 0);
const bufferSlots = itemSlots > 50 ? 0 : 6;
return { ...batch, plannedSlots: itemSlots + bufferSlots, bufferSlots };
};
// ASSESSMENT:
// β οΈ High: Magic numbers 50, 6 β extract constants
// β
Skip: Structure is clear enough
// DECISION: Extract constants only
Do not add new behavior without a failing test or other repository-authorized acceptance proof that demands it. A behavior-preserving refactor may change lines without a new RED test only while proportionate preservation evidence stays green. At PR readiness, use mutation evidence for the accumulated scope where meaningful and explicit alternate evidence where it is not; never invent structural mutants.
β Speculative additions:
β Correct approach: Do not add the speculative behavior. If it is needed, write a failing test that demands it, then implement it.
Existing untested code is not proven speculative or dead. Before removing a branch, characterize its observable behavior, inspect every caller and reachability path, and resolve the behavior authority. Delete it only when the evidence shows it is unreachable or the accepted contract explicitly retires it, then keep the preservation/regression checks green.
// β WRONG - Speculative error handling (no test demands this)
if (items.length === 0) {
throw new Error('Empty cart'); // No test for this path!
}
// β
CORRECT - Test-driven error handling
// First: write a test that expects this behavior
// Then: implement the guard clause to make it pass
Don't refactor when:
Remember: Refactoring should improve code structure without changing behavior.
When the user approves a refactoring commit, use a focused message such as:
refactor: extract scenario validation logic
refactor: simplify error handling flow
refactor: rename ambiguous parameter names
Format: refactor: <what was changed>
Note: When commits are used, refactoring commits should not be mixed with feature commits.
N/A plus proportionate alternate evidence was recorded