[Windows] Extension host truncates .git/index to 0 bytes on Accept (concurrent read-truncate-write race)

Summary

On Windows, pressing “Accept” causes the VS Code extension host process to
truncate .git/index to 0 bytes. All git commands then fail with
“fatal: .git/index: index file smaller than expected”.

Environment

  • Windows 11, VS Code (stable), extension google.google-antigravity 1.2.0
  • Also installed: charliermarsh.ruff, ms-python.python / pylance / debugpy /
    vscode-python-envs, mechatroner.rainbow-csv, zainchen.json

Reproduction

  1. Ask the agent to create about 4 small text files in a single turn.
  2. Press Accept.
  3. Within ~0.2 s, .git/index becomes 0 bytes.
    Reproduced 2 times out of 6 attempts.
    Creating the same 4 files from PowerShell (outside the IDE) never reproduced
    it (0 out of 6). A window reload also appears to trigger it.

Evidence (Process Monitor, filtered to “.git\index”)

The writer is Code.exe with
–type=utility --utility-sub-type=node.mojom.NodeService
shown as “extension-host” in VS Code’s Process Explorer.

It runs overlapping cycles on .git/index:

CreateFile Generic Read/Write, Disposition: Open
SetEndOfFileInformationFile EndOfFile: 0
WriteFile Offset: 0, Length: 189,440 (normal case)
FlushBuffersFile
CloseFile

When one cycle truncates while another is still reading, the reader gets
END OF FILE and writes back an empty buffer:

SetEndOfFile 0
ReadFile END OF FILE
WriteFile Length: 189,440
SetEndOfFile 0
WriteFile Length: 0 ← empty write
SetEndOfFile 0
WriteFile Length: 189,440

If the empty write happens last, the file stays at 0 bytes.
One capture recorded 32 “EndOfFile: 0” events in 8 bursts of 4.

Impact

No data loss - the index is derived and rebuilt with
“rm -f .git/index && git reset” (about 10 seconds).
But it happened roughly 10 times in a single working day, and every git
command fails until recovery.

Request

Should an extension read and write .git/index directly at all?
If a snapshot or checkpoint feature needs it, please make the write atomic
(write to a temporary file, then rename) or exclude .git entirely.

Note on attribution

I cannot prove which extension performs the write, because all extensions
share one extension host process. What I can show is that the Accept flow
is a trigger I could reproduce, and that writes outside the IDE are not.

Workaround under test

Adding “files.watcherExclude”: { “/.git/”: true } to workspace settings.