Done-condition (controller re-scoped 2026-09-23): The SSE publisher supports the remaining three documented transitions on the same stream: quest-uncompleted, child-day-complete, and quest-missed, with payloads built by the core event builders (add a core quest-missed builder mirroring the documented sweep payload if none exists). child-day-complete is wired into the panel complete route so it is published when a completion clears the childs whole day, carrying quests_due and quests_completed. Tests subscribe to the stream and assert each of the three event types and their documented payload fields.
Changes:
core/events.py: new build_quest_missed_event mirroring the documented sweep payload exactly (reuses _instance_payload and _now_stamp); existing builders untouched.
api/transitions.py (new): reusable publish helpers publish_quest_uncompleted / publish_quest_missed / publish_child_day_complete, each building payloads through the core builders and publishing via the ONE publisher on app.state.publisher.
api/routes_panel.py: on an actual transition the complete route publishes quest-completed first, then evaluates the day-complete rule via publish_child_day_complete using the completed payload and today from the route single clock read (hoisted). No-op re-complete publishes nothing; zero-quest day and non-today instance never fire (core builder rule unchanged).
tests: core key-set test for the missed builder (tests/test_events.py); three new SSE tests (tests/test_api_sse.py) driving uncompleted, day-complete (last quest of day through the panel route) and missed through the real stream; the existing no-op test now drains the day-complete frame Ada single-quest day produces.
Scope per the controller note: quest-uncompleted and quest-missed are published through the reusable API functions the later uncomplete route (da0226b3) and missed sweep will call; wiring them into routes/the sweep is deferred.
Tests (TZ=UTC):
uv run pytest -q: 1612 passed in 9.54s (baseline 1608 + 4 new)
uv run pytest -q tests/test_api_sse.py: 6 passed in 2.07s
Maestro task: 44c93cfd-79f8-4d47-a807-e9b8613992f1
Done-condition (controller re-scoped 2026-09-23): The SSE publisher supports the remaining three documented transitions on the same stream: quest-uncompleted, child-day-complete, and quest-missed, with payloads built by the core event builders (add a core quest-missed builder mirroring the documented sweep payload if none exists). child-day-complete is wired into the panel complete route so it is published when a completion clears the childs whole day, carrying quests_due and quests_completed. Tests subscribe to the stream and assert each of the three event types and their documented payload fields.
Changes:
- core/events.py: new build_quest_missed_event mirroring the documented sweep payload exactly (reuses _instance_payload and _now_stamp); existing builders untouched.
- api/transitions.py (new): reusable publish helpers publish_quest_uncompleted / publish_quest_missed / publish_child_day_complete, each building payloads through the core builders and publishing via the ONE publisher on app.state.publisher.
- api/routes_panel.py: on an actual transition the complete route publishes quest-completed first, then evaluates the day-complete rule via publish_child_day_complete using the completed payload and today from the route single clock read (hoisted). No-op re-complete publishes nothing; zero-quest day and non-today instance never fire (core builder rule unchanged).
- tests: core key-set test for the missed builder (tests/test_events.py); three new SSE tests (tests/test_api_sse.py) driving uncompleted, day-complete (last quest of day through the panel route) and missed through the real stream; the existing no-op test now drains the day-complete frame Ada single-quest day produces.
Scope per the controller note: quest-uncompleted and quest-missed are published through the reusable API functions the later uncomplete route (da0226b3) and missed sweep will call; wiring them into routes/the sweep is deferred.
Tests (TZ=UTC):
- uv run pytest -q: 1612 passed in 9.54s (baseline 1608 + 4 new)
- uv run pytest -q tests/test_api_sse.py: 6 passed in 2.07s
The panel stream so far carried only quest-completed. This adds the
three remaining documented transitions (§3) so the panel UI can react
to reversals, full days, and nightly misses through the same ONE
publisher:
- core/events.py gains build_quest_missed_event, mirroring the
sweep's hand-built payload exactly (shared _instance_payload shape),
so the API plane publishes the same shape the integration sweep fires.
- api/transitions.py adds the reusable publish helpers the later
uncomplete route (da0226b3) and the API-side missed sweep will call;
payloads are always built by the core builders, never hand-built.
- The panel complete route now evaluates the day-complete rule on an
actual transition, off the completed event's payload and the route's
single clock read; the core builder still decides, so a zero-quest
day and a non-today instance never fire it and a no-op re-complete
publishes nothing.
- Tests drive all three transitions through the real SSE stream
(server-loop scheduling for the not-yet-routed helpers) and assert
every documented payload field.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Maestro task: 44c93cfd-79f8-4d47-a807-e9b8613992f1
Done-condition (controller re-scoped 2026-09-23): The SSE publisher supports the remaining three documented transitions on the same stream: quest-uncompleted, child-day-complete, and quest-missed, with payloads built by the core event builders (add a core quest-missed builder mirroring the documented sweep payload if none exists). child-day-complete is wired into the panel complete route so it is published when a completion clears the childs whole day, carrying quests_due and quests_completed. Tests subscribe to the stream and assert each of the three event types and their documented payload fields.
Changes:
Scope per the controller note: quest-uncompleted and quest-missed are published through the reusable API functions the later uncomplete route (da0226b3) and missed sweep will call; wiring them into routes/the sweep is deferred.
Tests (TZ=UTC):
Independent Claude Sonnet 5 review completed for this exact commit.