---
name: Refactor Safely
slug: refactor-safely-2
category: Quality
description: Refactor Safely restructures existing code without changing externally visible behavior. It guides characterization-first refactors with context, architecture, code quality, and test guardrails.
github: "https://github.com/techygarg/lattice/tree/main/skills/refactor-safely"
language: Shell
stars: 185
forks: 13
install: "npx degit https://github.com/techygarg/lattice/tree/main/skills/refactor-safely ~/.claude/skills/refactor-safely"
installs_to: ~/.claude/skills/refactor-safely
source_path: skills/refactor-safely/SKILL.md
collection_size: 25
category_size: 1745
collection_url: "https://dirskills.com/collections/techygarg/lattice"
added: 2026-09-06T05:20:45.156Z
last_synced: 2026-09-06T05:20:45.156Z
canonical_url: "https://dirskills.com/skills/refactor-safely-2"
---

# Refactor Safely

Refactor Safely restructures existing code without changing externally visible behavior. It guides characterization-first refactors with context, architecture, code quality, and test guardrails.

**Install:**

```bash
npx degit https://github.com/techygarg/lattice/tree/main/skills/refactor-safely ~/.claude/skills/refactor-safely
```

## README

# Refactor Safely

## Required Skills

Load these skills based on refactor scope (see Steps 3, 5, 6 for conditional use):

1. `framework:knowledge-priming` -- Load project context so the refactor grounds in the real codebase. (always)
2. `framework:context-anchoring` -- Find and load the feature's context doc; capture approved plans and decisions in it. (always)
3. `framework:learning-harvest` -- Load prior operational learnings at session start; harvest new ones at session end. (always)
4. `framework:collaborative-judgment` -- Surface trade-offs in structure, seams, and migration sequence instead of silently assuming. (always)
5. `framework:clean-code` -- Readability, responsibility boundaries, local craft. (always)
6. `framework:test-quality` -- Characterization tests and the safety net. (always)
7. `framework:design-first` -- Target-structure planning for significant structural changes. (conditional: Step 3)
8. `framework:architecture` -- Layer placement and dependency direction. (conditional: responsibilities move across layers in Steps 5/6)
9. `framework:domain-driven-design` -- Aggregate boundaries and domain behavior. (conditional: domain rules move or sharpen in Step 6)
10. `framework:secure-coding` -- Trust bounds, authorization, sensitive data handling. (conditional: security-sensitive code touched in Step 6)

## Workflow

### Step 1: Establish Refactor Context

Start from the current pain, not from a preferred abstraction.

- Identify the target area: a module, service, aggregate, endpoint path, or subsystem.
- Clarify why the refactor is needed: mixed responsibilities, duplication, wrong-layer logic, coupling, poor testability, or unreadable control flow.
- Clarify what the user expects to improve: simpler structure, correct layer placement, smaller units, clearer domain behavior, easier testing, or safer extension points.
- Run `framework:learning-harvest` Load behavior. Focus hint: "refactoring session — focus: structural health, quality signals".
- Run `framework:context-anchoring` Document Discovery to check for an existing context doc covering the affected feature/module:
  - **Found** → Load behavior. Honor every logged decision and constraint as an active commitment while planning the refactor. The doc already contains an approved refactor plan (preservation boundaries + target structure) → confirm it still matches the user's intent, then resume at Step 4 unless the user wants to revisit the plan first.
  - **Not found** → Proceed from the conversation and the current code. Do not block planning on a missing context doc.

End the step by summarizing the intent in one sentence:

> "Refactor X to improve Y while preserving Z."

**STOP:** If you cannot state both the improvement target and the preservation target that clearly, continue clarifying with the user before planning any changes.

**Persistence check**:

- Refactor is substantial, risky, or likely to span multiple sessions → ask whether the user wants to persist an approved plan.
- A relevant context doc already exists and the user wants persistence → use it and update it.
- No relevant doc exists and the user wants persistence → propose creating one; confirm the doc name per `framework:context-anchoring`, then use it as the source of truth for the approved plan.
- The user declines persistence, or the refactor is small and local → continue in non-persistent mode. Approval gates still apply; the plan simply stays in-session.

### Step 2: Define Preservation Boundaries

Refactoring changes structure, **not behavior**. Make the preservation contract explicit before proposing any structural edits.

List the behaviors that must remain unchanged:

- Public API contracts and response shapes
- Domain invariants and state transitions
- Persistence semantics and side effects
- Event emission and integration behavior
- Authorization and security posture
- Error behavior wherever externally visible
- Performance or operational characteristics, if part of the current contract

Also list explicit **out-of-scope changes**:

- New features
- Schema changes
- Contract changes
- Intentional behavior changes
- Unrelated cleanup outside the approved area

If the desired outcome requires changing preserved behavior, stop and discuss what the task actually is — a bug fix (`/bug-fix`), a feature change (`/design-blueprint`), or a broader redesign. **STOP:** Never proceed as a refactor after making one of those determinations.

### Step 3: Propose High-Level Structural Plan

**Zero Refactor Rule**: make no structural code changes until the user approves both the target structure and the transition plan.

For small refactors the plan may be brief. For larger ones, use `framework:design-first` selectively:

- Start at **Level 2 (Components)** to define target responsibilities and boundaries.
- Use **Level 3 (Interactions)** when data flow or dependency direction will change.
- Use **Level 4 (Contracts)** when internal interfaces or seams need to be formalized.
- Skip Level 1 (Capabilities) unless the user-facing scope is actually changing.

Present:

- **Current structural problems** -- what is wrong with the current shape
- **Target structure** -- which components, classes, and functions should exist after the refactor
- **Movement plan** -- what logic moves where
- **Preservation boundaries** -- what will stay behaviorally unchanged
- **Out-of-scope items** -- what will not be changed in this pass

End the step with an explicit gate:

> "Does this refactor plan look correct? Should I proceed to Step 4: characterization tests?"

**STOP:** Do not write any refactoring code until the user explicitly approves this plan.

If persistence is enabled, use `framework:context-anchoring` Enrich to capture the approved preservation boundaries, target structure, movement plan, and out-of-scope items. **STOP:** When persistence is enabled, do not proceed to Step 4 until the approved plan is written.

### Step 4: Add Characterization Protection First

Before changing any structure, lock in current behavior with tests.

- Identify existing tests that already protect preserved behavior.
- Strengthen existing tests that are too implementation-coupled or too vague to serve as guardrails.
- Add **characterization tests** for important behaviors that are currently implicit.
- Prefer the lowest-level test that faithfully captures each preserved behavior without missing important integration effects.
- Characterization tests must describe the **current observable behavior**, not the intended refactored shape.
- Apply `framework:test-quality` inline while writing them.
- Run the safety net where the environment allows. If tests cannot be executed here, say so explicitly — the safety net then counts as unverified, and the stopping rule below applies.

**Stopping rule**:

- An important preserved behavior is not protected by tests → pause and make that gap explicit before refactoring.
- **STOP:** Do not start structural edits without a believable safety net unless the user explicitly accepts the risk.
- Green characterization tests are the baseline for the refactor. Anything red before the first structural change must be resolved first, or the task re-scoped.

End the step with an explicit gate:

> "Characterization tests in place and passing. Ready to discuss refactor strategy and pacing?"

**STOP:** Do not proceed to strategy selection until the safety net is verified green — or the user has explicitly accepted an unverified safety net per the stopping rule above.

### Step 5: Choose Refactor Strategy and Pacing

With the high-level plan approved and the safety net green, choose the implementation approach.

Preferred strategies:

- **Extract and redirect** -- extract focused units, route callers gradually.
- **Introduce seam, then migrate** -- add an interface or boundary, then move behavior behind it.
- **Move behavior inward** -- shift business rules from outer layers into the appropriate inner layer per `framework:architecture`.
- **Split and collapse** -- separate unrelated responsibilities, then remove the old mixed path.

Ask the user to choose a pacing mode:

> "How would you like to review the refactor?"
> 1. **Slice-by-slice** (recommended) -- refactor one safe slice at a time, pausing after each slice. Best for risky legacy code.
> 2. **Layer-by-layer** -- complete the refactor for one structural layer or concern, then pause for review. Best for broader architectural cleanup.
> 3. **Full autonomy** -- execute the approved refactor end-to-end and present the complete result at the end. Best for tightly scoped, low-risk refactors. (Still pause immediately if any slice reveals the approved plan unsafe or invalid — see the Deviation Rule in Step 6.)

Default to **slice-by-slice** when the user expresses no preference.

### Step 6: Refactor in Small Green Steps

Implement only within the approved preservation boundaries and the approved target structure.

For each slice:

1. Make one structural improvement from the approved plan.
2. Re-run the relevant characterization tests.
   - Any characterization test goes red → **stop immediately**. Do not start the next slice. Fix the regression or revert the slice before continuing.
3. Apply the applicable atom Self-Validation Checklists.
4. Run the applicable Active Anti-Pattern Scans.
5. Fix violations before presenting the slice.
6. Collect judgment calls for the slice via `framework:collaborative-judgment` and surface them before presenting the slice's code. Do not interrupt mid-slice unless the approved plan becomes unsafe or invalid.

Always apply:

- `framework:clean-code` -- better boundaries, simpler control flow, smaller focused units, clearer naming.
- `framework:test-quality` -- maintain strong characterization tests and nearby supporting tests.

Conditionally apply:

- Responsibilities move across layers or dependency direction changes → apply `framework:architecture`.
- Business rules, aggregates, value objects, or domain behavior move or sharpen → apply `framework:domain-driven-design`.
- Trust boundaries, authorization, validation, queries, or sensitive data handling are touched → apply `framework:secure-coding`.

**Deviation rule**: if the implementation reveals the approved plan incomplete, unsafe, or requiring changes to preserved behavior → **STOP:** pause immediately and discuss before continuing.

### Step 7: Verify Preservation and Structural Improvement

The refactor succeeds only if **both** are true:

1. **Behavior preserved**
2. **Structure measurably better**

Verify preservation:

- Characterization tests still pass.
- No unintended outward behavior changed.
- Preserved contracts remain intact.
- Security posture not weakened.

Verify structural improvement:

- Responsibilities clearer.
- Dependency direction improved, or at least no worse.
- Duplication or entanglement reduced.
- Testability and readability improved.
- Old paths and temporary scaffolding removed once migration is complete.

When reporting completion, be explicit about both sides:

- What behavior was preserved and how it was verified.
- What structural improvement was achieved.
- What was intentionally deferred to a later refactor.

### Step 8: Capture Decisions and Remaining Debt

Use `framework:context-anchoring` Enrich to preserve the important parts of the refactor:

- Refactor scope: what area changed.
- Preservation boundaries: what was explicitly kept stable.
- Target structure: what shape was approved.
- Strategy chosen: why this migration path was selected over the alternatives.
- Key files changed: path + role in the doc's Key Files table (skip a path already listed).
- Deferred debt: what remains and why it was intentionally left for later.

No context doc exists and the refactor involved non-trivial structural reasoning → suggest creating one so the decisions are not lost across sessions.

**Harvest learnings**: run `framework:learning-harvest` Harvest behavior. Session context: "refactoring session — structural restructuring and debt resolution". Synthesize and propose cross-cutting patterns from this session — structural debt that accumulated, migration strategies that worked, characterization test gaps discovered. The user confirms what enters the document. **STOP: run this before recommending `/review` below.**

After the refactor is complete, recommend `/review` when the change:

- touches multiple layers
- changes domain boundaries
- changes security-sensitive code
- leaves temporary migration scaffolding behind
- is large enough that an independent quality pass would add confidence
