fix(tools): retain read-before-edit snapshots across turns#4475
Conversation
|
Thanks @Angel-Hair for taking the time to contribute. This repository is observing a maintainer-managed PR intake gate in dry-run mode, so this pull request is staying open. This note helps maintainers prepare the allowlist before any enforcement is considered. Please read |
…ections After compaction, read_file results were deduplicated into TOOL_RESULT_REF references. The model sees the content and assumes it can edit, but the in-memory file_read_tracker has no record, causing edit_file to reject with 'not been read in this session'. - Exclude read_file from the dedup_eligible predicate so that after compaction, file contents are naturally absent from context - This makes file_read_tracker state consistent with what the model sees, causing the model to re-read files before editing (correct behavior)
5b42e7f to
e6795f7
Compare
Maintainer amendment for PR Hmbown#4475: retain the contributor-reported edit_file failure, but fix its actual lifetime boundary. Tool-result dedup only serializes request history and never skips read_file execution, so preserve that cache-saving contract. Share one FileReadTracker across transient turn contexts, while retaining stale-file rejection and the original contributor commit in history. Signed-off-by: Hunter B <hmbown@gmail.com>
|
Maintainer amendment pushed at The reported failure is real, but wire compaction does not skip The amended PR now:
Local focused gates passed:
Fresh exact-head CI is now running. Thank you for surfacing this — the report led directly to the lifetime fix. |
Summary
After compaction,
edit_filerejects edits on previously-read files with "not been read in this session". The root cause is not inedit_file— it correctly requires a priorread_fileinvocation. The problem is in compaction: it deduplicatesread_fileresults into<TOOL_RESULT_REF>references, telling the model "the content is still available", but the in-memoryfile_read_trackeris not updated. The model sees the content and assumes it can edit, but the tracker sees no record and rejects the edit. The two mechanisms give the model contradictory signals.Root cause
compact_tool_result_for_wireclassifiesread_fileas dedup-eligible and collapses identical large results into<TOOL_RESULT_REF>. The dedup logic saves tokens but skips the tool invocation — sonote_file_read(which populatesfile_read_tracker) is never called. Meanwhile,edit_file'srequire_fresh_file_readchecksfile_read_trackerand rejects when no snapshot is found.Fix
Exclude
read_filefrom the dedup_eligible predicate so that after compaction, file contents are naturally absent from context. This makes the model's context accurately reflect what it can act on: file contents are gone,file_read_trackeris empty, everything is consistent. The model will naturally re-read files before editing.Testing
cargo fmt -- --checkcargo clippy -p codewhale-tui(zero warnings)cargo check -p codewhale-tuicargo test -p codewhale-tui -- client::chat::stream_decoder(34/34 passed)Checklist