fix: Codex-Review-Befunde zu Verlauf-Detailanzeige und Log-Umstellung

- RuntimeLogDirectoryReconfigurer: Bei fehlgeschlagenem Log4j2-Reconfigure wird die
  System-Property log.directory auf den vorherigen Wert zurückgesetzt, damit ein
  späterer Versuch nicht faelschlich als "bereits aktiv" uebersprungen wird. Test ergaenzt.
- GuiHistoryTab: Beim Detailwechsel wird die KI-Rohantwort zurückgesetzt; verspätet
  eintreffende Detail-Ergebnisse einer inzwischen gewechselten/abgewählten Selektion
  werden über einen Fingerprint-Abgleich verworfen (kein "A unter B", keine dauerhaft
  sichtbare fremde Rohantwort bei Ladefehler).
- GuiHistoryTab: Der technische Fehler-Tooltip wird bei nicht-fehlerhaften Datensätzen
  auf den Standardtext zurückgesetzt (keine fremde Fehlermeldung mehr sichtbar).
- AiFailureMessageTranslator: praezisere Meldung ("kein gueltiges JSON oder ein
  Pflichtfeld fehlt").

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 18:53:46 +02:00
parent a3ed5329af
commit c7a40298df
4 changed files with 64 additions and 3 deletions
@@ -83,7 +83,7 @@ public final class AiFailureMessageTranslator {
|| lower.contains("empty_response")
|| lower.contains("missing_title") || lower.contains("blank_title")
|| lower.contains("missing_reasoning")) {
return "KI-Antwort war nicht im erwarteten Format (kein gültiges JSON). "
return "KI-Antwort war nicht im erwarteten Format (kein gültiges JSON oder ein Pflichtfeld fehlt). "
+ "Bitte erneut verarbeiten; hält der Fehler an, den Prompt anpassen.";
}
@@ -146,6 +146,13 @@ public final class GuiHistoryTab {
private final TextArea reasoningArea = new TextArea();
private final TextArea rawResponseArea = new TextArea();
/**
* SHA-256 des zuletzt angeforderten Detail-Dokuments. Dient dazu, verspätet
* eintreffende Detail-Ergebnisse einer inzwischen abgewählten oder gewechselten
* Selektion zu verwerfen. Zugriff ausschließlich auf dem JavaFX Application Thread.
*/
private String pendingDetailFingerprintHex;
private final Button resetButton = new Button("Status zurücksetzen");
private final Button deleteButton = new Button("Eintrag löschen");
@@ -715,7 +722,10 @@ public final class GuiHistoryTab {
}
private void loadDetails(DocumentFingerprint fingerprint) {
pendingDetailFingerprintHex = fingerprint.sha256Hex();
reasoningArea.setText(LOADING_TEXT);
rawResponseArea.setText("");
rawResponseArea.setPromptText(NO_RAW_RESPONSE_TEXT);
attemptsItems.clear();
clearDetailFields();
@@ -729,6 +739,9 @@ public final class GuiHistoryTab {
try {
Optional<HistoryDetailsResult> result = detailsPort.loadDetails(configPath, fingerprint);
Platform.runLater(() -> {
if (isSupersededDetail(fingerprint)) {
return;
}
if (result.isEmpty()) {
clearDetailPane();
statusBarLabel.setText("Eintrag nicht mehr vorhanden.");
@@ -740,6 +753,10 @@ public final class GuiHistoryTab {
LOG.error("Fehler beim Laden der Dokumentdetails für {}: {}",
fingerprint.sha256Hex(), ex.getMessage(), ex);
Platform.runLater(() -> {
if (isSupersededDetail(fingerprint)) {
return;
}
clearDetailPane();
reasoningArea.setText("Fehler beim Laden der Details: " + ex.getMessage());
statusBarLabel.setText("Fehler beim Laden der Details.");
});
@@ -957,6 +974,7 @@ public final class GuiHistoryTab {
if (!failureRelevant || attempts.isEmpty()) {
failureArea.setText("");
failureArea.setPromptText("Keine Fehlerdetails für diesen Status.");
failureArea.setTooltip(new Tooltip(GuiTooltipTexts.VERLAUF_FAILURE_AREA));
return;
}
@@ -1010,7 +1028,19 @@ public final class GuiHistoryTab {
}
}
/**
* Prüft, ob ein asynchron geladenes Detail-Ergebnis inzwischen überholt ist, weil
* mittlerweile ein anderes (oder kein) Dokument ausgewählt wurde.
*
* @param fingerprint der Fingerprint, für den das Ergebnis geladen wurde
* @return {@code true}, wenn das Ergebnis verworfen werden soll
*/
private boolean isSupersededDetail(DocumentFingerprint fingerprint) {
return !fingerprint.sha256Hex().equals(pendingDetailFingerprintHex);
}
private void clearDetailPane() {
pendingDetailFingerprintHex = null;
clearDetailFields();
attemptsItems.clear();
failureArea.setText("");