Re-export shims at the original paths keep the integration working unchanged (from .core.<name> import *).
core/events.py — payload construction only
Refactored to build and RETURN (event_type, payload) tuples; it never touches hass.bus or hass.config. The HA-local today the day-complete rule needs is now a parameter, read from hass.config.time_zone by the integration shim. The events.py shim retains fire_quest_completed/fire_quest_uncompleted, wiring the returned events to hass.bus.async_fire so the four event names and payload shapes stay identical:
Core isolation test (test_core_isolation.py) covers the new files automatically (its scan is rglob over core/).
No homeassistant import under custom_components/nestquest/core/ (AST).
No file under custom_components/nestquest/ imports a top-level core (level=0).
No repo-root core/.
Updated two test logger-name references (children now logs as ...core.children) and the materialize _now_stamp monkeypatch target (now patches the core module the walk reads globals from).
Extracts the engines and business layer into `custom_components/nestquest/core/` (task 510c1f78).
## What
- Moves `presence.py`, `materialize.py`, `completion.py`, `events.py`, `children.py`, `quest_definitions.py`, `admin_allowlist.py`, `service_policy.py` into `core/`.
- Re-export shims at the original paths keep the integration working unchanged (`from .core.<name> import *`).
## core/events.py — payload construction only
Refactored to build and RETURN `(event_type, payload)` tuples; it never touches `hass.bus` or `hass.config`. The HA-local `today` the day-complete rule needs is now a parameter, read from `hass.config.time_zone` by the integration shim. The `events.py` shim retains `fire_quest_completed`/`fire_quest_uncompleted`, wiring the returned events to `hass.bus.async_fire` so the four event names and payload shapes stay identical:
- `nestquest_quest_completed` (+ `was_on_time`)
- `nestquest_quest_uncompleted`
- `nestquest_child_day_complete` (+ `quests_due`/`quests_completed`)
- `occurred_at` strict UTC ISO-8601
## Verification
- `uv run pytest -q` green: **1497 passed** (baseline).
- Core isolation test (`test_core_isolation.py`) covers the new files automatically (its scan is `rglob` over `core/`).
- No `homeassistant` import under `custom_components/nestquest/core/` (AST).
- No file under `custom_components/nestquest/` imports a top-level `core` (level=0).
- No repo-root `core/`.
- Updated two test logger-name references (`children` now logs as `...core.children`) and the materialize `_now_stamp` monkeypatch target (now patches the core module the walk reads globals from).
Done-condition met: `core/` additionally contains `presence.py`, `materialize.py`, `completion.py`, `events.py`, `children.py`, `quest_definitions.py`, `admin_allowlist.py`, `service_policy.py`.
Move presence.py, materialize.py, completion.py, events.py, children.py,
quest_definitions.py, admin_allowlist.py and service_policy.py into
custom_components/nestquest/core/, leaving re-export shims at the
original paths so the integration keeps working unchanged.
core/events.py is refactored to PAYLOAD CONSTRUCTION ONLY: it builds
and returns (event_type, payload) tuples and never touches hass.bus or
hass.config. The HA-local 'today' the day-complete rule needs is now a
parameter (read from hass.config.time_zone by the integration shim).
The events.py shim retains fire_quest_completed/fire_quest_uncompleted,
wiring the returned events to hass.bus.async_fire so the four event
names and payload shapes stay identical (nestquest_quest_completed with
was_on_time, nestquest_quest_uncompleted, nestquest_child_day_complete
with quests_due/quests_completed, occurred_at strict UTC ISO-8601).
Update two test logger-name references (children now logs as
...core.children) and the materialize _now_stamp monkeypatch target
(now patches the core module the walk reads globals from).
1497 passed (baseline). No homeassistant import under core/, no
top-level core import under the integration, no repo-root core/.
P2.1: Point test_presence.py ISO-week scan at core.presence (the real
model since task 510c1f78); the integration's presence.py is now a
re-export shim, so scanning it was vacuous.
P2.2: Add direct core-builder unit tests to test_events.py — exact
payload key sets for completed/uncompleted/day-complete events,
was_on_time threading (True/False/None), event ordering (completed
fires before day-complete on the bus), and the four day-complete
outcomes (zero-quest day, non-today instance, partial day,
fully-cleared today). Add a shim timezone test that sets
hass.config.time_zone to a zone whose local date differs from UTC and
asserts the day-complete rule uses that local date.
P3.1: Split build_quest_completed_events into
build_quest_completed_event (single event, no day-complete state) and
build_child_day_complete_event (separate, returns the day-complete
event or None). The shim fires nestquest_quest_completed BEFORE it
reads the HA-local today and evaluates the day-complete rule,
restoring the pre-extraction ordering so a failure in the day-complete
DB reads or the ZoneInfo lookup cannot suppress the completed event.
Payloads and the day-complete rule are identical.
P3.2: test_startup_db.py glob -> rglob so core/ is scanned by the
'never unlinks or truncates DB files' guardrail (non-recursive glob
skipped the extracted core package).
P3.3: RELEASE_NOTES.md notes the children and admin_allowlist loggers
moved to .core.children / .core.admin_allowlist (parent logger still
catches them).
P3.4: Refresh the stale test_core_isolation.py docstring to cover the
whole core package (storage-layer task d0b691d8 + engines/business-
layer task 510c1f78).
uv run pytest -q = 1507 passed (baseline 1497 + 10 new).
dev_agent
merged commit 315010b901 into feature/a9513378-856c-4ced-8722-c99850d3a524-domain-core-extraction2026-09-21 15:07:51 -04:00
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.
Extracts the engines and business layer into
custom_components/nestquest/core/(task 510c1f78).What
presence.py,materialize.py,completion.py,events.py,children.py,quest_definitions.py,admin_allowlist.py,service_policy.pyintocore/.from .core.<name> import *).core/events.py — payload construction only
Refactored to build and RETURN
(event_type, payload)tuples; it never toucheshass.busorhass.config. The HA-localtodaythe day-complete rule needs is now a parameter, read fromhass.config.time_zoneby the integration shim. Theevents.pyshim retainsfire_quest_completed/fire_quest_uncompleted, wiring the returned events tohass.bus.async_fireso the four event names and payload shapes stay identical:nestquest_quest_completed(+was_on_time)nestquest_quest_uncompletednestquest_child_day_complete(+quests_due/quests_completed)occurred_atstrict UTC ISO-8601Verification
uv run pytest -qgreen: 1497 passed (baseline).test_core_isolation.py) covers the new files automatically (its scan isrglobovercore/).homeassistantimport undercustom_components/nestquest/core/(AST).custom_components/nestquest/imports a top-levelcore(level=0).core/.childrennow logs as...core.children) and the materialize_now_stampmonkeypatch target (now patches the core module the walk reads globals from).Done-condition met:
core/additionally containspresence.py,materialize.py,completion.py,events.py,children.py,quest_definitions.py,admin_allowlist.py,service_policy.py.