Skip to content

Keep polling after watched files are deleted - #17

Merged
pasunboneleve merged 3 commits into
mainfrom
fix/3cqj-watched-file-deletion
Sep 2, 2026
Merged

Keep polling after watched files are deleted#17
pasunboneleve merged 3 commits into
mainfrom
fix/3cqj-watched-file-deletion

Conversation

@pasunboneleve

Copy link
Copy Markdown
Owner

Summary

  • keep polling sessions alive when a configured file is deleted and recreated
  • keep native, pathless, registered-root, and configured-target watcher failures fatal
  • add deterministic process-level deletion/recreation coverage and document the boundary
  • prepare patch release 0.10.5

Validation

  • cargo fmt --check
  • cargo test — 174 main-unit tests plus all integration suites passed
  • cargo clippy --all-targets --all-features -- -D warnings
  • RUST_LOG=info bash scripts/ci-smoke.sh
  • target/debug/devloop --versiondevloop 0.10.5
  • bash scripts/release-notes-from-changelog.sh 0.10.5 pasunboneleve/devloop

Review

  • Roborev 248: two medium findings fixed
  • Roborev 249: one medium verification finding fixed; no third review submitted

Kata: 3cqj

Context:
The polling backend registered literal files as scan roots. Deleting one made
notify report a missing scan root on every poll, and the runtime propagated the
first report as a fatal watcher error.

Decision:
Register the immediate parent for polled literal files, and treat only
PathNotFound and IO NotFound watcher reports as transient. Keep other watcher
errors fatal. Exercise deletion, continued supervision, recreation, and a later
workflow in one process-level regression test.

Alternatives considered:
Ignoring every watcher error would keep the loop alive, but it would conceal
permission failures and broken watcher backends. Ignoring NotFound without
changing registration would also leave the deleted file as a noisy scan root.

Tradeoffs:
Polling a parent can inspect unrelated siblings, but event classification still
runs workflows only for configured paths. The parent registration removes the
permanent missing-root condition and preserves recreation events.

Architectural impact:
The watcher adapter now owns recovery for transient filesystem disappearance;
the runtime still fails on non-transient watcher faults. This is a SemVer patch
fix recorded under Unreleased; this commit does not bump the package version or
create a dated release section.
Context:
Parent-directory polling keeps deleted literal files observable, but a broad
missing-path exception could hide permanent native-watch loss, and scanning a
parent could make an unrelated sibling's failure fatal.

Decision:
Limit transient missing-path recovery to the polling backend. Ignore a polling
error only when every reported path is disjoint from configured watch targets;
keep target, parent, pathless, and native watcher errors fatal.

Alternatives considered:
Treating every NotFound report as recoverable was simpler but unsafe for native
registrations. Treating every parent-scan error as fatal coupled configured
files to unrelated siblings introduced by the adapter's broader scan root.

Tradeoffs:
The overlap test depends on notify supplying paths for sibling-specific errors.
Pathless errors remain fatal because devloop cannot prove that they are safe.

Architectural impact:
Recovery now follows the watcher backend and configured-target boundary. The
runtime remains strict whenever the adapter cannot demonstrate that an error is
both polling-specific and outside the user's watch surface. Changelog release
mode moves the fix into 0.10.5 and aligns Cargo.toml, Cargo.lock, release-note
input, and intended tag v0.10.5.
Context:
The polling recovery guard accepted every NotFound report before checking its
path. A pathless error or missing registered parent could therefore leave the
runtime alive without an effective watcher.

Decision:
Recover only when notify reports configured literal files or disappearing
children beneath recursive targets. Keep pathless reports, recursive target
roots, parent registration roots, and native watcher errors fatal.

Alternatives considered:
Applying the existing overlap test after the NotFound guard would still treat a
configured recursive root as transient. The dedicated target-shape predicate
distinguishes recoverable children from registration roots explicitly.

Tradeoffs:
Recovery requires notify to report the affected path. Pathless errors fail the
session because devloop cannot prove that observation can continue safely.

Architectural impact:
The polling adapter's recovery contract now matches its documented boundary:
leaf disappearance is recoverable, while loss of the observation root is not.
The 0.10.5 version and dated changelog remain consistent.
@pasunboneleve
pasunboneleve merged commit cb67a67 into main Sep 2, 2026
2 checks passed
@pasunboneleve
pasunboneleve deleted the fix/3cqj-watched-file-deletion branch September 2, 2026 01:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant