mirror of
https://github.com/ruvnet/RuView
synced 2026-07-27 18:11:43 +00:00
2e018f4f19
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
55 lines
5.3 KiB
Markdown
55 lines
5.3 KiB
Markdown
# 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 overwritten** — `to_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):
|
||
|
||
```text
|
||
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.
|