This commit is contained in:
team3
2026-07-12 20:02:13 +02:00
parent 31a42bbf1d
commit cde1721d10
23 changed files with 731 additions and 219 deletions

View File

@@ -1,4 +1,4 @@
"""Ebene 3.5 Diagramme: deterministische DAG-Diagramme (kein LLM), Spec→Mermaid."""
"""Ebene 3.5 Diagramme: LLM-Diagramme (Automat/Ablauf/Baum), Spec→Mermaid, Assembly."""
import db
import diagramme
@@ -21,7 +21,7 @@ def _baustein_mit_kette(topic, n=4):
def test_spec_zu_mermaid_flowchart():
spec = {"typ": "dependency",
spec = {"typ": "flow",
"knoten": [{"id": "1", "label": "A"}, {"id": "2", "label": 'B "x" [y]'}],
"kanten": [{"von": "1", "zu": "2", "label": ""}]}
out = diagramme._spec_zu_mermaid(spec)
@@ -30,25 +30,11 @@ def test_spec_zu_mermaid_flowchart():
assert '"' not in out.split("\n", 1)[1].replace('["', "").replace('"]', "") # Label entschärft
async def test_dag_diagramm_wird_gebaut_und_verifiziert():
topic = topic_anlegen("diag-dag")
b, atome = _baustein_mit_kette(topic, n=4) # 3 Kanten ≥ DIAGRAMM_MIN_KANTEN
ctx = llm.Kontext(run_anlegen(topic), topic, "minimax")
await diagramme.bauen(ctx)
d = db.one("SELECT * FROM diagramme WHERE baustein_id=?", (b,))
assert d and d["status"] == "verifiziert" and d["quelle"] == "dag"
assert d["mermaid"].startswith("flowchart TD")
assert all(f"n{a}" in d["mermaid"] for a in atome) # jeder Knoten drin
assert diagramme.messen(ctx) == [] # keine offenen Kandidaten
assert diagramme.gate(ctx) is None
async def test_wenig_kanten_kein_diagramm():
async def test_fake_judge_nein_keine_diagramme():
topic = topic_anlegen("diag-leer")
b, _ = _baustein_mit_kette(topic, n=2) # nur 1 Kante < Schwelle
b, _ = _baustein_mit_kette(topic, n=2)
ctx = llm.Kontext(run_anlegen(topic), topic, "minimax")
await diagramme.bauen(ctx)
# kein GEBAUTES Diagramm (Fake-Judge sagt noetig=False → nur eine 'kein'-Merkzeile)
await diagramme.bauen(ctx) # Fake-Judge sagt noetig=False → nur 'kein'-Merkzeile
assert db.query("SELECT id FROM diagramme WHERE topic=? AND status='verifiziert'",
(topic,)) == []
assert db.one("SELECT status FROM diagramme WHERE baustein_id=?", (b,))["status"] == "kein"
@@ -97,12 +83,12 @@ async def test_marker_wird_zu_fence():
"""Assembly: platzierter <!-- diagramm: id --> → ```mermaid-Fence."""
import guide
topic = topic_anlegen("diag-place")
b, _ = _baustein_mit_kette(topic, n=4)
ctx = llm.Kontext(run_anlegen(topic), topic, "minimax")
await diagramme.bauen(ctx)
d = db.one("SELECT id FROM diagramme WHERE baustein_id=?", (b,))
b, _ = _baustein_mit_kette(topic, n=2)
mermaid = "flowchart TD\n n1[\"A\"]\n n2[\"B\"]\n n1 --> n2"
d = db.insert("diagramme", topic=topic, baustein_id=b, typ="flow", quelle="llm",
spec=db.j({}), mermaid=mermaid, status="verifiziert")
db.insert("sections", baustein_id=b, stage="done", text_kompakt="- k",
text_lang=f"Text.\n\n<!-- diagramm: {d['id']} -->\n\nMehr Text.")
text_lang=f"Text.\n\n<!-- diagramm: {d} -->\n\nMehr Text.")
lang = guide.kapitel_struktur(topic)[0]["sections"][0]["lang"]
assert "```mermaid" in lang and "flowchart TD" in lang
assert "<!-- diagramm:" not in lang # Marker ersetzt
@@ -128,3 +114,23 @@ async def test_guide_messen_meldet_toten_marker():
ctx = llm.Kontext(run_anlegen(topic), topic, "minimax")
ctx.ebene = "guide"
assert "diagramm_marker_tot" in {x["art"] for x in guide.messen(ctx)}
async def test_marker_platzieren_deterministisch():
"""Der Writer setzt keine Beispiel-Marker mehr — _marker_platzieren fügt sie
hinter den Atom-Absatz ein (atom-genau)."""
import guide
topic = topic_anlegen("platz")
b = db.insert("bausteine", topic=topic, ziel_id=1, titel="B", ord=0, status="neu")
a = db.insert("atome", topic=topic, titel="X", typ="begriff", definition="d",
status="neu", baustein_id=b, ord=0, braucht=db.j([]))
art = db.insert("artefakte", atom_id=a, typ="beispiel", status="verifiziert",
inhalt=db.j({"form": "tabelle", "tabelle": "| A | B |\n|---|---|\n| 1 | 2 |"}))
lang = f"#### X\n<!-- atom: {a} | X -->\nErklärung von X.\n\nWeiterer Absatz zum Thema."
out = guide._marker_platzieren(db.one("SELECT * FROM bausteine WHERE id=?", (b,)), lang)
assert f"<!-- beispiel: {art} -->" in out
# der Marker steht NACH dem Atom-Absatz
assert out.index("<!-- beispiel:") < out.index("Weiterer Absatz")
# idempotent: zweiter Lauf dupliziert nicht
assert guide._marker_platzieren(db.one("SELECT * FROM bausteine WHERE id=?", (b,)),
out).count("<!-- beispiel:") == 1