From 8f6f1a6e0eeeb65e7e2cc08850bb184ac1863ae8e0430b96efed83a4c6e1d7e3 Mon Sep 17 00:00:00 2001 From: wlfb Date: Sun, 19 Jul 2026 22:10:23 +0200 Subject: [PATCH] docs: Ausbaustufe-3-Plan abgeschlossen Co-Authored-By: Claude Fable 5 --- .../plans/2026-07-19-ausbaustufe-3.md | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/superpowers/plans/2026-07-19-ausbaustufe-3.md b/docs/superpowers/plans/2026-07-19-ausbaustufe-3.md index 4dd99fe..b9b9712 100644 --- a/docs/superpowers/plans/2026-07-19-ausbaustufe-3.md +++ b/docs/superpowers/plans/2026-07-19-ausbaustufe-3.md @@ -51,10 +51,10 @@ Beträge deutsch formatiert (`1.234,56`, Minus führend) → `parse_german_amoun - GUI Übersicht: je Konto Ankeranzeige („Anker: X € am TT.MM.JJJJ" oder „kein Anker") + Inline-Formular (Datum+Betrag, json-form hx-patch). - `views.py`: `v_balance_history`/`v_balance_total` seeden pro Konto mit `anchor_balance − Σ(tx > … bis anchor_date)` statt Statement-opening — konkret: Basis je Konto = `account_balance` zum frühesten Buchungsdatum − dessen Tagesumsatz; einfachste korrekte Form: CTE mit Anker-Join und kumulativer Fenstersumme relativ zum Anker. `v_projection` unverändert. -- [ ] **Step 1: Failing Tests** — test_crud_api: (a) Konto mit Anker (Datum D, Betrag B) + bestätigte Buchungen vor/nach D → `account_balance(at=D)==B`, `at=D+2d` addiert spätere Buchung, `at=D−2d` subtrahiert dazwischenliegende; (b) PATCH setzt/löscht Anker, 422 bei nur-einem-Feld; test_gui: Übersicht zeigt Ankertext. -- [ ] **Step 2: FAIL** · **Step 3: Implementieren + Alembic-Autogenerate gegen Wegwerf-SQLite** (Muster Task 2 Ausbaustufe 1; Migration committen) · **Step 4: PASS, Suite grün** -- [ ] **Step 5: FABLE-TESTAGENT** verifiziert unabhängig (Suite + Anker-Randfälle: at==anchor_date, Buchung AM Ankertag zählt nicht zur Vorwärtssumme/wohl zur Rückwärtssumme — Konvention: Anker gilt per Tagesende). -- [ ] **Step 6: Commit** — `feat: Konto-Saldo-Anker mit ankerbasierter Saldenrechnung` +- [x] **Step 1: Failing Tests** — test_crud_api: (a) Konto mit Anker (Datum D, Betrag B) + bestätigte Buchungen vor/nach D → `account_balance(at=D)==B`, `at=D+2d` addiert spätere Buchung, `at=D−2d` subtrahiert dazwischenliegende; (b) PATCH setzt/löscht Anker, 422 bei nur-einem-Feld; test_gui: Übersicht zeigt Ankertext. +- [x] **Step 2: FAIL** · **Step 3: Implementieren + Alembic-Autogenerate gegen Wegwerf-SQLite** (Muster Task 2 Ausbaustufe 1; Migration committen) · **Step 4: PASS, Suite grün** +- [x] **Step 5: FABLE-TESTAGENT** verifiziert unabhängig (Suite + Anker-Randfälle: at==anchor_date, Buchung AM Ankertag zählt nicht zur Vorwärtssumme/wohl zur Rückwärtssumme — Konvention: Anker gilt per Tagesende). +- [x] **Step 6: Commit** — `feat: Konto-Saldo-Anker mit ankerbasierter Saldenrechnung` --- @@ -68,10 +68,10 @@ Beträge deutsch formatiert (`1.234,56`, Minus führend) → `parse_german_amoun - Produces: `csv_formats.detect_csv_format(head_bytes: bytes) -> str | None` („dkb_csv"|„vr_csv"|„hvb_csv"; erkennt Encoding inkl. UTF-16/BOM + Headersignatur); `csv_formats.parse_csv(path: Path) -> ParsedCsv` mit `ParsedCsv(statement: ParsedStatement, anchor: tuple[date, Decimal] | None, balance_checkable: bool)`. Transaktionen chronologisch aufsteigend im ParsedStatement, Mapping exakt gemäß Formatreferenz oben. VR: Saldo-Kette prüfen, bei Bruch `ParserError(„VR-CSV: Saldo-Kette inkonsistent bei Zeile N")`; opening/closing setzen (balance_checkable=True). DKB: anchor=(Datum aus „Kontostand vom", Betrag), opening/closing=None, nur „Gebucht". HVB: alles None/False. - ParserError bei unbekanntem Format/kaputter Struktur. -- [ ] **Step 1: Failing Tests** — pro Format parametrisiert (skip wenn Datei fehlt): Zeilenzahl >0, Transaktionen aufsteigend, Beträge Decimal, VR: balance_difference(stmt)==0 und anchor gesetzt, DKB: anchor gesetzt + alle Status Gebucht + counterparty je Vorzeichen befüllt, HVB: balance_checkable False; plus `expected_csv_.json` (gitignored, Schema wie expected_*: transaction_count + 5 spot_checks) — Dateien erstellt der CONTROLLER nach Implementierung aus Stichproben. -- [ ] **Step 2: FAIL** · **Step 3: Implementieren** (csv-Modul der stdlib; Encoding-Erkennung: BOM-Sniff + UTF-16-Heuristik über Nullbytes) · **Step 4: PASS** -- [ ] **Step 5: CONTROLLER erstellt expected-Dateien** (Stichproben aus den echten CSVs, nur lokal) · **Step 6: FABLE-TESTAGENT** verifiziert (Suite + eigene Stichproben-Gegenkontrolle CSV-Zeile↔geparste Transaktion für je 3 Zeilen pro Format, feldweise). -- [ ] **Step 7: Commit** — `feat: CSV-Parser fuer DKB/VR/HVB-Kontoumsatz-Exporte` +- [x] **Step 1: Failing Tests** — pro Format parametrisiert (skip wenn Datei fehlt): Zeilenzahl >0, Transaktionen aufsteigend, Beträge Decimal, VR: balance_difference(stmt)==0 und anchor gesetzt, DKB: anchor gesetzt + alle Status Gebucht + counterparty je Vorzeichen befüllt, HVB: balance_checkable False; plus `expected_csv_.json` (gitignored, Schema wie expected_*: transaction_count + 5 spot_checks) — Dateien erstellt der CONTROLLER nach Implementierung aus Stichproben. +- [x] **Step 2: FAIL** · **Step 3: Implementieren** (csv-Modul der stdlib; Encoding-Erkennung: BOM-Sniff + UTF-16-Heuristik über Nullbytes) · **Step 4: PASS** +- [x] **Step 5: CONTROLLER erstellt expected-Dateien** (Stichproben aus den echten CSVs, nur lokal) · **Step 6: FABLE-TESTAGENT** verifiziert (Suite + eigene Stichproben-Gegenkontrolle CSV-Zeile↔geparste Transaktion für je 3 Zeilen pro Format, feldweise). +- [x] **Step 7: Commit** — `feat: CSV-Parser fuer DKB/VR/HVB-Kontoumsatz-Exporte` --- @@ -85,10 +85,10 @@ Beträge deutsch formatiert (`1.234,56`, Minus führend) → `parse_german_amoun - Produces: preview-Response `balance_ok: bool | None`. Statement.bank erhält Formatkennung („dkb_csv" etc.). Duplikatschutz unverändert über dedup_hash (funktioniert für künftige überlappende CSV-Exporte, da identische Texte). - Anker-Regel: Import (bereits beim Draft-Anlegen) aktualisiert `account.anchor_*` nur, wenn CSV-Anker-Datum ≥ bestehendes Anker-Datum oder Konto ohne Anker; manuelles Überschreiben bleibt via PATCH möglich. -- [ ] **Step 1: Failing Tests** — Upload einer synthetischen Mini-CSV je Format (im Test als Bytes konstruiert nach Formatreferenz — KEINE echten Daten): 201 draft, preview balance_ok-Wert je Format (VR True, HVB None), confirm übernimmt, DKB-Anker am Konto gesetzt; Upload .txt → 400; Inbox-Scan findet .csv. -- [ ] **Step 2: FAIL** · **Step 3: Implementieren** · **Step 4: PASS, Suite grün** -- [ ] **Step 5: FABLE-TESTAGENT** verifiziert (Suite + Upload der ECHTEN 6 Dateien gegen Test-Instanz in-memory: je 201+plausible Zeilenzahlen — Zahlen nur als Counts berichten). -- [ ] **Step 6: Commit** — `feat: CSV-Import ueber bestehende Pipeline mit dreiwertiger Saldo-Pruefung` +- [x] **Step 1: Failing Tests** — Upload einer synthetischen Mini-CSV je Format (im Test als Bytes konstruiert nach Formatreferenz — KEINE echten Daten): 201 draft, preview balance_ok-Wert je Format (VR True, HVB None), confirm übernimmt, DKB-Anker am Konto gesetzt; Upload .txt → 400; Inbox-Scan findet .csv. +- [x] **Step 2: FAIL** · **Step 3: Implementieren** · **Step 4: PASS, Suite grün** +- [x] **Step 5: FABLE-TESTAGENT** verifiziert (Suite + Upload der ECHTEN 6 Dateien gegen Test-Instanz in-memory: je 201+plausible Zeilenzahlen — Zahlen nur als Counts berichten). +- [x] **Step 6: Commit** — `feat: CSV-Import ueber bestehende Pipeline mit dreiwertiger Saldo-Pruefung` --- @@ -101,8 +101,8 @@ Beträge deutsch formatiert (`1.234,56`, Minus führend) → `parse_german_amoun **Interfaces:** - GET /salden[?stichtag=YYYY-MM-DD] → Abschnitt 1 „Salden am " (Default heute): Tabelle Konto→Saldo (account_balance(at=stichtag)) + Gesamtzeile; Datumsformular (GET). Abschnitt 2 „Monatsanfangs-Salden": Zeilen = 1. jedes Monats von frühestem Buchungsmonat bis heute (absteigend), Spalten = Konten + Gesamt; Werte = account_balance(at=Monatsersten). Beträge 2 Nachkommastellen, .neg-Klasse, Konten ohne Anker mit Fußnote „ohne Anker — relative Werte". -- [ ] **Step 1: Failing Tests** — /salden in beide Seiten-Tests; mit Seed (Anker + Buchungen über 3 Monate): Stichtags-Tabelle zeigt erwarteten Kontosaldo, Monatsübersicht enthält 3 Monatszeilen mit korrektem Wert für einen definierten Monatsersten. -- [ ] **Step 2: FAIL** · **Step 3: Implementieren** · **Step 4: PASS** · **Step 5: FABLE-TESTAGENT** (Suite + Handrechnung eines Monatsanfangs-Werts gegen Seed-Daten) · **Step 6: Commit** — `feat: Salden-Seite mit Stichtag und Monatsuebersicht` +- [x] **Step 1: Failing Tests** — /salden in beide Seiten-Tests; mit Seed (Anker + Buchungen über 3 Monate): Stichtags-Tabelle zeigt erwarteten Kontosaldo, Monatsübersicht enthält 3 Monatszeilen mit korrektem Wert für einen definierten Monatsersten. +- [x] **Step 2: FAIL** · **Step 3: Implementieren** · **Step 4: PASS** · **Step 5: FABLE-TESTAGENT** (Suite + Handrechnung eines Monatsanfangs-Werts gegen Seed-Daten) · **Step 6: Commit** — `feat: Salden-Seite mit Stichtag und Monatsuebersicht` --- @@ -115,10 +115,10 @@ Beträge deutsch formatiert (`1.234,56`, Minus führend) → `parse_german_amoun **Interfaces:** - `parser_vs_csv.py `: matcht PDF-Transaktionen gegen CSV-Zeilen im Überlappungszeitraum über (booking_date, amount); gibt je Match Feldvergleich counterparty/purpose aus (Ähnlichkeit + Differenzen), am Ende Metrik: N matched, counterparty-Übereinstimmung x %, purpose-Kernübereinstimmung y %. Nur lokal, echte Daten nur im gitignorten Workspace. -- [ ] **Step 1: Werkzeug bauen (Subagent)** · **Step 2: CONTROLLER-Audit (Fable)**: Werkzeug auf DKB/VR/HVB-Überlappung (Juni–Juli 2026) laufen lassen, konkrete strukturelle Verbesserungen identifizieren (v. a. DKB: Empfänger/Zweck-Trennung — CSV-Empfängerspalte zeigt, wo die Grenze liegt; erwartbar: Empfänger = Anfang der ersten Fortsetzungszeile bis zum ersten Schlüsselwort-Muster). Mängelliste in `.superpowers/sdd/parser-vs-csv-audit.md` (gitignored). -- [ ] **Step 3: Parser-Fixes (Subagent, Mängelliste als Brief)** — Saldo-Gates und bestehende expected-Tests bleiben Pflicht; expected_*.json passt der CONTROLLER an, wo sich purposes verbessern. -- [ ] **Step 4: FABLE-TESTAGENT**: Suite + Metrik-Vergleich vorher/nachher (Werkzeug erneut ausführen; Verbesserung dokumentieren, Zahlen ohne echte Daten). **Fable-Abnahme durch Controller.** -- [ ] **Step 5: Commit** — `fix: PDF-Parser per CSV-Ground-Truth verbessert` (generische Beschreibung). Hinweis: „möglichst gut" = Best effort; verbleibende strukturbedingte Grenzen (z. B. DKB-Fließtext) werden dokumentiert, nicht erzwungen. +- [x] **Step 1: Werkzeug bauen (Subagent)** · **Step 2: CONTROLLER-Audit (Fable)**: Werkzeug auf DKB/VR/HVB-Überlappung (Juni–Juli 2026) laufen lassen, konkrete strukturelle Verbesserungen identifizieren (v. a. DKB: Empfänger/Zweck-Trennung — CSV-Empfängerspalte zeigt, wo die Grenze liegt; erwartbar: Empfänger = Anfang der ersten Fortsetzungszeile bis zum ersten Schlüsselwort-Muster). Mängelliste in `.superpowers/sdd/parser-vs-csv-audit.md` (gitignored). +- [x] **Step 3: Parser-Fixes (Subagent, Mängelliste als Brief)** — Saldo-Gates und bestehende expected-Tests bleiben Pflicht; expected_*.json passt der CONTROLLER an, wo sich purposes verbessern. +- [x] **Step 4: FABLE-TESTAGENT**: Suite + Metrik-Vergleich vorher/nachher (Werkzeug erneut ausführen; Verbesserung dokumentieren, Zahlen ohne echte Daten). **Fable-Abnahme durch Controller.** +- [x] **Step 5: Commit** — `fix: PDF-Parser per CSV-Ground-Truth verbessert` (generische Beschreibung). Hinweis: „möglichst gut" = Best effort; verbleibende strukturbedingte Grenzen (z. B. DKB-Fließtext) werden dokumentiert, nicht erzwungen. --- @@ -126,16 +126,16 @@ Beträge deutsch formatiert (`1.234,56`, Minus führend) → `parse_german_amoun **Files:** `finance/VERSION` → `0.4.0`; keine weiteren Code-Änderungen. -- [ ] **Step 1:** VERSION bump + Commit `chore: Version 0.4.0` → Image-Build → `create_pod_finance.sh` (Alembic-Migration läuft im Entrypoint). -- [ ] **Step 2 (CONTROLLER, beaufsichtigt):** (a) 3 PDF-Importe zurückrollen (Rollback-Feature); (b) HVB-Anker setzen: PATCH anchor_date=2026-07-03, anchor_balance=4559.51 (aus PDF-Auszug); (c) die 6 CSVs importieren (Reihenfolge egal, je: Upload → Preview prüfen [Zeilenzahl plausibel; VR balance_ok True; DKB/HVB Kennzeichnung sichtbar] → Confirm); DKB/VR-Anker kommen automatisch aus den Dateien; (d) Endkontrolle: Buchungszahl gesamt = Summe der CSV-Zeilen (minus evtl. Nicht-Gebucht), Salden-Seite: DKB-Saldo heute == Datei-Kontostand, VR-Saldo == neuester Saldo nach Buchung, HVB plausibel gegen Anker; Grafana-Kurven ab 2025; Suite grün; Smoke der Kernseiten. -- [ ] **Step 3:** Ledger + Plan-Häkchen + Commit; Hilfe-/Memory-Konsistenz. +- [x] **Step 1:** VERSION bump + Commit `chore: Version 0.4.0` → Image-Build → `create_pod_finance.sh` (Alembic-Migration läuft im Entrypoint). +- [x] **Step 2 (CONTROLLER, beaufsichtigt):** (a) 3 PDF-Importe zurückrollen (Rollback-Feature); (b) HVB-Anker setzen: PATCH anchor_date=2026-07-03, anchor_balance=4559.51 (aus PDF-Auszug); (c) die 6 CSVs importieren (Reihenfolge egal, je: Upload → Preview prüfen [Zeilenzahl plausibel; VR balance_ok True; DKB/HVB Kennzeichnung sichtbar] → Confirm); DKB/VR-Anker kommen automatisch aus den Dateien; (d) Endkontrolle: Buchungszahl gesamt = Summe der CSV-Zeilen (minus evtl. Nicht-Gebucht), Salden-Seite: DKB-Saldo heute == Datei-Kontostand, VR-Saldo == neuester Saldo nach Buchung, HVB plausibel gegen Anker; Grafana-Kurven ab 2025; Suite grün; Smoke der Kernseiten. +- [x] **Step 3:** Ledger + Plan-Häkchen + Commit; Hilfe-/Memory-Konsistenz. --- ## Abschluss-Checkliste -- [ ] Suite grün (>= 90 Tests erwartet); alle Task-Verifikationen durch FABLE-Testagenten dokumentiert -- [ ] Live: v0.4.0; Datenbestand vollständig aus 6 CSVs (2025-01-01 bis heute), Anker je Konto gesetzt, Salden-Seite konsistent mit CSV-Quellwerten -- [ ] Parser-Tuning-Metriken dokumentiert (vorher/nachher), Fable-Abnahme erteilt -- [ ] Keine echten Kontodaten/Secrets in git log beider Repos; CSV/PDF/expected-Dateien untracked -- [ ] Plan-Häkchen gesetzt, beide Repos committet +- [x] Suite grün (>= 90 Tests erwartet); alle Task-Verifikationen durch FABLE-Testagenten dokumentiert +- [x] Live: v0.4.0; Datenbestand vollständig aus 6 CSVs (2025-01-01 bis heute), Anker je Konto gesetzt, Salden-Seite konsistent mit CSV-Quellwerten +- [x] Parser-Tuning-Metriken dokumentiert (vorher/nachher), Fable-Abnahme erteilt +- [x] Keine echten Kontodaten/Secrets in git log beider Repos; CSV/PDF/expected-Dateien untracked +- [x] Plan-Häkchen gesetzt, beide Repos committet