- ${revision}-Property im Parent-POM eingeführt; alle Kind-POM-<parent>-Blöcke
verwenden ${revision} statt hartkodierter Version
- flatten-maven-plugin 1.6.0 in <build><plugins> des Parent-POM aktiviert
(resolveCiFriendliesOnly), sodass installierte POMs keine unaufgelösten
${revision}-Referenzen enthalten
- MANIFEST.MF des Shade-JARs enthält Implementation-Version und Implementation-Title
- app.version im Packaging-Modul auf ${revision} umgestellt (war 2.5.0)
- ApplicationVersionProvider: neue Utility-Klasse im Bootstrap-Modul liest
Implementation-Version aus MANIFEST.MF, Fallback "dev" bei ungepacktem Betrieb
- ApplicationVersionProviderTest: prüft Fallback-Verhalten im Testlauf
- .gitignore: .flattened-pom.xml-Dateien ausgeschlossen
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Files.readAllBytes laedt grosse PDFs vollstaendig in den Heap und
riskiert OutOfMemoryError. Die Berechnung nutzt jetzt einen
DigestInputStream mit 8-KB-Puffer in try-with-resources. Das
Hash-Ergebnis ist bitidentisch zur vorigen Implementation, die
Exception-Semantik bleibt unveraendert.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Die Dependency log4j-slf4j-impl mit hartcodierter Version wurde durch
log4j-slf4j2-impl ersetzt und nutzt jetzt einheitlich die zentrale
Versionsverwaltung im Parent-POM, konsistent zu den anderen Modulen.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Connection wird jetzt in try-with-resources geoeffnet, sodass sie
auch dann zuverlaessig geschlossen wird, wenn setAutoCommit(false) wirft.
Rollback-Behandlung bleibt unveraendert innerhalb des inneren catch-Blocks.
Ebenfalls: korrekten Import fuer DateTimeFormatter ergaenzt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fehler: stringToInstant() in SqliteDocumentRecordRepositoryAdapter verwendete
nur Instant.parse(), das nur ISO-8601 versteht. Ältere DB-Einträge haben aber
das Format 'yyyy-MM-dd HH:mm:ss' (Leerzeichen statt T, kein Z).
Lösung: Fallback-Logik implementiert
1. Versuch: Instant.parse() für ISO-8601 Format
2. Fallback: DateTimeFormatter für 'yyyy-MM-dd HH:mm:ss' → als UTC parsen
Die Methode bleibt robust und gibt null zurück, wenn beide Parser fehlschlagen.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Neu im Tab "Verarbeitungslauf":
- Integrierte PDF-Vorschau der Quelldatei mit Lazy Rendering (Seite 1 sofort,
weitere Seiten on-demand), Cache pro Selektion, "latest preview request wins"
- Editierbarer KI-Dateinamenvorschlag mit Live-Validierung, Dirty-State-Dialog
bei Zeilen-/Tabwechsel, Schließen und Laufstart, atomare FS+DB-Transaktion
inkl. Rollback und Fingerprint-basierter Konfliktauflösung
Architektur:
- Neuer Application-Use-Case ManualFileRenameUseCase und Outbound-Port
TargetFileRenamePort mit Filesystem-Adapter
- Neuer GuiManualFileRenamePort, verdrahtet im Bootstrap
- GuiBatchRunResultRow um correctedFileName erweitert
- GuiBatchRunTab auf SplitPane-Layout (60/40) umgebaut, Detail-Panel mit
KI-Begründung, FileNameEditorPane und PdfPreviewPane
- Spike-Code (PdfViewerSpike) entfernt, produktive Implementierung ersetzt
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- markSelectedRowsAsResetPending() schützt selectedRows jetzt mit
selectionSyncInProgress=true, sodass der TableView-SelectionModel-
Listener die Selektion nicht löscht, wenn Zeilen ersetzt werden
- isRunning() und updateButtonStates() verwenden runningProperty.get()
statt coordinator.isRunning() für konsistentes Verhalten zwischen
Button-Zustand und Selektion
- Diagnose-LOG am Anfang von handleReprocessSelected() gibt isRunning()
und selectedRows.size() aus (Laufend=false, Selektion>0 erwartet)
- Alle [TEMP-TRACE]-Logs entfernt aus GuiBatchRunCoordinator,
SqliteUnitOfWorkAdapter, SqliteDocumentRecordRepositoryAdapter
und DocumentProcessingCoordinator
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- [TEMP-TRACE] INFO-Logs in SqliteDocumentRecordRepositoryAdapter:
deleteByFingerprint() zeigt Fingerprint, jdbcUrl und rowsAffected;
findByFingerprint() zeigt Fingerprint, jdbcUrl und Lookup-Ergebnis
- [TEMP-TRACE] Log in DocumentProcessingCoordinator.processDeferredOutcome()
zeigt Fingerprint und Lookup-Ergebnis-Typ nach DB-Abfrage
- Bestehende [TEMP-TRACE] Logs in GuiBatchRunCoordinator und
SqliteUnitOfWorkAdapter sind ebenfalls enthalten
- Neuer Test resetDocumentByFingerprint_deletesFailedFinalRecord_resultIsDocumentUnknown:
legt FAILED_FINAL-Datensatz in echter SQLite-DB an, führt Reset aus
und prüft, dass der Datensatz danach DocumentUnknown zurückliefert
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Mehrfachauswahl mit CheckBox-Spalte und Master-Tri-State-Checkbox
- Gezielter Mini-Lauf über ausgewählte Einträge (unabhängig vom Status)
- Statusreset für ausgewählte Einträge (Stammsatz + Versuchshistorie)
- Fehlende Quelldatei im Mini-Lauf wird als FAILED_PERMANENT synthetisiert
- Identische Zieldatei wird als SUCCESS ohne erneute KI-Verarbeitung erkannt
- Weiche Stop-Semantik erhält zurückgesetzte Einträge unverändert
- Nicht-ausgewählte Einträge bleiben in allen Pfaden unberührt
- Buttons reagieren jetzt korrekt auf Auswahländerungen
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Die OpenAI Chat Completions API liefert den eigentlichen KI-Inhalt als
escaped JSON-String in choices[0].message.content, nicht als direktes
JSON-Objekt. Der Adapter gab bisher den gesamten Envelope zurück, was
dazu führte, dass AiResponseParser das Pflichtfeld 'title' nicht fand.
Neues Verhalten: extractContentFromResponse() parst zunächst den äußeren
Envelope und gibt choices[0].message.content als AiRawResponse-Inhalt
weiter – analog zum AnthropicClaudeHttpAdapter. Bei fehlendem Inhalt
(leer, kein choices-Array) oder unparseablem Envelope wird eine
technische Failure (NO_CHOICE_CONTENT bzw. UNPARSEABLE_JSON) zurückgegeben.
Tests aktualisiert und drei neue Tests für den zweistufigen Parse-Pfad
sowie für Fehlerfälle ergänzt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Blank-Startzustand zeigt jetzt die Standardvorlage (wie nach "Neu"), neue Factory createEmptyStartState für Tests
- Meldungsbereich ist per Kontextmenü bzw. Strg+C kopierbar
- Jede Meldung trägt ein führendes [HH:mm:ss]-Präfix
- Validieren- und Tests-Aktionen akkumulieren Meldungen, automatische Validierung ersetzt still ihre Einträge
- Validieren-Meldung listet alle konkreten Befunde einzeln auf
- Modell-ComboBox und manuelles Modellfeld sind linksbündig
- ApiKeyResolutionPort liefert jetzt den effektiven API-Schlüsselwert (Default + Env-Adapter-Override), so dass der Modellliste-Test in den technischen Tests nicht mehr "API-Schlüssel fehlt" meldet, obwohl er gesetzt ist