Refactor Safely

SkillMonitoring & ops

Restructure existing code safely without changing externally observable behavior. Composes context, design, architecture, code quality, and testing guardrails into a characterization-first refactoring workflow. Use when the user says 'refactor this', 'clean this up', 'untangle this module', 'move this to the right layer', 'simplify this code', or 'improve this structure'.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Refactor Safely skill

What this skill tells your AI

The instructions your AI receives, as published by techygarg/lattice in skills/refactor-safely/SKILL.md and read by ahel’s review.

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

Signals

GitHub stars
190
Forks
13
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
refactor-safely
Source
github.com/techygarg/lattice