Auto-discovery slug must match Home Assistant's real slugify (P2 fix) #181

Member

Feature-review finding (P2) remediation — Maestro task 67775be9-6b0d-4839-bbe1-bb8eaefaa5f4 (Feature 20, zero-config panel dashboard).

Done-condition: the household roster's slug matches the entity_id slug Home Assistant actually assigns for a child's display name — HA's real slugify (homeassistant.util.slugify) instead of a hand-rolled Latin-only mirror — so a non-Latin display name yields the same slug the per-child entity_ids use and auto-discovery resolves those children, with a test covering at least one non-Latin name.

Why

sensor._slugify NFKD-normalized and ASCII-encoded-ignoring, so non-Latin characters were DROPPED (京子 → unknown), while HA's real slugifier transliterates through unidecode (京子 → jing_zi, Дана → dana, Zoë → zoe). Per-child entity_ids are derived from the child name by HA's real slugify, so the roster's slugs diverged and the party-board/strategy auto-discovery silently failed for non-Latin households.

What changed

  • custom_components/nestquest/sensor.py: _slugify now delegates to the real homeassistant.util.slugify at runtime and composes the object-id cap (64 - len("sensor.")) the roster needs — verified against HA 2024.6 sources: HA's slugify does NOT truncate (it delegates to python-slugify's frozen legacy pipeline + an unknown sentinel); the ENTITY REGISTRY truncates the full <domain>.<slug> id at MAX_LENGTH_STATE_ENTITY_ID (64), so the roster keeps its own cap and does not double-cap.
  • tests/conftest.py: the mocked homeassistant package now provides a faithful homeassistant.util.slugify stub — python-slugify's legacy pipeline step for step (quotes→dashes, NFKD, transliterate via the real unidecode dev dependency, entity decoding, lowercase, dash folding, separator mapping, unknown sentinel), verified byte-for-byte against real python-slugify (HA's wrapper, separator _) across 52 Latin/Cyrillic/CJK/Greek/fullwidth/entity-reference name shapes.
  • tests/test_sensors.py: existing tests kept; added test_slugify_transliterates_non_latin_names_like_home_assistant (Дана → dana, 京子 → jing_zi, Zoë → zoe) and test_non_latin_child_names_resolve_auto_discovery, which asserts the roster slug equals the slug HA's entity-id derivation (slugify("NestQuest <name> quests due today")) actually embeds for the per-child sensor.
  • pyproject.toml/uv.lock: unidecode added to the DEV group only (test-harness stand-in; the integration's runtime slugify comes from HA itself).

Checks

  • TZ=UTC uv run pytest -q → 1711 passed (baseline 1709 + 2 new tests)
  • TZ=UTC uv run pytest -q tests/test_sensors.py → 26 passed

Task: 67775be9-6b0d-4839-bbe1-bb8eaefaa5f4 — Auto-discovery slug must match Home Assistant's real slugify.

Feature-review finding (P2) remediation — Maestro task `67775be9-6b0d-4839-bbe1-bb8eaefaa5f4` (Feature 20, zero-config panel dashboard). **Done-condition:** the household roster's `slug` matches the entity_id slug Home Assistant actually assigns for a child's display name — HA's real slugify (`homeassistant.util.slugify`) instead of a hand-rolled Latin-only mirror — so a non-Latin display name yields the same slug the per-child entity_ids use and auto-discovery resolves those children, with a test covering at least one non-Latin name. ## Why `sensor._slugify` NFKD-normalized and ASCII-encoded-ignoring, so non-Latin characters were DROPPED (京子 → `unknown`), while HA's real slugifier transliterates through unidecode (京子 → `jing_zi`, Дана → `dana`, Zoë → `zoe`). Per-child entity_ids are derived from the child name by HA's real slugify, so the roster's slugs diverged and the party-board/strategy auto-discovery silently failed for non-Latin households. ## What changed - `custom_components/nestquest/sensor.py`: `_slugify` now delegates to the real `homeassistant.util.slugify` at runtime and composes the object-id cap (`64 - len("sensor.")`) the roster needs — verified against HA 2024.6 sources: HA's slugify does NOT truncate (it delegates to python-slugify's frozen legacy pipeline + an `unknown` sentinel); the ENTITY REGISTRY truncates the full `<domain>.<slug>` id at `MAX_LENGTH_STATE_ENTITY_ID` (64), so the roster keeps its own cap and does not double-cap. - `tests/conftest.py`: the mocked `homeassistant` package now provides a faithful `homeassistant.util.slugify` stub — python-slugify's legacy pipeline step for step (quotes→dashes, NFKD, transliterate via the real `unidecode` dev dependency, entity decoding, lowercase, dash folding, separator mapping, `unknown` sentinel), verified byte-for-byte against real python-slugify (HA's wrapper, separator `_`) across 52 Latin/Cyrillic/CJK/Greek/fullwidth/entity-reference name shapes. - `tests/test_sensors.py`: existing tests kept; added `test_slugify_transliterates_non_latin_names_like_home_assistant` (Дана → `dana`, 京子 → `jing_zi`, Zoë → `zoe`) and `test_non_latin_child_names_resolve_auto_discovery`, which asserts the roster slug equals the slug HA's entity-id derivation (`slugify("NestQuest <name> quests due today")`) actually embeds for the per-child sensor. - `pyproject.toml`/`uv.lock`: `unidecode` added to the DEV group only (test-harness stand-in; the integration's runtime slugify comes from HA itself). ## Checks - `TZ=UTC uv run pytest -q` → **1711 passed** (baseline 1709 + 2 new tests) - `TZ=UTC uv run pytest -q tests/test_sensors.py` → **26 passed** Task: 67775be9-6b0d-4839-bbe1-bb8eaefaa5f4 — Auto-discovery slug must match Home Assistant's real slugify.
dev_agent added 1 commit 2026-09-23 12:13:30 -04:00
The per-child entity ids are derived from the child name by Home
Assistant's real slugifier, which transliterates every script through
unidecode; the hand-rolled Latin-only mirror in sensor.py dropped
non-Latin characters instead (slugging 京子 to "unknown"), so the
roster's slugs diverged from the actual entity ids and the
party-board/strategy auto-discovery silently failed for non-Latin
households.

Use homeassistant.util.slugify at runtime, composing the registry's
64-character entity-id cap the roster needs (verified against HA
2024.6: slugify itself does not truncate; the entity registry
truncates the full <domain>.<slug> id). Give the mock harness a
faithful homeassistant.util.slugify stub — python-slugify's frozen
legacy pipeline with unidecode, verified byte-for-byte against real
python-slugify across Latin, Cyrillic, CJK and Greek name shapes —
and cover the non-Latin resolution contract in tests (roster slug ==
the object id HA's entity-id derivation produces).

Feature-review finding (P2): auto-discovery slug must match Home
Assistant's real slugify.
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 77d1c0feab into feature/3e640c07-2132-46e2-a363-be72ee091291-zero-config-panel-dashboard 2026-09-23 12:21:48 -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#181