fix: Solver-Fehler gilt als unzuverlässig; Aufräumrunde ohne LLM

- Status error nach allen Reparaturen -> reliable=False („Solver-Fehler: …“, auch bei
  --resolve); vorher Exit-Code 0 ohne Warnkasten. Benchmark zählt einen Absturz nicht
  als ehrliches Scheitern.
- Report: „längster Weg“ bei maximize; Harness druckt „Gefundener Weg“.
- check_requested_method: Verneinung kurz davor im selben Satz („ohne/nicht/statt/
  anders als Dijkstra“) ist keine Forderung.
- Reparatur-Prompt enthält die Fehlertexte aller früheren Versuche.
- ruff (F, E9) als Test tests/test_lint.py, Konfiguration in pyproject.toml.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-09-18 18:15:22 +02:00
commit f101b63947

View file

@ -213,6 +213,11 @@ def _assess_run(result: PipelineResult) -> None:
"""Abnahme eines Solver-Laufs: Befunde, die das Ergebnis unzuverlässig machen, in `result` übernehmen."""
run = result.solver_run
log(f"Solver: {run.status.value}, Zielwert: {run.objective_value}" + (f"\n {run.error}" if run.error else ""))
if run.status == SolverStatus.ERROR:
# Auch nach allen Reparaturen kein Ergebnis – bisher blieb reliable=True und die CLI endete mit 0
result.reliable = False
result.reliability_issues.append(f"Solver-Fehler: {solver_error_summary(run)}")
log("ERGEBNIS UNZUVERLÄSSIG – das Solver-Programm ist auch nach allen Reparaturversuchen gescheitert.")
if run.feasibility:
result.reliable = False
result.reliability_issues += [f"Zulässigkeitsprüfung: {p}" for p in run.feasibility]
@ -233,6 +238,12 @@ def _assess_run(result: PipelineResult) -> None:
log(f" Mit angenommenen Daten gelöst ({len(result.solver_code.data_assumptions)} Annahmen).")
def solver_error_summary(run) -> str:
"""Erste aussagekräftige Zeile des Fehlers – der volle Text steht im Report unter „Ergebnis“."""
zeilen = [z.strip() for z in (run.error or "").splitlines() if z.strip()]
return (zeilen[-1] if zeilen else "das Programm meldete selbst Status 'error'")[:200]
def _log_usage(session, result: PipelineResult) -> None:
result.usage = session.usage
cost = f", Kosten ${session.usage.cost_usd:.4f}" if session.usage.cost_usd is not None else ""
@ -394,8 +405,11 @@ def resolve_result(result_json: str, data_file: str | None = None, solver_timeou
run.warnings += check_multistart(run, result.specification.objective.sense.value)
result.solver_run = run
# Frühere Befunde (Zielgröße, Abbildung, Datenherkunft) gelten weiter – nur die Zulässigkeit ist neu geprüft
result.reliability_issues = ([p for p in result.reliability_issues if not p.startswith("Zulässigkeitsprüfung: ")]
# Frühere Befunde (Zielgröße, Abbildung, Datenherkunft) gelten weiter – nur Lauf und Zulässigkeit sind neu geprüft
result.reliability_issues = ([p for p in result.reliability_issues
if not p.startswith(("Zulässigkeitsprüfung: ", "Solver-Fehler: "))]
+ ([f"Solver-Fehler: {solver_error_summary(run)}"]
if run.status == SolverStatus.ERROR else [])
+ [f"Zulässigkeitsprüfung: {p}" for p in run.feasibility])
result.reliable = not result.reliability_issues
result.usage = None # keine LLM-Nutzung in diesem Lauf