Compare commits

..
Author SHA1 Message Date
overseerandClaude Opus 5.5 cf118cf305 Serialise time zone adoption with the missed-sweep scheduler
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>
2026-09-28 22:43:40 -04:00
overseerandClaude Opus 5.5 bcf387d902 Re-plan the missed sweep when the panel adopts a time zone
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>
2026-09-28 22:21:53 -04:00
overseerandClaude Opus 5.5 09d6a55e04 Adopt Home Assistant's time zone for the API household clock
The deployed API host runs UTC and the household `timezone` setting was
never set, so the panel snapshot read UTC: morning quests showed overdue
hours early and `today_iso` rolled over at UTC midnight.

The integration now reports `hass.config.time_zone` on every panel
request (`X-NestQuest-Timezone`).  While the admin has not chosen a zone
(`timezone_configured` is false) the API adopts and persists it, so the
panel, the admin plane, and the missed-sweep scheduler all read the
household clock out of the box.  An explicit admin choice — including an
explicitly chosen empty zone — still wins; an invalid reported zone is
logged and ignored.  No schema change.

Task: 6351b36d-0eef-4e7d-bf5a-96b754cbc883

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:05:16 -04:00
4 changed files with 3 additions and 54 deletions
-51
View File
@@ -1,56 +1,5 @@
# NestQuest Release Notes
## Version 0.9.6 — 2026-09-28
### Scope
Patch release carrying the household time-zone fix onto `main` (PR #275, task
6351b36d "Time zone errors").
### Behaviour
- The Home Assistant integration now reports `hass.config.time_zone` to the API
in an `X-NestQuest-Timezone` header on every panel request.
- While the API's `timezone` setting has never been explicitly chosen
(`timezone_configured` false), the API adopts and persists the reported zone
(under the settings lock), so the panel's overdue/today calculation, the
admin plane and the missed-sweep scheduler are all household-local even when
the API host runs UTC. No manual setup is required.
- The missed-sweep scheduler re-plans immediately when the adopted zone changes
while it is sleeping, and re-reads the stored zone before sweeping, so it no
longer fires at the old (UTC) rollover.
- An admin-chosen zone — including an explicit choice of empty (API-host local)
— still wins over the reported zone. An invalid reported zone is logged and
ignored; the panel keeps serving on the stored settings.
### Requirements
- Home Assistant floor 2024.6.0 (unchanged).
### Breaking changes
- None. The database schema is unchanged at version 9: no migration and no
database backup is required for this release.
- Deployment note: this fix needs BOTH the API service and the HA integration
upgraded. The integration supplies the zone and the API adopts it; upgrading
only one side leaves the previous behaviour. An install whose `timezone` was
previously set — or explicitly cleared to host-local — keeps that choice.
### Known limitations
- If `timezone` is empty and `timezone_configured` is true (an explicit
"host local" choice), that choice is respected and the API host's zone (UTC
on the standard deployment) still applies until an admin selects a zone in
the admin Preferences.
- A change to Home Assistant's own `time_zone` takes effect after the
integration reloads or Home Assistant restarts.
### Rollback
- No schema change: rolling back to 0.9.5 requires no database restore. The API
and the integration may be rolled back independently; rolling back only the
integration restores the previous stored-setting-only behaviour.
## Version 0.9.5 — 2026-09-27
### Scope
+1 -1
View File
@@ -15,5 +15,5 @@
"iot_class": "local_polling",
"issue_tracker": "https://github.com/Maniacs-Mansion/NestQuest/issues",
"requirements": [],
"version": "0.9.6"
"version": "0.9.5"
}
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "nestquest"
version = "0.9.6"
version = "0.9.5"
description = "NestQuest Home Assistant Integration"
readme = "README.md"
requires-python = ">=3.11"
Generated
+1 -1
View File
@@ -373,7 +373,7 @@ wheels = [
[[package]]
name = "nestquest"
version = "0.9.6"
version = "0.9.5"
source = { virtual = "." }
[package.dev-dependencies]