Files
ruvnet--RuView/v2
ruv cde81b7755 fix(vitals): BreathingExtractor's stale window let a departed subject read as 30 BPM
extract() already correctly returned None once the estimated
frequency left the breathing band, but filtered_history only cleared
by passively flushing sample-by-sample over the full 30s window. That
let a decreasingly-accurate estimate keep being accepted as noise
diluted the window -- ramping up to and pinning at the range ceiling
(30 BPM, the exact value from the GH issue) right before rejection --
and left a returning subject waiting out the rest of that stale window
before a clean, undiluted estimate could dominate again (measured:
~29s recovery pre-fix vs ~6s post-fix).

Fix: track consecutive_rejections and reset() the window/filter state
immediately on the first out-of-band rejection instead of waiting for
FIFO eviction to drain it.

Note: the "pins forever" framing in the reported repro is partly a
caller-side artifact -- a `last = extract(...) or last` driver holds
the last non-None reading across every subsequent None, which this
fix cannot change without breaking the Option<VitalEstimate> contract.
What's fixed here is the real defect underneath: the stale window no
longer lingers, and reacquisition after a dropout is fast.

Fixes #1422

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-07-27 11:11:19 -04:00
..