A useful refactor starts with an agreed destination, not a generated patch. Before letting a model edit files, use it to map dependencies, identify behavior that must survive, and propose a sequence you can review. This walkthrough uses a concrete example: separating invoice calculation from an invoice service that also handles persistence and email.
1. Write the refactor contract before opening an agent
Describe the structural change and explicitly exclude unrelated improvements. For the invoice service, the goal is to extract calculation into a separate component while keeping the public service interface unchanged.
Give the model this instruction: Plan only. Do not edit files, install dependencies, run migrations, or generate a patch. Preserve invoice totals, rounding rules, persistence behavior, and email timing. Flag uncertainty instead of inventing requirements.
Add a reason for the work: calculation needs isolated tests because pricing changes currently require database fixtures. That gives the model a concrete outcome without inviting a wholesale redesign.
2. Set up a read-only planning session
Use a separate planning conversation and restrict the agent to repository inspection. Where your tool supports permission controls, allow file reads and searches while disabling writes and shell execution. An instruction is useful, but tool permissions provide a stronger boundary.
SwiftRelay works with Claude Code, Codex, Gemini CLI, and OpenAI-compatible SDKs, so you can use your existing workflow. A model such as Claude Sonnet 5.5 can help inspect the supplied context and draft a plan. Sign up for SwiftRelay to try this workflow with the small gift credit available to new accounts; usage is billed per token.
3. Build an evidence-backed dependency map
Start with the invoice service, its callers, calculation helpers, database boundary, email adapter, and nearby tests. Ask the model to follow references rather than infer architecture from filenames.
Use this prompt: List the entry points, collaborators, side effects, and tests relevant to invoice calculation. Cite file paths and symbols for each finding. Separate observed facts from hypotheses, and list anything you could not inspect.
Review that map yourself. A missing scheduled job or alternate API handler can turn an apparently internal extraction into a behavior change. Keep the context focused, and exclude credentials and customer data.
4. Turn preserved behavior into a test inventory
Ask for a behavior inventory before asking for a new abstraction. In this example, it should cover discount ordering, tax calculation, currency rounding, empty invoices, invalid quantities, and failures during persistence or email delivery.
- Existing coverage: identify tests that already protect each behavior.
- Missing coverage: propose characterization tests that capture current behavior, including surprising behavior.
- Open decisions: separate suspected bugs from refactor requirements.
Do not silently fix a suspicious rounding rule during extraction. Record it for a separate change unless the refactor explicitly includes that correction.
5. Request small implementation slices with checkpoints
Now ask for an ordered plan, not code: For each slice, name the affected symbols, explain the intended change, identify the behavior check, and describe how to revert that slice.
A sensible sequence might add characterization tests first, introduce a calculator behind the existing service, redirect calculation calls, and finally remove duplicated logic. Each slice should leave the repository in a reviewable state.
Reject vague steps such as “clean up dependencies.” Ask which dependency moves, who constructs it afterward, and whether callers need to change.
6. Challenge the plan with failure scenarios
Have the model critique its own proposal: Identify where this plan could alter transaction boundaries, exception behavior, rounding, or side-effect order. Explain what evidence would resolve each risk.
Then inspect the highest-risk assumptions yourself. Extracting a calculator is not behavior-preserving if it changes when data is loaded or when errors occur. Unresolved questions should become explicit blockers, not confident prose.
7. Approve the checklist before granting write access
Save the reviewed plan in your issue or planning document. Include the scope, dependency map, behavior inventory, implementation slices, verification commands, and unresolved questions.
The green light is specific: the baseline is understood, required tests are identified, and the first slice has a clear completion check. Only then start an editing session, authorize that slice alone, and review its diff before proceeding. The model supplies a proposal; repository evidence and human review decide whether it is safe to execute.