Releases: ruvnet/RuView
Release list
v0.8.3-esp32 — multistatic + csi_fps + control-packet fixes
ESP32-S3 CSI node firmware v0.8.3-esp32 — bug-fix release.
Fixed
- #1170 — multistatic fusion
DimensionMismatchflood. The live sensing-server bridge fed raw, un-canonicalized per-node CSI (HT20≈64 / HT40≈128/192 bins) intoMultistaticFuser, so fusion errored every cycle on a mixed mesh and silently fell back to per-node sum/dedup. Node frames are now resampled onto the canonical 56-tone grid (resample-only, no z-score) before fusion. - #1180 —
csi_fps_emainflated 40–840×. Sub-millisecond UDP burst arrivals (36 µs → ~27 kHz) polluted the per-node frame-rate EMA. A 5 ms plausibility floor now rejects burst deltas, and the arrival anchor is kept across bursts so the next genuine gap measures true cadence. - #1183 — ENOMEM backoff starved control packets. Under a weak uplink the global CSI backoff also suppressed the ≤48 B/≤1 Hz
feature_state/HEALTH/sync packets. A new priority send path bypasses the backoff gate (without touching the streak) for those control packets; the misleading"HEALTH sent"log now reports the real send result.
Tooling
- Added
scripts/firmware-release-guard.sh(#1194): regenerates the expected partition table from the variant's CSV and byte-compares it to the builtpartition-table.bin(+ flash-size cross-check), failing closed so a release can't ship a partition table that doesn't match its flash-size variant.
Verification (MEASURED)
wifi-densepose-signal: 501 passed, 0 failedwifi-densepose-sensing-server: 677 passed, 0 failed- Firmware: both variants build clean (ESP-IDF v5.4); release guard PASS for 8MB (
partitions_display.csv) and 4MB (partitions_4mb.csv). - ✅ Hardware smoke test PASS — flashed the 8MB build to an ESP32-S3 (QFN56 rev v0.2, the #1116 board); booted clean, streamed real WiFi CSI (mixed
len=128/len=384, RSSI −42…−59), emitted HEALTH/feature_state via the #1183 priority path, mesh time-syncfail=0, and no #1116 edge_dsp watchdog crash over the capture. Note: #1183 starvation needs a weak (~−78 dBm) uplink to trigger; strong-RSSI bench run shows no regression but does not reproduce that specific condition.
Binaries
| File | Variant | SHA-256 |
|---|---|---|
esp32-csi-node-s3-8mb.bin |
8MB/common | ed825c52468e8ecf1cfd14417914d9e2b6acd2b1489bd60168d2559ee3ba6c88 |
esp32-csi-node-s3-4mb.bin |
4MB | 94c547a033448b437a65659bbcd8c81616d5e5d83990a9f7829625a5581bad66 |
bootloader.bin |
8MB/common | 74f90ff55a097539d788bef133c6fd2b13ee85f53b1e07f23d65de2d2f63941d |
ota_data_initial.bin |
8MB/common | 7d2c7ac4888bfd75cd5f56e8d61f69595121183afc81556c876732fd3782c62f |
partition-table.bin |
8MB/common | 67222c257c0477501fd4002275638dc4262b34eb68235b8289fb1337054d322b |
partition-table-4mb.bin |
4MB | 4c2cc4ffd52641e23b779bd57b3908014083ac3c1aab395756478c89e70d81f0 |
ESP32-S3 v0.8.2-esp32 — phantom LD2410 + ENOMEM fix (#1135)
ESP32-S3 CSI node firmware — fixes the #1135 phantom-LD2410 + sendto ENOMEM loop reported against v0.8.1-esp32.
Fixes (#1135)
- Phantom LD2410 on a floating UART (root cause). Probe-detection matched only the 4-byte head
0xF4F3F2F1, so line noise at 256000 baud on an unconnected UART1 could phantom-detect a sensor and spawn a UART task. Now requires a full validated report frame (head + sane intra-frame length + matching tail0xF8F7F6F5) — the same validate-before-trust gate used for MR60BHA2 in v0.8.1. Extracted tommwave_detect.hand covered by a host unit test (test_mmwave_detect.c). sendto ENOMEMstuck loop. The fixed 100 ms backoff was too short to drain sustained lwIP/WiFi buffer pressure. Now exponential (100→200→…→2000 ms per consecutive ENOMEM, reset on first successful send). Removing the phantom LD2410 task also removes the extra load that tipped tier-2 nodes into the stuck state.
Validation
- All CI green (firmware s3-8mb/4mb + c6, all QEMU configs, fuzzing, security scans).
- Host unit test: the #1135 case (head magic without valid tail) is REJECTED.
- Hardware (ESP32-S3 QFN56 rev v0.2): streams clean at tier-0 and tier-2, correctly reports no mmWave (no phantom), no regression.
- Caveat: the reporter's environment-specific floating-pin noise could not be reproduced on the bench, so the deterministic proof for the phantom case is the unit test. If you hit #1135, please confirm this build clears it.
Flashing (ESP32-S3)
esptool --chip esp32s3 -p <PORT> -b 460800 write_flash \
0x0 bootloader.bin 0x8000 partition-table.bin \
0xf000 ota_data_initial.bin 0x20000 esp32-csi-node-s3-8mb.bin
4MB boards: esp32-csi-node-s3-4mb.bin @ 0x20000, partition-table-4mb.bin @ 0x8000.
SHA-256
d1dd4143…ee24f7d esp32-csi-node-s3-8mb.bin
958fdd68…a686fcc esp32-csi-node-s3-4mb.bin
4c402ce4…714da509 bootloader.bin
67222c25…054d322b partition-table.bin
4c2cc4ff…e70d81f0 partition-table-4mb.bin
7d2c7ac4…3782c62f ota_data_initial.bin
App version 0.7.0 · ESP-IDF v5.4 · built from main @ 7831f29.
ESP32-S3 v0.8.1-esp32 — display + mmwave false-detect fixes (#1000, #1107)
ESP32-S3 CSI node firmware — two field-reported sensing bugs fixed and validated on real hardware (ESP32-S3 QFN56 rev v0.2, 8MB flash / 2MB PSRAM).
Fixes
- #1000 — no CSI on a bare/display-less DevKit. The SH8601 QSPI AMOLED is write-only, so panel init "succeeds" even with no panel attached; that false-positive left
display_is_active()true and starved CSI at MGMT-only frames. Now the readable FT3168 touch controller gates it: no touch readback → run headless → CSI upgrades to MGMT+DATA. (PR #1121) - #1107 — false MR60BHA2 detection → ENOMEM. UART probe now requires a validated MR60 header (8-byte SOF + checksum + type
0x0A__/0x0F09) instead of counting bare0x01bytes, so an empty UART no longer false-detects a sensor. (PR #1119)
Hardware validation (boot log, rev v0.2 silicon)
disp_hal: SH8601 panel init OK (368x448) # write-only panel "succeeds" on bare board
disp_hal: FT3168 not found (ret=ESP_FAIL) # touch readback fails — no real panel
disp_task: ... running headless so CSI captures (#1000)
csi_collector: CSI filter upgraded to MGMT+DATA (no display, RuView#893)
mmwave: No mmWave sensor detected (CSI-only mode) # no false detect on empty UART
CSI streamed cleanly (frames len 128→384/256), 600 callbacks / 22s, zero crash or watchdog.
Flashing
ESP32-S3, esptool offsets:
esptool --chip esp32s3 -p <PORT> -b 460800 write_flash \
0x0 bootloader.bin 0x8000 partition-table.bin \
0xf000 ota_data_initial.bin 0x20000 esp32-csi-node-s3-8mb.bin
4MB (no-display) boards: use esp32-csi-node-s3-4mb.bin @ 0x20000 and partition-table-4mb.bin @ 0x8000.
SHA-256
0a66190d…36822 esp32-csi-node-s3-8mb.bin
b818e358…f6e7c2 esp32-csi-node-s3-4mb.bin
dda279df…d8a216 bootloader.bin
67222c25…4d322b partition-table.bin
4c2cc4ff…0d81f0 partition-table-4mb.bin
7d2c7ac4…82c62f ota_data_initial.bin
App version 0.7.0 · ESP-IDF v5.4 · built from main @ 65e29ef. Binaries are the exact bytes flashed during hardware validation.
Release v1770
Automated release from CI pipeline
Changes:
feat(ADR-262 P1): wifi-densepose-rufield bridge — RuView sensing → signed RuField FieldEvents (fail-closed privacy map) (#1070)
- feat(rufield): ADR-262 P1 — wifi-densepose-rufield anti-corruption bridge
New v2 workspace member that converts RuView WiFi-CSI sensing output into
signed RuField FieldEvents. Path-deps the vendor/rufield submodule crates
(rufield-core/-provenance/-privacy/-fusion); single coupling point between
RuView and the standalone RuField MFS spec (ADR-262 §5.4).
- SensingSnapshot: owned primitives mirroring SensingUpdate + TrustedOutput
(no dependency on wifi-densepose-sensing-server). - snapshot_to_field_event(): builds a WifiCsi FieldTensor + Observation,
derives a real position from the signal-field peak (never fabricated),
real sha256 provenance + ed25519 signature (synthetic=false). - map_privacy() (§3.3 crux): maps by information content, NEVER byte value —
Derived (byte 1) → P4/P5, never P1; fail-closed demotion floor to P2.
P1 gates (tests/p1_gates.rs): round-trip serde, is_fusable verified receipt,
RuFieldFusion::ingest accept + infer runs, privacy-safety (Derived never P1),
full §3.3 table, fail-closed demotion, determinism, no-fabricated-position.
15 tests pass (5 unit + 9 integration + 1 doc), 0 failed.
Honesty: P1 plumbing (tested conversion + safe privacy mapping), NOT wired
into the live server (P3) and NOT an accuracy claim.
Co-Authored-By: claude-flow ruv@ruv.net
- docs(adr-262): mark P1 implemented + CI submodules:recursive + CHANGELOG/CLAUDE
- ADR-262 Status → "Proposed — P1 implemented"; add §0.1 Implementation
status (the bridge crate + the five P1 gates that pass; defers the
provenance-carrier reuse, P3 live wiring, and P4 multi-modality). - ci.yml: add
submodules: recursiveto the rust-tests checkout so the new
crate'svendor/rufieldpath-deps resolve in CI (they fail otherwise even
though the workspace build passes locally with the submodule present). - CHANGELOG [Unreleased]: P1 bridge entry (kept alongside the upstream
ADR-262 research entry). - CLAUDE.md: crate table row for
wifi-densepose-rufield.
Co-Authored-By: claude-flow ruv@ruv.net
Docker Image:
ghcr.io/ruvnet/RuView:f250149e94148d3f9b6a01a004c074178413cc2c
Release v1767
Automated release from CI pipeline
Changes:
docs(adr-262): RuField↔RuView integration design (Proposed) (#1069)
Researched integration ADR: thin wifi-densepose-rufield bridge crate
(rvcsi pattern), live SensingServerAdapter emitting signed FieldEvents,
vertical fusion composition (ruvsense within-WiFi → rufield cross-modal),
and ONE canonical privacy/provenance model (RuView effective_class →
RuField P0-P5 at egress; reuse cog-ha-matter SHA-256+Ed25519 receipt).
Key finding: RuView has 2 privacy enums + 3 witness mechanisms; the
Derived(byte=1)<Anonymous(byte=2)-but-carries-identity trap means the
bridge must map by information content, not byte value. Plumbing
architecture, not accuracy (real-CSI is unlabeled replay today).
Co-authored-by: ruv ruvnet@gmail.com
Docker Image:
ghcr.io/ruvnet/RuView:faca0530defc1599ae0be96308046740d466f509
Release v1765
Automated release from CI pipeline
Changes:
feat(rufield): CsiReplayAdapter — first real WiFi-CSI adapter (submodule bump) (#1068)
Bumps vendor/rufield to include CsiReplayAdapter: RuField now ingests real
captured WiFi CSI (.csi.jsonl) → FieldTensor → CSI-variance motion/presence
proxy → signed FieldEvents → fusion. Measured on 199 real frames: 182 fused
inferences (115 breathing, 67 person_present) from real signal. Replay-from-file,
unlabeled (proxy not validated accuracy) — live streaming + labeled accuracy
remain roadmap; mmWave/thermal stay synthetic.
Co-authored-by: ruv ruvnet@gmail.com
Docker Image:
ghcr.io/ruvnet/RuView:6f6c8676296481bd5928a5a3e26735ed28299f86
Release v1762
Automated release from CI pipeline
Changes:
feat(rufield): rufield-viewer dashboard — completes ADR-260 §27.9 (#1067)
Bumps the vendor/rufield submodule to include the new rufield-viewer crate
(Axum + vanilla JS read-only dashboard streaming the deterministic
SyntheticSim→fusion camera-free room-intelligence demo: live room state,
P0–P5 privacy-badged event log, fusion graph, signed-receipt viewer, behind
a permanent SYNTHETIC banner). All ADR-260 §27 criteria 1–10 now PASS.
Read-only demo viewer, not device management (real-adapter milestone later).
rufield repo now 7 crates / 72 tests.
Co-authored-by: ruv ruvnet@gmail.com
Docker Image:
ghcr.io/ruvnet/RuView:95a5ecc746f018e3222f72c470b5d84cfdb40ac3
Release v1759
Automated release from CI pipeline
Changes:
feat(ADR-261 M2): multi-bit + large-N ANN scaling study — measured, no crossover (refutes M1 prediction) (#1066)
- feat(ADR-261): multi-bit (b∈{1,2,4}) quantized HNSW traversal + scaling harness
Generalize the SymphonyQG-style quantized-traversal HNSW from 1-bit Hamming to a
b-bit-per-dimension code (b ∈ {1,2,4}), mirroring ADR-156 §10's multi-bit RaBitQ
scheme (rotate via FHT Pass-2, uniform mid-rise scalar quantizer over [-3,3],
ranked by per-dim L1). b=1 is byte-for-byte the original construction (codes in
{0,1} ⇒ L1 == Hamming), pinned by one_bit_build_bits_matches_legacy_build.
Bytes/node scales linearly: 128-d → 16/32/64 B for b=1/2/4.
- hnsw_quantized.rs: QuantizedHnswIndex::build_bits(...,bits,...), bits()/
bytes_per_node() accessors, code-L1 greedy+beam traversal. build(...) kept as
the b=1 backward-compatible entry point. +4 tests (multi-bit recall regression,
bits clamp, bytes/node, legacy parity). - ann_measure.rs: build_indices_bits / build_quant_bits / run_scaling_study +
best_float_op / best_quant_op; scaling_report (#[ignore], --release) and a
CI-safe scaling_study_small_is_consistent. - ann_bench.rs: 2-bit and 4-bit quant criterion benches over the shared graph.
ruvector lib 151 → 156 passed, 0 failed, 1 ignored (scaling_report).
Co-Authored-By: claude-flow ruv@ruv.net
- docs(adr-261): record M2 multi-bit scaling study — measured, no crossover (refutes M1 prediction)
Multi-bit (b∈{1,2,4}) quantized HNSW traversal + N∈{10k,100k,250k} scaling study,
measured on this box. No crossover at any (N,b): at 10k more bits help (ratio
0.19→0.48×, b≥2 reaches 0.90 recall) but quant stays slower than float HNSW at
equal recall; at 100k/250k quant recall collapses (b=4: 1.0→0.788→0.624, never
≥0.90) while float holds ≥0.92. The predicted large-N crossover moved the wrong
way. Published negative with the mechanism explained. ADR-261 §11.
Co-Authored-By: claude-flow ruv@ruv.net
Co-authored-by: ruv ruvnet@gmail.com
Docker Image:
ghcr.io/ruvnet/RuView:1f05456588ccccc03ef487b76959e2685425f02a
Release v1753
Automated release from CI pipeline
Changes:
feat(ADR-261): ruvector HNSW graph-ANN (25x measured vs linear) + honest SymphonyQG-direction refutation (#1063)
- feat(ruvector): real float HNSW + SymphonyQG-style quantized-traversal index (ADR-261)
Adds the graph-ANN index the ruvector retrieval path was missing (ADR-156
§5 #1 noted there was no HNSW baseline to measure SymphonyQG against).
- hnsw.rs: correct float HNSW (Malkov & Yashunin) — multi-layer NSW graph,
ef_construction/ef_search, Algorithm-4 neighbour selection, seeded-
deterministic level assignment (SplitMix64, reused from rotation.rs),
L2 + cosine, brute-force ground truth, full degenerate-case guards.
recall@10 correctness gate >=0.95 vs brute force (L2 + cosine). - hnsw_quantized.rs: SymphonyQG-style variant — same graph, traversal scored
by cheap 1-bit Hamming over the RaBitQ Pass-2 rotated sign code, final
exact-float rerank. - ann_measure.rs: shared deterministic planted-cluster fixture + recall/QPS
measurement (ann_bench_report is the ADR source of truth).
Fixes an index-out-of-bounds bug the recall gate caught: insert wired
bidirectional edges before pushing the node's own link row. +20 tests,
ruvector lib 131->151, 0 failed.
Co-Authored-By: claude-flow ruv@ruv.net
- bench(ruvector): criterion ann_bench for HNSW vs quantized vs linear (ADR-261)
Times the same shared ann_measure fixture/indices through criterion so the
bench and the report test can never measure different graphs.
Co-Authored-By: claude-flow ruv@ruv.net
- docs(adr-261): graph-ANN index ADR with MEASURED HNSW vs quantized verdict
ADR-261 (Accepted): float HNSW ~25x QPS over linear scan at recall >=0.99
(the baseline ADR-156 said was missing). Honest negative: the 1-bit
quantized traversal is too coarse to beat float HNSW at equal recall at
N=10k (best recall 0.738, no >=0.90 equal-recall point) — the SymphonyQG
3.5-17x is NOT reproduced by our 1-bit construction; expected crossover at
large N + a multi-bit code. Caveat: our HNSW + our quant, not SymphonyQG's
system — direction tested, not a 1:1 reproduction.
ADR-156 §5 #1 + §8 backlog: CLAIMED -> MEASURED-direction-tested.
CHANGELOG [Unreleased] entry.
Co-Authored-By: claude-flow ruv@ruv.net
Docker Image:
ghcr.io/ruvnet/RuView:f756a8af493a960a5217e39776685668bcdf19ad
Release v1749
Automated release from CI pipeline
Changes:
feat(adr-260): RuField MFS spec + vendor/rufield submodule (#1061)
ADR-260 (Accepted — v0.1 reference stack): RuField, the open specification
for camera-free multimodal field sensing — one FieldEvent/FieldTensor/
FusionGraph/PrivacyClass/ProvenanceReceipt model above WiFi CSI/CIR/BFLD,
UWB, BLE Channel Sounding, mmWave radar, ultrasound, subsonic, infrared,
and quantum sensors.
Published standalone as github.com/ruvnet/rufield and vendored here as the
vendor/rufield submodule (the vendor/rvcsi pattern — not a v2/ workspace
member). v0.1 reference stack: 6 crates, 60 tests/0 failed, clippy-clean.
All benchmark metrics SYNTHETIC (simulator ground truth, no hardware).
Co-authored-by: ruv ruvnet@gmail.com
Docker Image:
ghcr.io/ruvnet/RuView:261ce80a72c6ffd285f1e7c59b43b113110fd996