fix(watch): preserve final rapid-write state#78
Conversation
Co-Authored-By: GPT-5.6 Sol <codex@openai.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
JordanCoin
left a comment
There was a problem hiding this comment.
Thanks for this — confirmed the bug is real: the debouncer is leading-edge only with no trailing flush, so the final write of a rapid burst could be dropped while the cached graph state still described an earlier file state. The fix is correct, locking is right (RLock on graph.mu, single-goroutine event loop), error paths fail open in the safe direction, and it composes correctly with the temp-file churn filtering since isTransientFile runs before shouldSkipEvent. Full suite passes with -race, and the new test genuinely exercises all three branches of the new logic.
Two non-blocking thoughts for a follow-up (not asking for changes here):
- Same-size content changes are still dropped —
FileStateonly stores Lines+Size, so a burst whose final write leaves size unchanged (e.g.s/foo/bar/) still loses its last event. Not a regression (main drops it too), but storing ModTime inFileStateand comparing it would close the hole cheaply. - This effectively turns "skip writes within 100ms" into "skip writes within 100ms whose size hasn't changed" — a file being written in chunks now runs full
handleEventper event (countLines + agit diffsubprocess + writeState), which is the burst load the debouncer exists to absorb. A trailing-edge flush timer would preserve both coalescing and final-state accuracy if this ever shows up in profiles.
Minor: checking the State cache before os.Stat would save a syscall for untracked/gitignored paths.
What does this PR do?
Type of change
Checklist
go build && ./codemap .Additional notes
Filesystem watchers can emit multiple write notifications for one logical save. Time-based debouncing alone could discard the final notification while the cached graph still described an earlier file state. The debounce decision now checks the current file size against the cached state before skipping a rapid write.
Focused debounce/daemon tests pass with the full race suite, formatting,
module verification, vet, staticcheck, and a debug build/smoke run.
Reviewer setup:
Developed with carefully directed, manually reviewed AI assistance.
Allow edits by maintainersis enabled, so maintainers are welcome to fix wording or make minor cleanup directly; broader review feedback will be incorporated.Co-Authored-By: GPT-5.6 Sol codex@openai.com