838f71738ed6858f7838bf5f09b402089c299913
A watch whose poll fails was invisible: `detect` turned the failure into one `eprintln!` per tick and nothing else. A watch that had 401'd every sixty seconds since the day it was created was indistinguishable — on `/v1/watches`, in the agent's own `list_watches`, everywhere — from a repository that had simply been quiet. That is how a dead credential survives for weeks: the log line scrolls, and nothing else remembers. `watch_health` is a third table beside `watches` and `account_watches`, keyed by `(scope, forge, subject)`, holding `last_ok_at`, `last_error`, `last_error_at` and `consecutive_failures`. Every detect pass records each poll's outcome — repo watches as `repo`, account watches as `account` — and the pass that *starts* a streak (the first failure after a success, or after never having succeeded) pushes one device notification, naming the watch and quoting the forge's error. The rest of the streak stays quiet: the row carries the count, so the tick's log line no longer has to. Readable where the question gets asked: `/v1/watches` answers a `health` array alongside the two watch lists, and the `list_watches` tool reports `last_ok_at`, `last_error` and `consecutive_failures` per repo, so "is this watch working?" is answerable without the daemon's stderr. A watch that has never polled has no row and reports empty health, which is what it is.
Languages
Rust
74.9%
Kotlin
13.8%
Vue
7.1%
TypeScript
3%
Dockerfile
0.5%
Other
0.6%