UDP TUI clarity. Two issues from real users — @brettowe (#70) and @pythonwood (#72) — pointed at the same weakness: the running TUI was confusing about what its UDP numbers meant. This release rewires the live data path so the values you see during a test match what the test actually saw.
Fixed
- Live UDP packet-loss counter during the run (#70) — the Packet Loss line was stuck at 0.0% for the entire test and only updated to the real value at completion. With
-t 0(infinite mode) the real value was never visible. Server now ships cumulativeUdpIntervalProgress { packets_received, packets_lost }on every Interval message; client derives the percent locally and the TUI updates it live. Reported by @brettowe. - Final UDP loss accounting only counts valid xfr packets —
UdpStats.packets_receivedandpackets_sentnow exclude short, malformed, or foreign datagrams that can't be header-decoded. Previously such datagrams inflatedpackets_receivedand silently understated the final loss percent.
Added
- Throughput sparkline tints by per-interval loss severity (#70) — clean intervals stay the graph color, light loss (<1% per-interval rate) tints warning, heavy loss (≥1%) tints error. A single-packet hiccup and a heavy drop burst no longer collapse to the same flat tint. Magnitude unknown stays the graph color — honest "no signal."
- Freshness signal for the Packet Loss line — renders dimmed
--%when paired against a pre-0.9.11 server or before any UDP traffic has been observed, so unknown is visually distinct from a fresh0.0%reading.
Changed
- Jitter rolling-window label (#72) — the running display now reads
Jitter: 0.86 ms (10s avg: 0.03 ms). The previous(10s: …)form read like a stuck timer; @pythonwood opened an issue thinking the display was broken on a v0.9.10-client → v0.9.6-server pairing.
Wire-protocol note
AggregateInterval gains an optional udp_progress field (raw counts, not a derived percent — the client owns the math). Cross-version compatibility preserved with serde(default, skip_serializing_if = "Option::is_none"). Verified for both 0.9.10 ↔ 0.9.11 directions in tests; pythonwood's mismatched-version pairing in #72 is a deliberate compat target.
Full changelog: v0.9.10...v0.9.11