kshana 0.22.0

Open, reproducible PNT-resilience simulator with quantum-sensor performance models
Documentation
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
# Capability map — what Kshana does, partially does, and does not do

Kshana is a **PNT-performance-and-resilience simulator**, not a full space-systems
toolkit. This page is the honest scope map: for every capability area a procurement or
research reviewer might check, it states the status, what actually exists in the code,
what is missing, and where it sits on the roadmap. Status is one of:

- **yes** — implemented and validated to a stated level;
- **partial** — a real but limited model (scope explicitly bounded below);
- **none** — not modelled (out of scope today).

Nothing here is aspirational: "partial" never means "almost done", it means "this much
and no more". See also [`VALIDATION.md`](VALIDATION.md), [`INTEGRITY.md`](INTEGRITY.md),
[`QUANTUM-MODELS.md`](QUANTUM-MODELS.md), and the overclaim closure ledger
[`CLAIMS-VS-REALITY.md`](CLAIMS-VS-REALITY.md) (every historical overclaim, how it was
resolved, and a CI guard that keeps it resolved).

## Core PNT (where Kshana actually plays)

| Capability | Status | What exists | What is missing | Roadmap |
|------------|--------|-------------|-----------------|---------|
| **Orbit determination & propagation** | partial | Dependency-free **SGP4/SDP4**, validated to 4.12 mm vs all 666 AIAA 2006-6753 vectors (position **and** velocity, the latter to 1 mm/s); analytic Keplerian + J2-secular; inertial velocity exposed and surfaced **end-to-end** via the runnable **`ephemeris` scenario** (`src/ephemeris.rs`, reachable from CLI/Python/WASM/MCP) — per step it emits the TEME **and** GCRS state (position + velocity), the ITRF/ECEF position, the WGS-84 **sub-satellite ground track** (lat/lon/alt), and station azimuth/elevation/range + **range-rate/Doppler** (the radial range-rate matches the true position derivative JD-noise-free to 6e-9 m/s) — and via the CCSDS **OEM** velocity-carrying ephemeris export (`--export-oem`). A **numerical (Cowell) propagator** (`src/propagator.rs`) integrates a configurable **zonal-gravity** force model — the **full Earth zonal field through degree 6** (`forces::zonal_accel`, the published EGM-96 `J2..J6`) — with a choice of adaptive driver — RK4 **step doubling** or the **Dormand–Prince RK5(4)** embedded pair (`integrate_dopri` / `propagate_dopri`, a cheaper 7-eval embedded error estimate that clears the same Kepler gate and agrees with the RK4 path to <1 m on a J2..J6 orbit) — pinned against **analytic truth stronger than a numerical cross-tool**: the unperturbed orbit reproduces the **exact universal-variable Kepler solution to sub-metre over 24 h** (a tighter gate than the milestone's "vs reference < 10 m"), energy + angular momentum conserve to ~1e-9 relative, the J2 nodal regression matches the closed-form secular rate to first-order theory, the zonal acceleration is verified to be the **exact gradient of its own potential** (and to reduce to the 666-vector-validated J2 closed form), and `solve_kepler_checked` **returns `Err` rather than a wrong answer** when Newton fails to converge (e.g. near-perigee e = 0.999). **Epoch-driven third-body (Sun and Moon)** gravity is **wired into the time-varying integrator** (`ForceModel::third_body` / `accel_at`, with the `src/ephem.rs` Montenbruck & Gill low-precision Sun and Moon ephemerides — no DE/SPK kernel needed): each RHS evaluation samples the perturber positions at the advanced epoch `epoch_jd_tt + t/86400`, so the Sun/Moon move along their orbits during the integration. The perturbation is verified as the exact gradient of its disturbing potential, vanishes at the geocentre, and has the textbook LEO magnitudes (~5e-7 m/s² Sun, ~1.1e-6 m/s² Moon); the Sun ephemeris hits hand-derived J2000 anchors (perihelion distance, ~−23° solstice declination, ~1°/day motion) and the Moon ephemeris its perigee/apogee envelope, ~384 400 km mean distance, ≤ 5.3° inclination bound, and sidereal-month direction return; and the integration wiring is proven **bit-exact** (RHS term equals `third_body_accel` at the sampled position at t = 0 and t = 1 day) with a quarter-year epoch shift yielding a different trajectory. **Solar-radiation pressure** rides the same epoch-driven RHS (`forces::srp_accel` / `ForceModel::solar_radiation`): the cannonball model `ν·P☉·cᵣ·(A/m)·(AU/d)²·d̂` with a `forces::conical_shadow` umbra+penumbra eclipse factor (smooth ν ∈ [0,1], verified to taper through a monotonic penumbra that extends beyond the umbral cylinder), verified against the textbook 1-AU pressure (≈ 4.54e-6 N/m²), the ~1.36e-7 m/s² LEO magnitude pushing away from the Sun, the inverse-square fall-off (doubling Sun distance quarters it), an **exactly-zero** acceleration in the umbral cylinder, and a propagated displacement that scales ~linearly with A/m. **Atmospheric drag** is the first velocity-dependent term (`forces::drag_accel` / `ForceModel::drag` + the new `accel_rv` / velocity-passing RHS): quadratic drag `−½·ρ(h)·(C_D·A/m)·\|v_rel\|·v_rel` against the co-rotating atmosphere `v_rel = v − ωₑ ẑ × r`, with `ρ` the Vallado piecewise-exponential `forces::atmospheric_density` — verified by the 1.225 kg/m³ sea-level anchor, a strictly monotonic LEO decay with a physical ~58 km scale height, the ~2e-6 m/s² drag magnitude opposing the relative velocity, and the **dissipation signature** (a 300 km orbit loses specific energy monotonically and its semi-major axis decays a bounded ~km/day, where the vacuum orbit conserves energy). The **post-Newtonian (Schwarzschild) relativistic correction** is the second velocity-dependent term (`forces::relativistic_accel` / `ForceModel::relativity`): the IERS `β = γ = 1` form `a = (μ/c²r³)·{[4μ/r − v²]·r + 4(r·v)·v}`, the leading driver of the relativistic perigee advance — verified against its closed-form circular value `3μ²/(c²r³)·r̂` (radial, outward), its textbook `≈1.9e-9` LEO ratio to two-body, the hand-simplified radial-velocity form, and the **conservative signature** (it perturbs the orbit but holds the semi-major axis to under a metre/day, the structural opposite of drag). The **Lense–Thirring** frame-dragging term (`forces::lense_thirring_accel` / `ForceModel::lense_thirring`, IERS 2010 §10) is the gravitomagnetic correction beyond Schwarzschild — opt-in, ~1–2 orders of magnitude below it at LEO, verified to vanish without Earth rotation and to sit below the Schwarzschild magnitude. **Orbit determination** (`src/orbit_determination.rs`) closes the loop from observations back to a state: a **Gauss–Newton batch** corrector (`src/batch_ls.rs`) drives a candidate `[r, v]` onto the best fit of ground-station ranges propagated across the arc (sub-metre / mm·s⁻¹ from noiseless ranges; ~2 m with a post-fit residual at the 5 m noise floor — the signature of a consistent least-squares fit), with a **sequential** recursive variant on the unscented filter | No high-degree EGM **tesseral** field (200×200 + loader); drag density is the **static** Vallado piecewise-exponential (solar-activity-independent), **not** NRLMSISE-00 (the < 5 % thermospheric-density clause); SRP is the **cannonball** model with a geometric **conical umbra+penumbra** shadow (no solar limb darkening, no oblate-Earth shadow, no satellite shape/attitude); relativity covers the **Schwarzschild and Lense–Thirring** (frame-dragging) terms, both opt-in, but no PPN-parameter tuning; **third-body/SRP use the low-precision ephemerides (~0.005° Sun, ~0.3° Moon), not DE/SPK-kernel accuracy**; no external GMAT/Orekit cross-validation of a high-fidelity orbit run; no orbit *determination* (fit from observations) | high-degree tesseral gravity + NRLMSISE-00 drag + solar limb darkening + Lense–Thirring + DE-grade ephemeris + GMAT cross-val + OD range-rate/angle measurements & analytic STM: P2+ |
| **Time systems** | partial | `src/timescales.rs`: Julian-date API (civil↔JD, MJD), UTC↔TAI via the full IERS leap-second table (10→37 s, 1972→2017), TAI→TT, UT1 via DUT1, and the IAU-2000 **Earth Rotation Angle** (ERA validated bit-for-bit against the SOFA `eraEra00` vector). The SGP4 path's **DUT1≈0 approximation is explicitly documented** at the `gstime` call site (a ≤ ~13″ GMST error, well inside SGP4's own model error), and the `ephemeris` scenario takes explicit `dut1_s`/`xp_arcsec`/`yp_arcsec` knobs **or an inlined real IERS `finals2000A` series** (`eop_finals2000a` / `kshana --eop <file>`, interpolated through the same `EopSeries` `precise_od` uses) so the ground track is reduced through real IERS UT1 / polar motion, not just the nominal scalars | Single-`f64` JD (~50 µs resolution near 2020 — this, not the algorithm, is the floor on a finite-difference cross-check; two-part JD on the roadmap); pre-1972 rubber-seconds not modelled; DUT1 not predicted (must be supplied) | **done** (foundation); two-part JD: P2 |
| **Reference frames** | partial | `src/frames.rs`: GMST-based TEME↔ECEF, WGS-84 geodetic↔ECEF (exact + iterative inverse, machine-precision at all altitudes), and a geodetic ground-station observer (azimuth/elevation/range); **IAU 2006 precession** (`src/precession.rs`: the Fukushima–Williams angles `(γ̄, φ̄, ψ̄, ε̄_A)` + the GCRS↔mean-of-date bias-precession matrix); **IAU 2000A/2000B nutation + full TEME→GCRS chain** (`src/nutation.rs`: the **full IAU 2000A** series — 678 luni-solar + 687 planetary terms, `nutation_iau2000a` / `nutation_matrix_2000a`, table machine-generated from the ERFA `nut00a` reference by `tools/gen_nut00a.py` — alongside the 77-term 2000B series, Delaunay arguments, the SOFA `iauNumat` nutation matrix, the equation of the equinoxes, and `teme_to_gcrs(r, v, jd_tt)` via TEME→TOD→MOD→GCRS — both series validated **bit-for-bit** against the SOFA/ERFA `nut00a`/`nut00b` reference vectors, Δψ/Δε to 1e-13 rad); **IERS polar motion** PEF→ITRF (`teme_to_itrf` / `polar_motion_matrix`, SOFA `iauPom00`, caller-supplied `x_p`/`y_p` — a tens-of-metres effect at orbital radius); **CIO-based IAU 2006/2000A reduction** (`src/cio.rs`: the equinox-free GCRS↔CIRS↔ITRS chain — CIP `X,Y` from the 2006/2000A NPB matrix, the 66-term CIO-locator `s` series, `gcrs_to_cirs_matrix`, the Earth rotation angle, and the full `gcrs_to_itrs_matrix` — validated **bit-for-bit** against the SOFA `eraXys06a`/`eraC2ixys`/`eraEra00` vectors). The **end-to-end** transforms are now pinned to a published authoritative worked example, not just self-consistency: against the **Vallado** AIAA 2006-6753 state (2004-04-06, with its IERS EOP; `tests/frame_reference_vectors.rs`) TEME→PEF matches to **0.1 mm**, TEME→ITRF to **0.6 mm**, the full CIO GCRS→ITRS to **4 mm**, and ECEF→geodetic reproduces Vallado Example 3-3 lat/lon/alt to the last published digit. The whole chain is **user-reachable** via the `ephemeris` scenario (ITRF/ECEF position + WGS-84 sub-satellite ground track per step) | The default TEME→GCRS chain uses 2000B (~1 mas, below its own velocity-frame-rotation simplification); the < 0.1 mas full-2000A path is available via `nutation_matrix_2000a`, and the rigorous **CIO (X, Y, s)** reduction is available via `src/cio.rs`. The legacy TEME path uses IAU-1982 GMST (SGP4 convention); an ANISE/SPICE numerical cross-check (a second independent realisation) is a follow-on | TEME↔ECEF + geodetic: **done** (Vallado-verified); inertial TEME→GCRS: **done** (2000B + full 2000A); polar-motion ITRF: **done** (Vallado-verified); CIO GCRS→ITRS: **done** (Vallado-verified) |
| **Timing & frequency** | partial | Exact van-Loan-Q two-state Kalman clock (NIST SP 1065) with a **Joseph-stabilised covariance update** (positive-semidefinite under extreme Q/R ratios, Cholesky-checked in CI) and a **filter-consistency health monitor** (`src/filter_health.rs`): a Monte-Carlo NIS/NEES assessment against χ² confidence bands, surfaced as `filter_health` in the result JSON and a green/amber card in the playground, with a Q/R-mismatch sweep test proving the monitor flips to *inconsistent* when the tuning is off (Bar-Shalom §5.4); overlapping **ADEV, MDEV, TDEV, HDEV** estimators + χ²-based confidence intervals with **noise-type-specific effective degrees of freedom** (NIST SP 1065 Table 5 closed forms for WPM/FPM/WFM/FFM/RWFM, the set Stable32 uses; the exported ADEV curve identifies the record's power-law type from its MDEV slope and attaches a 95% band per τ — `src/allan.rs`), **numerically validated against the Stable32 reference deviations for the canonical NBS14 dataset to 1e-4** (`tests/allan_reference.rs`) and the edf cross-checked by a Monte-Carlo white-FM ensemble; honest grid-bounded holdover FoM; clock ensembles; **two-way time-transfer model** with reciprocal-delay cancellation + a non-reciprocal random-walk-FM differential-delay floor (`src/timetransfer.rs`, Allan signature reported); a **GNSS-denied clock-holdover calculator** (`src/holdover.rs`) exposing the closed-form van-Loan coast-error growth `σ_x²(t) = q_wf·t + q_rw·t³/3 + q_drift·t⁵/20` as a user-facing *holdover-to-threshold* inversion (how long a clock free-runs before its timing error exceeds budget), with representative quantum-clock classes (optical-lattice/trapped-ion/mercury-ion) — **modelled, not externally validated**: cross-checked against the multi-step `clock_state` covariance recursion, and stated honestly that for a very stable clock the holdover to a tight threshold is **governed by the *assumed* long-tau red-noise floor, not the cited ADEV** (use measured floors for a defensible number). A **conditional Timing Protection Level** (`src/tpl.rs`) builds on the same holdover machinery for the *spoofing* case: a bound on the **undetected** time error given an independent cross-check — a k-σ monitor floor plus the van-Loan coast variance over the detection latency plus a CUSUM time-to-alarm — calibrated on a **real recorded spoof** (JammerTest 2024, Zenodo 15911589) and reproducible via `cargo run --example tpl_jammertest`. **Modelled** composition, conditional on detection: there is no finite *unconditional* bound (a slow-enough ramp evades a single clock-aided monitor) | full Greenhall-algorithm edf (the simple closed forms are bias-bounded but coarser than the exact BasicSum), and multi-noise-mixture identification | exact-edf + mixed-noise ID: P2 |
| **GNSS / PNT processing** | partial | A **measurement-domain pseudorange simulation** (`gnss-sim` kind, `src/gnss_sim.rs`): per visible satellite it synthesises `ρ = geometric range + c·δt_rx − c·δt_sv + I + T + noise + multipath` and the L1 Doppler, with the **Klobuchar single-frequency ionosphere** (IS-GPS-200 §20.3.3.5.2.5) and the **Saastamoinen zenith troposphere** (Davis 1985) projected by the **Niell (1996) mapping function** — each model unit-tested against hand computation — then feeds the residuals to **snapshot RAIM** for per-epoch HPL/VPL and emits a `gnss_measurements[]` array (pseudorange, Doppler, C/N₀, iono/tropo corrections per SV). Plus DOP/availability and solution-separation RAIM from orbits; **RINEX 3 multi-GNSS NAV ingestion** (GPS/Galileo/QZSS/BeiDou via IS-GPS-200, GLONASS state-vector) parsed → SV ECEF position & clock bias, usable as a first-class `Propagator` source AND as an inline constellation `rinex` block (`scenarios/orbit-rinex.toml`); **RINEX 3/4 OBSERVATION ingestion**; a **single-point-positioning solver** (`pvt` kind, `src/pvt.rs`) that turns real RINEX code pseudoranges + broadcast ephemeris into a **receiver position** by iterated weighted least squares — Sagnac/Earth-rotation correction, broadcast satellite clock with `−TGD`, the **dual-frequency L1/L2 ionosphere-free combination** (or single-frequency Klobuchar), Saastamoinen/Niell troposphere, elevation weighting, DOP, and snapshot RAIM — **validated on real IGS data** (station ABMF, Guadeloupe, 2018-05-13) to **5.7 m 3-D RMS / 1.1 m horizontal** against the station's surveyed coordinate (`tests/pvt_abmf.rs`, `scenarios/pvt-abmf.toml`); and SP3 precise-orbit read/write | A **code** positioning engine: the `pvt` solver computes a real position from real measurements (single-point positioning, metre-level, with the dual-frequency iono-free combination), but **not carrier-phase PPP/RTK** — no ambiguity resolution, no carrier smoothing, no inter-epoch Kalman filter; the forward `gnss-sim` pack remains a from-truth simulator; BeiDou-GEO excluded | carrier-phase PPP/RTK: use RTKLIB/gLAB |
| **Sensor fusion / INS dead-reckoning** | full | **3-axis strapdown library** (`src/inertial/{attitude,mechanization,imu_errors}.rs`): quaternion attitude with coning/sculling compensation, full NED mechanization (Earth-rate + transport-rate, WGS-84 Somigliana gravity), and a deterministic IMU error model (**scale-factor, misalignment, g-sensitivity, quantization, rate-ramp** modelled). The strapdown navigator is now **wired into a runnable loosely-coupled GNSS/INS pack** with a figure of merit (`src/fusion/pack.rs`, `kind = "gnss-ins"`): the three-axis mechanization is disciplined by the **15-state error-state EKF** (`src/fusion/{gnss_ins_ekf,closed_loop}.rs`, position/velocity/attitude/bias feedback) while GNSS is up, then coasts through the outage — replacing the truth-snap reset with genuine fusion, and reporting the fused horizontal error vs the open-loop free-INS coast. The separate legacy `inertial` pack still runs the **1-DOF scalar** budget with truth-snap reset. A **tightly-coupled pseudorange** update (`update_tightly_coupled` / `fuse_tightly_coupled`) is also implemented: it forms the innovation in the range domain (line-of-sight Jacobian on δp) and keeps correcting with **fewer than four satellites**, where a loosely-coupled PVT fix does not exist. A **full 17-state tightly-coupled GNSS/INS UKF** (`src/fusion/tightly_coupled17.rs`) carries position, velocity, attitude error, accelerometer and gyro biases, and the receiver clock (bias + drift), with **quantum-CAI dead-reckoning** — the velocity-random-walk process noise is the cold-atom accelerometer's derived `q_va` — coasting a 120-second outage bounded to a few hundred metres (vs the kilometres of a navigation-grade free INS). This 17-state UKF is now **surfaced as a runnable scenario** (`src/fusion/hybrid_ukf.rs`, `kind = "hybrid-ukf"`, reachable from CLI/Python/WASM/MCP): the **15 INS error states** are augmented with the **CAI-derived accelerometer-bias correction** (the cold-atom interferometer sets the velocity-random-walk floor `q_va`) and a **2-state phase+frequency clock** whose process noise comes from the **q-parameter clock engine** (`clock_state::q_from_allan`, Allan profile → `q_wf`/`q_rw`), driven by the bracketed CAI error model so the run demonstrates classical-IMU short-term + quantum long-term hybridisation. Its figure of merit is **filter self-consistency** — pooled **NEES + innovation-whiteness (NIS)** over a Monte-Carlo ensemble against their 95% χ² bands (the matched filter lands inside the bands; a mistuned filter is flagged, an objectively checkable gate). **This is a SELF-CONSISTENCY statement under the modelled noise, NOT a real-world accuracy guarantee** — the CAI/clock inputs are bracketed/modelled, the CAI hardware is partner-owned, and nothing here implies TRL>3, flight heritage, or external validation. The deterministic IMU error model is **configurable per sensor from the `gnss-ins` TOML** (`[imu_*.error_model]`: scale-factor, misalignment, g-sensitivity, quantization, rate-ramp), defaulting to a pure constant-bias source when omitted | Tightly-coupled is **pseudorange-only** (carrier-phase is roadmap); the `hybrid-ukf` scenario uses a **single constant-velocity, level trajectory** on which the attitude and IMU-bias error states are only weakly observable, so the NEES consistency is assessed over the **estimable subset** (position, velocity, clock = 8 states) — full-17 observability needs a manoeuvring trajectory (roadmap); the loosely-coupled accel-bias/tilt pair is weakly separable so per-bias calibration is not claimed; IMU error model omits vibration rectification, temperature-gradient drift; the 17-state UKF and the tightly-coupled paths are **self-validated** (analytic CV integration, GNSS-aiding convergence, bias recovery, the CAI-limited 120-s outage bound, and the NEES/NIS χ² consistency oracle) — an external **NaveGo / KF-GINS cross-validation** has not yet been run | carrier-phase tight coupling, manoeuvring-trajectory full-17 observability, trajectory library, NaveGo/KF-GINS cross-validation: **P2** |
| **Integrity / RAIM / ARAIM** | partial | **Real snapshot RAIM** in `src/raim.rs`: least-squares solution + residual χ² fault detection (exact threshold from a dependency-free incomplete-gamma χ²) and **slope-based HPL/VPL** (pbias from a non-central χ² for the configured P_fa/P_md); **solution-separation (MHSS) RAIM** with fault detection/identification; **ARAIM integrity-risk (P_HMI) budget** (`araim_raim`) that solves the smallest HPL/VPL whose summed `P_HMI = Σ_k p_fault,k·Q((PL−T_k)/σ_k)` meets an explicit integrity-risk allocation, the **dual-/multi-constellation constellation-wide fault mode** (`araim_dual_raim`, EU ARAIM TN / DO-316; `P_const = 0` ⇒ bit-for-bit `araim_raim`), an explicit **integrity support message** (`IntegritySupportMessage`: σ_URA/σ_URE/b_nom/P_sat/P_const, with the WG-C GPS+Galileo reference values), plus a **Stanford(-ESA) integrity-diagram** (the `integrity` scenario kind, and a standalone `stanford_svg` renderer of the four zones + `PL=error` boundary). Documented end-to-end in [`ARAIM_REFERENCE.md`](ARAIM_REFERENCE.md). Plus the scenario FoM's filter self-consistency (k-σ bound) | RAIM is reachable via the `integrity` scenario kind but **not yet folded into the clock/holdover FoM** (those still report self-consistency); the ARAIM budget covers single-SV **and** constellation-wide faults but simultaneous multi-SV-subset faults and **FDE** beyond identification are not modelled, and `araim_dual_raim` is wired into the TOML scenario runner via the `araim_dual` flag (`scenarios/araim-gps-galileo.toml`), with a per-epoch availability path `araim_dual_constellation_availability`; the snapshot/MHSS/ARAIM cores are exercised on **real IGS precise-orbit (SP3) geometry** (`tests/igs_real_data.rs`) and on **real Celestrak GPS+Galileo TLEs** (`tests/araim_dual_real_data.rs`: pooling Galileo lifts availability 0.21→0.67 under a 12 m VAL; the constellation-fault-robust mode is limited with only two constellations); the exact EU-ARAIM-TN Table A-3 / 15–25 % figure against a single version-locked epoch + a Zenodo record remain external; not DO-229/ARAIM-certified | multi-fault ARAIM + receiver-domain gLAB parity + FoM wiring: **P2** (see [`INTEGRITY.md`](INTEGRITY.md)) |
| **Spoofing / jamming threat modelling** | partial | A **stochastic time-spoof detector** (`spoof` kind, `src/spoof.rs` + `src/detection.rs`): four injection shapes (linear ramp, step jump, meaconing, replay) against a clock-aided monitor with a two-sided **χ²₁ energy / Neyman–Pearson test**, the detection threshold set from a target false-alarm budget `P_fa`, and the **missed-detection probability `P_md` reported both closed-form and by Monte-Carlo** (the two agree to a few ×1/√N) — the Security figure of merit is `1 − P_md`. Plus a **link-budget jamming model** (`jamming` kind, `src/jamming.rs`): jammer-to-signal ratio from geometry (free-space path loss + per-direction receive-antenna gain), the standard **anti-jam effective-C/N₀ equation** (despreading processing gain + spectral-separation factor `Q`; Kaplan & Hegarty §9.4), per-satellite loss-of-lock at a configurable tracking threshold, and an `availability_under_jamming` figure of merit over a Walker constellation. Plus a **multi-layer RF/measurement spoof-monitor suite** (`src/spoof_monitors.rs`): a **multi-satellite RAIM-consistency** parity test (`parity_raim_test`, weighted residual SOS vs a χ²(m−4) threshold — and it correctly flags that a common-mode bias is RAIM-invisible), an **AGC monitor** (`AgcMonitor`, received-power excess over the expected floor), a **signal-quality / SQM monitor** (`SqmMonitor`, Early/Late correlator imbalance), and a layer-fusion combiner (`fuse_spoof_layers`). These compose into an **integrated `CombinedSpoofDetector`** whose `evaluate` ingests one epoch of observables (geometry + residuals, AGC power, Early/Late taps) and runs all three layers through the weighted fusion in a single call, returning the per-layer diagnostics; it is exposed as the runnable **`spoof-detect` scenario** (`src/spoof_detect.rs`, CLI / Python / playground reachable, JSON + SVG) and **characterised against the published TEXBAT scenario parameters** (Humphreys et al., ION GNSS 2012; `tests/spoof_texbat_validation.rs`) — reproducing the documented detectability pattern, including the negative results: overpowered ds2 caught by AGC + SQM, matched-power ds3 by SQM alone, position-push ds4 by RAIM, and the carrier-phase-aligned matched-power ds7 left (correctly) to the clock-aided detector | Jamming model is a **link budget** — no multipath, terrain shadowing of the jammer, near/far AGC dynamics, adaptive nulling, or acquisition-vs-tracking hysteresis; the spectral-separation `Q` values are representative but are now **cross-checked against the per-PSD-derived coefficient** in [`navsignal`](#) (see the nav-signal row). The clock-aided spoof detector is single-clock; the RF/measurement monitors are now integrated (`CombinedSpoofDetector`) and **characterised against the published TEXBAT scenario *parameters*** (Humphreys et al.); the residual is validation against the **raw** vectors — TEXBAT IQ (which needs an SDR acquisition/tracking front-end kshana does not have, being a simulator, not a receiver) or a licensed Spirent scenario — a documented follow-on | clock-aided + integrated multi-SV-RAIM-consistency + AGC + SQM **combined detector** + TEXBAT-parameter characterisation: **done**; raw-vector (TEXBAT IQ / licensed Spirent) validation: follow-on |
| **Nav-signal modulation & code-tracking performance** | partial | `src/navsignal.rs`: the **signal level** between the link budget and the measurement domain. Unit-area **power spectral densities** for **BPSK-R(n)** and **sine-BOC(m,n)** (CI-validated to unit area, to the BPSK self-SSC closed form `κ = 2/(3R_c)`, and to the BOC spectral split — null at the carrier, peaks at ±f_s); the **spectral-separation coefficient** `κ = ∫ G_s(f)G_i(f) df`, which now **derives the anti-jam `Q`** used by [`jamming`](#) from the actual signal/jammer spectra (`Q = 1/(R_c·κ)`) instead of a representative constant (the broadband reference is cross-checked in CI); the **RMS (Gabor) bandwidth** (BOC > BPSK — the ranging-information / Cramér–Rao measure); the **coherent early–late DLL code-tracking thermal-noise jitter** (Kaplan & Hegarty §8 — ~sub-metre for C/A at 45 dB-Hz, monotone in C/N₀); and the **multipath error envelope** (coherent EML, found by locating the composite-discriminator zero — narrow-correlator suppression verified). A **ranging-code design-trade** layer (`CodeFamily`) adds the m-sequence/Gold periodic-autocorrelation sidelobe (`1/L` for an m-sequence) and the three-valued **Gold cross-correlation bound `t(n)/L`** — reproducing the published **GPS C/A −23.9 dB** Gold cross-correlation (an external anchor) and the `φ(2ⁿ−1)/n` m-sequence count — plus the code-length↔unambiguous-range inversion; the Gold guarantees honestly return *None* where no preferred pair exists (`n mod 4 = 0`), rather than reporting a bound that does not hold. | No full receiver acquisition/correlator chain, no BOC tracking-ambiguity resolution, no band-limited front-end beyond the integration window, and **no validation against recorded IQ** (kshana is a simulator, not a receiver). Antenna/RF-payload **hardware** design (radiation patterns, front-end) is deliberately out of scope — a payload partner's role. | full correlator chain + BOC ambiguity + recorded-signal validation: P2+ |
| **Quantum PNT sensor physics** | partial | Most sensors are **published Allan/noise-budget coefficients** (CSAC, optical), **plus a first-principles cold-atom-interferometer (CAI) accelerometer** in `src/inertial/quantum_imu.rs`: the three-pulse Mach–Zehnder phase `Φ = k_eff·a·T²`, quantum projection (shot) noise `σ_Φ = 1/(C√N)`, the derived velocity-random-walk PSD `q_va` the inertial stack consumes, contrast decay, the vibration transfer function `\|H(ω)\|` + white-PSD variance, and now the **Coriolis/rotation** (`coriolis_phase`, equivalent bias `2Ω×v`) and **AC-Stark light-shift** (`ac_stark_phase`, symmetric-cancellation) systematics + a cycle-time **drift sweep** (`cai_drift_sweep`), and a **composed quantum-inertial dead-reckoning error budget** (`QuantumNavBudget`) that folds the CAI white-noise velocity-random-walk together with residual bias (`½·b·t²`, cross-checked against the independent `AccelModel` Euler integrator), scale-factor error, and an optional **long-term** stability degradation (distinct from per-shot decoherence) into one position-drift-over-holdover figure plus an inertial holdover-to-threshold — the dead-reckoning twin of the clock holdover. The modelled quantum floor is **bracketed (not parity-matched)** against the 96 nm/s²/√Hz of the Freier et al. 2016 mobile gravimeter (arXiv:1512.05660) — it lies below and within ~2 orders of it. Documented in [`QUANTUM.md`](QUANTUM.md) | Wavefront/beam-pointing systematics and Mach–Zehnder fringe-ambiguity resolution not modelled; the exact CARIOQA-PMP / Boeing-AOSense flight-test budgets (need published platform PSDs + per-shot SNR) and a JS playground preset are residual | wavefront systematics + flight-test repro: P2+ ([`QUANTUM-MODELS.md`](QUANTUM-MODELS.md)) |
| **Constellation design** | partial | Synthetic Walker (both analytic Keplerian **and SGP4 mean-element**, the latter propagated through the 4.12 mm-validated core — `src/walker.rs`) + real-TLE multi-constellation visibility & DOP (GPS+Galileo to 100%), validated against a **real Celestrak gps-ops snapshot** (`tests/igs_real_data.rs`); a **PDOP design sweep** over the `{planes × sats × inclination}` grid and **coverage-fraction / revisit-time** figures of merit; a **gradient-free design optimiser** (`optimize_walker_design`) that searches the grid for the best design under a chosen objective (`MinSatellitesForCoverage` / `MaxCoverage` / `MinWorstPdop`), validated to return the brute-force winner; and **analytical streets-of-coverage geometry** (`coverage_half_angle_rad`, `street_half_width_rad`; Rider/Beste closed forms, hand-verified — GPS at a 5° mask: λ ≈ 71.2°, 4-sat street half-width ≈ 62.8°) | The full Rider **minimum-satellite global-coverage solver** (the seam-sensitive plane count) is not yet implemented; no 3-D playground globe view; multi-constellation DOP is not yet cross-checked against an external reference tool (gnss-rtk); geodetic vs geocentric "up" in the DOP frame | streets-of-coverage min-sat solver + 3-D globe + gnss-rtk DOP cross-check: P2 |
| **Verification & validation** | partial | One world-class island (SGP4 vs 666 AIAA vectors); deterministic Allan checks; a **machine-checked verification matrix** (`src/verification.rs`) — a requirement→module→test→oracle→status cross-reference whose honesty invariants are **unit-tested**: a row may be labelled *validated* only if it carries an independent **external** oracle (NIST/AIAA/SOFA/IGS/published value), so an internal self-consistency check cannot masquerade as a validation; renders to Markdown/CSV for an ECSS-E-ST-10-02 verification cross-reference, and records the four partner-owned hardware/PA gaps as such | Golden tests pin few exact numbers; calibration on single seeds; the matrix enforces row *classification*, not that every cited test string resolves to live code (curated, code-reviewed) | golden numerics + calibration ensembles: P1 (M17/M18) |

## Broader space-systems domains (out of scope today)

Several of these are **none**; others are now **first-order `partial` models** (the
mission-analysis / environment kinds added in the v0.17.0 series) — listed so the scope is
unambiguous, not implied by silence. Kshana is a PNT simulator, not GMAT/STK/Orekit; these
adjacent models are deliberately first-order and MODELLED, never validated flight tools.

| Capability | Status | Note / roadmap |
|------------|--------|----------------|
| Mission design / trajectory optimization | partial | `src/maneuver.rs`: impulsive ΔV nodes with 6×6 covariance propagation (ECI/LVLH execution-error frames), finite-burn integration checked against the closed-form **Tsiolkovsky** equation to < 0.01 %, an **Izzo-2015 single-revolution Lambert** solver + an exact universal-variable **Kepler propagator** (Lambert outputs round-tripped against two-body truth), and a **porkchop** (launch × arrival) C3 / arrival-V∞ sweep emitted as a JSON contour grid whose minimum is checked against the analytic Hohmann floor. **No trajectory optimizer, no multi-revolution Lambert**; the porkchop still uses a synthetic coplanar-circular heliocentric model (a GMAT Earth–Mars C3 cross-check needs a shared DE-ephemeris and has not been run). A deep-space **planetary-ephemeris seam** (`src/ephem_provider.rs`) and a **DE440 cross-check** (`xval/anise-mars-od`, 137 m @ 1-day Mars arc) now exist — see the deep-space / interplanetary PNT row. The performance-simulation layer above GMAT/Orekit, not a replacement. P3 |
| AOCS / GNC / attitude | partial | `attitude-budget` kind (`src/attitude_budget.rs`): worst-case **gravity-gradient torque** `1.5·(μ/R³)·ΔI` + **RSS pointing-error budget** over per-contributor 1σ terms — a MODELLED scalar pre-hardware pointing/disturbance budget. **No** 6-DoF attitude dynamics, no control loop, no estimator/quaternion state (the IMU "gyro" is still a scalar tilt channel) — the budgeting layer above Basilisk/42, not a replacement. P3 |
| Reference frames → Earth-fixed | none | **P1** brings TEME→ECEF/ITRF (listed above under frames) |
| Comms & link budgets | partial | `src/linkbudget.rs`: a **deep-space Friis link budget** (Tx power · antenna gains · noise → C/N₀ · Eb/N₀ · margin) feeding the radiometric/GSE path, plus the optical/RF time-transfer links (`src/timetransfer*.rs`), and the runnable **`link-budget` kind** — the one-way CCSDS-401/DSN-810-005 link equation `C/N₀ = EIRP − FSPL − L_other + G/T − k` with **EIRP / G-T** inputs and S/X/Ka band selection (MODELLED engineering link budget, not a calibrated terminal datasheet). No access scheduling, no adaptive coding. P2 |
| Ground segment & operations | partial | `passes` kind (`src/passes.rs`): **ground-station rise/set pass prediction** — AOS/TCA/LOS, max elevation, per-pass duration and total access over a horizon, from Keplerian TEME→ECEF propagation with mask-crossing interpolation (MODELLED, sample-step TCA resolution; no SGP4/J2/refraction/light-time, no scheduling optimiser or conflict resolution). P3 |
| Telemetry / TT&C / CCSDS | partial | bespoke TOML-in/JSON-out; **CCSDS OEM (Orbit Ephemeris Message) export *and import*** (502.0-B KVN, GMAT/Orekit/STK) via the runnable **`oem-interop` kind** (`src/oem.rs` `parse_oem` round-trip bridge); **CCSDS-TDM (503) Tracking-Data-Message parse + emit** (`src/ccsds_tdm.rs`, the deep-space radiometric interchange format); and the **`space-packet` kind** (`src/space_packet.rs`): **CCSDS 133.0-B Space Packet** primary-header encode/decode with bit-exact round-trip. Other CCSDS message types (ODM/AEM) and SPICE interop remain a roadmap item (P2) |
| Interoperability & standards (RINEX/SP3/SPICE/CCSDS) | partial | RINEX 3 **multi-GNSS NAV** — GPS, Galileo, QZSS, BeiDou MEO/IGSO (IS-GPS-200) **and GLONASS** (PZ-90 state-vector RK4) — ingested + propagated + runnable as one mixed constellation; **RINEX 3/4 OBSERVATION parser** (pseudorange/carrier/Doppler/SNR by observation code, with LLI/SSI flags); SP3-c/d precise-ephemeris **read ↔ write round trip** (parse + export for Ginan/RTKLIB/gLAB) **and a 9th-order Lagrange propagator** (`Propagator::Sp3Precise`); SP3 export is **CLI-exposed** (`kshana <orbit.toml> --export-sp3 out.sp3`, or `export_sp3 = true`) and **round-trip-validated** against the real GPS constellation to <0.5 m over 24 h (`tests/sp3_export_roundtrip.rs`); **CCSDS OEM 2.0 ephemeris writer** — the velocity-carrying TEME state export for flight-dynamics tools — now **CLI-exposed** (`kshana <orbit.toml> --export-oem out.oem`, or `export_oem = true`) and round-trip-checked against the propagator state (`tests/sp3_export_roundtrip.rs`). The **RINEX observation parser now feeds a single-point-positioning solution** (`pvt`, validated on real IGS data — see the GNSS / PNT row). Plus **CCSDS-TDM (503)** tracking-data-message parse + emit (`src/ccsds_tdm.rs`). No BeiDou-GEO, no SP3 clock interpolation, no carrier-phase PPP/RTK, no SPICE / no ODM·AEM yet (the **OEM reader now exists** via the `oem-interop` kind) — **P2** "annex adjacent domains via standard formats" |
| Space weather / environment (iono/atmo/radiation) | partial | `space-weather` kind (`src/space_weather.rs`): solar/geomagnetic indices (**Kp↔ap** IAGA 28-step table, daily Ap, centred 81-day **F10.7a**), **Jacchia-71 exospheric temperature**, and an **activity-driven thermospheric-density coupling** over a static atmosphere — MODELLED first-order, **NOT** an NRLMSISE absolute-density model. Iono/TEC is still a known GNSS error source omitted even in the PNT niche; P2+ |
| Gravity-map / alt-PNT navigation | partial | `src/gravimeter.rs`: a cold-atom **gravimeter measurement model** whose white-noise floor is derived from the CAI accelerometer ASD (`σ = ASD/√τ`), a low-degree **fully-normalised spherical-harmonic gravity-anomaly field** (validated against the closed-form Legendre functions and a hand-derived single-term anomaly) plus synthetic **mascons**, and a **gravity-map-matching particle filter** (composing `mapmatch` + `particle_filter`) that recovers a GPS-denied track from the anomaly sequence it flies through. The **60-minute GPS-denied benchmark** (`run_gps_denied_gravity_nav`, `scenarios/gps-denied-gravity-nav.toml`) flies a ~700 km / one-hour outage where the inertial solution drifts to **≈ 70 km**, and a **hierarchical coarse-to-fine** matcher with the gravimeter's deterministic seeded white noise recovers it to **≈ 145 m (< 500 m)** — stable across noise realisations, and provably refinement-limited (a single coarse grid stalls at ~2 km). Plus a **full IGRF-14 geomagnetic main-field model** (`src/igrf.rs`: the IAGA Schmidt-normalised spherical-harmonic field to degree/order 13, 2025.0 + secular variation, coefficients machine-generated from the official `igrf14coeffs.txt`; validated against the closed-form tilted dipole, a finite-difference of the scalar potential, and the known geomagnetic pole/strength) — the magnetic field a platform can map-match for magnetic-anomaly navigation. Plus **terrain-referenced navigation (TERCOM/SITAN)** and the **combined gravity+magnetic+terrain navigator** (`src/altpnt/terrain.rs`): a hand-rolled SRTM `.hgt` digital-elevation-model parser (16-bit signed big-endian, row-major, north-row-first, void -32768; validated against the GDAL SRTMHGT driver spec and a closed-form bilinear-midpoint oracle), a radar/baro **altimeter** model and `run_terrain_nav` matcher that recovers a GPS-denied track from the ground-elevation profile against the DEM, and `run_combined_altpnt` which fuses **three scalar field channels** per waypoint (Δg mGal · |B| nT crustal-anomaly · elevation m) so the joint posterior is sharper (lower CRLB) than any single field — bounded < 500 m over the 60-min outage and, in expectation, no worse than the best single channel. Plus **sequential (recursive) terrain-referenced navigation — SITAN as a running filter** (`src/altpnt/sequential.rs`, `run_sequential_trn`): the same altimeter-vs-DEM measurement model run **epoch by epoch** through the `particle_filter` SIR engine (predict by the INS increment + process noise → reweight by the terrain match → resample on degeneracy), so a **time-varying** INS drift is *tracked* along the track where the batch matcher only recovers a single constant offset — the recursive estimate stays bounded and re-converges (final ≈ 70 m) while the unaided solution diverges unbounded to ≈ 5 km, with per-epoch error following terrain distinctiveness and an effective-sample-size health monitor. Honest scope: the map is **known and fixed** — recursive *localization* against a stored DEM (the localization half of terrain SLAM), not joint map estimation. All four are now **scenario-engine `kind=` wired** (`gravity-map`, `terrain-nav`, `combined-altpnt`, `terrain-slam`) with an SVG drift chart (`scenarios/terrain-nav.toml`, `scenarios/combined-altpnt.toml`, `scenarios/terrain-slam.toml`). **Still missing: the full EGM2008/EIGEN coefficient set and its loader** (the gravity field is low-degree + mascons, not a real high-resolution map), a Monte-Carlo over map-representation-error realisations, and a real high-frequency **crustal** magnetic-anomaly map (the magnetic channel rides on the smooth IGRF main field plus synthetic crustal mascons; the CI terrain field is the self-contained synthetic DEM, with `#[ignore]`-gated real-SRTM-tile checks against published Whitney/Badwater spot-heights via `tools/fetch_srtm_tile.py`). P3 |
| Re-entry / EDL, Launch analysis, EO/payload | partial | First-order MODELLED geometry via three runnable kinds: **`reentry`** (`src/reentry.rs`, **Allen-Eggers** ballistic corridor — peak deceleration, peak-g and peak-heating velocities, peak-g altitude), **`launch-window`** (`src/launch.rs`, two-body **launch azimuth** `sin Az = cos i/cos lat`, plane-change Δv, site-rotation bonus, daily opportunities), and **`eo-coverage`** (`src/eo_payload.rs`, SMAD space-triangle EO **swath / GSD / access / revisit** geometry). **No** 6-DoF EDL/aerothermal sim, no trajectory optimiser, no sensor radiometry/MTF. P3 |
| Lunar / cislunar PNT (LunaNet) | partial | `src/lunar.rs`: a **lunar ARAIM** engine reusing the Earth-side MHSS core with LunaNet LNIS parameters (σ_URE ≈ 30 m, P_sat ≈ 1e-4), the **MCI↔MCMF cislunar frame reduction** (`mci_to_mcmf` / `mcmf_to_mci`, a simplified mean-rotation model at the sidereal rate) and **selenographic** lat/lon/alt (`mcmf_to_selenographic`), and a **south-pole protection-level pass** (`south_pole_hpl_pass`) that quantifies the integrity gap — with 30 m ranging the HPL is finite but exceeds a 50 m surface-ops alert limit. `src/cr3bp.rs` adds the Earth–Moon **CR3BP** (rotating-frame dynamics + RK4 propagator + Jacobi constant + the five Lagrange points, validated against the published L1/L2/L3 values and the exact L4/L5) — the three-body core a real NRHO needs — and a **state-transition-matrix + single-shooting differential corrector** (`cr3bp_jacobian`, `propagate_state_stm`, `differential_correct_halo`) that produces genuinely periodic L2 halo/NRHO orbits: the STM is validated against finite differences, corrected halos close on themselves to machine precision (Jacobi-conserving), and seeding the published apolune state reproduces the **L2 southern 9:2 NRHO** (the Gateway orbit) at **period ≈ 6.57 d** and **perilune ≈ 3,250 km** — consistent with the published ≈ 6.56 d / ≈ 3,370 km | The differential-corrected NRHO ICs are now wired in, but the **de-normalised selenocentric (MCI/MCMF) transform of the corrected orbit** and family-continuation are still follow-ons; the MCMF model omits physical libration / the precessing lunar pole (no DE421/SPICE); the NRHO is a CR3BP (circular, Sun-free) solution, **not** validated against a real LANS/Gateway ephemeris; a runnable `lunar-integrity` scenario kind (`scenarios/lunanet-araim.toml`) exposes the south-pole pass from the CLI | selenocentric transform + family continuation + SPICE/LunaNet interface: **P3** |
| Deep-space / interplanetary PNT (Mars, radiometric) | partial | **Shipped v0.17.0.** A radiometric navigation engine: iterative light-time + Shapiro delay, two-/one-/three-way Doppler & range (Moyer two-leg), coherent transponder turnaround, regenerative/PN ranging (CCSDS 414), Δ-DOR (CCSDS 506), solar-plasma/tropo/iono media (`src/radiometric.rs`); **CCSDS-TDM (503)** parse + emit (`src/ccsds_tdm.rs`); a **reduced-dynamic SRIF** with RTN empirical accelerations + a 3-state onboard clock + Mars drag (`src/deepspace_od.rs`, `clock_state.rs`, `mars_atmos.rs`) doing **Mars-LMO OD ≈ 0.2 m** in a synthetic closed loop; one-way+two-way fusion; a multi-body dynamics core (`src/body.rs`, Mars GMM-3, IAU Mars frame `src/mars_frame.rs`, an `EphemerisProvider` seam `src/ephem_provider.rs`, two-part JD + TT↔TDB); and the **`mars-pnt`** relay-PNT scenario (MARCONI areostationary constellation, `src/mars_pnt.rs`) + an end-to-end GSE performance simulator (`src/gse_sim.rs`). **Simulation-validated** (covariance/closed-loop FoM); Sun-central dynamics cross-checked vs JPL DE440 (137 m @ 1-day arc, `xval/anise-mars-od`). **Missing:** real DSN/ESTRACK tracking-data validation; a high-fidelity Mars gravity loader beyond GMM-3 d/o 4; DE-grade ephemeris in the core (kernel-gated in xval). P3 |

## Ecosystem & readiness (tracked honestly, not a code capability)

| Area | Status | Note |
|------|--------|------|
| Language bindings & packaging | partial | Rust + Python (abi3) + WASM on three registries; string-in/string-out bindings |
| Education / onboarding UX | partial | Browser playground (a real structural white-space); guided mode is roadmap |
| Community / governance | partial | Governance scaffolding present — `GOVERNANCE.md` (benevolent-maintainer model + technical bar + open/closed boundary), `CODE_OF_CONDUCT.md`, `CONTRIBUTING.md`, `SECURITY.md`, issue/PR templates, `FUNDING.yml`, dependabot. Single-founder; an **active external community** (contributors, citations) is people/time-dependent and still building (outreach founder-gated) |
| Funding & procurement readiness | none | TRL ~3; no agency citations/contracts yet (see strategy notes) |

_Last aligned with the 2026-06-02 grand audit's 27-row capability matrix; deep-space / Mars PNT row added in v0.17.0. Quantum-PNT additions (GNSS-denied clock holdover `src/holdover.rs`, composed quantum-inertial dead-reckoning budget `QuantumNavBudget`, ranging-code design-trade `CodeFamily`, machine-checked verification matrix `src/verification.rs`) folded into the Timing, Quantum-PNT-sensor, Nav-signal and V&V rows — each labelled validated-or-modelled per its actual oracle._

_FutureNAV demonstrator additions (modelled, internally cross-checked — **not** externally validated): (1) **AI/ML RF-impairment detection evaluation testbed** `src/impairment_eval.rs` — a labelled **synthetic** (parameter-grounded, not IQ) impairment corpus + a detector-agnostic ROC/AUC/confusion/Pfa-Pmd harness with a leakage guard and stratified split; the bundled detectors are transparent published-method baselines, not SOTA, and a high AUC here demonstrates the pipeline, not field performance. (2) **Quantum-vs-classical PNT trade engine** `src/quantum_trade.rs` — measured-ADEV ingestion (NNLS fit of `σ_y²(τ)=q_wf/τ + q_rw·τ/3 + q_drift·τ³/20`, round-trip-checked against `q_from_allan`), a timing/inertial-holdover benefit table that carries the floor-assumption caveat on the artifact, and a GNSS-denied resilience-vs-time envelope; it **quantifies** a partner's quantum benefit, never validates the device. Both adversarially reviewed (a τ²→τ³ drift-basis bug and a false-"bounded-indefinitely" resilience claim were caught and fixed). 911 lib tests, fmt+clippy clean._

_Interchange / standard-format addition (`src/interchange.rs`): the **Kshana Interchange Format (KIF)** — a neutral, versioned, self-describing `Envelope` that wraps any artifact (scenario, result, trade study) with a recognisable `format` tag, the single-source-of-truth `SCHEMA_VERSION` (the schema version, formerly copied as a literal in 15 places, is now owned in one constant the whole crate references), the producing `engine_version`, and an explicit, tested compatibility contract (`compatibility()`: same-major / equal-or-older-minor is readable under the additive-field discipline; a newer minor or a different major is refused on the boundary by `Envelope::parse` rather than silently mis-parsed). Round-trippable (`wrap`→`to_json`→`parse`→`payload_as::<T>()`) for any `Deserialize` payload; deliberately **timestamp-free** to preserve Kshana's bit-for-bit reproducibility. Documented in [`SCHEMA.md`](SCHEMA.md) so the format is **citable**, not merely emitted — the open-core "standard-in-waiting" positioning. 923 lib tests, fmt+clippy clean._

_FutureNAV dominance-build additions (modelled, internally cross-checked — **not** externally validated): (1) **Frugal cost-per-coverage / ROI layer** `src/frugal.rs` — a benefit-framing layer over the constellation-sizing engine (`walker`) that reports cost-per-percentage-point-of-coverage and coverage-per-euro ROI vs a baseline; per-satellite cost is a **caller-supplied, sourced low/nominal/high bracket** (no fabricated point prices), so outputs are ranges, not spurious points; a modelled economic framing of a modelled coverage figure, not a quote. (2) **Detection-miss integrity-impact mapping** `src/integrity_impact.rs` — maps an undetected spoof/jam-induced position bias to its effective error → Stanford region (available / system-unavailable / misleading / hazardously-misleading) against **context-specific alert limits** (open-sky vs urban, HAL vs VAL), composing the externally-anchored RAIM `classify_stanford`; the detection-miss→alert-limit bridge is modelled, not a certified integrity allocation. Both are mapped into the machine-checked verification matrix (`src/verification.rs`, now 89 rows, Validated⇒ExternalDataset invariant intact). The cross-validation / leakage-guard / parameter-stratified split for the AI-evaluation harness was already shipped in `src/impairment_eval.rs` (`stratified_split`, `Split::has_leakage`). 951 lib tests, fmt+clippy clean._

_FutureNAV optimism-gap study additions (modelled, internally cross-checked against closed forms — **not** externally validated, **not** a sim-to-field claim): a controlled **synthetic** study of the in-distribution→out-of-distribution AUC **optimism gap** for RF-impairment detectors. (1) **Learned detectors** `src/impairment_ml.rs` — a fixed feature map + train-fit standardiser, a logistic-regression baseline (deterministic full-batch gradient descent), and a one-hidden-layer **MLP** (seeded backprop SGD) behind the same `ImpairmentDetector` trait the published-method baselines use. (2) **Hand-derived statistics** `src/eval_stats.rs` — percentile-bootstrap CIs, **DeLong** AUC variance/CI, **Spearman** ρ, and **ridge** regression, each checked against a closed form (binormal AUC Φ(d′/√2), a hand-worked DeLong variance, a textbook tied-rank ρ, exact OLS recovery). (3) **The study** `src/impairment_study.rs` — per-class AUC, the per-`(detector,class)` scaling-law trend (gap vs 1−severity), and an **ID-only ridge gap predictor** that estimates the optimism gap from in-distribution diagnostics alone, scored **leave-one-detector-out** and **leave-one-class-out** against a predict-the-mean baseline. One-command artifact via `cargo run --release --example optimism_study`. Every number is an AUC over model-derived labels on a synthetic, parameter-grounded corpus; the gap is a synthetic→synthetic severity shift, never a field-detection result. Mapped into the machine-checked verification matrix (`src/verification.rs`, Validated⇒ExternalDataset invariant intact)._