Added comprehensive tests in `tests/test_watch.py` to cover the `render_dashboard` function from `src/netsleuth/watch.py`.
Included tests for:
- Empty sessions
- Sessions populated with valid ping results
- Error states with missing data (e.g., 100% loss) ensuring dashes ("—") render properly
- Dashboard captions for speed test results
Improved test coverage for `netsleuth.watch`.
Co-authored-by: Horizontal42 <75383519+Horizontal42@users.noreply.github.com>
Filenames only carry a time-of-day now (report_<asn>_HH-MM-SSZ)
since the date lives in the directory path; history lookups walk
the tree with rglob and sort by full path instead of basename,
since the basename alone no longer encodes recency across days.
watch.py never imported interpret and had no notion of a verdict at all -
summarize_cycle() now runs the same latency_findings/speed_findings/
overall_verdict pipeline the one-shot report uses, so every tick carries
status/score/finding_ids and the dashboard caption shows a verdict line.
Real improvement on its own, independent of whether a webhook exists.
New alerting.py carries the whole notification contract as pure functions:
should_fire() only fires on an actual transition, into a state the user
opted into via watch.webhook_on, debounced by
watch.webhook_min_interval_seconds (floored at 30 in a validator) so a
flapping link can't spam an endpoint every tick. Recovery is its own
opt-in "recovered" token, separate from configuring "crit", since wanting
outage alerts doesn't imply wanting a second ping when they clear.
build_payload() is flat JSON, not shaped for Slack/Discord - that's the
receiver's problem. post_webhook() swallows every failure and returns a
bool; a dead endpoint must never interrupt the loop watching it.
New --webhook URL flag overrides watch.webhook_url per run.
Verified the tick sequence end-to-end outside the Rich Live loop -
sending real OS signals to test --watch's Ctrl-C handling in this shell
wasn't reliable, so exercised should_fire/build_payload/render_dashboard/
to_report in the same order run_watch calls them.
Part of plans/zesty-zooming-wilkinson.md (gitignored).