feat(write-guard): preventive ACI echo of post-format content on a clean write#60
Conversation
…ean write Roadmap #2 (SWE-agent ACI), preventive half. On a CLEAN write whose content the strip/auto-format pass reshaped, the write-guard now echoes the post-format file (numbered, <=80 lines) so the model's next edit anchors on disk reality instead of the now-stale text it wrote — preventing the stale-anchor not-found that #57 only recovers from. No echo when nothing diverged (token-smart) or for large files (a short re-read note instead). Pure reformatEcho() extracted + unit-tested.
There was a problem hiding this comment.
Code Review
This pull request introduces a preventive "ACI echo" mechanism in write-guard.ts to echo the post-format file content back to the model when a clean write is reshaped by auto-formatting. This ensures the model's next edit anchors on the actual disk content rather than a stale copy. Tests are also added to verify this behavior. The review feedback suggests trimming trailing newlines before splitting the file content into lines to avoid generating an extra empty numbered line in the echo output.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Pull request overview
Adds a preventive “ACI echo” path to the write-guard so that when a clean write is subsequently reshaped by strip/auto-format, the tool result can echo the post-format on-disk content (bounded) to keep the model’s next oldString anchor in sync with reality.
Changes:
- On clean writes, compares pre-format vs post-format content and returns a bounded “current content” echo when they diverge.
- Extracts the echo logic into an exported pure helper (
reformatEcho) and adds unit tests for key cases. - Updates borrowed-ideas documentation to record the new behavior.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| packages/core/src/loop/write-guard.ts | Adds reformatEcho, snapshots pre-format content, and returns post-format echo on clean-divergent writes. |
| packages/core/tests/write-guard.test.ts | New unit tests for the preventive echo behavior (no-op / unreadable / divergent echo / large-file note). |
| docs/borrowed-ideas.md | Documents the new preventive echo behavior and its relationship to the earlier corrective fix. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…mini review) A …\n-terminated file produced a phantom empty last line in the numbered echo, which the model could anchor on. Drop the standard trailing newline before split. Test asserts exactly N numbered lines.
Roadmap #2 (SWE-agent ACI) — the preventive half, complementing #57's corrective fix. (Pivoting back from eval-discovery to building the roadmap, as discussed.)
Why
The write-guard auto-formats every write (strip casts + eslint --fix + prettier). On a clean write it returned
""— so the model never saw the post-format result, and its in-context copy went stale. Its next edit then anchored on the text it wrote, not what's on disk →not-found. #57 made that recoverable (carry content on rejection, 1 wasted turn); this makes it not happen in the first place.What
On a clean write whose content the strip/format pass actually changed, the write-guard now echoes the post-format file (numbered lines, ≤80) so the model edits against disk reality:
Token-smart:
Logic extracted into a pure, exported
reformatEcho(file, written, current)and unit-tested.Tests
write-guard: no echo when unchanged / unreadable; numbered post-format content echoed on divergence (with the "anchor on THIS" guidance); large file → re-read note, content not inlined.lsp-write-feedback,execute-tool,editor-e2e,session-e2e,write-policy-p1) stay green.bun run validategreen (1836 tests).