What happened?
On Linux (chokidar backend), two directory-lifecycle sequences leave the tree unobserved until the next reload. Both reproduce identically before and after #1076, so they are pre-existing.
- Deleting the watched root itself (e.g.
rm -rf the repo checkout dir and recreate it, or a tool that replaces the directory atomically). After the root is recreated, file changes under it produce no events. Reproduced with a 100 ms gap between delete and recreate.
- Recreating a directory within ~1 ms of deleting it (
rm -rf dir && mkdir -p dir/sub in one shell command; some build tools do this). Subsequent writes under it are sometimes not observed. Gaps of ≥10 ms recover reliably.
Ordinary delete-then-recreate with a realistic gap recovers (covered by observer.fs.test.ts since #1076).
Evidence
Found by an adversarial probe during review of #1076: five cycles each on the previous main (bc76a0bc) and on the batched observer, nested subtree vs root, 0/1/10/100 ms gaps. Probe and log were kept at /tmp/1063-review-churn.{ts,log} on the measurement host; the fixture spec is in test/pty/watch-start-integration.test.ts and scratch-style notes in #1063.
Possible direction
- Root case: the observer anchors a watcher on the root's parent only when the root is missing at startup (
portableTree.ts "missing-root-parent fallback"). Extending that anchor to the steady state — always watch the parent for addDir of the root — would cover the delete-and-recreate case.
- ~1 ms recreate: likely inotify delivering
IN_DELETE_SELF after the new inode already exists, so chokidar drops the path and never re-adds it. A short debounce on unlinkDir that re-stats before invalidating would probably cover it.
Priority: low. The steady-state safety signature check (every few seconds when the observer is healthy) does not run in this state either, so the user sees a stale review until they trigger a manual refresh.
What happened?
On Linux (chokidar backend), two directory-lifecycle sequences leave the tree unobserved until the next reload. Both reproduce identically before and after #1076, so they are pre-existing.
rm -rfthe repo checkout dir and recreate it, or a tool that replaces the directory atomically). After the root is recreated, file changes under it produce no events. Reproduced with a 100 ms gap between delete and recreate.rm -rf dir && mkdir -p dir/subin one shell command; some build tools do this). Subsequent writes under it are sometimes not observed. Gaps of ≥10 ms recover reliably.Ordinary delete-then-recreate with a realistic gap recovers (covered by
observer.fs.test.tssince #1076).Evidence
Found by an adversarial probe during review of #1076: five cycles each on the previous
main(bc76a0bc) and on the batched observer, nested subtree vs root, 0/1/10/100 ms gaps. Probe and log were kept at/tmp/1063-review-churn.{ts,log}on the measurement host; the fixture spec is intest/pty/watch-start-integration.test.tsandscratch-style notes in #1063.Possible direction
portableTree.ts"missing-root-parent fallback"). Extending that anchor to the steady state — always watch the parent foraddDirof the root — would cover the delete-and-recreate case.IN_DELETE_SELFafter the new inode already exists, so chokidar drops the path and never re-adds it. A short debounce onunlinkDirthat re-stats before invalidating would probably cover it.Priority: low. The steady-state safety signature check (every few seconds when the observer is healthy) does not run in this state either, so the user sees a stale review until they trigger a manual refresh.