- Point recurrence purity scan at custom_components.nestquest.core.recurrence
(P2.1); the shim only re-exports, so the real model was no longer scanned.
- Make test_const/test_config_flow/test_dao_matrix module scans recursive
(rglob) so custom_components/nestquest/core/ is covered (P2.2, P2.3);
const.py name exclusion retained.
- Add test_core_isolation: AST-scan every core module for homeassistant
imports, relative imports climbing out of core (level > 1), absolute
imports reaching custom_components.nestquest.<not core>, and bare
'import core'/'from core' (P2.4).
- Drop the private re-export of _month_end/_nth_weekday_of_month from the
recurrence shim; those are test-only, so move the two test imports to
custom_components.nestquest.core.recurrence (P2.1/P3.1).
- Fix shim docstrings and core/__init__.py to reference
custom_components.nestquest.core.* instead of the unimportable 'core.*'
paths (P3.2).
- Note the migrations logger namespace move to
custom_components.nestquest.core.migrations in RELEASE_NOTES.md (P3.3).
HACS and the manual install copy only custom_components/nestquest, so
the integration shipped with a top-level 'core' package that was never
deployed and failed with ModuleNotFoundError: No module named 'core'.
Move core/ into custom_components/nestquest/core/, repoint the
re-export shims to relative '.core.X' imports, and update tests
(import paths, monkeypatch targets, caplog logger) to the new
'custom_components.nestquest.core.X' location. The integration is now
self-contained: nothing under custom_components/nestquest reaches
outside its own tree, the migrations logger becomes
custom_components.nestquest.core.migrations, and the SQL-leak guard
allowlists point at the new core/ paths.
uv run pytest -q: 1496 passed.
- ChildrenDao.reorder now requires a COMPLETE permutation of the
children table: partial lists (missing an existing child), unknown
ids and duplicates are rejected with ValueError before any write,
inside the existing transaction and connection lock (check and
write atomic). Empty list is the maximally partial reorder against
a non-empty table; against an empty table it stays a no-op. The two
DAO tests that encoded the old permissive semantics (silent no-op
on empty/unknown) are updated to the new contract.
- children.py gains reorder_children: the Feature 09-facing wrapper,
which additionally rejects non-integer ids up front (bools and
floats would silently compare against stored integer ids at the SQL
layer).
- Business tests: round-trip (active list returns new order), partial/
unknown/duplicate/non-int rejections with order-unchanged proofs,
empty-list rejection, and inactive children keeping positions in a
whole-table permutation. Suite: 866 passed.