Architektur: Domain-Driven Design — Analyse (nur Bewertung, keine Umgestaltung) #136

Closed
opened 2026-04-20 01:09:31 +02:00 by tobias · 4 comments
Owner

Kontext

Das Repository ist organisch gewachsen (Solo-Entwicklung, ~1 Jahr, derzeit
ca. 22 Module in webapp/app/, technisch geschichtet nach Funktionalität:
models.py, database.py, analyzer.py, parlamente.py, …). Das ist eine
Technical Layering-Architektur — sauber genug für den aktuellen Scope,
aber wenn das Projekt reift (mehr Bundesländer, Abstimmungsverhalten,
Trendanalysen, externe Konsumenten der API) droht der klassische
Big-Ball-of-Mud-Drift.

Dieser Issue fragt: Wie müsste das Repo aussehen, wenn wir konsequent
Domain-Driven Design anwenden würden?
reine Analyse, keine
Umgestaltung. Ergebnis ist ein Dokument mit Zielbild, Trade-off-Bewertung
und Empfehlung, ob/in-welchem-Umfang die Migration sich lohnt.

Explizit kein Code-Change in diesem Issue. Wenn die Analyse zu einer
Empfehlung "umsetzen" kommt, werden konkrete Umsetzungs-Issues separat
angelegt.

Aufgabe

Als DDD-Experte das Repo durchsehen und als Markdown-Deliverable in
webapp/docs/analysen/ddd-bewertung.md (neue Datei) ablegen:

1. Ist-Zustand dokumentieren

  • Module-Inventar: app/*.py × Verantwortung × erkennbare Verletzungen
    (anämisches Modell, Infrastruktur-Leaks, fehlende Abstraktion)
  • Konkrete Beispiele mit Zeilennummern (z.B. analyzer.py:231 mischt
    Domain-Logik, Infrastruktur-Call und Retry-Loop)
  • Ubiquitous-Language-Inkonsistenzen: Deutsch/Englisch-Mix auflisten

2. Bounded Contexts identifizieren

Minimum zu benennen und zu charakterisieren (Core / Supporting / Generic):

Kontext-Kandidat Typ Kern-Konzepte
Antragsbewertung Core Antrag, Bewertung, GWÖ-Matrix, Empfehlung, Zitat
Wahlprogramm-Wissensbasis Supporting Programm, Chunk, Embedding
Parlamentsintegration Supporting Drucksache, Bundesland, Wahlperiode, Adapter
Publikation Supporting Report, Feed, Sharing-Post
Benutzer & Abonnement Generic User, Subscription, Bookmark, Kommentar
Monitoring Generic Scan, Tagesstatistik, Kostenprognose

Analyse prüft diese Liste, ergänzt/verwirft/kombiniert, begründet.

3. Zielbild skizzieren (nur als Referenz, nicht umsetzen)

  • Ordner-Skelett unter DDD (Ports-and-Adapters / Hexagonal)
  • Beispiel-Refactoring eines Hot-Spots als Pseudo-Code (z.B. analyzer.py
    antragsbewertung/application/bewerte_antrag.py). Nur zur Illustration,
    keine Implementation
  • Mapping-Tabelle: aktuelle Datei → künftiger Bounded Context

4. Ubiquitous Language

Glossar-Skelett mit den 20-30 wichtigsten Begriffen, Deutsch als
Domänen-Sprache (weil Domäne = deutsche Landtage), Englisch nur für
Infrastruktur-Konzepte.

5. Trade-off-Bewertung — ehrlich

  • Kosten von Voll-DDD für ein Solo-Projekt dieser Größe (Boilerplate,
    kognitive Einstiegshürde, geschätzte Nettozeit)
  • Nutzen (Testbarkeit, Austauschbarkeit von LLM/Adapter, Onboarding)
  • Lightweight-Alternative: welche 2-3 DDD-Prinzipien bringen 60% des
    Nutzens bei 15% des Aufwands (z.B. Repository-Pattern + DTO-Trennung,
    ohne Voll-Package-Split)?
  • Risiko-Assessment: was passiert, wenn wir nicht migrieren, in
    1 Jahr / 3 Jahren / bei 3× so vielen Contexts?

6. Empfehlung

Drei Optionen bewertet und priorisiert:

  • A) Voll-DDD (Strangler Fig, 4-8 Wochen netto)
  • B) Lightweight (Repository + DTO-Trennung, 1-2 Wochen)
  • C) Status quo (weiter organisch, dokumentierte Regeln statt
    Strukturzwang)

Mit klarer Empfehlung welche Option unter Berücksichtigung von Projekt-
Charakter (Solo, Beta-artig, hoher Erkenntnisgewinn-pro-Feature) passt.

Deliverables

  • webapp/docs/analysen/ddd-bewertung.md — Volltext-Analyse nach
    obigem Raster
  • Context-Map als Mermaid-Diagramm inline in der Analyse
  • Glossar-Skelett (20-30 Begriffe) inline oder als separate
    webapp/docs/glossar.md (Entwurfsstatus)
  • Gitea-Kommentar hier mit Executive Summary (max 300 Wörter,
    Empfehlung + 3 Begründungs-Bullets)

Akzeptanzkriterien

  • Analyse nennt konkrete Dateien/Zeilen, keine Allgemein-Floskeln
  • Trade-off-Abschnitt hat eine nachvollziehbare Kosten-/Nutzen-Rechnung,
    nicht nur "DDD ist immer besser"
  • Empfehlung ist explizit eine der drei Optionen, nicht "kommt drauf an"
  • Kein Code-Change in diesem Issue. Umsetzungs-Issues folgen
    separat, wenn die Empfehlung das hergibt

Nicht-Ziele

  • Kein Refactoring, keine Datei-Verschiebung, keine neuen Package-Ordner
  • Kein ADR — der kommt erst, wenn die Analyse eine Entscheidung stützt
  • Keine Test-Strategie-Aussage — das ist #134

Bezug

  • #134 Test-Suite-Audit (DDD-Migration würde Tests anders schneiden)
  • #135 Monitoring (Greenfield-Kandidat, falls man die neue Struktur
    probeweise dort testen will)
  • ADR 0002 Adapter-Architektur — Grundlage, weil bereits Ansatz von
    Ports-and-Adapters
## Kontext Das Repository ist organisch gewachsen (Solo-Entwicklung, ~1 Jahr, derzeit ca. 22 Module in `webapp/app/`, technisch geschichtet nach Funktionalität: `models.py`, `database.py`, `analyzer.py`, `parlamente.py`, …). Das ist eine *Technical Layering*-Architektur — sauber genug für den aktuellen Scope, aber wenn das Projekt reift (mehr Bundesländer, Abstimmungsverhalten, Trendanalysen, externe Konsumenten der API) droht der klassische Big-Ball-of-Mud-Drift. Dieser Issue fragt: *Wie müsste das Repo aussehen, wenn wir konsequent Domain-Driven Design anwenden würden?* — **reine Analyse**, keine Umgestaltung. Ergebnis ist ein Dokument mit Zielbild, Trade-off-Bewertung und Empfehlung, ob/in-welchem-Umfang die Migration sich lohnt. **Explizit kein Code-Change in diesem Issue.** Wenn die Analyse zu einer Empfehlung "umsetzen" kommt, werden konkrete Umsetzungs-Issues *separat* angelegt. ## Aufgabe Als DDD-Experte das Repo durchsehen und als Markdown-Deliverable in `webapp/docs/analysen/ddd-bewertung.md` (neue Datei) ablegen: ### 1. Ist-Zustand dokumentieren - Module-Inventar: `app/*.py` × Verantwortung × erkennbare Verletzungen (anämisches Modell, Infrastruktur-Leaks, fehlende Abstraktion) - Konkrete Beispiele mit Zeilennummern (z.B. `analyzer.py:231` mischt Domain-Logik, Infrastruktur-Call und Retry-Loop) - Ubiquitous-Language-Inkonsistenzen: Deutsch/Englisch-Mix auflisten ### 2. Bounded Contexts identifizieren Minimum zu benennen und zu charakterisieren (Core / Supporting / Generic): | Kontext-Kandidat | Typ | Kern-Konzepte | |---|---|---| | Antragsbewertung | Core | Antrag, Bewertung, GWÖ-Matrix, Empfehlung, Zitat | | Wahlprogramm-Wissensbasis | Supporting | Programm, Chunk, Embedding | | Parlamentsintegration | Supporting | Drucksache, Bundesland, Wahlperiode, Adapter | | Publikation | Supporting | Report, Feed, Sharing-Post | | Benutzer & Abonnement | Generic | User, Subscription, Bookmark, Kommentar | | Monitoring | Generic | Scan, Tagesstatistik, Kostenprognose | Analyse prüft diese Liste, ergänzt/verwirft/kombiniert, begründet. ### 3. Zielbild skizzieren (nur als Referenz, nicht umsetzen) - Ordner-Skelett unter DDD (Ports-and-Adapters / Hexagonal) - Beispiel-Refactoring *eines* Hot-Spots als Pseudo-Code (z.B. `analyzer.py` → `antragsbewertung/application/bewerte_antrag.py`). Nur zur Illustration, keine Implementation - Mapping-Tabelle: aktuelle Datei → künftiger Bounded Context ### 4. Ubiquitous Language Glossar-Skelett mit den 20-30 wichtigsten Begriffen, Deutsch als Domänen-Sprache (weil Domäne = deutsche Landtage), Englisch nur für Infrastruktur-Konzepte. ### 5. Trade-off-Bewertung — ehrlich - **Kosten** von Voll-DDD für ein Solo-Projekt dieser Größe (Boilerplate, kognitive Einstiegshürde, geschätzte Nettozeit) - **Nutzen** (Testbarkeit, Austauschbarkeit von LLM/Adapter, Onboarding) - **Lightweight-Alternative**: welche 2-3 DDD-Prinzipien bringen 60% des Nutzens bei 15% des Aufwands (z.B. Repository-Pattern + DTO-Trennung, ohne Voll-Package-Split)? - **Risiko-Assessment**: was passiert, wenn wir *nicht* migrieren, in 1 Jahr / 3 Jahren / bei 3× so vielen Contexts? ### 6. Empfehlung Drei Optionen bewertet und priorisiert: - **A) Voll-DDD** (Strangler Fig, 4-8 Wochen netto) - **B) Lightweight** (Repository + DTO-Trennung, 1-2 Wochen) - **C) Status quo** (weiter organisch, dokumentierte Regeln statt Strukturzwang) Mit klarer Empfehlung welche Option unter Berücksichtigung von Projekt- Charakter (Solo, Beta-artig, hoher Erkenntnisgewinn-pro-Feature) passt. ## Deliverables - [ ] `webapp/docs/analysen/ddd-bewertung.md` — Volltext-Analyse nach obigem Raster - [ ] Context-Map als Mermaid-Diagramm inline in der Analyse - [ ] Glossar-Skelett (20-30 Begriffe) inline oder als separate `webapp/docs/glossar.md` (Entwurfsstatus) - [ ] Gitea-Kommentar hier mit **Executive Summary** (max 300 Wörter, Empfehlung + 3 Begründungs-Bullets) ## Akzeptanzkriterien - Analyse nennt konkrete Dateien/Zeilen, keine Allgemein-Floskeln - Trade-off-Abschnitt hat eine nachvollziehbare Kosten-/Nutzen-Rechnung, nicht nur "DDD ist immer besser" - Empfehlung ist explizit **eine** der drei Optionen, nicht "kommt drauf an" - **Kein Code-Change in diesem Issue.** Umsetzungs-Issues folgen separat, wenn die Empfehlung das hergibt ## Nicht-Ziele - Kein Refactoring, keine Datei-Verschiebung, keine neuen Package-Ordner - Kein ADR — der kommt erst, wenn die Analyse eine Entscheidung stützt - Keine Test-Strategie-Aussage — das ist #134 ## Bezug - #134 Test-Suite-Audit (DDD-Migration würde Tests anders schneiden) - #135 Monitoring (Greenfield-Kandidat, falls man die neue Struktur probeweise dort testen will) - ADR 0002 Adapter-Architektur — Grundlage, weil bereits Ansatz von Ports-and-Adapters
tobias changed title from Architektur: Domain-Driven Design konsequent anwenden — Analyse + Migrationspfad to Architektur: Domain-Driven Design — Analyse (nur Bewertung, keine Umgestaltung) 2026-04-20 01:10:15 +02:00
Author
Owner

Executive Summary

Empfehlung: Option B — Lightweight DDD (ca. 5-8 Tage, ohne Package-Split).

Volltext in webapp/docs/analysen/ddd-bewertung.md.

Begründung in 3 Bullets

  1. Voll-DDD rechnet sich nicht für Solo-Projekt — die Domäne ist mittel-komplex, aber Change-Rate hoch (tgl. Features). 4-8 Wochen Big-Refactor würden den Feature-Flow abwürgen, während der Hauptgewinn (Team-Parallelisierbarkeit) hier nicht zutrifft.

  2. Drei gezielte Lightweight-Eingriffe lösen die akuten Schmerzpunkte:

    • AntragRepository/BewertungRepository → DB-Leak aus 5 Call-Sites (database.py hat heute 0% Coverage bei 299 LOC)
    • LlmBewerter-Port → AsyncOpenAI raus aus analyzer.py:234-237, macht conftest.py-Stubbing obsolet
    • Verhalten auf Domain-Objekte ziehen — die System-Prompt-Regeln (analyzer.py:167-171) gehören als Methoden auf Bewertung/MatrixFeld
  3. Status-quo ist auch nicht kostenlos — Coverage-Zahlen aus #134 (database.py 0%, mail.py 0%, main.py 1%) zeigen, dass die Flachstruktur den Test-Unterbau ausdünnt. Lightweight-DDD adressiert das ohne Big-Bang.

Nicht-Empfehlungen

  • Option A (Voll-DDD): nur, wenn das Projekt in ein Team übergeht oder absehbar 3× so viele Kontexte bekommt
  • Option C (Status quo): nur, wenn die nächsten 6 Monate ausschließlich Feature-Drift sind — bei dieser Coverage-Basis nicht empfohlen

Reihenfolge (wenn Option B gewählt)

  1. Repository-Pattern (1-2 Tage) — akuter Pain
  2. LlmBewerter-Port (2-3 Tage) — Test-Hygiene
  3. Domain-Verhalten (1-2 Tage) — Invarianten ins Modell

Greenfield-Test

#135 Monitoring hat noch keinen Code — guter Kandidat, die neue Struktur probeweise direkt richtig zu bauen, ohne Migrationsrisiko.


Analyse durch Claude Code autonom 2026-04-20. Kein Code-Change, wie vom Issue-Scope gefordert.

## Executive Summary **Empfehlung: Option B — Lightweight DDD** (ca. 5-8 Tage, ohne Package-Split). Volltext in `webapp/docs/analysen/ddd-bewertung.md`. ### Begründung in 3 Bullets 1. **Voll-DDD rechnet sich nicht für Solo-Projekt** — die Domäne ist mittel-komplex, aber Change-Rate hoch (tgl. Features). 4-8 Wochen Big-Refactor würden den Feature-Flow abwürgen, während der Hauptgewinn (Team-Parallelisierbarkeit) hier nicht zutrifft. 2. **Drei gezielte Lightweight-Eingriffe lösen die akuten Schmerzpunkte:** - `AntragRepository`/`BewertungRepository` → DB-Leak aus 5 Call-Sites (`database.py` hat heute 0% Coverage bei 299 LOC) - `LlmBewerter`-Port → `AsyncOpenAI` raus aus `analyzer.py:234-237`, macht `conftest.py`-Stubbing obsolet - Verhalten auf Domain-Objekte ziehen — die System-Prompt-Regeln (`analyzer.py:167-171`) gehören als Methoden auf `Bewertung`/`MatrixFeld` 3. **Status-quo ist auch nicht kostenlos** — Coverage-Zahlen aus #134 (database.py 0%, mail.py 0%, main.py 1%) zeigen, dass die Flachstruktur den Test-Unterbau ausdünnt. Lightweight-DDD adressiert das ohne Big-Bang. ### Nicht-Empfehlungen - **Option A (Voll-DDD):** nur, wenn das Projekt in ein Team übergeht oder absehbar 3× so viele Kontexte bekommt - **Option C (Status quo):** nur, wenn die nächsten 6 Monate ausschließlich Feature-Drift sind — bei dieser Coverage-Basis nicht empfohlen ### Reihenfolge (wenn Option B gewählt) 1. Repository-Pattern (1-2 Tage) — akuter Pain 2. `LlmBewerter`-Port (2-3 Tage) — Test-Hygiene 3. Domain-Verhalten (1-2 Tage) — Invarianten ins Modell ### Greenfield-Test #135 Monitoring hat noch keinen Code — guter Kandidat, die neue Struktur probeweise direkt richtig zu bauen, ohne Migrationsrisiko. --- _Analyse durch Claude Code autonom 2026-04-20. Kein Code-Change, wie vom Issue-Scope gefordert._
Author
Owner

Analyse vertieft — fertig (Opus 4.7)

webapp/docs/analysen/ddd-bewertung.md: 439 → 1237 Zeilen (≈2.8×), kein Code angefasst.

Neue/ausgebaute Kapitel

  • Kap. 1.1 — LOC-Zahlen korrigiert: parlamente.py 3397 statt vorher 1425 geschätzt, main.py 1746 statt 680, analyzer.py 379 statt 138. Das Projekt ist deutlich größer als die alte Analyse angenommen hatte (11789 LOC gesamt).
  • Kap. 2.2 (neu) — Aggregate/Entities/VOs pro Context mit impliziten Invarianten-Liste (inkl. Zeilen-Referenzen)
  • Kap. 2.3 — Context-Map mit Beziehungstypen (Customer-Supplier, Shared-Kernel, Conformist, Anti-Corruption, Published Language)
  • Kap. 2.4 (neu) — 5 konkrete Anti-Corruption-Layer-Kandidaten mit Code-Pfaden
  • Kap. 3.2-3.7 — 4 volle Pseudo-Code-Beispiele (Bewertung, MatrixFeld, Ports, Application-Service); Repository-Vorlage mit SQLite+In-Memory-Fake; DI-Urteil pro FastAPI Depends
  • Kap. 4 — Glossar 24 → 58 Begriffe, mit Quellen-Referenz und Verwechslungs-Flags
  • Kap. 9 (neu) — Test-Strategie mit Migration der 296 Unit / 27 Integration / 20 E2E-Tests
  • Kap. 10 (neu) — 8-Tage-Roadmap mit Mermaid-Abhängigkeitsgraph, pro Tag 3-5 Schritte + AK, Risiko-Matrix, Ausstiegs-Trigger
  • Kap. 11 (neu) — Ehrliche Negativ-Abgrenzung: was DDD NICHT löst (Halluzinationen, Adapter-Drift, Performance, DX, Daten-Migrations-Risiko)

Kernerkenntnis

Die Invarianten aus analyzer.py:168-171 und :101-106 sind heute schon testbarer Python-Code, der nur im LLM-System-Prompt lebt. Das LLM kann sie jederzeit still verletzen — strukturelles Risiko, das DDD-Lightweight (Option B) durch Domain-Verhalten auf Bewertung/MatrixFeld direkt adressieren würde.

Empfehlung unverändert

Option B (Lightweight, 5-8 Tage) — Vertiefung stützt die Empfehlung, kippt sie nicht. Tages-Roadmap (Kap. 10) ist jetzt ausdruckbar und abarbeitbar.

Willst du die Umsetzung starten, eigenes Issue #139 mit der Roadmap aus Kap. 10?

## Analyse vertieft — fertig (Opus 4.7) `webapp/docs/analysen/ddd-bewertung.md`: **439 → 1237 Zeilen** (≈2.8×), kein Code angefasst. ### Neue/ausgebaute Kapitel - **Kap. 1.1** — LOC-Zahlen korrigiert: `parlamente.py` 3397 statt vorher 1425 geschätzt, `main.py` 1746 statt 680, `analyzer.py` 379 statt 138. **Das Projekt ist deutlich größer als die alte Analyse angenommen hatte (11789 LOC gesamt).** - **Kap. 2.2 (neu)** — Aggregate/Entities/VOs pro Context mit impliziten Invarianten-Liste (inkl. Zeilen-Referenzen) - **Kap. 2.3** — Context-Map mit Beziehungstypen (Customer-Supplier, Shared-Kernel, Conformist, Anti-Corruption, Published Language) - **Kap. 2.4 (neu)** — 5 konkrete Anti-Corruption-Layer-Kandidaten mit Code-Pfaden - **Kap. 3.2-3.7** — 4 volle Pseudo-Code-Beispiele (`Bewertung`, `MatrixFeld`, Ports, Application-Service); Repository-Vorlage mit SQLite+In-Memory-Fake; DI-Urteil pro FastAPI `Depends` - **Kap. 4** — Glossar 24 → 58 Begriffe, mit Quellen-Referenz und Verwechslungs-Flags - **Kap. 9 (neu)** — Test-Strategie mit Migration der 296 Unit / 27 Integration / 20 E2E-Tests - **Kap. 10 (neu)** — 8-Tage-Roadmap mit Mermaid-Abhängigkeitsgraph, pro Tag 3-5 Schritte + AK, Risiko-Matrix, Ausstiegs-Trigger - **Kap. 11 (neu)** — Ehrliche Negativ-Abgrenzung: was DDD NICHT löst (Halluzinationen, Adapter-Drift, Performance, DX, Daten-Migrations-Risiko) ### Kernerkenntnis Die **Invarianten aus `analyzer.py:168-171` und `:101-106`** sind heute schon testbarer Python-Code, der nur im LLM-System-Prompt lebt. Das LLM kann sie jederzeit still verletzen — strukturelles Risiko, das DDD-Lightweight (Option B) durch Domain-Verhalten auf `Bewertung`/`MatrixFeld` direkt adressieren würde. ### Empfehlung unverändert **Option B (Lightweight, 5-8 Tage)** — Vertiefung stützt die Empfehlung, kippt sie nicht. Tages-Roadmap (Kap. 10) ist jetzt ausdruckbar und abarbeitbar. Willst du die Umsetzung starten, eigenes Issue #139 mit der Roadmap aus Kap. 10?
Author
Owner

DDD-Lightweight-Migration — Tag 1-4 abgeschlossen

Umgesetzt

Neu

  • app/repositories/{antrag,bewertung,abonnement}_repository.py — Protocol + Sqlite-Impl + InMemory-Fake
  • app/ports/llm_bewerter.pyLlmBewerter-Protocol + LlmRequest-Dataclass
  • app/adapters/qwen_bewerter.py — QwenBewerter, kapselt AsyncOpenAI + Retry-Loop + Markdown-Stripping
  • docs/adr/0008-ddd-lightweight-migration.md

Geändert

  • app/analyzer.py::analyze_antrag nimmt optional bewerter-Parameter; AsyncOpenAI-Import raus; nutzt Port
  • app/models.py — 5 neue Domain-Methoden: Assessment.ist_ablehnung(), ist_uneingeschraenkt_unterstuetzend(), hat_fundamental_kritisches_feld(), verletzt_score_cap(); MatrixEntry.ist_fundamental_kritisch(), to_symbol()
  • analyze_antrag loggt WARNING wenn LLM-Output die Score-Cap-Invariante verletzt (Score ≤ 3 bei Feld ≤ -4)

Tests

+105 neue Tests (105 = 21 AntragRepo + 5 BewertungRepo + 11 AbonnementRepo + 13 LlmBewerter + 26 Domain-Behavior + 29 via parametrize). Gesamt: 574 passed, 0 Regressions.

Deploy-Risiko

Niedrig bis mittel. Kein API-Breaking-Change. Einziger Laufzeit-Unterschied: Retry-Logs gehen jetzt unter app.adapters.qwen_bewerter statt app.analyzer — wer log-filter setzt, muss das nachpflegen.

Nicht-Migriert (Folge-PR)

  1. Callsite-Migration in main.py — 21 direkte database.*-Calls auf Depends(get_antrag_repository) umstellen. Rein mechanisch, aber wegen 1746 LOC in einer Datei mit Konflikt-Potenzial bewusst ausgelagert
  2. Migration weiterer Caller (mail.py, monitoring.py)
  3. conftest.py::_stub("openai") entfernen — geht, sobald alle Caller nur noch lazy importieren
  4. Tag 5/6/7 der DDD-Roadmap — ZitatVerifier-Port, frozen Domain-Dataclasses. Nicht Scope dieser Migration

Die Fundament-Arbeit ist da. Weitere Migration kann inkrementell im Folge-PR erfolgen.

## DDD-Lightweight-Migration — Tag 1-4 abgeschlossen ### Umgesetzt **Neu** - `app/repositories/{antrag,bewertung,abonnement}_repository.py` — Protocol + Sqlite-Impl + InMemory-Fake - `app/ports/llm_bewerter.py` — `LlmBewerter`-Protocol + `LlmRequest`-Dataclass - `app/adapters/qwen_bewerter.py` — QwenBewerter, kapselt AsyncOpenAI + Retry-Loop + Markdown-Stripping - `docs/adr/0008-ddd-lightweight-migration.md` **Geändert** - `app/analyzer.py::analyze_antrag` nimmt optional `bewerter`-Parameter; AsyncOpenAI-Import raus; nutzt Port - `app/models.py` — 5 neue Domain-Methoden: `Assessment.ist_ablehnung()`, `ist_uneingeschraenkt_unterstuetzend()`, `hat_fundamental_kritisches_feld()`, `verletzt_score_cap()`; `MatrixEntry.ist_fundamental_kritisch()`, `to_symbol()` - `analyze_antrag` loggt `WARNING` wenn LLM-Output die Score-Cap-Invariante verletzt (Score ≤ 3 bei Feld ≤ -4) ### Tests **+105 neue Tests** (105 = 21 AntragRepo + 5 BewertungRepo + 11 AbonnementRepo + 13 LlmBewerter + 26 Domain-Behavior + 29 via parametrize). Gesamt: **574 passed**, 0 Regressions. ### Deploy-Risiko Niedrig bis mittel. **Kein** API-Breaking-Change. Einziger Laufzeit-Unterschied: Retry-Logs gehen jetzt unter `app.adapters.qwen_bewerter` statt `app.analyzer` — wer log-filter setzt, muss das nachpflegen. ### Nicht-Migriert (Folge-PR) 1. **Callsite-Migration in `main.py`** — 21 direkte `database.*`-Calls auf `Depends(get_antrag_repository)` umstellen. Rein mechanisch, aber wegen 1746 LOC in einer Datei mit Konflikt-Potenzial bewusst ausgelagert 2. **Migration weiterer Caller** (`mail.py`, `monitoring.py`) 3. **`conftest.py::_stub("openai")` entfernen** — geht, sobald alle Caller nur noch lazy importieren 4. **Tag 5/6/7 der DDD-Roadmap** — ZitatVerifier-Port, frozen Domain-Dataclasses. Nicht Scope dieser Migration Die Fundament-Arbeit ist da. Weitere Migration kann inkrementell im Folge-PR erfolgen.
tobias added this to the 1.0 milestone 2026-04-25 20:59:56 +02:00
Author
Owner

Tag 1-4 in Commits 8f0f6d6 + 20b33c7 (Release 1.0) gelandet. Callsite-Migration in main.py als Folge-PR. ADR 0008 schreibt das Vorgehen fest. Schliesse als 1.0-Done.

Tag 1-4 in Commits 8f0f6d6 + 20b33c7 (Release 1.0) gelandet. Callsite-Migration in main.py als Folge-PR. ADR 0008 schreibt das Vorgehen fest. Schliesse als 1.0-Done.
Sign in to join this conversation.
No description provided.