P1: the first-refresh error handling never fired against real Home
Assistant. Real DataUpdateCoordinator.async_config_entry_first_refresh
converts ANY refresh failure into ConfigEntryNotReady (the original
exception survives only as __cause__), so `except NestQuestApiError`
could never match: the failure fell through to the outer except block,
unwound listeners, closed the DB and re-raised, and
async_forward_entry_setups never ran — no entities at all. Two-sided
fix: _async_update_data now converts every typed NestQuestApiError
(unconfigured stub, transport failure, non-2xx) into
homeassistant.helpers.update_coordinator.UpdateFailed — the exception
HA's coordinator machinery records as a failed pass
(last_update_success=False, data=None) — and setup catches
ConfigEntryNotReady around the first refresh instead, so an unconfigured
API or failed fetch keeps setup alive with unavailable entities while
everything else still unwinds. The conftest DataUpdateCoordinator
stand-in now reproduces HA's real contract (async_refresh records a
failure instead of raising; first_refresh wraps it in
ConfigEntryNotReady) and gains an UpdateFailed stand-in, so this class
of bug is caught by the suite — verified by reverting the catch, which
fails both unconfigured-API and failed-fetch tests.
P1: a stale hass.data[DOMAIN][entry.entry_id] survived a failed setup.
The runtime record registers in hass.data before the first refresh and
platform forward, but the except cleanup only cleared
entry.runtime_data; after any failure in that window a later unload
picked up the stale, already-torn-down record and re-invoked the
already-consumed update-listener remover (ValueError). The except block
now also pops the hass.data entry, and
test_setup_failure_after_registration_shuts_coordinator_down (reworked
from the fiction-based first-refresh trigger: a failed first refresh is
tolerated setup, not an unwind) proves a failed setup followed by an
unload does not raise and leaves no residue.
P3: dropped the function-local re-import of NestQuestApiClient in
coordinator_client_from_entry (module-level import already covers it),
and the unused coordinator_client_from_entry alias in the conftest
fixture.
P3: test_due_today_payload_omits_missed_admin_equals_panel dropped the
missed-instance count assertions in the Feature 18 rewrite; restored
quests_completed_today == 0 / quests_remaining_today == 1 so the
missed-derivation + counts pairing stays verified (the counts arrive
precomputed and still roll the full day).
Feature 18: the shared coordinator's refresh pass now fetches
GET /api/v1/panel/snapshot through the NestQuestApiClient and
reconstructs the exact core dataclasses (NestQuestSnapshot,
ChildDaySnapshot, QuestInstanceView) the Feature 10 entities read, so
sensor.py and binary_sensor.py are untouched and every entity_id and
attribute payload keeps its shape.
Why: the integration becomes an API client of the NestQuest service
instead of a second reader of the SQLite file, and the panel cards and
the four blueprints keep working without changes.
- snapshot_from_api_payload maps the route's JSON back onto the
dataclasses field by field (state 'completed' -> 'done' so
instance_payload renders 'completed' again; counts, presence,
next_present, overdue, on_time, completed_at pass through verbatim;
due_date is stamped from today_iso, the only date the route serves).
- The panel payload omits missed instances (D-009), so
admin_instances can no longer carry missed rows — the admin surface
for missed quests is the PWA reading the API directly. Documented in
the module docstring and pinned by tests.
- An unconfigured panel token (the shipped default) gets a typed-error
stub instead of a construction crash: setup succeeds, the first
refresh fails cleanly, entities come up unavailable and HA's retry
cycle applies. Fetch failures log the typed error and mark the
entities unavailable while data keeps its last good snapshot.
- The runtime record registers before the first refresh so the refresh
path always finds the live entry state; the update interval and the
serialized forced-refresh behaviour are unchanged.
- Tests: a fixture snapshot drives the coordinator (stub client, no
network) asserting per-child values, household rollups, cycle day,
and the exact instance payload shape, plus unconfigured and
failed-fetch cases; DB-seeded tests ride a lazy local-snapshot
client through the same JSON path.
HA event triggers expose the payload as trigger.event.data, not
trigger.payload; fix the blueprint, its tests, and the README
examples, with a regression guard.
README gains the blueprint section: all four blueprints, their
inputs, the wiring table to the options-flow notification settings,
the celebration helper setup, event/sensor payload reference, and a
copy-pasteable example package. Tests assert every event trigger
references a real NestQuest event and no reminder is produced for an
absent child.
Child ids sharing a prefix no longer suppress each other (split and
compare entries for equality), and queued mode keeps a second child's
day-complete event from being dropped while the first notify runs.
Triggers on nestquest_child_day_complete (never a zero-quest day),
notifies with the payload's child name, and dedupes per child per
day via an input_text helper holding <child_id>:<today> entries
pruned to today — a re-cleared day does not re-fire, but a second
child clearing the same day still celebrates.
A missing or non-numeric remaining sensor reads as -1 in the
all-clear guard, so a degraded day reaches the parent instead of
looking like a clear day.
Defaults to 20:00 local — deliberately before the midnight missed
sweep, reading the same day's data. Every present child gets a
completion line; owed lines name still-open quests; absent children
are omitted; nothing sends when all clear unless opted in.
The modern HA action schema passes title and message to the notify
service only under data; fix the morning summary and afternoon
reminder blueprints and the test accessors accordingly.
Lists only present children who still owe quests; sends nothing at
all when every present child is clear (a false template condition
stops the action). Blueprint test helpers move to a shared module.
Duplicate child names get HA registry suffixes (_2); the template now
iterates the due sensors (which carry present/child_id/child_name as
attributes) and pairs counts by child_id, so suffixed duplicates are
listed and the household rollup is excluded by the presence guard.
Iterates present children from the Feature 10 presence sensors, lists
what each owes today from the remaining sensor, omits absent children
entirely. Blueprint inputs (time, notify service, send toggle); the
notify target is the household's choice, never hard-coded. PyYAML and
Jinja2 join the dev-only dependencies for blueprint template tests.