You asked the model to fix one function. It fixed the function. It also “while it was at it” reformatted two adjacent functions, renamed a constant, and added a comment block above the file because “this should explain the module purpose”. None of that was in your prompt. But none of it was forbidden either. The model expanded scope because it is trained to leave things “better than it found them”, and “better” is unbounded unless you bound it.
Fastest fix: stop fixing the output, fix the prompt. Swap the open verb (“improve”) for a scoped one plus an explicit object (“edit only the function validate_email”), then add a literal out-of-scope list and ask for a diff. For an agent, the boundary has to be mechanical, not a sentence: lock the model to the target file or directory with Cursor’s edit-scope, Claude Code’s permissions.deny rules, or Codex’s --sandbox read-only. This page covers both the prompt-level and the tool-level boundary.
Which bucket are you in
| Symptom | Most likely cause | Go to |
|---|---|---|
| Extra changes inside the file you named | Open verb plus no out-of-scope list | Steps 1-2 |
| Adjacent functions/sections you pasted got rewritten | Long context, no boundary | Steps 1-3 |
| Scope grows with each step of a multi-step chat | Boundary dropped between steps | Step 5 |
| Files you never named were touched | Agent has wide write permission | Step 6 |
| Model agrees to the boundary then breaks it anyway | Prompt-only boundary, not enforced | ”If it still fails” |
Common causes
1. Open verbs license expansion
“Improve”, “clean up”, “polish”, “refactor” all imply “make better wherever you can”. The model takes that literally.
How to spot it: your verb is open. Scoped verbs are “edit function X”, “replace line Y”, “rename variable Z”.
2. No explicit out-of-scope list
You said what to do but not what to leave alone. The model treats everything within view as fair game.
How to spot it: your prompt has an in-scope set but no out-of-scope set.
3. Long context shows fixable adjacent issues
You pasted the whole file. The model sees your target and five other things that look fixable. Without a boundary, it fixes them all.
How to spot it: scope expansion lands in adjacent code or content visible in the prompt.
4. Multi-step task with no per-step boundary
Step 1 was scoped to function X. Step 2 says “now improve the module” and the boundary evaporates. By step 3 the model has rewritten the file.
How to spot it: scope creep correlates with step number in multi-step workflows.
5. Agent has wide write permission
In Cursor’s Agent mode, Claude Code, or Codex with a writable workspace, the model can touch any file in scope. “Scope” mechanically becomes “everything it can read and write”.
How to spot it: changes appear in files you never named.
Before you change anything
- Identify exactly what should change (in-scope).
- Identify what should not change (out-of-scope).
- Decide whether the model should flag adjacent issues or just ignore them.
- For multi-step work, plan boundaries per step.
- For agent runs, narrow tool permissions to the target file or directory before you start.
Information to collect
- The current prompt.
- The over-scope output (
git difffor code). - A list of changes that should not have happened.
- The in-scope and out-of-scope sets.
- The model, agent, and tool permissions in effect.
Shortest path to fix
Step 1: Replace open verbs with scoped verbs
Bad: Improve the user.py file.
Good: Edit only the function `validate_email` in user.py. Keep all
other functions byte-identical. Do not reformat unchanged lines.
The scoped verb plus an explicit object removes the ambiguity that “improve” leaves open.
Step 2: Declare an out-of-scope list
Out of scope (do not modify):
- Any function other than validate_email.
- Imports and exports.
- The MAX_RETRIES constant.
- Existing comments.
- The file-level docstring.
If you would normally "clean up" something, list it under
SUGGESTED_FOLLOWUPS instead of changing it.
The SUGGESTED_FOLLOWUPS pattern lets the model surface its observations without acting on them, which is usually what you actually wanted when you noticed the over-edit.
Step 3: Use marked edit zones for content
For prose, markdown, or config where line-level instructions are awkward, fence the editable region:
Edit only the text between the markers below. Leave everything
outside the markers exactly as written.
# AI-EDIT-START
def validate_email(email: str) -> bool:
return "@" in email
# AI-EDIT-END
Physical markers survive scope drift better than a sentence the model can reinterpret.
Step 4: Require a diff, not a full rewrite
Output a unified diff. Include only hunks for changes inside the
edit zone. Do not output the full file.
A diff makes out-of-scope edits mechanically visible, and the model behaves more conservatively when it knows you will read one. With an agent, the same effect comes for free: Cursor’s Agent shows every proposed change as a reviewable diff before applying it, so read it instead of clicking Accept All.
Step 5: For multi-step work, re-declare the boundary every step
Step 1: Edit ONLY validate_email. Out of scope: everything else.
Step 2: After step 1 is approved, edit ONLY send_email. Out of scope:
validate_email (now frozen) and everything else.
Carry forward the “now frozen” list so scope is monotonic instead of accumulating. A boundary you stated once at the top of a long chat does not survive; restate it.
Step 6: For agents, restrict at the tool level, not the prompt
A prompt boundary is a request; a permission boundary is enforced by the tool regardless of what the model decides to do. As of June 2026:
- Cursor. Use Edit mode (single-file, surgical) instead of Agent mode when the change is local. To keep a file out of the agent’s reach entirely, add it to
.cursorignore(gitignore syntax) — but note this is best-effort and currently blocks both read and write, and the agent can sometimes still reach an ignored file through a shell command, so review the diff. See Cursor’s agent security docs. - Claude Code. Permission rules in
.claude/settings.jsonare enforced by Claude Code, not the model. Deny edits outside your target with gitignore-style path rules, for example"deny": ["Edit(/src/legacy/**)"], or flip the whole session to read-only exploration with/permissionsset to plan mode. Only--add-dirdirectories are writable, so launching from the target subdirectory is itself a boundary. The CLI equivalent is--disallowedTools "Edit". See Claude Code’s permissions docs. - Codex. Run with
--sandbox read-onlyto plan without writes, or--sandbox workspace-writeto confine edits to the working directory;.git,.codex, and.agentsstay read-only even then. Use/permissionsmid-session to downgrade to read-only. See Codex’s sandboxing docs.
Mechanical permission beats a prompt-level instruction every time.
How to confirm the fix
- The diff is restricted to the in-scope set.
- Out-of-scope files, functions, and sections are byte-identical — confirm with
git diff --stat(only the files you expected should appear) andgit diffon each. SUGGESTED_FOLLOWUPS, if present, lists adjacent issues the model noticed without changing.- Re-running the prompt produces a similar-shaped diff.
- A teammate reviewing the diff cannot point to a surprising change.
If it still fails
- The model agreed to the boundary then broke it: stop relying on prose. Move to a tool-enforced boundary (Step 6) — Claude Code
Edit(...)deny rules and Codexread-onlysandbox are checked by the tool, not the model. - The agent has wider permissions than your prompt implies: confirm the writable scope (Cursor edit mode vs agent, Claude Code working directory, Codex sandbox mode) rather than the prompt.
- For repeated work, lock the boundary in the system prompt or project instructions (
CLAUDE.md,.cursor/rules,AGENTS.md), not the user message, so it applies to every turn. - Try a different model. Behavior varies, and a model that is over-eager on one task may hold scope better on another.
FAQ
Why does the model expand scope when I never asked it to? Frontier models are tuned to be helpful and to leave code “better than they found it”. With no stated boundary, “helpful” includes fixing things you did not ask about. The expansion is a feature working without a constraint, not a bug — so the fix is to add the constraint.
Is telling it “do not change anything else” enough? It helps, but a single negative instruction is weak against a long context full of fixable-looking code. Pair it with a concrete out-of-scope list (Step 2) and a diff request (Step 4) so over-edits become visible. For agents, back it with a permission rule (Step 6).
My agent edited files I never mentioned. How do I stop that specifically?
That is a permissions problem, not a prompt problem. In Cursor, switch to Edit mode or add the off-limits paths to .cursorignore. In Claude Code, add an Edit(...) deny rule in .claude/settings.json or launch from the narrow subdirectory. In Codex, run --sandbox read-only or workspace-write. The model cannot touch what the tool will not let it write.
How do I scope a multi-step chat without re-pasting everything? Keep a short running “frozen” list and restate it at the top of each step: “Frozen (do not touch): validate_email, send_email. Edit only: parse_headers.” It is a few tokens per step and it stops the boundary from eroding as the conversation grows.
Does a smaller model really obey scope better? Sometimes, but it is task-dependent rather than a rule. Do not switch models as your first move — a clear out-of-scope list plus a diff request fixes most cases on whatever model you are already using.
Prevention
- Default verb: “edit”, “rename”, “replace” — never “improve”, “refactor”, “polish” without scoping.
- Always declare out-of-scope. If nothing is off-limits, say so explicitly.
- Use marked edit zones for content; use a tool-enforced boundary for agents.
- For agent workflows, restrict tool scope mechanically before you start, not after the over-edit.
- Use the
SUGGESTED_FOLLOWUPSpattern: let the model report observations without acting on them. - Audit the diff every time. Do not trust the model’s self-summary of what it changed.
Related reading
- AI rewrote key logic
- AI over-edits light rewrite
- Prompt too broad
- Too many tasks one prompt
- Model fills missing details
Tags: #Troubleshooting #Prompt #Prompt quality #Prompt engineering