Doku: Modulare Architektur-Dokumentation (#34)

Drei neue Architektur-Übersichten unter docs/architecture/ angelegt
(domain-overview, gui-overview, adapter-overview), die das bisher in
CLAUDE.md verstreute Detailwissen zu Paketen, Schlüsselklassen, Ports
und Bootstrap-Verdrahtung pro Modulbereich bündeln. CLAUDE.md verweist
auf die drei Dateien und enthält das Detailwissen nicht mehr selbst,
sodass Arbeit an einem Modulbereich mit CLAUDE.md plus der jeweils
passenden Übersicht auskommt. Workpackage-Liste um M14 und M15 ergänzt;
V2.9-Implementierungsstand auf Modul-/Verhaltensebene konsolidiert.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-28 16:21:58 +02:00
parent 330bcfe124
commit bdc5e8331f
4 changed files with 670 additions and 24 deletions
+170
View File
@@ -0,0 +1,170 @@
# Architektur-Übersicht: Domain & Application
Dieses Dokument beschreibt die fachliche und anwendungsnahe Schicht des PDF-Umbenenners: das Modul `pdf-umbenenner-domain` und das Modul `pdf-umbenenner-application`. Es richtet sich an Entwickler, die in diesen beiden Modulen arbeiten, und soll als alleiniger Architekturkontext ausreichen ergänzt durch die `CLAUDE.md` im Projektroot. Nicht enthalten sind Adapter-Implementierungen (Dateisystem, PDFBox, SQLite, HTTP-Clients); diese sind in `adapter-overview.md` beschrieben. GUI-spezifische Ports und deren Einbettung in den Konfigurationseditor sind in `gui-overview.md` dokumentiert.
---
## 1. Modulzweck
### `pdf-umbenenner-domain`
Enthält ausschließlich fachliche Kerntypen (Records, Enums, Sealed Interfaces) ohne jegliche Infrastrukturabhängigkeiten. Alle Typen modellieren den Problembereich und sind von anderen Modulen referenzierbar, ohne transitive Abhängigkeiten einzuschleppen.
### `pdf-umbenenner-application`
Definiert Use-Case-Orchestrierung sowie alle Inbound- und Outbound-Ports der hexagonalen Architektur. Enthält anwendungsnahe Dienste (KI-Antwort-Parsing, Pre-Check-Auswertung, Retry-Entscheidung) und Konfigurationsmodelle, aber keinerlei Infrastrukturcode (kein JDBC, kein PDFBox, kein HTTP-Client, kein JavaFX).
---
## 2. Paketstruktur
### `pdf-umbenenner-domain`
| Paket | Verantwortung |
|-------|---------------|
| `de.gecheckt.pdf.umbenenner.domain` | Wurzelpaket; enthält nur `package-info.java` |
| `de.gecheckt.pdf.umbenenner.domain.model` | Alle fachlichen Kerntypen: Records, Sealed Interfaces und Enums, die die Verarbeitungsdomäne beschreiben |
### `pdf-umbenenner-application`
| Paket | Verantwortung |
|-------|---------------|
| `de.gecheckt.pdf.umbenenner.application` | Wurzelpaket des Application-Moduls |
| `de.gecheckt.pdf.umbenenner.application.port.in` | Inbound-Ports (Use-Case-Interfaces) Einstiegspunkte für den Aufrufer |
| `de.gecheckt.pdf.umbenenner.application.port.out` | Outbound-Ports Verträge gegenüber Infrastruktur-Adaptern (Persistenz, Dateisystem, KI, Uhr, Logging) |
| `de.gecheckt.pdf.umbenenner.application.port.out.modelcatalog` | Spezialisierter Outbound-Port für den Abruf verfügbarer KI-Modelle; ausschließlich im GUI-Pfad genutzt (siehe `gui-overview.md`) |
| `de.gecheckt.pdf.umbenenner.application.service` | Anwendungsnahe, zustandslose Dienste: KI-Antwort-Parsing, Pre-Check-Auswertung, Verarbeitungs-Pipeline, Retry-Entscheidung |
| `de.gecheckt.pdf.umbenenner.application.config` | Konfigurationsmodelle der Anwendungsschicht (`RuntimeConfiguration`, Provider-Konfiguration) |
| `de.gecheckt.pdf.umbenenner.application.config.startup` | Vollständiges Startup-Konfigurationsmodell (`StartConfiguration`) |
| `de.gecheckt.pdf.umbenenner.application.config.provider` | Modelle für KI-Provider-Konfiguration (Provider-Familie, Einzelkonfiguration, Multi-Provider) |
| `de.gecheckt.pdf.umbenenner.application.validation.editor` | Validierungslogik für den GUI-Konfigurationseditor (Findings, Report, API-Key-Auflösung); siehe `gui-overview.md` |
| `de.gecheckt.pdf.umbenenner.application.validation.technicaltest` | Technischer Selbsttest: Pfad-Checks, Korrekturpläne, Checkpoints; Details in `gui-overview.md` |
| `de.gecheckt.pdf.umbenenner.application.usecase` | Paket-Marker für Use-Case-Implementierungen |
---
## 3. Schlüsselklassen
### Domain-Modul
**`de.gecheckt.pdf.umbenenner.domain.model.SourceDocumentCandidate`**
Record für einen PDF-Kandidaten aus dem Quellordner. Enthält keinen `Path`, sondern einen opaken `SourceDocumentLocator`, damit die Domain frei von NIO-Typen bleibt.
**`de.gecheckt.pdf.umbenenner.domain.model.DocumentFingerprint`**
Record mit einem SHA-256-Hex-String (64 Zeichen) als stabiler Dokumentidentität; Grundlage für Idempotenz und Persistenz-Lookup.
**`de.gecheckt.pdf.umbenenner.domain.model.DocumentProcessingOutcome`**
Sealed Interface mit sechs Implementierungen, die alle möglichen Ausgänge der Dokumentverarbeitung exhaustiv abbilden:
| Implementierung | Bedeutung |
|-----------------|-----------|
| `PreCheckPassed` | Vorprüfung bestanden, KI-Pfad freigegeben |
| `PreCheckFailed` | Deterministischer Inhaltsfehler vor KI-Aufruf |
| `TechnicalDocumentError` | Technischer Fehler ohne erneuten KI-Aufruf |
| `NamingProposalReady` | KI-Antwort gültig, Vorschlag liegt vor |
| `AiTechnicalFailure` | Transienter technischer Fehler beim KI-Aufruf |
| `AiFunctionalFailure` | Deterministischer fachlicher Fehler der KI-Antwort |
**`de.gecheckt.pdf.umbenenner.domain.model.ProcessingStatus`**
Enum mit acht Zuständen. Dokumentiert Zustandsübergänge und Retry-Schwellen; fachliches Herzstück der Persistenz-Semantik.
| Status | Bedeutung |
|--------|-----------|
| `READY_FOR_AI` | Verarbeitbar, KI-Pfad noch nicht durchlaufen |
| `FAILED_RETRYABLE` | Verarbeitbar, transient fehlgeschlagen |
| `PROPOSAL_READY` | Eingangszustand für Dateinamensbildung und Zielkopie |
| `SUCCESS` | Terminaler Enderfolg nur nach Zielkopie und konsistenter Persistenz |
| `FAILED_FINAL` | Terminal, wird nicht erneut fachlich verarbeitet |
| `SKIPPED_ALREADY_PROCESSED` | Historisierter Skip für `SUCCESS`-Dokumente |
| `SKIPPED_FINAL_FAILURE` | Historisierter Skip für `FAILED_FINAL`-Dokumente |
**`de.gecheckt.pdf.umbenenner.domain.model.NamingProposal`**
Record mit aufgelöstem Datum, `DateSource`, validiertem Titel und KI-Begründung. Führende Quelle für die Zieldateinamensbildung.
**`de.gecheckt.pdf.umbenenner.domain.model.BatchRunContext`**
Klasse mit Run-ID, Zeitstempel und optionalem Fingerabdruck-Filter; steuert den Umfang eines Batch-Laufs.
---
### Application-Modul
**`de.gecheckt.pdf.umbenenner.application.config.RuntimeConfiguration`**
Schmales Laufzeit-Record (`maxPages`, `maxRetriesTransient`, `aiContentSensitivity`). Wird von den Use Cases verwendet, enthält keine Pfade.
**`de.gecheckt.pdf.umbenenner.application.config.startup.StartConfiguration`**
Vollständige typisierte Startup-Konfiguration; einziger Ort in der Anwendungsschicht, an dem `java.nio.file.Path` vorkommt. Wird vom `ConfigurationPort` geliefert und von Bootstrap ausgewertet.
**`de.gecheckt.pdf.umbenenner.application.service.DocumentProcessingService`**
Statische Hilfsklasse: überführt ein Extraktionsergebnis über den Pre-Check in ein `DocumentProcessingOutcome`. Kompakte Pipeline-Klasse; guter Einstieg zum Verständnis der Verarbeitungslogik.
**`de.gecheckt.pdf.umbenenner.application.service.AiResponseParser`**
Statischer Parser für KI-Antworten in `ParsedAiResponse`. Erzwingt reines JSON-Objekt; Validierungslogik liegt vollständig in der Anwendungsschicht.
**`de.gecheckt.pdf.umbenenner.application.port.out.ProcessingAttempt`**
Record für einen Versuchshistorie-Eintrag; enthält u. a. Provider-Identifikator, Modellname, Prompt-Identifikator, aufgelöstes Datum und finalen Zieldateinamen.
**`de.gecheckt.pdf.umbenenner.application.port.out.DocumentRecord`**
Record für den Dokument-Stammsatz; enthält Gesamtstatus, Fehler- und Transientzähler sowie letzten Zielpfad.
---
## 4. Inbound Ports
### `BatchRunProcessingUseCase`
```
de.gecheckt.pdf.umbenenner.application.port.in.BatchRunProcessingUseCase
```
Zentraler Use-Case-Einstiegspunkt für den gesamten Batch-Betrieb. Beschreibt den Anwendungszweck in einer einzigen Methode:
```java
BatchRunOutcome execute(BatchRunContext context);
```
Mögliche Ergebnisse:
| Ergebnis | Bedeutung |
|----------|-----------|
| `SUCCESS` | Lauf technisch ordnungsgemäß abgeschlossen |
| `LOCK_UNAVAILABLE` | Run-Lock konnte nicht erworben werden |
| `FAILURE` | Harter technischer Fehler beim Laufstart |
---
## 5. Outbound Ports
Alle Outbound-Ports liegen in `de.gecheckt.pdf.umbenenner.application.port.out` (bzw. dessen Unterpaket `modelcatalog`). Implementierungen befinden sich ausschließlich in `pdf-umbenenner-adapter-out`; Details dort sind in `adapter-overview.md` beschrieben.
| Interface | Zweck | Hauptmethode(n) |
|-----------|-------|-----------------|
| `SourceDocumentCandidatesPort` | Scannt Quellordner, liefert Kandidaten in deterministischer Reihenfolge | `List<SourceDocumentCandidate> loadCandidates()` |
| `FingerprintPort` | Berechnet SHA-256-Fingerabdruck eines Kandidaten | `FingerprintResult computeFingerprint(SourceDocumentCandidate)` |
| `PdfTextExtractionPort` | Extrahiert Text und Seitenanzahl aus einer PDF | `PdfExtractionResult extractTextAndPageCount(...)` |
| `AiInvocationPort` | Ruft den aktiven KI-Dienst auf; provider-neutral | `AiInvocationResult invoke(AiRequestRepresentation)` |
| `PromptPort` | Lädt das Prompt-Template aus der konfigurierten Quelle | `PromptLoadingResult loadPrompt()` |
| `TargetFileCopyPort` | Kopiert Quelldokument unter aufgelöstem Namen in den Zielordner (Temp + Rename) | `TargetFileCopyResult copyToTarget(...)` |
| `TargetFileRenamePort` | Atomare Umbenennung einer bereits kopierten Zieldatei (manuelle Korrektur) | `TargetFileRenameResult rename(...)` |
| `RunLockPort` | Exklusiver Lauf-Lock gegen parallele Instanzen | `acquire()` / `release()` |
| `PersistenceSchemaInitializationPort` | Idempotente Schema-Initialisierung der SQLite-Datenbank | `initializeSchema()` |
| `ClockPort` | Abstraktion des Systemtakts | `Instant now()` |
| `ConfigurationPort` | Lädt die typisierte Startup-Konfiguration | `StartConfiguration loadConfiguration()` |
| `ProcessingLogger` | Logging-Delegation; sensibles KI-Content-Logging über Flag gesteuert | `info/debug/warn/error/debugSensitiveAiContent(...)` |
| `AiModelCatalogPort` | Abruf verfügbarer Modelle vom Provider (nur GUI-Pfad, siehe `gui-overview.md`) | `ModelCatalogResult fetchAvailableModels(...)` |
| `PathCheckPort` | Lesende Pfad-Prüfung für den technischen Selbsttest | `isDirectoryReadable`, `isDirectoryWritableOrCreatable`, `isFileReadable`, `isSqlitePathUsable` |
| `ResourceCreationPort` | Schreibende Korrektur-Aktionen (Ordner anlegen, Prompt-Datei erzeugen, SQLite-Pfad vorbereiten) | `createDirectory`, `createPromptFile`, `prepareSqlitePath` |
| `ApiKeyResolutionPort` | Ermittelt API-Key-Herkunft pro Provider-Familie für die GUI-Validierung | `EffectiveApiKeyDescriptor resolve(...)` |
> **Hinweis zu GUI-spezifischen Ports:** `AiModelCatalogPort`, `PathCheckPort`, `ResourceCreationPort` und `ApiKeyResolutionPort` werden ausschließlich im GUI-Pfad genutzt. Ihre Implementierungen und der Aufrufkontext sind in `gui-overview.md` beschrieben.
---
## 6. Einstiegspunkte für neue Entwickler
Die folgende Lesereihenfolge gibt den kürzesten Weg zum Gesamtverständnis:
1. **`de.gecheckt.pdf.umbenenner.application.port.in.BatchRunProcessingUseCase`** beschreibt den gesamten Anwendungszweck in einer Methode.
2. **`de.gecheckt.pdf.umbenenner.domain.model.ProcessingStatus`** fachliches Herzstück; dokumentiert Zustandsübergänge und Retry-Schwellen.
3. **`de.gecheckt.pdf.umbenenner.domain.model`** (gesamtes Paket) gemeinsame Sprache aller Schichten; vollständig in wenigen Minuten lesbar.
4. **`de.gecheckt.pdf.umbenenner.application.service.DocumentProcessingService`** kompakte Pipeline-Klasse; zeigt, wie Pre-Check und Ergebnis-Typen zusammenspielen.
5. **`de.gecheckt.pdf.umbenenner.application.port.out`** (gesamtes Paket) vollständige Außengrenzen der Architektur; jeder Infrastrukturzugriff ist hier als Port definiert.