Files
pdf-umbenenner/CLAUDE.md
T

21 KiB
Raw Blame History

CLAUDE.md

Zweck

Dieses Repository implementiert einen lokal gestarteten PDF-Umbenenner mit KI. Das Programm liest bereits OCR-verarbeitete, durchsuchbare PDF-Dateien aus einem Quellordner, ermittelt daraus einen normierten Dateinamen und legt eine Kopie der Datei im Zielordner ab. Die Quelldatei bleibt unverändert.

Ab V2.0 wird die Anwendung um eine lokale JavaFX-Desktop-GUI erweitert. Die GUI ist der neue Standardstart. Der bestehende headless Batch-Betrieb bleibt über --headless vollständig erhalten.

Autoritative Dokumente

@docs/specs/technik-und-architektur.md @docs/specs/fachliche-anforderungen.md @docs/specs/meilensteine-v2_0.md

Für die Umsetzung ist zusätzlich immer das aktuell aktive Arbeitspaket unter docs/workpackages/ maßgeblich. Dateinamensschema: M9 - Arbeitspakete.md, M10 - Arbeitspakete.md, … M13 - Arbeitspakete.md, M14_-_Arbeitspakete.md, M15_-_Arbeitspakete.md. Nicht raten, wenn Dokumente fehlen, unklar sind oder sich widersprechen.

Modulare Architektur-Übersichten

Detailwissen über Pakete, Schlüsselklassen, Ports und Bootstrap-Verdrahtung ist in drei modularen Übersichtsdokumenten unter docs/architecture/ ausgelagert. Wer in einem bestimmten Modul arbeitet, liest diese Datei zusätzlich zu CLAUDE.md:

  • docs/architecture/domain-overview.md pdf-umbenenner-domain und pdf-umbenenner-application: Domänenmodell, Inbound- und Outbound-Ports, Application-Services.
  • docs/architecture/gui-overview.md pdf-umbenenner-adapter-in-gui: Workspace-/Tab-Struktur, View-Modelle, GUI-interne Ports, JavaFX-Threading-Modell.
  • docs/architecture/adapter-overview.md pdf-umbenenner-adapter-out, pdf-umbenenner-adapter-in-cli, pdf-umbenenner-bootstrap: konkrete Outbound-Adapter, CLI-Einstiegspunkt, Verdrahtungslogik und Provider-Auswahl.

Für Arbeit ausschließlich in einem dieser Bereiche genügt CLAUDE.md plus die jeweils passende Übersichtsdatei.

Priorisierung der Regeln

Die Dokumente haben folgende feste Bedeutung:

  • docs/specs/technik-und-architektur.md = verbindliche technische Zielarchitektur
  • docs/specs/fachliche-anforderungen.md = verbindliche fachliche Regeln
  • docs/specs/meilensteine-v2_0.md = verbindliche V2.0-Zieldefinition und Meilensteinabgrenzung
  • docs/workpackages/... = verbindlicher Scope, Reihenfolge und Inhalt des aktuell bearbeiteten Arbeitspakets

Bei Konflikten gilt folgende Priorität:

  1. Technik- und Architektur-Dokument Verbindliche technische Zielarchitektur. Architekturbrüche sind unzulässig.

  2. Fachliche Anforderungen Verbindliche fachliche Regeln und fachliches Zielverhalten.

  3. Meilensteine V2.0 Verbindliche Zieldefinition, Abgrenzungen und Leitplanken für den V2.0-Ausbau.

  4. Arbeitspakete Definieren den konkret erlaubten Umsetzungsumfang des aktuellen Schritts.

Wenn Dokumente fehlen, unklar sind oder sich widersprechen, nicht raten und keine stillen Annahmen treffen.

Unverrückbare Technikvorgaben

  • Java 21
  • Maven Multi-Module
  • ausführbares Standalone-JAR (ein gemeinsames JAR für GUI und headless)
  • GUI ist der neue Standardstart (ab V2.0)
  • --headless startet weiterhin den bestehenden Batch-/Scheduler-Betrieb
  • --config <pfad> steht für GUI und headless zur Verfügung
  • kein Webserver
  • kein Applikationsserver
  • keine Dauerlauf-Anwendung
  • kein interner Scheduler
  • das Shade-JAR bleibt das primäre Distributionsartefakt
  • zusätzlicher nativer Windows-Installer (MSI) ab V3.0 via Maven-Profil release (jpackage, WiX Toolset 3.x im PATH erforderlich); der Normalbuild mvn clean verify bleibt vom Profil unberührt und benötigt kein WiX
  • Log4j2 für Logging
  • SQLite als lokaler Persistenzspeicher
  • JavaFX wird mit dem JAR ausgeliefert (kein separates JavaFX-Setup)
  • GUI offiziell nur für Windows; headless bleibt für Windows Server / Task Scheduler geeignet
  • gemappte Laufwerke wie S:\ oder H:\ sind ausdrücklich zu unterstützen
  • KI-Anbindung über genau eine der beiden unterstützten Provider-Familien:
    • OpenAI-kompatible HTTP-Schnittstelle (Chat-Completions-Stil)
    • native Anthropic Messages API (Claude-Modelle)
  • Pro Lauf ist genau ein Provider aktiv. Kein Fallback, keine Parallelnutzung.
  • .properties bleibt die einzige Konfigurationswahrheit
  • Konkrete Provider-Familie, Base-URL und Modellname sind Konfiguration, keine Architekturentscheidung.

Verbindliche Modulstruktur (ab V2.0)

  • pdf-umbenenner-domain
  • pdf-umbenenner-application
  • pdf-umbenenner-adapter-in-cli
  • pdf-umbenenner-adapter-in-gui
  • pdf-umbenenner-adapter-out
  • pdf-umbenenner-bootstrap

Architekturregeln

  • Strikte hexagonale Architektur / Ports and Adapters
  • Abhängigkeiten zeigen immer nach innen
  • Domain kennt keine Infrastruktur, keine Datenbank, kein Dateisystem, keine HTTP-Kommunikation und kein JavaFX
  • Application enthält keine technischen Implementierungsdetails und keine JavaFX-Typen
  • Externe Zugriffe erfolgen ausschließlich über Ports
  • Konkrete technische Implementierungen sind Adapter
  • Adapter dürfen nicht direkt voneinander abhängen
  • Die GUI ist ein Inbound-Adapter (pdf-umbenenner-adapter-in-gui) sie wird nicht in Bootstrap vermischt
  • Bootstrap bleibt verantwortlich für: Startmoduswahl, Konfigurationsauflösung, Objektgraph, kontrollierten Start des passenden Adapters, Exit-Code-Ableitung bei harten Startfehlern
  • GUI-Code und JavaFX dürfen im headless Pfad nicht unnötig früh initialisiert oder geladen werden
  • Keine Vermischung von Dateisystem, PDF-Auslese, SQLite, KI-HTTP, Konfiguration, Logging, Benennungslogik und Retry-Entscheidungen
  • Logging ist technische Infrastruktur, kein fachlicher Port
  • Port-Verträge enthalten weder Path/File noch NIO- oder JDBC-Typen
  • Der AiNamingPort bleibt provider-neutral; provider-spezifische Typen, Header, URLs und Antwortstrukturen leben ausschließlich in der jeweiligen Adapter-Out-Implementierung
  • Es gibt keine gemeinsame „abstrakte KI-Adapter"-Zwischenschicht zwischen Port und konkreten Adaptern
  • Die Bootstrap-Schicht wählt die eine aktive AiNamingPort-Implementierung anhand der Konfiguration aus

GUI-Leitplanken (verbindlich für alle V2.0-Arbeitspakete)

Threadingmodell

  • Jede potenziell blockierende Operation (Modellabruf, technische Tests, Pfad-/Dateisystemprüfungen, SQLite-Prüfungen, Lesen/Schreiben der .properties) läuft auf einem Hintergrund-Worker-Thread
  • UI-Updates erfolgen ausschließlich über den JavaFX Application Thread (Platform.runLater)
  • Die GUI darf während laufender Hintergrund-Operationen nicht einfrieren

GUI-Teststrategie

  • View-Modelle und Application-nahe GUI-Logik werden mit JUnit unit-getestet; Fokus auf Zustandsübergängen, Validierungsregeln und Datenflüssen nicht auf Rendering
  • GUI-Smoke-Tests laufen unter headless JavaFX (Monocle) in der Maven-Test-Phase
  • Kein TestFX, kein weiteres GUI-Testframework über Monocle hinaus

GUI-Logging

  • Der GUI-Adapter nutzt denselben Log4j2-Stack wie der headless Pfad
  • Logformat und Log-Verzeichnis bleiben gegenüber dem headless Betrieb unverändert
  • Mindesteinträge für GUI-nahe Ereignisse: Start- und Beendigungsereignisse der GUI, Modellabruf-Versuche (Provider, Erfolg/Misserfolg, ohne API-Key), Dateischreibvorgänge inkl. Zielpfad, Ergebnisse der Aktionen Validieren und Technische Tests ausführen, sowie alle schreibenden Korrekturen

--config-Semantik

  • Zeigt --config <pfad> im GUI-Start auf eine nicht existente Datei: Fehlermeldung, danach verhält sich die GUI so, als wäre --config nicht angegeben worden
  • Zeigt --config <pfad> im headless Start auf eine nicht existente Datei: harter Startfehler, kein stiller Fallback

JavaDoc-Standard (verbindlich für alle V2.0-Arbeitspakete)

Für jede neu hinzugefügte oder substanziell geänderte öffentliche Klasse, öffentliche Methode und jedes neue Java-Package gilt:

  • Klassen-JavaDoc: Zweck, Verantwortung und Abgrenzung der Klasse
  • Methoden-JavaDoc: Zweck, Parameter, Rückgabewert und dokumentierte Ausnahmen
  • package-info.java: pro neuem Package, mit Kurzbeschreibung der Paketverantwortung

Ein Arbeitspaket ist erst fertig, wenn die betroffenen öffentlichen Klassen und Methoden dem JavaDoc-Standard entsprechen.

Globale fachliche Leitplanken

  • Zielformat: YYYY-MM-DD - Titel.pdf
  • Bei Namenskollisionen: YYYY-MM-DD - Titel(1).pdf, YYYY-MM-DD - Titel(2).pdf, ...
  • Die konfigurierte maximale Titellänge gilt nur für den Basistitel; das Dubletten-Suffix zählt nicht mit
  • Das Dubletten-Suffix wird unmittelbar vor .pdf angehängt
  • Titel sind deutsch, verständlich, eindeutig und enthalten keine Sonderzeichen außer Leerzeichen, Bindestrichen, Punkten, Kommas und Ampersands
  • Eigennamen bleiben unverändert
  • Datumsermittlung mit Priorität aus den fachlichen Anforderungen; wenn kein belastbares Datum eindeutig ableitbar ist, ist das aktuelle Datum als Fallback erlaubt
  • Mehrdeutige Dokumente liefern kein unsicheres Ergebnis, sondern einen Fehler
  • Erfolgreich verarbeitete Dateien werden nicht erneut verarbeitet
  • Retryable fehlgeschlagene Dateien dürfen in späteren Läufen erneut verarbeitet werden
  • Final fehlgeschlagene Dateien werden in späteren Läufen übersprungen
  • Identifikation erfolgt nicht über Dateinamen
  • Quelldateien werden nie überschrieben, verändert, verschoben oder gelöscht

Aktiver Implementierungsstand

V1.1 ist vollständig umgesetzt, dokumentiert, getestet und freigegeben.

Der Basisstand V2.0 (JavaFX-GUI als Standardstart, Konfigurationseditor, technische Tests) ist abgeschlossen.

V2.9 ist abgeschlossen. Der Tab „Verarbeitungslauf" wurde erweitert um eine integrierte PDF-Vorschau (Lazy-Rendering direkt über PDFBox, In-Memory-Cache, Seitennavigation) sowie einen editierbaren Dateiname-Bereich mit Live-Validierung, Dirty-State-Dialog und atomarer Dateisystem-/DB-Transaktion inklusive Rollback und Fingerprint-basierter Konfliktauflösung. Die zugehörigen neuen Ports, Use Cases und Adapter sind in den modularen Architektur-Übersichten beschrieben.

Verhaltensänderungen seit V2.9: Die GUI startet maximiert, und die zuletzt geladene Konfigurationsdatei wird beim Start automatisch wieder geladen; existiert sie nicht mehr, startet die GUI ohne Fehlermeldung mit dem Willkommenstext.

Die fachliche Kernverarbeitung des PDF-Umbenenners bleibt unverändert.

Statussemantik

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 zulässig
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

SUCCESS-Bedingung (verbindlich)

SUCCESS darf erst gesetzt werden, wenn:

  1. die Zielkopie erfolgreich geschrieben wurde,
  2. der finale Zieldateiname bestimmt ist,
  3. die Persistenz konsistent fortgeschrieben wurde.

Führende Quelle des Benennungsvorschlags (verbindlich)

  • Die führende Quelle für Datum, Datumsquelle, validierten Titel und Reasoning ist der neueste Versuchshistorieneintrag mit Status PROPOSAL_READY
  • Kein Rekonstruieren aus dem Dokument-Stammsatz
  • Kein neuer KI-Aufruf, wenn bereits ein nutzbarer PROPOSAL_READY-Versuch vorliegt
  • Status PROPOSAL_READY ohne lesbaren konsistenten Proposal-Versuch = dokumentbezogener technischer Fehler
  • Inkonsistente Proposal-Zustände werden nicht stillschweigend geheilt, sondern als technische Dokumentfehler behandelt

Retry-Semantik

Deterministische Inhaltsfehler

  • erster historisierter deterministischer Inhaltsfehler → FAILED_RETRYABLE
  • zweiter historisierter deterministischer Inhaltsfehler → FAILED_FINAL

Transiente technische Fehler

  • Transiente Fehler laufen über den Transientfehlerzähler im Dokument-Stammsatz
  • Retryable bis der konfigurierte Grenzwert max.retries.transient erreicht ist
  • Der Fehlversuch, der den Grenzwert erreicht, finalisiert den Dokumentstatus zu FAILED_FINAL
  • max.retries.transient = Integer >= 1; der Wert 0 ist ungültige Startkonfiguration

Technischer Sofort-Wiederholversuch

  • Genau ein zusätzlicher technischer Schreibversuch innerhalb desselben Dokumentlaufs
  • Ausschließlich für Fehler beim physischen Zielkopierpfad
  • Kein erneuter KI-Aufruf, keine erneute Fachableitung
  • Zählt nicht zum laufübergreifenden Transientfehlerzähler

Exit-Codes (verbindlich)

  • 0: normale erfolgreiche Beendigung eines headless Laufs sowie für das reguläre Beenden der GUI
  • 1: harte Start-, Bootstrap-, Verdrahtungs-, Konfigurations- oder Initialisierungsfehler, einschließlich ungültiger CLI-Verwendung, nicht existenter --config-Datei im headless Start und GUI-Startfehlern vor erfolgreicher Anzeige der Oberfläche
  • Dokumentbezogene Verarbeitungsfehler im headless Lauf ändern dieses Exit-Code-Modell nicht

Persistenz

Zwei-Ebenen-Modell keine dritte Wahrheitsquelle.

Dokument-Stammsatz enthält u.a.:

  • letzten Zielpfad, letzten Zieldateinamen
  • Inhaltsfehler- und Transientfehlerzähler
  • Gesamtstatus

Versuchshistorie enthält u.a.:

  • finalen Zieldateinamen
  • Fehlerklasse, Fehlermeldung, Retryable-Flag
  • Provider-Identifikator des aktiven KI-Providers für den Versuch

Invariante: Der führende PROPOSAL_READY-Versuch wird nicht überschrieben. Jeder Lauf erzeugt einen zusätzlichen neuen Versuchseintrag.

Rückwärtsverträglichkeit: Bestehende Datenbestände bleiben lesbar, fortschreibbar und korrekt interpretierbar.

Naming-Regel (verbindlich für alle Arbeitspakete)

In Implementierungen, Kommentaren und JavaDoc dürfen keine Meilenstein- oder Arbeitspaket-Bezeichner erscheinen:

  • Verboten: M1, M2, …, M13
  • Verboten: AP-001, AP-002, … AP-0xx
  • Verboten: Versionsbezeichner wie V1.0, V1.1, V2.0 in Code/JavaDoc

Stattdessen werden zeitlose technische Bezeichnungen verwendet. Bestehende Kommentare mit solchen Bezeichnern, die durch eigene Änderungen berührt werden, sind zu ersetzen.

Arbeitsweise

  • Arbeite immer nur im explizit aktiven Arbeitspaket
  • Kein Vorgriff auf spätere Arbeitspakete
  • Änderungen klein, fokussiert und architekturtreu halten
  • Keine unnötigen Umbenennungen, keine großflächigen Refactorings ohne Not
  • Vor Änderungen zuerst die betroffenen Dateien und Abhängigkeiten verstehen
  • Keine Annahmen über Dateipfade. Typen und Klassen werden per Suche nach Typname gefunden, nicht über vermutete Pfade.
  • Keine Vermutungen: Bei echter Unklarheit oder Dokumentkonflikten knapp nachfragen oder den Konflikt benennen
  • Keine stillen Änderungen am bestehenden headless Batch-Betrieb
  • GUI-Code darf den headless Pfad nicht unnötig früh initialisieren

Commit und Push nach jeder Implementierung

Nach jeder Implementierung oder Dateiänderung wird ein Commit auf main erstellt und gepusht:

  1. Geänderte Dateien stagen und committen
  2. git push origin main ausführen
  3. Schlägt der Push mit einem AUTH-Fehler fehl: 1 Sekunde warten, dann genau einen weiteren Versuch unternehmen
  4. Schlägt auch der zweite Versuch fehl: Fehler benennen, keinen weiteren automatischen Retry

Definition of Done pro Arbeitspaket

Ein Arbeitspaket ist erst fertig, wenn:

  • der Zielumfang des aktuellen Arbeitspakets vollständig umgesetzt ist
  • der Stand konsistent, fehlerfrei und buildbar ist
  • Implementierung, Konfiguration, JavaDoc (inkl. package-info.java für neue Packages) und Tests ergänzt sind
  • der JavaDoc-Standard für alle neu hinzugefügten oder substanziell geänderten öffentlichen Klassen und Methoden eingehalten wurde
  • keine Inhalte späterer Arbeitspakete vorweggenommen wurden
  • der Zwischenstand in sich geschlossen und übergabefähig ist

Pflicht-Output-Format nach jedem Arbeitspaket

- Scope erfüllt: ja/nein
- Geänderte Dateien:
  - <Dateipfad>
  - ...
- Build-Kommando: <verwendetes Kommando>
- Build-Status: ERFOLGREICH / FEHLGESCHLAGEN
- Offene Punkte: keine / <Beschreibung>
- Risiken: keine / <Beschreibung>

Qualitäts- und Prüfreihenfolge

  • Nur den für das aktuelle Arbeitspaket nötigen Scope ändern
  • Nach Änderungen den kleinsten sinnvollen Build-/Test-Umfang ausführen
  • Build-Validierung vom Parent-Root (Beispiel für vollständigen Reactor-Build ab V2.0): .\mvnw.cmd clean verify -pl pdf-umbenenner-domain,pdf-umbenenner-application,pdf-umbenenner-adapter-out,pdf-umbenenner-adapter-in-cli,pdf-umbenenner-adapter-in-gui,pdf-umbenenner-bootstrap --also-make
  • MSI-Build (nur lokal auf der Entwicklungsmaschine, WiX Toolset 3.x im PATH erforderlich): .\mvnw.cmd clean package -P release -pl pdf-umbenenner-packaging --also-make -DskipTests
  • Schlägt der Build fehl: Fehler beheben, erneut bauen, erst dann weiter
  • Vor Abschluss sicherstellen, dass der relevante Maven-Reactor-Stand fehlerfrei ist
  • Fehler nicht kaschieren; Ursachen sauber beheben oder offen benennen

Wichtige Betriebsregeln

  • Ungültige Startkonfiguration verhindert den Verarbeitungslauf und führt zu Exit-Code 1
  • Eine ungültige oder fehlende Provider-Auswahl ist eine ungültige Startkonfiguration
  • Run-Lock verhindert parallele Instanzen; wenn bereits eine Instanz läuft, beendet sich die neue Instanz sofort
  • API-Schlüssel: pro Provider eine eigene Umgebungsvariable, Vorrang vor Properties derselben Provider-Familie. Schlüssel verschiedener Provider werden niemals vermischt.
  • Dokumentbezogene Fehler führen nicht zu Exit-Code 1

Konfigurationsparameter

Verbindlich zweckmäßige Parameter:

  • source.folder Quellordner
  • target.folder Zielordner (muss vorhanden oder anlegbar sein, Schreibzugriff erforderlich)
  • sqlite.file SQLite-Datenbankdatei
  • ai.provider.active aktiver KI-Provider (Pflicht)
  • max.retries.transient max. historisierte transiente Fehlversuche pro Fingerprint (Integer >= 1, 0 ist ungültig)
  • max.pages Seitenlimit
  • max.text.characters maximale Zeichenzahl für KI-Eingabe
  • max.title.length maximale Länge des Basistitels in Zeichen (gültiger Bereich 10..120, Default 60)
  • prompt.template.file externe Prompt-Datei
  • log.ai.sensitive sensible KI-Logausgabe freischalten (Boolean, Default: false)
  • runtime.lock.file Lock-Datei (optional)
  • log.directory Log-Verzeichnis (optional)

Pro Provider-Familie existiert ein eigener Parameter-Namensraum:

ai.provider.active=openai-compatible

ai.provider.openai-compatible.baseUrl=...
ai.provider.openai-compatible.model=...
ai.provider.openai-compatible.timeoutSeconds=...
ai.provider.openai-compatible.apiKey=...

ai.provider.claude.baseUrl=...
ai.provider.claude.model=...
ai.provider.claude.timeoutSeconds=...
ai.provider.claude.apiKey=...

Migration historischer Konfiguration

Bestehende Properties-Dateien des Vorgängerstands (flache Schlüssel wie api.baseUrl, api.model, api.timeoutSeconds, api.key) werden beim ersten Start erkannt und kontrolliert in das neue Schema überführt.

Verbindlicher Ablauf:

  1. Legacy-Form erkennen
  2. .bak-Sicherung der Originaldatei anlegen
  3. Inhalt in das neue Schema überführen (Legacy-Werte → Namensraum openai-compatible, ai.provider.active=openai-compatible)
  4. Datei in-place schreiben
  5. Datei erneut laden und validieren
  6. Erst danach den normalen Lauf fortsetzen

Nicht-Ziele / Verbote

  • kein manueller Verarbeitungslauf aus der GUI (kein vollständiger Lauf; Bearbeitungen nach Lauf sind zulässig)
  • kein DB-/Historien-Tab in der GUI (erst V2.x+)
  • kein Kosten-Tracking (erst V2.x+)
  • kein echter Mini-KI-Testaufruf mit fachlicher Antwortauswertung
  • kein Web-UI
  • keine REST-API zur Bedienung
  • keine OCR innerhalb der Java-Anwendung
  • keine DMS-Funktionalität
  • kein menschlicher Review-Workflow in der Anwendung
  • keine interne Scheduler-Logik
  • keine Architekturbrüche
  • keine neuen Bibliotheken oder Frameworks ohne klare Notwendigkeit und Begründung
  • keine automatische Fallback-Umschaltung zwischen KI-Providern
  • keine parallele Nutzung mehrerer KI-Provider in einem Lauf
  • keine Profilverwaltung mit mehreren Konfigurationen je Provider-Familie
  • keine Provider-Familien jenseits der explizit unterstützten
  • kein neues Konfigurationsformat
  • keine Änderung der fachlichen Kernverarbeitung des PDF-Umbenenners
  • keine Änderung der bestehenden Status-, Retry- oder Persistenz-Wahrheit
  • keine stillen Änderungen am bestehenden headless Batch-Betrieb
  • kein Sofort-Wiederholversuch außerhalb des Zielkopierpfads
  • keine spekulativen Umbauten ohne konkreten Qualitäts- oder Konsistenzbezug
  • kein großflächiges Refactoring ohne nachweisbaren Defektbezug