You asked the model to rename a parameter in one function. It did. It also “cleaned up” a retry loop two functions below, swapped a forEach for a map, and silently changed a default timeout from 30s to 10s. None of that was in the prompt. None of it appears in the model’s summary of changes (“renamed parameter as requested”). Worse: the tests still pass because the retry path is exercised only in production. You will discover the change in a 3am incident, not in code review. AI agents over-edit because most chat-style instructions are interpreted as a license to “leave the code better than you found it” — a habit modeled on senior engineers in training data who do exactly that.
This page walks through how to scope an AI edit to a surgical change with a real diff you can audit.
Common causes
1. Verb is open-ended
“Refactor”, “improve”, “clean up”, “modernize” all give the model permission to touch anything that smells suboptimal — which, by training-set standards, is most pre-existing code.
How to spot it: your prompt verb has no object. “Refactor” alone means “improve everything you can”.
2. Whole file pasted, no edit zone marked
When the model receives the whole file and is told to “make a change”, regenerating the whole file is the path of least resistance. Anything regenerated drifts.
How to spot it: you pasted 400 lines and asked for one rename, and got 400 lines back.
3. Agent has wide write permission
In Cursor Composer, Claude Code with auto-edit, or Codex with broad scope, the model can touch any file. Without explicit scoping, “scope” becomes “everything the agent can read”.
How to spot it: changes appear in files you never named.
4. No diff format requested
If the output format is “the new file”, the model has to produce every line, and every line is a chance to drift. If the output format is “unified diff”, the model is forced to emit only changed hunks.
How to spot it: you got a full new file back, not a diff.
5. Model summary says “renamed” but does more
Models sometimes claim to do less than they did in their summary. The summary is a self-report; you cannot trust it for an audit. Audit the diff itself.
How to spot it: model summary mentions one change; diff shows many.
Before you change anything
- Commit the current state before re-prompting (so you can
git diffcleanly). - Identify exactly which lines/functions should change and which must not.
- Save the over-edited output so you can compare with the surgical version.
- For agent runs, narrow the scope (e.g., open only the target file in Cursor; restrict Claude Code’s working directory).
- Decide: do you want a diff, an
Edittool call (exact old-string match), or a constrained full file?
Information to collect
- The file(s) pasted and the prompt used.
- The model’s claimed summary of changes.
- The actual diff (
git diff). - The model, agent, and tool permissions in effect.
- A list of lines that were changed but should not have been.
Shortest path to fix
Step 1: Replace open verbs with surgical operations
Bad: "Refactor this module for readability."
Good: "In function `handlePayment`, rename parameter `amt` to `amountCents`.
Update all references inside `handlePayment` only.
Do not modify any other function. Do not touch imports.
Do not reformat unchanged lines."
Step 2: Declare a “do not modify” list
Constraints:
- Do not modify any function other than `handlePayment`.
- Do not touch imports, exports, or comments.
- Do not change constants `MAX_RETRIES` or `TIMEOUT_MS`.
- Do not change formatting of unchanged lines.
- If you would normally "clean up" something, list it in a separate
"Suggested follow-ups" section instead of doing it.
Step 3: Demand a unified diff, not a file
Return output in this format:
DIFF:
\`\`\`diff
--- path/to/file.ts
+++ path/to/file.ts
@@ ... @@
- old line
+ new line
\`\`\`
SUGGESTED FOLLOW-UPS:
- <things you noticed but did not change>
Diff output forces minimal change because regenerating untouched code is wasted work.
Step 4: Use exact-match Edit tools when available
In Cursor / Claude Code / Codex, prefer the Edit tool that requires an exact old_string to match. The model literally cannot edit unmarked regions because the match fails. This is the strongest mechanical guarantee.
Step 5: Audit the diff, not the summary
Never accept the model’s prose summary as truth. Always:
git diff HEAD
Scroll every hunk. If a hunk surprises you, revert that hunk individually with git checkout -p or your IDE’s per-hunk revert.
Step 6: Split multi-region edits into multiple prompts
If you really need to change 3 functions, do 3 prompts. Combined prompts blur scope and the model averages constraints across regions.
How to confirm the fix
git diffshows changes only in the files and functions you named.- No imports, exports, or constants moved.
- Existing tests still pass with no test changes from the model.
- The model’s “follow-ups” list is non-empty if it noticed other issues — meaning it respected the scope.
- A second AI run with the same prompt produces a similar diff (stable, scoped behavior).
If it still fails
- Restrict tool permissions: read-only on directories you do not want touched.
- Switch to
Edit-tool-only mode (no full file rewrites). - Use a smaller / cheaper model — many follow constraints more strictly than flagship models.
- For high-stakes code, never let an agent commit directly — always review the diff first.
When this is not on you
If your prompt literally said “refactor”, “polish”, or “modernize”, the model obeyed the prompt. The fix is to change the verb, not to blame the model.
Prevention
- Default prompt verb:
edit,rename,replace— neverrefactor,improve, orpolishwithout scoping. - Always require diff output for code edits over 20 lines.
- Bracket the edit zone with comments:
// AI-EDIT-START/// AI-EDIT-ENDand tell the model to only modify inside. - Use
Edit-tool exact-match mode for surgical edits. - Commit before every AI run so you can
git diffandgit restorecleanly. - Review the diff every time. Do not trust the model’s self-summary.
Related reading
- AI over-edits when light rewrite was requested
- Unclear task boundary
- Too many tasks one prompt
- Model fills missing details
- Prompt lacks context hierarchy
Tags: #Troubleshooting #Prompt #Prompt quality #Unwanted rewrite