Refactor Prompt — the Behavior Preservation Contract
"Refactor this code" invites silent behavior changes. The refactoring contract preserves business rules, outputs, and side effects — and flags uncertainty instead of deciding it.
Legacy code has callers you cannot see and assumptions nobody wrote down. This refactoring prompt treats every public surface as load-bearing and changes in small, verified steps.
Refactoring legacy code fails differently: the danger is not what the code says, it is what depends on it invisibly. This prompt configures the contract for that reality — the legacy context assumes unknown dependencies and hidden assumptions, treats every public surface as load-bearing, demands incremental change with verification between steps, and requires the model to document every assumption it had to make about unclear behavior. Combined with a conservative risk profile, frozen-schema constraints, and a strict validation plan, the result is a refactor that respects what a twelve-year-old system actually is.
Assume the unseen
Unknown callers, hidden assumptions, undocumented consumers — the contract treats them as existing, not hypothetical.
State the frozen ground
Public API stays, schema stays — constraints carried as hard rules, not preferences.
Collect the assumption ledger
Every assumption about unclear behavior arrives documented — each one is a risk to verify before merging.
It treats every public surface as load-bearing — the EXISTING CODE CONTEXT line 'assume unknown dependencies and hidden assumptions' tells the model that code this old has callers you cannot see, so signatures, return types, error types, and serialized shapes stay preserved rather than guessed. You generate that contract as a prompt and run it in ChatGPT, Claude, or Gemini; confirming who actually calls the module stays your job.
The ASSUMPTIONS section makes it mark each one VERIFIED with evidence or UNVERIFIED with the question that would resolve it, and any transformation depending on an UNVERIFIED assumption gets flagged as conditional on it. It surfaces those open questions in the output; it can't run the code to settle them, so checking each ledger entry before you merge remains yours.
Both live under Stated constraints ('Public API of OrderService must not change', 'Database schema is frozen') and the Conservative risk profile that keeps every public contract and observable behavior exactly as-is. If the goal and behavior collide, its rule is 'behavior wins' — it stops and explains instead of compromising. Enforcing those frozen boundaries at merge time is still your call.
"Refactor this code" invites silent behavior changes. The refactoring contract preserves business rules, outputs, and side effects — and flags uncertainty instead of deciding it.
For code that ships weekly: a refactoring prompt where regression avoidance outranks improvement depth, log lines stay intact, and every step is rollback-friendly.
Generated code duplicates instead of extracting, wraps without deciding, and defends against impossible states. This prompt hunts those exact failure modes — without preserving bugs as behavior.
"Review this code" gets shallow comments. The review contract gets findings with severities, a checklist, and a verdict.
getByRole over CSS chains, auto-wait over sleep, web-first assertions — Playwright tests written the way Playwright wants.
"Fix this error" gets guesses. The investigation contract gets a ten-stage diagnosis: facts separated from assumptions, alternatives weighed, fixes justified.
Build behavior-preserving refactor prompts — goal, risk level, and code context turn into a safe refactoring contract.
The full path to taming an inherited codebase — understand it, document its architecture, pin its behavior with tests, then refactor, modernize, review, speed up, and ship it without breaking what works.
Update old, risky code you didn't write — safely — by understanding and pinning its behavior in tests before you change a single line.
"Refactor this to be cleaner" returns tidier code that quietly changed the null handling and an error type — a silent regression. Here's how to refactor with AI without changing behavior: name a small goal, list what must stay identical, forbid fixes, and verify the diff.