mirror of
https://github.com/ruvnet/RuView
synced 2026-06-25 12:53:19 +00:00
fix(mat): gate api module behind its feature — standalone no-default-features builds
pub mod api was unconditional while its only dependency, serde, is optional behind the 'api' feature, so any build without default features failed with 101 unresolved-serde errors (masked in --workspace runs by feature unification). The api module and its create_router/AppState re-export are now cfg(feature = "api")-gated with docsrs annotations. All combos compile: bare --no-default-features (was 101 errors, now 0), --no-default-features --features api, and full default (177 tests pass). Workspace gate: 2,918 passed / 0 failed. https://claude.ai/code/session_01MjBucx95K4BuUxZi8NWwRH
This commit is contained in:
+1
-1
@@ -26,7 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- **Live trust path: sensing-server now routes real frames through the governed `StreamingEngine`.** Previously the live server ran only the *bare* `MultistaticFuser` (fused amplitudes, no trust control plane), while the privacy/provenance/witness engine (ADR-135..146) ran only on synthetic in-test frames — the gap called out in ADR-136 §8 and the beyond-SOTA system review (the privacy control plane was bypassable). New `engine_bridge` module drives `StreamingEngine::process_cycle` from the server's live `NodeState` map (reusing the existing `NodeState → MultiBandCsiFrame` conversion), lazily wiring each node as a WorldGraph sensor and bounding belief growth via the retention cap. Wired additively into both live ESP32/WiFi fusion sites in `main.rs` (split-borrow off the write guard; does not alter person-count behavior) and stores the latest BLAKE3 witness on `AppState`. Every published belief now carries evidence + model + calibration + privacy decision and a deterministic witness. Adds `wifi-densepose-engine/-worldgraph/-bfld/-geo` deps. 6 new bridge tests (witnessed belief with provenance, determinism, idempotent node registration, retention bound, privacy-mode propagation); sensing-server suite 430+128 green.
|
||||
|
||||
### Fixed
|
||||
- **WorldGraph no longer grows unboundedly under the live loop.** `StreamingEngine::process_cycle` appended one `SemanticState` belief per cycle with no eviction — ~1.7M nodes/day at 20 Hz (identified in `docs/research/ruview-beyond-sota/04-optimization-roadmap.md`). Added `WorldGraph::prune_semantic_states(max)` — deterministic eviction of the oldest beliefs by `(valid_from_unix_ms, id)`, structural nodes (rooms/zones/sensors/anchors/tracks/events) never eligible — and wired it into the engine after each belief append (`StreamingEngine::DEFAULT_SEMANTIC_RETENTION` = 7,200 ≈ 6 min at 20 Hz; tunable via `set_semantic_retention`). The WorldGraph holds *current* beliefs; durable history is the recorder's job, so no audit data is lost. 3 new tests (bounded growth end-to-end, oldest-only eviction, deterministic tie-break).
|
||||
- **`wifi-densepose-mat` standalone `--no-default-features` build (101 errors → 0).** `pub mod api` was unconditional while its only dependency, serde, is optional behind the `api` feature — so any build without default features failed with unresolved serde imports (masked in `--workspace` runs by feature unification). The `api` module and its `create_router`/`AppState` re-export are now `#[cfg(feature = "api")]`-gated (with docsrs annotations). All feature combos compile: bare `--no-default-features`, `--no-default-features --features api`, and full default (177 tests pass). `StreamingEngine::process_cycle` appended one `SemanticState` belief per cycle with no eviction — ~1.7M nodes/day at 20 Hz (identified in `docs/research/ruview-beyond-sota/04-optimization-roadmap.md`). Added `WorldGraph::prune_semantic_states(max)` — deterministic eviction of the oldest beliefs by `(valid_from_unix_ms, id)`, structural nodes (rooms/zones/sensors/anchors/tracks/events) never eligible — and wired it into the engine after each belief append (`StreamingEngine::DEFAULT_SEMANTIC_RETENTION` = 7,200 ≈ 6 min at 20 Hz; tunable via `set_semantic_retention`). The WorldGraph holds *current* beliefs; durable history is the recorder's job, so no audit data is lost. 3 new tests (bounded growth end-to-end, oldest-only eviction, deterministic tie-break).
|
||||
- **ESP32 edge heart rate no longer stuck at ~45 BPM / dropping wildly — #987.** The on-device HR estimator (`edge_processing.c`, `0xC5110002`) reported ~45 BPM regardless of true heart rate (Apple-Watch ground truth 87 BPM read as ~45) and swung frame-to-frame. Two root causes: (1) a hardcoded `sample_rate = 10.0f` that became wrong after #985's self-ping raised the CSI callback rate to a variable ~13–19 Hz — BPM scales as `assumed/actual × true`, so 87 read ~45 and the reading swung as CSI yield fluctuated; (2) the zero-crossing estimator locked onto a breathing harmonic (a 0.25 Hz breathing fundamental puts its 3rd harmonic at ~0.74 Hz ≈ 44 BPM inside the HR band). Fix: measure the real sample rate from inter-frame timestamps (used for BPM conversion + biquad re-tuning on >15% drift); replace the HR zero-crossing with an autocorrelation estimator that rejects breathing harmonics (driven by a robust autocorr breathing period); median-13 smooth the output. Hardware A/B (fixed vs unmodified control board, both `edge_tier=2`): control pegged 40–49 BPM; fixed reaches the true 88–91 BPM (vs 87 GT) and holds a stable physiological value (spread 59→0 for a steady subject). Known limitation: heavy subject motion still degrades the estimate (motion gating is a follow-up).
|
||||
- **Person count no longer leaks up to 10 in heuristic mode — addresses #894.** `field_bridge::occupancy_or_fallback` returned the eigenvalue-based `FieldModel::estimate_occupancy` count **unbounded** (its internal ceiling is 10), while the sibling estimators on the same single-link data — the perturbation-energy fallback right below it and `score_to_person_count` — both cap at 3 ("1-3 for single ESP32"). On noisy / under-calibrated CSI the eigenvalue count inflated, producing the "10 persons reported when 1 present" symptom (seen when `--model` fails to load and the server runs on heuristics). Bounded the eigenvalue path to the shared `MAX_SINGLE_LINK_OCCUPANCY` (3) so every estimator on one link agrees; genuine higher counts come from the multistatic fusion path, not a single-link covariance estimate.
|
||||
- **MQTT multi-node deployments now create one Home-Assistant device per node — closes #898.** After the #872 MQTT wiring landed, the JSON→`VitalsSnapshot` bridge hard-coded a single `node_id` (the MQTT client id) and the publisher used a single `OwnedDiscoveryBuilder`, so every physical node collapsed into one device (`identifiers:["wifi_densepose_wifi-densepose-1"]`), contradicting the "one device per node" docs. The bridge now emits one snapshot per node in the sensing update's `nodes[]` (each with its own `node_id` + RSSI, falling back to a single aggregate snapshot for wifi/simulate sources), and the publisher derives a per-node builder (`OwnedDiscoveryBuilder::for_node`) that publishes discovery + availability lazily on first sight of each `node_id` and routes state to per-node topics — yielding N distinct HA devices with per-node availability/LWT. Unit-tested (distinct nodes → distinct `wifi_densepose_<node>` identifiers); 71 MQTT tests pass.
|
||||
|
||||
@@ -31,9 +31,12 @@ the container; this is an environment limitation, not a code failure).
|
||||
| L1 deterministic proof | `python archive/v1/data/proof/verify.py` | **VERDICT: PASS** — hash `f8e76f21a0f9852b70b6d9dd5318239f6b20cbcb4cdd995863263cecdc446f7a` (bit-exact) |
|
||||
| L2 criterion (CIR) | `cargo bench -p wifi-densepose-signal --bench cir_bench --no-default-features --features cir` | Baselines captured pre/post optimization (below) |
|
||||
|
||||
Known pre-existing issue (not introduced here): `cargo check -p
|
||||
~~Known pre-existing issue (not introduced here): `cargo check -p
|
||||
wifi-densepose-mat --no-default-features` fails standalone with 101 serde
|
||||
feature-unification errors; it builds and passes inside `--workspace` runs.
|
||||
feature-unification errors; it builds and passes inside `--workspace` runs.~~
|
||||
**Fixed on this branch:** `pub mod api` (the only serde user) is now gated
|
||||
behind the `api` feature that owns the optional serde dependency; all feature
|
||||
combos compile.
|
||||
|
||||
## Optimizations applied (this session)
|
||||
|
||||
|
||||
@@ -78,6 +78,10 @@
|
||||
#![warn(rustdoc::missing_crate_level_docs)]
|
||||
|
||||
pub mod alerting;
|
||||
/// REST API surface (Axum). Requires the `api` feature — its DTOs derive
|
||||
/// serde, which is an optional dependency gated behind that feature.
|
||||
#[cfg(feature = "api")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "api")))]
|
||||
pub mod api;
|
||||
pub mod detection;
|
||||
pub mod domain;
|
||||
@@ -122,6 +126,8 @@ pub use integration::{
|
||||
AdapterError, HardwareAdapter, IntegrationConfig, NeuralAdapter, SignalAdapter,
|
||||
};
|
||||
|
||||
#[cfg(feature = "api")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "api")))]
|
||||
pub use api::{create_router, AppState};
|
||||
|
||||
pub use ml::{
|
||||
|
||||
Reference in New Issue
Block a user