Commit Graph
130 Commits
Author SHA1 Message Date
overseer 536caf91e4 Fix review findings: first-refresh handling, stale runtime record, P3s
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).
2026-09-23 06:26:29 -04:00
overseer ec7c8d4bc2 Coordinator polls the API snapshot and rebuilds the sensors' data
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.
2026-09-23 06:02:26 -04:00
dev_agent 78fd75ec45 Task 37d5e806: API client module for the integration (Feature 18) (#166) 2026-09-23 05:12:27 -04:00
dev_agent d78ef196d0 Feature 16: NestQuest API Service (#165)
Co-authored-by: dev_agent <17+dev_agent@code.cubecraftcreations.com>
Co-committed-by: dev_agent <17+dev_agent@code.cubecraftcreations.com>
2026-09-23 04:37:26 -04:00
dev_agent e78edbae3b No-HA end-to-end smoke test for the bundled core package (task 628473ad)
No-HA end-to-end smoke test for the bundled core package (task 628473ad)
2026-09-21 16:00:34 -04:00
dev_agent b3715ccdcd Replace HA config reads with an explicit settings object (task 4dd8f870)
Replace HA config reads with an explicit settings object (task 4dd8f870)
2026-09-21 15:55:18 -04:00
dev_agent 315010b901 Extract the engines and business layer into core/ (task 510c1f78)
Extract the engines and business layer into core/ (task 510c1f78)
2026-09-21 15:07:50 -04:00
dev_agent 1503774e85 Extract the storage layer into core/ (bundled in the integration)
Extract the storage layer into core/ (bundled in the integration)
2026-09-21 14:48:01 -04:00
overseer 418fc69f36 Remove removed SensorDeviceClass.PERCENTAGE 2026-09-21 10:02:08 -04:00
overseer 37f7d25cd6 Point HACS URLs at Maniacs-Mansion/NestQuest 2026-09-21 07:47:52 -04:00
dev_agent 7386999cf7 TouchHub setup runbook
TouchHub setup runbook
2026-09-20 20:20:52 -04:00
dev_agent 43ad44ee48 Panel card tests including the no-admin-controls assertion
Panel card tests including the no-admin-controls assertion
2026-09-20 19:41:57 -04:00
dev_agent 4cb07fbca4 Record 1920x1080 panel layout and TouchHub dock behaviour
Record 1920x1080 panel layout and TouchHub dock behaviour
2026-09-20 19:29:00 -04:00
dev_agent 1911b2bf6e Add the party board card (1a) read-only
Add the party board card (1a) read-only
2026-09-20 12:39:47 -04:00
grok 89f517b3ad Add bundled fonts, token CSS, and local font-face loading
Add bundled fonts, token CSS, and local font-face loading

Co-authored-by: grok <24+grok@code.cubecraftcreations.com>
Co-committed-by: grok <24+grok@code.cubecraftcreations.com>
2026-09-20 11:16:17 -04:00
overseer edca25affa Add the Lit card toolchain and auto-register the Lovelace bundle 2026-09-20 10:08:38 -04:00
orchestrator-agent ca93176768 Read the celebration payload from trigger.event.data
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.
2026-09-19 14:54:03 -04:00
orchestrator-agent 3a2e6faa69 Document the automation package and test event validity
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.
2026-09-19 14:52:12 -04:00
orchestrator-agent f6166f25d9 Compare celebration stamps as whole entries; queue events
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.
2026-09-19 14:50:59 -04:00
orchestrator-agent bf84793a1c Add the day-complete celebration blueprint
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.
2026-09-19 14:47:52 -04:00
orchestrator-agent b913772007 Report when remaining counts are unavailable, not all-clear
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.
2026-09-19 14:47:37 -04:00
orchestrator-agent d2f9c50930 Add the end-of-day parent report blueprint
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.
2026-09-19 14:46:13 -04:00
orchestrator-agent 715aac994a Nest notify payload fields under the action's data key
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.
2026-09-19 14:45:50 -04:00
orchestrator-agent ad6f1768d7 Add the afternoon open-quests reminder blueprint
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.
2026-09-19 14:42:50 -04:00
orchestrator-agent f31bda2714 Include collision-suffixed entity ids in the morning summary
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.
2026-09-19 14:31:00 -04:00
orchestrator-agent dc7a82f6e2 Add the morning summary blueprint
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.
2026-09-19 14:24:50 -04:00
orchestrator-agent fbde3eeaa1 Allow saving the empty default notify target
An empty target means notifications are not configured yet and is the
shipped default; only malformed strings (padded or whitespace-only)
reject.
2026-09-19 14:20:13 -04:00
orchestrator-agent 3c832c1cee Add the notification section to the options flow
Notify target (empty default, household fills their own service),
three strict HH:MM automation times (08:00/15:00/20:00 — the report
deliberately before the midnight sweep), and four independent enable
toggles, all leniently stored and round-tripped.
2026-09-19 14:18:18 -04:00
orchestrator-agent 8cd43141a9 Serialize the missed sweep's watermark claim
The whole watermark read-query-fire-write span runs under a
per-database sweep lock; a racing second sweep re-reads the watermark
inside the lock and announces nothing.
2026-09-19 14:16:50 -04:00
orchestrator-agent 3de9f4b970 Add the nightly missed-quest sweep
Fires one nestquest_quest_missed event per past-due open instance at
the configured rollover time and at startup, watermark-guarded in the
new nestquest_meta_state table (migration 7, strictly additive).
Read-only over the domain tables; never reports an instance that was
ever completed.
2026-09-19 14:15:21 -04:00
orchestrator-agent 35e66bd9e6 Carry completion timing under the lock; shut down before close
The completed event's was_on_time travels on the CompletionResult
(decided with the write) instead of re-reading latest state a racing
reversal could replace; unload clears coordinator listeners before
the database close.
2026-09-19 13:29:25 -04:00
orchestrator-agent 36263d3f19 Add the entity-and-event matrix test
One fixture drives every Feature 10 contract: all per-child sensors
and binary sensors, household rollups, the 255-character limit,
the three events exactly once with schema-valid payloads, the
missed-instance omission rule, and no entities for inactive children.
2026-09-19 13:26:51 -04:00
orchestrator-agent a9d8f1d225 Handle entity lifecycle for child add, deactivate, reactivate
The harness tracks entities per entry so a platform unload removes
exactly that entry's entities; lifecycle tests prove deactivated
children drop out on reload, reactivation restores the original
unique_ids, new children appear without disturbing existing ones,
and the restart equivalent restores live states.
2026-09-19 13:23:35 -04:00
orchestrator-agent a5dbae5d50 Serialize forced coordinator refreshes per entry
NestQuestCoordinator.async_refresh holds a per-entry lock so
overlapping service-path refreshes never interleave; the queued pass
always publishes after the in-flight one.
2026-09-19 13:21:54 -04:00
orchestrator-agent ad56d13c6e Refresh entities immediately after completion service calls
complete_quest and uncomplete_quest force a coordinator refresh when
the call appended, so entity states land the moment the service call
returns; scheduled internals are unaffected.
2026-09-19 13:16:12 -04:00
orchestrator-agent 2a4eec658f Decide event transitions under the completion lock
complete/uncomplete return a CompletionResult str subclass carrying
appended (decided with the write under the lock), so duplicate
concurrent calls fire one transition event; day-complete only
evaluates for an instance due today.
2026-09-19 12:03:42 -04:00
orchestrator-agent fe38e5040e Fire the documented bus events from the completion service paths
quest_completed and quest_uncompleted fire on actual transitions with
documented payloads; child_day_complete fires when a completion clears
the child's day; quest_missed is defined as Feature 11's contract.
Payloads documented in the README for automation authors.
2026-09-19 12:01:05 -04:00
orchestrator-agent 5bca24910a Add household rollup and cycle-day sensors
Household quests due/completed today sum the active children's
snapshots; cycle day reports the first scheduled child's cycle
position (0 when nobody is scheduled), anchor-date arithmetic only.
2026-09-19 11:58:12 -04:00
orchestrator-agent df4c9eb21a Add per-child all-done and present-today binary sensors
all_done is on exactly when the child owed quests today and owes none
remaining (a zero-quest day stays off so celebrations never fire on
an empty day); present_today mirrors the presence engine's answer
for the HA-local date.
2026-09-19 11:56:10 -04:00
orchestrator-agent 1f7a7ba46c Add the per-child next-quest sensor
State carries the earliest open quest's title truncated under the
255-character limit with the full shape in attributes; the documented
"none" sentinel is reported when the day is clear.
2026-09-19 11:54:19 -04:00
orchestrator-agent 7a0c8d1885 Honor failed platform unload; derive labels from the snapshot
A False platform unload now returns False and retains the runtime
record so live entities keep their database. Sensor names and device
labels re-derive from the current snapshot so child renames
propagate; unique_ids stay child-id based.
2026-09-19 11:53:27 -04:00
orchestrator-agent 00409a76db Add per-child daily count and percentage sensors
Four sensors per active child read the coordinator snapshot: quests
due today (carrying the panel payload that omits missed instances plus
the admin payload that includes them, D-009), completed, remaining, and
completion percentage (100 on a zero-quest day). Platform forwarding
wired through the harness's entity registry stand-ins.
2026-09-19 11:50:18 -04:00
orchestrator-agent 5c99987e7f Shut the coordinator down when first refresh fails setup
The setup except path closes the database; the coordinator created
above it now shuts down first so no listener can fire against the
closed connection. Regression test included.
2026-09-19 11:44:11 -04:00
orchestrator-agent 979eafc5a2 Add the shared NestQuest data update coordinator
One refresh pass builds the whole entity snapshot: active children,
today's instances with derived open/done/missed states, per-child
presence via the PresenceEngine (records converted to model objects),
rollup counts, and the custody cycle day. Interval configurable via
the new update_interval option, default five minutes.
2026-09-19 11:41:12 -04:00
orchestrator-agent c1efd39ce3 Add the permission test matrix across every registered service
Admin succeeds on all ten admin-only services; a non-admin and a
no-context call are refused on each; complete_quest stays open; a
kiosk-style id is refused on uncomplete_quest and regenerate; the
registry coverage assertion fails the suite on any gap.
2026-09-19 08:40:20 -04:00
orchestrator-agent b5058a3bed Test the permission gate's audit logging
Warning on denial and debug on success carry the service, the caller
user id (or none), and a UTC stamp; nothing beyond the user id leaks.
2026-09-19 08:39:02 -04:00
orchestrator-agent d0f49b44b5 Cover fail-closed no-context behavior across admin-only services
Parametrised test denies no-context calls on every admin-only service;
complete_quest proceeds with no user; scheduled internals stay direct
function calls.
2026-09-19 08:38:24 -04:00
orchestrator-agent 37d7b7e6c3 Gate every NestQuest service behind the admin permission check
permission_gate wraps all registered services at registration time:
admin-only policy reads call.context.user_id against admin_allowlist
is_admin (fail closed on no context); complete_quest stays open.
2026-09-19 08:36:14 -04:00
orchestrator-agent 4281b9d01c Add admin-only versus open service policy registry
One mapping in service_policy.py: complete_quest is open, every other
registered nestquest service is admin_only.
2026-09-18 16:05:12 -04:00
orchestrator-agent b1c42f10d0 Regenerate child instances after presence service writes
Presence pattern and override handlers now call regenerate_for_child.
Definition edit/activate pass HA-local today and configured horizon.
2026-09-18 16:03:42 -04:00