Files
ruvnet--RuView/CLAUDE.md
T
rUv 2a307138f2 feat: per-room calibration system (ADR-151) + cognitum-v0 appliance integration spec (#989)
* docs(adr): ADR-151 — Per-Room Calibration & Specialized Model Training

Room-first calibration -> bank of small specialised ruVector models
(breathing, heartbeat, restlessness, posture, presence, anomaly) distilled
from the frozen Hugging-Face-published RF Foundation Encoder (ADR-150).

Four-stage local-first pipeline: baseline (ADR-135 environmental fingerprint)
-> guided enrollment (NEW EnrollmentProtocol, clean anchors not hours) ->
feature extraction (reuse signal_features + ruvsense) -> specialist bank
training (rapid_adapt LoRA heads, RVF storage, HNSW prototypes).

Invariants: specialisation over scale; local heads over a shared public base;
honest STALE degradation on baseline drift. Indexes ADR-149/150/151.

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(cli): calibration HTTP API for UI-driven baseline capture (ADR-135/151)

Adds `wifi-densepose calibrate-serve` — an Axum HTTP API that wraps the
ADR-135 CalibrationRecorder so a UI (or any client) can drive an empty-room
baseline capture remotely. Stage 1 ("teach the room") of the ADR-151 room
calibration & training pipeline.

A single background task owns the UDP socket (ESP32 0xC511_0001 frames) and
the optional active recorder; HTTP handlers talk to it over an mpsc command
channel and read a shared status snapshot, keeping the &mut recorder
lock-free. CORS permissive so a browser UI can call it.

Endpoints (/api/v1/calibration/*):
  GET  /health      liveness + UDP ingest stats (frames_seen, streaming)
  POST /start       { tier?, duration_s?, room_id?, min_frames? }
  GET  /status      live progress (state, frames, progress, z, eta) — poll for UI
  POST /stop        finalize the current session early
  GET  /result      finalized baseline summary (amp/phase-dispersion averages)
  GET  /baselines   list persisted baseline .bin files

Reuses the existing calibrate.rs ESP32 wire parser (made pub(crate)); honest
abort when <10 frames arrive in the window (e.g. ESP32 not streaming).

Verified end-to-end over loopback: start -> 300 replayed HT20 frames ->
state=complete, 52-subcarrier baseline, phase_dispersion_avg=0.00096
(concentrated/valid), persisted to disk; all 6 endpoints exercised.
CLI: 19 tests pass; crate builds clean.

Co-Authored-By: claude-flow <ruv@ruv.net>

* test(cli): firewall-free CSI UDP relay for local Windows ESP32 testing

Windows Defender blocks inbound LAN UDP to a freshly-built binary without an
admin allow-rule; python.exe is already allowed. This relay binds the public
CSI port and forwards each datagram verbatim to a loopback port where
`calibrate-serve --udp-bind 127.0.0.1 --udp-port 5006` listens (loopback is
firewall-exempt). No admin required.

Validated: ESP32-format 0xC5110001 frames -> :5005 -> relay -> :5006 ->
calibrate-serve -> state=complete, 52-subcarrier baseline,
phase_dispersion_avg=0.00098 (clean). Completes the no-admin live-test path.

Co-Authored-By: claude-flow <ruv@ruv.net>

* docs(changelog): record ADR-151 calibration API (calibrate-serve)

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(calibration): ADR-151 Stages 2–5 — enrollment, extraction, specialist bank, runtime

New crate wifi-densepose-calibration implementing the per-room pipeline beyond
Stage-1 baseline:

- anchor.rs: guided-anchor sequence + event-sourced EnrollmentSession (Stage 2)
- enrollment.rs: AnchorQualityGate + AnchorRecorder — gates anchors against the
  ADR-135 baseline deviation (presence/motion), re-prompts bad captures
- extract.rs: Features + AnchorFeature — autocorrelation periodicity (breathing/
  HR bands), variance/motion (Stage 3)
- specialist.rs: 6 small room-calibrated models — presence (learned threshold),
  posture (nearest-prototype), breathing/heartbeat (band periodicity),
  restlessness (calm/active normalization), anomaly (novelty vs anchors) (Stage 4)
- bank.rs: SpecialistBank — train/persist + baseline-drift STALE invalidation
- runtime.rs: MixtureOfSpecialists — presence short-circuit + anomaly veto +
  stale flagging (Stage 5)

Statistical heads make the pipeline runnable/validatable today; the ADR-150 HF
RF Foundation Encoder backbone is the documented upgrade path. 29 unit tests pass.

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(cli): wire ADR-151 enroll / train-room / room-status / room-watch

Integrates the wifi-densepose-calibration crate into the CLI as four
subcommands driving the full Stage 2–5 pipeline against a live ESP32 raw-CSI
stream (edge_tier=0):

- enroll: walks the guided anchor sequence, gates each capture against the
  ADR-135 baseline deviation (re-prompts bad anchors), writes labelled features
- train-room: fits the SpecialistBank from the enrollment, persists JSON
- room-status: prints a trained bank's summary
- room-watch: live mixture-of-specialists readout (presence/posture/breathing/
  heart/restless) over a rolling window, with anomaly veto + STALE flagging

Per-frame scalar is the mean CSI amplitude (carries presence/motion + breathing
modulation). Validated end-to-end on the live ESP32 (COM8, edge_tier=0): the
real parser → feature extraction → runtime detected breathing (~16–31 BPM) on
hardware. Full multi-anchor enrollment accuracy requires the operator to perform
the poses; phase-based breathing extraction is a noted refinement.

48 tests pass (29 calibration + 19 CLI).

Co-Authored-By: claude-flow <ruv@ruv.net>

* docs(adr-151): mark Stages 1–5 implemented; expand CHANGELOG

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(cli): keep proven mean-amplitude carrier for room features

The max-variance-subcarrier carrier locked onto motion artifacts (not
breathing) and also had an out-of-bounds bug on variable CSI subcarrier
counts. Reverted to the mean-amplitude carrier, which is validated live to
detect breathing. Phase-based extraction on a stable subcarrier remains the
proper higher-SNR refinement (ADR-151 §4).

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(calibration): multistatic fusion of co-located nodes (ADR-029/151)

MultiNodeMixture fuses several co-located nodes (each with its own
room-calibrated SpecialistBank) into one RoomState:
- presence: OR across nodes (any node seeing a person wins)
- posture/breathing/heartbeat: highest-confidence node (best viewpoint)
- restlessness/anomaly: max across nodes
- veto: any node's physically-implausible signal vetoes the room's vitals
  (anti-hallucination, same as single-node runtime) + presence short-circuit
- stale: any node's STALE flag propagates

Same-room multistatic only; cross-room is federation (ADR-105), not fusion.
6 unit tests (presence OR, best-confidence breathing, single-node veto,
staleness). 35 calibration tests pass.

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(cli): multistatic room-watch — fuse co-located nodes (ADR-029/151)

`room-watch --node-bank N:path` (repeatable) groups live CSI frames by node_id
and fuses per-node banks via MultiNodeMixture. Validated live on COM8 (node 9,
edge_tier=0): frames grouped + fused end-to-end. True 2-node fusion is covered
by unit tests; a second raw-CSI node is the hardware blocker. 54 tests pass.

Co-Authored-By: claude-flow <ruv@ruv.net>

* docs(integration): calibration → cognitum-v0 appliance integration overview

Detailed cross-repo integration spec for cognitum-one/v0-appliance: data
contracts (CSI wire format, ADR-135 baseline binary, enrollment/bank/RoomState
JSON schemas), calibrate-serve HTTP API, public crate API, Pi5+Hailo tiering,
and a 5-step appliance integration plan. Grounded in the verified cognitum-v0
inventory (aarch64, cargo 1.96, HAILO10H, ruview-vitals-worker:50054).

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(calibration): address PR review — aarch64 decouple, API auth, path traversal, throttle

Resolves the review on #989:

- **Cross-compile (the appliance blocker):** make wifi-densepose-mat optional
  and feature-gate it (`mat`), so `cargo build -p wifi-densepose-cli
  --no-default-features` excludes the mat→nn→ort(ONNX)→openssl-sys chain.
  Verified: `cargo tree --no-default-features` shows 0 ort/openssl deps →
  calibration cross-compiles clean for the Pi.
- **Security (must-fix before LAN):**
  - `--token` / CALIBRATE_TOKEN bearer-auth middleware on every route; warns if
    bound non-loopback without a token.
  - sanitize client-supplied `room_id` to [A-Za-z0-9_-] (≤64) before it reaches
    the baseline write path — kills the `../` file-write primitive. + test.
- **Perf:** stop locking shared status + cloning SessionStatus on every UDP
  frame — counters/snapshot flush on the 200 ms tick instead (no CPU
  starvation under flood). finalize write moved to async `tokio::fs::write`.
- **Docs:** ADR-151 STALE wording matches the impl (baseline-id change;
  drift-threshold = P6 refinement); integration doc gets the
  `--no-default-features` build + auth/sanitize notes.

35 calibration + 15 CLI tests (no-default) / 20 CLI (default) pass.

Co-Authored-By: claude-flow <ruv@ruv.net>

* docs(worldgraph,worldmodel): add crates.io READMEs

Plain-language overviews + feature lists, comparison tables (symbolic graph vs
predictive occupancy; graph vs grid vs event-log), usage, and technical
details. Adds readme = "README.md" to both manifests so they render on
crates.io on the next release.

Co-Authored-By: claude-flow <ruv@ruv.net>

* release: worldgraph & worldmodel 0.3.1 (READMEs on crates.io)

Co-Authored-By: claude-flow <ruv@ruv.net>

* docs: precise calibration validation scope (capture+API+auth proven; clean enroll→train→infer not yet on-target)

Aligns ADR-151 §7 + the appliance integration doc with the PR #989 scope
clarification: nothing has run a clean baseline → enroll → train → infer on
live CSI; the live breathing read used the stateless head, not a trained bank.
Adds --source-format adr018v6 to the backlog.

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(calibrate-serve): live GET /room/state endpoint (mixture over CSI window)

Adds a live RoomState readout over HTTP — the appliance UI's main need. The
ingest task maintains a rolling per-frame scalar window (flushed on the 200 ms
tick, no per-frame lock); the handler loads a bank (resolved as a sanitized
name under output_dir — same path-traversal defense as room_id), runs the
MixtureOfSpecialists over the window, returns RoomState JSON.

Validated live (ESP32-S3 via relay): breathing 14-19 BPM over HTTP; a
bank=../../etc/passwd query is neutralized to 'etcpasswd' (no traversal).

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(calibrate-serve): POST /room/train + fix AnchorLabel JSON to snake_case

- POST /api/v1/room/train: { room_id, baseline_id, anchors[] } → trains a
  SpecialistBank and persists it as <output_dir>/<room_id>.json (path-sanitized),
  readable via /room/state?bank=<room_id>. Completes the HTTP train→infer loop.
- Fix data-contract bug: AnchorLabel serialized as PascalCase variant names
  (serde default) while as_str() + the integration doc used snake_case. Added
  #[serde(rename_all = "snake_case")] so the JSON wire format matches the
  documented contract (empty/stand_still/…). Locked with a roundtrip test.

Validated live (ESP32-S3): POST train (4 anchors → 6 specialists, persisted) →
GET /room/state returns RoomState with the trained presence/restlessness; the
synthetic-vs-real scale mismatch correctly triggers the anomaly veto. 36
calibration tests pass.

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(calibrate-serve): live enroll-over-HTTP (POST /enroll/anchor + /enroll/status)

Closes the last HTTP gap — the appliance can now drive the ENTIRE calibration
pipeline over HTTP without the CLI:
  baseline (start/stop) -> enroll/anchor x8 -> room/train -> room/state

- POST /enroll/anchor { room_id, baseline, label, duration_s? }: the ingest task
  loads the baseline (sanitized name under output_dir), captures the anchor for
  the duration against it (AnchorRecorder + per-frame series), runs the quality
  gate, and on completion replies with the verdict + accumulates the AnchorFeature
  in an in-server enrollment map keyed by room_id. Re-prompts on rejection.
- GET /enroll/status?room=<id>: accepted anchors, next, complete.
- POST /room/train now falls back to the in-server enrollment when anchors[] is
  omitted.

Validated live (ESP32-S3): capture baseline -> enroll stand_still (271 frames,
6s) -> gate correctly rejects "no person detected (presence_z 0.90 < 1.50)"
relative to a same-occupancy baseline (a clean empty-room baseline is the
documented on-target prerequisite). Builds clean; CLI tests pass.

Co-Authored-By: claude-flow <ruv@ruv.net>

* test(calibrate-serve): HTTP integration tests for the room/enroll endpoints

Factor the router into build_router() (shared by execute + tests) and add
tower-oneshot integration tests (no network/ingest needed):
- health + descriptor → 200
- POST /room/train persists the bank; GET /room/state → 200; train with no
  anchors/enrollment → 400
- path-traversal: /room/state?bank=../../etc/passwd → 404 (sanitized, never
  reads outside output_dir)
- enroll/status empty; /enroll/anchor with an unknown label → 400

CI regression coverage for the endpoints added this session. 18 CLI tests pass.

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(mat): make serde non-optional — unblocks `cargo test --workspace --no-default-features`

Making wifi-densepose-mat optional in the CLI (for the aarch64/ort decouple)
exposed a latent feature bug: mat's `api` module compiles unconditionally and
uses serde, but `serde` was an optional dep enabled only via the `api`/`serde`
features. Previously the CLI's *unconditional* mat dependency enabled those
features transitively, so `--workspace --no-default-features` still got serde;
once mat became optional+gated, the workspace build lost it →
`error[E0432]: unresolved import serde` across mat's api/* (CI red).

mat already pulls serde_json + axum unconditionally, so making `serde`
non-optional has no real cost and restores the workspace build. Does NOT affect
the aarch64 CLI build (mat isn't built there at all): verified
`cargo tree -p wifi-densepose-cli --no-default-features` still shows 0
ort/openssl deps, and `cargo test --workspace --no-default-features` compiles
clean.

Co-Authored-By: claude-flow <ruv@ruv.net>

* docs(claude.md): add wifi-densepose-calibration to crate table (pre-merge)

Co-Authored-By: claude-flow <ruv@ruv.net>

* docs(adr): ADR-152 — WiFi-pose SOTA 2026 intake (geometry-conditioned calibration, external benchmarks, encoder recipe)

Records the 2026-06-10 deep-research run (22 sources, 110 claims, 25
adversarially verified: 24 confirmed / 1 refuted) and the decisions it
implies:

- §2.1 ACCEPTED: geometry-condition the ADR-151 calibration system —
  NodeGeometry at enrollment, geometry embeddings for future LoRA heads,
  PerceptAlign-style two-checkerboard camera↔WiFi alignment for the
  ADR-079 supervised path. PerceptAlign (MobiCom'26) names the failure
  mode ("coordinate overfitting") that matches our own ADR-150 cross-
  subject collapse.
- §2.2 ACCEPTED: benchmark protocol vs external "WiFlow-STD (DY2434)"
  (claimed 97.25% PCK@20, Apache-2.0 weights+dataset) with a no-citation
  rule until measured on our 17-keypoint ESP32 eval set. Name collision
  with our internal WiFlow is disambiguated.
- §2.3 ACCEPTED: amend ADR-150 training recipe per UNSW MAE study —
  80% masking, (30,3) patches, data-over-capacity priority (log-linear,
  unsaturated at 1.3M samples).
- §2.4 watch items: IEEE 802.11bf-2025 published 2025-09-26;
  esp_wifi_sensing as external presence baseline (drop-in claim REFUTED
  0-3); ZTECSITool 160MHz/512-subcarrier anchor node (procurement-gated).
- §2.5 NOT adopted: non-WiFi "foundation model" papers; DensePose-UV
  (no 2025-2026 work does UV regression from commodity WiFi).

Every number is evidence-graded CLAIMED vs MEASURED in the source
register. Re-check horizon 2026-12.

Co-Authored-By: RuFlo <ruv@ruv.net>

* test(calibration): full-loop integration test — baseline→enroll→train→infer proven in-process (ADR-151 §7 gap, software half)

Closes the software half of PR #989's headline validation gap: the
complete calibration loop had never run end-to-end anywhere, even
in-process. tests/full_loop.rs (412 lines, deterministic xorshift32
room simulator, HT20/52-subcarrier/20Hz, same fingerprint family as
the ADR-135 roundtrip test) now drives the CLI's exact stage order
through the public API:

  1. baseline  — 600 static frames, zero motion flags post-warmup,
                 calibration_uuid() exactly as the CLI derives it
  2. enroll    — all 8 AnchorLabel::SEQUENCE anchors through
                 AnchorQualityGate::default(), session is_complete()
  3. extract   — AnchorFeature::from_series recovers injected 0.25Hz
                 and 0.125Hz breathing within ±0.04Hz
  4. train     — SpecialistBank::train fits all 6 specialists; JSON
                 round-trip and the runtime consumes the RELOADED bank
  5. infer     — positive: never-enrolled 0.30Hz subject reads present,
                 18±2 BPM; negative: empty window reads absent;
                 degradation: foreign baseline_id flags STALE

Seed-robust (5 seeds), passes with and without default features:
36 unit + 1 integration green.

Validation docs updated (ADR-151 §7 + integration doc §7 matrix): what
remains is strictly the on-target hardware session (real CSI, physically
empty room, operator performing the guided anchors). Three behavioral
findings from building the test are recorded for pre-session triage:
z-band squeeze between baseline motion flagging (z>2.0) and the still-
anchor gate (presence_z≥1.5) — likeliest on-hardware enroll failure;
variance-only PresenceSpecialist missing motionless-person mean shift;
ungated breathing_hz/heart_hz in noise-window embeddings.

Co-Authored-By: RuFlo <ruv@ruv.net>

* fix(calibration): close all four ADR-152 behavioral findings pre-hardware-session

The full-loop integration test surfaced three findings; fixing the third
exposed a fourth. All four are fixed and regression-guarded:

1. z-band squeeze (enrollment.rs) — anchor motion is now measured from
   frame-to-frame deltas of the deviation series (|Δz| > Z_DELTA_MOTION
   0.5 ∨ |Δφ| > π/6), not from the absolute motion_flagged, which fires
   at amplitude_z_median > 2.0 vs the EMPTY baseline and so conflated
   presence strength with motion. A strongly-reflecting still person
   (z = 3.0 — every frame flagged by the old heuristic) now enrolls.
   The old unit tests mocked (z=3.0, motion=false), a combination the
   real deviation() can never emit — which is exactly how the squeeze
   hid; tests now derive the flag from z the way the producer does.

2. variance-only presence (specialist.rs) — PresenceSpecialist gains a
   mean-shift channel: present when variance > threshold OR
   |mean − empty_mean| > mean_dist_threshold (trained at half the
   empty→occupied mean distance, None when the means don't separate).
   Detects the motionless person whose body raises the scalar mean but
   not its variance. Old persisted banks deserialize with the channel
   inert (serde default None) — variance-only behavior preserved,
   proven by a fixture test against pre-change JSON.

3. ungated hz embedding (extract.rs) — Features::embedding() zeroes
   breathing_hz/heart_hz below EMBED_MIN_SCORE (0.25), keeping the
   random in-band peaks of noise windows out of the posture/anomaly
   prototype space. Raw fields stay ungated (specialists have their
   own stricter gates).

4. heart-band lag-floor leakage (extract.rs, found while fixing 3) —
   a pure 0.30 Hz breathing signal scored 0.67 in the heart band at
   3.33 Hz: out-of-band rhythm leaks as a monotonic slope whose max
   sits at the band's lag floor, so score gating alone cannot stop it.
   autocorr_dominant now requires the winning lag to be an interior
   local maximum; band-edge "peaks" are rejected, true in-band peaks
   (interior by definition) are preserved.

full_loop.rs strengthened to drive the fixes end-to-end: the StandStill
anchor is now a z=3.0 strong reflector (unenrollable pre-fix), and a new
motionless-person runtime case proves mean-channel detection at empty-
level variance.

Validation: 41 calibration unit + 1 full-loop integration + 23 CLI tests
green; cargo test --workspace --no-default-features exit 0.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-06-10 15:21:09 -04:00

18 KiB

Claude Code Configuration — WiFi-DensePose + Claude Flow V3

Project: wifi-densepose

WiFi-based human pose estimation using Channel State Information (CSI). Dual codebase: Python v1 (v1/) and Rust port (v2/).

Key Rust Crates

Crate Description
wifi-densepose-core Core types, traits, error types, CSI frame primitives
wifi-densepose-signal SOTA signal processing + RuvSense multistatic sensing (16 modules)
wifi-densepose-nn Neural network inference (ONNX, PyTorch, Candle backends)
wifi-densepose-train Training pipeline with ruvector integration + ruview_metrics
wifi-densepose-mat Mass Casualty Assessment Tool — disaster survivor detection
wifi-densepose-hardware ESP32 aggregator, TDM protocol, channel hopping firmware
wifi-densepose-ruvector RuVector v2.0.4 integration + cross-viewpoint fusion (5 modules)
wifi-densepose-wasm WebAssembly bindings for browser deployment
wifi-densepose-cli CLI tool (wifi-densepose binary) — calibrate/calibrate-serve/enroll/train-room/room-watch + MAT (MAT gated behind the mat feature; build --no-default-features for the aarch64/appliance calibration binary)
wifi-densepose-calibration ADR-151 per-room calibration & specialist training — baseline → enroll → extract → train → bank of small specialists (presence/posture/breathing/heartbeat/restlessness/anomaly) + multistatic fusion; pure Rust, edge-deployable
wifi-densepose-sensing-server Lightweight Axum server for WiFi sensing UI
wifi-densepose-wifiscan Multi-BSSID WiFi scanning (ADR-022)
wifi-densepose-vitals ESP32 CSI-grade vital sign extraction (ADR-021)
nvsim Deterministic NV-diamond magnetometer pipeline simulator (ADR-089) — standalone leaf, WASM-ready
vendor/rvcsi (submodule) rvCSI — edge RF sensing runtime (ADR-095/096): 9 crates (rvcsi-core/-dsp/-events/-adapter-file/-adapter-nexmon/-ruvector/-runtime/-node/-cli). Lives in its own repo (github.com/ruvnet/rvcsi), vendored here under vendor/rvcsi, published to crates.io as rvcsi-* 0.3.x and to npm as @ruv/rvcsi. Not a v2/ workspace member — depend on the published crates (or the submodule's crates/rvcsi-* paths). Normalized CsiFrame/CsiWindow/CsiEvent schema, validate-before-FFI, reusable DSP, typed confidence-scored events, the napi-c Nexmon shim (real nexmon_csi .pcap from a Raspberry Pi 5 / 4 / 3B+ — BCM43455c0), the napi-rs SDK, the rvcsi CLI, a Claude Code plugin.
ruview-swarm Drone swarm control system (ADR-148) — hierarchical-mesh topology, Raft consensus, MARL, CSI sensing payload, MAVLink/PX4 compat, Ruflo AI-agent integration

RuvSense Modules (signal/src/ruvsense/)

Module Purpose
multiband.rs Multi-band CSI frame fusion, cross-channel coherence
phase_align.rs Iterative LO phase offset estimation, circular mean
multistatic.rs Attention-weighted fusion, geometric diversity
coherence.rs Z-score coherence scoring, DriftProfile
coherence_gate.rs Accept/PredictOnly/Reject/Recalibrate gate decisions
pose_tracker.rs 17-keypoint Kalman tracker with AETHER re-ID embeddings
field_model.rs SVD room eigenstructure, perturbation extraction
tomography.rs RF tomography, ISTA L1 solver, voxel grid
longitudinal.rs Welford stats, biomechanics drift detection
intention.rs Pre-movement lead signals (200-500ms)
cross_room.rs Environment fingerprinting, transition graph
gesture.rs DTW template matching gesture classifier
adversarial.rs Physically impossible signal detection, multi-link consistency
cir.rs ADR-134 CSI→CIR via ISTA L1 sparse recovery (NeumannSolver warm-start)
calibration.rs ADR-135 empty-room baseline (Welford amplitude + von Mises phase, drift trigger)

Cross-Viewpoint Fusion (ruvector/src/viewpoint/)

Module Purpose
attention.rs CrossViewpointAttention, GeometricBias, softmax with G_bias
geometry.rs GeometricDiversityIndex, Cramer-Rao bounds, Fisher Information
coherence.rs Phase phasor coherence, hysteresis gate
fusion.rs MultistaticArray aggregate root, domain events

RuVector v2.0.4 Integration (ADR-016 complete, ADR-017 proposed)

All 5 ruvector crates integrated in workspace:

  • ruvector-mincutmetrics.rs (DynamicPersonMatcher) + subcarrier_selection.rs
  • ruvector-attn-mincutmodel.rs (apply_antenna_attention) + spectrogram.rs
  • ruvector-temporal-tensordataset.rs (CompressedCsiBuffer) + breathing.rs
  • ruvector-solversubcarrier.rs (sparse interpolation 114→56) + triangulation.rs
  • ruvector-attentionmodel.rs (apply_spatial_attention) + bvp.rs

Architecture Decisions

43 ADRs in docs/adr/ (ADR-001 through ADR-043). Key ones:

  • ADR-014: SOTA signal processing (Accepted)
  • ADR-015: MM-Fi + Wi-Pose training datasets (Accepted)
  • ADR-016: RuVector training pipeline integration (Accepted — complete)
  • ADR-017: RuVector signal + MAT integration (Proposed — next target)
  • ADR-024: Contrastive CSI embedding / AETHER (Accepted)
  • ADR-027: Cross-environment domain generalization / MERIDIAN (Accepted)
  • ADR-028: ESP32 capability audit + witness verification (Accepted)
  • ADR-029: RuvSense multistatic sensing mode (Proposed)
  • ADR-030: RuvSense persistent field model (Proposed)
  • ADR-031: RuView sensing-first RF mode (Proposed)
  • ADR-032: Multistatic mesh security hardening (Proposed)
  • ADR-148: Drone swarm control system / ruview-swarm (In Progress)

Supported Hardware

Device Port Chip Role Cost
ESP32-S3 (8MB flash) COM9 (ruvzen, was COM7) Xtensa dual-core WiFi CSI sensing node ~$9
ESP32-S3 SuperMini (4MB) Xtensa dual-core WiFi CSI (compact) ~$6
ESP32-C6 + Seeed MR60BHA2 COM12 (ruvzen, was COM4) RISC-V + 60 GHz FMCW mmWave HR/BR/presence + WiFi CSI ~$15
HLK-LD2410 24 GHz FMCW Presence + distance ~$3

Not supported: ESP32 (original), ESP32-C3 — single-core, can't run CSI DSP pipeline.

Build & Test Commands (this repo)

# Rust — full workspace tests (1,031+ tests, ~2 min)
cd v2
cargo test --workspace --no-default-features

# Rust — single crate check (no GPU needed)
cargo check -p wifi-densepose-train --no-default-features

# Python — deterministic proof verification (SHA-256)
python archive/v1/data/proof/verify.py

# Python — test suite
cd archive/v1 && python -m pytest tests/ -x -q

ESP32 Firmware Build (Windows — Python subprocess required)

# Build 8MB firmware (real WiFi CSI mode, no mocks)
# See CLAUDE.local.md for the full Python subprocess command
# Key: must strip MSYSTEM env vars for ESP-IDF v5.4 on Git Bash

# Build 4MB firmware
cp sdkconfig.defaults.4mb sdkconfig.defaults
# then same build process

# Flash to COM7
# [python, idf_py, '-p', 'COM7', 'flash']

# Provision WiFi
python firmware/esp32-csi-node/provision.py --port COM7 \
  --ssid "YourWiFi" --password "secret" --target-ip 192.168.1.20

# Monitor serial
python -m serial.tools.miniterm COM7 115200

Firmware Release Process

  1. Build 8MB from sdkconfig.defaults.template (no mock)
  2. Build 4MB from sdkconfig.defaults.4mb (no mock)
  3. Save 6 binaries: esp32-csi-node.bin, bootloader.bin, partition-table.bin, ota_data_initial.bin, esp32-csi-node-4mb.bin, partition-table-4mb.bin
  4. Tag: git tag v0.X.Y-esp32 && git push origin v0.X.Y-esp32
  5. Release: gh release create v0.X.Y-esp32 <binaries> --title "..." --notes-file ...
  6. Verify on real hardware (COM7) before publishing
  7. CRITICAL: Always test with real WiFi CSI, not mock mode — mock missed the Kconfig threshold bug

Crate Publishing Order

Crates must be published in dependency order:

  1. wifi-densepose-core (no internal deps)
  2. wifi-densepose-vitals (no internal deps)
  3. wifi-densepose-wifiscan (no internal deps)
  4. wifi-densepose-hardware (no internal deps)
  5. wifi-densepose-signal (depends on core)
  6. wifi-densepose-nn (no internal deps, workspace only)
  7. wifi-densepose-ruvector (no internal deps, workspace only)
  8. wifi-densepose-train (depends on signal, nn)
  9. wifi-densepose-mat (depends on core, signal, nn)
  10. wifi-densepose-wasm (depends on mat)
  11. wifi-densepose-sensing-server (depends on wifiscan)
  12. wifi-densepose-cli (depends on mat)

Validation & Witness Verification (ADR-028)

After any significant code change, run the full validation:

# 1. Rust tests — must be 1,031+ passed, 0 failed
cd v2
cargo test --workspace --no-default-features

# 2. Python proof — must print VERDICT: PASS
cd ..
python archive/v1/data/proof/verify.py

# 3. Generate witness bundle (includes both above + firmware hashes)
bash scripts/generate-witness-bundle.sh

# 4. Self-verify the bundle — must be 7/7 PASS
cd dist/witness-bundle-ADR028-*/
bash VERIFY.sh

If the Python proof hash changes (e.g., numpy/scipy version update):

# Regenerate the expected hash, then verify it passes
python archive/v1/data/proof/verify.py --generate-hash
python archive/v1/data/proof/verify.py

Witness bundle contents (dist/witness-bundle-ADR028-<sha>.tar.gz):

  • WITNESS-LOG-028.md — 33-row attestation matrix with evidence per capability
  • ADR-028-esp32-capability-audit.md — Full audit findings
  • proof/verify.py + expected_features.sha256 — Deterministic pipeline proof
  • test-results/rust-workspace-tests.log — Full cargo test output
  • firmware-manifest/source-hashes.txt — SHA-256 of all 7 ESP32 firmware files
  • crate-manifest/versions.txt — All 15 crates with versions
  • VERIFY.sh — One-command self-verification for recipients

Key proof artifacts:

  • archive/v1/data/proof/verify.py — Trust Kill Switch: feeds reference signal through production pipeline, hashes output
  • archive/v1/data/proof/expected_features.sha256 — Published expected hash
  • archive/v1/data/proof/sample_csi_data.json — 1,000 synthetic CSI frames (seed=42)
  • docs/WITNESS-LOG-028.md — 11-step reproducible verification procedure
  • docs/adr/ADR-028-esp32-capability-audit.md — Complete audit record

Branch

Default branch: main Active feature branch: ruvsense-full-implementation (PR #77)


Behavioral Rules (Always Enforced)

  • Do what has been asked; nothing more, nothing less
  • NEVER create files unless they're absolutely necessary for achieving your goal
  • ALWAYS prefer editing an existing file to creating a new one
  • NEVER proactively create documentation files (*.md) or README files unless explicitly requested
  • NEVER save working files, text/mds, or tests to the root folder
  • Never continuously check status after spawning a swarm — wait for results
  • ALWAYS read a file before editing it
  • NEVER commit secrets, credentials, or .env files

File Organization

  • NEVER save to root folder — use the directories below
  • docs/adr/ — Architecture Decision Records (43 ADRs)
  • docs/ddd/ — Domain-Driven Design models
  • v2/crates/ — Rust workspace crates (15 crates)
  • v2/crates/wifi-densepose-signal/src/ruvsense/ — RuvSense multistatic modules (14 files)
  • v2/crates/wifi-densepose-ruvector/src/viewpoint/ — Cross-viewpoint fusion (5 files)
  • v2/crates/wifi-densepose-hardware/src/esp32/ — ESP32 TDM protocol
  • firmware/esp32-csi-node/main/ — ESP32 C firmware (channel hopping, NVS config, TDM)
  • archive/v1/src/ — Python source (core, hardware, services, api)
  • archive/v1/data/proof/ — Deterministic CSI proof bundles
  • .claude-flow/ — Claude Flow coordination state (committed for team sharing)
  • .claude/ — Claude Code settings, agents, memory (committed for team sharing)

Project Architecture

  • Follow Domain-Driven Design with bounded contexts
  • Keep files under 500 lines
  • Use typed interfaces for all public APIs
  • Prefer TDD London School (mock-first) for new code
  • Use event sourcing for state changes
  • Ensure input validation at system boundaries

Project Config

  • Topology: hierarchical-mesh
  • Max Agents: 15
  • Memory: hybrid
  • HNSW: Enabled
  • Neural: Enabled

Pre-Merge Checklist

Before merging any PR, verify each item applies and is addressed:

  1. Rust tests passcargo test --workspace --no-default-features (1,031+ passed, 0 failed)
  2. Python proof passespython archive/v1/data/proof/verify.py (VERDICT: PASS)
  3. README.md — Update platform tables, crate descriptions, hardware tables, feature summaries if scope changed
  4. CLAUDE.md — Update crate table, ADR list, module tables, version if scope changed
  5. CHANGELOG.md — Add entry under [Unreleased] with what was added/fixed/changed
  6. User guide (docs/user-guide.md) — Update if new data sources, CLI flags, or setup steps were added
  7. ADR index — Update ADR count in README docs table if a new ADR was created
  8. Witness bundle — Regenerate if tests or proof hash changed: bash scripts/generate-witness-bundle.sh
  9. Docker Hub image — Only rebuild if Dockerfile, dependencies, or runtime behavior changed
  10. Crate publishing — Only needed if a crate is published to crates.io and its public API changed
  11. .gitignore — Add any new build artifacts or binaries
  12. Security audit — Run security review for new modules touching hardware/network boundaries

Build & Test

# Build
npm run build

# Test
npm test

# Lint
npm run lint
  • ALWAYS run tests after making code changes
  • ALWAYS verify build succeeds before committing

Security Rules

  • NEVER hardcode API keys, secrets, or credentials in source files
  • NEVER commit .env files or any file containing secrets
  • Always validate user input at system boundaries
  • Always sanitize file paths to prevent directory traversal
  • Run npx @claude-flow/cli@latest security scan after security-related changes
  • All operations MUST be concurrent/parallel in a single message
  • Use Claude Code's Task tool for spawning agents, not just MCP
  • ALWAYS batch ALL todos in ONE TodoWrite call (5-10+ minimum)
  • ALWAYS spawn ALL agents in ONE message with full instructions via Task tool
  • ALWAYS batch ALL file reads/writes/edits in ONE message
  • ALWAYS batch ALL Bash commands in ONE message

Swarm Orchestration

  • MUST initialize the swarm using CLI tools when starting complex tasks
  • MUST spawn concurrent agents using Claude Code's Task tool
  • Never use CLI tools alone for execution — Task tool agents do the actual work
  • MUST call CLI tools AND Task tool in ONE message for complex work

3-Tier Model Routing (ADR-026)

Tier Handler Latency Cost Use Cases
1 Agent Booster (WASM) <1ms $0 Simple transforms (var→const, add types) — Skip LLM
2 Haiku ~500ms $0.0002 Simple tasks, low complexity (<30%)
3 Sonnet/Opus 2-5s $0.003-0.015 Complex reasoning, architecture, security (>30%)
  • Always check for [AGENT_BOOSTER_AVAILABLE] or [TASK_MODEL_RECOMMENDATION] before spawning agents
  • Use Edit tool directly when [AGENT_BOOSTER_AVAILABLE]

Swarm Configuration & Anti-Drift

  • ALWAYS use hierarchical topology for coding swarms
  • Keep maxAgents at 6-8 for tight coordination
  • Use specialized strategy for clear role boundaries
  • Use raft consensus for hive-mind (leader maintains authoritative state)
  • Run frequent checkpoints via post-task hooks
  • Keep shared memory namespace for all agents
npx @claude-flow/cli@latest swarm init --topology hierarchical --max-agents 8 --strategy specialized

Swarm Execution Rules

  • ALWAYS use run_in_background: true for all agent Task calls
  • ALWAYS put ALL agent Task calls in ONE message for parallel execution
  • After spawning, STOP — do NOT add more tool calls or check status
  • Never poll TaskOutput or check swarm status — trust agents to return
  • When agent results arrive, review ALL results before proceeding

V3 CLI Commands

Core Commands

Command Subcommands Description
init 4 Project initialization
agent 8 Agent lifecycle management
swarm 6 Multi-agent swarm coordination
memory 11 AgentDB memory with HNSW search
task 6 Task creation and lifecycle
session 7 Session state management
hooks 17 Self-learning hooks + 12 workers
hive-mind 6 Byzantine fault-tolerant consensus

Quick CLI Examples

npx @claude-flow/cli@latest init --wizard
npx @claude-flow/cli@latest agent spawn -t coder --name my-coder
npx @claude-flow/cli@latest swarm init --v3-mode
npx @claude-flow/cli@latest memory search --query "authentication patterns"
npx @claude-flow/cli@latest doctor --fix

Available Agents (60+ Types)

Core Development

coder, reviewer, tester, planner, researcher

Specialized

security-architect, security-auditor, memory-specialist, performance-engineer

Swarm Coordination

hierarchical-coordinator, mesh-coordinator, adaptive-coordinator

GitHub & Repository

pr-manager, code-review-swarm, issue-tracker, release-manager

SPARC Methodology

sparc-coord, sparc-coder, specification, pseudocode, architecture

Memory Commands Reference

# Store (REQUIRED: --key, --value; OPTIONAL: --namespace, --ttl, --tags)
npx @claude-flow/cli@latest memory store --key "pattern-auth" --value "JWT with refresh" --namespace patterns

# Search (REQUIRED: --query; OPTIONAL: --namespace, --limit, --threshold)
npx @claude-flow/cli@latest memory search --query "authentication patterns"

# List (OPTIONAL: --namespace, --limit)
npx @claude-flow/cli@latest memory list --namespace patterns --limit 10

# Retrieve (REQUIRED: --key; OPTIONAL: --namespace)
npx @claude-flow/cli@latest memory retrieve --key "pattern-auth" --namespace patterns

Quick Setup

claude mcp add claude-flow -- npx -y @claude-flow/cli@latest
npx @claude-flow/cli@latest daemon start
npx @claude-flow/cli@latest doctor --fix

Claude Code vs CLI Tools

  • Claude Code's Task tool handles ALL execution: agents, file ops, code generation, git
  • CLI tools handle coordination via Bash: swarm init, memory, hooks, routing
  • NEVER use CLI tools as a substitute for Task tool agents

Support