fix(calibration): fresh/bound calibration emits no `calibrated_presence_evidence` on any endpoint
Summary
A successfully completed, bound empty-room calibration produced no calibrated output.
calibrated_presence_evidence is computed per tick (main.rs:8211) and is part of
SensingUpdate (types.rs:130), but it never appeared on any endpoint on a system where
calibration reported fresh and bound.
State at the time
/api/v1/calibration/status
status: fresh binding_mode: bound legacy: false
frame_count: 85731 baseline_eigenvalue_count: 6
source_node_ids: [1,2,3] observed_source_node_ids: [1,2,3]
missing_source_node_ids: []
model_receipt: ruview.calibration.field-model-receipt.v1 present
All three bound nodes active and streaming at the time of sampling.
Observation
calibrated_presence_evidence was absent from the response of every endpoint checked:
/api/v1/sensing/latest absent
/api/v1/status absent
/api/v1/nodes absent
/api/v1/pose/current absent
/api/v1/calibration/status absent
/api/v1/sensing/latest top-level keys were: classification, estimated_persons, features, node_features, nodes, persons, room_inference, signal_field, signal_quality_score, source, tick, timestamp, type, vital_signs.
Since the field is Option<CalibratedPresenceEvidence>, absence means the chain returned
None on every tick.
Where it could be returning None
Not diagnosed — listing the candidates rather than guessing:
main.rs:1636—self.field_model.as_ref()?main.rs:1637— nodeframe_historylookupfield_bridge.rs:146—field.check_freshness(observed_at_us) != Freshfield_bridge.rs:156— empty frame window after canonical resamplingfield_bridge.rs:168—extract_perturbation(...).ok()?calibration_session.rs:240-251— receipt-side conditions (node insource_node_ids,observed_at >= completed_at,person_count <= 3,inference_methodone offield_model_eigenvalue_v1/field_model_perturbation_energy_v1)
Ruled out: a timestamp-unit mismatch between finalize_calibration(now.timestamp_micros())
(main.rs:6546) and the observed_at_unix_ms * 1_000 passed at main.rs:1641. Both are Unix
epoch microseconds; consistent.
Why it matters
This is the output the empty-room baseline exists to produce, and it is also the receipt-bound
one — it carries model_id, binding_digest and source_node_ids. Without it there is no way
for a consumer to tell calibrated output from uncalibrated, and an 11-minute calibration
appears to succeed while changing nothing observable.
Done when
A fresh/bound calibration with all bound nodes active emits calibrated_presence_evidence,
or the API states why it cannot.
Work items
- Determine which condition in the chain returns
Noneon a healthy bound calibration. - Surface the reason — a diagnostic field or a log line — so "calibrated but not emitting" is distinguishable from "not calibrated".
- Add a check that a finalized bound calibration actually yields evidence, so this cannot regress silently.
Related
Same deployment as the stuck-classification issue. That one concerns the uncalibrated
top-level classification; this one concerns the calibrated path, which turns out not to be
emitting at all.
Source: ruvnet/RuView