GuiBatchRunTab: Buttons "Erneut verarbeiten" / "Status zurücksetzen" und
Meldungsbereich in die linke SplitPane-Spalte unterhalb der Tabelle
verschoben. Detailbereich (rechte Spalte) erstreckt sich dadurch vollständig
von oben bis unten – mehr Platz für die PDF-Vorschau.
PdfPreviewPane: Gesamten suppressScrollReset / ChangeListener-Code entfernt.
Seite wird jetzt immer fit-to-view ohne Scrollbalken angezeigt: Seitenverhältnis
wird asynchron per renderPage(0.05f) ermittelt, Zoom über setZoomFactor() gesetzt
und bei Größenänderungen der Anzeigefläche automatisch neu berechnet.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Der bisherige ImageView-imageProperty-Listener mit Platform.runLater()
wurde von PDFViewFX nach dem Rendering noch einmal ueberschrieben, weil
die interne Scroll-Korrektur ebenfalls asynchron laeuft und spaeter
ausgefuehrt wird.
Neuer Ansatz: Nach jedem pdfView.load() und pdfView.setPage()-Aufruf
wird ein einmaliger ChangeListener auf die vvalueProperty des internen
ScrollPane registriert (scheduleScrollToTop). Sobald PDFViewFX seine
interne Scroll-Position durchschreibt und der Wert von 0 abweicht,
korrigiert der Listener ihn sofort auf 0 und entfernt sich danach selbst.
Damit greift der Eingriff immer nach dem internen PDFViewFX-Scroll,
unabhaengig von der Renderzeit.
Zusaetzlich wird ein aktiver Listener bei schnellen Seitenwechseln
(cancelScrollToTopListener) und bei clear() sauber aufgeraeumt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
pdfviewfx wird von 3.1.1 auf 3.3.2 aktualisiert. Version 3.3.1 behebt
'Do not interrupt rendering', wodurch ClosedByInterruptException bei
schnellem Seitenwechsel (#27 Folge-Bug) und das Ausbleiben weiterer
Renderings ab Seite 3+ (#29 Folge-Bug) nicht mehr auftreten.
Das 100-ms-PauseTransition-Workaround fuer den Seitenanfang wird ersetzt
durch einen Listener auf die imageProperty des internen ImageView der
PDFView-Skin. Der Listener scrollt erst dann zum Seitenanfang, wenn
das Rendering tatsaechlich abgeschlossen ist und pendingScrollToTop
gesetzt wurde (bei loadSource und Seitenwechsel-Buttons). Dadurch wird
der Seitenanfang zuverlaessig angezeigt, unabhaengig von der Renderzeit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bug #27: Den zu aggressiven ScrollEvent::consume-Filter durch einen
gezielten Filter auf dem internen ScrollPane der PDFView-Skin ersetzt.
Der Filter konsumiert nur dann, wenn die Seite keinen ueberlaufenden
Inhalt hat oder der Scroll-Inhalt an der oberen bzw. unteren Grenze
angekommen ist. Dadurch bleibt Inhalts-Scrolling innerhalb einer Seite
weiterhin moeglich; nur der Seitenwechsel per Mausrad wird verhindert.
Bug #29: Platform.runLater() durch eine PauseTransition (100 ms) ersetzt,
die nach dem vollstaendigen Rendering-Durchlauf der PDFView-Skin den
internen ScrollPane explizit auf vValue=0 zuruecksetzt. So wird der
Seitenanfang zuverlaessig angezeigt, ohne dass die Skin die Position
nachtraeglich ueberschreibt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bug #27: ScrollEvent-Filter auf PDFView verhindert Seitenwechsel durch Mausrad.
Seitenwechsel sind ausschliesslich ueber die Navigations-Buttons moeglich.
Die Seitenzahl wird nur noch bei Button-Klick aktualisiert.
Bug #29: Nach dem Laden einer PDF und bei Seitenwechsel ueber Buttons wird
die Seite jetzt explizit von oben angezeigt. Der setPage()-Aufruf erfolgt
via Platform.runLater() nach dem Layout-Pass, sodass stets der Seitenanfang
sichtbar ist.
Co-Authored-By: Claude Sonnet 4.6 <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>
Neue Klasse AiFailureMessageTranslator übersetzt technische englische
Fehlertexte (z.B. HTTP-Statuscodes, Verbindungsfehler) in lesbare
deutsche Benutzerhinweise. GuiBatchRunTab nutzt den Translator vor der
Anzeige; das Datenmodell (aiFailureMessage) bleibt unverändert.
Unit-Tests decken alle definierten Mapping-Fälle ab.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- DocumentCompletionEvent um optionales Feld failureMessage erweitert
- DocumentProcessingCoordinator leitet Fehlermeldung bei Fehler-Status durch
- GuiBatchRunResultRow um aiFailureMessage (Optional<String>) ergänzt
- GuiBatchRunCoordinator.toRow() befüllt aiFailureMessage aus dem Event
- GuiBatchRunTab.buildDetailText() zeigt bei fehlendem Reasoning und
vorhandenem Fehlergrund: "⚠ Fehler: <Meldung>" vor dem Hinweistext
- Alle Tests angepasst und neue Unit-Tests für aiFailureMessage ergänzt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Verarbeitungsfehler (PreCheckFailed, AiFunctionalFailure) und
Retry-Entscheidungen (FAILED_RETRYABLE, FAILED_FINAL) werden nun auf
WARN-Level geloggt. EmptyList- und IncompleteConfiguration-Ergebnisse
des Modellabrufs sowie fehlende Quelldateien im Mini-Lauf ebenfalls.
Tests angepasst: Assertions prüfen jetzt das korrekte WARN-Level.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Synthetisierte Fehlzeilen (fehlende Quelldatei) werden nur im lokalen
failedCount gezählt, nicht in RunSummary. Der abschließende Log-Eintrag
verwendete bisher summary.failedCount() und zeigte daher fehlgeschlagen=0
obwohl die GUI-Anzeige korrekt war.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
appendSummary verwendete bisher summary.failedCount() aus dem RunSummary-Objekt
des echten Laufs, das von synthesizeMissingSourceFileRows() nachträglich hochgezählte
failedCount nicht kannte. Nun werden die lokalen Zähler (successCount, failedCount,
skippedCount) verwendet, die über onDocumentCompleted und die Synthese konsistent
gepflegt werden. Test ergänzt um Assertion auf '1 fehlgeschlagen' in der Zusammenfassung.
Co-Authored-By: Claude Sonnet 4.6 <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>
Wenn startReprocessing() false zurückgibt, wurde bisher
ALREADY_RUNNING_HINT angezeigt – obwohl handleReprocessSelected()
isRunning() bereits vorab prüft. Das false bedeutet in diesem Kontext
einen Reset-Fehler, nicht einen laufenden Run.
Neu: REPROCESS_RESET_FAILED_HINT mit erklärender Meldung.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Das Problem: Der „Erneut verarbeiten"-Button startete einen Mini-Lauf,
ohne den DB-Status der selektierten Dateien zurückzusetzen. Dateien mit
FAILED_FINAL-Status wurden daher vom Use Case übersprungen.
Die Lösung:
1. Neue Methode startReprocessing() in GuiBatchRunCoordinator, die
resetPort.reset() SYNCHRON vor dem Mini-Lauf aufruft.
2. handleReprocessSelected() in GuiBatchRunTab nutzt jetzt
startReprocessing() statt startMiniRun() direkt.
3. Test-Fix: noOpReset muss die Fingerprints in der erfolgreich-zurückgesetzt-
Liste enthalten, damit successCount() > 0 ist.
Spec-Konformität:
- Reset erfolgt synchron vor dem Worker-Thread-Start
- Keine neue Architektur-Verletzung
- Hexagonale Architektur bleibt sauber (Port/Adapter)
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>
Statusicons (Bug 2): Emoji-Codepunkte werden durch BMP-Zeichen ersetzt
(✔ ⚠ ✘ ►), die in JavaFX auf Windows zuverlässig gerendert werden.
Die Statusspalte erhält eine farbige Cell-Factory (grün/orange/rot/grau).
Stale Summary (Bug 1): observerSummary wird zu Beginn jedes Laufs
zurückgesetzt, damit eine abgebrochene Vorgänger-Zusammenfassung
nicht als Ergebnis des neuen Laufs erscheint.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fuehrt neuen Inbound-Adapter-Subpfad batchrun/ mit Tab, Koordinator,
Launcher-Port und Ergebniszeilen-Model ein; der Batch-Lauf laeuft auf
einem Hintergrund-Worker, UI-Updates ausschliesslich via FX-Dispatcher.
- Ergaenzt application.port.in um BatchRunProgressObserver,
BatchRunCancellationToken, DocumentCompletionEvent/-Status und
RunSummary; DefaultBatchRunProcessingUseCase und
DocumentProcessingCoordinator melden Lauf-/Dokument-Ereignisse an den
Beobachter und unterstuetzen Soft-Stop zwischen Kandidaten.
- Verdrahtet BootstrapRunner so, dass die GUI den vollstaendigen
Headless-Pipelinepfad (Migration, Validierung, Schema-Init, Lock,
Use-Case) mit Observer und Cancellation ausfuehrt; headless-Verhalten
bleibt unveraendert.
- Editor-Workspace bettet den zweiten Tab ein, sperrt Tab 1 mit
Hinweisbanner waehrend eines Laufs und fragt den Benutzer beim
Schliessen waehrend eines laufenden Batches.
- Fuegt Tests fuer Observer-Wiring, Koordinator-Lebenszyklus und
Tab-Smoke-Verhalten ein; aktualisiert die GUI-Bedienanleitung und
docs/betrieb.md auf den neuen Tab.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Der API-Key-Herkunfts-Label (apiKeyOriginLabel) zeigte bisher sowohl
INFO-Befunde (Schlüssel kommt aus Umgebungsvariable) als auch
WARNING/ERROR-Befunde (Schlüssel fehlt) an. Da das fieldErrorLabel
direkt darunter dieselben WARNING/ERROR-Befunde bereits anzeigt,
erschien die „Kein API-Key"-Meldung zweimal im selben Bereich.
Lösung: refreshApiKeyOriginLabels() wertet nur noch INFO-Befunde aus.
WARNING/ERROR-Befunde für fehlende API-Keys werden ausschließlich vom
fieldErrorLabel angezeigt. STYLE_ORIGIN_MISSING entfernt.
Drei neue Smoke-Tests sichern das Verhalten ab:
- apiKeyAbsent_originLabelHidden
- apiKeyAbsent_fieldErrorLabelVisible
- apiKeyAbsent_noDuplicateMessageInPendingMessages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Der bisherige Standard-Default von 5000 Zeichen löste gemäß Spezifikation
sofort eine starke Warnung in der GUI aus (Schwellenwert: >3000).
Dies ist nicht benutzerfreundlich.
Der neue Standard-Default ist 1000 Zeichen (unkritisch laut Spec).
Das entspricht einer besseren Balance zwischen KI-Input-Größe und
Benutzerwarnung beim Start.
Änderungen:
- GuiConfigurationTemplateFactory: Standardvorlage auf 1000 geändert
- Alle *.properties-Beispieldateien aktualisiert
- Dokumentation in gui-bedienanleitung.md ergänzt
- Betroffene Tests angepasst (etwa 10 Testdateien)
- Alle 206 Tests bestehen nach der Änderung
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- clearMessagesButton ist jetzt linksbündig (CENTER_LEFT statt CENTER_RIGHT)
- pendingMessages.clear() wird auch am Anfang von runValidationAction() und
runTechnicalTestsAction() aufgerufen; jeder Durchlauf zeigt nur seine eigenen
Befunde
- GuiValidateActionSmokeTest: Erwartung von 2 auf 1 Bestätigungsmeldung nach
zwei Klicks angepasst (Replace- statt Akkumulierungsverhalten)
- Zwei neue Smoke-Tests: validationAction_clearsPreviousMessages und
technicalTestsAction_clearsPreviousMessages
- Dokumentation in docs/gui-bedienanleitung.md ergänzt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- pendingMessages wird in applyEditorState() geleert, bevor die neue
Konfiguration angezeigt wird (gilt für Neu und Öffnen)
- Neuer Button "Meldungen leeren" unterhalb des Meldungsbereichs;
ruft clearMessages() auf, das pendingMessages leert und die Ansicht
aktualisiert
- Dokumentation in docs/gui-bedienanleitung.md ergänzt
- Zwei neue Smoke-Tests: Neu löscht bisherige Meldungen,
clearMessages() leert den Bereich vollständig
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
- AP-001: Betriebs- und Startdokumentation für GUI und headless
konsolidiert (betrieb.md, README.md)
- AP-002: Endbenutzer-Bedienanleitung gui-bedienanleitung.md angelegt
(deskriptiv, 13 Kapitel, deutsch, Windows-Hinweise)
- AP-003: Konfigurationsbeispiele docs/examples/application.properties
und docs/examples/prompt.txt konsolidiert, konsistent mit Standardvorlage
- AP-004: Regressionstests für headless Abwärtskompatibilität
(JAR-Smoke-IT mit --config-Varianten und JavaFX-Freiheit)
- AP-005: GUI-Smoke-Tests für V2.0-Kernumfang vervollständigt
(Startup-Notice-Sichtbarkeit im Header)
- AP-006: Build- und Packaging-Dokumentation im Abschnitt
"Build und Packaging" in betrieb.md, README-Artefaktnamen korrigiert
- AP-007: Integrierte Gesamtprüfung durchgeführt, V2.0-Abschnitt in
befundliste.md — keine Release-Blocker, zwei nicht blockierende
Restpunkte (R1 ByteBuddy-Warning, R2 fehlender visueller GUI-Render-Test)
- AP-008: entfiel (keine Release-Blocker zu beheben)
- AP-009: Finale Gesamtprüfung, Freigabedokument docs/freigabe-v2_0.md
mit Git-HEAD, Build-/Test-Ergebnissen, Freigabeaussage. Ein während
der Stichprobe entdeckter Doku-Defekt (R3: API-Key-Legacy-Variable)
wurde unmittelbar in gui-bedienanleitung.md korrigiert.
V2.0 ist freigabefähig. 1.403 Tests grün, 0 Failures, 0 Errors.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- AP-004: Speichern und Speichern unter mit .bak-Rotation,
normalisierte .properties-Ausgabe, API-Key-Erhaltung bei leerem Feld
- AP-005: Dirty-State aus Editorzustand, Fenstertitel- und
Header-Marker, Schutzdialog (Speichern/Verwerfen/Abbrechen)
vor Neu/Öffnen/Schließen inkl. Close-Request-Handler
- AP-006: Vollständige Editoroberfläche mit allen Konfigurationswerten,
native Pfad-Picker für Quell-/Zielordner, SQLite- und Prompt-Datei,
Files.exists-Pfadprüfung auf Worker-Thread verlagert
- AP-007: Integrations- und Regressionstests für alle zentralen
Bedienpfade, Writer-Threading-Contract dokumentiert und getestet
Hexagonale Architektur, Threadingmodell und Naming-Regel durchgehend
eingehalten. Keine Vorgriffe auf M11/M12.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>