feat: Warnung bei ungeschützter Sandbox, Prüf-Regel für konstante Kosten, Grund je Korrekturrunde

- sandbox_warning: fehlt bubblewrap oder ist SOLVER_SANDBOX=aus, steht das im Log
  und in SolverRun.warnings (vorher lief der Code stillschweigend ungeschützt)
- Dijkstra-Markierung: der Report erklärt den Begriff selbst (DIJKSTRA_EXPLANATION),
  check_text_quality zählt das als Erklärung; Stamm 'markier' -> 'markierung'
- Pruef-Prompt Regel 7: entscheidungsunabhängige Terme ohne Zahlenwert dürfen
  weggelassen oder symbolisch mitgeführt werden (wagner_whitin_dijkstra: 1+1 statt
  2+1 Korrekturrunden, n=2)
- revision_reasons: jede Korrekturrunde nennt ihren Auslöser im Log

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-09-17 16:28:39 +02:00
commit 0f1ab04a8d

View file

@ -309,3 +309,31 @@ def test_repair_leaves_correct_words_and_identifiers_alone():
assert fix_transliterations(richtig) == richtig
namen = "Bindend: Spaet_zu_Frueh_Verbot und KeinFruehNachSpaet sowie Kapazitaet_M1."
assert fix_transliterations(namen) == namen
def _dijkstra_run(title, note, steps=True):
from core.model_schema import GraphSolution, ResultTable
graph = GraphSolution.model_validate({
"nodes": ["0", "1"], "arcs": [{"source": "0", "target": "1", "weight": 8}], "path": ["0", "1"],
"steps": [{"node": "0", "label": 0}, {"node": "1", "label": 8}] if steps else [],
"node_meaning": "Zeitpunkt", "arc_meaning": "Kauf und Nutzung"})
return SolverRun(status=SolverStatus.OPTIMAL, objective_value=8, graph=graph,
tables=[ResultTable(title=title, columns=["Knoten", "Marke"], rows=[["0", 0]], note=note)])
def test_dijkstra_marks_explained_by_the_report_are_not_flagged():
# beobachtet: „Dijkstra-Markierungen“ gemeldet, obwohl der Report den Markierungsverlauf erklärt
from solving.solver_stage import check_text_quality
run = _dijkstra_run("Dijkstra-Markierungen", "Die Knoten in der Reihenfolge ihrer Markierung.")
assert check_text_quality(run, "Ersatzplanung als kürzester Weg.") == []
def test_marks_without_dijkstra_steps_are_still_flagged():
from solving.solver_stage import check_text_quality
run = _dijkstra_run("Marken je Knoten", None, steps=False)
assert any("Markierung" in b for b in check_text_quality(run, "Ersatzplanung als kürzester Weg."))
def test_everyday_marked_is_no_jargon():
from checks.model_checks import unexplained_jargon
assert unexplained_jargon("nur die mit 'ja' markierten Kombinationen gehören zum Plan", "Zusammenfassung") == []