docs: Design-Spec v1 für What to Wear (WTW) + Projekt-Scaffolding

Brainstorming-Ergebnis der AI-Dev-Method (Phase 0/Design):
- HACS-Custom-Integration what_to_wear, Open-Source, standalone in Kunden-HA
- Kleiderschrank-Inventar (Sub-Entries), Regeln→Anforderungen→Matcher, optionaler LLM-Ton (BYO-Key)
- Wetter v1 aus HA-Wetter-Entität; Open-Meteo/LagerLens/CRUD-Karte = v1.1
- LEDGER inkl. Kritiker-Konsultation (gpt-5.6-luna-pro) zur Wetterquelle

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nora 2026-07-11 20:18:10 +00:00
commit 4d7ef85406
3 changed files with 255 additions and 0 deletions

View file

@ -0,0 +1,157 @@
# What to Wear (WTW) — Design-Spec v1
- **Datum:** 2026-07-11
- **Status:** Entwurf zur Review (Brainstorming-Ergebnis; Keim für den BMAD-PRD)
- **Methode:** AI-Dev-Method (BMAD + adversariale Reviewer-Linsen + KI-Zweitkritiker)
- **Domain / Name:** `what_to_wear` — „What to Wear (WTW)"
---
## 1. Intent (ein Satz)
Eine **quelloffene Home-Assistant-Integration**, die dem Nutzer abends sagt, **welche konkreten
Kleidungsstücke aus seinem Kleiderschrank** er für morgen rauslegen soll — deterministisch aus der
Wetterprognose abgeleitet, optional sprachlich schön formuliert, ausgespielt über Dashboard / Push / Ansage.
## 2. Problem & Zielgruppe
- **Problem:** Morgens Zeitdruck und Fehlgriffe bei der Kleidung; abends fehlt der schnelle Überblick,
was das Wetter *morgen* konkret verlangt (Regen, Frost, Wind, UV) — und was davon man überhaupt besitzt.
- **Zielgruppe:** Home-Assistant-Nutzer (DACH + international), die abends Kleidung vorbereiten —
Pendler, Eltern (Kind anziehen), Menschen mit festem Morgenritual.
- **Vertriebskontext:** Open-Source-HACS-Produkt (Reichweite/Reputation), später Upsell über einen
optionalen LagerLens-Connector (KI-Foto-Katalogisierung der Kleidung).
## 3. Umfang v1 — bewusste Nicht-Ziele (v1.1+)
**In v1:**
- HACS-Custom-Integration `what_to_wear`, Config-Flow, Options-Flow.
- Kleiderschrank-Inventar **nativ** über HA-Sub-Entries (echte Stücke mit Eigenschaften).
- `WeatherProvider`-Interface mit **einer** Implementierung: HA-Wetter-Entität.
- Pipeline: Normalizer → Regel-Engine → Matcher → (optional) LLM-Ton.
- Ausgabe: **Empfehlungs-Sensor** + Service/Event; **read-only Lovelace-Karte**; **2 Blueprints** (Push, TTS).
- Optionaler **LLM-Ton** (Bring-your-own-Key, default AUS).
- i18n **de + en**.
**Bewusst vertagt (v1.1+):**
- LagerLens-Connector als zweite Kleiderschrank-Quelle.
- Open-Meteo als zweiter `WeatherProvider`.
- Schöne CRUD-Verwaltungskarte für den Kleiderschrank (v1: native HA-UI genügt).
- Mehrere Personen/Profile; Aktivitäts-/Kalenderkontext (Termine, „heute Sport"); Wäsche-/Verfügbarkeitsstatus.
## 4. Produktform & Distribution
- Standard-HA-`custom_component` (Python, async), HACS-installierbar; MVP-Struktur:
```
custom_components/what_to_wear/ __init__.py, manifest.json, config_flow.py, coordinator.py,
sensor.py, services.yaml, strings.json, translations/{de,en}.json,
weather/ (provider-interface + ha_entity impl),
logic/ (normalize.py, rules.py, matcher.py, phraser.py)
blueprints/automation/what_to_wear/ notify_push.yaml, announce_tts.yaml
www/what-to-wear-card.js (read-only Lovelace-Karte)
```
- **Lizenz:** Vorschlag **MIT** (offene Kleinentscheidung).
- **Min-HA-Version:** Vorschlag **2024.12+** (für `weather.get_forecasts` mit `return_response=True`
und Config-Sub-Entries) — in der Architektur-Phase gegen die tatsächlich benötigten APIs verifizieren.
- Repo: **lokal** (git `master`), Remote später.
## 5. Architektur — Pipeline & Komponenten
```
WeatherProvider ─▶ ForecastNormalizer ─▶ RulesEngine ─▶ WardrobeMatcher ─▶ (opt.) LLMPhraser
RecommendationSensor ◀───────────────────────────────────┘
(User-Automation via Blueprint) ─▶ Push / TTS / Lovelace-Karte
```
- **WeatherProvider** (Interface `async get_tomorrow_forecast() -> RawForecast`): v1-Impl liest die vom
Nutzer gewählte `weather.*`-Entität via `weather.get_forecasts` (daily + hourly, `return_response=True`).
- **ForecastNormalizer:** RawForecast → **NormalizedForecast** für *morgen* (lokale TZ), interne **SI-Einheiten**,
je Feld ein „vorhanden?"-Flag. Aggregiert stündlich → Tageswerte nach lokalem Datum.
- **RulesEngine:** NormalizedForecast → Liste **Requirement** (Eigenschaft + Grund + Priorität).
- **WardrobeMatcher:** Requirements × Kleiderschrank → gewählte Stücke + Begründung + **Lücken** („keine Regenjacke").
- **LLMPhraser** (optional): formt nur den Text; bei Aus/Fehler → deterministischer Regeltext.
- **DataUpdateCoordinator:** hält das morgige Ergebnis aktuell; Benachrichtigung triggert der Nutzer per Blueprint.
### Invarianten-Spine (Keim für die Architektur-Phase)
- **INV-1 (Nie stumm):** Die Empfehlung fällt nie aus. Bei Teil-Ausfall (LLM, fehlendes Wetterfeld, leerer
Schrank) liefert der deterministische Kern trotzdem eine Empfehlung und **benennt die Lücke**.
- **INV-2 (Morgen lokal):** „Morgen" ist stets das lokale Kalenderdatum in `hass.config.time_zone` (DST-fest).
- **INV-3 (SI intern):** Interne Berechnung nur im SI-Normmodell; Quelle/Einheit/Missingness bleiben am Datum
erhalten; Werte werden **nie** aus Feldname oder Größenordnung geraten.
- **INV-4 (Geheimnisse):** LLM-Key (später LagerLens-Token) nie im Klartext in Logs/State/Attributen; nur im
HA-Config-Storage.
- **INV-5 (Keine stille Netzlast):** v1 spricht nur mit HA selbst. Externe Provider (v1.1) nur opt-in, mit
Coordinator/Timeout/Backoff/Attribution; kein stiller Provider-Wechsel.
- **INV-6 (Trennung):** Normalize / Rules / Matcher sind strikt getrennt und je einzeln testbar.
## 6. Datenmodell
- **Kleidungsstück (Sub-Entry):** `name`, `kategorie` (z. B. Jacke/Pullover/Hose/Schuhe/Accessoire/Kopf/Hand),
`waerme` 15, `wasserdicht` bool, `winddicht` bool, `formalitaet` (leger/business), `saison`/Temp-Range
(optional), `foto` (optional), `aktiv` bool.
- **NormalizedForecast (morgen):** `temp_min`, `temp_max`, `temp_gefuehlt_min/max` (°C), `regen_wkt` (%),
`regen_menge` (mm), `wind` / `boeen` (km/h), `uv_index`, `zustand` (klar/bewölkt/Regen/Schnee/Gewitter) —
**jeweils mit `vorhanden`-Flag** + Herkunft/Zeitstempel.
- **Requirement:** `eigenschaft` (z. B. `wasserdichte_aussenschicht`, `waerme_min:4`, `sonnenschutz`,
`handschuhe`, `muetze`), `grund` (menschlesbar), `prioritaet` (muss/soll/kann).
- **Recommendation:** `kurztext` (Sensor-State), `stuecke[]`, `requirements[]`, `luecken[]`, `kennwerte`, `quelle`.
## 7. Regel-Engine (illustrative Schwellwerte — final in PRD/Architektur)
> Beispielhaft, konfigurierbar; **nicht** endgültig. Kälteempfinden-Offset verschiebt Temperaturschwellen.
- `temp_gefuehlt_max < 0 °C``waerme_min:5`, `muetze`, `handschuhe`, `schal`.
- `08 °C``waerme_min:4`; `815 °C``waerme_min:3`; `1522 °C``waerme_min:2`; `> 22 °C``waerme_min:1`, ggf. `sonnenschutz`.
- `regen_wkt ≥ 40 %` **oder** `regen_menge ≥ 1 mm``wasserdichte_aussenschicht`, `feste_schuhe`.
- `boeen ≥ 40 km/h``winddicht`.
- `uv_index ≥ 6``sonnenschutz` (Brille/Kopfbedeckung).
- `zustand = Schnee``waerme_min:4`, `wasserdicht`, `profilsohle`.
## 8. Matcher
- Wählt je Requirement das am besten passende **aktive** Stück (Priorität muss > soll > kann; bei Gleichstand
nächstpassende Wärme/Formalität).
- Fehlt ein Stück für ein `muss`/`soll`-Requirement → **Lücke** in `luecken[]` (z. B. „Für morgen wäre eine
Regenjacke ideal — keine im Schrank hinterlegt.").
- Ergebnis ist erklärbar: jedes Stück trägt seinen Grund (welches Requirement es erfüllt).
## 9. LLM-Ton (optional, Bring-your-own-Key)
- Default **AUS**. Nutzer trägt eigenen Key (OpenAI/Anthropic) im Options-Flow ein → nur im Config-Storage.
- Eingabe an das LLM: die **strukturierte** Recommendation (Stücke + Gründe + Kennwerte) + Zielsprache.
Aufgabe: nur **umformulieren**, keine neuen Fakten, keine geänderte Stückauswahl.
- **Fehler/Timeout/kein Key → deterministischer Regeltext** (INV-1). LLM ändert nie die Auswahl.
## 10. Ausgabe: Sensor / Service / Karte / Blueprints
- **Sensor** `sensor.what_to_wear`: `state` = Kurzempfehlung; `attributes` = `stuecke`, `requirements`,
`luecken`, `kennwerte`, `quelle`, `stand`.
- **Service/Event** `what_to_wear.recommend` (manuelles Neuberechnen; feuert Event mit dem Ergebnis).
- **Lovelace-Karte** (read-only): zeigt morgige Empfehlung + Stücke + Lücken dauerhaft.
- **Blueprints:** `notify_push` (Nutzer wählt notify-Ziel + Uhrzeit), `announce_tts` (Nutzer wählt
media_player + Auslöser). Import ist ein geführter HA-Klick-Flow → laienfreundlich, ohne notify-Logik
in der Integration.
## 11. Konfiguration
- **Config-Flow (Ersteinrichtung):** Wetter-Entität wählen (Entity-Selector, Pflicht; Fehler wenn keine da),
Sprache (Default = HA-Sprache), Kälteempfinden-Offset.
- **Options-Flow:** Schwellwerte/Offsets, optionaler LLM-Key + Provider (default aus).
- **Sub-Entries:** Kleidungsstücke anlegen/bearbeiten/löschen in der nativen HA-UI.
## 12. Fehlerbehandlung & Edge Cases (aus dem Kritiker-Review)
- Keine geeignete `weather.*`-Entität → klarer Config-Fehler, kein Raten (INV-1/Config).
- Wetterfeld fehlt → Regel greift **degradiert** + Hinweis; „fehlend" ≠ „0" (INV-3).
- „Morgen"/DST strikt in lokaler TZ (INV-2).
- LLM-Fehler/Timeout/kein Key → Fallback auf Regeltext (INV-1).
- Leerer/lückenhafter Schrank → Anforderung + Lücke nennen statt schweigen (INV-1).
- Einheiten (°C/°F, km/h/mph, mm/inch) bewusst konvertieren; Open-Meteo-Wettercode ↔ HA-`condition` per Mapping-Tabelle (v1.1).
## 13. i18n
- HA-Translations für UI (`de`, `en`); Empfehlungstext folgt der HA-Sprache; Regeltext-Bausteine je Sprache.
## 14. Tests & echte Verifikation (Methoden-Pflicht)
- **Unit:** Normalizer/Rules/Matcher mit Wetter-Fixtures (Regen, Frost, Hitze, DST-Tag, fehlende Felder, leerer Schrank).
- **Integration:** `pytest-homeassistant-custom-component` (Config-Flow, Sensor, Service).
- **Echte E2E:** Wegwerf-HA-Docker-Instanz — Integration installieren → Wetter-Entität + Beispielschrank →
Sensor prüfen → Blueprint-Push real auslösen. Negativfälle (keine Wetter-Entität, LLM-Key falsch).
- **TDD:** Test rot → Code → grün → volle Suite → Commit (ein Commit pro Story). qwen/Cloud-Review nach jeder Story.
## 15. Offene Punkte / Annahmen (in PRD/Architektur klären)
- Lizenz (Vorschlag MIT). Min-HA-Version (Vorschlag 2024.12+, gegen APIs verifizieren).
- Ob v1 die Sub-Entry-CRUD-UX von HA praktisch trägt (sonst früher CRUD-Karte).
- Genaue Schwellwerte/Regeln (Kap. 7 illustrativ).
- Foto-Speicherung bei nativem Kleiderschrank (Pfad/Umfang) — v1 optional/minimal.
## 16. Roadmap v1.1+
LagerLens-Connector (Foto-Katalog) · Open-Meteo-Provider · CRUD-Verwaltungskarte · Mehrpersonen-Profile ·
Aktivitäts-/Kalenderkontext · Wäsche-/Verfügbarkeitsstatus.