"""Stufe 5: Guide-Zusammenbau (Kapitel + Intros + Sections) + deterministische Abschluss-Checks: jeder Atom-Marker global genau einmal, Anker-Links auflösbar.""" import re from . import config, db, engine from .guide import _MARKER_RE, _slug def guide_pfad(topic: str) -> str: return str(config.KORPUS_DIR.parent / "guides" / f"{topic}.md") def bauen(topic: str) -> str: teile = [] t = db.one("SELECT COALESCE(NULLIF(titel,''), name) t FROM topics WHERE name=?", topic) teile.append(f"# {t['t']}\n") for kap in db.query("SELECT * FROM kapitel WHERE topic=? ORDER BY ord", topic): teile.append(f"\n## {kap['titel']}\n") if kap["intro"]: teile.append(kap["intro"] + "\n") for b in db.query("SELECT * FROM bausteine WHERE kapitel_id=? ORDER BY ord", kap["id"]): sec = db.one("SELECT text FROM sections WHERE baustein_id=?", b["id"]) if sec and sec["text"]: teile.append(f"\n### {b['titel']}\n") teile.append(sec["text"] + "\n") return "\n".join(teile) @engine.worker("montage.montieren") async def montieren(task: dict) -> engine.Ergebnis: topic = task["topic"] text = bauen(topic) # Check 1: jeder aktive Atom-Marker genau einmal marker = [int(m) for m in _MARKER_RE.findall(text)] aktive = {a["id"] for a in db.query( "SELECT id FROM atome WHERE topic=? AND status='aktiv' AND " "baustein_id IS NOT NULL", topic)} fehler = [] for a in aktive: if marker.count(a) != 1: fehler.append(f"Atom-Marker {a}: {marker.count(a)}x") # Check 2: Anker-Links auflösbar (H2/H3-Slugs) slugs = {_slug(u) for u in re.findall(r"^#{2,3}\s+(.+)$", text, re.MULTILINE)} for link in re.findall(r"\]\(#([^)]+)\)", text): if link not in slugs: fehler.append(f"toter Anker-Link: #{link}") if fehler: for f in fehler: db.insert("befunde", run_id=task["run_id"], stufe="montage", knoten="montage", art="montage", item=topic, detail=f[:300]) raise RuntimeError(f"Montage-Checks: {len(fehler)} Fehler") from .laden import _atomar_schreiben _atomar_schreiben(guide_pfad(topic), text.encode("utf-8")) db.update("topics", "name=?", (topic,), status="fertig") return engine.Ergebnis(daten={"zeichen": len(text), "kapitel": len(db.query( "SELECT id FROM kapitel WHERE topic=?", topic))})