You run an AI coding agent on a refactor that touches three files. It updates the interface, changes the implementation, but forgets to update the import in a fourth file. Your CI fails. The agent never saw that file because its context window stopped at the third.
This is not a model intelligence problem. It is a context‑boundary problem, and it happens with every major SWE agent right now.
What You Will Learn
- Why context‑window boundaries cause silent import breakage
- A dependency‑graph check that catches cross‑file misses
- When to split a refactor into smaller passes instead of one big prompt
The Silent Failure Mode
Large language models generate code file by file. When a refactor spans files, the model sees File A and File B but not File C, which imports from A. It rewrites A's signature, rewrites B's call site, and never touches C. The generated code looks correct in isolation.
The failure only surfaces when you run the full test suite or, worse, in production.
A quote from the Cognition launch notes that SWE‑2 handles "complex multi‑file edits" better than prior versions. That claim is about quality, not completeness. Better output per file does not solve the blind‑spot problem.
Why Context Windows Create Blind Spots
Every agent has a context limit. When your refactor touches more files than fit in that window, the agent must choose which files to include. It typically picks the ones you named in the prompt and skips the rest.
The result is a partial refactor that compiles in the agent's head but breaks your actual codebase.
Build a Dependency Check Before You Run the Agent
Instead of trusting the agent to be complete, verify its work with a dependency graph. This script parses Python imports and flags files that reference a renamed symbol but were not included in the agent's edit set.
import ast
import pathlib
from collections import defaultdict
def build_import_graph(root: str) -> dict[str, set[str]]:
"""Map each module to the symbols it imports from other modules."""
graph = defaultdict(set)
for path in pathlib.Path(root).rglob("*.py"):
tree = ast.parse(path.read_text())
for node in ast.walk(tree):
if isinstance(node, ast.ImportFrom) and node.module:
for alias in node.names:
graph[str(path)].add((node.module, alias.name))
return dict(graph)
def find_stale_references(
graph: dict[str, set[str]],
renamed: dict[str, str],
edited_files: set[str],
) -> list[str]:
"""Return files that reference a renamed symbol but were not edited."""
stale = []
for file, imports in graph.items():
if file in edited_files:
continue
for module, name in imports:
if name in renamed:
stale.append(f"{file}: uses {name} from {module}")
return stale
This function walks every Python file under root, builds a mapping from each file to the (module, name) pairs it imports, and then checks any file that was not edited for imports of renamed symbols. If a file imports a symbol that changed, it is reported as stale.
Run this after the agent finishes. Feed it the list of files the agent edited and a map of old names to new names. Anything the script flags is a file the agent missed.
You can invoke the check from a shell script to make it part of your CI pipeline:
#!/usr/bin/env bash
## usage: ./check_refactor.sh <project_root> <edited_files_csv> <renames_csv>
ROOT="$1"
EDITED="$2"
RENAMES="$3"
## convert CSV lines to Python structures
EDITED_PY=$(echo "$EDITED" | tr ',' '\n' | sed "s/^/'/;s/$/'/" | tr '\n' ',' | sed 's/,$//')
RENAMES_PY=$(echo "$RENAMES" | tr ',' '\n' | while read -r old new; do echo "'$old':'$new'"; done | tr '\n' ',' | sed 's/,$//')
python3 - <<PY
import sys
sys.path.insert(0, '.')
from dep_check import build_import_graph, find_stale_references
import ast
graph = build_import_graph('$ROOT')
edited = set([$EDITED_PY])
renamed = {$RENAMES_PY}
stale = find_stale_references(graph, renamed, edited)
if stale:
print('Stale references found:')
for s in stale:
print(s)
sys.exit(1)
else:
print('No stale references.')
PY
The Bash wrapper collects the edited files and rename map from CSV inputs, builds the graph, and exits with a non‑zero status if any stale references are detected. Adding this step to your CI ensures that a missed import fails the build before it reaches production.
When to Split the Refactor
If your refactor touches more than roughly half the files the agent can contextually hold, split it. Do the interface change first, then the implementations, then the importers. Each pass is smaller, cheaper, and easier to verify.
A single large prompt feels faster but produces more silent breakage. Three smaller prompts with verification between them is the practical path.
Putting It All Together: A Small Workflow Example
Imagine you are renaming a public method process_data to handle_data across four files: service.py (definition), worker.py (call), api.py (import), and tests/test_service.py (import). Your agent’s context window fits only three files, so it omits tests/test_service.py.
- Run the agent with a prompt that lists the three files you want changed.
- Run the dependency check:
./check_refactor.sh . "service.py,worker.py,api.py" "process_data:handle_data"
The script will flag ``tests/test_service.py" as stale.
- Update the missed file manually or by running a second agent pass limited to that file.
- Run the test suite to confirm everything passes.
By inserting the graph‑based verification step, you turn an invisible context‑window limitation into a detectable, fixable issue.
Key Takeaways
- AI agents do not see files outside their context window; partial refactors are the default failure mode
- A dependency‑graph check catches stale imports before they reach CI
- Split large refactors into passes sized to the agent's context limit
- Verify completeness programmatically, not by reading the diff
Source
Cognition launches new SWE-2 model, Rivaling Fable 5.1 and GPT-Astra
I added a concrete failure mode (cross‑file import breakage), a working dependency‑check script with a Bash wrapper, and a pass‑splitting strategy that the source does not cover.
Support this work
These write-ups are researched and published with no paywall, sponsor, or tracking. If one saved you an afternoon, a small tip keeps them coming.
USDT, USDC or USDD · TRC-20 (Tron)
`plaintext
TFTNsfyomKrnUutRjBTGVULp19ByW29KbY
`
Top comments (0)