Merge PR #2133 (aepod) into release integration

This commit is contained in:
ruv committed 2026-10-05 11:44:34 -04:00
commit e9d0cef610
4 files changed
+89 -1

No files matched your search

+6
View File
@@ -116,6 +116,7 @@ handler (`health_ready`, `main.rs:8128,8133`) and return a `trust` block
"waiting_for_frames": false,
"last_frame_age_ms": 42,
"trust": {
"node_positions": { "1": [0.5, 0.0, 1.0], "2": [4.0, 3.0, 1.0] },
"last_witness": "…64 hex chars or null…",
"effective_class": "Anonymous | Restricted | …",
"demoted": false,
@@ -126,6 +127,11 @@ handler (`health_ready`, `main.rs:8128,8133`) and return a `trust` block
}
```
`node_positions` is the `--node-positions` map the governed fuser holds,
keyed by node id. It is `{}` when no positions are configured, and then every
node fuses at the origin. A node the map does not name also fuses at the
origin.
**This is a real, currently-shipped diagnostic surface — but it is honestly
limited.** It tells you *that* errors are occurring and *that* the current
class is demoted, and the total count, but not *why* for your specific run:
@@ -264,6 +264,14 @@ impl StreamingEngine {
self.fuser.set_node_positions_by_id(positions);
}
/// Node positions the governed fuser currently holds, keyed by node id.
/// Empty until [`Self::set_node_positions`] is called, in which case every
/// node fuses at the origin.
#[must_use]
pub fn node_positions(&self) -> &std::collections::HashMap<u8, [f32; 3]> {
self.fuser.node_positions_by_id()
}
/// Activate a per-room calibration adapter (ADR-150 §3.4). From the next
/// cycle on, the adapter id is part of provenance `model_version` — and
/// therefore of the witness — so the exact weights shaping inference are
@@ -135,6 +135,21 @@ impl EngineBridge {
self.engine.set_semantic_retention(max_states);
}
/// Give the governed fuser the `--node-positions` map, keyed by node id.
/// The fuser resolves each frame's position by its `node_id`, so nodes
/// discovered later pick up their entry without another call; nodes with
/// no entry fuse at the origin.
#[must_use]
pub fn with_node_positions(mut self, positions: HashMap<u8, [f32; 3]>) -> Self {
self.engine.set_node_positions(positions);
self
}
/// Node positions the governed fuser is using, keyed by node id.
pub fn node_positions(&self) -> &HashMap<u8, [f32; 3]> {
self.engine.node_positions()
}
/// Switch the active privacy mode (operator/control-plane action).
pub fn set_privacy_mode(&mut self, mode: PrivacyMode) {
self.engine.set_privacy_mode(mode);
@@ -309,6 +324,33 @@ mod tests {
m
}
fn configured_positions() -> HashMap<u8, [f32; 3]> {
[(0u8, [0.5, 0.0, 1.0]), (1u8, [4.0, 3.0, 1.0])]
.into_iter()
.collect()
}
#[test]
fn with_node_positions_reaches_the_governed_fuser() {
let bridge = EngineBridge::new(PrivacyMode::PrivateHome, 1, "r", "R", None)
.with_node_positions(configured_positions());
assert_eq!(bridge.node_positions(), &configured_positions());
}
#[test]
fn node_positions_survive_a_guard_config() {
let cfg = MultistaticConfig {
guard_interval_us: 200_000,
min_nodes: 1,
..MultistaticConfig::default()
};
let mut bridge = EngineBridge::new(PrivacyMode::PrivateHome, 1, "r", "R", Some(cfg))
.with_node_positions(configured_positions());
assert_eq!(bridge.node_positions(), &configured_positions());
assert!(bridge.observe_cycle(&two_node_states(), 1_000).is_some());
assert_eq!(bridge.node_positions(), &configured_positions());
}
#[test]
fn empty_states_produce_no_belief() {
let mut bridge = EngineBridge::new(PrivacyMode::PrivateHome, 1, "living_room", "Living Room", None);
@@ -7142,6 +7142,31 @@ async fn health_live(State(state): State<SharedState>) -> Json<serde_json::Value
}))
}
/// Governed-fuser positions for `/api/v1/status`, keyed by node id and sorted.
fn engine_node_positions_json(positions: &HashMap<u8, [f32; 3]>) -> serde_json::Value {
let sorted: BTreeMap<String, [f32; 3]> = positions
.iter()
.map(|(id, p)| (id.to_string(), *p))
.collect();
serde_json::json!(sorted)
}
#[cfg(test)]
mod engine_node_positions_json_tests {
use super::*;
#[test]
fn engine_node_positions_json_is_keyed_by_id() {
let configured: HashMap<u8, [f32; 3]> = [(12, [4.0, 3.0, 1.0]), (11, [0.5, 0.0, 1.0])]
.into_iter()
.collect();
assert_eq!(
engine_node_positions_json(&configured),
serde_json::json!({"11": [0.5, 0.0, 1.0], "12": [4.0, 3.0, 1.0]})
);
}
}
/// Lowercase hex of a 32-byte witness for JSON exposure.
fn witness_hex(w: [u8; 32]) -> String {
use std::fmt::Write;
@@ -7168,6 +7193,8 @@ async fn health_ready(State(state): State<SharedState>) -> Json<serde_json::Valu
// witness + privacy class + recalibration flag, and the engine error
// audit — previously write-only on AppState, now readable here.
"trust": {
// Positions the governed fuser uses, from --node-positions.
"node_positions": engine_node_positions_json(s.engine_bridge.node_positions()),
"last_witness": s.engine_bridge.last_trust_witness().map(witness_hex),
"effective_class": s.engine_bridge.effective_class().map(|c| format!("{c:?}")),
"demoted": s.engine_bridge.demoted(),
@@ -13027,6 +13054,9 @@ async fn main() {
// WDP_TDM_SLOTS/WDP_GUARD_INTERVAL_US-derived guard (#1049/#1057).
let mut engine_bridge_multistatic_cfg: Option<MultistaticConfig> = None;
let mut node_positions_config: HashMap<u8, [f32; 3]> = HashMap::new();
// The same map for the governed fuser behind `engine_bridge`, which
// otherwise places every node at the origin.
let mut engine_bridge_node_positions: HashMap<u8, [f32; 3]> = HashMap::new();
let state: SharedState = Arc::new(RwLock::new(AppStateInner {
latest_update: None,
rssi_history: VecDeque::new(),
@@ -13146,6 +13176,7 @@ async fn main() {
// no `node_id:` prefix takes its list index as its id), so
// an existing `--node-positions` string keeps its meaning.
fuser.set_node_positions_by_id(node_positions_config.clone());
engine_bridge_node_positions = node_positions_config.clone();
}
}
engine_bridge_multistatic_cfg = Some(MultistaticConfig {
@@ -13162,7 +13193,8 @@ async fn main() {
"default",
"Default Room",
engine_bridge_multistatic_cfg,
),
)
.with_node_positions(engine_bridge_node_positions),
field_model: bootstrap_field_model,
installation_id: args.installation_id.clone(),
bootstrap_baseline: bootstrap_metadata.clone(),