Files
NestQuest/design/ENTITIES-AND-SERVICES.md
T
dev_agent a2c027deca Add the quest complete screen (1c)
Add the quest complete screen (1c)
2026-09-20 18:39:11 -04:00

4.9 KiB
Raw Blame History

Screens → HA entities, services and events

Planned surface from CTXD CONTEXT.MD, adjusted for the design decisions in DESIGN-HANDOFF.md. Names use the quest_* model.

1. Entities the cards read

Entity Type Used by
sensor.nestquest_<child>_quests_due_today int 1a plate progress, 1b counts, 1d stats
sensor.nestquest_<child>_quests_completed_today int 1a, 1b, 1c, 1d, 1h
sensor.nestquest_<child>_quests_remaining_today int 1b remaining block, 1d
sensor.nestquest_<child>_completion_pct_today float progress bars
sensor.nestquest_<child>_next_quest str + attrs optional panel hint
binary_sensor.nestquest_<child>_all_done bool 1c trigger, 1d "all done"
binary_sensor.nestquest_<child>_present_today bool 1a away plate, 1d away row
sensor.nestquest_household_quests_due_today int 1b party line, 1c party stat
sensor.nestquest_household_quests_completed_today int same
sensor.nestquest_cycle_day int 1d sub-line, 1f header
configured weather.<entity> HA core panel dock

Per-instance data is too granular for entity state. The cards read the day's instance list from an attribute payload on the per-child sensor (or a websocket command — implementer's call), shaped:

{
  "instances": [
    { "id": 4821, "definition_id": 12, "child_id": 3, "title": "Fill bird feeder",
      "icon": "bird", "window": "afternoon", "due_time": "17:00",
      "state": "open", "overdue": true, "completed_at": null, "on_time": null }
  ]
}

state ∈ open | completed. Missed instances are omitted from panel payloads (decision 5) and included in admin payloads.

2. Services the cards call

Service Admin only Called from
nestquest.complete_quest no (panel allowed) 1j confirm
nestquest.uncomplete_quest yes 1d Undo
nestquest.create_quest_definition yes 1e New
nestquest.update_quest_definition yes 1e sheet Save changes
nestquest.set_quest_definition_active yes 1e row action
nestquest.set_presence_pattern yes 1f presence card
nestquest.create_presence_override yes 1i Save override
nestquest.delete_presence_override yes 1f override row trash-2
nestquest.export_history_csv yes 1g CSV
nestquest.manage_child yes settings

complete_quest payload from the panel:

service: nestquest.complete_quest
data:
  instance_id: 4821
  actor: panel            # kiosk user context
  actor_child_id: 3       # the tapped profile (decision 9)

Every service resolves call.context.user_id against the admin allowlist and fails closed with no user context (D-003). The panel's kiosk user is never allowlisted, so uncomplete_quest is unreachable from the wall even though the card never renders the control.

3. Events the cards listen for

Event Effect
nestquest_quest_completed stamp the seal, re-sort the column, refresh counts
nestquest_quest_uncompleted un-seal, restore the card (admin action, panel must reflect it)
nestquest_quest_missed remove the instance from the panel; add a history row
nestquest_child_day_complete show screen 1c

All four come off the DataUpdateCoordinator; cards should also refresh on state_changed for their sensors so they recover if an event is dropped.

4. Card configuration

# kids' panel, view 1
type: custom:nestquest-party-board-card
weather_entity: weather.home          # optional; dock falls back to date/time
quest_log_path: /nestquest/log        # view the crest tap navigates to
child_order: [declan, jordyn, chloe]

# kids' panel, view 2
type: custom:nestquest-quest-log-card
board_path: /nestquest/board
weather_entity: weather.home          # optional; dock falls back to date/time
idle_return_seconds: 40               # must be shorter than TouchHub Auto-Return
confirm_timeout_seconds: 15
complete_screen_seconds: 12

# parent phone
type: custom:nestquest-admin-card
density: compact                      # compact | roomy
default_tab: today

The quest log reads the selected child from the view's URL/hass path parameter so the board → log hop is a plain Lovelace navigation (decision 6).

5. Data-shape consequences of the design

  1. Instance key is (definition_id, child_id, due_date, window) — the schema's task_instances unique index must widen.
  2. quest_definitions needs an assignees join table, replacing the single child_id column.
  3. quest_definitions needs a windows set (morning/afternoon/evening) plus an optional due time per window.
  4. The materialiser emits one instance per (assignee × window × firing date), still idempotent on the widened key, still only when the child is present.
  5. completion_events gains actor_child_id so a panel completion records which profile was tapped, while actor stays panel.