docs: rvCSI edge RF sensing platform — PRD, ADR-095, DDD domain model
Adds design documentation for rvCSI, a Rust-first / TypeScript-accessible / hardware-abstracted edge RF sensing runtime that normalizes WiFi CSI from Nexmon, ESP32, Intel, Atheros, file and replay sources into one validated CsiFrame schema, runs reusable DSP, emits typed confidence-scored events, and bridges to RuVector RF memory, an MCP tool server and a TS SDK. - docs/prd/rvcsi-platform-prd.md — purpose, users, success criteria, FR1-FR10, NFRs (safety/perf/reliability/privacy/security/portability), system architecture, runtime components, reference layout, data model - docs/adr/ADR-095-rvcsi-edge-rf-sensing-platform.md — the 15 architectural decisions (Rust core, C-at-the-boundary, TS SDK via napi-rs, normalized schema, validate-before-FFI, CSI-as-temporal-delta, RuVector as RF memory, replayability, detection != decision, local-first, read-first/write-gated MCP, mandatory quality scoring, versioned calibration, plugin adapters) - docs/ddd/rvcsi-domain-model.md — 7 bounded contexts (Capture, Validation, Signal, Calibration, Event, Memory, Agent) with aggregates, invariants, context map, data model and domain services - indexed in docs/adr/README.md and docs/ddd/README.md; CHANGELOG entry Design-only; no code or crates added yet. https://claude.ai/code/session_01CdYAPvRTjcch6YrYf42n1z
This commit is contained in:
parent
6f77b37f5e
commit
d98b7e3f65
|
|
@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
tracked in the PR.
|
||||
|
||||
### Added
|
||||
- **rvCSI platform design — PRD, ADR-095, and DDD domain model.** New design documents for **rvCSI**, a Rust-first / TypeScript-accessible / hardware-abstracted edge RF sensing runtime that normalizes CSI from Nexmon, ESP32, Intel, Atheros, file, and replay sources into one validated `CsiFrame` schema, runs reusable DSP, emits typed confidence-scored events, and bridges to RuVector RF memory, an MCP tool server, and a TypeScript SDK. Adds `docs/prd/rvcsi-platform-prd.md` (purpose, users, success criteria, FR1–FR10, NFRs, system architecture, data model), `docs/adr/ADR-095-rvcsi-edge-rf-sensing-platform.md` (the 15 architectural decisions: Rust core, C-at-the-boundary, TS SDK via napi-rs, normalized schema, validate-before-FFI, CSI-as-temporal-delta, RuVector as RF memory, replayability, detection≠decision, local-first, read-first/write-gated MCP, mandatory quality scoring, versioned calibration, plugin adapters), and `docs/ddd/rvcsi-domain-model.md` (7 bounded contexts: Capture, Validation, Signal, Calibration, Event, Memory, Agent — with aggregates, invariants, context map, and domain services). Indexed in `docs/adr/README.md` and `docs/ddd/README.md`. Design-only; no code or crates added yet.
|
||||
- **`wifi-densepose-train`: `signal_features` module — wires `wifi-densepose-signal` into the training pipeline.** `wifi-densepose-signal` was previously a phantom dependency of `wifi-densepose-train` (listed in `Cargo.toml`, never imported). New `wifi_densepose_train::signal_features::extract_signal_features` (and `CsiSample::signal_features()`) run a windowed CSI observation's centre frame through `wifi_densepose_signal::features::FeatureExtractor`, producing a fixed-length (`FEATURE_LEN = 12`) amplitude/phase/PSD feature vector — the hook for a future vitals / multi-task supervision head (breathing- and heart-rate-band power are read off the PSD summary). The vector is produced on demand and not yet fed back into the loss. Surfaced by the 2026-05-11 training-pipeline audit (findings #1 "vitals features absent from training" and #2 "`wifi-densepose-signal` ghost dep").
|
||||
- **`wifi-densepose-train`: `TrainingConfig` subcarrier-layout presets + a real-loader integration test.** New `TrainingConfig::for_subcarriers(native, target)` plus named presets `ht40_192()` (≈192-sc ESP32 HT40 → 56) and `multiband_168()` (168-sc ADR-078 multi-band mesh → 56), so non-MM-Fi CSI shapes are first-class instead of requiring manual `native_subcarriers`/`num_subcarriers` overrides; field docs now list the supported source counts and the multi-NIC mapping. New `tests/test_real_loader.rs` round-trips synthetic CSI through `.npy` files → `MmFiDataset::discover`/`get` (including the subcarrier-interpolation branch and the empty-root case) — exercising the on-disk loader path the deterministic `verify-training` proof intentionally bypasses. Addresses training-pipeline audit findings #6 (56-sc/1-NIC config default) and #7 (multi-band mesh not in config); the #4 concern ("proof uses synthetic data") is reframed — the proof *should* use a reproducible source, and this test covers the real loader it skips.
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,210 @@
|
|||
# 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](../prd/rvcsi-platform-prd.md) |
|
||||
| **Domain model** | [rvCSI Domain Model](../ddd/rvcsi-domain-model.md) |
|
||||
|
||||
---
|
||||
|
||||
## 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](../prd/rvcsi-platform-prd.md); the bounded contexts, aggregates, and ubiquitous language are in the [domain model](../ddd/rvcsi-domain-model.md).
|
||||
|
||||
### 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.
|
||||
|
||||
### 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](../prd/rvcsi-platform-prd.md#9-system-architecture) for the full component table and reference layout, and the [domain model](../ddd/rvcsi-domain-model.md) 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)
|
||||
|
||||
1. **v0** — `rvcsi-core` + file/replay/ESP32 adapters + validation + `rvcsi-dsp` (presence/motion) + `rvcsi-node` SDK + `rvcsi-cli` + WebSocket output + `rvcsi-ruvector` export + basic calibration + health checks. Targets all eight PRD success criteria.
|
||||
2. **v1** — multi-node sync, RF room signatures, breathing-rate where signal permits, temporal embeddings, drift detection, room-topology graph, `rvcsi-mcp` tool server, replayable benchmark datasets, RuView sensor fusion, Cognitum deployment profile.
|
||||
3. **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](../prd/rvcsi-platform-prd.md)
|
||||
- [rvCSI Domain Model](../ddd/rvcsi-domain-model.md)
|
||||
- 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
|
||||
|
|
@ -105,6 +105,7 @@ Statuses: **Proposed** (under discussion), **Accepted** (approved and/or impleme
|
|||
| [ADR-011](ADR-011-python-proof-of-reality-mock-elimination.md) | Proof-of-Reality and Mock Elimination | Proposed |
|
||||
| [ADR-026](ADR-026-survivor-track-lifecycle.md) | Survivor Track Lifecycle (MAT crate) | Accepted |
|
||||
| [ADR-038](ADR-038-sublinear-goal-oriented-action-planning.md) | Sublinear GOAP for Roadmap Optimization | Proposed |
|
||||
| [ADR-095](ADR-095-rvcsi-edge-rf-sensing-platform.md) | rvCSI — Edge RF Sensing Runtime Platform | Proposed |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ DDD organizes the codebase around the problem being solved — not around techni
|
|||
| [Sensing Server](sensing-server-domain-model.md) | Single-binary Axum server: CSI ingestion, model management, recording, training, visualization | 5 contexts: CSI Ingestion, Model Management, CSI Recording, Training Pipeline, Visualization |
|
||||
| [WiFi-Mat](wifi-mat-domain-model.md) | Disaster response: survivor detection, START triage, mass casualty assessment | 3 contexts: Detection, Localization, Alerting |
|
||||
| [CHCI](chci-domain-model.md) | Coherent Human Channel Imaging: sub-millimeter body surface reconstruction | 3 contexts: Sounding, Channel Estimation, Imaging |
|
||||
| [rvCSI](rvcsi-domain-model.md) | Edge RF sensing runtime: multi-source CSI ingestion, validation, normalization, event extraction, RuVector RF memory, agent/MCP integration | 7 contexts: Capture, Validation, Signal, Calibration, Event, Memory, Agent |
|
||||
|
||||
## How to read these
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,395 @@
|
|||
# rvCSI — Edge RF Sensing Runtime Domain Model
|
||||
|
||||
## Domain-Driven Design Specification
|
||||
|
||||
> Companion documents: [rvCSI Platform PRD](../prd/rvcsi-platform-prd.md) · [ADR-095 — rvCSI Edge RF Sensing Platform](../adr/ADR-095-rvcsi-edge-rf-sensing-platform.md)
|
||||
|
||||
### Domain
|
||||
|
||||
Camera-free RF spatial sensing from WiFi Channel State Information (CSI).
|
||||
|
||||
### Core domain
|
||||
|
||||
**RF field interpretation.** rvCSI converts noisy radio channel measurements into validated events and temporal embeddings that represent changes in physical space. CSI is treated as a *temporal delta stream* against learned baselines — not as exact vision.
|
||||
|
||||
### Supporting subdomains
|
||||
|
||||
Hardware adapter management · packet parsing · signal processing · calibration · event extraction · temporal memory · agent integration · replay and audit.
|
||||
|
||||
### Generic subdomains
|
||||
|
||||
Logging · configuration · CLI parsing · WebSocket streaming · package publishing · dashboard visualization.
|
||||
|
||||
---
|
||||
|
||||
## Ubiquitous Language
|
||||
|
||||
| Term | Definition |
|
||||
|------|------------|
|
||||
| **CSI** | Channel State Information — per-subcarrier complex channel response measured by a WiFi receiver |
|
||||
| **Source** | A physical or replayed producer of CSI frames (a NIC, an ESP32 node, a PCAP file, a recorded capture) |
|
||||
| **Adapter** | A software module that knows how to receive and decode source-specific CSI and normalize it into a `CsiFrame` |
|
||||
| **Frame** | One CSI observation at a timestamp — the unit of ingestion |
|
||||
| **Window** | A bounded sequence of frames from one source/session, used for analysis |
|
||||
| **Baseline** | The learned normal RF-field state for a space |
|
||||
| **Delta** | The measured difference of the current field from baseline |
|
||||
| **Event** | A semantic interpretation of one or more windows (presence started, motion detected, anomaly, …) |
|
||||
| **Quality score** | Confidence, in [0, 1], that a signal/frame/window is usable |
|
||||
| **Calibration** | The process of learning a stable baseline for a space |
|
||||
| **Room signature** | A vector representation of a space under normal conditions |
|
||||
| **Drift** | Slow movement of the field away from baseline |
|
||||
| **Anomaly** | A significant, unexplained deviation from baseline |
|
||||
| **RF memory** | Persisted temporal vectors and events for a physical space (stored in RuVector) |
|
||||
| **Coherence** | Consistency among sources, windows, and learned baselines |
|
||||
| **Quarantine** | A holding store for rejected/corrupt frames, kept for audit rather than discarded |
|
||||
| **Adapter profile** | A capability descriptor for a source (chip, firmware/driver versions, supported channels/bandwidths, expected subcarrier counts, capture/injection/monitor-mode support) |
|
||||
| **Calibration version** | An immutable identifier for a particular learned baseline; every event references the calibration version it was detected against |
|
||||
| **Evidence window set** | The set of `WindowId`s an event references as its justification — an event with no evidence is invalid |
|
||||
|
||||
---
|
||||
|
||||
## Bounded Contexts
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌──────────────┐ ┌────────────┐ ┌──────────────┐
|
||||
│ Capture │──▶│ Validation │──▶│ Signal │──▶│ Calibration │
|
||||
│ context │ │ context │ │ context │ │ context │
|
||||
└─────────────┘ └──────────────┘ └─────┬──────┘ └──────┬───────┘
|
||||
│ │
|
||||
▼ │
|
||||
┌────────────┐ │
|
||||
│ Event │◀──────────┘
|
||||
│ context │
|
||||
└─────┬──────┘
|
||||
│
|
||||
┌─────────────┴─────────────┐
|
||||
▼ ▼
|
||||
┌────────────┐ ┌────────────┐
|
||||
│ Memory │ │ Agent │
|
||||
│ context │ │ context │
|
||||
└────────────┘ └────────────┘
|
||||
```
|
||||
|
||||
- **Capture** upstreams raw input from sources.
|
||||
- **Validation** protects every downstream context — nothing crosses into SDK/DSP/memory/agents unvalidated.
|
||||
- **Signal** turns frames into windows.
|
||||
- **Calibration** gives windows a room-specific baseline.
|
||||
- **Event** converts deltas into meaning.
|
||||
- **Memory** stores time, similarity, drift, and coherence (RuVector).
|
||||
- **Agent** exposes safe actions and queries (MCP / TypeScript).
|
||||
|
||||
---
|
||||
|
||||
### 1. Capture context
|
||||
|
||||
**Responsibility:** connect to CSI sources and produce raw frames.
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ Capture Context │
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ ┌────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
|
||||
│ │ Source │ │ CaptureSession │ │ AdapterProfile │ │
|
||||
│ │ (adapter │ │ (aggregate root)│ │ (capability │ │
|
||||
│ │ plugin) │ │ │ │ descriptor) │ │
|
||||
│ └────────────┘ └─────────────────┘ └─────────────────┘ │
|
||||
│ │
|
||||
│ CsiSource trait: open · start · next_frame · stop · health │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
| Element | Kind | Notes |
|
||||
|---------|------|-------|
|
||||
| `Source` | Entity | A configured adapter instance bound to a device or file |
|
||||
| `CaptureSession` | Entity / **aggregate root** | Owns exactly one `AdapterProfile` and one runtime configuration |
|
||||
| `AdapterProfile` | Entity | Chip, firmware/driver versions, supported channels/bandwidths, expected subcarrier counts, capability flags |
|
||||
| `Channel`, `Bandwidth`, `FirmwareVersion`, `DriverVersion` | Value objects | Immutable |
|
||||
|
||||
**Commands:** `StartCapture` · `StopCapture` · `RestartCapture` · `InspectSource`
|
||||
**Domain events:** `CaptureStarted` · `CaptureStopped` · `SourceDisconnected` · `AdapterUnsupported`
|
||||
|
||||
---
|
||||
|
||||
### 2. Validation context
|
||||
|
||||
**Responsibility:** make frames safe and trustworthy before any language-boundary crossing.
|
||||
|
||||
| Element | Kind | Notes |
|
||||
|---------|------|-------|
|
||||
| `ValidationPolicy` | Entity | Bounds, monotonicity rules, finiteness checks, quarantine on/off |
|
||||
| `QuarantineStore` | Entity | Holds rejected/corrupt frames for audit |
|
||||
| `ValidatedFrame` | **Aggregate root** | The frame once it has passed (or been degraded by) validation |
|
||||
| `ValidationError`, `QualityScore`, `FrameBounds` | Value objects | `QualityScore` ∈ [0, 1] |
|
||||
|
||||
**Commands:** `ValidateFrame` · `QuarantineFrame`
|
||||
**Domain events:** `FrameAccepted` · `FrameRejected` · `QualityDropped`
|
||||
|
||||
---
|
||||
|
||||
### 3. Signal context
|
||||
|
||||
**Responsibility:** DSP and window features.
|
||||
|
||||
```
|
||||
Frame stream ─▶ SignalPipeline ─▶ WindowBuffer ─▶ CsiWindow
|
||||
(DC removal, phase unwrap, (mean amplitude,
|
||||
smoothing, Hampel filter, phase variance,
|
||||
variance, baseline subtraction, motion energy,
|
||||
motion energy, presence score) presence/quality scores)
|
||||
```
|
||||
|
||||
| Element | Kind | Notes |
|
||||
|---------|------|-------|
|
||||
| `SignalPipeline` | Entity | Ordered DSP stages; reuses `wifi-densepose-signal` primitives |
|
||||
| `WindowBuffer` | Entity | Accumulates frames into bounded windows |
|
||||
| `CsiWindow` | **Aggregate root** | Frames from exactly one source/session |
|
||||
| `AmplitudeVector`, `PhaseVector`, `MotionEnergy`, `PresenceScore` | Value objects | |
|
||||
|
||||
**Commands:** `ProcessFrame` · `BuildWindow` · `EstimateBaselineDelta`
|
||||
**Domain events:** `WindowReady` · `BaselineDeltaMeasured`
|
||||
|
||||
---
|
||||
|
||||
### 4. Calibration context
|
||||
|
||||
**Responsibility:** learn and version the normal RF state and room signatures.
|
||||
|
||||
| Element | Kind | Notes |
|
||||
|---------|------|-------|
|
||||
| `CalibrationProfile` | **Aggregate root** | Linked to source, room, adapter profile, configuration |
|
||||
| `RoomSignature` | Entity | Vector representation of a space under normal conditions |
|
||||
| `BaselineModel` | Entity | Statistical model of the baseline field; carries version history |
|
||||
| `CalibrationVersion`, `StabilityScore`, `RoomId` | Value objects | Calibration cannot complete if `StabilityScore` < threshold |
|
||||
|
||||
**Commands:** `StartCalibration` · `CompleteCalibration` · `UpdateBaseline` · `RejectUnstableCalibration`
|
||||
**Domain events:** `CalibrationStarted` · `CalibrationCompleted` · `CalibrationFailed` · `BaselineUpdated`
|
||||
|
||||
---
|
||||
|
||||
### 5. Event context
|
||||
|
||||
**Responsibility:** semantic event extraction with confidence and evidence.
|
||||
|
||||
| Element | Kind | Notes |
|
||||
|---------|------|-------|
|
||||
| `EventDetector` | Entity | One per event family (presence, motion, breathing, anomaly, …) |
|
||||
| `EventStateMachine` | Entity | Holds the per-source detection state; emits transitions |
|
||||
| `CsiEvent` | **Aggregate root** | Must reference ≥ 1 evidence window; confidence ∈ [0, 1]; references calibration version |
|
||||
| `Confidence`, `EvidenceWindowSet`, `EventKind` | Value objects | |
|
||||
|
||||
**Commands:** `DetectEvents` · `PublishEvent` · `SuppressEvent`
|
||||
**Domain events (the `CsiEventKind` enum):** `PresenceStarted` · `PresenceEnded` · `MotionDetected` · `MotionSettled` · `BaselineChanged` · `SignalQualityDropped` · `DeviceDisconnected` · `BreathingCandidate` · `AnomalyDetected` · `CalibrationRequired`
|
||||
|
||||
---
|
||||
|
||||
### 6. Memory context
|
||||
|
||||
**Responsibility:** RuVector storage and retrieval — RF memory.
|
||||
|
||||
| Element | Kind | Notes |
|
||||
|---------|------|-------|
|
||||
| `RfMemoryCollection` | Entity | A RuVector collection scoped to a deployment |
|
||||
| `TemporalEmbedding` | Entity | Frame / window / event embedding with timestamp |
|
||||
| `SensorGraph` | Entity | Graph of sources and their topological relationships |
|
||||
| `RoomMemory` | **Aggregate root** | Stored embeddings must be traceable to frame windows or event windows |
|
||||
| `EmbeddingVector`, `DriftScore`, `CoherenceScore` | Value objects | `DriftScore` must include the baseline version |
|
||||
|
||||
**Commands:** `StoreWindowEmbedding` · `StoreEventEmbedding` · `QuerySimilarWindows` · `ComputeDrift`
|
||||
**Domain events:** `EmbeddingStored` · `DriftDetected` · `SimilarPatternFound`
|
||||
|
||||
Data stored: frame embeddings · window embeddings · room baseline vectors · event vectors · drift snapshots · sensor-topology graph edges · source health records. Retention policy applies at collection level. No orphan embeddings.
|
||||
|
||||
---
|
||||
|
||||
### 7. Agent context
|
||||
|
||||
**Responsibility:** MCP and TypeScript agent interaction — safe actions and queries.
|
||||
|
||||
| Element | Kind | Notes |
|
||||
|---------|------|-------|
|
||||
| `AgentSubscription` | Entity | An agent's filtered stream of events |
|
||||
| `McpToolSession` | Entity | A tool invocation context with permissions |
|
||||
| `AgentSession` | **Aggregate root** | |
|
||||
| `ToolPermission`, `EventFilter`, `AgentIntent` | Value objects | `ToolPermission` distinguishes read vs. write-gated |
|
||||
|
||||
**Commands:** `SubscribeToEvents` · `RequestStatus` · `RequestCalibration` · `QueryMemory`
|
||||
**Domain events:** `AgentSubscribed` · `ToolExecuted` · `PermissionDenied`
|
||||
|
||||
**MCP tools** (read by default; write-gated marked `*`): `rvcsi_status` · `rvcsi_list_sources` · `rvcsi_start_capture *` · `rvcsi_stop_capture *` · `rvcsi_get_presence` · `rvcsi_get_recent_events` · `rvcsi_calibrate_room *` · `rvcsi_export_window *` · `rvcsi_query_ruvector` · `rvcsi_health_report`.
|
||||
|
||||
---
|
||||
|
||||
## Context Map
|
||||
|
||||
| Upstream → Downstream | Relationship | ACL / contract |
|
||||
|-----------------------|--------------|----------------|
|
||||
| Capture → Validation | Customer/Supplier | Raw frames pass through `ValidationPolicy`; only `Accepted`/`Degraded` continue |
|
||||
| Validation → Signal | Conformist (Signal accepts `ValidatedFrame` as-is) | `CsiFrame` schema is the published language |
|
||||
| Signal → Calibration | Customer/Supplier | Windows + baseline-delta measurements feed baseline modeling |
|
||||
| Calibration → Event | Customer/Supplier | Detectors declare which `CalibrationVersion` they used |
|
||||
| Signal/Event → Memory | Published Language (`EmbeddingVector`, event metadata) | `rvcsi-ruvector` ACL translates to RuVector's API |
|
||||
| Event → Agent | Open Host Service (event stream + MCP tools) | `EventFilter` + `ToolPermission` enforced at the boundary |
|
||||
| Capture → Agent | Conformist (health/status only, via MCP read tools) | No raw frames cross to agents |
|
||||
|
||||
The **`CsiFrame` schema is the shared kernel** between Capture, Validation, Signal, and the language-boundary (napi-rs) layer. It is the FFI-safe object; nothing device-specific leaks past it.
|
||||
|
||||
---
|
||||
|
||||
## Aggregates and Invariants
|
||||
|
||||
### `CaptureSession` aggregate
|
||||
|
||||
**Invariant:** a capture session has exactly one source profile and one runtime configuration.
|
||||
|
||||
1. A session cannot emit frames before it is started.
|
||||
2. A session cannot change channel without restart unless the adapter supports dynamic retune.
|
||||
3. A session must emit `SourceDisconnected` before stopping due to device loss.
|
||||
|
||||
### `ValidatedFrame` aggregate
|
||||
|
||||
**Invariant:** no frame crosses into SDK, DSP, memory, or agents unless its validation status is `Accepted` or `Degraded`.
|
||||
|
||||
1. Rejected frames go to quarantine when quarantine is enabled.
|
||||
2. Degraded frames must carry quality-reason metadata.
|
||||
3. Missing *optional* hardware metadata must not invalidate a frame.
|
||||
|
||||
### `CsiWindow` aggregate
|
||||
|
||||
**Invariant:** a window contains frames from exactly one source and one session.
|
||||
|
||||
1. Mixed-source windows are not allowed.
|
||||
2. Window start time must be strictly less than end time.
|
||||
3. Window quality is bounded in [0, 1].
|
||||
|
||||
### `CalibrationProfile` aggregate
|
||||
|
||||
**Invariant:** a calibration profile is linked to source, room, adapter profile, and configuration.
|
||||
|
||||
1. Calibration cannot complete if `StabilityScore` is below threshold.
|
||||
2. Baseline updates must preserve version history.
|
||||
3. Event detectors must declare which calibration version they used.
|
||||
|
||||
### `CsiEvent` aggregate
|
||||
|
||||
**Invariant:** an event must have evidence.
|
||||
|
||||
1. Every event references at least one evidence window.
|
||||
2. Confidence is bounded in [0, 1].
|
||||
3. Event suppression must be explainable by policy.
|
||||
|
||||
### `RoomMemory` aggregate
|
||||
|
||||
**Invariant:** stored embeddings are traceable to frame windows or event windows.
|
||||
|
||||
1. No orphan embeddings.
|
||||
2. Retention policy applies at collection level.
|
||||
3. Drift scores must include the baseline version.
|
||||
|
||||
---
|
||||
|
||||
## Data Model
|
||||
|
||||
```rust
|
||||
pub struct CsiFrame {
|
||||
pub frame_id: FrameId,
|
||||
pub session_id: SessionId,
|
||||
pub source_id: SourceId,
|
||||
pub adapter_kind: AdapterKind,
|
||||
pub timestamp_ns: u64,
|
||||
pub channel: u16,
|
||||
pub bandwidth_mhz: u16,
|
||||
pub rssi_dbm: Option<i16>,
|
||||
pub noise_floor_dbm: Option<i16>,
|
||||
pub antenna_index: Option<u8>,
|
||||
pub tx_chain: Option<u8>,
|
||||
pub rx_chain: Option<u8>,
|
||||
pub subcarrier_count: u16,
|
||||
pub i_values: Vec<f32>,
|
||||
pub q_values: Vec<f32>,
|
||||
pub amplitude: Vec<f32>,
|
||||
pub phase: Vec<f32>,
|
||||
pub validation: ValidationStatus,
|
||||
pub quality_score: f32,
|
||||
pub calibration_version: Option<String>,
|
||||
}
|
||||
|
||||
pub struct CsiWindow {
|
||||
pub window_id: WindowId,
|
||||
pub session_id: SessionId,
|
||||
pub source_id: SourceId,
|
||||
pub start_ns: u64,
|
||||
pub end_ns: u64,
|
||||
pub frame_count: u32,
|
||||
pub mean_amplitude: Vec<f32>,
|
||||
pub phase_variance: Vec<f32>,
|
||||
pub motion_energy: f32,
|
||||
pub presence_score: f32,
|
||||
pub quality_score: f32,
|
||||
}
|
||||
|
||||
pub enum CsiEventKind {
|
||||
PresenceStarted,
|
||||
PresenceEnded,
|
||||
MotionDetected,
|
||||
MotionSettled,
|
||||
BaselineChanged,
|
||||
SignalQualityDropped,
|
||||
DeviceDisconnected,
|
||||
BreathingCandidate,
|
||||
AnomalyDetected,
|
||||
CalibrationRequired,
|
||||
}
|
||||
|
||||
pub struct CsiEvent {
|
||||
pub event_id: EventId,
|
||||
pub kind: CsiEventKind,
|
||||
pub session_id: SessionId,
|
||||
pub source_id: SourceId,
|
||||
pub timestamp_ns: u64,
|
||||
pub confidence: f32,
|
||||
pub evidence_window_ids: Vec<WindowId>,
|
||||
pub metadata_json: String,
|
||||
}
|
||||
|
||||
pub struct AdapterProfile {
|
||||
pub adapter_kind: AdapterKind,
|
||||
pub chip: Option<String>,
|
||||
pub firmware_version: Option<String>,
|
||||
pub driver_version: Option<String>,
|
||||
pub supported_channels: Vec<u16>,
|
||||
pub supported_bandwidths_mhz: Vec<u16>,
|
||||
pub expected_subcarrier_counts: Vec<u16>,
|
||||
pub supports_live_capture: bool,
|
||||
pub supports_injection: bool,
|
||||
pub supports_monitor_mode: bool,
|
||||
}
|
||||
|
||||
pub enum ValidationStatus { Accepted, Degraded, Rejected, Recovered }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domain Services
|
||||
|
||||
| Service | Input | Output | Responsibility |
|
||||
|---------|-------|--------|----------------|
|
||||
| `FrameValidationService` | `RawFrame`, `AdapterProfile`, `ValidationPolicy` | `ValidatedFrame` or `RejectedFrame` | Enforce bounds, finiteness, monotonicity; assign initial `QualityScore`; route rejects to quarantine; emit structured errors |
|
||||
| `SignalProcessingService` | `ValidatedFrame` stream | `CsiWindow` stream | Run the DSP pipeline; build bounded windows; compute motion energy, presence score, window quality |
|
||||
| `BaselineDeltaService` | `CsiWindow`, `BaselineModel` | `BaselineDelta` | Subtract the calibrated baseline; measure deviation magnitude |
|
||||
| `CalibrationService` | `CsiWindow` stream over a calibration window | `CalibrationProfile` (new version) or `CalibrationFailed` | Learn a stable baseline; compute `StabilityScore`; reject unstable calibrations; preserve version history |
|
||||
| `EventDetectionService` | `CsiWindow` + `BaselineDelta` + `CalibrationVersion` | `CsiEvent` stream | Drive per-source state machines; attach confidence + evidence windows + calibration version; apply suppression policy |
|
||||
| `EmbeddingService` | `CsiWindow` / `CsiEvent` | `TemporalEmbedding` | Produce frame/window/event vectors (v0: deterministic DSP feature vector; later: AETHER / on-device model) |
|
||||
| `RfMemoryService` | `TemporalEmbedding`, query | `EmbeddingStored` / similar windows / `DriftScore` | Store to RuVector; similarity search; drift computation against a baseline version |
|
||||
| `ReplayService` | A captured session bundle | A deterministic frame/window/event stream | Replay preserving timestamps, ordering, validation decisions, event output, calibration version, runtime config |
|
||||
| `AdapterRegistryService` | — | List of available adapters + `AdapterProfile`s | Discover sources (reuses ADR-049 interface detection); report health; flag unsupported firmware/driver state |
|
||||
| `AgentGatewayService` | MCP tool call / SDK subscription | Tool result / filtered event stream | Enforce `ToolPermission` (read vs. write-gated), apply `EventFilter`, audit `ToolExecuted` / `PermissionDenied` |
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- [rvCSI Platform PRD](../prd/rvcsi-platform-prd.md) — requirements, success criteria, scope
|
||||
- [ADR-095 — rvCSI Edge RF Sensing Platform](../adr/ADR-095-rvcsi-edge-rf-sensing-platform.md) — the fifteen architectural decisions
|
||||
- [RuvSense Domain Model](ruvsense-domain-model.md) — adjacent multistatic sensing context
|
||||
- [Signal Processing Domain Model](signal-processing-domain-model.md) — the DSP primitives `rvcsi-dsp` reuses
|
||||
- [ADR Index](../adr/README.md)
|
||||
|
|
@ -0,0 +1,376 @@
|
|||
# rvCSI — Edge RF Sensing Runtime
|
||||
|
||||
## Product Design Requirements (PRD)
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Product name** | rvCSI |
|
||||
| **Category** | Edge RF sensing runtime and developer platform |
|
||||
| **Status** | Proposed (v0 design) |
|
||||
| **Date** | 2026-05-12 |
|
||||
| **Owner** | ruv |
|
||||
| **Relates to** | [ADR-095](../adr/ADR-095-rvcsi-edge-rf-sensing-platform.md) (rvCSI platform), [ADR-012](../adr/ADR-012-esp32-csi-sensor-mesh.md) (ESP32 mesh), [ADR-013](../adr/ADR-013-feature-level-sensing-commodity-gear.md) (feature-level sensing), [ADR-014](../adr/ADR-014-sota-signal-processing.md) (SOTA signal processing), [ADR-016](../adr/ADR-016-ruvector-integration.md) (RuVector integration), [ADR-024](../adr/ADR-024-contrastive-csi-embedding-model.md) (AETHER embeddings), [ADR-031](../adr/ADR-031-ruview-sensing-first-rf-mode.md) (RuView sensing-first RF mode), [ADR-040](../adr/ADR-040-wasm-programmable-sensing.md) (WASM programmable sensing) |
|
||||
| **Domain model** | [rvCSI Domain Model](../ddd/rvcsi-domain-model.md) |
|
||||
|
||||
---
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
rvCSI is a **Rust-first, TypeScript-accessible, hardware-abstracted Channel State Information (CSI) platform** for WiFi-based spatial sensing.
|
||||
|
||||
The goal is to convert CSI from fragile research data into a durable edge sensing runtime that can feed RuView, RuVector, Cognitum, and agentic systems with validated live radio-field observations.
|
||||
|
||||
rvCSI does **not** try to replace Nexmon on day one. It wraps, validates, normalizes, streams, embeds, and learns from CSI produced by Nexmon, ESP32 CSI, Intel CSI, Atheros CSI, SDR pipelines, and future RF sensor sources.
|
||||
|
||||
### 1.1 System framing
|
||||
|
||||
CSI is treated as a **physical-world delta stream**.
|
||||
|
||||
A room, hallway, vehicle, warehouse, machine bay, or care facility has a radio-field baseline. Human motion, breathing, door movement, equipment vibration, device movement, and environmental change perturb that baseline. rvCSI captures those perturbations, normalizes them into tensors, converts them into events, stores them as temporal memory, and exposes them to agents.
|
||||
|
||||
The core invariant:
|
||||
|
||||
| Layer | Owns |
|
||||
|-------|------|
|
||||
| **C** | Fragile vendor and firmware compatibility |
|
||||
| **Rust** | Safety, validation, signal processing, memory discipline, deterministic runtime behavior |
|
||||
| **TypeScript** | Developer experience, orchestration, dashboards, SDKs, agent integration |
|
||||
| **RuVector** | Memory, similarity, drift, graph relationships, coherence over time |
|
||||
| **Cognitum** | Low-power event-driven deployment, local decision loops |
|
||||
|
||||
### 1.2 Strategic framing
|
||||
|
||||
Most CSI projects today are Linux shell scripts, kernel patching, Python notebooks, PCAP dumps, and ad-hoc signal processing. A Rust + TypeScript + napi-rs architecture turns CSI into **real-time sensor infrastructure**: npm-installable, reproducible, typed, safe-parsed, embeddable, WebSocket-streamable, WASM-portable, MCP-exposed, agent-integrable, and edge/cloud-federated.
|
||||
|
||||
The right framing is **structural sensing**, not "magic X-ray vision". CSI is excellent for detecting change, presence, and learned patterns; it is weak for exact identity, exact pose, legal/security certainty, and highly dynamic RF spaces. rvCSI's product claims stay inside that boundary (see Non-goals, §6).
|
||||
|
||||
---
|
||||
|
||||
## 2. Users
|
||||
|
||||
| User | Need |
|
||||
|------|------|
|
||||
| AI engineers building physical-world agents | A stable sensing primitive that emits typed events agents can react to |
|
||||
| Researchers working with WiFi CSI and RF sensing | Reproducible ingestion, replay, and benchmark datasets |
|
||||
| Smart-building and elder-care solution builders | Privacy-preserving presence/motion/breathing without cameras |
|
||||
| Industrial monitoring teams | Camera-free movement/anomaly detection that runs unattended |
|
||||
| Developers using RuView / RuVector / Cognitum | A drop-in source of RF observations for the broader ruvnet stack |
|
||||
|
||||
---
|
||||
|
||||
## 3. Problem & Hypothesis
|
||||
|
||||
**Problem.** WiFi CSI is useful but hard to operationalize. Most CSI pipelines are built from fragile scripts, patched firmware, lab notebooks, inconsistent packet formats, unstable drivers, and device-specific assumptions. This makes CSI difficult to deploy outside research settings. The system needs a production-grade runtime that can ingest CSI from multiple sources, validate packets, normalize formats, stream typed events, support signal processing, and feed vector-based learning systems.
|
||||
|
||||
**Hypothesis.** If rvCSI provides a stable Rust core with TypeScript APIs and hardware adapters, then CSI can become a reusable sensing primitive for camera-free spatial intelligence.
|
||||
|
||||
---
|
||||
|
||||
## 4. Success criteria
|
||||
|
||||
1. A developer can install rvCSI and parse recorded CSI files in **under five minutes**.
|
||||
2. A supported live device can stream **validated** CSI frames into TypeScript.
|
||||
3. Bad packets **cannot crash** the process.
|
||||
4. The same application code consumes CSI from Nexmon, ESP32, Intel, or Atheros adapters.
|
||||
5. Presence and motion detection work from **normalized tensors**, not device-specific raw packets.
|
||||
6. rvCSI can publish embeddings and event summaries into **RuVector**.
|
||||
7. rvCSI can run as a **local daemon on Raspberry Pi-class hardware**.
|
||||
8. rvCSI can expose events to **MCP tools and local agents**.
|
||||
|
||||
---
|
||||
|
||||
## 5. Scope
|
||||
|
||||
### 5.1 Version zero — safe ingestion, normalized data, live streaming, SDK usability, RuVector integration
|
||||
|
||||
1. Recorded CSI file parser
|
||||
2. Live capture adapter for existing Nexmon CSI output where supported
|
||||
3. ESP32 CSI adapter
|
||||
4. Unified CSI frame schema
|
||||
5. Rust validation pipeline
|
||||
6. TypeScript SDK through napi-rs
|
||||
7. CLI for capture, inspect, replay, stream
|
||||
8. WebSocket output
|
||||
9. Presence and motion baseline detectors
|
||||
10. RuVector export interface
|
||||
11. Basic calibration model
|
||||
12. Hardware and driver health checks
|
||||
|
||||
### 5.2 Version one
|
||||
|
||||
1. Multi-node synchronization
|
||||
2. RF room signatures
|
||||
3. Breathing-rate estimation where signal quality permits
|
||||
4. Temporal embeddings
|
||||
5. Drift detection
|
||||
6. Graph-based room topology
|
||||
7. Local MCP tool server
|
||||
8. Replayable benchmark datasets
|
||||
9. Sensor fusion with RuView
|
||||
10. Deployment profile for Cognitum Seed and Appliance
|
||||
|
||||
### 5.3 Version two
|
||||
|
||||
1. Hardware-agnostic RF sensor fabric
|
||||
2. Multi-room RF memory
|
||||
3. Streaming anomaly detection
|
||||
4. RF SLAM research mode
|
||||
5. On-device embedding model
|
||||
6. Federated learning of room signatures
|
||||
7. Secure signed sensor-evidence records
|
||||
8. Proof-gated event publication
|
||||
9. Dynamic cut-based coherence over RF graphs
|
||||
10. Agent-driven calibration and self-repair
|
||||
|
||||
---
|
||||
|
||||
## 6. Non-goals (version zero)
|
||||
|
||||
1. Pure-Rust replacement for Broadcom firmware patches
|
||||
2. Universal support for all WiFi chips
|
||||
3. Identity recognition from RF signals
|
||||
4. Medical-grade vital-sign diagnosis
|
||||
5. Legal-grade occupancy proof
|
||||
6. Guaranteed through-wall pose detection
|
||||
7. Cloud dependency
|
||||
8. Camera-replacement claims
|
||||
|
||||
---
|
||||
|
||||
## 7. Functional requirements
|
||||
|
||||
### FR1 — CSI ingestion
|
||||
|
||||
rvCSI shall ingest CSI from multiple sources. Initial source types: recorded binary dump, PCAP file, Nexmon CSI live stream, ESP32 CSI serial/UDP stream, Intel CSI logs (where supported), Atheros CSI logs (where supported). **Output:** a normalized `CsiFrame` object.
|
||||
|
||||
### FR2 — Packet validation
|
||||
|
||||
rvCSI shall validate every frame before exposing it to TypeScript or RuVector:
|
||||
|
||||
1. Frame length must match declared schema.
|
||||
2. Subcarrier count must be inside adapter-profile limits.
|
||||
3. Timestamp must be monotonic within a capture session unless marked as recovered.
|
||||
4. RSSI must be within plausible device bounds.
|
||||
5. Complex values must be finite.
|
||||
6. Corrupt frames must be rejected or quarantined.
|
||||
7. Parser failures must return structured errors.
|
||||
|
||||
### FR3 — Normalized frame schema
|
||||
|
||||
rvCSI shall normalize all hardware output into a common schema. Required fields: `frame_id`, `session_id`, `source_id`, `adapter_kind`, `timestamp_ns`, `channel`, `bandwidth_mhz`, `rssi_dbm`, `noise_floor_dbm` (when available), `antenna_index` (when available), `tx_chain` (when available), `rx_chain` (when available), `subcarrier_count`, `i_values`, `q_values`, `amplitude`, `phase`, `validation_status`, `quality_score`, `calibration_version`.
|
||||
|
||||
### FR4 — Signal processing
|
||||
|
||||
rvCSI shall provide reusable Rust signal-processing stages: DC offset removal, phase unwrap, amplitude smoothing, Hampel/median outlier filter, short-window variance, baseline subtraction, motion energy, presence score, breathing-band estimator (where supported), confidence scoring.
|
||||
|
||||
### FR5 — Event extraction
|
||||
|
||||
rvCSI shall convert frame streams into typed events: `PresenceStarted`, `PresenceEnded`, `MotionDetected`, `MotionSettled`, `BaselineChanged`, `SignalQualityDropped`, `DeviceDisconnected`, `BreathingCandidate`, `AnomalyDetected`, `CalibrationRequired`.
|
||||
|
||||
### FR6 — TypeScript SDK
|
||||
|
||||
rvCSI shall expose a TypeScript SDK:
|
||||
|
||||
```ts
|
||||
import { RvCsi } from "@ruv/rvcsi";
|
||||
|
||||
const sensor = await RvCsi.open({
|
||||
source: "nexmon",
|
||||
iface: "wlan0",
|
||||
channel: 6,
|
||||
bandwidthMHz: 20,
|
||||
});
|
||||
|
||||
sensor.on("frame", (frame) => {
|
||||
console.log(frame.qualityScore);
|
||||
});
|
||||
|
||||
sensor.on("presence", (event) => {
|
||||
console.log(event.confidence);
|
||||
});
|
||||
|
||||
await sensor.start();
|
||||
```
|
||||
|
||||
### FR7 — CLI
|
||||
|
||||
```bash
|
||||
rvcsi inspect file sample.csi
|
||||
rvcsi capture start --source nexmon --iface wlan0 --channel 6
|
||||
rvcsi replay sample.csi --speed 1x
|
||||
rvcsi stream --format json --port 8787
|
||||
rvcsi calibrate --room livingroom --duration 60
|
||||
rvcsi health --source nexmon
|
||||
rvcsi export ruvector --collection room_rf
|
||||
```
|
||||
|
||||
### FR8 — RuVector integration
|
||||
|
||||
rvCSI shall export temporal RF embeddings and event metadata to RuVector. Data stored: frame embeddings, window embeddings, room baseline vectors, event vectors, drift snapshots, sensor-topology graph edges, source health records.
|
||||
|
||||
### FR9 — MCP integration
|
||||
|
||||
rvCSI shall expose MCP tools for local agents: `rvcsi_status`, `rvcsi_list_sources`, `rvcsi_start_capture`, `rvcsi_stop_capture`, `rvcsi_get_presence`, `rvcsi_get_recent_events`, `rvcsi_calibrate_room`, `rvcsi_export_window`, `rvcsi_query_ruvector`, `rvcsi_health_report`. Tools default to read actions; capture start/stop, calibration, and export are write-gated.
|
||||
|
||||
### FR10 — Replay and audit
|
||||
|
||||
rvCSI shall support deterministic replay of captured sessions, preserving: original timestamps, frame ordering, validation decisions, event-extraction output, calibration version, runtime configuration.
|
||||
|
||||
---
|
||||
|
||||
## 8. Non-functional requirements
|
||||
|
||||
### 8.1 Safety
|
||||
|
||||
1. TypeScript shall never receive raw unchecked pointers.
|
||||
2. Rust shall validate all frames before the FFI boundary export.
|
||||
3. C shims shall be minimal and isolated.
|
||||
4. All `unsafe` blocks shall be documented.
|
||||
5. Fuzz tests shall cover parsers.
|
||||
|
||||
### 8.2 Performance (v0 targets)
|
||||
|
||||
1. Parse one CSI frame in **< 1 ms** on Raspberry Pi 5.
|
||||
2. Sustain **≥ 1000 frames/s** on Pi 5 for normalized parsing.
|
||||
3. Keep memory **< 256 MB** for one active source.
|
||||
4. Keep event latency **< 50 ms** for presence and motion.
|
||||
5. Avoid heap growth during steady capture.
|
||||
|
||||
### 8.3 Reliability
|
||||
|
||||
1. Bad packets shall not crash the daemon.
|
||||
2. Device disconnect shall produce a typed event.
|
||||
3. Capture sessions shall be restartable.
|
||||
4. Logs shall include source, adapter, session, and validation details.
|
||||
5. Health checks shall identify unsupported firmware or driver state.
|
||||
|
||||
### 8.4 Privacy
|
||||
|
||||
1. rvCSI shall operate locally by default.
|
||||
2. No cloud endpoint shall be required.
|
||||
3. Raw CSI export shall be disableable by policy.
|
||||
4. Event-level export shall be supported for privacy-preserving deployments.
|
||||
5. Retention policies shall be configurable.
|
||||
|
||||
### 8.5 Security
|
||||
|
||||
1. Device-control operations shall require explicit permission.
|
||||
2. Firmware-installation operations shall be separated from capture operations.
|
||||
3. Signed capture profiles shall be supported in later versions.
|
||||
4. MCP tools shall mark write actions as gated.
|
||||
5. File parsing shall be fuzzed and sandbox-friendly.
|
||||
|
||||
### 8.6 Portability
|
||||
|
||||
1. Linux first.
|
||||
2. Raspberry Pi first among edge devices.
|
||||
3. macOS and Windows support for file replay and SDK development.
|
||||
4. Live-capture support depends on adapter and driver capability.
|
||||
5. WASM support for offline parsing and visualization is a later target.
|
||||
|
||||
---
|
||||
|
||||
## 9. System architecture
|
||||
|
||||
### 9.1 High-level pipeline
|
||||
|
||||
```
|
||||
CSI Source
|
||||
↓
|
||||
Adapter Layer (vendor-specific decode, C shims isolated here)
|
||||
↓
|
||||
Rust Validation Pipeline (bounds, finiteness, monotonicity, quarantine)
|
||||
↓
|
||||
Normalized CSI Frame (CsiFrame schema — the FFI-safe boundary object)
|
||||
↓
|
||||
Signal Processing (DC removal, phase unwrap, smoothing, motion energy …)
|
||||
↓
|
||||
Window Aggregator (bounded frame sequences → CsiWindow)
|
||||
↓
|
||||
Event Extractor (state machines → CsiEvent with confidence + evidence)
|
||||
↓
|
||||
TypeScript SDK · CLI · MCP · RuVector
|
||||
```
|
||||
|
||||
### 9.2 Runtime components
|
||||
|
||||
| # | Component | Role |
|
||||
|---|-----------|------|
|
||||
| 1 | `rvcsi-core` | Frame types, parser traits, validation, quality scoring, shared abstractions |
|
||||
| 2 | `rvcsi-adapter-*` | Rust/C-backed adapters: Nexmon, ESP32, Intel, Atheros, files, replay |
|
||||
| 3 | `rvcsi-dsp` | Rust signal-processing primitives |
|
||||
| 4 | `rvcsi-events` | Windowing, baseline modeling, event extraction, state machines |
|
||||
| 5 | `rvcsi-node` | napi-rs bindings exposing safe APIs to Node.js |
|
||||
| 6 | `rvcsi-sdk` | TypeScript SDK |
|
||||
| 7 | `rvcsi-cli` | Command-line interface |
|
||||
| 8 | `rvcsi-daemon` | Long-running capture and event service |
|
||||
| 9 | `rvcsi-mcp` | MCP tool server |
|
||||
| 10 | `rvcsi-ruvector` | Exporter and query bridge |
|
||||
|
||||
### 9.3 Reference repository layout
|
||||
|
||||
```
|
||||
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/
|
||||
packages/
|
||||
sdk/
|
||||
cli/
|
||||
dashboard/
|
||||
native/
|
||||
nexmon-shim-c/
|
||||
docs/
|
||||
adr/
|
||||
ddd/
|
||||
prd/
|
||||
benchmarks/
|
||||
testdata/
|
||||
captures/
|
||||
malformed/
|
||||
replay/
|
||||
```
|
||||
|
||||
> Within the RuView monorepo, rvCSI would be introduced as a new bounded context (see the [domain model](../ddd/rvcsi-domain-model.md)) and a small set of `v2/crates/rvcsi-*` crates, reusing existing `wifi-densepose-signal` DSP and `wifi-densepose-ruvector` integration where they overlap rather than duplicating them.
|
||||
|
||||
---
|
||||
|
||||
## 10. Data model (summary)
|
||||
|
||||
The authoritative definitions live in the [rvCSI domain model](../ddd/rvcsi-domain-model.md). Summary:
|
||||
|
||||
- **`CsiFrame`** — one validated CSI observation at a timestamp (the FFI-safe object). Carries I/Q, amplitude, phase, RSSI, channel/bandwidth, optional antenna/chain metadata, validation status, quality score, calibration version.
|
||||
- **`CsiWindow`** — a bounded sequence of frames from one source/session, with mean amplitude, phase variance, motion energy, presence score, quality score.
|
||||
- **`CsiEvent`** — a semantic interpretation of one or more windows, with `kind`, confidence, evidence window IDs, and metadata.
|
||||
- **`AdapterProfile`** — capability descriptor for a source: chip, firmware/driver versions, supported channels/bandwidths, expected subcarrier counts, capture/injection/monitor-mode support.
|
||||
|
||||
---
|
||||
|
||||
## 11. Open questions
|
||||
|
||||
1. **Embedding model.** What produces frame/window embeddings in v0 — a fixed DSP feature vector, the existing AETHER contrastive model (ADR-024), or a lightweight on-device model? v0 leans on a deterministic DSP feature vector; v2 targets an on-device model.
|
||||
2. **Calibration UX.** How long must a calibration window be before `StabilityScore` is trustworthy, and how is that surfaced in the SDK/CLI?
|
||||
3. **Nexmon coupling.** Which Nexmon-supported chips/firmwares are in the v0 "supported" matrix vs. "best effort"?
|
||||
4. **Monorepo vs. standalone.** Does rvCSI ship as `v2/crates/rvcsi-*` inside RuView or as a separate `rvcsi/` repo? This PRD assumes monorepo crates that reuse `wifi-densepose-signal` and `wifi-densepose-ruvector`.
|
||||
5. **MCP transport.** stdio-only for v1, or also a local socket for multi-agent fan-out?
|
||||
|
||||
---
|
||||
|
||||
## 12. References
|
||||
|
||||
- [ADR-095 — rvCSI Edge RF Sensing Platform](../adr/ADR-095-rvcsi-edge-rf-sensing-platform.md)
|
||||
- [rvCSI Domain Model](../ddd/rvcsi-domain-model.md)
|
||||
- [ADR-013 — Feature-Level Sensing on Commodity Gear](../adr/ADR-013-feature-level-sensing-commodity-gear.md)
|
||||
- [ADR-014 — SOTA Signal Processing](../adr/ADR-014-sota-signal-processing.md)
|
||||
- [ADR-016 — RuVector Integration](../adr/ADR-016-ruvector-integration.md)
|
||||
- [ADR-024 — Project AETHER: Contrastive CSI Embeddings](../adr/ADR-024-contrastive-csi-embedding-model.md)
|
||||
- [ADR-031 — RuView Sensing-First RF Mode](../adr/ADR-031-ruview-sensing-first-rf-mode.md)
|
||||
- [ADR-040 — WASM Programmable Sensing](../adr/ADR-040-wasm-programmable-sensing.md)
|
||||
Loading…
Reference in New Issue