Audit Panel/iOS: sechs Befunde behoben, Zuendung aufs Trip-Signal (2026.8.31.5)

ZUENDUNG_SENSOR liegt jetzt auf dem Trip-Signal des FMM003 statt auf dem rohen,
prellenden Zuendungseingang. Damit kommt die Pausentoleranz vom Geraet - eine
Fahrt beginnt erst bei Zuendung UND Bewegung UND Start Speed.

MINDESTDAUER_S wandert nach verlauf.py und gilt jetzt auch im Livepfad. Vorher
verwarf nur der Import Zuendphasen unter 60 s; live entstanden daraus am 31.08.
elf Fahrten mit 0 km, zwei davon mit null Sekunden Dauer.

Das Panel erfand einen Literpreis von 0,00 EUR, wenn die Kosten noch nicht
feststanden (null/liter ist 0 in JavaScript) - neue Hilfsfunktion literpreis()
prueft beides, wie die App seit jeher. schnittpreis() teilte ohne Nennerpruefung
und konnte "NaN" oder "unendlich" anzeigen.

Der Setup-Dialog ist wirklich modal: die Tab-Leiste hatte einen eigenen Zuhoerer
vor der Sperre und liess einen Tabwechsel bei offenem Fenster zu.

Verwaister Code entfernt: drei Funktionen und vier Regeln im Panel, 20 Regeln in
der App.

Offen bleibt allein die leere Erstzulassung - eine Angabe, keine Aenderung.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-31 20:05:59 +02:00
parent 90efcc5b00
commit 9b0e390dfd
11 changed files with 183 additions and 215 deletions
+106 -1
View File
@@ -1,6 +1,8 @@
# AGENTS.md — Project state, review findings, open items, and working rules
**Last updated: 2026-08-31** (Neustart-Festhänger der App, OTA-Prüfsumme, Statistik-Kopfzahl,
**Last updated: 2026-08-31** (Audit über Panel und iOS-App: sieben Befunde, sechs behoben,
`ZUENDUNG_SENSOR` auf das Trip-Signal des FMM003 umgelegt; Manifest `2026.8.31.5`, siehe
Abschnitt AV. Davor am selben Tag: Neustart-Festhänger der App, OTA-Prüfsumme, Statistik-Kopfzahl,
Setup-Filter und die gemessene Wahrheit über die Dongle-Konfiguration; Manifest `2026.8.31.4`,
siehe Abschnitte AT und AU. Davor: 2026-08-30 (owner findings batch - vehicle pin, tile chevrons, select arrows,
SmartDeal dialog, address cache and pull-to-refresh; manifest `2026.8.30.19`, see sections AO, AP and AQ.
@@ -6189,6 +6191,109 @@ mitten in der Fahrt eine Lücke von **2739 s** ohne einen einzigen Satz. Dagegen
Einstellung am Gerät; das ist der in Abschnitt P/W beschriebene Fall, den die
Plausibilitätsgrenze (`UNPLAUSIBLE_KMH`) abfängt.
## AV. Audit Panel/iOS und die sieben Befunde daraus (2026.8.31.5)
Bericht mit allen Messwerten:
https://claude.ai/code/artifact/59b55b39-0d49-483d-a3b7-c29ca59af7bf
Der Eigentümer hat „alles" angewiesen, danach ausdrücklich auch die bis dahin
vertagte Sensor-Umstellung. Alle sieben Befunde sind erledigt bis auf Befund 07, der
eine Angabe des Eigentümers braucht.
### Die Zündung liegt jetzt auf dem Trip-Signal des Geräts
`ZUENDUNG_SENSOR` zeigt in `audi_ha_test` nicht mehr auf
`engine_ignition_or_acc_status` (den rohen, prellenden Eingang), sondern auf
`binary_sensor.…_trip_status_true_if_trip_started_false_if_stopped`. Begründung
vollständig in Abschnitt AU. Kurz: das Trip-Signal beginnt erst, wenn Zündung **und**
Bewegung **und** `Start Speed` zusammenkommen, und endet erst 900 s nach Zündung aus —
die Pausentoleranz kommt damit vom Gerät, ohne dass wir einen zweiten Zeitgeber bauen.
Geschrieben über den echten Dienst (`entitaeten_schreiben`), nicht durch Hantieren an
der Datei: nur diese eine Rolle hat sich geändert, alle 23 Einträge stehen noch.
**Merkposten Werkzeug:** `hass.callService(...)` aus dem Browser-Werkzeug heraus
scheiterte reproduzierbar mit der nichtssagenden Meldung `3`, `hass.callApi("POST",
"services/…")` mit demselben Rumpf ging durch. Bei so einer Meldung also den REST-Weg
nehmen, statt den Dienst zu verdächtigen.
**Der Preis, bewusst in Kauf genommen:** das Fahrtende liegt 15 Minuten hinter dem
tatsächlichen — genau wie mit der früheren eigenen Pausentoleranz, also kein Rückschritt.
Wer es genauer will, müsste das Ende nachträglich auf den letzten Punkt mit
Geschwindigkeit > 0 zurückrechnen; eigenes Arbeitspaket, hier nicht angefangen.
### Live-Erkennung und Import bewerten dasselbe Fenster wieder gleich
`MINDESTDAUER_S = 60` lebt jetzt in `verlauf.py` neben `UNPLAUSIBLE_KMH` und aus
demselben Grund. `fahrterkennung.fahrt_beenden()` prüft sie, bevor eine Fahrt entsteht;
der laufende Start wird trotzdem zurückgesetzt, sonst hinge er für immer.
Vorher stand die Zahl allein in `historienimport.py` — dessen eigener Kommentar den
Widerspruch sogar benannte („die Live-Erkennung legt sie zwar an"). Am 31.08. sind daraus
an einem Tag **elf Fahrten mit 0 km** entstanden, zwei davon mit null Sekunden Dauer, alle
als „vollständig" im Bestand. Die Umstellung oben nimmt die Ursache, diese Grenze fängt
den Rest ab; beides zusammen, nicht eines statt des anderen.
**Nicht angefasst: die elf bereits gespeicherten Fahrten.** Das ist die echte Historie des
Eigentümers, und deren Bereinigung ist seine Entscheidung — dieselbe Linie wie in
Abschnitt W.
### Das Panel erfand einen Literpreis von 0,00 €
`f.liters ? f.fuel_total_eur / f.liters : null` — bei einem automatisch erkannten
Tankvorgang stehen die Kosten noch nicht fest, und `null / 11.5` ist in JavaScript `0`.
Liste, Einzelbeleg und CSV zeigten daraufhin einen Preis, den niemand bezahlt hat. Neue
Hilfsfunktion `literpreis(f)` prüft beides, wie die App an derselben Stelle seit jeher;
vier Aufrufstellen umgestellt. Live bestätigt: die drei Zeilen vom 27./29.08. zeigen jetzt
nur noch die Liter.
### „Ø NaN €/l" und „Ø ∞ €/l" waren erreichbar
`schnittpreis()` teilte ohne Nennerprüfung: ein Zeitraum ohne Liter ergibt `0/0`, einer
mit Kosten aber ohne Liter eine Division durch null, und `de()` reicht beides durch.
Einzelne solche Datensätze gibt es real; es braucht nur einen Monat, der ausschließlich
daraus besteht. Jetzt `if (liter <= 0) return 0`, wie `format.ts` es seit jeher tut.
### Der Setup-Dialog ist wirklich modal
Die Tab-Leiste hat einen eigenen, früher registrierten Zuhörer und umging damit die Sperre
`if (setupOffen) return` des großen click-Handlers — obwohl der Dialog
`aria-modal="true"` trägt. Er schwebte anschließend über einer anderen Seite, mitsamt der
nicht gespeicherten Zuordnung. Dieselbe Sperre (plus `sheet`) steht jetzt auch dort.
Live geprüft: Tabwechsel bei offenem Dialog bleibt wirkungslos, nach „Abbrechen" gehen
alle fünf Tabs und eine Detailseite wieder.
### Verwaister Code entfernt
Panel: `bildSrc()`, `ring()`, `zustandsDaten()` (ohne Aufrufstelle) sowie
`.bildgrid`, `.platzhalter-datei` und die beiden `.row-fussnote`-Regeln — Reste dreier
abgelöster Entwürfe. App: 20 `.dm-*`-Regeln, darunter `dm-detail__zahl`, seit der
Umstellung auf `Fig` ohne Markup.
**Wie geprüft wurde, damit die Liste stimmt:** ein Skript liest jede Regel und sucht ihre
Verwender im Quelltext beider Codebasen. Zwei Fallen dabei, beide real aufgetreten: Namen
aus deutschen Kommentaren sehen wie Klassen aus, und `ads-dot--${status}` wird zur
Laufzeit zusammengesetzt und taucht in keiner Suche auf — sechs Design-System-Klassen
standen deshalb zunächst falsch auf der Liste und wurden vor dem Melden aussortiert.
### Offen: Befund 07, Erstzulassung
`fahrzeug.erstzulassung` ist leer, deshalb steht bei der Hauptuntersuchung in beiden
Oberflächen „kein Eintrag im Wartungsplan" — ohne dieses Datum gibt es keinen Anker,
weder aus dem Wartungsplan noch aus einer Fahrzeugmeldung. Kein Codefehler; einzutragen
unter Einstellungen → Fahrzeug einrichten. Bewusst nicht erfunden.
### Was am Panel und an der App in Ordnung war
Vier von fünf Tabs textgleich (die fünfte Abweichung war Befund 02 selbst), Service und
Fahrzeugstatus ebenfalls, 153 `esc()`-Aufrufe ohne Lücke bei Freitext, beide
Frontend-Dateien als **Modul** geparst (siehe Abschnitt AQ), 165/165 Tests grün, in der
Konsole beider Oberflächen nur das bekannte ServiceWorker-Rauschen.
Verifiziert: `py_compile` auf den drei Backend-Dateien, `node --check` gegen die
Modul-Grammatik, `tsc --noEmit` sauber, 165/165, `vite build` sauber,
`audi_ha_test` auf `2026.8.31.5` sauber gestartet, und jede der fünf Codeänderungen
einzeln live nachgewiesen.
## Working conventions (observed — keep them)
- German is the project language: identifiers, comments, commits, UI texts. Exceptions: