complete_quest proxies to the API (task 47c7c90e) #169

Member

Task: 47c7c90e-cbe8-4192-a996-b639834f67b2 (Feature 18 - HA Integration as API Client)

Done-condition: nestquest.complete_quest proxies to POST /api/v1/panel/instances/{id}/complete through the API client, so a panel tap completes a quest through the API. The service keeps its payload contract (instance_id, actor=panel, actor_child_id). A test asserts the service call reaches the API client with the right arguments, and that an API failure surfaces as a service error.

What changed

  • custom_components/nestquest/services.py - _complete_quest is now a thin proxy: it resolves the entry's ONE shared API client off the runtime (the same instance the coordinator polls and the SSE subscription reads) and calls complete_instance(instance_id, actor_child_id). NO local database completion and NO local completed/day-complete event (the API publishes the transition on its SSE stream and the subscription re-fires it - firing locally too would double-fire). After a successful call the coordinator refreshes so the sensors reflect the completion immediately (the old immediate-update behaviour). NestQuestApiError, an unconfigured client (the no-token stub), and a non-panel actor all raise HomeAssistantError with clear, token-free messages. The payload schema is unchanged.
  • tests/test_complete_quest_proxy.py (new) - the service reaches the shared client with the right arguments; no local write, no local event; a coordinator refresh on success; non-2xx and transport failures raise a service error chained to the typed error (never containing the panel token); the unconfigured stub fails clearly; a user-actor call is rejected before reaching the client.
  • tests/conftest.py - the harness stand-in client (LazyLocalSnapshotClient) bridges the panel complete route the way it already bridges the snapshot: same core completion the route delegates to, panel actor shape, route-shaped {"status": ...} answer, and the route's per-completion SSE frame publishing (core builders, appended completions only). New refire_api_transitions helper delivers published frames through the real NestQuestEventStream subscription and waits for the bus.
  • tests/test_events.py, tests/test_entity_matrix.py - the tests that drove complete_quest through the local database now drive it through the API client path and assert their bus events after the frames are delivered through the SSE subscription (production event path); the two shim-level tests drive the events shim directly, the way its remaining callers invoke it. No test deleted, no assertion weakened.

Checks

  • TZ=UTC uv run pytest -q -> 1815 passed in 15.72s (baseline 1810 + 5 new)
  • TZ=UTC uv run pytest -q tests/test_services.py tests/test_complete_quest_proxy.py -> 36 passed in 0.22s

Head: ffda0a2ed7

Task: 47c7c90e-cbe8-4192-a996-b639834f67b2 (Feature 18 - HA Integration as API Client) Done-condition: nestquest.complete_quest proxies to POST /api/v1/panel/instances/{id}/complete through the API client, so a panel tap completes a quest through the API. The service keeps its payload contract (instance_id, actor=panel, actor_child_id). A test asserts the service call reaches the API client with the right arguments, and that an API failure surfaces as a service error. ## What changed - `custom_components/nestquest/services.py` - `_complete_quest` is now a thin proxy: it resolves the entry's ONE shared API client off the runtime (the same instance the coordinator polls and the SSE subscription reads) and calls `complete_instance(instance_id, actor_child_id)`. NO local database completion and NO local completed/day-complete event (the API publishes the transition on its SSE stream and the subscription re-fires it - firing locally too would double-fire). After a successful call the coordinator refreshes so the sensors reflect the completion immediately (the old immediate-update behaviour). `NestQuestApiError`, an unconfigured client (the no-token stub), and a non-panel actor all raise `HomeAssistantError` with clear, token-free messages. The payload schema is unchanged. - `tests/test_complete_quest_proxy.py` (new) - the service reaches the shared client with the right arguments; no local write, no local event; a coordinator refresh on success; non-2xx and transport failures raise a service error chained to the typed error (never containing the panel token); the unconfigured stub fails clearly; a user-actor call is rejected before reaching the client. - `tests/conftest.py` - the harness stand-in client (`LazyLocalSnapshotClient`) bridges the panel complete route the way it already bridges the snapshot: same core completion the route delegates to, panel actor shape, route-shaped `{"status": ...}` answer, and the route's per-completion SSE frame publishing (core builders, appended completions only). New `refire_api_transitions` helper delivers published frames through the real `NestQuestEventStream` subscription and waits for the bus. - `tests/test_events.py`, `tests/test_entity_matrix.py` - the tests that drove `complete_quest` through the local database now drive it through the API client path and assert their bus events after the frames are delivered through the SSE subscription (production event path); the two shim-level tests drive the events shim directly, the way its remaining callers invoke it. No test deleted, no assertion weakened. ## Checks - `TZ=UTC uv run pytest -q` -> `1815 passed in 15.72s` (baseline 1810 + 5 new) - `TZ=UTC uv run pytest -q tests/test_services.py tests/test_complete_quest_proxy.py` -> `36 passed in 0.22s` Head: ffda0a2ed7fe78d2fd5dd2da19c2cc6eda1e98e4
dev_agent added 1 commit 2026-09-23 07:45:52 -04:00
WHY: Feature 18 makes the integration a client of the NestQuest API
service — every database write must go through the API.  The
complete_quest service still wrote the local database and fired the
completed event itself, which would double-fire once the SSE
subscription re-fires the API's transition (and stops being true the
moment the local database is dropped).  The service now proxies to the
entry's ONE shared API client (complete_instance: the panel complete
route) and keeps only the old immediate-update behaviour: a successful
call refreshes the coordinator so the sensors reflect the completion
at once; the bus event comes solely from the SSE stream.  Typed API
failures (and an unconfigured client, and a non-panel actor) surface
as HomeAssistantError with token-free messages instead of being
swallowed; the payload contract (instance_id, actor=panel,
actor_child_id) is unchanged for the panel cards.

Tests: new tests/test_complete_quest_proxy.py asserts the call reaches
the shared client with the right arguments, that no local write or
local event happens on the API path, that a non-2xx/transport failure
raises a service error chained to the typed error (never containing
the token), and that the unconfigured stub fails clearly.  Existing
tests that drove complete_quest through the local database move to the
API path via the harness stand-in client (which performs the same core
completion and publishes the same SSE frames the API route does) and
assert their bus events after the frames are delivered through the
real SSE subscription; the shim-level tests drive the events shim
directly, the way its remaining callers invoke it.

Task 47c7c90e (complete_quest proxies to the API, Feature 18).
review_agent left a comment
Member

Independent Claude Sonnet 5 review completed for this exact commit.

Independent Claude Sonnet 5 review completed for this exact commit.
dev_agent merged commit b0bbb5f8c5 into feature/430f7f98-7650-43e9-aa98-4b340303602a-ha-integration-as-api-client 2026-09-23 07:52:33 -04:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Maniacs_Mansion/NestQuest#169