CLASLIB near-equivalence plan¶
This plan defines “near equivalent” as a reproducible, layered parity result,
not as similarity to one previously recorded position RMS. The canonical
scorecard schema is claslib_parity_scorecard.v1; all claimed metrics must be
traceable to one claslib_parity_manifest.v1 file.
Canonical contract (P0)¶
The primary case is the public 2019-08-27 QZSS CLAS sample, evaluated for 3600 one-second epochs beginning at 16:00:00 GPST. A manifest pins:
- OBS, broadcast NAV, and L6 inputs by path and SHA-256;
- CLASLIB implementation version, commit/build identity, and solution output;
- LibGNSS++ commit and solution output;
- reference ECEF, epoch window, 300-second warmup, status mappings, and gates;
- the constellation-specific code/phase ZD component diffs produced for the
same run.
layers.zd_diff_jsonskeeps GPS, QZSS, and Galileo row surfaces independent; each constellation must pass complete coverage and both RMS gates. The legacy singlezd_diff_jsonform remains accepted.
Start from
configs/benchmarks/claslib_parity.example.json, replace every placeholder,
and run:
python3 scripts/analysis/claslib_parity_scorecard.py \
/path/to/claslib_parity.json \
--json-out output/claslib_parity_scorecard.json \
--fail-on-gate
The scorecard records artifact hashes, the raw FIX/FLOAT status matrix, status
agreement after warmup, native-only FIX epochs, FIX-count difference, the full
trajectory delta, and post-warmup all/FIX/FLOAT solution deltas. The trajectory
RMS/P95 gates use every matched epoch, including startup. It imports the existing
madoca_solution_diff.py implementation for epoch matching and ENU math, so
there is one position-comparison implementation. CLASLIB FIX is read from NMEA
quality 4; native FIX is read from .pos FixedAmbiguities > 0. NMEA UTC is
converted to GPST using the applicable leap-second offset before matching.
The canonical ZD evidence uses the runner's fixed diagnostic overrides plus
GNSS_PPP_CLAS_QZSS_S_PRN_FIX=1. It does not enable the base-clock, SIS
boundary, or trop-grid position-scorecard gates. The runner summary records all
inherited and effective GNSS_PPP_CLAS_*/GNSS_PPP_QZSS_* inputs and emits a
typed clas-zd-parity profile, so an artifact cannot silently inherit a
behavior-changing gate.
Delivery sequence¶
P1 — GPS ZD closure¶
Match the CLASLIB row surface for GPS, including exact observation identity, SIS 30-second boundary behavior, network/orbit suppression, atmosphere age, and every PRC/CPC term. Exit when row keys are complete and PRC/CPC RMS deltas are each at most 10 mm.
P1 is complete on the canonical 3580-epoch window: code and phase each match all 52,065 GPS row keys, PRC RMS is 2.414 mm, and CPC RMS is 5.058 mm. The implementation closed the following units without feeding the output-only L5 slot into the estimator:
- select the network-7 bank with its 15-second reception lag and strict 30-second lifetime;
- combine SIS continuity with the IODE-dependent
adjust_r_dts()geometry change; - materialize CLASLIB's zero PRC5/CPC5 L5 diagnostic surface separately from the L1/L2 estimator frequency count;
- remove native-only rows when a required code/phase bias cell is withdrawn;
- rerun the canonical scorecard and core regression suite.
P2 — QZSS ZD closure¶
Extend the same contract to J01–J03. Close STEC, code bias, phase bias, troposphere, and signal selection independently before measuring their combined PRC/CPC result. The P1 thresholds remain unchanged.
P2 is closed. QZSS now uses CLASLIB's internal S120–S122 identity, emits the output-only L5 slot, delays compact code-bias banks by 15 seconds, expires phase-bias withdrawals, reproduces the legacy receiver-ANTEX slot-2 alias to the final C02 entry, and treats omission of legacy S120 from a newer orbit bank as an explicit J01 orbit withdrawal. The typed withdrawal status prevents the OSR layer from publishing broadcast-only J01 rows while leaving ordinary orbit-unavailable QZSS rows and direct J02/J03 identities unchanged.
On the full 3580-epoch run, code and phase each have 29,925 candidate rows, 29,925 common rows, and zero unmatched rows. Code bias and phase bias are exact; PRC RMS is 1.375 mm and CPC RMS is 1.427 mm. The 300-epoch probe also closes at 2,190/2,190 common rows with zero unmatched rows.
P3 — Galileo row-surface closure¶
Make Galileo frequency and observation identity explicit and reproduce the CLASLIB inclusion/exclusion surface. Missing rows are failures rather than implicitly ignored comparisons.
P3 is closed on the joint GPS/QZSS/Galileo 3580-epoch ZD profile. Galileo code and phase each have 15,640 oracle rows, 15,640 native rows, and zero unmatched rows. Using Galileo's gravitational constant only in the old/current IODE continuity reconstruction removes the false 0.2--0.4 m boundary jumps. PRC RMS is 2.300 mm and CPC RMS is 1.648 mm, both below the 10 mm ZD gate. The remaining sparse 39.5 mm code and 25.7 mm phase maxima are retained as P4/P5 diagnostic leads; they do not prevent the specified RMS and complete-surface P3 exit.
P4 — DD measurement parity¶
Add a versioned DD dump and comparator keyed by epoch, rover/base satellite, frequency, and measurement type. Require phase DD RMS at most 5 mm and code DD RMS at most 20 mm, with a complete common row surface.
P4 infrastructure is active. Both CLASLIB and native emit
clas_dd_measurement.v3 prefit rows keyed by epoch, system/frequency,
phase/code, reference satellite, and target satellite. The
clas_dd_measurement_diff.v1 comparator rejects duplicate or unmatched keys and
applies the 5/20 mm RMS gates. The first five canonical epochs exposed and then
closed the Galileo E5a DD slot mismatch (f=2 in CLASLIB versus native f=1):
the surface is now 160/160 with zero unmatched rows. The residual baseline is
still open at 0.624 m phase RMS and 1.316 m code RMS. The dump also preserves
state-unadjusted raw_dd_m; it is diagnostic only because carrier ambiguity
makes it unsuitable for the phase gate. Version 3 also records the receiver
linearization ECEF and DD position Jacobian so measurement-model parity can be
evaluated at a common position without hiding lifecycle divergence.
P5 — Filter lifecycle parity¶
Compare prefit/postfit residuals, state creation/removal, covariance, rejection, slip/reset, and reference-satellite transitions at the first divergent epoch. After the 300-second warmup, mutually FLOAT position delta RMS must be at most 20 mm.
P6 — AR and FIX publication parity¶
Compare ambiguity candidates, integer validation, ratio, accepted set, hold, and publication state. Require at least 99% FIX/FLOAT agreement, zero native-only false FIX, and a FIX-count difference no greater than 1%.
P7 — multi-dataset safety and default-on decision¶
Repeat the canonical scorecard on multiple public CLAS days/sites and keep MADOCA, non-CLAS, static, white-noise, and parity-gate-off safety outputs bit-exact. Only then consider enabling the typed CLASLIB parity profile by default; the decision and rollback trigger must be recorded separately.
P7 reached a decision on 2026-07-15. The canonical 3580-epoch scorecard passes,
and MADOCA/non-CLAS/white-noise containment checks are bit-exact. The independent
2018-11-25 TSKB sample does not pass: its final 400 seconds are mutually FIX but
remain 58.417 mm 3D RMS from CLASLIB, above the 20 mm gate. Therefore the full
typed CLASLIB parity profile remains opt-in for 0.1. The evidence, reconsideration
criteria, and mandatory rollback trigger are recorded in
docs/claslib_parity_default_decision.md.
Definition of done¶
For each sign-off dataset:
- expected and matched solution epoch coverage are 100%;
- ZD row-key coverage is 100%, with PRC and CPC RMS deltas at most 10 mm;
- DD phase/code RMS deltas are at most 5/20 mm;
- post-warmup FLOAT 3D delta RMS is at most 20 mm;
- FIX/FLOAT agreement is at least 99%, native-only false FIX is zero, and FIX count differs by at most 1%;
- full trajectory 3D delta RMS is at most 20 mm and P95 is at most 30 mm;
- safety profiles remain bit-exact.
Until every layer is present in the scorecard, a small final position delta is evidence of progress, not proof of near equivalence.