feat(sensing-server): ADR-084 Pass 3.5 — novelty_score on PerNodeFeatureInfo

Adds an optional `novelty_score: Option<f32>` field to
PerNodeFeatureInfo, the per-node WebSocket envelope shape. Mirrored
on both struct definitions (types.rs canonical + main.rs's
refactoring-leftover duplicate) so the schema is consistent.

`#[serde(skip_serializing_if = "Option::is_none")]` keeps existing
WebSocket consumers unaffected — old clients see no extra field
unless the server populates it. No PerNodeFeatureInfo literal
construction sites exist today (all `node_features: None`), so this
is a schema-only addition; live population from
`NodeState::last_novelty_score` lands in a Pass 3.6 follow-up that
also wires `node_features: Some(...)` at the per-node ESP32 frame
emit path.

Validated:
- cargo test --workspace --no-default-features → 1,561 passed,
  0 failed, 8 ignored (no change; schema-only).
- ESP32-S3 on COM7 streaming live CSI (cb #2100, fresh boot).

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
ruv 2026-04-26 01:20:44 -04:00
parent 5152bff1f4
commit 8b050e87bb
2 changed files with 12 additions and 0 deletions

View file

@ -476,6 +476,13 @@ struct PerNodeFeatureInfo {
last_seen_ms: u64,
frame_rate_hz: f64,
stale: bool,
/// ADR-084 Pass 3 cluster-Pi novelty score in `[0.0, 1.0]`.
/// `0.0` = exact-match-in-bank, `1.0` = no overlap with recent
/// per-node frame history. `None` until the first
/// `update_novelty()` call. Consumers (model-wake gate, anomaly
/// emit, UI heatmap) read this to decide whether to escalate.
#[serde(skip_serializing_if = "Option::is_none")]
novelty_score: Option<f32>,
}
/// Shared application state

View file

@ -203,6 +203,11 @@ pub struct PerNodeFeatureInfo {
pub rssi_dbm: f64,
pub last_seen_ms: u64,
pub frame_rate_hz: f64,
/// ADR-084 Pass 3 cluster-Pi novelty score in `[0.0, 1.0]`.
/// `0.0` = exact-match-in-bank, `1.0` = no overlap with recent
/// per-node frame history. `None` until first `update_novelty()`.
#[serde(skip_serializing_if = "Option::is_none")]
pub novelty_score: Option<f32>,
pub stale: bool,
}