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

@ -820,3 +820,36 @@ def test_missing_value_without_declared_assumption_is_repaired_or_unreliable():
session = FakeSession([fehlend], [OK], [SolverCode(code=STRUCTURED_CODE)] * 3)
result = run_pipeline("Aufgabe", session=session, max_revisions=0, max_restarts=0)
assert not result.reliable and any(i.startswith("Datenherkunft") for i in result.reliability_issues)
# --- Solver-Fehler macht das Ergebnis unzuverlässig ---
KAPUTT = "def main():\n raise RuntimeError('Modell nicht lösbar gebaut')\n\n\nif __name__ == '__main__':\n main()\n"
def test_solver_error_after_all_repairs_is_unreliable():
# bisher blieb reliable=True: CLI-Exit 0, Report ohne Warnkasten
session = FakeSession([GOOD], [OK], [SolverCode(code=KAPUTT)] * 3)
result = run_pipeline("Aufgabe", session=session, max_revisions=0, max_restarts=0)
assert result.solver_run.status == SolverStatus.ERROR
assert not result.reliable
assert any(i.startswith("Solver-Fehler: ") and "Modell nicht lösbar gebaut" in i for i in result.reliability_issues)
def test_crash_is_not_an_honest_failure():
from benchmark.benchmark import observed_behaviors
session = FakeSession([GOOD], [OK], [SolverCode(code=KAPUTT)] * 3)
result = run_pipeline("Aufgabe", session=session, max_revisions=0, max_restarts=0)
assert observed_behaviors(result) == set()
def test_second_repair_knows_the_first_error():
# Die Reparatur sah nur den letzten Fehler – und konnte den vorletzten wieder einführen
from solving.solver_stage import solve
erster = "def main():\n raise RuntimeError('Fehler A: Index')\n\n\nif __name__ == '__main__':\n main()\n"
zweiter = "def main():\n raise RuntimeError('Fehler B: Typ')\n\n\nif __name__ == '__main__':\n main()\n"
session = FakeSession([], [], [SolverCode(code=erster), SolverCode(code=zweiter), SolverCode(code=STRUCTURED_CODE)])
solve(session, "Aufgabe", GOOD, retries=2)
reparaturen = [inhalt for stufe, inhalt in session.contents if stufe == "Solver-Reparatur"]
assert "FRÜHERE FEHLVERSUCHE" not in reparaturen[0] # beim ersten gibt es noch keinen Verlauf
assert "Fehler B: Typ" in reparaturen[1] and "Versuch 1: " in reparaturen[1] and "Fehler A: Index" in reparaturen[1]