NetWatch gains a diagnostic engine: a Diagnose tab that names what is wrong,
ranks the explanations by the checks that separated them, offers a fix, and
closes the issue when its own success condition holds. The chrome is rebuilt to
one panel definition across every tab, and AI Insights becomes a commentary
block inside Diagnose rather than a tab of its own.
Added
-
Diagnose (tab
9) — issue → probable cause → remediation → verified
close. Deterministic; no model involved. Per-metric EWMA baselines with
standard deviation, learned over a minimum of 30 minutes and scoped to a
fingerprint of the network that taught them, so carrying a laptop from a
1.2 ms office resolver to a hotel hotspot doesn't fire every rule at once. A
25-rule catalogue with an explicit suppression graph, so a dead gateway is
one finding with its consequences underneath rather than six. Causes are
ranked by weighted check-pass fraction and shown as a word —strong,
likely,possible— because the number underneath is not a calibrated
probability and92%invites reading it as one; checks that couldn't run
report as not run and count neither way.Remediations are key-bound and reversible, and journal their intent before
they write, so aSIGKILLcan't leave/etc/resolv.confpointing where
NetWatch put it — the next start reverts what a dead process left behind, and
declines if something else has edited the file since.report.mdand
report.jsoncome from the sameVec<Issue>the screen renders; a test
fails if any line quotes a number no evidence field can justify.Four of the 25 rules are declared
Plannedand can never open an issue,
because their inputs don't exist yet (a DNSSEC reference query, per-reply DNS
flags, wireless statistics, a STUN probe), and two more detectors report
their strongest check as not run for the same reason. The header states the
split: a tool that lists 25 rules and evaluates 19 is misreporting its own
coverage. -
A verdict line under the tab bar on every tab, from that same issue list:
what is wrong, since when, what to press. When the baselines aren't learned
yet it says so rather than claiming health it hasn't earned — the dashboard,
Lite and Dense readouts now defer to the engine for the word "nominal". -
--demoreplays a recorded incident through the real engine, rules and
UI. Diagnose has nothing to say on a healthy machine and wants 30 minutes of
baseline first, which makes it impossible to demonstrate honestly otherwise.
Every frame is labelled, remediations touch nothing, and the issue still
closes through the normal verify path.
Changed
- btop-style chrome across the whole tool. Every box now comes from one
widgets::Panel— rounded corners, title inline in the brand accent,
metadata right-aligned in the same border row. There were 48 hand-built
blocks across 15 files agreeing by convention rather than construction, two
already drifted to a different border style on the same screen. Tab bar,
table headers and panel titles move to the tool's lowercase voice; dropping
the tab brackets returns twenty columns and stops the status chips clipping
at 150 columns. - AI Insights is no longer a tab. It renders inside Diagnose as labelled
commentary on findings the engine has already established.insights_enabled
and the other config keys are unchanged; tab9is Diagnose, and a config
naminginsightsas its start tab resolves there. screenshots/is excluded from the published crate, asdocs/media/already
was.
Fixed
pid:0owned megabytes of traffic on Connections, Processes and Egress.
PID 0 is the kernel swapper; this was what the label printed when attribution
returnedNone, so "644 MB owned by pid:0" meant 644 MB unattributed — and
the invented process sent an investigation hunting the sandbox for a bug that
was in a format string. Unattributed traffic now says so; a known PID whose
commcouldn't be read still readspid:<n>.Eexport silently did nothing under the default sandbox. Exports went
to$HOME, which the Landlock policy makes read-only, so every one failed
withPermission denied— indistinguishable, with no confirmation on screen,
from one that worked. They now land in the working directory the sandbox
grants, and the path is shown.- The five KPI sparklines covered different spans at identical width.
Gateway, DNS and loss are sampled once per health probe; throughput once per
refresh tick. All drew "the last N samples", so at five ticks per probe the
latency tiles showed five minutes beside a throughput tile showing one, in a
row meant to be read across. Every tile is resampled onto one window first. - Latency sparklines rendered flat, in both directions. RTT was rounded to
whole milliseconds, so a 0.5 ms resolver collapsed to 0 or 1 and any non-zero
sample drew full height; and the ceiling was a rawmax(), so one 200 ms
excursion against a 2 ms baseline scaled everything else to the floor. RTT
now plots in microseconds against a 95th-percentile ceiling with headroom
above the median. - The Connections state column truncated
ESTABLISHEDtoESTABLI…, which
is not a state anyone can look up. States now have short names that fit whole
—estab,time-wait,close-wait— and a mixed group drops the
denominator rather than clipping the word. - The Timeline's "now" cursor overwrote the newest sample it pointed at,
painting a│one column in from the panel border so it read as doubled
chrome. It tints the cells already there, which is what the "cyan = now"
legend always claimed. - The footer advertised
1-8:Taband--helpsaid1-7 Switch tabswhile the
bar drew ten tabs.
Install: cargo install netwatch-tui, brew install netwatch, or a binary below.
Full Changelog: v0.29.2...v0.30.0