Runtime FIX containment and recovery¶
gnss_solve --fix-recovery enables an optional residual guard after the RTK
candidate is produced. It uses the candidate's runtime diagnostics, with no
reference trajectory, external score or covariance-confidence shortcut.
The option defaults to off. It adds no output buffering or future-observation
dependency; a demoted candidate keeps its coordinates and reports FLOAT.
Demotion by itself does not improve position error.
Add --fix-recovery-log new.csv to record every processed decision. That
option enables the guard; --no-fix-recovery can disable it later on the command
line. The advanced options are listed by the native solver's full help.
State transitions¶
| State | Trigger and behavior |
|---|---|
| NORMAL | Ordinary FIX candidates pass. |
| SUSPECT | A FIX with prefit RMS above 10 m, at least 50% suppressed rows and ratio below 6 is immediately demoted. Two consecutive matches enter quarantine. A nonmatching next epoch cancels the streak. |
| QUARANTINE | Post-suppression RMS above 4 m or NIS per observation above 50 on a FIX enters quarantine immediately. Entry requests one primary-filter reset. Persistent bad evidence does not request repeated resets. FIX candidates remain demoted. |
| RECOVERY | Consecutive clean FIX candidates accumulate. Missing, FLOAT or insufficient diagnostic evidence returns to quarantine. Five clean candidates restore NORMAL. |
A clean candidate requires at least eight satellites, ratio at least 3, prefit RMS at most 5 m, post-suppression RMS at most 2 m, NIS per observation at most 10 and suppressed-row fraction at most 20%. Position and diagnostics must be finite, residual/NIS values nonnegative, and update row count positive. A gap over one second clears consecutive evidence; it cannot complete recovery. Observation timestamps must be strictly increasing.
The library header exposes configurable thresholds through FixRecoveryGuard.
The command uses these frozen values for the development comparison. Additional
threshold tuning requires a separately recorded recipe and evaluation.
Evaluation contract¶
Run an identical native binary and input population with the guard off and on. Record exact argv, binary/source/input hashes, runtime, POS and decision CSV. The source-tree replay command supports an RTK-only comparison:
python apps/gnss.py ppc-native-replay --dataset-root /datasets/PPC-Dataset \
--build-dir build --paths rtk --output-dir output/native-baseline
python apps/gnss.py ppc-native-replay --dataset-root /datasets/PPC-Dataset \
--build-dir build --paths rtk --fix-recovery --output-dir output/native-fix-recovery
Keep source contents and the selected build unchanged between these commands.
The guard option records its decision CSV and recipe flag in the provenance
manifest. It does not apply to the fusion recipe. --compare-to is for identical
recipe repeatability and rejects an off/on pair; use the accuracy audit below.
scripts/analysis/audit_ppc_native_integrity.py labels existing outputs offline:
python scripts/analysis/audit_ppc_native_integrity.py \
--dataset-root /datasets/PPC-Dataset \
--replay-dir output/native-baseline \
--candidate-dir output/native-fix-recovery \
--output-json output/native-fix-recovery-audit.json
The audit retains both 0.5 m and 2 m 3D wrong-FIX populations, baseline-correct FIX losses, wrong-FIX removal, missing outputs, actual accuracy recovery, recovery delays and right-censored events. It keeps horizontal P95 and runtime from the native replay scorer. Its descriptive runtime classes are not the guard's decision rule or a guarantee of position accuracy.
An off/on audit requires both replay manifests to have passed a full run. It verifies source contents, executable hashes, input population, runtime libraries, CMake settings and effective solver arguments; only the recovery flag and output destinations may differ. It rechecks recorded artifact hashes before labeling. An equal epoch count alone is insufficient provenance.
The default-adoption gate for this development comparison is conservative: for every run, neither wrong-FIX threshold may increase; baseline-correct FIX loss must stay within 1%; missing/unmatched output count and horizontal P95 must not increase; recovery-delay P95 and right-censored event counts must not increase at either threshold. At least one wrong-FIX population must decrease. All runtime measurements are retained, with concurrent-job contention noted. A failed gate leaves the feature an opt-in diagnostic experiment. Demoting a wrong coordinate to FLOAT is never counted as a correct position recovery.
The new Tokyo run1 baseline contains 784 wrong FIX epochs above 0.5 m, including 247 without any of the audit's named runtime warnings. At 2 m the counts are 217 and 77. These are development-data observations: the guard cannot promise to detect all wrong ambiguity basins from ordinary residuals.
Six-run decision: NO_GO¶
The full off/on experiment used frozen source 8235764f, the same executable,
inputs, configuration, runtime libraries and algorithm environment. Both replay
manifests passed. The paired audit verified and rehashed their provenance before
labeling. ppc_fix_recovery_evaluation.json
retains all run/threshold summaries, correct-FIX losses, accuracy recovery P50/P95,
right-censored counts, missing outputs, runtime and runtime-state counts. It also
pins the complete event-level audit and both replay manifests by SHA-256.
All six runs fail at least one predeclared adoption condition. The decision is NO_GO; keep the default off. No thresholds were retuned after this result.
| Run | Wrong FIX >0.5 m OFF / ON | Wrong FIX >2 m OFF / ON | Baseline-correct FIX loss at 2 m | Horizontal P95 m OFF / ON | Missing/unmatched OFF / ON |
|---|---|---|---|---|---|
| Tokyo 1 | 784 / 406 | 217 / 225 | 7.91% | 1.380763 / 1.404645 | 1702 / 1777 |
| Tokyo 2 | 133 / 131 | 44 / 44 | 2.09% | 0.870171 / 0.875513 | 706 / 692 |
| Tokyo 3 | 341 / 131 | 34 / 34 | 3.25% | 0.883091 / 1.063567 | 1510 / 1496 |
| Nagoya 1 | 837 / 173 | 314 / 64 | 8.07% | 0.755371 / 1.251883 | 903 / 898 |
| Nagoya 2 | 434 / 51 | 27 / 12 | 20.04% | 5.198496 / 5.746931 | 2512 / 2575 |
| Nagoya 3 | 694 / 56 | 288 / 20 | 38.29% | 10.641817 / 10.638017 | 1892 / 1999 |
Aggregated wrong-FIX counts decrease from 3,223 to 948 at 0.5 m and from 924 to 399 at 2 m. Baseline-correct FIX losses are 1,608/36,833 (4.37%) and 3,339/39,132 (8.53%), respectively. These exceed the 1% gate. Tokyo 1 also increases wrong FIX above 2 m; five runs increase horizontal P95. A lower wrong FIX count therefore does not justify default adoption or an accuracy claim. The 28 quarantine entries all reach runtime clean-candidate recovery; that is separate from the offline accuracy recovery and censoring records.
With the guard disabled, every POS numeric field including status matches the original native baseline on all six complete RTK runs, as recorded in ppc_native_default_parity_verification.json. Seven native mechanism tests and seven audit tests pass. The guard remains an explicit opt-in research feature, with no held-out integrity guarantee.