CONTROL-001: add safe HA automation handoff
Some checks failed
quality / test (3.11) (push) Has been cancelled
quality / test (3.13) (push) Has been cancelled

This commit is contained in:
2026-06-14 16:21:57 +02:00
parent 77f328c4a8
commit b3cf68eade
25 changed files with 1083 additions and 69 deletions

73
docs/BEHAVIOR_ENGINE.md Normal file
View File

@@ -0,0 +1,73 @@
# Verhaltensmodell und Berechnung
## Datenfluss
1. Nutzer wählt einen Aktor.
2. `ActuatorReconciliationService` ordnet Kontext-Entities zu.
3. `BehaviorEngine.train()` liest Aktor- und Kontexthistorie.
4. Aktor-Zustandswechsel werden als `BehaviorPattern` gespeichert.
5. `BehaviorEngine.evaluate()` vergleicht aktuelle Zustände mit den Mustern.
6. Shadow zeigt nur die Vorhersage. Active darf sie ausführen.
## Herkunft und Gewicht
- HA-Benutzer: `source=user`, Gewicht `1.0`
- eindeutig erkannte HA-Automation oder Script: `source=automation`, Gewicht `1.0`
- physisch oder unbekannt: `source=physical_or_unknown`, Gewicht `0.7`
- eigene SillyHome-Ausführung: wird verworfen
Manuelle und eindeutig automatisierte Handlungen zählen für die Freigabe.
## Kausale Muster
Wechselt ein Kontextsensor höchstens drei Sekunden vor der Aktorhandlung, wird
der Wechsel gespeichert:
```text
binary_sensor.tuer: off -> on
light.raum: off -> on
```
Eine kausale Vorhersage gilt nur, wenn derselbe Kontextzustand frisch ist. Das
Standardfenster ist zweimal `SILLYHOME_PREDICTION_INTERVAL_SECONDS`.
## Nicht-kausale Bewertung
Für Muster ohne frischen Trigger:
```text
score = weight * (
0.45 * time_score
+ 0.45 * context_score
+ 0.10 * weekday_score
)
```
Die Confidence ist der mittlere Score, begrenzt durch die Mindestunterstützung:
```text
confidence = mean(scores) * min(1, support / min_behavior_actions)
```
## Ausführungsbedingungen
Eine Vorhersage wird nur ausgeführt, wenn alle Bedingungen erfüllt sind:
- Betriebsart `active`
- Confidence mindestens `SILLYHOME_PREDICTION_CONFIDENCE`
- Zielzustand ist noch nicht erreicht
- Domain und Zustand sind erlaubt
- Cooldown erlaubt die Aktion
Der Cooldown sperrt nur eine schnelle Wiederholung desselben Zielzustands.
Eine Gegenaktion, beispielsweise `on` gefolgt von `off`, bleibt sofort erlaubt.
## Freigabe
`activation_ready=true`, wenn:
- Verhaltensstatus `trained`
- mindestens `SILLYHOME_MIN_BEHAVIOR_ACTIONS` eindeutig zugeordnete manuelle
oder automatisierte Handlungen vorhanden sind
Die UI zeigt `activation_reason` immer an.

47
docs/CONTROL_HANDOFF.md Normal file
View File

@@ -0,0 +1,47 @@
# Übergabe zwischen SillyHome und HA-Automationen
## Erkennung
SillyHome liest aktive `automation.*`-Entities, lädt deren Konfiguration über
die Home-Assistant-API und sucht darin nach der exakten Aktor-Entity-ID.
Namensähnlichkeit allein reicht nicht.
## Betriebsarten
### Shadow
- SillyHome lernt und prognostiziert.
- SillyHome schaltet nicht.
- HA-Automationen können normal weiterlaufen.
### Active parallel
- SillyHome darf schalten.
- Passende HA-Automationen bleiben aktiv.
- Diese Betriebsart kann doppelte Auslöser verursachen und ist nur für Tests.
### Active mit Übernahme
- SillyHome wird zuerst aktiviert.
- Danach werden aktuell aktive, passend erkannte HA-Automationen pausiert.
- Nur erfolgreich pausierte Automationen werden für eine spätere
Wiederherstellung gespeichert.
- Scheitert die Pause, fällt SillyHome auf Shadow zurück und stellt bereits
pausierte Automationen wieder her.
## Stoppen
Zwei bewusste Optionen:
- SillyHome stoppen und pausierte HA-Automationen fortsetzen.
- SillyHome stoppen und HA-Automationen pausiert lassen.
Einzelne passende Automationen können im Dashboard jederzeit pausiert oder
fortgesetzt werden.
In Home Assistant bedeutet:
```text
automation.turn_off = pausieren/deaktivieren
automation.turn_on = fortsetzen/aktivieren
```

63
docs/DEBUGGING.md Normal file
View File

@@ -0,0 +1,63 @@
# Debugging
## Vorhersage korrekt, aber keine Ausführung
1. Aktor-Details öffnen.
2. `Betriebsart` prüfen.
3. `Freigabestatus` prüfen.
4. Text hinter der Vorhersage lesen. `execution_reason` nennt exakt:
- Shadow-Modus
- Confidence unter Schaltschwelle
- Zielzustand bereits erreicht
- Cooldown aktiv
- ausgeführt
5. Live-Zustand des Aktors und Triggers in HA prüfen.
6. Add-on-Logs prüfen.
## Weder SillyHome noch HA-Automation schaltet
1. SillyHome-Modus prüfen.
2. Unter `Passende Home-Assistant-Automationen` den Zustand prüfen.
3. Bei Shadow mindestens eine gewünschte HA-Automation fortsetzen.
4. Bei Active mit Übernahme müssen die passenden HA-Automationen pausiert sein.
## Freigabe fehlt
Die UI zeigt den Grund immer als `activation_reason`.
Prüfen:
```text
behavior.status
behavior.sample_count
behavior.high_confidence_sample_count
behavior.activation_ready
behavior.activation_reason
```
## Entität fehlt in der Liste
Den vollständigen Entitätsnamen direkt eingeben. Der Server akzeptiert nur
existierende, unterstützte Aktoren. Ein unbekannter Name liefert `404`.
## Standarddiagnose lokal
```bash
.venv/bin/pytest tests/behavior/test_engine.py -q
.venv/bin/pytest tests/api/test_actuators.py -q
.venv/bin/ruff check app tests
.venv/bin/mypy app backend tests
```
## Standarddiagnose im HA-Add-on
```bash
ha apps info 58adbe1e_sillyhome_next
ha apps logs 58adbe1e_sillyhome_next
```
Health aus einem Add-on mit Zugriff auf das interne Netz:
```bash
wget -qO- http://58adbe1e-sillyhome-next:8000/health
```

87
docs/OPERATIONS.md Normal file
View File

@@ -0,0 +1,87 @@
# Entwicklung, Release und Betrieb
## Lokales Setup
```bash
python3 -m venv .venv
.venv/bin/pip install -e '.[dev]'
cp .env.example .env
.venv/bin/uvicorn app.main:app --reload
```
`SILLYHOME_HA_URL` und `SILLYHOME_HA_TOKEN` nur lokal in `.env` setzen.
## Qualitätsprüfung
```bash
.venv/bin/pytest -q
.venv/bin/ruff check .
.venv/bin/mypy app backend tests
git diff --check
```
## Release
1. Version in allen vier Stellen ändern:
`pyproject.toml`, `addon/config.yaml`, `app/main.py`, `CHANGELOG.md`.
2. Qualitätsprüfung ausführen.
3. Feature-Branch committen und pushen.
4. Pull Request nach `main` erstellen und mergen.
5. Annotiertes Tag auf dem Merge-Commit erstellen.
6. Gitea-Release aus demselben Tag erstellen.
Beispiel:
```bash
git tag -a v0.7.0 -m 'SillyHome Next 0.7.0'
git push origin v0.7.0
```
## Home-Assistant-Update
Vorher Teil-Backup des Add-ons erstellen. Danach:
```bash
ha store reload
ha apps info 58adbe1e_sillyhome_next
ha apps update 58adbe1e_sillyhome_next
ha apps info 58adbe1e_sillyhome_next
ha apps logs 58adbe1e_sillyhome_next
```
Kein Home-Assistant-Neustart ist erforderlich.
## Live-Verifikation
Pflicht:
```bash
wget -qO- http://58adbe1e-sillyhome-next:8000/health
wget -qO- http://58adbe1e-sillyhome-next:8000/v1/actuators
```
Für einen Aktor prüfen:
- `behavior.mode`
- `behavior.activation_ready`
- `behavior.activation_reason`
- `behavior.related_automations`
- `behavior.paused_automation_entity_ids`
- `behavior.prediction.execution_reason`
Bei einer Übernahme testen:
1. Passende HA-Automation ist vorher `on`.
2. SillyHome übernimmt.
3. SillyHome ist `active`.
4. Passende HA-Automation ist `off`.
5. Trigger erzeugt erwartete Aktoraktion.
6. Gegenaktion wird trotz Cooldown ausgeführt.
7. SillyHome stoppen und Automationen fortsetzen.
8. SillyHome ist `shadow`, HA-Automation wieder `on`.
## Rollback
Bevorzugt das vor dem Update erstellte HA-Teil-Backup wiederherstellen.
Alternativ vorherige Git-Version in `addon/config.yaml` veröffentlichen und das
Add-on erneut aktualisieren.

View File

@@ -205,12 +205,44 @@ Shadow-Modus wird niemals geschaltet.
### `POST /v1/actuators/{actuator_entity_id}/activation`
```json
{"active": true}
{
"active": true,
"pause_matching_automations": true,
"restore_paused_automations": false
}
```
Aktiviert autonomes Schalten erst nach ausreichendem Training und nur für
erlaubte Aktor-Domains. Mit `false` wird der Aktor sofort wieder in den
Shadow-Modus versetzt.
erlaubte Aktor-Domains. `pause_matching_automations` pausiert eindeutig
zugeordnete HA-Automationen bei der Übernahme.
Beim Stoppen:
```json
{
"active": false,
"pause_matching_automations": false,
"restore_paused_automations": true
}
```
Damit wird der Aktor in den Shadow-Modus versetzt und zuvor von SillyHome
pausierte Automationen werden fortgesetzt.
### `POST /v1/actuators/{actuator_entity_id}/related-automations/refresh`
Liest passende HA-Automationen anhand ihrer echten Konfiguration neu ein.
### `POST /v1/actuators/{actuator_entity_id}/related-automations/control`
```json
{
"automation_entity_id": "automation.licht_abstellkammer",
"enabled": false
}
```
Pausiert oder aktiviert eine eindeutig diesem Aktor zugeordnete Automation.
## Betrieb