Files
ruvnet--RuView/docs/adr/ADR-279-native-rf-frame-contract.md
T
rUv 2e018f4f19 feat(ruview-unified): Unified RF spatial world model — ADR-273..282 (#1437)
Native frame contract, universal RF encoder, RF-aware Gaussian spatial memory, physics-guided synthetic RF worlds, edge sensing control plane, BLE-CS + factorized pose. All 10 ADRs (273-282) fully implemented and tested (99 tests); ADR-278 (radar inverse rendering) honestly gated with zero code as a future research program.

Deep-reviewed and hardware-tested against a live ESP32-C6 CSI node before merge: fixed a reachable panic, a silent NaN-corruption path, a cross-entity Gaussian conflation bug, and a wrong-center-frequency bug in the WiFi adapter (confirmed live: was misreporting channel 4 as 2437 MHz, now correctly reports 2427 MHz matching the hardware parser exactly). Added a standing hardware-in-the-loop test (examples/esp32_live_hardware_test.rs). Also fixed unrelated pre-existing issues surfaced during validation (wifi-densepose-core clippy warnings, a ruview-auth Windows build break, a sensing-server test flake).

Full review: https://gist.github.com/ruvnet/89795f3c4b8ea166cff5ac35ae4c7651
2026-07-26 14:37:56 -07:00

5.3 KiB
Raw Blame History

ADR-279: Native RF frame contract — RfFrameV2 is authoritative, the canonical tensor is a derived view

Field Value
Status Accepted — implemented (ruview-unified/src/frame.rs; 5 invariant tests)
Date 2026-07-26
Parent ADR-273 (amends ADR-274 §2)
Relates to ADR-136 (CanonicalFrame — extended, not replaced), ADR-262 (provenance discipline), ADR-282 (evidence ladder policy)

0. PROOF discipline

Grades per ADR-273 §0. This ADR is a correction to ADR-274 §2, adopted before any measured-data debt accumulates.

1. Context — the architectural correction

ADR-274 made the 56-bin × 8-snapshot canonical RfTensor the adapter output, which is right for compatibility but wrong as the authoritative format: resampling every device into one fixed tensor discards bandwidth (a 320 MHz 802.11bk capture and a 20 MHz 802.11n capture become indistinguishable), antenna structure, phase state, and hardware-specific information a foundation encoder should learn from (the WiLLM lesson: lightweight per-device adapters into a shared latent, not a shared tensor). RuView's own history proves the cost of premature canonicalization — MERIDIAN's normalizer is useful precisely because the native data was still around.

2. Decision — RfFrameV2

The authoritative record preserves the native capture. Fields per the implementation: schema version, frame id, timestamp, modality (now including WifiCir, WifiBfReport, FmcwRangeAzimuth, FmcwDopplerAzimuth alongside CSI/SRS/FMCW/UWB/BLE-CS), declared native axes (FieldAxis: time/frequency/delay/Doppler/range/azimuth/elevation/antenna/polarization), centre frequency, bandwidth, sample rate, arbitrary-rank native_shape + native_iq + explicit valid_mask, TX/RX Pose3 in one building frame, AntennaElement geometry, sample_age_ns, CalibrationState with a declared PhaseState (Raw | Sanitized | Calibrated | Unavailable), SignalQuality, and FrameProvenance.

Seven required invariants, each enforced in the validated constructor or proven by a test:

  1. Native samples are never overwrittento_canonical(&self) is read-only; canonical_view_is_derived_and_native_is_untouched asserts byte-identical native IQ + mask after derivation.
  2. Subcarrier/antenna masks are explicit (valid_mask, arity-checked).
  3. Phase declares its state — consumers branch on PhaseState instead of guessing whether detrending happened.
  4. TX/RX geometry uses one building coordinate system (Pose3).
  5. Results retain source identity via receipt_id (consumed by the Gaussian memory's source_receipts lineage, ADR-275).
  6. Synthetic and measured frames can never share a provenance class, strengthened to an evidence rule: Synthetic ⇒ exactly L0Simulation, Measured ⇒ ≥ L1CapturedReplay — both directions rejected at construction (synthetic_and_measured_provenance_can_never_alias).
  7. Sample age is carried through the whole path (frame → tensor → age gate → BoundedEvent).

3. The canonical tensor is demoted to a compatibility view

RfFrameV2::to_canonical() derives the ADR-274 tensor through the exact same normalization code path as every adapter (adapters::normalize_grid — one normalization, many entry points), after mask-aware gap-filling (invalid bins interpolated from nearest valid neighbors on the complex plane). Rank ≠ 3 frames have no canonical projection and say so with a typed error. The existing ESP32/Intel/Atheros 114→56 projections stay as-is; they simply stop being the storage format.

4. The mandatory split manifest

The brief's leakage rule is now code: PartitionKey gains a session dimension (packet-session leakage is as real as room leakage) and eval::SplitManifest certifies per-dimension disjointness across all seven dimensions (room/day/person/chipset/firmware/layout/session):

train_rooms ∩ test_rooms = ∅ … train_sessions ∩ test_sessions = ∅

fully_disjoint() is the bar for reporting a result as leakage-resistant; a room-holdout split that still shares people says so in its manifest instead of masquerading (test split_manifest_certifies_per_dimension_disjointness). The hidden real-world test set requirement (never accessible to synthetic generation/calibration) is process, recorded in ADR-282 §4.

5. Consequences

  • New hardware (PicoScenes, Intel, Atheros, Realtek radar, 320 MHz 802.11bk) lands as an RfFrameV2 producer + latent adapter; nothing is lost at ingest. Vendor conformance receipt = the constructor's invariants (native shape preserved, phase state declared, timestamps monotonic, geometry present, loss measured, synthetic flag correct).
  • The encoder input contract (ADR-274) is unchanged today (it consumes the derived view); migrating the tokenizer to native-resolution tokens is the flagged follow-up once real multi-bandwidth data exists (P2).
  • Storage cost rises (native + derived); accepted — the derived view can always be recomputed, the native never can be.

6. Verification

cargo test -p ruview-unified frame:: — 5 tests: provenance aliasing, shape/mask/axes arity, derived-view purity + gap-filling, rank/geometry rejection, P3162 import-profile validation (SyntheticApertureSoundingDataset, ADR-281 §5). All MEASURED-CODE.