Summary
Sometimes when I open a chat session, VS Code silently restores stale agent-edit content into open files, marking them dirty. If the file has been modified since the chat last persisted its state, saving the now-dirtied buffer will overwrite those newer changes — i.e. silent data loss. This happens even for files edited entirely inside VS Code.
Steps to reproduce
- In a chat, have the agent edit a file. Call this content S1. Don't Keep/Undo.
- Close the chat.
- Reload VS Code.
- Edit the file (in VS Code) and save it. Call this content S2.
- Reload VS Code again.
- Open the chat.
- The file's editor buffer is replaced with S1 and marked dirty. Saving (or autosave) overwrites S2 on disk with S1 — the user's edits from step 4 are lost.
Root cause
ChatEditingSession.storeState() persists every entry whose state is Modified on shutdown (chatEditingServiceImpl.ts, the onWillSaveState block).
On reopen, _init → _initEntries in chatEditingSession.ts restores them:
const restoreToDisk = snapshotEntry.state === ModifiedFileEntryState.Modified;
await entry.restoreFromSnapshot(snapshotEntry, restoreToDisk);
restoreFromSnapshot in chatEditingModifiedDocumentEntry.ts then calls:
await this._textModelChangeService.resetDocumentValues(snapshot.original, snapshot.current);
…which in resetDocumentValues (chatEditingTextModelChangeService.ts) unconditionally rewrites the freshly disk-loaded model with snapshot.current whenever it differs from the current buffer — marking the buffer dirty. There is no check against the actual on-disk content, and no detection that the file changed since the snapshot was taken.
This dirties the buffer (and risks data loss on save) when:
- The file was edited and saved inside VS Code while the chat was closed.
- The file was edited outside VS Code, by another tool, or via file sync.
- EOL / BOM / final-newline differences exist between disk and snapshot → buffer dirtied with semantically identical content.
- The session was persisted with
state === Modified even though the user had moved on.
Expected behavior
Opening a chat session must not silently dirty editor buffers, and must never put a buffer in a state where saving would overwrite newer on-disk content. Restoring pending agent edits should either:
- be a no-op when on-disk content already matches the snapshot (modulo EOL/BOM),
- detect that the file changed since the snapshot was taken (mtime/hash) and skip the restore (or prompt),
- keep only the diff baseline and require the user to explicitly replay/keep/undo, instead of writing back to the modified buffer on session open.
Affected code
src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingSession.ts (_initEntries, around the restoreToDisk decision)
src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingModifiedDocumentEntry.ts (restoreFromSnapshot)
src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingTextModelChangeService.ts (resetDocumentValues)
src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingServiceImpl.ts (onWillSaveState persistence)
cc @jrieken @roblourens
Summary
Sometimes when I open a chat session, VS Code silently restores stale agent-edit content into open files, marking them dirty. If the file has been modified since the chat last persisted its state, saving the now-dirtied buffer will overwrite those newer changes — i.e. silent data loss. This happens even for files edited entirely inside VS Code.
Steps to reproduce
Root cause
ChatEditingSession.storeState()persists every entry whose state isModifiedon shutdown (chatEditingServiceImpl.ts, theonWillSaveStateblock).On reopen,
_init→_initEntriesinchatEditingSession.tsrestores them:restoreFromSnapshotinchatEditingModifiedDocumentEntry.tsthen calls:…which in
resetDocumentValues(chatEditingTextModelChangeService.ts) unconditionally rewrites the freshly disk-loaded model withsnapshot.currentwhenever it differs from the current buffer — marking the buffer dirty. There is no check against the actual on-disk content, and no detection that the file changed since the snapshot was taken.This dirties the buffer (and risks data loss on save) when:
state === Modifiedeven though the user had moved on.Expected behavior
Opening a chat session must not silently dirty editor buffers, and must never put a buffer in a state where saving would overwrite newer on-disk content. Restoring pending agent edits should either:
Affected code
src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingSession.ts(_initEntries, around therestoreToDiskdecision)src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingModifiedDocumentEntry.ts(restoreFromSnapshot)src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingTextModelChangeService.ts(resetDocumentValues)src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingServiceImpl.ts(onWillSaveStatepersistence)cc @jrieken @roblourens