From 4d7ef85406e98846e1c6612a640f0ec3b3fba5b6 Mon Sep 17 00:00:00 2001 From: Nora Date: Sat, 11 Jul 2026 20:18:10 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20Design-Spec=20v1=20f=C3=BCr=20What=20to?= =?UTF-8?q?=20Wear=20(WTW)=20+=20Projekt-Scaffolding?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .gitignore | 29 ++++ LEDGER.md | 69 ++++++++ .../specs/2026-07-11-what-to-wear-design.md | 157 ++++++++++++++++++ 3 files changed, 255 insertions(+) create mode 100644 .gitignore create mode 100644 LEDGER.md create mode 100644 docs/superpowers/specs/2026-07-11-what-to-wear-design.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9c6f5e1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +# Python / HA custom component +__pycache__/ +*.py[cod] +.venv/ +venv/ +*.egg-info/ +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ + +# HA test instance artifacts +test-ha-config/.storage/ +test-ha-config/*.log +test-ha-config/*.db* + +# Node / Lovelace-Karte (Build) +node_modules/ +dist/ + +# Secrets / lokale Umgebung — niemals committen +.env +*.env.local +secrets.yaml + +# OS / Editor +.DS_Store +*.swp +.idea/ +.vscode/ diff --git a/LEDGER.md b/LEDGER.md new file mode 100644 index 0000000..cf7c009 --- /dev/null +++ b/LEDGER.md @@ -0,0 +1,69 @@ +# Fortschritts-Ledger — What to Wear (WTW) + +> Methode: **AI-Dev-Method** (BMAD + adversariale Reviewer-Linsen + KI-Zweitkritiker qwen/Cloud). +> Quelle der Methode: `/root/.claude/method/DEV-METHOD.md` (v1.1) bzw. Repo `Kenearos/ai-dev-method`. +> Dieses Ledger überlebt Kontext-Kompaktierung: erledigte Stories, offene Punkte, Gate-Ergebnisse +> (inkl. je Kritiker-Aufruf geschickter Dateien + Modell), Finding-Urteile. + +**Stand:** 2026-07-11 · **Phase:** 0/2 (Intent & Design abgeschlossen → PRD offen) + +--- + +## Umgebung (für spätere Sessions wichtig) +- Bash läuft als **`openclaw`** (uid 1000), **kein passwortloses sudo**. `/root/Labor` gehört `root`; + Projektordner `/root/Labor/what-to-wear` wurde einmalig per sudo an `openclaw` übereignet. +- **qwen-Kritiker** nur über Tailscale erreichbar, wenn der Windows-Desktop (100.64.0.2) an ist + (am 2026-07-11 erreichbar). Fällt er aus → Cloud-Eskalation `openai/gpt-5.6-luna-pro` via OpenRouter + (`QWEN_MAXTOK=16000 QWEN_REASONING=medium` Pflicht). Tool: `/root/.claude/tools/qwen.mjs`. +- Repo: **lokal** (git `master`), noch kein Remote. Ziel-Remote später zu entscheiden (Forgejo vs. neues GitHub). + +## Phase 0 — Intent +**Produkt:** Quelloffene **Home-Assistant-Integration** (`what_to_wear`, HACS), die abends sagt, welche +**konkreten Kleidungsstücke aus dem Kleiderschrank** man für morgen rauslegen soll — deterministisch aus +der Wetterprognose, optional sprachlich schön formuliert, ausgespielt über Dashboard/Push/Ansage. +**Vertriebsprodukt** (läuft in jeder Kunden-HA, nicht bei uns). + +## Design-Entscheidungen (Phase 0/Brainstorm, vom Benutzer freigegeben) +1. Form: Open-Source **HACS-Custom-Integration** `what_to_wear`, standalone in jeder Kunden-HA. Kein Vendor-Cloud. +2. Monetarisierung: **kostenlos/Open-Source** (Reichweite/Reputation, späterer Upsell via LagerLens). +3. Kleiderschrank: **Inventar echter Stücke** (nicht nur Kategorien), v1 nativ über **HA-Sub-Entries**. +4. LagerLens: **Vision C** — Standalone-Kern + **optionaler** LagerLens-Connector (v1.1), nicht Pflicht. +5. Logik: **Hybrid** — Regeln bestimmen *was*, optionaler **LLM** (Bring-your-own-Key, default AUS) den *Ton*. +6. Wetterquelle v1: **HA-Wetter-Entität** via `weather.get_forecasts`; Open-Meteo als Zweit-Provider v1.1. +7. Ausgabe: **Sensor + Service/Event**, read-only **Lovelace-Karte**, **2 Blueprints** (Push, TTS) — alle 3 Kanäle. +8. Sprache: **de + en**. +9. Name: **What to Wear (WTW)**, Domain `what_to_wear`. + +## Kritiker-Konsultationen +### K1 — Wetterquelle (Design-Entscheidung), 2026-07-11 +- **Modell:** `openai/gpt-5.6-luna-pro` (Cloud-Eskalation; vom Benutzer ausdrücklich erlaubt, da nuancierte + HA-Architekturfrage). **Geschickte Datei:** `scratchpad/wetterquelle-briefing.md`. Laufzeit 43 s, 10 Findings. +- **Mein Urteil:** alle 10 nach eigener Prüfung **berechtigt** (kein Fehlalarm; starkes Modell). +- **Kern-Findings → übernommen ins Design:** + - [KRITISCH] HA hat nicht zwingend eine Wetter-Entität → Config-Flow-Auswahl + klarer Fehlerzustand. + - [KRITISCH] `weather.get_forecasts` liefert kein einheitlich reiches Schema (`return_response=True`, + HA-Mindestversion; UV/gefühlt/Böen/Regen-Wkt. oft fehlend) → bewusste Normalisierung, „fehlend ≠ 0". + - [HOCH] Kein stiller Feld-Fallback zwischen Providern → Provider stabil pro Konfiguration. + - [HOCH] Open-Meteo nicht pauschal „kostenlos/kommerziell frei" + Koordinaten an Dritte → Opt-in + + Attribution + Coordinator/Timeout/Backoff (deshalb v1.1, nicht v1-Default). + - [HOCH] „Morgen" = lokales Kalenderdatum in `config.time_zone` (DST 23/25 h), nie `now+24h`. + - [HOCH] Einheiten mehr als °C/°F → festes SI-Internmodell, Werte nie aus Feldname/Größenordnung raten. + - [MITTEL] Provider-Interface = ok; automatisch-fehlertoleranter Open-Meteo-Zweig = Over-Engineering für v1. +- **Konsequenz:** v1 = nur HA-Wetter-Entität hinter kleinem `WeatherProvider`-Interface; Open-Meteo v1.1. + +## Gates (Status) +| Gate | Gegenstand | Modell | Datei(en) | Status | +|---|---|---|---|---| +| — | Wetterquelle (Design) | luna-pro | wetterquelle-briefing.md | ✅ verifiziert | +| Gate 1 | PRD | qwen/luna | — | offen | +| Gate 2 | Architektur | qwen/luna | — | offen | +| Gate 3 | Code (Security) | qwen/luna | — | offen | + +## Stories +- (noch keine — folgen nach PRD + Architektur + Epics/Stories) + +## Offene Punkte / nächste Schritte +- Benutzer-Review des Specs (`docs/superpowers/specs/2026-07-11-what-to-wear-design.md`). +- Danach DEV-METHOD-Kanal: **BMAD-Installation** (`npx bmad-method install … --directory /root/Labor/what-to-wear`, + legt Verzeichnisse an → Benutzer-OK), dann PRD → adversariale Linsen → **qwen-Gate 1**. +- Kleinentscheidungen offen: Lizenz (Vorschlag MIT), Min-HA-Version (Vorschlag 2024.12+). diff --git a/docs/superpowers/specs/2026-07-11-what-to-wear-design.md b/docs/superpowers/specs/2026-07-11-what-to-wear-design.md new file mode 100644 index 0000000..8f43d38 --- /dev/null +++ b/docs/superpowers/specs/2026-07-11-what-to-wear-design.md @@ -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` 1–5, `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`. +- `0–8 °C` → `waerme_min:4`; `8–15 °C` → `waerme_min:3`; `15–22 °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.