Commit graph

422 commits

Author SHA1 Message Date
rUv
c19a33ee1c
docs(adr): ADR-084 — RaBitQ similarity sensor for CSI/pose/memory (proposed) (#429)
Adopt RaBitQ-style binary sketches as a first-class cheap similarity
sensor at four points in the RuView pipeline: AETHER re-ID hot-cache
filter, per-room novelty / drift detection, mesh-exchange compression,
and privacy-preserving event logs. Implementation home is
ruvector-core::quantization::BinaryQuantized (already vendored, already
SIMD-accelerated NEON+POPCNT, 32x compression, 1-bit sign quantization
+ hamming distance), re-exported through a thin RuView-flavored API in
wifi-densepose-ruvector::sketch.

Pattern at every site: dense embedding -> RaBitQ sketch -> hamming
pre-filter to top-K -> full-precision refinement only on miss. Decision
boundary unchanged; sketch is a sensor that gates *which* comparisons
run, not *what* they decide.

Acceptance test (per source proposal):
- sketch compare cost reduction: 8x-30x vs full float
- top-K candidate coverage: >= 90% agreement with full-float pass
- end-to-end accuracy regression: < 1 percentage point

Site-by-site rollback if any criterion fails at a given site;
remaining sites continue. Five implementation passes, each
independently testable: ruvector module wrap, AETHER re-ID pre-filter,
cluster-Pi novelty sensor, mesh-exchange compression, privacy log.

Sensor MCU unchanged; sketches happen at the cluster Pi (ADR-083).
Validation requires acceptance numbers on >= 3 of 5 passes.

Open question (out-of-scope until pass-1 benchmark): whether RuView
embeddings need a Johnson-Lindenstrauss / RaBitQ-paper randomized
rotation before sign-quantization, or whether pure 1-bit sign
quantization (today's BinaryQuantized) is sufficient.
2026-04-25 23:08:05 -04:00
rUv
259939b7ec
docs(adr): ADR-083 — per-cluster Pi compute hop (proposed) (#428)
Adopt one Pi per cluster of 3-6 ESP32-S3 sensor nodes as the canonical
fleet-shape, rather than the full three-tier (dual-MCU + per-node Pi)
shape. Sensor nodes are unchanged from ADR-028 / ADR-081; the cluster
Pi gains the responsibilities the ESP32-S3 cannot carry — pose-grade
ML inference, QUIC backhaul to gateway/cloud, and a cluster-level OTA
+ secure-boot anchor.

The cluster-Pi shape is the L3-hybrid path identified in
docs/research/architecture/decision-tree.md §2 — the cheapest viable
upgrade. The full three-tier shape remains the long-term exploration
target, gated behind no_std CSI maturity (decision-tree L4) and
per-node ISR-jitter evidence (L2).

Status: Proposed. Acceptance gated on:
1. Cross-compile to aarch64 / armv7 with workspace tests passing
2. 3-sensor + 1-Pi field test demonstrating end-to-end CSI → fusion →
   cloud at <=100 ms cluster latency
3. Cluster-Pi SoC choice ADR (decision-tree L6) approved

References:
- docs/research/architecture/three-tier-rust-node.md (seed exploration)
- docs/research/architecture/decision-tree.md (L3 hybrid path)
- docs/research/sota/2026-Q2-rf-sensing-and-edge-rust.md (SOTA evidence)
2026-04-25 23:08:02 -04:00
rUv
81cc241b9e
chore(repo): move v1/ → archive/v1/ + add archive/README.md (#430)
The Rust port at v2/ has been the primary codebase since the rename
in #427. The Python implementation at v1/ is no longer the active
target; the only load-bearing path is the deterministic proof bundle
at v1/data/proof/ (per ADR-011 / ADR-028 witness verification).

Move the whole Python tree into archive/v1/ and document the policy
in archive/README.md: no new features, bug fixes only when they affect
a still-load-bearing path (currently just the proof), CI continues to
verify the proof on every push and PR.

Path references updated in 26 files via path-pattern sed (only
matches v1/<known-child> patterns, never bare v1 or API URLs like
/api/v1/). Two double-prefix typos (archive/archive/v1/) caught and
hand-fixed in verify-pipeline.yml and ADR-011.

Validated:
- Python proof verify.py imports cleanly at archive/v1/data/proof/
  (numpy/scipy still required; CI installs requirements-lock.txt
  from archive/v1/ now)
- cargo test --workspace --no-default-features → 1,539 passed,
  0 failed, 8 ignored (unaffected by Python tree relocation)
- ESP32-S3 on COM7 untouched (no firmware paths changed)

After-merge: contributors should re-run any local `python v1/...`
commands as `python archive/v1/...` (CLAUDE.md and CHANGELOG already
updated).
2026-04-25 23:07:52 -04:00
rUv
74233cfb23
fix(ci): use env scope for secrets in gating if: expressions (#431)
GitHub Actions does not allow `secrets.X` to appear directly in
step-level `if:` expressions — only `env.X` is valid in that context.
Both ci.yml and security-scan.yml had Slack-notify steps gated on
`secrets.SLACK_WEBHOOK_URL != ''`, which made the entire workflow
fail to parse. Result: every push to main produced a 0-second failure
with 0 jobs run, masquerading as a CI signal that wasn't actually
running CI.

Confirmed root cause via:
  gh api -X POST repos/.../actions/workflows/167079093/dispatches \
    -f ref=main
  → 422 Invalid Argument - failed to parse workflow:
    (Line: 315, Col: 11): Unrecognized named-value: 'secrets'

Fix: promote the secret to job-level `env:` so step-level `if:`
references `env.SLACK_WEBHOOK_URL`. The actual secret value still
flows through unchanged for the action's runtime use.

Same pattern applied to security-scan.yml line 406 (the existing
SECURITY_SLACK_WEBHOOK_URL gate).

After this lands, every push to main should produce real CI runs
that actually execute jobs and reflect repo health honestly. The
runs may still fail for *real* reasons (e.g., CI image dependencies,
test gaps), but they will fail visibly with logs instead of in 0s
with no jobs.
2026-04-25 23:06:27 -04:00
ruv
5bcb25b2b0 docs(adr): update bare wifi-densepose-rs refs to v2/ in ADR-012, ADR-052
Two leftover references missed by the sed pass in #427 (which only
matched the full `rust-port/wifi-densepose-rs` path). These are bare
references to the workspace directory name, which is now v2/.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-25 21:43:21 -04:00
rUv
f49c722764
chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427)
The Rust port lived two directories deep (rust-port/wifi-densepose-rs/)
without any sibling under rust-port/ that warranted the extra level.
Move the whole workspace up to v2/ to match v1/ (Python) at the same
depth and shorten every cd / build command across the repo.

git mv preserves history for all tracked files. 60 files updated for
path references (CI workflows, ADRs, docs, scripts, READMEs, internal
.claude-flow state). Two manual fixes for relative-cd paths in
CLAUDE.md and ADR-043 that became wrong after the depth change
(cd ../.. → cd ..).

Validated:
- cargo check --workspace --no-default-features → clean (after target/
  nuke; the gitignored target/ was carried by the OS rename and had
  hard-coded old paths in build scripts)
- cargo test --workspace --no-default-features → 1,539 passed, 0 failed,
  8 ignored (same totals as pre-rename)
- ESP32-S3 on COM7 → still streaming live CSI (cb #40300, RSSI -64 dBm)

After-merge follow-up: contributors should `rm -rf v2/target` once and
let cargo regenerate from the new path.
2026-04-25 21:28:13 -04:00
ruv
2a58fe478b docs(research): three-tier Rust node design + 2026-Q2 SOTA survey + decision tree
Three exploratory research documents under docs/research/:

- architecture/three-tier-rust-node.md (3,382 words) — exploration of a
  dual-ESP32-S3 + Pi Zero 2W node architecture with BQ24074 power-path,
  ESP-WIFI-MESH + LoRa fallback + QUIC backhaul, and an esp-hal/Embassy
  vs esp-idf-svc Rust toolchain split. Status: Exploratory — not adopted.

- sota/2026-Q2-rf-sensing-and-edge-rust.md (3,757 words) — twelve-section
  state-of-the-art survey covering WiFi CSI through-wall pose, IEEE 802.11bf
  (ratified 2025-09-26), edge ML on ESP32-class hardware, embedded Rust
  ecosystem maturity (esp-hal 1.x, esp-radio rename, embassy-executor
  ISR-safety on esp-idf-svc), LoRa for sensor mesh fallback, QUIC for IoT
  backhaul, solar power-path management beyond BQ24074, mesh routing
  alternatives, and Pi Zero 2W secure-boot reality.

- architecture/decision-tree.md (1,461 words) — Mermaid decision tree
  mapping each load-bearing decision in the three-tier proposal to its
  dependencies, evidence-for-yes/no, and prospective ADR slot.

No production code, firmware, or ADRs touched. Research-only.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-25 20:41:14 -04:00
Cocoon-Break
1c17c50930
fix: move test-only deps out of requirements.txt into requirements-dev.txt (#411)
* fix: remove test-only deps from requirements.txt, add requirements-dev.txt

Test dependencies (pytest, pytest-asyncio, pytest-mock, pytest-benchmark) should
not be installed in production. Move them to requirements-dev.txt.

Closes #410

Signed-off-by: Cocoon-Break <54054995+kuishou68@users.noreply.github.com>

* fix: add requirements-dev.txt with test and dev dependencies

Closes #410

Signed-off-by: Cocoon-Break <54054995+kuishou68@users.noreply.github.com>

---------

Signed-off-by: Cocoon-Break <54054995+kuishou68@users.noreply.github.com>
2026-04-25 20:11:34 -04:00
rUv
7f201bdf6f
fix(tracker): exclude Lost tracks from bridge output (#420, ADR-082) (#426)
`tracker_bridge::tracker_to_person_detections` documented itself as filtering
to `is_alive()` but never actually filtered — it forwarded every non-Terminated
track to the WebSocket stream. With 3 ESP32-S3 nodes × ~10 Hz CSI, transient
detections that fell outside the Mahalanobis gate created a steady stream of
new Tentative tracks that aged through Active and into Lost. Lost tracks are
kept in the tracker for `reid_window` (~3 s) so re-identification can match
them when a similar detection reappears, but they are NOT currently observed
and must not render as live skeletons. Up to ~90 ghost skeletons could
accumulate at any moment, hence the 22-24 phantoms users saw while
`estimated_persons` correctly reported 1.

Add `PoseTracker::confirmed_tracks()` that returns only `Tentative ∪ Active`
and rewire the bridge to use it. `Lost` tracks remain in the tracker for
re-ID; they just no longer ship to the UI. `active_tracks()` is left
unchanged for the AETHER re-ID consumers (ADR-024).

Regression test `test_lost_tracks_excluded_from_bridge_output` drives a
track to Active, lapses for `loss_misses + 1` ticks to push it to Lost,
and asserts `tracker_update` returns an empty Vec while the Lost track
is still present in `all_tracks()` (re-ID still works).

Validated:
- cargo test --workspace --no-default-features → 1,539 passed, 0 failed
- ESP32-S3 on COM7 still streaming live CSI (cb #32800)
2026-04-25 20:03:03 -04:00
rUv
58a63d6bdf
fix(workspace): unblock --no-default-features build on Windows (#366, #415) (#425)
mat, sensing-server, and train all depended on signal with default features
enabled, which pulled ndarray-linalg → openblas-src → vcpkg/system-BLAS through
the entire workspace. --no-default-features at the workspace root could not
opt out of BLAS, breaking cargo build / cargo test on Windows without vcpkg.

Set default-features = false on the signal dep in all three consumers so the
flag actually propagates. Also gate signal::ruvsense::field_model::tests
::test_estimate_occupancy_noise_only with #[cfg(feature = "eigenvalue")] —
the test unwraps a NotCalibrated stub when eigenvalue is compiled out.

Validated: cargo test --workspace --no-default-features → 1,538 passed,
0 failed, 8 ignored. ESP32-S3 on COM7 still streams live CSI.
2026-04-25 19:45:07 -04:00
rUv
79477c17a9
fix: restore WSL release build for sensing server (#389)
Some checks failed
Firmware CI / Build ESP32-S3 Firmware (4mb) (push) Has been cancelled
Firmware CI / Build ESP32-S3 Firmware (8mb) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / Build Espressif QEMU (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / Fuzz Testing (ADR-061 Layer 6) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / NVS Matrix Generation (push) Has been cancelled
Security Scanning / Static Application Security Testing (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Container Security Scan (push) Has been cancelled
Security Scanning / Infrastructure Security Scan (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / License Compliance Scan (push) Has been cancelled
Security Scanning / Security Policy Compliance (push) Has been cancelled
Continuous Deployment / Deploy to Staging (push) Has been cancelled
Continuous Deployment / Deploy to Production (push) Has been cancelled
Continuous Deployment / Rollback Deployment (push) Has been cancelled
Continuous Deployment / Post-deployment Monitoring (push) Has been cancelled
Continuous Deployment / Notify Deployment Status (push) Has been cancelled
Continuous Integration / Performance Tests (push) Has been cancelled
Continuous Integration / Docker Build & Test (push) Has been cancelled
Continuous Integration / API Documentation (push) Has been cancelled
Continuous Integration / Notify (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (boundary-max) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (boundary-min) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (default) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (edge-tier0) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (edge-tier1) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (full-adr060) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (tdm-3node) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / Swarm Test (ADR-062) (push) Has been cancelled
Security Scanning / Security Report (push) Has been cancelled
fix: restore successful WSL release build for rust sensing server
2026-04-20 14:29:15 -04:00
rUv
648ff525a2
docs: troubleshooting guide for ESP32 CSI deployments (#377)
docs: troubleshooting guide for ESP32 CSI deployments
2026-04-20 14:29:11 -04:00
rUv
0943a32248
feat: Real-time dense point cloud from camera + WiFi CSI (#405)
* Add wifi-densepose-pointcloud: real-time dense point cloud from camera + WiFi CSI

New crate with 5 modules:
- depth: monocular depth estimation + 3D backprojection (ONNX-ready, synthetic fallback)
- pointcloud: Point3D/ColorPoint types, PLY export, Gaussian splat conversion
- fusion: WiFi occupancy volume → point cloud + multi-modal voxel fusion
- stream: HTTP + Three.js viewer server (Axum, port 9880)
- main: CLI with serve/capture/demo subcommands

Demo output: 271 WiFi points + 19,200 depth points → 4,886 fused → 1,718 Gaussian splats.
Serves interactive 3D viewer at http://localhost:9880 with Three.js orbit controls.

ADR-SYS-0021 documents the architecture for camera + WiFi CSI dense point cloud pipeline.

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

* Optimize pointcloud: larger splat voxels, smaller responses, faster fusion

- Gaussian splat voxel size: 0.10 → 0.15 (42% fewer splats: 1718 → 994)
- Splat response: 399 KB → 225 KB (44% smaller)
- Pipeline: 22.2ms mean (100 runs, σ=0.3ms)
- Cloud API: 1.11ms avg, 905 req/s
- Splats API: 1.39ms avg, 719 req/s
- Binary: 1.0 MB arm64 (Mac Mini), tested

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

* Complete implementation: camera capture, WiFi CSI receiver, training pipeline

Three new modules added to wifi-densepose-pointcloud:

1. camera.rs — Cross-platform camera capture
   - macOS: AVFoundation via Swift, ffmpeg avfoundation
   - Linux: V4L2, ffmpeg v4l2
   - Camera detection, listing, frame capture to RGB
   - Graceful fallback to synthetic data when no camera

2. csi.rs — WiFi CSI receiver for ESP32 nodes
   - UDP listener for CSI JSON frames from ESP32
   - Per-link attenuation tracking with EMA smoothing
   - Simplified RF tomography (backprojection to occupancy grid)
   - Test frame sender for development without hardware
   - Ready for real ESP32 CSI data from ruvzen

3. training.rs — Calibration and training pipeline
   - Depth calibration: grid search over scale/offset/gamma
   - Occupancy training: threshold optimization for presence detection
   - Ground truth reference points for depth RMSE measurement
   - Preference pair export (JSONL) for DPO training on ruOS brain
   - Brain integration: submit observations as memories
   - Persistent calibration files (JSON)

New CLI commands:
   ruview-pointcloud cameras         # list available cameras
   ruview-pointcloud train           # run calibration + training
   ruview-pointcloud csi-test        # send test CSI frames
   ruview-pointcloud serve --csi     # serve with live CSI input

All tested: demo, training (10 samples, 4 reference points, 3 pairs),
CSI receiver (50 test frames), server API.

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

* Fix viewer: replace WebSocket with fetch polling

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

* Wire live camera into server — real-time updating point cloud

- Server captures from /dev/video0 at 2fps via ffmpeg
- Background tokio task refreshes cloud + splats every 500ms
- Viewer polls /api/splats every 500ms, only updates on new frame
- Shows 🟢 LIVE / 🔴 DEMO indicator
- Camera position set for first-person view (looking forward into scene)
- Downsample 4x for performance (19,200 points per frame)
- Graceful fallback to demo data if camera capture fails

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

* Add MiDaS GPU depth, serial CSI reader, full sensor fusion

- MiDaS depth server: PyTorch on CUDA, real monocular depth estimation
- Rust server calls MiDaS via HTTP for neural depth (falls back to luminance)
- Serial CSI reader for ESP32 with motion detection + presence estimation
- CSI disabled by default (RUVIEW_CSI=1 to enable) — serial reader needs baud config
- Edge-enhanced depth for better object boundaries
- All sensors wired: camera, ESP32 CSI, mmWave (CSI gated until serial fixed)

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

* Complete 7-component sensor fusion pipeline (all working)

1. ADR-018 binary parser — decodes ESP32 CSI UDP frames, extracts I/Q subcarriers
2. WiFlow pose — 17 COCO keypoints from CSI (186K param model loaded)
3. Camera depth — MiDaS on CUDA + luminance fallback
4. Sensor fusion — camera depth + CSI occupancy grid + skeleton overlay
5. RF tomography — ISTA-inspired backprojection from per-node RSSI
6. Vital signs — breathing rate from CSI phase analysis
7. Motion-adaptive — skip expensive depth when CSI shows no motion

Live results: 510 CSI frames/session, 17 keypoints, 26% motion, 40 BPM breathing.
Both ESP32 nodes provisioned to send CSI to 192.168.1.123:3333.
Magic number fix: supports both 0xC5110001 (v1) and 0xC5110006 (v6) frames.

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

* Add brain bridge — sparse spatial observation sync every 60s

Stores room scan summaries, motion events, and vital signs
in the ruOS brain as memories. Only syncs every 120 frames
(~60 seconds) to keep the brain sparse and optimized.

Categories: spatial-observation, spatial-motion, spatial-vitals.

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

* Update README + user guide with dense point cloud features

Added pointcloud section to README (quick start, CLI, performance).
Added comprehensive user guide section: setup, sensors, commands,
pipeline components, API endpoints, training, output formats,
deep room scan, ESP32 provisioning.

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

* Add ruview-geo: geospatial satellite integration (11 modules, 8/8 tests)

New crate with free satellite imagery, terrain, OSM, weather, and brain integration.

Modules: types, coord, locate, cache, tiles, terrain, osm, register, fuse, brain, temporal
Tests: 8 passed (haversine, ENU roundtrip, tiles, HGT parse, registration)
Validation: real data — 43.49N 79.71W, 4 Sentinel-2 tiles, 2°C weather, brain stored

Data sources (all free, no API keys):
- EOX Sentinel-2 cloudless (10m satellite tiles)
- SRTM GL1 (30m elevation)
- Overpass API (OSM buildings/roads)
- ip-api.com (geolocation)
- Open Meteo (weather)

ADR-044 documents architecture decisions.
README.md in crate subdirectory.

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

* Update ADR-044: add Common Crawl WET, NASA FIRMS, OpenAQ, Overture Maps sources

Extended geospatial data sources leveraging ruvector's existing web_ingest
and Common Crawl support for hyperlocal context.

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

* Fix OSM/SRTM queries, add change detection + night mode

- OSM: use inclusive building filter with relation query and 25s timeout
- SRTM: switch to NASA public mirror with viewfinderpanoramas fallback
- Add detect_tile_changes() for pixel-diff satellite change detection
- Add is_night() solar-declination model for CSI-only night mode
- 6 new unit tests (night mode + tile change detection)

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

* Enhance viewer: skeleton overlay, weather, buildings, better camera

Add COCO skeleton rendering with yellow keypoint spheres and white bone
lines, info panel sections for weather/buildings/CSI rate/confidence,
overhead camera at (0,2,-4), and denser point size with sizeAttenuation.

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

* Add CSI fingerprint DB + night mode detection

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

* Fix ADR-044 numbering conflict, update geo README

Renumbered provisioning tool ADR from 044 to 050 to avoid conflict
with geospatial satellite integration ADR-044.

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

* Clean up warnings: suppress dead_code for conditional pipeline modules

Removes unused imports/variables via cargo fix and adds #[allow(dead_code)]
for modules used conditionally at runtime (CSI, depth, fusion, serial).
Pointcloud: 28 → 0 warnings. Geo: 2 → 0 warnings. 8/8 tests pass.

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

* Fix PR #405 blockers: async runtime panic, crate rename, path traversal, brain URL config

- brain_bridge.rs: replace `Handle::current().block_on(...)` inside async fn
  with `.await` (was a guaranteed "runtime within runtime" panic). Brain URL
  now read from RUVIEW_BRAIN_URL env var (default http://127.0.0.1:9876),
  logged once via OnceLock.
- wifi-densepose-geo: rename Cargo package from `ruview-geo` to
  `wifi-densepose-geo` to match directory and workspace conventions. Update
  all use sites (tests/examples/README). Same env-var pattern for brain URL
  in brain.rs + temporal.rs.
- training.rs: add sanitize_data_path() rejecting `..` components and
  safe_join() that canonicalises + enforces base-dir containment on every
  write (calibration.json, samples.json, preference_pairs.jsonl,
  occupancy_calibration.json). Defence-in-depth check also in main.rs
  before TrainingSession::new.
- osm.rs: clamp Overpass radius to MAX_RADIUS_M=5000m; return Err beyond
  that. Add parse_overpass_json() that rejects malformed payloads
  (missing top-level `elements` array).

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

* csi_pipeline: rename WiFlow stub to heuristic_pose_from_amplitude, decouple UDP

Blocker 3 (PR #405 review): The "WiFlow inference" path was a stub that
built a model from empty weight vectors and synthesised keypoints from
amplitude energy. Presenting this as "WiFlow inference" was misleading.

- Rename WiFlowModel to PoseModelMetadata (empty tag struct; we only care
  if the on-disk file exists)
- Rename load_wiflow_model() -> detect_pose_model_metadata() and log
  "amplitude-energy heuristic enabled/disabled" (no "WiFlow" claim)
- Rename estimate_pose() -> heuristic_pose_from_amplitude() with
  prominent `STUB:` doc comment saying this is NOT a trained model

Blocker 4 (PR #405 review): The UDP receiver held the shared Arc<Mutex>
across a synchronous process_frame() call, starving HTTP handlers.

- Introduce a std::sync::mpsc channel between the UDP thread (which only
  parses + pushes) and a dedicated processor thread (which locks only
  briefly around a single process_frame). HTTP snapshots via
  get_pipeline_output no longer contend with the socket read loop.

Also:
- Move ADR-018 parser to parser.rs (see next commit); csi_pipeline re-exports
- send_test_frames now uses parser::build_test_frame for synthetic frames
- Log a one-line node stats summary every 500 frames (reads every public
  CsiFrame field on the runtime path)

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

* Extract ADR-018 parser into parser.rs + wire Fingerprint CLI

File-split (strong concern #9 in PR #405 review): csi_pipeline.rs was 602
LOC; extract the pure-function ADR-018 parser + synthetic frame builder
into src/parser.rs. Inline unit tests in parser.rs cover:

- 0xC5110001 (raw CSI, v1) roundtrip
- 0xC5110006 (feature state, v6) roundtrip
- wrong magic is rejected
- truncated header is rejected
- truncated payload is rejected

main.rs: expose `fingerprint NAME [--seconds N]` subcommand wiring
record_fingerprint() (this was the only caller needed to make the public
API non-dead on the runtime path). Also:

- Replace `--host/--port` + external `--csi` with a single `--bind`
  defaulting to loopback (`127.0.0.1:9880`) — addresses strong concern
  #7 about exposing camera/CSI/vitals by default.
- Update synthetic `csi-test` to target UDP 3333 (matching the ADR-018
  listener) and use the shared parser::build_test_frame.
- Defence-in-depth: call training::sanitize_data_path on the expanded
  --data-dir before TrainingSession::new does the same.

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

* stream: extract viewer HTML to viewer.html, default bind to loopback

Strong concern #7 (PR #405): default HTTP bind leaked camera/CSI/vitals
to the LAN. The `serve` fn now takes a single `bind` arg and prints a
loud WARNING when bound outside loopback.

Strong concern #10 (PR #405): embedded HTML+JS was ~220 LOC of the 418
LOC stream.rs. Moved the markup verbatim into viewer.html and inlined
via `include_str!("viewer.html")`. Also:

- Drop the #![allow(dead_code)] crate-level silencing (reviewer point
  #11). Remove the now-unused AppState.csi_pipeline field.
- capture_camera_cloud_with_luminance returns the mean luminance of the
  captured frame; the background loop feeds that to
  CsiPipelineState::set_light_level so the night-mode flag actually
  toggles at runtime (previously it could only be set from tests).

Net effect on file size: stream.rs 418 → 232 LOC.

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

* Dead-code cleanup + tests for fusion/depth/OSM/training/fingerprinting

Reviewer point #11 (PR #405): remove the `#![allow(dead_code)]`
silencing added in 8eb808d and fix the underlying issues.

- Delete csi.rs: duplicate of csi_pipeline.rs with incompatible wire
  format (JSON vs ADR-018 binary). csi_pipeline is the real path.
- Delete serial_csi.rs: never referenced by any module.
- Drop Frame.timestamp_ms (unread), AppState.csi_pipeline (unread),
  brain_bridge::brain_available (caller-less), fusion::fetch_wifi_occupancy
  (caller-less) — these had no runtime users.
- Drop crate-level #![allow(dead_code)] from camera.rs, depth.rs,
  fusion.rs, pointcloud.rs.

Tests (target: 8-12, actual: 15 unit + 9 geo unit + 8 geo integration
= 32 total, all pass):

- parser.rs: 5 tests (v1/v6 magic roundtrip, wrong magic, truncated
  header, truncated payload).
- fusion.rs: 2 tests (non-overlapping merge, voxel dedup).
- depth.rs: 2 tests (2x2 backproject → 4 points at z=1, NaN rejected).
- training.rs: 4 tests (rejects `..`, accepts relative child, refuses
  TrainingSession::new("../etc/passwd"), accepts a clean tmpdir).
- csi_pipeline.rs: 2 tests (set_light_level toggles is_dark,
  record_fingerprint stores and self-identifies).
- osm.rs: 3 tests (parse_overpass_json minimal fixture, rejects
  malformed payload, fetch_buildings rejects > MAX_RADIUS_M).

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

* Update README + user-guide for PR #405 review-fix additions

- serve now uses --bind 127.0.0.1:9880 (loopback default) instead of --port
- Add fingerprint subcommand to CLI tables
- Document RUVIEW_BRAIN_URL env var + --brain flag
- Flag pose path as amplitude-energy heuristic stub (not trained WiFlow)
- Security note on exposing server outside loopback
- Add wifi-densepose-pointcloud + wifi-densepose-geo rows to crate table

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-20 12:48:54 -04:00
ruv
ae40e2b33e Release v0.6.2-esp32: ADR-081 kernel + Timer Svc fix, 4MB CI variant
version.txt → 0.6.2.

firmware-ci.yml: matrix-build both 8MB (sdkconfig.defaults) and 4MB
(sdkconfig.defaults.4mb) variants, uploading variant-named artifacts
(esp32-csi-node.bin / esp32-csi-node-4mb.bin, partition-table.bin /
partition-table-4mb.bin). Unblocks 6-binary releases from CI alone,
no local ESP-IDF required.

CHANGELOG: promote [Unreleased] ADR-081 work into [v0.6.2-esp32],
plus Fixed entries for Timer Svc stack overflow and the
fast_loop_cb → emit_feature_state implicit-decl compile error.

Validation: 30 s run on ESP32-S3 (MAC 3c:0f:02:e9:b5:f8), 149
rv_feature_state emissions, no stack overflow, HEALTH mesh packet sent.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-20 10:59:05 -04:00
ruv
a426ae386d Fix ADR-081 Timer Svc stack overflow on ESP32-S3
emit_feature_state() runs inside the FreeRTOS Timer Svc task via the
fast loop callback; it memsets an rv_feature_state_t, queries vitals/
radio, and sends via stream_sender (lwIP sendto). Default Timer Svc
stack is 2 KiB, which overflows and panics ~1 s after boot:

  ***ERROR*** A stack overflow in task Tmr Svc has been detected.

Bump CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH to 8 KiB across the three
sdkconfig defaults files (default, template, 4mb). Matches the main
task stack size already in use.

Found during on-device validation on ESP32-S3 (MAC 3c:0f:02:e9:b5:f8)
after flashing the post-merge v0.6.1 build — firmware boots, connects
WiFi, emits one medium tick, then crashes on the fast tick that calls
emit_feature_state().

Follow-up: consider moving emit_feature_state + network I/O out of the
timer daemon into a dedicated worker task (open issue).

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-20 10:48:21 -04:00
rUv
5a7f431b0e
ADR-081: Implement 5-layer adaptive CSI mesh firmware kernel (#404)
* ADR-081: adaptive CSI mesh firmware kernel + scaffolding

Introduces a 5-layer firmware kernel that reframes the existing ESP32
modules as components of a chipset-agnostic architecture and authorizes
adaptive control + a compact feature-state stream as the default upstream.

Layers:
  L1 Radio Abstraction Layer  — rv_radio_ops_t vtable + ESP32 binding
  L2 Adaptive Controller      — fast/medium/slow loops (200ms/1s/30s)
  L3 Mesh Sensing Plane       — anchor/observer/relay/coordinator (spec)
  L4 On-device Feature Extr.  — rv_feature_state_t (magic 0xC5110006)
  L5 Rust handoff             — feature_state default; debug raw gated

Files:
  docs/adr/ADR-081-adaptive-csi-mesh-firmware-kernel.md  (new)
  firmware/esp32-csi-node/main/rv_radio_ops.h            (new)
  firmware/esp32-csi-node/main/rv_radio_ops_esp32.c      (new)
  firmware/esp32-csi-node/main/rv_feature_state.{h,c}    (new)
  firmware/esp32-csi-node/main/adaptive_controller.{h,c} (new)
  firmware/esp32-csi-node/main/main.c                    (wire L1+L2)
  firmware/esp32-csi-node/main/CMakeLists.txt            (add 4 sources)
  firmware/esp32-csi-node/main/Kconfig.projbuild         (controller knobs)
  CHANGELOG.md                                           (Unreleased)

Default policy is conservative: enable_channel_switch and
enable_role_change are off, so behavior matches today's firmware
unless an operator opts in via menuconfig. The pure
adaptive_controller_decide() is exposed for offline unit tests.

Reuses (does not rewrite): csi_collector, edge_processing (ADR-039),
swarm_bridge (ADR-066), secure_tdm (ADR-032), wasm_runtime (ADR-040).

* ADR-081: implement Layers 1/2/4 end-to-end + host tests + QEMU hooks

Turns the ADR-081 scaffolding into a working adaptive CSI mesh kernel:
Layer 1 radio abstraction has an ESP32 binding and a mock binding; Layer 2
adaptive controller runs on FreeRTOS timers; Layer 4 feature-state packet
is emitted at 5 Hz by default, replacing raw ADR-018 CSI as the default
upstream.

New files:
  firmware/esp32-csi-node/main/adaptive_controller_decide.c  (pure policy)
  firmware/esp32-csi-node/main/rv_radio_ops_mock.c           (QEMU binding)
  firmware/esp32-csi-node/tests/host/Makefile                (host tests)
  firmware/esp32-csi-node/tests/host/test_adaptive_controller.c
  firmware/esp32-csi-node/tests/host/test_rv_feature_state.c
  firmware/esp32-csi-node/tests/host/esp_err.h               (shim)
  firmware/esp32-csi-node/tests/host/.gitignore

Modified:
  adaptive_controller.c         — includes pure decide.c; emit_feature_state()
                                  wired into fast loop (200 ms = 5 Hz)
  rv_radio_ops_esp32.c          — get_health() fills pkt_yield + send_fail
  csi_collector.{c,h}           — pkt_yield/send_fail accessors (ADR-081 L1)
  rv_feature_state.h            — packed size corrected to 60 bytes
                                  (was incorrectly 80 in initial commit)
  main.c                        — mock binding registered under mock CSI
  CMakeLists.txt                — rv_radio_ops_mock.c under CSI_MOCK_ENABLED
  scripts/validate_qemu_output.py — 3 new ADR-081 checks (17/18/19)
  docs/adr/ADR-081-*.md         — status → Accepted (partial);
                                  implementation-status matrix; measured
                                  benchmarks (decide 3.2 ns, CRC32 614 ns);
                                  bandwidth 300 B/s @ 5 Hz (99.7% vs raw);
                                  verification section
  CHANGELOG.md                  — artifact-level entries

Tests (host, gcc -O2 -std=c11):
  test_adaptive_controller:  18/18 pass, decide() = 3.2 ns/call
  test_rv_feature_state:     15/15 pass, CRC32(56 B) = 614 ns/pkt, 87 MB/s
                             sizeof(rv_feature_state_t) == 60 asserted
                             IEEE CRC32 known vectors verified

Deferred (tracked in ADR-081 roadmap Phase 3/4):
  Layer 3 mesh-plane message types, role-assignment FSM, Rust-side mirror
  trait in crates/wifi-densepose-hardware/src/radio_ops.rs.

* ADR-081: Layer 3 mesh plane + Rust mirror trait — all 5 layers landed

Fully implements the remaining deferred pieces of the adaptive CSI mesh
firmware kernel. All 5 layers (Radio Abstraction, Adaptive Controller,
Mesh Sensing Plane, On-device Feature Extraction, Rust handoff) are
now implemented and host-tested end-to-end.

Layer 3 — Mesh Sensing Plane (firmware/esp32-csi-node/main/rv_mesh.{h,c}):
  * 4 node roles: Unassigned / Anchor / Observer / FusionRelay / Coordinator
  * 7 message types: TIME_SYNC, ROLE_ASSIGN, CHANNEL_PLAN,
    CALIBRATION_START, FEATURE_DELTA, HEALTH, ANOMALY_ALERT
  * 3 auth classes: None / HMAC-SHA256-session / Ed25519-batch
  * Payload types: rv_node_status_t (28 B), rv_anomaly_alert_t (28 B),
    rv_time_sync_t (16 B), rv_role_assign_t (16 B),
    rv_channel_plan_t (24 B), rv_calibration_start_t (20 B)
  * 16-byte envelope + payload + IEEE CRC32 trailer
  * Pure rv_mesh_encode()/rv_mesh_decode() plus typed convenience encoders
  * rv_mesh_send_health() + rv_mesh_send_anomaly() helpers

Controller wiring (adaptive_controller.c):
  * Slow loop (30 s default) now emits HEALTH
  * apply_decision() emits ANOMALY_ALERT on transitions to ALERT /
    DEGRADED
  * Role + mesh epoch tracked in module state; epoch bumps on role
    change

Layer 5 — Rust mirror (crates/wifi-densepose-hardware/src/radio_ops.rs):
  * RadioOps trait mirrors rv_radio_ops_t vtable
  * MockRadio backend for offline tests
  * MeshHeader / NodeStatus / AnomalyAlert types mirror rv_mesh.h
  * Byte-identical IEEE CRC32 (poly 0xEDB88320) verified against
    firmware test vectors (0xCBF43926 for "123456789")
  * decode_mesh / decode_node_status / decode_anomaly_alert / encode_health
  * 8 unit tests, including mesh_constants_match_firmware which asserts
    MESH_MAGIC/VERSION/HEADER_SIZE/MAX_PAYLOAD match rv_mesh.h
    byte-for-byte
  * Exported from lib.rs
  * signal/ruvector/train/mat crates untouched — satisfies ADR-081
    portability acceptance test

Tests (all passing):
  test_adaptive_controller:   18/18   (C, decide() 3.2 ns/call)
  test_rv_feature_state:      15/15   (C, CRC32 87 MB/s)
  test_rv_mesh:               27/27   (C, roundtrip 1.0 µs)
  radio_ops::tests (Rust):     8/8
  --- total:                 68/68 assertions green ---

Docs:
  * ADR-081 status flipped to Accepted
  * Implementation-status matrix updated; L3 + Rust mirror both
    marked Implemented
  * Benchmarks table extended with rv_mesh encode+decode roundtrip
  * Verification section updated with cargo test invocation
  * CHANGELOG: two new entries for L3 mesh plane + Rust mirror

Remaining follow-ups (Phase 3.5 polish, not blocking):
  * Mesh RX path (UDP listener + dispatch) on the firmware
  * Ed25519 signing for CHANNEL_PLAN / CALIBRATION_START
  * Hardware validation on COM7

* Add test_rv_mesh to host-test .gitignore

Fixes an untracked-file warning from the repo stop-hook: the compiled
binary was built by make but the .gitignore update was missed in
8dfb031. No source changes.

* Fix implicit decl of emit_feature_state in adaptive_controller

fast_loop_cb calls emit_feature_state() at line 224, but the static
definition is at line 256. GCC treats the implicit declaration as
non-static, then the real static definition conflicts, and
-Werror=all promotes both to hard build errors.

Add a forward declaration above the first use. Unblocks ESP32-S3
firmware build and all QEMU matrix jobs.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-20 10:38:23 -04:00
rUv
b816292ead
Merge pull request #402 from voidborne-d/fix/docker-entrypoint-and-model-path
fix: Docker entrypoint arg handling + configurable model directory
2026-04-20 10:25:27 -04:00
voidborne-d
e38c0f4dcc fix: Docker entrypoint arg handling + configurable model directory
Fixes #384: docker run with --source/--tick-ms flags now works correctly.
Fixes #399: model files in mounted volumes are now discoverable via MODELS_DIR env var.

Root cause (issue #384):
The Dockerfile used ENTRYPOINT ["/bin/sh", "-c"] with a shell-form CMD.
When users passed flags like `--source wifi --tick-ms 500` as docker run
arguments, Docker replaced CMD entirely, resulting in
`/bin/sh -c "--source wifi --tick-ms 500"` which executes `--source` as
a shell command → `--source: not found`.

Root cause (issue #399):
Model directory was hardcoded to the relative path `data/models`. When Docker
users mounted models to `/app/models/`, the scan looked in the wrong place.

Changes:

1. docker/docker-entrypoint.sh (new):
   - Proper entrypoint script that handles both env-var-based defaults and
     user-passed CLI flags
   - No arguments → starts server with CSI_SOURCE env var as --source
   - Flag arguments (start with -) → prepends /app/sensing-server + defaults,
     appends user flags (clap last-wins allows overrides)
   - Non-flag first arg → exec passthrough (e.g., /bin/sh for debugging)
   - Sets --bind-addr 0.0.0.0 (was 127.0.0.1 which blocks container access)

2. docker/Dockerfile.rust:
   - Switch from ENTRYPOINT ["/bin/sh", "-c"] to exec-form entrypoint
   - Add MODELS_DIR env var (default: data/models)
   - COPY the entrypoint script into the image

3. docker/docker-compose.yml:
   - Remove shell-form command (entrypoint handles defaults)
   - Add MODELS_DIR env var

4. model_manager.rs + main.rs:
   - Replace hardcoded `data/models` path with `effective_models_dir()`
     / `models_dir()` that reads MODELS_DIR env var at runtime
   - Docker users can now: docker run -v /host/models:/app/models -e MODELS_DIR=/app/models

5. tests/test_docker_entrypoint.sh (new, 17 tests):
   - Default CSI_SOURCE substitution (6 assertions)
   - Custom CSI_SOURCE propagation
   - User-passed flag arguments (--source, --tick-ms, --model)
   - Unset CSI_SOURCE defaults to auto
   - Explicit command passthrough
   - MODELS_DIR env var propagation
2026-04-18 21:55:01 +00:00
ruv
8914538bfe chore: bump firmware version to 0.6.1
Some checks failed
Continuous Integration / Tests-2 (push) Has been cancelled
Firmware CI / Build ESP32-S3 Firmware (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / Build Espressif QEMU (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / Fuzz Testing (ADR-061 Layer 6) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / NVS Matrix Generation (push) Has been cancelled
Security Scanning / Static Application Security Testing (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Container Security Scan (push) Has been cancelled
Security Scanning / Infrastructure Security Scan (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / License Compliance Scan (push) Has been cancelled
Security Scanning / Security Policy Compliance (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (default) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (edge-tier0) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (edge-tier1) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (full-adr060) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (tdm-3node) (push) Has been cancelled
Continuous Deployment / Deploy to Staging (push) Has been cancelled
Continuous Deployment / Deploy to Production (push) Has been cancelled
Continuous Deployment / Rollback Deployment (push) Has been cancelled
Continuous Deployment / Post-deployment Monitoring (push) Has been cancelled
Continuous Deployment / Notify Deployment Status (push) Has been cancelled
Continuous Integration / Performance Tests (push) Has been cancelled
Continuous Integration / Docker Build & Test (push) Has been cancelled
Continuous Integration / API Documentation (push) Has been cancelled
Continuous Integration / Notify (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (boundary-max) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (boundary-min) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / Swarm Test (ADR-062) (push) Has been cancelled
Security Scanning / Security Report (push) Has been cancelled
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-16 10:38:02 -04:00
rUv
8a9e890956
Merge pull request #393 from ruvnet/fix/esp32-node-id-clobber
fix(firmware): defensive node_id capture prevents runtime clobber (#390)
2026-04-16 10:22:59 -04:00
bilibili12433014
1871ef3c2d docs(user-guide): add Linux desktop build prerequisites for Rust builds
- add Debian/Ubuntu desktop build prerequisites to the Rust source build guide
- document required GTK/WebKit development packages for Linux release builds
- add a matching troubleshooting entry for native desktop build dependencies
- keep installation and troubleshooting guidance aligned and context-consistent
2026-04-16 16:58:12 +08:00
ruv
425f0e6aac fix(firmware): defensive node_id capture prevents runtime clobber (#390)
Users on multi-node ESP32 deployments have been reporting for months
that their provisioned `node_id` reverts to the Kconfig default of `1`
in UDP frames and the `csi_collector` init log, despite boot showing:

    nvs_config: NVS override: node_id=4
    main: ESP32-S3 CSI Node (ADR-018) - Node ID: 4
    csi_collector: CSI collection initialized (node_id=1, channel=11)

See #232, #375, #385, #386, #390. The root memory-corruption path for
the `g_nvs_config.node_id` byte has not been definitively isolated
(does not reproduce on my attached ESP32-S3 running current source
and the v0.6.0 release binary), but the UDP frame header can be made
tamper-proof regardless:

1. `csi_collector_init()` now captures `g_nvs_config.node_id` into a
   module-local `static uint8_t s_node_id` at init time.
2. `csi_serialize_frame()` reads `buf[4]` from `s_node_id`, not from
   the global - so any later corruption of `g_nvs_config` cannot
   affect outgoing CSI frames.
3. All other consumers (`edge_processing.c` x3, `wasm_runtime.c`,
   `display_ui.c`, `main.c swarm_bridge_init`) now go through a new
   `csi_collector_get_node_id()` accessor instead of reading the
   global directly.
4. A canary at end-of-init logs `WARN` if `g_nvs_config.node_id`
   already diverges from the captured value - this will pinpoint
   the corruption path if it happens on a user's device.

Hardware validation on attached ESP32-S3 (COM8):
  - NVS loads node_id=2
  - Boot log: `main: ... Node ID: 2`
  - NEW log: `csi_collector: Captured node_id=2 at init (defensive
    copy for #232/#375/#385/#390)`
  - Init log: `csi_collector: CSI collection initialized (node_id=2)`
  - UDP frame byte[4] = 2 (verified via socket sniffer, 15/15 packets)

This is defense in depth - it shields the UDP frame from whatever
upstream bug is clobbering the struct. When a user hits the original
bug, the canary WARN will help isolate the root cause.

Refs #232 #375 #385 #386 #390

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-15 13:47:34 -04:00
rUv
6e015c4626
fix: provision.py esptool v5 + refuse partial NVS flashes (#391) (#392)
Some checks are pending
Continuous Deployment / Notify Deployment Status (push) Blocked by required conditions
Continuous Integration / Rust Workspace Tests (push) Waiting to run
Continuous Integration / Code Quality & Security (push) Waiting to run
Continuous Integration / Tests (push) Waiting to run
Continuous Integration / Tests-1 (push) Waiting to run
Continuous Integration / Tests-2 (push) Waiting to run
Continuous Integration / Performance Tests (push) Blocked by required conditions
Continuous Integration / Docker Build & Test (push) Blocked by required conditions
Continuous Integration / API Documentation (push) Blocked by required conditions
Continuous Integration / Notify (push) Blocked by required conditions
Firmware CI / Build ESP32-S3 Firmware (push) Waiting to run
Firmware QEMU Tests (ADR-061) / Build Espressif QEMU (push) Waiting to run
Firmware QEMU Tests (ADR-061) / QEMU Test (boundary-max) (push) Blocked by required conditions
Firmware QEMU Tests (ADR-061) / QEMU Test (boundary-min) (push) Blocked by required conditions
Firmware QEMU Tests (ADR-061) / QEMU Test (default) (push) Blocked by required conditions
Firmware QEMU Tests (ADR-061) / QEMU Test (edge-tier0) (push) Blocked by required conditions
Firmware QEMU Tests (ADR-061) / QEMU Test (edge-tier1) (push) Blocked by required conditions
Firmware QEMU Tests (ADR-061) / QEMU Test (full-adr060) (push) Blocked by required conditions
Firmware QEMU Tests (ADR-061) / QEMU Test (tdm-3node) (push) Blocked by required conditions
Firmware QEMU Tests (ADR-061) / Fuzz Testing (ADR-061 Layer 6) (push) Waiting to run
Firmware QEMU Tests (ADR-061) / NVS Matrix Generation (push) Waiting to run
Firmware QEMU Tests (ADR-061) / Swarm Test (ADR-062) (push) Blocked by required conditions
Security Scanning / Infrastructure Security Scan (push) Waiting to run
Security Scanning / Static Application Security Testing (push) Waiting to run
Security Scanning / Dependency Vulnerability Scan (push) Waiting to run
Security Scanning / Container Security Scan (push) Waiting to run
Security Scanning / Secret Scanning (push) Waiting to run
Security Scanning / License Compliance Scan (push) Waiting to run
Security Scanning / Security Policy Compliance (push) Waiting to run
Security Scanning / Security Report (push) Blocked by required conditions
* fix: provision.py esptool v5 syntax + refuse partial NVS flashes (#391)

Bug 1: `write_flash` -> `write-flash` for esptool v5.x compat
  - Actual flash command (flash_nvs, line 153) was already fixed
  - Dry-run manual-flash hint (line 301) still printed old syntax

Bug 2: Refuse partial invocations that would silently wipe NVS
  - provision.py flashes a fresh NVS binary at offset 0x9000, which
    REPLACES the entire csi_cfg namespace. Any key not passed on the
    CLI is erased.
  - Previously: `provision.py --port COM8 --target-port 5005` would
    silently wipe ssid, password, target_ip, node_id, etc., causing
    "Retrying WiFi connection (10/10)" in the field.
  - Now: refuse unless all of --ssid/--password/--target-ip provided,
    or --force-partial is set (prints warning listing wiped keys).

Validation:
  - Dry-run: binary generates to 24576 bytes, hint uses write-flash
  - Safety check: partial invocation rejected with clear message
  - Force-partial: warning lists keys that will be wiped
  - Hardware: esptool v5.1.0 `read-flash 0x9000 0x100` works on
    attached ESP32-S3 (COM8); NVS preserved, device reconnected at
    192.168.1.104 with node_id=2 intact after reset.

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

* docs: CHANGELOG catch-up for v0.5.5, v0.6.0, v0.7.0 (#367)

The changelog was stale at v0.5.4 — three releases were cut without
updating it. Added full entries for each, plus an [Unreleased] block
for the #391 provision.py fixes.

version.txt correctly stays at 0.6.0 — v0.7.0 was a model/pipeline
release, not a new firmware binary. Latest firmware is v0.6.0-esp32.

Closes #367

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-15 13:12:46 -04:00
bilibili12433014
e619b9430c fix(rust): resolve WSL release build failures in sensing server
- add missing `ruvector-mincut` dependency for sensing server
- fix mutable/immutable borrow conflicts in tracker and field model flows
- use dynamic adaptive model class names in status response
- add a narrow dead_code compatibility workaround to avoid rustc ICE in WSL
- verify `cargo build --release` succeeds in WSL
2026-04-15 16:44:59 +08:00
Deploy Bot
b74fdcc733 docs: add troubleshooting guide for common ESP32 CSI issues
Covers 8 known issues encountered during multi-node ESP32-S3 deployments:
1. Node not appearing (limping state after USB flash)
2. Person count stuck at 1 (ADR-044)
3. Heart rate/breathing rate jitter (last-write-wins from multiple nodes)
4. Signal quality placeholder
5. Dashboard freezing (WS disconnect loop)
6. OTA crash at 59% (BLE vs OTA conflict)
7. SSH LAN hang (Tailscale workaround)
8. USB-C port selection

Helps with #268 (no nodes found), #375 (node_id), #366 (build errors).
2026-04-10 07:04:48 -04:00
rUv
2a05378bd2
Merge pull request #365 from ruvnet/feat/adr-080-qe-remediation
Some checks failed
Continuous Integration / Code Quality & Security (push) Has been cancelled
Security Scanning / Static Application Security Testing (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Container Security Scan (push) Has been cancelled
Security Scanning / Infrastructure Security Scan (push) Has been cancelled
Continuous Deployment / Pre-deployment Checks (push) Has been cancelled
Continuous Integration / Rust Workspace Tests (push) Has been cancelled
Continuous Integration / Tests (push) Has been cancelled
Continuous Integration / Tests-1 (push) Has been cancelled
Continuous Integration / Tests-2 (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / License Compliance Scan (push) Has been cancelled
Security Scanning / Security Policy Compliance (push) Has been cancelled
Verify Pipeline Determinism / Verify Pipeline Determinism (push) Has been cancelled
Continuous Deployment / Deploy to Staging (push) Has been cancelled
Continuous Deployment / Deploy to Production (push) Has been cancelled
Continuous Deployment / Rollback Deployment (push) Has been cancelled
Continuous Deployment / Post-deployment Monitoring (push) Has been cancelled
Continuous Deployment / Notify Deployment Status (push) Has been cancelled
Continuous Integration / Performance Tests (push) Has been cancelled
Continuous Integration / Docker Build & Test (push) Has been cancelled
Continuous Integration / API Documentation (push) Has been cancelled
Continuous Integration / Notify (push) Has been cancelled
Security Scanning / Security Report (push) Has been cancelled
fix: ADR-080 QE remediation — 13 of 15 issues fixed
2026-04-06 18:40:21 -04:00
ruv
ccb27b280c merge: bring feat/adr-080-qe-remediation up to date with main
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-06 18:36:20 -04:00
ruv
55c5ddfc40 docs: collapse all details sections in README for cleaner view
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-06 18:20:30 -04:00
ruv
c5fef33c6a docs: reorder README sections — v0.7.0 first, then descending
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-06 18:18:40 -04:00
ruv
599ea61a17 docs: update README and user guide for v0.7.0 camera-supervised training
- Add v0.7.0 section with 92.9% PCK@20 result and new scripts
- Add camera-supervised training section to user guide with step-by-step
- Update release table (v0.7.0 as latest)
- Update ADR count (62 → 79)
- Update beta notice with camera ground-truth link

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-06 17:52:44 -04:00
rUv
8dddbf941a
Merge pull request #363 from ruvnet/feat/adr-079-camera-ground-truth
feat: camera ground-truth training pipeline with ruvector optimizations (ADR-079)
2026-04-06 17:29:13 -04:00
ruv
35903a313d feat: NaN-safe TCN + CSI UDP recorder for real ESP32 training (#362)
- Add activation clamping [-10, 10] in TCN forward pass to prevent NaN
  from real CSI amplitude ranges after normalization
- Add safe sigmoid with input clamping [-20, 20]
- Add scripts/record-csi-udp.py: lightweight ESP32 CSI UDP recorder

Validated on real paired data (345 samples):
  ESP32 CSI: 7,000 frames at 23fps from COM8
  Mac camera: 6,470 frames at 22fps via MediaPipe
  PCK@20: 92.8% | Eval loss: 0.083 | Bone loss: 0.008

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-06 17:18:41 -04:00
ruv
4bb0b87465 feat: ADR-080 P1+P2 remediation — refactor, perf, tests, safety
P1 fixes (this sprint):
- P1-6: Extract sensing-server modules (cli, types, csi, pose) from main.rs
- P1-7: DDA ray march for tomography — O(max(n)) replaces O(n^3) voxel scan
- P1-8: Batch neural inference — Tensor::stack/split for single GPU call
- P1-10: Eliminate 112KB/frame alloc — islice replaces deque→list copy

P2 fixes (this quarter):
- P2-11: Python unit tests for 8 modules (rate_limit, auth, error_handler,
  pose_service, stream_service, hardware_service, health_check, metrics)
- P2-13: MAT simulated data safety guard — blocking overlay + pulsing banner
- P2-14: Wire token blacklist into auth verification + logout endpoint
- P2-15: Frame budget benchmark — confirms pipeline well under 50ms budget

Addresses 8 of 10 remaining issues from QE analysis (ADR-080).

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-06 17:01:07 -04:00
ruv
5bd0d59aa6 feat: ADR-080 P1+P2 remediation — refactor, perf, tests, safety
P1 fixes (this sprint):
- P1-6: Extract sensing-server modules (cli, types, csi, pose) from main.rs
- P1-7: DDA ray march for tomography — O(max(n)) replaces O(n^3) voxel scan
- P1-8: Batch neural inference — Tensor::stack/split for single GPU call
- P1-10: Eliminate 112KB/frame alloc — islice replaces deque→list copy

P2 fixes (this quarter):
- P2-11: Python unit tests for 8 modules (rate_limit, auth, error_handler,
  pose_service, stream_service, hardware_service, health_check, metrics)
- P2-13: MAT simulated data safety guard — blocking overlay + pulsing banner
- P2-14: Wire token blacklist into auth verification + logout endpoint
- P2-15: Frame budget benchmark — confirms pipeline well under 50ms budget

Addresses 8 of 10 remaining issues from QE analysis (ADR-080).

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-06 17:00:27 -04:00
ruv
924c32547e fix: ADR-080 P0 security + CI remediation from QE analysis
Address all 5 P0 issues from QE analysis (55/100 score):

- P0-1: Rate limiter bypass — validate X-Forwarded-For against trusted proxy list
- P0-2: Exception detail leak — generic 500 messages, exception_type gated by dev mode
- P0-3: WebSocket JWT in URL (CWE-598) — first-message auth pattern replaces query param
- P0-4: Rust tests not in CI — add rust-tests job gating docker-build and notify
- P0-5: WebSocket path mismatch — use WS_PATH constant instead of hardcoded /ws/sensing

Includes ADR-080 remediation plan and 9 QE reports (4,914 lines).
Firmware validated on ESP32-S3 (COM8): CSI collecting, calibration OK.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-06 16:12:13 -04:00
ruv
327d0d13f6 feat: scalable WiFlow model with 4 size presets (#362)
Add --scale flag with 4 presets for dataset-appropriate sizing:

  lite:   ~190K params, 2 TCN blocks k=3  (trains in seconds)
  small:  ~200K params, 4 TCN blocks k=5  (trains in minutes)
  medium: ~800K params, 4 TCN blocks k=7  (trains in ~15 min)
  full:   ~7.7M params, 4 TCN blocks k=7  (trains in hours)

Refactored model to use dynamic TCN block count, kernel size,
channel widths, hidden dim, and SPSA perturbation count — all
driven by the scale preset. Default is 'lite' for fast iteration.

Validated: lite model completes 30 epochs on 265 samples in ~2 min
on Windows CPU (vs stuck at epoch 1 with full model).

Scale up with: --scale small|medium|full as dataset grows.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-06 14:55:35 -04:00
ruv
d09baa6a09 fix: remove hardcoded Tailscale IPs and usernames from public files
- ADR-079: strip SSH user/IP from optimization description
- mac-mini-train.sh: replace hardcoded IP with env var WINDOWS_HOST

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-06 14:39:21 -04:00
ruv
486392bb68 docs: update ADR-079 with validated hardware, ruvector optimizations, baseline
- Status: Proposed → Accepted
- Add O6-O10 optimizations (subcarrier selection, attention, Stoer-Wagner
  min-cut, multi-SPSA, Mac M4 Pro training via Tailscale)
- Add validated hardware table (Mac camera, MediaPipe, M4 Pro GPU, Tailscale)
- Add baseline benchmark results (PCK@20: 35.3%)
- Update implementation plan with completion status

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-06 14:38:40 -04:00
ruv
33f5abd0e0 feat: ruvector + DynamicMinCut optimizations for WiFlow training (#362)
Add 4 ruvector-inspired optimizations to the training pipeline:

- O6: Subcarrier selection (ruvector-solver) — variance-based top-K
  selection reduces 128→56 subcarriers (56% input reduction)
- O7: Attention-weighted subcarriers (ruvector-attention) — motion-
  correlated weighting amplifies informative channels
- O8: Stoer-Wagner min-cut person separation (ruvector-mincut) —
  identifies person-specific subcarrier clusters via correlation
  graph partitioning for multi-person training
- O9: Multi-SPSA gradient estimation — K=3 perturbations per step
  reduces gradient variance by sqrt(3) vs single SPSA

Also fixes data loader to accept both `kp`/`keypoints` field names
and flat CSI arrays with `csi_shape`, and scalar `conf` values.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-06 14:22:08 -04:00
ruv
e3522ddcda feat: camera ground-truth training pipeline (ADR-079, #362)
Add 4 scripts for camera-supervised WiFlow pose training:

- collect-ground-truth.py: synchronized webcam + CSI capture via
  MediaPipe PoseLandmarker (17 COCO keypoints at 30fps)
- align-ground-truth.js: time-align camera keypoints with CSI windows
  using binary search, confidence-weighted averaging
- train-wiflow-supervised.js: 3-phase supervised training (contrastive
  pretrain → supervised keypoint regression → bone-constrained
  refinement) with curriculum learning and CSI augmentation
- eval-wiflow.js: PCK@10/20/50, MPJPE, per-joint breakdown, baseline
  proxy mode for benchmarking

Baseline benchmark (proxy poses, no camera supervision):
  PCK@10: 11.8% | PCK@20: 35.3% | PCK@50: 94.1% | MPJPE: 0.067

Camera pipeline validated over Tailscale to Mac Mini M4 Pro
(1920x1080, 14/17 keypoints visible, MediaPipe confidence 0.94-1.0).

Target after camera-supervised training: PCK@20 > 50%

Closes #362

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-06 14:07:25 -04:00
ruv
b5e924cd72 fix: embed firmware version from version.txt, log at boot (#354)
Some checks failed
Continuous Deployment / Post-deployment Monitoring (push) Blocked by required conditions
Continuous Deployment / Notify Deployment Status (push) Blocked by required conditions
Continuous Integration / Code Quality & Security (push) Waiting to run
Continuous Integration / Tests (push) Waiting to run
Continuous Integration / Tests-1 (push) Waiting to run
Continuous Integration / Tests-2 (push) Waiting to run
Continuous Integration / Performance Tests (push) Blocked by required conditions
Continuous Integration / Docker Build & Test (push) Blocked by required conditions
Continuous Integration / API Documentation (push) Blocked by required conditions
Continuous Integration / Notify (push) Blocked by required conditions
Security Scanning / Static Application Security Testing (push) Waiting to run
Security Scanning / Dependency Vulnerability Scan (push) Waiting to run
Security Scanning / Container Security Scan (push) Waiting to run
Security Scanning / Infrastructure Security Scan (push) Waiting to run
Security Scanning / Secret Scanning (push) Waiting to run
Security Scanning / License Compliance Scan (push) Waiting to run
Security Scanning / Security Policy Compliance (push) Waiting to run
Security Scanning / Security Report (push) Blocked by required conditions
Firmware CI / Build ESP32-S3 Firmware (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / Build Espressif QEMU (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / Fuzz Testing (ADR-061 Layer 6) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / NVS Matrix Generation (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (boundary-max) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (boundary-min) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (default) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (edge-tier0) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (edge-tier1) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (full-adr060) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (tdm-3node) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / Swarm Test (ADR-062) (push) Has been cancelled
- Add version.txt (0.6.0) read by CMakeLists.txt so
  esp_app_get_description()->version matches the release tag
- Log firmware version on boot: "v0.6.0 — Node ID: X"
- Remove stale Kconfig help text (said default 2.0, actual is 15.0)

Fixes the version mismatch reported in #354 where flashing v0.5.3
binaries showed v0.4.3 because PROJECT_VER was never set.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-06 11:26:58 -04:00
rUv
854342297a
Merge pull request #359 from ruvnet/docs/hf-links-update
Some checks failed
Continuous Integration / Tests (push) Has been cancelled
Continuous Integration / Tests-1 (push) Has been cancelled
Continuous Integration / Tests-2 (push) Has been cancelled
Continuous Integration / Code Quality & Security (push) Has been cancelled
Security Scanning / Static Application Security Testing (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Container Security Scan (push) Has been cancelled
Security Scanning / Infrastructure Security Scan (push) Has been cancelled
Continuous Deployment / Pre-deployment Checks (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / License Compliance Scan (push) Has been cancelled
Security Scanning / Security Policy Compliance (push) Has been cancelled
Continuous Deployment / Deploy to Staging (push) Has been cancelled
Continuous Deployment / Deploy to Production (push) Has been cancelled
Continuous Deployment / Rollback Deployment (push) Has been cancelled
Continuous Deployment / Post-deployment Monitoring (push) Has been cancelled
Continuous Deployment / Notify Deployment Status (push) Has been cancelled
Continuous Integration / Performance Tests (push) Has been cancelled
Continuous Integration / Docker Build & Test (push) Has been cancelled
Continuous Integration / API Documentation (push) Has been cancelled
Continuous Integration / Notify (push) Has been cancelled
Security Scanning / Security Report (push) Has been cancelled
docs: update HuggingFace links to ruv/ruview
2026-04-03 14:23:17 -04:00
ruv
23b4491e7b docs: update HuggingFace links to ruv/ruview (primary repo)
Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-03 14:23:07 -04:00
rUv
2b24250a69
Merge pull request #358 from ruvnet/feat/deep-scan
Some checks failed
Continuous Deployment / Deploy to Production (push) Blocked by required conditions
Continuous Deployment / Notify Deployment Status (push) Blocked by required conditions
Continuous Integration / Tests (push) Waiting to run
Continuous Integration / Tests-1 (push) Waiting to run
Continuous Integration / Tests-2 (push) Waiting to run
Continuous Integration / Code Quality & Security (push) Waiting to run
Continuous Integration / Performance Tests (push) Blocked by required conditions
Continuous Integration / Docker Build & Test (push) Blocked by required conditions
Continuous Integration / API Documentation (push) Blocked by required conditions
Continuous Integration / Notify (push) Blocked by required conditions
Security Scanning / Container Security Scan (push) Waiting to run
Security Scanning / Infrastructure Security Scan (push) Waiting to run
Security Scanning / Static Application Security Testing (push) Waiting to run
Security Scanning / Dependency Vulnerability Scan (push) Waiting to run
Security Scanning / Secret Scanning (push) Waiting to run
Security Scanning / License Compliance Scan (push) Waiting to run
Security Scanning / Security Policy Compliance (push) Waiting to run
Security Scanning / Security Report (push) Blocked by required conditions
Firmware QEMU Tests (ADR-061) / Fuzz Testing (ADR-061 Layer 6) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / NVS Matrix Generation (push) Has been cancelled
Firmware CI / Build ESP32-S3 Firmware (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / Build Espressif QEMU (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (boundary-max) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (boundary-min) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (default) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (edge-tier0) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (edge-tier1) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (full-adr060) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / QEMU Test (tdm-3node) (push) Has been cancelled
Firmware QEMU Tests (ADR-061) / Swarm Test (ADR-062) (push) Has been cancelled
feat: deep-scan.js — comprehensive RF intelligence report
2026-04-03 13:03:28 -04:00
ruv
6d446e5459 feat: deep-scan.js — comprehensive RF intelligence report
Shows: who, what they're doing, vitals, position, objects, electronics,
physics, and RF fingerprint. The 'wow factor' demo script.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-03 13:03:18 -04:00
rUv
62fd1d96af
Merge pull request #357 from ruvnet/docs/v0.6.0-models-guide
docs: HuggingFace models + 17 sensing apps + v0.6.0 guide
2026-04-03 10:28:40 -04:00
ruv
b3fd0e2951 docs: add HuggingFace models, 17 sensing apps, v0.6.0 to README + user guide
README:
- New "Pre-Trained Models" section with HuggingFace download link
- Model table (safetensors, q4, q2, presence head, LoRA adapters)
- Updated benchmarks (0.008ms, 164K emb/s, 51.6% contrastive)
- "17 Sensing Applications" section (health, environment, multi-freq)
- v0.6.0 in release table as Latest

User guide:
- "Pre-Trained Models" section with quick start + huggingface-cli
- What the models do (presence, fingerprinting, anomaly, activity)
- Retraining instructions
- "Health & Wellness Applications" section with all 4 health scripts
- Medical disclaimer

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-03 10:28:29 -04:00
rUv
aae01a2be8
Merge pull request #356 from ruvnet/fix/large-dataset-training
fix: skip triplet JSON export for large datasets (>100K)
2026-04-03 09:37:30 -04:00
ruv
828d0599d7 fix: skip triplet JSON export for large datasets (>100K)
JSON.stringify fails on 1M+ triplets. Training succeeded (33.3%
improvement) but export crashed. Now skips export when >100K triplets.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-04-03 09:37:08 -04:00
rUv
21fd7c84e2
Merge pull request #355 from ruvnet/fix/windows-bind-addr
fix: --bind flag for Windows firewall compatibility
2026-04-03 09:11:01 -04:00