Repository navigation
feat(files): report files that change under the agent; refuse stale rewrites - #223
Merged
Merged
Conversation
…ewrites FileLedger keeps track of the files the agent has read or written with the file tools (size, time and hash). Before and after each tool call, a file that changed is named in that tool's result: changed outside fuseraft, or while the tool ran. In the REPL, changes made while the agent waited are noted after the user's message. Names only: the agent re-reads what it needs, so long-line files can't flood the context. write_file on a file that changed since the agent last saw it is refused until it reads the file again. In orchestration, a file a tool changed this way counts as written or deleted in the change log. files.trackedFiles (a new `files` section, default 50, shared by the REPL and fuseraft run) sets how many recent files are tracked; 0 turns tracking off, which matters on network shares.
A file's modified time moves in clock ticks (about 15 ms on Windows), so a same-size edit right after the read kept the size and time the check had recorded, and the change was missed. Windows CI caught it. A time from the last 2 seconds is no longer trusted: until it's older, the file is compared by content.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An agent works from the copy of a file it last read, but the file can change under it: a shell command it ran (
sed, a formatter), the user's editor, or another process. This change tells the agent when that happens, and stops it from rewriting a file from an out-of-date copy. It replaces #221 (closed) and leaves out that PR's secret masking.Change notices
FileLedgerkeeps track of the files the agent has read or written with the file tools. For each file it stores the size, the time and a hash, and no content. Before and after every tool call, the tracked files are checked, and a changed file is named in that tool's result:read_file, so a file with long lines (JSONL, minified code) can't flood the context./clear,/switch,/resumeand a newservetask forget the tracked files.A file's modified time moves in clock ticks (about 15 ms on Windows), so a same-size edit made right after a read can leave the size and time unchanged. A time from the last 2 seconds isn't trusted: until it's older, the file is compared by content. Windows CI caught this.
Stale rewrites are refused
write_fileon a file that changed since the agent last read or wrote it fails withWRITE BLOCKED, because content built from the old copy would undo the change. Reading the file again lifts the block.patch_filestill works, because it matches the file as it is now.Orchestration
A file a tool changed without naming it (a
sedthroughshell_run) is recorded inFilesWritten/FilesDeletedin the change log.RequireAllFilesWrittenand the other validators that read the log now see it like awrite_file.files.trackedFilesEach tracked file costs one lookup before and after every tool call, and on a network share each lookup is a round trip.
fuseraft settings set files.trackedFiles <0–5000>sets how many of the most recently seen files are tracked. The default is 50, and0turns tracking off, along with the notices and the stale-write refusal. The setting is in a newfilessection because it applies to both the REPL andfuseraft run.settings showlists it under "Files", and the VS Code and web settings panels get it from the catalog.Live check (Claude Sonnet 5.5, JSON bridge)
config.txtbetween two messages. The note after the next message named the file, and the model re-read it before answering.sed -ion a file it had read. Theshell_runresult named the file.write_filewithout re-reading was refused withWRITE BLOCKED, and the file was left as it was.files.trackedFilesset to 0, no notices appeared anywhere in the session.Tests
New test files:
FileLedgerTests,FileChangeNoticeTests,AgentMiddlewareBuilderChangeReportingTestsandFileSystemPluginStaleWriteTests.ChangeTrackerTestsgains cases for tool-changed files in the change log.