Mein-Audi-Kachel "Versicherung/Steuer" (vAudi()) und Kfz-Steuer-Detail
(vSteuer()): "Zusammen" heisst jetzt "Summe", die Fusszeile "feste
Kosten im Jahr" darunter entfaellt ersatzlos. Die Kfz-Steuer-Zeile
zeigt "im Jahr" statt des rohen Datenwerts "jaehrlich", deckungsgleich
mit der Versicherungs-Zeile darueber - nur wenn steuer.zeitraum
tatsaechlich "jaehrlich" ist. Der gespeicherte Wert und die
"jaehrlich"/"halbjaehrlich"-Auswahl in vSteuerBearbeiten() bleiben
unveraendert, das war ein reiner Anzeige-Fix, keine Datenmodell-
Aenderung. companion-app hatte an keiner der beiden Stellen ein
Gegenstueck (kein "Zusammen"-Tile, keine Nur-Lese-Anzeige des
Zeitraums) - dokumentiert als vorbestehende strukturelle Luecke statt
kommentarlos uebersprungen.
Vertrag-Kachel: war komplett nur lesbar (Gesellschaft, Umfang,
Vertragsnummer, Selbstbeteiligung, Schadenfreiheitsklasse). Neue
vVertragBearbeiten()-Ansicht (Panel, Route "vertrag") ueber ein neues
Zahnrad auf der Vertrag-Kachel - alle Felder editierbar,
Selbstbeteiligung zusaetzlich mit Hinzufuegen/Loeschen pro Zeile (neue
.zeile-loeschen-Klasse, 44x44pt-Tippflaeche wie .km-edit). Die
aktuelle Schadenfreiheitsklasse bleibt bewusst nur ueber "Beitrag
anpassen" editierbar (Querverweis statt Duplikat), nur "zuvor" (sfAlt)
ist neu in der Vertrag-Ansicht.
companion-app: neue Vertrag()-Seite (Route "vertrag", eigene
NaviKachel auf der Versicherungs-Seite) nach dem dortigen etablierten
Muster (lokaler Entwurf-State + expliziter Speichern-Knopf statt
Panel-Autosave pro Feld - gleiches Verhalten, eigenes Idiom). Die
bisherige Nur-Lese-Selbstbeteiligung in Vertragsdetails() entfaellt,
da sie jetzt (editierbar) in Vertrag() lebt. Schadenfreiheitsklasse
wird in companion-app bewusst nicht ergaenzt: das Feld war dort noch
nie sichtbar, auch nicht lesend - eine komplette neue UI-Sektion dafuer
waere kein "Zeile editierbar machen" mehr, sondern ein neues Feature;
als Luecke dokumentiert statt still uebergangen.
tsc --noEmit sauber, companion-app-Tests 100/100 (inkl. dem
Alle-Seiten-Rendertest, der jetzt auch "vertrag" abdeckt), vite build
erfolgreich. Panel live im Docker-Testcontainer geprueft: Zeile
hinzufuegen/bearbeiten/loeschen, Daten bleiben nach Re-Render erhalten.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Naechster-Service-Kachel (Uebersicht): das "bis zum Oelwechsel"/
"bis zur Inspektion" vor der Kennzahl entfaellt zugunsten der echten
Audi-CI-Icons oil-change/inspection (vom Nutzer als SVG geliefert,
verbatim uebernommen wie die uebrigen CI-Icons). Hauptuntersuchung hat
kein eigenes Icon (kein Restkilometer-Ziel) und zeigt stattdessen ihr
Datum in derselben 40px-Groesse wie die km-Zahlen, mit dem Wort
"Hauptuntersuchung" darunter statt "bis zur Hauptuntersuchung" - vorher
war das Datumsfeld kleiner (30px), um Umbruch zu vermeiden; am
laufenden Panel nachgemessen, dass 40px keinen Umbruch verursacht.
"vsl." wird ausgeschrieben zu "voraussichtlich am". bisText()/ART_BIS
(Panel) und bisText()/BIS_TEXT (companion-app) wurden durch die
Aenderung ueberfluessig und als Orphans entfernt.
Anstehende-Termine-Box (Service-Seite): aus der dt/dd-Liste werden drei
sichtbar getrennte Bloecke (Kopfzeile mit Icon + Name + optionalem
Werkstatt-Chip, optionale Herstellervorgabe-Zeile, grosse Kennzahl,
optionale Prognose-Fusszeile) - Apple HIG (Hierarchie ueber
Position/Groesse, Inhalt nicht mit Nebensaechlichem ueberladen) plus
Audi-CI (Flaeche mit Haarlinien statt Karten). Durchlief drei
Mockup-Runden als Artefakt vor der Umsetzung, zwei davon vom Nutzer
zurueckgewiesen ("Major Information is missing" bzw. Kommentare zu
Icon-Groesse/Herstellervorgabe/Ausrichtung).
Herstellervorgabe-Logik korrigiert: eine Fahrzeugmeldung stammt immer
aus dem werkseigenen Wartungsprogramm des Bordcomputers, unabhaengig
vom in "Einrichten" gewaehlten App-Intervall - zaehlt also immer als
Herstellervorgabe, nicht nur wenn der App-Modus zufaellig "hersteller"
ist. Die Prognose-Fusszeile zeigt die Restkilometerzahl nur noch beim
eigenen (kuerzeren) Intervall, bei Herstellervorgabe nur noch das
Datum. "Eigenes" in der Ölwechsel-Intervall-Auswahl umbenannt zu
"Individuell".
companion-app-Portierung ist eine echte Neustrukturierung: die
bisherige "Naechster Oelwechsel"-Kachel mischte Oelwechsel-,
Inspektions- und Hauptuntersuchungs-Zeilen in einer gemeinsamen
Werteliste, jetzt "Anstehende Termine" mit denselben drei Bloecken wie
im Panel. Neuer Export letzterInspektion() in service.ts. Zwei
dokumentierte, vorbestehende Luecken bleiben bestehen statt neu
kaschiert zu werden: kein Werkstatt-Chip (companion-app hat keine
"Termin vereinbaren"-Funktion), Herstellervorgabe kommt aus
fahrzeug.oel.modus statt einem intervalle()-Aequivalent (das es dort
nicht gibt).
npm run typecheck sauber, npm run test 99/99, npm run build erfolgreich.
Panel deployed als Version 1787013003, synchron in installationspaket/,
live im Docker-Testcontainer per DOM-Abfrage geprueft.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Nutzer stellte klar: Panel und companion-app sollen immer denselben
funktionalen Stand haben, auch wenn eine Anfrage nur das Panel nennt -
das ist reiner Testkomfort (Docker-Instanz laesst sich am schnellsten
ansehen), keine Scope-Entscheidung. Regel als verbindlicher Absatz in
AGENTS.md verankert, direkt unter der bestehenden Maintenance-Regel.
Erste Anwendung im selben Zug: die eben im Panel gebaute
"Naechster Service"-Kachel nach companion-app/ portiert.
- daten/service.ts: neues naechsterService() als Gegenstueck zu
naechsterTermin() im Panel - waehlt ueber Oelwechsel-/Inspektions-
Prognose und die von Hand gepflegte Hauptuntersuchung hinweg den
zeitlich naechsten Termin. bisText() liefert denselben Artikel wie
ART_BIS im Panel ("bis zum Oelwechsel" / "bis zur Inspektion").
- screens/Uebersicht.tsx: die bisherigen Kacheln "Reichweite"/
"Kilometerstand" nebeneinander plus eine separate "Service"-Kachel
mit Werteliste weichen einer Reichweiten-Kachel plus einer
Service-Kachel mit .dm-serviceblock (Knopf, nur der obere Teil) und
.dm-servicezeile (reine Anzeige) darunter - dieselbe Control/Content-
Trennung wie im Panel.
- stile/screens.css: .dm-serviceblock/.dm-servicezeile ergaenzt.
Tests: 4 neue in service.test.ts (naechsterService waehlt das frueher
faellige Datum, nimmt die Hauptuntersuchung auf, liefert nichts ohne
Servicebuch/HU, bisText-Artikel je Art), 1 neuer in screens.test.tsx,
der mit einem vi.fn() als geheZu wirklich belegt, dass ein Klick auf
den Serviceblock navigiert und ein Klick auf die Kilometerstand-Zeile
es nicht tut - dafuer bekam zeige() in screens.test.tsx erst einen
injizierbaren geheZu-Parameter (vorher hart auf () => {} verdrahtet).
npm run typecheck sauber, npm run test 100/100 (von 95), npm run build
erfolgreich.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Auf Nachfrage, wie Apple HIG und die Audi-CI die beiden Kacheln loesen
wuerden - beide laufen auf dieselbe Antwort hinaus.
Die Oelwechsel-Kachel presste zwei verschiedene Groessen in ein
Zahlenfeld: Restkilometer und Prognosedatum, getrennt durch einen
Schraegstrich. Zwei Einheiten, davon eine erfundene ("tkm" schreibt
niemand - die Mein-Audi-Servicebox nannte dieselbe Zahl schon immer
"9.029 km"), zwei Schraegstriche mit zwei Bedeutungen, und auf 375px
zweizeilig umgebrochen.
Apple HIG "Layout" ("don't obscure essential information by crowding it
with nonessential details") und "Typography" (Hierarchie ueber Groesse
und Farbe) verlangen die Trennung; die Audi-CI definiert .fig
ausdruecklich als "large numeric figures" - eine Zahl, nicht zwei.
- Wert gross (9.029 km), Kontext leise darunter (vsl. 04/2027)
- Echte Einheit statt "tkm"
- Kachel ist jetzt ein Knopf mit Chevron zur Service-Seite; vorher eine
Sackgasse, obwohl es die Seite gibt
- mmjj() dadurch verwaist, ersetzt durch mmjjjj() mit vollem Jahr
- HU-/Inspektionszweig faellt mit dem Oelwechselzweig zusammen, weil sie
nach der Trennung dieselbe Form haben
companion-app hatte diesen Fehler nicht (dort standen die Termine schon
als Label/Wert/Zusatz). Dort stattdessen der benachbarte
Gruppierungsfehler behoben: die Service-Zeilen hingen innerhalb der
Kilometerstand-Kachel und fuehrten nirgendwohin - jetzt eigene,
antippbare Kachel zur Service-Seite.
Live geprueft im Panel (Tag und Nacht, 375px): beide Kacheln einzeilig,
Tippen oeffnet Service. companion-app: typecheck sauber, 95/95 Tests,
Build erfolgreich.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The phone-app codebase (companion-app/) hadn't been touched since
2026-08-11 - every panel fix and feature since then (HIG audit rounds,
receipt upload, trip editing, Inspektion forecast, ...) existed only in
the HA panel. Found while auditing what's needed for a real iPhone
build; user decision was to port everything now rather than ship a
stale app.
Six real, verified gaps (not blind copies of panel CSS/markup, which
doesn't transfer to the @audi-dash/ui component set):
- Battery voltage cutoff was still 13.2V, not the panel's 12.8V fix.
- Dead wlan_name field (WLAN trip detection was fully removed from the
backend 2026-08-12) - removed from the adapter and the settings screen
instead of leaving a form field that silently does nothing.
- No Inspektion forecast - added inspektionPrognose() alongside the
existing oelwechselPrognose(), sharing a refactored core.
- Arbeitsweg pill used the design-system's "work" variant, which is
documented as recoloring to red - stopped passing it, same fix as the
panel.
- Trip creation only took Beginn/Ende/Art; extended with Startort/
Zielort/Kilometerstand/Distanz via a new shared FahrtFelder.tsx.
- FahrtDetail.tsx was read-only - added an edit mode using the same
shared fields, backed by a new DataMetricApi.fahrtAktualisieren()
calling the backend service built earlier this session.
Explicitly checked and found not applicable: price rounding (already
2 decimals here), pull-to-refresh CSS (no native gesture to fix),
the panel's drag/paste receipt dialog (solves a desktop-browser problem
this native app doesn't have - the plain file picker already gets iOS's
native Files integration), and the purely cosmetic panel CSS fixes.
npm install run at the repo root (node_modules was incomplete/stale),
package-lock.json reflects the real dependency tree. Verified with
npm run typecheck (clean), npm run test (95/95, up from 90 - added
interaction tests for the new form and inspektionPrognose), and
npm run build (succeeds).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Xcode ist vorhanden, die Huelle liess sich also wirklich bauen statt nur
vorzubereiten: Capacitor 8 fuer iOS und Android, Build fuer den Simulator
erfolgreich, App laeuft und zeigt echte Daten vom Server.
CapacitorHttp eingeschaltet. Das ist keine Feinheit: die native Huelle
liefert die Oberflaeche unter eigenem Ursprung aus, jede Anfrage an Home
Assistant ist damit ursprungsuebergreifend, und die WebView lehnt sie ohne
CORS-Freigabe ab. Nativ gestellte Anfragen kennen keine CORS-Pruefung -
die App braucht dadurch keine CORS-Einstellung am Server.
Drei Fehler, die erst die Bildschirmfotos zeigten:
1. Der Fahrzeug-Block auf der Uebersicht war unsichtbar. Ursache war der
Flexbox-Fallstrick: "overflow: hidden" setzt die automatische Mindesthoehe
auf 0, und sobald die Seite laenger ist als der Bildschirm, quetscht
flex-shrink den Block auf Hoehe 0. Modellname, Typenschild und Kennzeichen
waren damit schlicht weg.
2. Neben dem Typenschild stand der Modellname noch einmal komplett, obwohl
das Schild ihn bereits zeigt. Das alte Panel loest das laengst richtig -
nur der Zusatz gehoert daneben. Nachgezogen, samt Entdopplung, wenn die
Ausfuehrung schon im Namen steckt.
3. In der Fotogalerie liefen die Dateinamen ueber den Rand der Miniaturen.
Dazu: Datumszeile in Listen bricht um statt abzuschneiden, Statistik nutzt
auf der Flaeche mehrere Spalten.
Im Backend war das Kilometerstand-Screening kaputt: es rief urlopen direkt
auf, was Home Assistant seit 2026.8 als blockierenden Aufruf abbricht. Jede
Fahrt blieb dadurch ohne Strecke - sichtbar nur als Warnung im Protokoll.
Laeuft jetzt ueber task.executor und rechnet an der Testinstanz wieder echte
Strecken aus dem Verlauf.
Die CORS-Freigabe fuer die Web-Fassung ist in der Testkonfiguration
hinterlegt. Sie greift in Home Assistant 2026.8 allerdings nicht - deshalb
wird die App aus Home Assistant selbst ausgeliefert (gleicher Ursprung, kein
CORS), was ohnehin der geplante Weg ist.
Die erzeugten Ordner ios/ und android/ bleiben ungetrackt; sie entstehen
jederzeit neu aus dem Webbuendel.
PWA laeuft: Manifest, Symbole in allen noetigen Groessen und die
iOS-Angaben, die Apple statt des Manifests auswertet. Das Startsymbol ist
bewusst neutral - die Vier Ringe auf einem Homescreen waeren nach aussen
sichtbar und fielen nicht mehr unter die private Nutzung.
Vorbereitet, aber nicht ausgefuehrt: Capacitor-Konfiguration, ein
Ablage-Adapter fuer Schluesselbund und Keystore (greift defensiv auf die
Laufzeit zu, damit die App ohne das Plugin unveraendert weiterlaeuft), die
Pfad-Freigabeliste fuer den Reverse Proxy und das Geruest der
FMM003-Zuordnungstabelle.
Die QR-Seite fuer die Einrichtung war zunaechst ein Fehlgriff: Ich hatte den
QR-Erzeuger selbst geschrieben. Der Vergleich gegen eine erprobte
Implementierung zeigte 1239 abweichende Module von 3249 - der Code waere
unlesbar gewesen. Jetzt liegt eine bewaehrte Bibliothek (MIT, 57 KB) neben
der Seite im eigenen Home Assistant. Das erfuellt die eigentliche
Anforderung genauso: kein Netzzugriff, der Token verlaesst das eigene Netz
nicht. Geprueft ueber einen Umlauf - 233 Zeichen hinein, identisch wieder
heraus.
41 weitere Tests fuer Statistik, Service-Prognose und Formatierung. Die
Faelle sind entlang der Regeln gewaehlt, die beim Portieren wichtig waren:
Wochenbeginn Montag, Nachtspanne ueber Mitternacht, mengengewichteter
Durchschnittspreis statt Mittel der Einzelpreise, Plausibilitaetsfenster beim
Langzeitverbrauch, Neustart der Oelprognose ab dem letzten Wechsel samt
Zeitlimit-Deckelung, BOM und Semikolon in der CSV-Ausgabe.
Ein Test war zunaechst falsch: er verglich das UTC-Datum gegen eine
Ortszeit-Erwartung. Der Code rechnet bewusst lokal - sonst begaenne der
Monat in unserer Zeitzone einen Tag zu frueh.
companion-app/README.md auf den erreichten Stand gebracht.
Gesamt: 90 Unit- und Rendertests plus 9 Pruefungen gegen die laufende
Home-Assistant-Instanz.
Die drei Schriftschnitte stammen aus dem Panel, wo sie als base64 im
Stylesheet lagen - als eigene woff2-Dateien sind sie zwischenspeicherbar
statt bei jedem Laden erneut uebertragen zu werden. Typenschilder und Ringe
wechseln mit dem Erscheinungsbild.
Lizenzgrenze eingehalten und geprueft: design-system bleibt unveraendert und
enthaelt keine Markendateien, weil es nach aussen hochgeladen wird. Die App
darf sie nutzen, weil sie nur seitlich installiert wird.
Dabei noch eine Typungenauigkeit korrigiert: technik und ausstattung im
Profil sind Listen von Gruppen, waren aber wie die uebrigen Abschnitte als
Objekt deklariert.
Fahrzeugdaten, Batterieverlauf, Service mit Werkstatt und Servicebuch,
Reifen, die ganze Versicherungs- und Steuergruppe, Einstellungen in voller
Tiefe und die Live-Ansicht.
Portiert dazu: die eigene Oelwechsel-Prognose (rechnet ab dem letzten
Wechsel im Servicebuch neu, weil der Langzeitschnitt dafuer zu traege ist),
Kalenderdateien fuer Termine und die CSV-Ausgabe im deutschen Format.
Die Live-Ansicht ist gebaut, aber ueber einen Schalter abgeschaltet: die
Werte dafuer liefert erst der FMM003. Ein Menuepunkt mit lauter Nullen waere
schlechter als keiner.
Zwei Stellen, an denen die App bewusst zurueckhaltend ist: ein unbekannter
Pruefpunkt erscheint als hohler Ring statt als geratenes Gruen, und der
Reifen-Kilometerstand wird nie zurueckgeschrieben, weil ihn der Server
fortschreibt.
49 Tests, darunter ein Rendertest ueber alle 21 Seiten in beiden Layouts
mit Beispieldaten in der Form, die das Backend wirklich liefert.
Listen mit Jahr-Monat-Aufklappung, Detailseiten, manuelles Eintragen und
Beleg-Upload. Statistik rechnet ueber die portierten Regeln.
Zwei offene Audit-Befunde des alten Panels sind hier gleich mit erledigt:
1. Loeschen war ausschliesslich per Wischgeste erreichbar. Wer mit
Sprachausgabe oder Schaltersteuerung bedient, wischt nicht - Fahrten und
Tankvorgaenge waren fuer diese Nutzer gar nicht loeschbar. Jede Zeile hat
jetzt zusaetzlich ein sichtbares Menue, ein richtiger Knopf mit Tastatur.
2. Leaflet kam per CDN und blieb auf einem Handy ohne eigenen Internetzugang
still leer. Es liegt jetzt im Buendel (eigener Abschnitt, erst bei Bedarf
geladen).
Bewusst NICHT uebernommen: fakeTrack() aus dem alten Panel, das eine
erfundene Linie zwischen zwei Punkten zeichnete, wenn keine Route vorlag.
Solange das Fahrzeug keine Positionen liefert, sagt die Seite das - statt
eine glaubwuerdig aussehende Erfindung zu zeigen.
Erste drei Screens auf der fertigen Datenschicht. Uebersicht mit Fahrzeugbild,
Sicherungsstatus, Reichweite und Tankfuellstand, Kilometerstand samt
Service-Faelligkeit und Vorschau auf letzte Fahrt und Tankung. Fahrzeugstatus
zeigt die 16 Einzelpruefungen, wobei ein unbekannter Sensor als hohler Ring
erscheint statt als gruen geratener Punkt - dieselbe Vorsicht, die schon das
Backend walten laesst. Mein Audi buendelt Fotogalerie und Wege zu den
Unterseiten.
Dazu die geteilte Rechenlogik der Statistik portiert (Zeitraeume,
Langzeitverbrauch mit Plausibilitaetsfenster, Gruppierung nach Jahr und
Monat) und Formatierung im deutschen Format.
Bild-Komponente kapselt eine Reibung zwischen App und Bibliothek: die App
laeuft mit exactOptionalPropertyTypes, ein undefined an einem optionalen Prop
waere sonst an jeder Aufrufstelle einzeln zu behandeln.
Die App spricht jetzt echt mit Home Assistant. Ein Datenkontext buendelt die
vier Datentoepfe, haengt sich an den WebSocket-Ereignisstrom und reicht
Verbindungszustand und Warteschlange nach aussen; die Screens kennen weder
REST noch WebSocket. Ersteinrichtung prueft die Zugangsdaten, bevor sie sie
speichert, und unterscheidet in der Fehlermeldung zwischen abgelehntem Token
und nicht erreichbarem Server - zwei Faelle, die voellig verschiedene
Reaktionen verlangen.
Zwei echte Fehler, die erst der Test gegen die laufende Instanz zutage
brachte:
1. Die Typen der Datenschicht deklarierten tank_prozent, sicher_abgestellt
und sicherheit. Das Backend schreibt tankprozent, gesichert und
sicherheitscheck - die Oberflaeche haette still ueberall undefined
gelesen, ohne dass irgendetwas fehlgeschlagen waere.
2. Der Profil-Adapter reichte lebende Verweise ins Rohprofil durch. Ein
Formular haette damit den Rohstand mitveraendert und die Zusage gebrochen,
den vom Backend fortgeschriebenen Reifen-Kilometerstand nie zu
ueberschreiben. Abschnitte werden jetzt kopiert.
Ausserdem zwei Parameter-Eigenschaften in der Datenschicht aufgeloest, weil
Node sie im Strip-Modus nicht uebersetzt und genau darueber die Rauchtests
laufen.
Belegt durch neun Pruefungen gegen die laufende Instanz (Lesen, Dienstaufruf,
vollstaendiger Warteschlangenumlauf, WebSocket-Anmeldung) und 21 Unit-Tests.
Zwei Layouts aus derselben Zusammensetzung: unter 1000px Tab-Leiste unten,
darueber Seitenleiste links mit Brotkrume statt Zurueck-Pfeil. Navigation
ist wie im alten Panel ein flacher Zustand mit fester ZURUECK-Tabelle statt
eines Router-Pakets - die Verschachtelung ist hoechstens dreistufig.
Theme und Tab-Beschriftung ueberleben einen Neustart (localStorage,
abgesichert fuer den Privatmodus), Startwert folgt der Systemeinstellung.
Symbole aus dem alten Panel uebernommen, damit App und Panel gleich aussehen.
Neun Rendertests belegen die Abnahmekriterien: Layoutwechsel in beide
Richtungen, Zurueck-Ziel ueber die Tabelle, Zahnrad statt Tab-Leiste fuer
die Einstellungen, Theme-Persistenz.
npm-Workspace im Repo-Root verbindet companion-app mit @audi-dash/ui, so
dass die App die Komponentenbibliothek als echte Abhaengigkeit nutzt statt
nur in der Doku. Dazu Vite, React 18, Einstiegsdateien und eine schlanke
Grundlage-CSS, die nur enthaelt was eine App braucht und eine Bibliothek
nicht mitbringt: Vollbild, sichere Bereiche, Scrollverhalten.
Zwei Audit-Befunde des alten Panels sind hier von Anfang an beruecksichtigt:
Formularfelder mit 16px (sonst zoomt iOS Safari beim Fokus) und ein
globaler :focus-visible-Ring.
Nebenbei im design-system den Kontrastwert --fg3 nachgezogen: dort stand
noch #657081 mit 3,0:1 auf --tile, das Panel hatte den Wert laengst auf
#8a94a3 korrigiert. Ohne das haette die neue App den bereits behobenen
WCAG-Verstoss geerbt.
Drei zusammengehörige Teile in einem Repository:
- homeassistant/ Das fertige, im Einsatz befindliche Home-Assistant-Panel
(panel_custom Custom Element + pyscript-Backend). Echte Fahrzeug- und
Personendaten (fahrzeugprofil.json, fahrten.jsonl, tankvorgaenge.jsonl,
Tankbelege) bleiben per .gitignore außen vor; die anonymisierte Vorlage
fahrzeugprofil.example.json ist mit dabei.
- design-system/ Eigenständige React-Komponentenbibliothek (@audi-dash/ui),
die die visuelle Sprache des Panels nachbildet - ohne Audi-Markenzeichen
und ohne die lizenzierte Hausschrift. Dient als Grundlage für Claude
Design. War bis hierher ein eigenes Repository und ist in dieses
eingeschmolzen worden.
- companion-app/ Datenschicht der neuen App DataMetric360 (iOS/Android via
Capacitor, zusätzlich als Iframe im HA-Dashboard). Noch ohne Oberfläche:
REST- und WebSocket-Zugriff auf Home Assistant plus Warteschlange für
Änderungen ohne Netz. Ersetzt das eingespritzte hass-Objekt, das nur
innerhalb des HA-Frontends existiert.
Dazu die Projektdokumentation: SPECIFICATION.md (Ist-Stand des Panels),
COMPANION_APP_ARCHITECTURE.md (Architekturentscheidungen der neuen App),
AUDIT_2026-08-10.md, DESIGN_BRIEF_DATAMETRIC360.md und der ursprüngliche
Bauauftrag.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>