Both the shell collector and the working-tree collector handed the watcher
their root directory, because that is what the port asked for. Rooted at
$HOME and ~/git, that asks the kernel for one inotify watch descriptor per
directory the user owns: 342 MB resident on this machine, plus a permanent
stream of permission denials from podman volume storage.
Neither watch bought anything. The shell history files that matter sit
directly in $HOME, and working trees are swept periodically precisely
because walking them is expensive — so every event they raised was
discarded.
watch_roots now returns WatchRoot { path, recursive }. A Periodic collector
registers no watch at all; the shell collector watches $HOME shallowly.
342 MB -> 49 MB, and the denials are gone. A test pins the policy, since the
regression is invisible in any fixture small enough to be a unit test.
Also moves StartLimitIntervalSec/StartLimitBurst to [Unit], where systemd
actually reads them — `systemd-analyze --user verify` was warning that it
was ignoring them in [Service].
Verified live: installed to ~/.local/bin, enabled as a systemd --user unit,
baseline swept 60849 sources / 977 MB, and a synthetic spill produced a
desktop notification.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XAqHWfdMAsYu1o36tgeima