BaselineDriftDetector compared `mean_amplitude` against its EWMA baseline with *absolute* thresholds (anomaly 1.0, drift 0.15). Fine for the synthetic unit tests (amplitudes ~1.0), but raw ESP32 CSI is int8 I/Q with amplitudes up to ~128, so window-to-window RMS distance is routinely 5-50 >> 1.0 and AnomalyDetected fired on ~96% of windows (319/331 on a real node-1 capture). Drift is now `||current - baseline||2 / ||baseline||2` (a fraction, with an eps floor that falls back to absolute for a degenerate near-zero baseline), so one tuning is valid across raw-int8 ESP32, int16-scaled Nexmon, and baseline-subtracted streams. AnomalyDetected drops to 40/331 on the same data; the existing detector tests still pass (their explicit configs are valid relative thresholds too); added baseline_drift_is_scale_invariant_ no_anomaly_storm. rvcsi-events 18 -> 19 tests; 162 rvcsi tests, 0 failures, clippy-clean. Surfaced by an end-to-end test against real ESP32 CSI on COM7: the device (ESP32-S3, node 1, ADR-018 firmware, WiFi "ruv.net" ch5 RSSI -39, CSI cb only because nothing listens at .156). rvcsi has no ESP32 adapter yet, so a 7,000-frame node-1 recording was transcoded to .rvcsi via the new scripts/esp32_jsonl_to_rvcsi.py (stand-in for `record --source esp32-jsonl`) and run through `rvcsi inspect`/`replay`/`calibrate`/`events` end-to-end. ADR-095 D13 and ADR-096 sections 2.1/5 updated; CHANGELOG entry added; rvcsi-adapter-esp32 (live serial/UDP source) noted as a follow-up. Co-Authored-By: claude-flow <ruv@ruv.net>
14 KiB
ADR-095: rvCSI — Edge RF Sensing Runtime Platform
| Field | Value |
|---|---|
| Status | Proposed |
| Date | 2026-05-12 |
| Deciders | ruv |
| Codename | rvCSI — RuVector Channel State Information runtime |
| Relates to | ADR-012 (ESP32 CSI mesh), ADR-013 (feature-level sensing on commodity gear), ADR-014 (SOTA signal processing), ADR-016 (RuVector integration), ADR-024 (AETHER contrastive embeddings), ADR-031 (RuView sensing-first RF mode), ADR-040 (WASM programmable sensing), ADR-049 (cross-platform WiFi interface detection) |
| PRD | rvCSI Platform PRD |
| Domain model | rvCSI Domain Model |
1. Context
WiFi Channel State Information (CSI) is a powerful camera-free sensing primitive — but in practice it is hard to operationalize. Most CSI pipelines today are Linux shell scripts, patched firmware, kernel modules, Python notebooks, PCAP dumps, and ad-hoc signal processing. Packet formats are inconsistent across chips; drivers are unstable; malformed packets are common; and device-specific assumptions leak everywhere. CSI works in the lab and falls over in the field.
RuView already contains substantial CSI infrastructure (wifi-densepose-signal, wifi-densepose-ruvector, the ESP32 mesh of ADR-012, the RuView multistatic work of ADR-031). What is missing is a stable, hardware-abstracted runtime layer that:
- ingests CSI from many sources behind one interface,
- validates every packet before it can touch application code,
- normalizes everything into one schema,
- runs reusable signal processing,
- emits typed, confidence-scored events,
- exposes a safe TypeScript SDK, a CLI, MCP tools, and a RuVector bridge,
- and runs unattended on Raspberry Pi-class hardware.
This ADR establishes that runtime — rvCSI — and the architectural decisions that constrain it. Detailed requirements are in the PRD; the bounded contexts, aggregates, and ubiquitous language are in the domain model.
1.1 What rvCSI is not (day one)
rvCSI is not a pure-Rust replacement for vendor firmware patches, not a universal driver for all WiFi chips, and not an identity/pose/medical/legal-grade claim. It is a structural sensing runtime: excellent at detecting change, presence, motion, drift, and learned patterns; deliberately silent on exact identity, exact pose, and certainty guarantees. The product surface stays inside that boundary (see Decision D7).
1.2 Existing assets rvCSI builds on
| Asset | Source | Reuse in rvCSI |
|---|---|---|
| SOTA DSP (Hampel, phase unwrap, Fresnel, BVP, spectrograms) | wifi-densepose-signal (ADR-014) |
rvcsi-dsp wraps/extends rather than re-implements |
| RuVector integration (5 crates) | wifi-densepose-ruvector (ADR-016) |
rvcsi-ruvector exporter rides on the existing integration |
| ESP32 CSI firmware + aggregator | wifi-densepose-hardware / firmware (ADR-012) |
rvcsi-adapter-esp32 consumes the existing serial/UDP stream |
| AETHER contrastive embeddings | ADR-024 | optional embedding backend for window/event vectors |
| Cross-platform interface detection | ADR-049 | adapter discovery / health checks |
2. Decision
Adopt rvCSI as a layered edge RF sensing runtime with the boundary discipline C → Rust → TypeScript, a single normalized CsiFrame schema, mandatory validation before any language boundary crossing, and RuVector as RF memory. The fifteen decisions below are the architectural contract.
D1 — Rust is the core runtime
CSI parsing and DSP require memory safety, predictable latency, and high throughput; C/Python research stacks are fragile for unattended edge deployment. rvCSI uses Rust for parsing, validation, signal processing, event extraction, and daemon execution. Consequences: safer packet handling; better long-running stability; stronger portability to edge devices; more complex build system than pure TypeScript.
D2 — C only at the hardware-compatibility boundary
Nexmon and similar CSI sources often require C shims, legacy drivers, or firmware-patch hooks. C is isolated to thin shims for existing capture and firmware compatibility — never in the data path beyond decode. Consequences: existing Nexmon capability reused; unsafe surface stays small; full firmware rewrite avoided; some device support stays dependent on upstream tools.
D3 — TypeScript for SDK, CLI, and developer orchestration
Developers need an approachable SDK, agent integrations, dashboards, and scripts. rvCSI exposes a first-class TypeScript SDK (@ruv/rvcsi) and CLI; native performance stays in Rust.
Consequences: easy adoption by app/agent developers; native perf preserved; requires a native build + prebuild release pipeline.
D4 — napi-rs for Node bindings
Native Node modules need a stable ABI and ergonomic Rust integration. rvCSI uses napi-rs for the rvcsi-node bindings.
Consequences: Rust exposes typed APIs to TypeScript; prebuilt binaries distributable; careful memory-ownership rules required.
D5 — Normalize all sources into one CsiFrame / CsiWindow schema
Different CSI sources expose incompatible formats; application code must not know device-specific details. Every source is normalized into CsiFrame and CsiWindow (schema in the domain model).
Consequences: hardware-agnostic application code; easier RuVector integration; some source-specific metadata needs extension fields.
D6 — Validate before crossing language boundaries
Malformed packets and unsafe pointers are the dominant stability risk. All raw data is validated in Rust before it crosses into TypeScript or RuVector; rejected frames are quarantined (when enabled); parser failures return structured errors; TypeScript never receives raw unchecked pointers. Consequences: safer SDK; cleaner error model; small validation overhead.
D7 — Treat CSI as a temporal delta, not absolute truth
CSI is noisy and environment-specific. rvCSI frames CSI as a temporal delta stream against learned baselines, not as exact vision. Consequences: honest product claims; good fit for presence/motion/drift/anomaly; identity and exact pose excluded from core claims.
D8 — RuVector is RF memory
CSI becomes far more valuable stored as temporal embeddings and room signatures. rvCSI integrates with RuVector for vector storage, similarity search, drift detection, and sensor-graph relationships. Consequences: rvCSI joins the broader ruvnet cognitive stack; RF field history becomes queryable; requires embedding design and retention policy.
D9 — Design for replayability
Signal algorithms need repeatable benchmarks and debugging. rvCSI supports deterministic replay of captured sessions (timestamps, ordering, validation decisions, event output, calibration version, runtime config all preserved). Consequences: easier testing; better audit trail; enables benchmark datasets.
D10 — Separate detection from decision
rvCSI detects RF events; agents/applications decide what to do. rvCSI emits events with confidence and evidence and performs no high-consequence actions by default. Consequences: cleaner safety model; clean integration with Cognitum proof-gated execution; applications implement policy.
D11 — Local-first operation
RF sensing is privacy-sensitive and often valuable offline. rvCSI runs locally by default and requires no cloud service; remote observability is opt-in. Consequences: better privacy posture; usable in industrial/care/sovereign deployments; remote observability must be explicitly enabled.
D12 — MCP tools are read-first, write-gated
Agents should observe RF state safely; device mutation and calibration change system behavior. MCP tools default to read actions; capture start/stop, calibration, and export are gated. Consequences: safer agent integration; lower accidental device disruption; more explicit operational control.
D13 — Quality scoring is mandatory
CSI quality varies widely by chip, antenna, environment, channel, and interference. Every frame, window, and event carries quality or confidence scoring.
Consequences: downstream systems can suppress weak evidence; easier debugging; requires calibration and thresholds. Where a detector compares against a learned baseline (e.g. baseline-drift / anomaly), thresholds are expressed relative to the baseline's magnitude, not as absolute amplitude units, so a single tuning is valid across sources whose raw CSI scales differ by orders of magnitude (raw int8 ESP32 vs. int16-scaled Nexmon vs. baseline-subtracted streams).
D14 — Versioned calibration profiles
Room baselines change over time. Calibration profiles are versioned, and event outputs reference the calibration version used. Consequences: more auditable detection; replay can reproduce prior outputs; slight storage overhead.
D15 — Hardware adapters are plugins
Device support will evolve and vary by platform. Source adapters are plugins behind a common Rust trait (CsiSource).
Consequences: easier support for Nexmon/ESP32/Intel/Atheros/SDR/future sources; cleaner testability; adapter certification becomes important.
3. Architecture
CSI Source
↓ ┌─ Capture context ──────────────┐
Adapter Layer (C shims here) │ Source · CaptureSession · │
↓ │ AdapterProfile │
Rust Validation Pipeline ─────┤ Validation context │
↓ │ ValidationPolicy · Quarantine │
Normalized CsiFrame ──────────┘ ← FFI-safe boundary object
↓ ┌─ Signal context ───────────────┐
Signal Processing │ SignalPipeline · WindowBuffer │
↓ ├─ Calibration context ──────────┤
Window Aggregator ───────────┤ CalibrationProfile · │
↓ │ RoomSignature · BaselineModel │
Event Extractor ─────────────┤ Event context │
↓ │ EventDetector · StateMachine │
TS SDK · CLI · MCP · RuVector └─ Memory + Agent contexts ──────┘
Crates (within RuView's v2/crates/, or a standalone rvcsi/crates/):
rvcsi-core · rvcsi-adapter-file · rvcsi-adapter-nexmon · rvcsi-adapter-esp32 · rvcsi-dsp · rvcsi-events · rvcsi-ruvector · rvcsi-daemon · rvcsi-node · rvcsi-mcp — plus TypeScript packages sdk, cli, dashboard, and native/nexmon-shim-c.
See the PRD §9 for the full component table and reference layout, and the domain model for bounded contexts, aggregates, invariants, and domain services.
4. Consequences
Positive
- CSI becomes reusable infrastructure: npm-installable, reproducible, typed, safe-parsed, embeddable, WebSocket-streamable, WASM-portable, MCP-exposed, agent-integrable.
- One application codebase works across Nexmon, ESP32, Intel, and Atheros sources.
- Bad packets cannot crash the daemon; unattended operation becomes realistic.
- RuView/RuVector/Cognitum/agents gain a validated live source of RF observations.
- Honest product framing ("structural sensing") avoids over-claiming.
Negative / costs
- Larger build surface: Rust core + napi-rs native module + C shims + TypeScript packages + prebuild pipeline.
- Adapter certification and a supported-hardware matrix become ongoing maintenance.
- Embedding design, calibration thresholds, and retention policy are non-trivial open questions (tracked in the PRD).
- Risk of duplicating
wifi-densepose-signal/wifi-densepose-ruvector; mitigated by wrapping, not re-implementing.
Risks
- Nexmon coupling: some device support remains dependent on upstream firmware/driver projects.
- CSI quality variance: weak-signal environments may yield low-confidence events; mitigated by mandatory quality scoring (D13) and versioned calibration (D14).
5. Alternatives considered
| Alternative | Why not |
|---|---|
| Pure-Python runtime (extend the v1 stack) | Fragile under malformed packets; GC pauses break the < 50 ms latency target; poor unattended stability. |
| Pure-Rust including firmware (replace Nexmon) | Enormous scope; vendor-specific; would block v0 indefinitely. D2 keeps C at the boundary instead. |
| Per-source SDKs (no normalized schema) | Pushes device specifics into application code; defeats the "same app code across adapters" success criterion. |
| WASM-only core | No raw socket / serial / monitor-mode access for live capture; fine for offline parsing (a later target) but not v0 live capture. |
| Cloud-first ingestion | Violates the privacy posture and the local-first requirement; unacceptable for care/industrial/sovereign deployments. |
6. Implementation phases (proposed)
- v0 —
rvcsi-core+ file/replay/ESP32 adapters + validation +rvcsi-dsp(presence/motion) +rvcsi-nodeSDK +rvcsi-cli+ WebSocket output +rvcsi-ruvectorexport + basic calibration + health checks. Targets all eight PRD success criteria. - v1 — multi-node sync, RF room signatures, breathing-rate where signal permits, temporal embeddings, drift detection, room-topology graph,
rvcsi-mcptool server, replayable benchmark datasets, RuView sensor fusion, Cognitum deployment profile. - v2 — hardware-agnostic RF sensor fabric, multi-room RF memory, streaming anomaly detection, RF-SLAM research mode, on-device embedding model, federated room-signature learning, signed sensor-evidence records, proof-gated event publication, dynamic cut-based coherence over RF graphs, agent-driven calibration and self-repair.
7. References
- rvCSI Platform PRD
- rvCSI Domain Model
- ADR-012 — ESP32 CSI Sensor Mesh
- ADR-013 — Feature-Level Sensing on Commodity Gear
- ADR-014 — SOTA Signal Processing
- ADR-016 — RuVector Integration
- ADR-024 — Project AETHER: Contrastive CSI Embeddings
- ADR-031 — RuView Sensing-First RF Mode
- ADR-040 — WASM Programmable Sensing
- ADR-049 — Cross-Platform WiFi Interface Detection