You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
nap.dart: leading edge of the record is unguarded, unlike the trailing edge #40
immobilityMask / detectNaps guard the trailing edge of the record but not the leading edge, so edge has to guess at the boundary with a wall-clock heuristic instead of being told.
The asymmetry
nap.dart handles a bout running past the end of the record properly — it marks it unfinished and defers it, and propagates that backward through napChainGapSec so a chained fragment is deferred too. That is exactly right.
At the other end there is no equivalent, because stillAt short-circuits its own discontinuity check at k == 0:
So a bout that was already in progress when the record opened is emitted as if it started there, with no way for the caller to tell the difference.
Why it matters downstream
edge slices a day's nap window at local midnight, so index 0 is the day boundary. A nap straddling midnight is emitted whole by the day that owns it and then re-detected as a fresh bout at index 0 by the next day — double-counted, with its minutes subtracted from both days' sleep need.
edge currently works around this (OpenStrap/edge#204) by dropping an index-0 bout when the record is contiguous into midnight, judged by a 60-second timestamp tolerance. That is a guess, and it has a known residual: if the band only starts recording at midnight, the previous day never saw the bout either, so both days drop it and a real nap is lost.
What would fix it properly
Expose leading-edge-unfinished the same way the trailing edge already is — e.g. a startsAtRecordEdge flag on NapWindow, or extend the existing unfinished concept to both ends. The caller can then defer on evidence rather than infer from a timestamp tolerance, and the residual disappears.
ImmobilityMask already carries immobileUnknown for undecidable seconds, which is the same idea — index 0 is undecidable in exactly that sense.
Activity
abdulsaheel commentedon Oct 4, 2026
fixed in c22ff93