Skip to content

Anchor-pair audit fires on every client: radiod's (gps_time, rtp_timesnap) self-disagrees by ~ms routinely, hundreds of ms at worst #4

Description

@mijahauan

Summary

The anchor-pair self-consistency audit added in c5bf01e (status_listener.py:432-467,
written as an instrument for HamSCI/hf-timestd#7) has now accumulated 24 h of data on
AC0G-B4, and it is reporting a real, host-wide inconsistency rather than the 20 ms
quantisation it was built to look for.

Every sigmond client on the box sees it independently: wspr-recorder, psk-recorder,
meteor-scatter and timestd-core-recorder each log their own audit against their own
channels, and all four show the same shape. This is radiod's published
(gps_time, rtp_timesnap) pair disagreeing with itself, surfaced through four unrelated
consumers — not a defect in any one recorder.

Evidence (AC0G-B4, 2026-08-15 → 08-16)

Max disagreement observed per process lifetime:

client max disagreement
timestd-core-recorder −72 689.666 ms (Aug 15 11:08)
psk-recorder +357.758 ms / +203.874 ms / −165.401 ms
wspr-recorder +292.911 ms / +219.286 ms / +141.621 ms / −111.217 ms / +85.367 ms
meteor-scatter +171.919 ms / +166.094 ms / −120.700 ms

The bulk distribution is consistent across all four clients and all lifetimes — here
wspr-recorder at n=224 758 updates:

delta_ms histogram = [(0, 83909), (-1, 62946), (1, 34200), (2, 21008),
                      (-2, 11814), (3, 4572), (-3, 1672), (4, 933)]

Two things stand out:

  1. The typical disagreement is ±1–4 ms, not 0. The audit's own docstring argues it
    should be nanoseconds — the ADC is GPSDO-disciplined, so advancing rtp_timesnap by
    n samples must advance gps_time by n/sample_rate. Milliseconds of routine
    disagreement is 6 orders of magnitude off that expectation. Whether that is real
    epoch noise or an artefact of when radiod snapshots the two halves of the pair is
    exactly the open question.
  2. The distribution is asymmetric — 0 > −1 > +1 > +2 > −2 > +3 > −3 > +4, reproduced
    independently on all four clients. Noise about a correct anchor should be symmetric.
    A skew toward negative-then-positive-tail looks like a sampling-phase effect.
  3. It is NOT 20 ms-quantised. The hypothesis the audit was built to test — that
    consecutive pairs disagree in whole radiod blocks — is not what the data shows. Worth
    recording as a negative result for hf-timestd#7.

The −72.7 s excursion on timestd-core-recorder at Aug 15 11:08 correlates with a
disturbed window on that host: wspr-recorder logged two gross timing faults at 11:04 and
11:24 (slot ... finished 87.7s BEFORE its nominal end) and the dt-guard re-anchored
17 band recorders. Something re-dated the timeline in that window and the audit caught it.

Why it matters here

rtp_to_utc() and every sub-second timestamp downstream of it rest on this pair. hf-timestd
additionally feeds it into the BPSK chain delay and the chrony SHM reference time. If the
pair is routinely inconsistent at the ms level, that is a floor under every timing claim the
suite makes, and it is invisible to consumers today because nothing but this audit checks it.

Defect in the instrument itself

_anchor_audit['max_ns'] is a running max that never resets and never ages out, and the
logger emits at WARNING every 60 s for the life of the process. The practical effect is that
a single excursion 20 h ago is re-reported 1 200 times as though it were current — the B4
journal shows max_disagreement=+292.911 ms repeated identically across every sample I took
between 09:23 and 09:49, long after the event.

So the audit cannot answer "is this happening now", which is the question an operator
actually has. Suggested: keep a windowed max (or log the delta that triggered a new max,
with its timestamp) and drop the steady-state line to INFO/DEBUG, reserving WARNING for a
fresh excursion above threshold.

Asks

  1. Decide whether ms-scale routine disagreement is genuine or an artefact of radiod's status
    snapshot — i.e. are gps_time and rtp_timesnap captured atomically on the radiod side?
    That determines whether this is a ka9q-radio report or a ka9q-python interpretation fix.
  2. Explain the asymmetry in the histogram; it is reproducible and should be diagnostic.
  3. Fix the running-max/WARNING behaviour above so the instrument can distinguish live from
    historical.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions