* perf(signal): hoist FFT planner across subcarriers (ADR-154 §7.4 #20) compute_multi_subcarrier_spectrogram called compute_spectrogram once per subcarrier, and each call built a fresh FftPlanner + re-planned the same length-window_size FFT. Hoist the plan + window out of the per-subcarrier loop via a new compute_spectrogram_with_plan core that takes a pre-planned Arc<dyn Fft> and pre-built window. compute_spectrogram delegates to it (unchanged behaviour); the multi-subcarrier path plans once and reuses. MEASURED-HOT (dsp_perf_bench, this box): at 56 subcarriers, window 128, fresh-planner-per-subcarrier 467.88 µs -> hoisted-plan 254.75 µs = 1.84x; window 256: 627.27 µs -> 448.39 µs = 1.40x. Plan-forward cost alone is ~1.86 µs (w128), x56 subcarriers ~= the removed delta. Output is bit-identical: multi_subcarrier_hoisted_plan_bit_identical compares f64::to_bits of every spectrogram value + freq/time resolution against the per-call fresh-planner path across all 4 window functions x {power,magnitude} on a 56-subcarrier matrix. The numeric STFT body is the old loop verbatim; only plan/window construction is lifted. Co-Authored-By: claude-flow <ruv@ruv.net> * test(signal): boundary/tolerance tests for ADR-154 §7.4 #14 #16 #19 Three "+ test" backlog gaps closed — pure additions, no behaviour change (phase_align refactor is internal: estimate_phase_offsets still returns the identical offset vector; a counted core is split out only to observe the iteration count). #14 cir.rs fft_operator — fft_operator_within_tolerance_of_dense_canonical56: the opt-in FFT Φ/Φᴴ path changes the witness hash, so pin it numerically CLOSE to the dense path (not silently divergent). Asserts the full Cir output (every tap within 1e-2·dominant, dominant idx/ratio, active_tap_count, ranging_valid, rms_delay_spread) on the production canonical-56 config across τ ∈ {20,50,90} ns. Extends the existing HT20/single-τ test. #16 phase_align.rs — refinement_terminates_at_iteration_cap_when_not_converging: forces non-convergence (tolerance=0.0, unreachable) and asserts the loop runs exactly max_iterations then returns — proving the cap, not convergence, bounds the loop (no infinite spin). Companion refinement_converges_before_cap_on_easy_input proves the cap is an upper bound, not the only exit. #19 csi_ratio.rs — ratio_finite_at_and_below_1e_12_epsilon: the module implements the CSI ratio as the conjugate product H_i·conj(H_j) (no division), so it is finite even at/below the 1e-12 magnitude boundary a naive H_i/H_j division would need an epsilon to guard. Pins finiteness + bit-exact conjugate product at the boundary (zero target → zero, never inf/NaN), through the amplitude/phase extraction. cargo test -p wifi-densepose-signal --no-default-features --lib: 447 passed, 0 failed; --features cir --lib: 447 passed, 0 failed. Co-Authored-By: claude-flow <ruv@ruv.net> * docs(adr-154): record Milestone-2 P2-perf verdicts + boundary tests (§7.4) §7.4: #20 MEASURED-HOT (1.40–1.84× spectrogram FFT-plan hoist, bit-identical); #5/#6/#7 MEASURED-NULL (benched, not hot, left as-is — sub-µs / stack-only / alloc-once); #8 MEASUREMENT-ONLY (per-call 56×56 eigh cost; eigenvalue/BLAS backend un-buildable on this Windows host, number deferred to a BLAS box, NOT fabricated; also corrects the finding — extract_perturbation reuses cached modes, the recompute is in estimate_occupancy). #14/#16/#19 RESOLVED (tolerance / convergence-cap / epsilon-boundary tests). Updated §7.4 intro + Horizon-ledger (deferred count 41→36). CHANGELOG [Unreleased] entry added. Co-Authored-By: claude-flow <ruv@ruv.net> * bench(signal): committed P2 bench-first benches (ADR-154 §7.4 #5/#6/#7/#8/#20) New dsp_perf_bench.rs backs every Milestone-2 perf verdict with a committed criterion bench — no speedup claimed without a before/after number here, and a benched NULL is the proof a micro-opt was unnecessary (the §5.x "already amortized" pattern). Registered in Cargo.toml [[bench]]. MEASURED (this box, criterion medians): #20 spectrogram_multi_subcarrier (fresh vs hoisted plan): MEASURED-HOT — 467.88→254.75 µs (1.84x) @ sc56/w128; 627.27→448.39 µs (1.40x) @ sc56/w256. Optimized in the prior commit. #5 multistatic_attention/weights: MEASURED-NULL — 181 ns (2 nodes) .. 848 ns (8 nodes); sub-µs, no hot-path alloc — left as-is. #6 tomography_reconstruct/solve: MEASURED-NULL — 47.5 µs (16 links) / 60.4 µs (32 links) for a full 50-iter ISTA solve; the 2 per-solve voxel buffers (~4 KB) are negligible vs O(iters·links·voxels) compute, and reconstruct(&self) reuses them across iterations already — left as-is. #7 pose_kalman_update/cycles: MEASURED-NULL — 150 ns (17 kpts) / 2.82 µs (170); the Kalman "gain matrices" are fixed-size STACK arrays ([[f32;3];6]), zero heap — nothing to reuse — left as-is. #8 field_model_occupancy (eigenvalue feature): MEASUREMENT-ONLY — quantifies the per-call n×n eigendecomposition cost; incremental SVD is a sized future project, not attempted (number recorded in ADR-154 §7.4). Reproduce: cargo bench -p wifi-densepose-signal --no-default-features --bench dsp_perf_bench cargo bench -p wifi-densepose-signal --bench dsp_perf_bench # adds #8 Cargo.lock: dev-dep (criterion/clap) graph + crate version bumps from the build; no runtime-dependency change. Co-Authored-By: claude-flow <ruv@ruv.net>
Architecture Decision Records
This folder contains 45 Architecture Decision Records (ADRs) that document every significant technical choice in the RuView / WiFi-DensePose project.
Why ADRs?
Building a system that turns WiFi signals into human pose estimation involves hundreds of non-obvious decisions: which signal processing algorithms to use, how to bridge ESP32 firmware to a Rust pipeline, whether to run inference on-device or on a server, how to handle multi-person separation with limited subcarriers.
ADRs capture the context, options considered, decision made, and consequences for each of these choices. They serve three purposes:
-
Institutional memory — Six months from now, anyone (human or AI) can read why we chose IIR bandpass filters over FIR for vital sign extraction, not just see the code.
-
AI-assisted development — When an AI agent works on this codebase, ADRs give it the constraints and rationale it needs to make changes that align with the existing architecture. Without them, AI-generated code tends to drift — reinventing patterns that already exist, contradicting earlier decisions, or optimizing for the wrong tradeoffs.
-
Review checkpoints — Each ADR is a reviewable artifact. When a proposed change touches the architecture, the ADR forces the author to articulate tradeoffs before writing code, not after.
ADRs and Domain-Driven Design
The project uses Domain-Driven Design (DDD) to organize code into bounded contexts — each with its own language, types, and responsibilities. ADRs and DDD work together:
- ADRs define boundaries: ADR-029 (RuvSense) established multistatic sensing as a separate bounded context from single-node CSI. ADR-042 (CHCI) defined a new aggregate root for coherent channel imaging.
- DDD models define the language: The RuvSense domain model defines terms like "coherence gate", "dwell time", and "TDM slot" that ADRs reference precisely.
- Together they prevent drift: An AI agent reading ADR-039 knows that edge processing tiers are configured via NVS keys, not compile-time flags — because the ADR says so. The DDD model tells it which aggregate owns that configuration.
How ADRs are structured
Each ADR follows a consistent format:
- Context — What problem or gap prompted this decision
- Decision — What we chose to do and how
- Consequences — What improved, what got harder, and what risks remain
- References — Related ADRs, papers, and code paths
Statuses: Proposed (under discussion), Accepted (approved and/or implemented), Superseded (replaced by a later ADR).
ADR Index
Hardware and firmware
| ADR | Title | Status |
|---|---|---|
| ADR-012 | ESP32 CSI Sensor Mesh for Distributed Sensing | Accepted (partial) |
| ADR-018 | ESP32 Development Implementation Path | Proposed |
| ADR-028 | ESP32 Capability Audit and Witness Record | Accepted |
| ADR-029 | RuvSense Multistatic Sensing Mode (TDM, channel hopping) | Proposed |
| ADR-032 | Multistatic Mesh Security Hardening | Accepted |
| ADR-039 | ESP32-S3 Edge Intelligence Pipeline (on-device vitals) | Accepted (hardware-validated) |
| ADR-040 | WASM Programmable Sensing (Tier 3) | Accepted |
| ADR-041 | WASM Module Collection (65 edge modules) | Accepted (hardware-validated) |
| ADR-044 | Provisioning Tool Enhancements | Proposed |
| ADR-110 | ESP32-C6 firmware extension — Wi-Fi 6 / 802.15.4 / TWT / LP-core | Accepted, P1-P10 complete, firmware-side substrate closed at v0.7.0-esp32. Companion docs: WITNESS-LOG-110 (13 §A0.x entries · 99.56 % cross-board RX · 104.1 µs smoothed sync stdev · ≤100 µs target met), ADR-110-REVIEW-GUIDE (one-page reviewer tour), ADR-110-BRANCH-STATE (coordination map vs feat/adr-115-ha-mqtt-matter). Host decoders + tests: Python SyncPacketParser (10) + Rust wifi_densepose_hardware::SyncPacket (15), cross-language hex pin gates drift. |
Signal processing and sensing
| ADR | Title | Status |
|---|---|---|
| ADR-013 | Feature-Level Sensing on Commodity Gear | Accepted |
| ADR-014 | SOTA Signal Processing Algorithms | Accepted |
| ADR-021 | Vital Sign Detection (breathing, heart rate) | Partial |
| ADR-030 | Persistent Field Model and Drift Detection | Proposed |
| ADR-033 | CRV Signal Line Sensing Integration | Proposed |
| ADR-037 | Multi-Person Pose Detection from Single ESP32 | Proposed |
| ADR-042 | Coherent Human Channel Imaging (beyond CSI) | Proposed |
| ADR-134 | First-Class Channel Impulse Response (CIR) Support | Proposed |
| ADR-135 | Empty-Room Baseline Calibration (per-subcarrier Welford statistics) | Proposed |
Machine learning and training
| ADR | Title | Status |
|---|---|---|
| ADR-005 | SONA Self-Learning for Pose Estimation | Partial |
| ADR-006 | GNN-Enhanced CSI Pattern Recognition | Partial |
| ADR-015 | Public Dataset Strategy (MM-Fi, Wi-Pose) | Accepted |
| ADR-016 | RuVector Training Pipeline Integration | Accepted |
| ADR-017 | RuVector Signal + MAT Integration | Proposed |
| ADR-020 | Migrate AI Inference to Rust (ONNX Runtime) | Accepted |
| ADR-023 | Trained DensePose Model with RuVector Pipeline | Proposed |
| ADR-024 | Project AETHER: Contrastive CSI Embeddings | Required |
| ADR-027 | Project MERIDIAN: Cross-Environment Generalization | Proposed |
| ADR-149 | AetherArena: public spatial-intelligence benchmark on Hugging Face | Proposed |
| ADR-150 | RF Foundation Encoder: pose-preserving, subject/room/device-invariant CSI embedding | Proposed |
| ADR-151 | Per-Room Calibration & Specialized Model Training (room-first → bank of small ruVector specialists) | Proposed |
| ADR-152 | WiFi-Pose SOTA 2026 Intake: geometry-conditioned calibration, external benchmarks, foundation-encoder recipe | Proposed |
Platform and UI
| ADR | Title | Status |
|---|---|---|
| ADR-019 | Sensing-Only UI with Gaussian Splats | Accepted |
| ADR-022 | Windows WiFi Enhanced Fidelity (multi-BSSID) | Partial |
| ADR-025 | macOS CoreWLAN WiFi Sensing | Proposed |
| ADR-031 | RuView Sensing-First RF Mode | Proposed |
| ADR-034 | Expo React Native Mobile App | Accepted |
| ADR-035 | Live Sensing UI Accuracy and Data Transparency | Accepted |
| ADR-036 | Training Pipeline UI Integration | Proposed |
| ADR-043 | Sensing Server UI API Completion (14 endpoints) | Accepted |
| ADR-115 | Home Assistant integration via MQTT auto-discovery + Matter bridge (HA-DISCO + HA-FABRIC + HA-MIND) | Accepted (MQTT track) / Proposed (Matter SDK P8b) |
| ADR-169 | adam-mode — light theme toggle for the three.js realtime demo | Proposed |
| ADR-170 | yoga-mode — yoga pose detection, classification, and scoring for the three.js realtime demo | Proposed |
Architecture and infrastructure
| ADR | Title | Status |
|---|---|---|
| ADR-001 | WiFi-Mat Disaster Detection Architecture | Accepted |
| ADR-002 | RuVector RVF Integration Strategy | Superseded |
| ADR-003 | RVF Cognitive Containers for CSI | Proposed |
| ADR-004 | HNSW Vector Search for Fingerprinting | Partial |
| ADR-007 | Post-Quantum Cryptography for Sensing | Proposed |
| ADR-008 | Distributed Consensus for Multi-AP | Proposed |
| ADR-009 | RVF WASM Runtime for Edge Deployment | Proposed |
| ADR-010 | Witness Chains for Audit Trail Integrity | Proposed |
| ADR-011 | Proof-of-Reality and Mock Elimination | Proposed |
| ADR-026 | Survivor Track Lifecycle (MAT crate) | Accepted |
| ADR-038 | Sublinear GOAP for Roadmap Optimization | Proposed |
| ADR-095 | rvCSI — Edge RF Sensing Runtime Platform | Proposed |
| ADR-096 | rvCSI — Crate Topology, the napi-c Shim, and the napi-rs Node Surface | Proposed |
| ADR-097 | Adopt rvCSI as RuView's primary CSI runtime (phased adoption) | Proposed |
| ADR-098 | Evaluate ruvnet/midstream for RuView's CSI / WebSocket / mesh pipeline |
Rejected |
| ADR-099 | Adopt midstream as RuView's real-time introspection + low-latency tap | Proposed |
Related
- DDD Domain Models — Bounded context definitions, aggregate roots, and ubiquitous language
- User Guide — Setup, API reference, and hardware instructions
- Build Guide — Building from source