fix(udpscope): reconstruct lost accumulated bursts from the packet counter

Review found the decoder was estimating something the wire states exactly.
FrameView::counter increments once per update, so a gap of g means g-1 lost
datagrams; reinstating their duration restores the hole precisely, with no
threshold and no dependence on arrival time. The arrival-anchor comparison
survives only as a backstop for what the counter cannot express — a producer
restart, a counter stuck at zero, a wrong declared rate — and can no longer
step a signal's timestamps backwards, which the ring and trigger forbid.

Also from review: guard the time-signal lookup against a frame carrying more
signals than the installed table, and give FrameBuilder a counter parameter.
Leaving it at zero had hidden the counter rules from every test, and made the
hrt-gap test vacuous — under uniform arrivals the hrt path and packetBurst
agree by construction, so it could not tell which branch answered. Its
arrivals now carry zero-mean jitter.

Each new assertion was proven non-vacuous by sabotage: dropping the gap term,
the backward guard, or the hrt branch fails exactly its own test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino Ferrari
2026-08-27 20:16:52 +02:00
co-authored by Claude Opus 4.6
parent 892e3eae28
commit 7102412a9f
4 changed files with 186 additions and 78 deletions
+5 -6
View File
@@ -54,12 +54,11 @@ private:
bool lastAccValid = false;
uint32_t prevAccCount = 0;
/** For accumulated scalars with a declared sampling rate: end timestamp
* of the most recently emitted burst. The next burst is PREDICTED to
* start one sample period after it — immune to arrival-time jitter
* but the prediction is discarded when arrival time disagrees with it
* by more than a delivery backlog can explain, so packet loss cannot
* displace the trace permanently. */
double lastEmittedEnd = 0.0;
* of the most recently emitted burst, and the packet counter it came
* from. The next burst is chained onto that end, with the counter gap
* reinstating the exact duration of any lost datagrams. */
double lastEmittedEnd = 0.0;
uint32_t lastCounter = 0u;
bool lastEmittedValid = false;
};