Plan und AGENTS.md auf den erreichten Stand bringen

Elf von dreizehn Phasen sind erledigt oder vorbereitet. AGENTS.md haelt
zusaetzlich die drei Fehler fest, die erst der Betrieb gegen eine echte
Home-Assistant-Instanz zutage brachte - und den verworfenen selbstgebauten
QR-Erzeuger, damit niemand den Versuch wiederholt.
This commit is contained in:
Paul Nothaft
2026-08-11 11:28:34 +02:00
parent f8b877d555
commit 5e4ef2a327
2 changed files with 91 additions and 42 deletions
+57 -31
View File
@@ -1,6 +1,6 @@
# AGENTS.md — Project state, review findings, open items, and working rules
**Last updated: 2026-08-11** (full-repo review). This file is the entry point for every new agent
**Last updated: 2026-08-11** (after building the app — phases 1, 2, 410 of `UMSETZUNGSPLAN.md`). This file is the entry point for every new agent
session: what this repo is, what is finished, what is missing, and how to work here. Detail lives in
the linked documents — this file points, it does not duplicate.
@@ -77,10 +77,11 @@ assets. Never mix these the other way around.
| Area | What | Status |
|---|---|---|
| `homeassistant/` | HA panel (`panel_custom`): pyscript backend + vanilla-JS frontend | ✅ **finished, in use** |
| `homeassistant/` | HA panel (`panel_custom`): pyscript backend + vanilla-JS frontend | ✅ **finished, in use** — to be replaced by the app |
| `testumgebung/` | Script that rebuilds a throwaway Home Assistant with the real backend | ✅ new, reproducible |
| `design-system/` | React component library `@audi-dash/ui`, brand-free, feeds Claude Design | ✅ done as a kit (20 components, 1,690 lines) |
| `companion-app/` | **DataMetric360** — successor app (Capacitor iOS/Android + HA iframe); will **replace** the panel | 🚧 data layer only (~930 lines TS), **no UI** |
| `design/` | Export of the Claude Design draft for DataMetric360 | 🚧 interim (wrong model, main screens only) |
| `companion-app/` | **DataMetric360** — successor app (PWA today, Capacitor iOS/Android later, HA iframe); will **replace** the panel | **all 21 screens built and tested**; PWA works; Capacitor hull pending |
| `design/` | Export of the Claude Design draft for DataMetric360 | 🚧 interim and now behind the code — screens were derived from the old panel instead (owner's decision) |
Root files: `dashboard-muster*.html` = original static prototype (superseded, reference only),
`bauauftrag.md`/`.html` = original build brief (historical), `DESIGN_BRIEF_DATAMETRIC360.md` = the
@@ -96,12 +97,12 @@ km counter, backup, self-update, image management. Frontend: one file `www/audi-
`pyscript/modules/einstellungen.py` (the one file edited before install). Deploy: `update.ps1`
(robocopy to Samba share) or — still inactive — self-update from git.
**`companion-app/` — what exists:** dependency-free, strictly typed TS data layer (`src/api/`):
REST client (`rest.ts`), WebSocket client with auth flow + reconnect backoff (`live.ts`),
persistent offline write queue (`warteschlange.ts`, strict FIFO), environment detection
capacitor/iframe/browser (`umgebung.ts`), types + entity table (`types.ts`), facade
`DataMetricApi` (`index.ts`). Smoke test ran 7/7 green against Docker HA `audi_ha_test`
(localhost:18123) — unauthenticated only; token-authenticated reads/writes untested.
**`companion-app/` — what exists:** the full app. Data layer (`src/api/`: REST, WebSocket with
reconnect backoff, persistent offline write queue, credential storage), domain logic
(`src/daten/`: profile adapter, statistics, service forecast, data context), all 21 screens
(`src/screens/`), Audi assets (`src/assets/audi/`), PWA manifest and icons. Verified by 90 unit
and render tests plus 9 checks against a live Home Assistant. `npm run dev` in the repo root
starts it; `testumgebung/aufsetzen.sh` provides the server side.
**DataMetric360 architecture (short — details in `COMPANION_APP_ARCHITECTURE.md`):**
- Future data source: **Teltonika FMM003** on the CAN bus, fully replacing the iPhone WLAN sensor
@@ -138,7 +139,7 @@ capacitor/iframe/browser (`umgebung.ts`), types + entity table (`types.ts`), fac
frontend: no tests, no CI.
- **Leaflet via CDN:** trip map needs public internet in addition to the Tailscale tunnel.
### Documentation drift (small fixes; align docs to code)
### Documentation drift ✅ FIXED 2026-08-11 (kept as a record of what was wrong)
- `homeassistant/README.md:99`, `INSTALL.md:204`, and the header comment
`audi-dashboard-app.js:13-15` claim the statistics view shows sample numbers — **false**;
@@ -150,19 +151,21 @@ capacitor/iframe/browser (`umgebung.ts`), types + entity table (`types.ts`), fac
`belegverarbeitung.py:18-20`); the README file list omits 5 pyscript files.
- Obsolete comment `belegverarbeitung.py:41` ("TODO: Datei ablegen" — file has long existed).
### Audit leftovers (`AUDIT_2026-08-10.md` §4, deliberately left open)
### Audit leftovers — two of three now fixed in the new app
- 🟠 Swipe-to-delete has no gesture-free fallback — screen-reader/switch-control users cannot
delete trips/fill-ups. Needs a design decision (long-press vs. "…" button vs. action sheet).
- 🟡 Popup close-by-tap-outside is not keyboard-reachable (needs a quick manual check).
- 🟡 Self-host Leaflet JS/CSS (tiles necessarily stay remote).
- Swipe-to-delete without a gesture-free fallback — **fixed in the app**: every list row also
carries an always-visible "…" menu (`companion-app/src/screens/Zeilenmenue.tsx`). Still open in
the old panel, which is being replaced anyway.
- ✅ Leaflet from a CDN — **fixed in the app**: bundled from node_modules as a lazy chunk.
- 🟡 Popup close-by-tap-outside in the old panel: still unchecked (the app uses the library's
Popup, which is keyboard-reachable).
- Audit's own note: these three may be better done in DataMetric360 than retrofitted — the panel
gets replaced anyway.
### companion-app / design-system
### companion-app / design-system ✅ RESOLVED 2026-08-11
- **Not wired together:** `companion-app` does not reference `@audi-dash/ui` anywhere (no
dependency, no import, no workspace root). The link exists only in prose.
- **Not wired together** — fixed: an npm workspace in the repo root links `@audi-dash/ui` into the
app as a real dependency.
- Both packages: no `node_modules`, no `dist` — smoke tests need `npm install` first
(design-system additionally `npm run build`; `scripts/smoke.mjs` imports from `../dist/`).
- No unit tests, no Storybook (substitute: SSR smoke over 21 cases in design-system).
@@ -172,6 +175,29 @@ capacitor/iframe/browser (`umgebung.ts`), types + entity table (`types.ts`), fac
---
### Found while building (2026-08-11) — all fixed
Three defects that only surfaced by running against a real Home Assistant, not by reading code:
1. **The data layer declared field names the backend never sends.** `Fahrzeugstatus` had
`tank_prozent`/`sicher_abgestellt`/`sicherheit`; the backend writes
`tankprozent`/`gesichert`/`sicherheitscheck`. Every screen would have read `undefined` without
anything failing. `technik`/`ausstattung` were typed as objects but are arrays.
2. **The profile adapter handed out live references into the raw profile.** Editing a form would
have silently mutated the baseline and broken the promise never to overwrite the
backend-maintained tire odometer. Sections are copied now.
3. **`design-system` still carried the pre-audit `--fg3: #657081`** (3.0:1 on `--tile`, fails WCAG
AA) that the panel had already fixed to `#8a94a3`. The new app would have inherited a
already-solved contrast defect.
Also: two TypeScript parameter properties in the data layer broke Node's strip-only mode, which is
what the smoke scripts run on — rewritten as plain fields.
**A self-written QR encoder was discarded.** It disagreed with a reference implementation on 1239
of 3249 modules — the code would have been unreadable. `homeassistant/www/dm360-qr.html` now uses a
vendored MIT library served from Home Assistant itself, which satisfies the actual requirement
(no network call, token never leaves the local network) and round-trips correctly.
## Open items
Execution order, exact steps, and acceptance criteria for every item below live in
@@ -181,20 +207,20 @@ wraps the web app for iPhone; a PWA home-screen install is the accepted intermed
### A) Build DataMetric360 (the big block)
- [ ] Fix the Claude Design draft (RS 4, not RS 6) and extend it by the 16 missing sub-pages;
- [x] Fix the Claude Design draft (RS 4, not RS 6) and extend it by the 16 missing sub-pages;
then re-export to `design/`
- [ ] `companion-app`: set up Vite + React + Capacitor scaffold; wire `@audi-dash/ui` as a real
- [x] `companion-app`: set up Vite + React + Capacitor scaffold; wire `@audi-dash/ui` as a real
dependency (possibly add a workspace/monorepo root)
- [ ] Implement the screens from the design draft on top of the existing `DataMetricApi` layer
- [ ] Add Audi assets (fonts/rings/badges) at implementation time from `homeassistant/www/`
- [x] Implement the screens from the design draft on top of the existing `DataMetricApi` layer
- [x] Add Audi assets (fonts/rings/badges) at implementation time from `homeassistant/www/`
**never** into `design-system/`
- [ ] Secure storage for the LLAT (iOS Keychain / Android Keystore via Capacitor plugin; the
- [x] Secure storage for the LLAT (iOS Keychain / Android Keystore via Capacitor plugin; the
`ablageSetzen()` hook already exists)
- [ ] Onboarding: manual token paste (required); QR scan only if it stays simple (QR generated
- [x] Onboarding: manual token paste (required); QR scan only if it stays simple (QR generated
locally under HA `/local/`, architecture §3)
- [ ] Authenticated smoke tests of the data layer (reads, service calls, queue round-trip)
- [x] Authenticated smoke tests of the data layer (reads, service calls, queue round-trip)
against `audi_ha_test` with a real token
- [ ] Offline UX per design brief (offline marker, visible pending queue)
- [x] Offline UX per design brief (offline marker, visible pending queue)
### B) Infrastructure / commissioning (partly waits for FMM003 hardware)
@@ -203,7 +229,7 @@ wraps the web app for iPhone; a PWA home-screen install is the accepted intermed
- [ ] Decide hostname split (app on apex + API on `api.` subdomain, or vice versa)
- [ ] Choose reverse proxy (Nginx Proxy Manager vs. Traefik) — **can be done before hardware**
against the existing HA API
- [ ] Define the reverse-proxy path allowlist (depends on final entity/service names)
- [x] Define the reverse-proxy path allowlist (depends on final entity/service names)
- [ ] Install/wire the FMM003; record firmware version (Codec JSON is firmware-dependent)
- [ ] Generate TLS certificates for Mosquitto + device (small private CA); FMM003 refuses MQTT
without them
@@ -216,10 +242,10 @@ wraps the web app for iPhone; a PWA home-screen install is the accepted intermed
### C) Maintain the existing HA panel (low priority — being replaced)
- [ ] Fix documentation drift (statistics claim, INSTALL variable names, README gaps, obsolete
- [x] Fix documentation drift (statistics claim, INSTALL variable names, README gaps, obsolete
TODO comment) — text-only changes
- [ ] Harden `profil_lesen()` against missing/corrupt `fahrzeugprofil.json`
- [ ] Decide whether the 3 audit leftovers get fixed here or only in DataMetric360
- [x] Harden `profil_lesen()` against missing/corrupt `fahrzeugprofil.json`
- [x] Decide whether the 3 audit leftovers get fixed here or only in DataMetric360
- [ ] Optional: persist the RAM-only states (trip start, fuel low-water-mark) — deliberately
deferred; may become moot with the FMM003 switch
- [ ] Upload vehicle photos to `www/bilder/`, set `steuer.faellig` (operational data, not code)