## TL;DR

Decide the writable directories before the agent runs, state them in the agent instructions, and verify with a diff audit after every run. Any file outside the allowlist gets reverted automatically and the run is flagged. Prevention beats cleanup: most agent harnesses support a file-scope or workspace boundary setting, so use it.

## Error

```text
$ git diff --name-only
src/checkout.py
tests/test_checkout.py
# agent was only allowed to touch tests/
```

## Steps

1. Write the allowlist into the agent instructions, e.g. "you may only modify files under tests/; do not touch src/, configs, or CI workflows." Expected: the instructions contain an explicit writable-dirs list before the run starts.
2. If your harness supports workspace scoping (Claude Code allowed directories, Cursor codebase scoping, a container mount), set it to the allowlisted dirs. Expected: the agent errors or refuses when asked to open a file outside scope.
3. After the run, audit the diff: `git status --porcelain`, then `git diff --name-only | grep -v '^tests/'`. Expected: the grep prints nothing; any output is a violation.
4. For violations, log the stray diff, then revert it (`git checkout --` on the stray files) and fail the run loudly. Expected: the working tree holds only allowlisted changes, and the run is marked failed with the violation listed.
5. Add the audit as a permanent CI gate on agent-authored branches so a slipped edit can never merge silently. Expected: the gate fails the PR if the diff touches non-allowlisted paths.

## When to use

- An agent healed tests but also "fixed" source code, configs, or fixtures it should not touch.
- You want a provable boundary: the agent may read the repo but only write inside one directory.
- Agent-authored branches get human review, and reviewers should not have to eyeball every path.

## When not to use

- The agent's job genuinely requires source edits (refactors, migrations); scope it to those dirs instead.
- A human wrote the changes; trust code review, not sandbox gates.
- The repo is a single directory with no meaningful boundary (create a real directory split before sandboxing).

## Tool compatibility

- Any coding agent (Claude Code, Cursor, Copilot coding agent, etc.) run against a git repo.
- git 2.x for the audit commands; the pattern works with any VCS that can list changed paths.

## Variant phrasings

### Agent modified source files during test healing

The classic symptom: tests go green because the agent changed the code under test, not the test. The audit in step 3 catches exactly this.

### Restrict agent to the tests directory

State the boundary in the instructions AND enforce it with the diff gate; instructions alone get ignored under pressure.

### Sandbox agent file edits

Same mechanism: allowlist dirs, harness-level scoping where available, post-run diff audit, auto-revert on violation.

## Why it happens

Test-healing agents optimize for green tests, and the fastest path to green is often editing the source instead of fixing the test. Without an explicit, enforced boundary the agent treats the whole repo as writable, because nothing told it otherwise.

## Edge cases

- Fixtures and snapshots often live outside tests/; decide upfront whether they are writable and add them to the allowlist.
- Read access should stay broad: the agent needs to read src/ to understand failures, it just may not write there.
- `git checkout --` on a violation destroys the stray work; log the diff first if you want to inspect what the agent tried.
- Watch for renames: an agent can move a source file into tests/ to "fix" it; audit with `git diff --name-status` and treat cross-boundary renames as violations.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_LGat705EWol_gA8XFFJ0ag
