Repository navigation
fix(watch): an arriving directory re-decides the worktrees beneath it - #703
Merged
Merged
Conversation
…neath it PLAN-558, the residual of #700's review: a worktree verdict cached at X/wt survived X being removed and an ordinary tree arriving whole at X (a mv), and so did a stale bookkeeping record for X/wt — the arrival's expansion then treated the ordinary wt as a worktree and its edits were silenced. A Create or Rename of a directory now drops the worktree verdicts beneath it and supersedes the records beneath it; a real worktree inside the arriving tree still verifies as one. Worktree and ordinary verdicts are kept in separate sets so that scan stays over the few worktrees, and a full worktree set drops only directories that no longer exist. Co-Authored-By: Claude Opus 5.5 <[email protected]>
… a stale ordinary verdict Co-Authored-By: Claude Opus 5.5 <[email protected]>
…es the worktrees beneath it Co-Authored-By: Claude Opus 5.5 <[email protected]>
…nt directory stands Review of #703 (BLOCKING): inotify reports a directory moving AWAY as Remove|Rename, and one moved away and back is the same directory; treating either as an arrival dropped the worktree verdicts beneath it and superseded their records, so the rest of a removal leaked (thousands of events measured on Linux; main leaked none). Now nothing happens unless a directory stands at the path, and a belief at or beneath it is dropped only where its directory still exists and is not the one the belief was formed for (dev+inode, taken when the verdict or record was formed). A directory being removed keeps its belief. Known residual: a directory recreated with a reused inode looks unchanged. Also: arrived() no longer re-remembers a cached worktree. The Linux-image control: the new real-backend rename-away-and-back test fails 7/10 on the previous head and passes 10/10 here. Co-Authored-By: Claude Opus 5.5 <[email protected]>
… to lean on Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
#703's Linux CI failed TestWatcher_AnOrdinaryTreeMovedOverAWorktreesParentIsWatched: on ext4 the tree made right after `rm -rf` reused the freed inodes, so the moved-in ordinary wt read as the old worktree (device + inode alike) and its edits were silenced. The container gate's overlayfs hands out fresh inodes, which hid it. dirID now adds the birth time where the platform reports one (statx STATX_BTIME on Linux, Birthtimespec on darwin); elsewhere it falls back to os.SameFile. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
…the filesystem records; a gone worktree keeps its verdict through an arrival Review of #703: the reused-inode test skipped exactly when dirID's birth time went missing, so a broken statDir or darwin birthTime survived it. It now skips only where the platform genuinely records no birth time (platformRecordsBirth, checked independently). Co-Authored-By: Claude Opus 5.5 <[email protected]>
golimpio
approved these changes
Oct 16, 2026
atlas-from-plumb
added a commit
that referenced
this pull request
Oct 16, 2026
An arriving directory re-decides the worktrees beneath it (#703). Co-authored-by: Claude Opus 5.5 <[email protected]>
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.
What
PLAN-558, the residual of #700's review. The watcher's worktree skip (
internal/fswatch/worktrees.go) cached a "worktree" verdict atX/wt, and that verdict outlivedX. So did a stale git record forX/wt. RemoveX, then move an ordinary tree into its place (mv), and the arrival's expansion treated the ordinarywtas a worktree, silencing every edit inside it.arrivalLocked). An event at P is an arrival only if a directory now stands at P. A worktree verdict or record at or beneath P is dropped (or superseded) only where its directory still exists and is a different one (dev+inode, taken when the belief was formed).dirID: device, inode and birth time (statxSTATX_BTIMEon Linux,Birthtimespecon darwin;os.SameFilealone elsewhere). Linux CI caught inode reuse: on ext4 a tree made right afterrm -rfreuses the freed inodes, which the container's overlayfs hid. The birth time tells a reused inode apart.worktreeandordinarysets, so the arrival scan covers only the few worktrees. A directory that becomes a worktree loses its stale ordinary verdict. A full worktree set drops only the directories that no longer exist.Verification
mv'd over a worktree's parent is watched. Rename away and back, thenrm -rf, stays quiet: in the gate's Linux image it fails 7/10 on the previous head and passes 10/10 here. The whole fswatch package passes 10/10 under-racein that image.replacedLocked's gone-keeps rule makes redundant, and the re-remember guard, which is perf-only).Closes PLAN-558 (ops board).
🤖 Generated with Claude Code