This commit is contained in:
Team3
2026-07-04 16:50:50 +02:00
parent 8488737303
commit 92c69c1561
7 changed files with 298 additions and 37 deletions

View File

@@ -1181,3 +1181,144 @@ async def test_namecheck_ok_behaelt_titel(testdb, tmp_path, monkeypatch):
block = await db.kanban_get_card(TOPIC, B, "b-c9")
assert block["payload"]["title"] == "Eigener Titel"
assert block["payload"]["description"] == "Eigene Beschreibung"
# ── Sanierung: Titel auf Korpus-Form, Beschreibungspflicht (QA: fremd/hygiene) ──────
def test_sanierung_schema_varianten():
assert bi._sanierung_schema({"title": " k-Color ", "description": "d"}) == ("k-Color", "d")
assert bi._sanierung_schema({"title": "", "description": "nur Beschreibung"}) == ("", "nur Beschreibung")
assert bi._sanierung_schema({"title": "x" * 90, "description": "d"}) == ("", "d") # zu lang
assert bi._sanierung_schema({"title": "", "description": ""}) is None
assert bi._sanierung_schema("quatsch") is None
def test_sanierung_noetig():
ctoks = {"color", "graph"}
assert bi._sanierung_noetig({"title": "k-Color", "description": ""}, ctoks) # leere Beschreibung
assert bi._sanierung_noetig({"title": "k-Coloring", "description": "d"}, ctoks) # kein Korpus-Anker
assert not bi._sanierung_noetig({"title": "k-Color", "description": "d"}, ctoks)
assert not bi._sanierung_noetig({"title": "k-Coloring", "description": "d"}, None) # thema: kein Korpus
def _sanierung_env(tmp_path, monkeypatch, antwort):
"""Korpus mit 'k-Color'-Oberflächenform; Judge antwortet mit `antwort`."""
(tmp_path / "korpus.txt").write_text(
"Das k-Color Problem: Kann der Graph mit k Farben gefärbt werden? NP-vollständig.",
encoding="utf-8")
monkeypatch.setattr(bi, "source_folder", lambda t: tmp_path)
seen = {}
async def fake_slot(ctx, label, *, key, prompt, role, capabilities, payload, timeout):
seen[key] = prompt
return "ok", payload((0, json.dumps(antwort["val"]), ""))
monkeypatch.setattr(bi, "run_single_slot", fake_slot)
return GenContext(topic=TOPIC, provider="claude", is_cancelled=lambda: False), seen
async def test_singleton_unverankert_wird_saniert(testdb, tmp_path, monkeypatch):
"""Singleton-Cluster mit Reader-Titel ohne Korpus-Anker: Naming wird nicht mehr
übersprungen — der Titel wird auf die Korpus-Oberflächenform umgeschrieben
(gemessener aak-Fall 'k-Coloring' statt 'k-Color')."""
db = testdb
antwort = {"val": {"title": "k-Color", "description": "Kann der Graph mit k Farben gefärbt werden?"}}
ctx, seen = _sanierung_env(tmp_path, monkeypatch, antwort)
async def fake_members(topic, cid):
return [{"norm": "k-coloring", "title": "k-Coloring",
"description": "Kann der Graph mit k Farben gefärbt werden?",
"readers": ["r1", "r2"], "sources": []}]
monkeypatch.setattr(bi, "_member_rows", fake_members)
payload = {"title": "k-Coloring", "description": "Kann der Graph mit k Farben gefärbt werden?"}
await db.kanban_upsert_card(TOPIC, B, "c1", "cluster", "naming", payload)
await bi._name_one(ctx, _mk_flow(tmp_path), {"card_id": "c1", "payload": payload})
card = await db.kanban_get_card(TOPIC, B, "c1")
assert card["stage"] == "naming_check"
assert card["payload"]["title"] == "k-Color"
assert any("-sanierung-" in k for k in seen)
async def test_leere_beschreibung_wird_gefuellt(testdb, tmp_path, monkeypatch):
"""Verankerter Titel, leere Beschreibung (gemessener aak-Fall der SetCover-Fragmente):
Beschreibung wird belegt nachgefasst, Titel bleibt."""
db = testdb
antwort = {"val": {"title": "k-Color", "description": "Färbbarkeit mit k Farben."}}
ctx, _seen = _sanierung_env(tmp_path, monkeypatch, antwort)
async def fake_members(topic, cid):
return [{"norm": "k-color", "title": "k-Color", "description": "",
"readers": ["r1"], "sources": []}]
monkeypatch.setattr(bi, "_member_rows", fake_members)
payload = {"title": "k-Color", "description": ""}
await db.kanban_upsert_card(TOPIC, B, "c5", "cluster", "naming", payload)
await bi._name_one(ctx, _mk_flow(tmp_path), {"card_id": "c5", "payload": payload})
card = await db.kanban_get_card(TOPIC, B, "c5")
assert card["payload"]["title"] == "k-Color"
assert card["payload"]["description"] == "Färbbarkeit mit k Farben."
async def test_sanierung_unverankerter_vorschlag_verfaellt(testdb, tmp_path, monkeypatch):
"""Judge-Vorschlag ohne Korpus-Anker wird verworfen (dieselbe Messlatte wie QA-fremd);
die Beschreibung wird trotzdem übernommen."""
db = testdb
antwort = {"val": {"title": "Graphfärbungsproblem", "description": "Färbbarkeit mit k Farben."}}
ctx, _seen = _sanierung_env(tmp_path, monkeypatch, antwort)
async def fake_members(topic, cid):
return [{"norm": "k-coloring", "title": "k-Coloring",
"description": "Kann der Graph mit k Farben gefärbt werden?",
"readers": ["r1"], "sources": []}]
monkeypatch.setattr(bi, "_member_rows", fake_members)
payload = {"title": "k-Coloring", "description": "Kann der Graph mit k Farben gefärbt werden?"}
await db.kanban_upsert_card(TOPIC, B, "c2", "cluster", "naming", payload)
await bi._name_one(ctx, _mk_flow(tmp_path), {"card_id": "c2", "payload": payload})
card = await db.kanban_get_card(TOPIC, B, "c2")
assert card["payload"]["title"] == "k-Coloring" # unverankert → verfällt
assert card["stage"] == "naming_check"
async def test_sanierung_fail_open(testdb, tmp_path, monkeypatch):
"""Judge-Ausfall → Karte läuft unverändert weiter (kein Deadletter am Naming)."""
db = testdb
(tmp_path / "korpus.txt").write_text("Der Graph ist endlich.", encoding="utf-8")
monkeypatch.setattr(bi, "source_folder", lambda t: tmp_path)
async def broken_slot(*a, **kw):
return "failed", None
async def fake_members(topic, cid):
return [{"norm": "x", "title": "Graph", "description": "", "readers": ["r1"], "sources": []}]
monkeypatch.setattr(bi, "run_single_slot", broken_slot)
monkeypatch.setattr(bi, "_member_rows", fake_members)
payload = {"title": "Graph", "description": ""}
await db.kanban_upsert_card(TOPIC, B, "c3", "cluster", "naming", payload)
ctx = GenContext(topic=TOPIC, provider="claude", is_cancelled=lambda: False)
await bi._name_one(ctx, _mk_flow(tmp_path), {"card_id": "c3", "payload": payload})
card = await db.kanban_get_card(TOPIC, B, "c3")
assert card["stage"] == "naming_check" and card["payload"]["title"] == "Graph"
async def test_sanierung_anker_und_beschreibung_ok_kein_judge(testdb, tmp_path, monkeypatch):
"""Verankerter Titel + Beschreibung vorhanden → kein Sanierungs-Call."""
db = testdb
(tmp_path / "korpus.txt").write_text("Das k-Color Problem im Graph.", encoding="utf-8")
monkeypatch.setattr(bi, "source_folder", lambda t: tmp_path)
async def never_slot(*a, **kw):
raise AssertionError("Sanierung darf ohne Befund-Form nicht laufen")
async def fake_members(topic, cid):
return [{"norm": "k-color", "title": "k-Color", "description": "d", "readers": ["r1"], "sources": []}]
monkeypatch.setattr(bi, "run_single_slot", never_slot)
monkeypatch.setattr(bi, "_member_rows", fake_members)
payload = {"title": "k-Color", "description": "d"}
await db.kanban_upsert_card(TOPIC, B, "c4", "cluster", "naming", payload)
ctx = GenContext(topic=TOPIC, provider="claude", is_cancelled=lambda: False)
await bi._name_one(ctx, _mk_flow(tmp_path), {"card_id": "c4", "payload": payload})
assert (await db.kanban_get_card(TOPIC, B, "c4"))["stage"] == "naming_check"