Supervise the collectors and bound the ways they hang !16

merged merged by cmc on 2026-09-04 15:56 UTC · krz/ambient-companions:feat/supervisor into main

cmc

Third of the v1.0 stack. Targets !15.

supervisor.rs owns collector liveness and is the only publisher of CollectorUp.

  • Panics no longer kill the producer thread. Git and terminal calls are wrapped; a panic publishes that source down, the tick continues, the next retries. The terminal collector is replaced with a fresh one, costing one window of rate data.
  • The hardware child is respawned. Backoff 1s doubling to a 60s cap, reset after a run surviving 30s, no retry limit. Never-configured is reported down once and not retried — absent is not failed.
  • run_git has a 10s budget and kills the child. A Rust thread cannot be safely killed, so killing the subprocess is the only way to get the thread back from a held index lock or a vanished network mount.
  • keys_per_min has a floor. Two prompts a millisecond apart extrapolated to a five-figure rate.
  • Signal.ts no longer claims to be monotonic-corrected. It cannot be: it is persisted, retention prunes on it, and CommitsToday means since local midnight.
  • The spool is capped at 1 MiB in the hook, checked with zstat so the prompt does not fork.

Also fixes the git_collector flake noted in NOTES: unique_dir keyed temp dirs by pid and nanoseconds, but tests run in parallel threads of one process, so the pid is shared and the clock is coarser than a nanosecond. Two git inits into one directory failed with "File exists". Reproduced, then fixed with a process-wide counter.

Verified live: killing the collector child respawns it with the logged backoff, and a subscriber sees collector_up as four separate entries — one per source, which is the (name, source, tag) cache key from !14 doing its job.

Closes #10

retargeted from feat/signal-client to main: !15 merged

2026-09-04 15:56 UTC