The wake flag compared an adoption only against the plan the loop last
recorded, so New York -> UTC -> New York during the re-plan read left
the scheduler sleeping on UTC midnight; and an adoption committing
between the pre-sweep check and the sweep still let the stale sweep run.
`MissedSweepScheduler.settings_lock` now serialises the panel's adoption
(write plus `settings_changed`) with the loop's plan read and with its
pre-sweep re-read plus sweep. It is never held across the wait, and the
loop holds nothing else while acquiring it, so a panel request is at
most delayed by one settings read or one sweep.
`_sleep_unless_woken` now cancels and awaits both child tasks, and
re-raises a failed sleep inside the loop's retry block, so the backoff
runs instead of a sweep and nothing outlives `stop()`.
Tests (all four fail on bcf387d): the successive-zone race, an adoption
issued during the pre-sweep check, a failing sleep, and stop() waiting
for the sleep's cancellation cleanup.
Task: 6351b36d-0eef-4e7d-bf5a-96b754cbc883
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The scheduler loaded settings once per cycle and slept on them until the
old rollover, so a zone adopted from Home Assistant after start-up left a
UTC host sweeping at UTC midnight (20:00 in New York), marking quests
missed hours early.
`MissedSweepScheduler.settings_changed` now wakes the sleeping loop when
the stored zone or rollover time differs from the one it planned with;
the panel's household clock calls it after adopting a reported zone.
Before sweeping, the loop re-reads the settings and re-plans instead if
they no longer match its plan.
Tests: the scheduler re-plans for New York midnight when a panel request
adopts the zone mid-sleep, and skips a stale sweep when the zone changed
without a wake-up. The admin-precedence and invalid-header tests now
prove adoption first, and the SSE client test asserts the timezone header
rides beside the Authorization header.
Task: 6351b36d-0eef-4e7d-bf5a-96b754cbc883
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>