feat(2.5): Blueprints Push & TTS — Epic 2 komplett

Story 2.5 (deklaratives Artefakt, Struktur-Validierung, Suite gruen 130/130):
- blueprints/automation/what_to_wear/notify_push.yaml: device(mobile_app)+time+
  boolean, Bedingung changed/gaps_count/alert, notify.mobile_app_ via slugify.
- announce_tts.yaml: tts+media_player+trigger-Selector, tts.speak.
- Beide: what_to_wear.recommend via response_variable, rec.llm_text || full_text,
  min_version 2025.3.0, gehaertete Templates (.get()+Defaults), continue_on_error.
- luna-pro-Story-Review: 5/6 Findings uebernommen, 1 verworfen (flat-response-Evidenz).

Epic 2 (15-Minuten-Wow) komplett: Kleiderschrank->Karte->Service->Push/TTS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nora 2026-07-13 14:55:01 +00:00
parent dc941a127f
commit 8effa251cf
5 changed files with 186 additions and 5 deletions

View file

@ -21,17 +21,16 @@ async def _unload_wtw_entries(request):
"""Unload any What to Wear entries after each hass test.
This cancels the coordinator's periodic refresh timer so it never lingers
into a following test under randomized ordering.
into a following test under randomized ordering. Only runs for tests that
actually use the ``hass`` fixture; guarded so pure-logic tests are untouched.
"""
yield
if "hass" not in request.fixturenames:
return
from homeassistant.config_entries import ConfigEntryState
from custom_components.what_to_wear.const import DOMAIN
hass = request.getfixturevalue("hass")
for entry in list(hass.config_entries.async_entries(DOMAIN)):
for entry in list(hass.config_entries.async_entries("what_to_wear")):
if entry.state is ConfigEntryState.LOADED:
await hass.config_entries.async_unload(entry.entry_id)
await hass.async_block_till_done()