44 lines
2.3 KiB
Python
44 lines
2.3 KiB
Python
"""Auto-Repair-Loop einer Ebene: QA → Befunde beheben, bis 100 % (10.0/10),
|
||
Stillstand (Repair verbessert die Note nicht mehr) oder max_iter erreicht ist.
|
||
|
||
Reine Primitive — keine Kanban-/DB-Kopplung. Der Aufrufer übergibt zwei Coroutinen:
|
||
`messen()` liefert die aktuelle QA-Note (0–10), `reparieren()` behebt die Befunde.
|
||
So bleibt der Loop pro Ebene (Inventar/Artefakte/Guide) identisch testbar.
|
||
"""
|
||
import logging
|
||
|
||
log = logging.getLogger("creator.auto_loop")
|
||
|
||
VOLL = 10.0 # 100 % = 10.0/10
|
||
MAX_ITER = 10 # Sicherheitslimit: mehr Runden ⇒ etwas im System stimmt nicht
|
||
|
||
|
||
async def auto_repair_loop(ebene: str, erst_note: float, reparieren, max_iter: int = MAX_ITER) -> dict:
|
||
"""Loop QA→Repair für eine Ebene.
|
||
|
||
erst_note : float — bereits gemessene QA-Note vor dem ersten Repair (0–10).
|
||
reparieren() -> (float, bool): behebt die Befunde UND gibt die neu gemessene Note
|
||
zurück (die Repair-Bausteine messen ohnehin am Ende — keine Doppel-
|
||
messung) plus „bewegt": ob die Runde etwas getan hat (Fixes, Merges,
|
||
Freisprüche, Nach-Recherche). Eine bewegte Runde darf die Note auch
|
||
mal transient senken (neue Blöcke → neue Verdachte) — Stillstand ist
|
||
erst, wenn NICHTS mehr passiert UND die Note nicht steigt.
|
||
|
||
Stopp bei: Note == VOLL (fertig), unbewegt ohne Verbesserung (stillstand),
|
||
oder max_iter Runden (limit — begrenzt „bewegt ohne Notengewinn"-Livelocks).
|
||
Returns {ebene, note, runden, grund} mit grund ∈ {"fertig","stillstand","limit"}.
|
||
"""
|
||
if erst_note >= VOLL:
|
||
return {"ebene": ebene, "note": erst_note, "runden": 0, "grund": "fertig"}
|
||
note = erst_note
|
||
for runde in range(1, max_iter + 1):
|
||
neu, bewegt = await reparieren()
|
||
log.info("[%s] Auto-Loop Runde %d: %.1f → %.1f (%s)",
|
||
ebene, runde, note, neu, "bewegt" if bewegt else "unbewegt")
|
||
if neu >= VOLL:
|
||
return {"ebene": ebene, "note": neu, "runden": runde, "grund": "fertig"}
|
||
if not bewegt and neu <= note: # nichts getan UND keine Verbesserung ⇒ kein Repair-Pfad
|
||
return {"ebene": ebene, "note": neu, "runden": runde, "grund": "stillstand"}
|
||
note = max(note, neu)
|
||
return {"ebene": ebene, "note": note, "runden": max_iter, "grund": "limit"}
|