Decision returned by decide_bedtime — fully captures what the tick
should do with the bedtime window. The caller still performs the
side effects (overlay, hooks, logging, timer mutation).
Clear the “resume last skipped break” slot. Returns true iff a
stored break was actually cleared (used to decide whether to emit
the last_break:changed event).
Minutes since local midnight (0..1440). The unit used everywhere
the scheduler reasons about time-of-day windows (work hours,
bedtime window, fixed-time break list).
True iff now (minutes since midnight) falls inside [start, end),
with wrap-around: a window like 22:00–06:00 correctly straddles
midnight. start == end is treated as an empty window.
Parse "HH:MM" (or "H:MM") into minutes since midnight.
Returns None on anything out of range or unparseable — used to
filter the user’s fixed-time list without spilling errors.
True iff the pre-break notification for this kind should fire now —
i.e. we’re inside the lead window before a due interval break, and
we haven’t already shown the notification for this cycle.
Reset the micro / long timers and clear deferral / postpone state
without disturbing last_sleep or active_break. Called when the
active profile switches: a new profile gets fresh intervals but we
don’t want to re-fire a sleep prompt that’s already shown today.
Decide whether a due break should be delayed because the user is
mid-keystroke. Returns true while we should keep waiting and
false once either the user has paused typing OR the deferral cap
has been reached (so we don’t postpone indefinitely).
Dedupe gate for fixed-time fires: true unless we already fired
this exact (date, minute) slot. Prevents the 1Hz tick from firing
the same fixed slot up to 60 times, and (because the key includes
the local date) stays correct across DST: 02:00 on a “fall back”
day fires once even though the wall clock visits it twice, and
02:30 on a “spring forward” day simply never matches.