Commit Graph

304 Commits

Author SHA1 Message Date
marcus 46fc1d4fa4 #7: Historien-Tab mit Liste, Detail, Filter, Status-Reset und Eintrag-Loeschen
Implementiert den vollstaendigen Historien-Tab (Verlauf) als vierten Tab der GUI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 13:57:07 +02:00
marcus 5d5dee0bbf #71: Prompt-Editor-Tab in der GUI implementieren
Neuer Tab „Prompt" in der GUI-Hauptansicht ermöglicht das Lesen, Bearbeiten
und atomare Speichern der konfigurierten KI-Prompt-Datei ohne externen Editor.

Änderungen:
- PromptSaveResult: neue sealed interface mit Saved, WriteFailed, TargetDirectoryMissing,
  AtomicMoveFailed als strukturierte Ergebnistypen für savePrompt()
- PromptPort: um savePrompt(String) erweitert (nicht mehr funktional – Teststubs angepasst)
- FilesystemPromptPortAdapter: savePrompt() mit Temp-Datei im selben Verzeichnis + ATOMIC_MOVE,
  kein stiller Fallback bei AtomicMoveNotSupportedException
- DefaultPromptEditorUseCase: Use-Case-Klasse mit loadPrompt(), savePrompt(),
  createDefaultPromptIfMissing() als Delegation an PromptPort und ResourceCreationPort
- GuiPromptEditorPort: GUI-internes Bridge-Interface (kein hexagonaler Port)
- GuiPromptEditorTab: JavaFX-Tab mit TextArea, Dirty-State-Tracking, Speichern/Reset/Anlegen,
  injizierbare threadFactory + fxDispatcher für Testbarkeit
- GuiStartupContext: um promptEditorPort erweitert; alle Backward-Compat-Konstruktoren
  und blank() mit noOpPromptEditorPort() versorgt
- GuiConfigurationEditorWorkspace: promptEditorTab integriert, Tab-Wechsel-Schutz erweitert
- BootstrapRunner: buildGuiPromptEditorPort() verdrahtet FilesystemPromptPortAdapter +
  DefaultPromptEditorUseCase; noOpGuiPromptEditorPort() für Blank-Start-Fälle
- Tests: DefaultPromptEditorUseCaseTest, FilesystemPromptPortAdapterTest (savePrompt),
  GuiPromptEditorTabSmokeTest (headless Monocle), GuiAdapterSmokeTest auf 3 Tabs aktualisiert
- docs/betrieb.md: Prompt-Tab dokumentiert, Pfad-Auflösungstabelle ergänzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 13:13:47 +02:00
marcus 4f5ce4c750 #50: Statuszeile mit Version, Provider und Konfigurationsdateipfad
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 12:35:21 +02:00
marcus dc17824e84 #73: Summary-Banner unterhalb Fortschrittsbalken nach Laufabschluss
Neue Komponente BatchRunSummaryBanner aggregiert die Ergebnisliste nach
Laufende und zeigt je Kategorie Icon + Anzahl + Text an. Banner verschwindet
beim Start des nächsten Laufs. READY_FOR_AI, PROPOSAL_READY und PROCESSING
werden nicht gezählt (nicht im DocumentCompletionStatus-Enum enthalten);
Reset-Pending-Zeilen werden explizit ausgeschlossen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 12:22:57 +02:00
marcus 0fe5359299 #66: Tooltips auf Konfigurationstab, Verarbeitungslauf-Tab und Toolbar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 12:13:00 +02:00
marcus 563d9f52db #51: Einheitliche Status-Darstellung mit Icon, Farbe und Tooltip
Neue zentrale Klasse ProcessingStatusPresentation als einzige autoritative
Quelle fuer Icons, CSS-Farben, Tooltip-Texte und Summary-Kategorielabels
aller DocumentCompletionStatus-Werte. GuiBatchRunResultRow delegiert
statusIcon() und statusColor() an diese Klasse und stellt neue Methode
statusTooltip() bereit. In GuiBatchRunTab erhalten Status-Icons Tooltips
per CellFactory; die duplizierte private statusColor()-Methode entfaellt.
Fuer FAILED_PERMANENT wird im Detailbereich ein erweiterter Erklaerungstext
gemaess Spezifikation #51 angezeigt. Unit-Tests fuer ProcessingStatusPresentation
(alle Status, Eindeutigkeit, korrekte Mapping-Werte) und statusTooltip() in
GuiBatchRunResultRowTest ergaenzt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 11:55:11 +02:00
marcus 732d00c4ad Fix #49: Flyway-Integration mit V1-Basisskript und 3-Fall-Strategie
Ersetzt die manuelle evolveTableColumns()-Schema-Evolution durch Flyway 10.20.1.
Die Initialisierung unterscheidet drei Faelle: leere DB (Flyway-Migration),
Bestandsschema ohne Flyway-History (Baseline nach Schema-Pruefung) und
Folgestart mit Flyway-History (idempotent). Smoke-Test-Deadlock auf Windows
durch paralleles Ausgabe-Draining des Subprozesses behoben.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 11:44:28 +02:00
marcus 500a8c5340 #68: Jenkins-Build mit -Drevision-Übergabe und robuster Shade-JAR-Archivierung
- Neues Jenkinsfile mit pipeline-Struktur (Checkout, Version bestimmen,
  Maven Build, Archive JAR, Berichte, Artefakt ablegen, Aufräumen)
- Maven-Build übergibt -Drevision=MAJOR.MINOR.BUILD_NUMBER
- Archive-Stage: Bash explizit via #!/usr/bin/env bash + set -euo pipefail,
  mapfile-Prüfung bricht bei 0 oder mehr als 1 Shade-JAR mit Fehlermeldung ab
- MSI-Build als bewusst manuell dokumentiert (Kommentar im Jenkinsfile)
- MAJOR/MINOR via Jenkins-Parameter, EFFECTIVE_MAJOR/MINOR-Stub für State-Datei
- docs/betrieb.md: CI-Hinweis zum manuellen MSI-Build ergänzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 10:43:48 +02:00
marcus c6379c04f6 #67: Konsistente Versionierung via Maven CI-friendly revision
- ${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>
2026-04-30 10:36:55 +02:00
marcus 01e97848a7 Spezifikation für V3.0 hinzugefügt 2026-04-30 10:30:50 +02:00
marcus 8aaa3331d7 Fix #60: SHA-256-Fingerprint streaming statt Files.readAllBytes berechnen
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>
2026-04-29 06:21:25 +02:00
marcus d10a572b50 Fix #54: Modellabruf ueber Generation-Counter gegen veraltete Ergebnisse absichern
Bei mehrfachem Provider-Wechsel oder Modelle-Neu-Laden konnten parallele
HTTP-Threads ihre Ergebnisse in dieselbe Meldungsliste schreiben. Mit
einem AtomicLong-Generationszaehler wird vor jedem Lauf eine Generation
festgehalten; bei der UI-Auslieferung auf dem JavaFX Application Thread
wird verworfen, was nicht mehr zur aktuellen Generation gehoert. Damit
ueberschreiben veraltete Worker den UI-Zustand nicht mehr.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 06:21:15 +02:00
marcus a87c73401b Fix #53: Konfigurations-Oeffnen ueber Single-Thread-Executor serialisieren
Statt fuer jede openConfigurationFile-Anfrage einen neuen Thread zu
starten, werden Anfragen jetzt ueber einen Single-Thread-ExecutorService
mit Daemon-ThreadFactory eingereiht. Mehrfaches Klicken auf Oeffnen
erzeugt keine konkurrierenden Worker-Threads mehr; Anfragen werden
seriell hintereinander abgearbeitet.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 06:21:05 +02:00
marcus 8ca6d08133 Fix #55: Mutable Felder in PdfPreviewPane als volatile deklarieren
Die Felder currentDocument, currentRenderer, currentSourceFile,
currentPage und totalPages werden vom Worker-Thread geschrieben und
vom JavaFX Application Thread gelesen. Das volatile-Keyword garantiert
nun die Sichtbarkeit zwischen den Threads gemaess Java Memory Model.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 06:20:56 +02:00
marcus cd273505af Fix #56: Inkonsistente log4j-slf4j Artifact-ID vereinheitlichen
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>
2026-04-29 06:20:36 +02:00
marcus bdc5e8331f 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>
2026-04-28 16:21:58 +02:00
marcus 330bcfe124 Fix #63: Datei-Filter in pickFile wirksam machen
Neues funktionales Interface FilePickerDialog eingefuehrt, das Titel,
Anfangspfad und ExtensionFilter-Liste entgegennimmt. showNativeFileChooser
wendet die Filter auf den FileChooser an. pickFile reicht die Filter
durch. Test-Stubs verwenden die aktualisierte Drei-Parameter-Signatur.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 15:57:25 +02:00
marcus c137d9e02e Fix #61: Connection-Leak in SqliteUnitOfWorkAdapter beheben
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>
2026-04-28 15:52:21 +02:00
marcus ea8b94acc7 Fix #57 Fix #58: Catch auf DocumentPersistenceException einengen
Catch in ResolveHistoricalDocumentContext und ResolveHistoricalFileName
praezisiert: nur DocumentPersistenceException wird abgefangen, geloggt
(WARN) und mit leerem Optional beantwortet. Andere RuntimeExceptions
propagieren weiter zum Aufrufer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 15:52:13 +02:00
marcus 4bbee57d41 Fix #58: Verschluckte Exception in ResolveHistoricalFileName loggen
Catch von Exception auf RuntimeException eingeengt; unerwartete
Laufzeitfehler werden jetzt per logger.warn() protokolliert und
weiterpropagiert statt still verschluckt zu werden.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 15:43:52 +02:00
marcus 43c54923f8 Fix #57: Verschluckte Exception in ResolveHistoricalDocumentContext loggen
Log4j2-API als Abhaengigkeit im Application-Modul ergaenzt. Catch von
Exception auf RuntimeException eingeengt; unerwartete Laufzeitfehler
werden jetzt per logger.warn() protokolliert und weiterpropagiert statt
still verschluckt zu werden.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 15:43:45 +02:00
marcus a910633c64 Fix #64: Obergrenze für .bak-Backup-Schleife
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-28 15:37:36 +02:00
marcus 899525a75c Fix #59: Legacy-Format-Schutz für Instant-Parsing in ProcessingAttempt-Repository
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-28 15:36:48 +02:00
marcus 0a139193b4 Fix #62: Leere Bootstrap.java löschen
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-28 15:30:23 +02:00
marcus 0da80849d4 Fix #52: Race Condition auf pendingMessages beim Test-Trigger
pendingMessages.clear() wurde aus runTechnicalTestsAction() in den
Coordinator verlagert (erste Anweisung in triggerTechnicalTests()).
Damit liegen clear() und Worker-Start auf demselben Thread (FX),
und das Race-Fenster zwischen clear() und den per Platform.runLater
zurueckgefuehrten add()-Aufrufen entfaellt.

Die fachliche Produktionssemantik (Replace beim Trigger) bleibt
identisch. JavaDoc und Kommentare wurden auf Replace-Semantik
korrigiert. Der Smoke-Test trigger_twice_accumulatesTestEntries
wurde zu trigger_twice_replacesTestEntries umbenannt und prueft
nun die Replace-Erwartung des isolierten Coordinators.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 15:28:18 +02:00
marcus 014b11abd2 Doku: R4 Dokumentations-Review umgesetzt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 15:04:56 +02:00
marcus 6ff463b7ef Repository aufräumen 2026-04-28 09:57:11 +02:00
marcus 8bb0aabb51 Code aufräumen 2026-04-28 08:52:59 +02:00
marcus 27b4292c2f Imports aufgeräumt 2026-04-28 08:44:24 +02:00
marcus 0b5a441a5d Fix #44: Ersetze Status-Icons durch Unicode-Symbole mit Farben
- SUCCESS: ✓ (U+2713) mit #2e7d32 (grün)
- FAILED_RETRYABLE: ↻ (U+21BB) mit #d98200 (orange)
- FAILED_PERMANENT: × (U+00D7) mit #c62828 (rot)
- SKIPPED_ALREADY_PROCESSED: ≡ (U+2261) mit #1565c0 (blau-grau)
- SKIPPED_FINAL_FAILURE: ⊘ (U+2298) mit #757575 (grau)

Die neue Methode statusColor() gibt CSS-Hex-Farben zurück.
Font: 16px, font-weight: bold

Betroffene Dateien:
- GuiBatchRunResultRow.java: neue statusColor() Methode
- GuiBatchRunResultRowTest.java: Icons aktualisiert
- GuiBatchRunCoordinatorTest.java: Icons aktualisiert
- GuiBatchRunTabSmokeTest.java: Icons aktualisiert

Alle 323 Tests bestanden.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-28 07:55:49 +02:00
marcus 3877359b42 Fix #24: Meldungs-ListView dehnt sich vertikal aus
setMaxHeight(200) entfernt und VBox.setVgrow(messagesListView, ALWAYS)
gesetzt. Die ListView füllt nun den verbleibenden Platz innerhalb der
Meldungs-Card; der Button darunter bleibt davon unberührt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 07:35:21 +02:00
marcus 769d15fd86 Fix #24: Meldungsbereich füllt verbleibenden vertikalen Platz
VBox.setVgrow(card, ALWAYS) auf dem Meldungs-Card macht die Sektion
dehnbar innerhalb von sectionsBox. Damit das VGrow überhaupt wirken kann,
wurde scrollPane.setFitToHeight(true) ergänzt – ohne diese Voraussetzung
bleibt tabContent auf seine natürliche Höhe beschränkt und das VGrow
läuft ins Leere.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 07:28:10 +02:00
marcus 6317a27378 Fix #24: GridPane-Platzhalter in Provider-Block auf managed=false gesetzt
Die leeren Label-Spacer in Spalte 0 der Fehler- und Info-Zeilen des
fieldGrid waren managed=true (JavaFX-Default). JavaFX reservierte dadurch
pro Zeile ~20px Hoehe, selbst wenn das eigentliche Fehler-Label in
Spalte 1 unmanaged/unsichtbar war. Fuenf betroffene Zeilen (baseUrl-Fehler,
Timeout-Fehler, Modell-Fehler, API-Key-Fehler, API-Key-Herkunft) erzeugten
zusammen ~96-120px ungenutzten Leerraum unterhalb der Felder.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 07:20:43 +02:00
marcus 4fa4c152a5 Fix #24: Provider-Bereich kompakter – VBox-Spacing auf 2px, unteres Padding auf 4px 2026-04-28 06:56:00 +02:00
marcus ec23b2455a Fix #24: Provider-Bereich kompakter – Spacing und Padding an Pfade-Bereich angepasst
- VBox-Spacing in Provider-Block von 2 auf 4 Pixels erhöht (wie im Pfade-Bereich)
- Padding in der Provider-Box von 6px auf 8px erhöht (wie im createCardContainer)
- Abstände zwischen Basis-URL, Modell und API-Key sind nun einheitlich mit dem Pfade-Bereich

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-27 19:04:02 +02:00
marcus 7f2cccf317 Fix #35: Einzelinstanz-Schutz ueber Loopback-ServerSocket
Eine zweite parallele Instanz wird beim Start abgewiesen. Der Schutz
greift fuer GUI- und Headless-Pfad gleichermassen vor der Modusweiche
in BootstrapRunner.

Umsetzung als ServerSocket-Bind auf 127.0.0.1:47832: stale-lock-frei,
da das Betriebssystem den Port beim Prozessende automatisch freigibt,
robust unter Windows mit gemappten Laufwerken und UNC-Pfaden, und ohne
Konflikt mit dem bestehenden RunLockPort, der nur den Batch-Lauf
schuetzt. Bei kollidierender Bindung erscheint im GUI-Modus ein
Swing-Dialog (JavaFX ist hier noch nicht initialisiert) und im
Headless-Modus eine Logmeldung; beide Pfade enden mit Exit-Code 1.
Ein ShutdownHook und try-with-resources geben den Port deterministisch
wieder frei.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 16:11:54 +02:00
marcus a5fae8cf55 Fix #42: KI-Prompt weist explizit zur Kuerzung bei Zeichenlimit an
Wenn die KI einen Titel nahe am Zeichenlimit erzeugt, kam es regelmaessig
zur Limit-Ueberschreitung um wenige Zeichen, was den Lauf in
FAILED_RETRYABLE und nach Wiederholung in FAILED_FINAL trieb.

Der Default-Prompt enthaelt jetzt eine explizite Kuerzungsanweisung
(Abkuerzungen, kompaktere Datumsformate, Weglassen unwichtiger Details)
mit dynamisch eingesetztem Zeichenlimit. Die bestehende Validierung
in AiResponseValidator bleibt als Sicherheitsnetz unveraendert.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 16:11:42 +02:00
marcus 191d398604 Fix #44: Differenzierte Icons fuer alle Verarbeitungsstatus
Die beiden SKIPPED-Statuswerte teilten sich bisher Icon und Farbe.
Jeder Status erhaelt jetzt ein eigenes Unicode-Icon und passende Farbe:
SUCCESS gruen, FAILED_RETRYABLE orange, FAILED_PERMANENT rot,
SKIPPED_ALREADY_PROCESSED blau (Naechster-Track), SKIPPED_FINAL_FAILURE
grau (Durchgestrichener Kreis).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 16:11:32 +02:00
marcus f204ad1f1e Fix #24 (fortgesetzt): Provider-Bereich kompakter, Meldungen kleiner, Abstände reduziert
- Basis-URL und Timeout stehen jetzt nebeneinander (4-Spalten-Layout,
  Timeout schmal rechts), Modell und API-Key belegen jeweils volle Breite
- Meldungsbereich: minHeight/prefHeight von 140px auf 60px reduziert
- Sektionsabstände (sectionsBox spacing) von 12 auf 4px reduziert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 15:40:27 +02:00
marcus ac3513504d Fix #24 (fortgesetzt): Restliche Bereiche der Konfigurationsseite kompakter
Verbesserungen für kompakteres Layout:
- createCardContainer(): spacing 8→4, padding 12px→8px
- createFieldGrid(): vgap 8→4 (reduziert vertikale Abstände)
- createProviderBlock():
  * spacing 8→2, padding 10px→6px
  * Basis-URL, Modell, Timeout, API-Key in kompaktem GridPane
  * Reduzierter vertikaler Abstand zwischen Feldern
- createProcessingLimitsSection():
  * Umgestellt auf 2-Spalten-GridPane für Feldgruppen
  * Max. Seiten + Max. Zeichen nebeneinander
  * Max. Titellänge + Max. Retries nebeneinander
  * Log-Level + Sensible KI-Ausgabe nebeneinander
- Abstände zwischen Sektionen global reduziert:
  * sectionsBox spacing: 12→6
  * tabContent spacing: 8→4

Ziel: Konfigurationsseite passt jetzt komplett auf 1920x1080 ohne Scrollen.
Alle Kommentare auf Deutsch.

Build: .\mvnw.cmd clean verify -pl pdf-umbenenner-adapter-in-gui --also-make
Build-Status: ERFOLGREICH (322 Tests bestanden)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-27 15:28:11 +02:00
marcus 65d8379c15 Fix #24 (teilweise): Pfade-Bereich kompakter gestalten
- Quellordner + Zielordner nebeneinander in 2-Spalten-Layout
- SQLite-Datei + Prompt-Datei nebeneinander in 2-Spalten-Layout
- Vertikale Abstände zwischen Feldern reduziert (von 0 zu 4)
- Lock-Datei und Log-Verzeichnis in ausklappbare TitledPane verschoben
  (standardmäßig eingeklappt, Label: "Weitere Optionen (Click zum Aufklappen)")
- Neue Hilfsmethode buildTwoPathFieldsRow() für 2-Spalten-Pfad-Layouts
- Import für TitledPane hinzugefügt
- Alle Kommentare auf Deutsch

Build: .\mvnw.cmd clean verify -pl pdf-umbenenner-adapter-in-gui --also-make
Build-Status: ERFOLGREICH (322 Tests bestanden)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-27 15:17:56 +02:00
marcus a3642608b4 Fix #48: Fehlerbehandlung für Legacy-Datumsformat in stringToInstant()
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>
2026-04-27 14:33:36 +02:00
marcus ff86a07f0e Fix #48: Korrekte Abschlussmeldung bei SKIPPED-only-Läufen und neutrale Farbe
Problem 1: Falsche Meldung bei reinen SKIPPED-Läufen (0 failed, >0 skipped)
- Die Nachricht enthielt immer "fehlgeschlagen" auch wenn failedCount=0
- Neue Logik formuliert Meldung basierend auf tatsächlichen Zählern

Problem 2: Falsche rote Farbe für SKIPPED-only-Läufe
- Farblogik basierte auf Keywords im Text statt auf failedCount
- Neue Logik färbt rot nur wenn failedCount > 0
- Farbe neutral (kein Hintergrund) für SKIPPED-only-Läufe

Neue buildSummaryMessage()-Methode mit drei Fällen:
- Alle erfolgreich (0 failed, 0 skipped)
- Nur übersprungen (0 failed, >0 skipped)
- Mit Fehlern (failed > 0)

Neue Farblogik in appendSummary() direkt auf failedCount basieren.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-27 14:15:18 +02:00
marcus d9670ddfbe Fix #47: Hinweisbereich im Verarbeitungslauf-Tab verbessert
- Padding unterhalb der Selektions-Button-Leiste ergaenzt
- Hinweisbereich wird nur eingeblendet wenn eine Meldung vorliegt
- Farbliche Unterscheidung: Erfolg gruen, Fehler rot, neutral Standard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 14:01:32 +02:00
marcus 03b23eb6a9 Fix #46: Button 'Zuruecksetzen auf KI-Vorschlag' wird korrekt deaktiviert
Der Reset-Button wird jetzt explizit deaktiviert, wenn kein KI-Vorschlag
vorhanden ist (finalFileName ist Optional.empty()). Die Bedingung in
refreshUiState() wurde geklaert und dokumentiert.
2026-04-27 13:51:36 +02:00
marcus 1d77173c49 Fix #31: Manuelle Dateinamen-Eingabe für nicht verarbeitete Dateien
Nicht-erfolgreiche Zeilen (FAILED, FAILED_RETRYABLE, SKIPPED_FINAL_FAILURE)
können im Detailbereich des Verarbeitungslauf-Tabs nun einen manuellen
Zieldateinamen erhalten. Beim Bestätigen wird die Quelldatei mit dem
benutzerdefinierten Namen ins Zielverzeichnis kopiert und der Stammsatz
atomar auf SUCCESS gehoben.

Neuer Inbound-Port ManualFileCopyUseCase mit sealed Result-Hierarchie,
Default-Implementierung mit Best-Effort-Rollback bei Persistenzfehler
sowie GUI-Brücke GuiManualFileCopyPort. Die GUI entscheidet anhand des
Status zwischen Umbenennen (SUCCESS, SKIPPED_ALREADY_PROCESSED) und
Kopieren (FAILED_*, SKIPPED_FINAL_FAILURE).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 13:22:44 +02:00
marcus fb0e9809f6 Fix #45: Fehlender Abstand unterhalb der PDF-Navigationsbuttons
Die Buttons 'Vorherige' und 'Naechste' in der PDF-Vorschau hatten keinen
Abstand nach unten zur Trennlinie/zum Panel-Rand. Padding unten am navBar-
Container (HBox) hinzugefügt, konsistent mit dem Padding oben.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-27 12:47:58 +02:00
marcus c3f8103572 Fix #43: Benutzerfreundliche Fehlermeldungen bei FAILED-Einträgen im Detailbereich
Jeder Fehlertyp erhält jetzt eine präzise deutsche Meldung:
- Kein lesbarer Text (NO_USABLE_TEXT) → OCR-Hinweis
- Titel zu lang → Titeltext + tatsächliche Länge + Limit
- Defekte/nicht extrahierbare PDF → Beschädigungshinweis
- Verbindungsfehler/Timeout → Verbindungs- und Konfigurationshinweis
- Unbekannter Fehler → neutraler Fallback ohne Log-Verweis

Der Verweis auf "Details im Anwendungslog" wurde vollständig entfernt.
Das "Fehler:"-Präfix in buildDetailText() entfällt; bei vorhandener
Fehlermeldung wird NO_REASONING_TEXT unterdrückt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 12:24:50 +02:00
marcus 3f5602de01 Fix #30: Detailbereich bei SKIPPED-Zeilen mit historischen Informationen befüllen
- Teile DocumentCompletionStatus.SKIPPED in SKIPPED_ALREADY_PROCESSED und
  SKIPPED_FINAL_FAILURE auf, um den Skip-Grund unterscheidbar zu machen
- Führe neuen Typ HistoricalDocumentContext ein (lastTargetFileName,
  lastSuccessInstant, lastFailureInstant, wasEverSuccessful)
- Führe ResolveHistoricalDocumentContextUseCase und
  DefaultResolveHistoricalDocumentContextUseCase ein
- Ersetze GuiHistoricalFileNamePort durch GuiHistoricalDocumentContextPort
- Lade historischen Kontext für übersprungene Zeilen im Coordinator-Worker-Thread
- Zeige im Detailbereich je nach Skip-Grund:
  SKIPPED_ALREADY_PROCESSED: "Bereits erfolgreich verarbeitet am [Datum]. Zieldatei: [Name]."
  SKIPPED_FINAL_FAILURE: "Endgültig fehlgeschlagen am [Datum]. Erneute Verarbeitung nur nach Reset möglich."
- Passe alle betroffenen Tests an

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 12:00:27 +02:00
marcus 1db6e27be8 Fix #41: Historischen KI-Dateinamen für übersprungene Dokumente in Ergebnistabelle anzeigen
Neue Komponenten:
- ResolveHistoricalFileNameUseCase (port/in) und DefaultResolveHistoricalFileNameUseCase (usecase)
- GuiHistoricalFileNamePort (GUI-interner Port, folgt dem Muster von GuiManualFileRenamePort)

GuiBatchRunCoordinator ruft in toRow() für SKIPPED-Zeilen ohne finalName den
historicalFileNamePort auf und trägt den Rückgabewert als neuen Dateinamen ein.

Bootstrap verdrahtet resolveHistoricalFileNameForGui als GuiHistoricalFileNamePort
und übergibt ihn über GuiStartupContext an den GUI-Adapter.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 10:54:31 +02:00