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

@ -128,20 +128,24 @@ def split_math(text: str) -> list:
return _join_text(parts)
def _graph_section(run) -> list:
"""Zeichnung des Graphen mit hervorgehobenem Weg, darüber die Bedeutung von Knoten und Bogen."""
def _graph_section(run, sense: str = "minimize") -> list:
"""Zeichnung des Graphen mit hervorgehobenem Weg, darüber die Bedeutung von Knoten und Bogen.
Bei maximize (längster Weg, z. B. kritischer Pfad) heißt der Weg nicht „kürzester“.
"""
g = run.graph
if g is None:
return []
weg = "längste" if sense == "maximize" else "kürzeste"
doc = [("p", f"Knoten des Graphen: {g.node_meaning} Ein Bogen: {g.arc_meaning}")]
zeichnung = charts.graph_chart([n for n in g.nodes], [(a.source, a.target, a.weight) for a in g.arcs],
path=list(g.path), title="Graph mit kürzestem Weg")
path=list(g.path), title=f"Graph mit {weg}m Weg")
if zeichnung:
doc.append(("svg", zeichnung))
if g.path and run.objective_value is not None:
auf_weg = set(zip(g.path, g.path[1:]))
summanden = " + ".join(_fmt_number(a.weight) for a in g.arcs if (a.source, a.target) in auf_weg)
doc.append(("p", "Hervorgehoben ist der kürzeste Weg " + " → ".join(g.path)
doc.append(("p", f"Hervorgehoben ist der {weg} Weg " + " → ".join(g.path)
+ f" mit der Länge {summanden} = {_fmt_number(run.objective_value)}."))
if g.steps:
doc += [("h4", "Markierungsverlauf des Dijkstra-Algorithmus"),
@ -182,7 +186,7 @@ def _result_section(result) -> list:
f"{len(run.variables)} Variablen wurden aus der Lösung nachgerechnet und eingehalten."))
# Die Erklärung („Wie das Modell die Aufgabe sieht“) steht als eigener Abschnitt vor dem Modell, also schon
# vor diesem Ergebnis – die Fachbegriffe der Tabellen sind damit eingeführt, bevor sie auftauchen.
doc += _graph_section(run)
doc += _graph_section(run, spec.objective.sense.value)
for table in run.tables:
doc += [("h3", table.title),
("table", table.columns, [[_fmt_cell(c) for c in row] for row in table.rows])]