This commit is contained in:
team3
2026-06-17 22:56:24 +02:00
parent 0ff33271a0
commit dce9156ac8
17 changed files with 743 additions and 42 deletions

View File

@@ -24,7 +24,7 @@ from database import list_guides, update_guide
from fsutil import atomic_write_json
from jsonio import read_json_file as _json_datei
from onepager import _generate_onepager
from paths import bausteine_path, guide_content_path, project_dir
from paths import bausteine_path, guide_content_path, project_dir, subbausteine_path
from pipeline import (
CANCELLED, FAILED, GenContext, _claude_error, _extra,
_fail, _gather_error, _log, _prompt, _race, _rest_schema, _runde_schema,
@@ -47,6 +47,41 @@ WRITER_SECTIONS = 30
WRITER_MAX = 20
def _load_subbausteine(topic: str) -> dict[str, list[dict]]:
"""Sidecar laden: {Baustein-Titel: [{titel, stufe}, …]}. Fehlt sie → {} (Fallback)."""
data = _json_datei(subbausteine_path(topic))
if not isinstance(data, dict):
return {}
out: dict[str, list[dict]] = {}
for titel, subs in data.items():
if not isinstance(subs, list):
continue
gut = [s for s in subs if isinstance(s, dict) and str(s.get("titel", "")).strip()
and s.get("stufe") in ("einfach", "mittel", "schwer")]
if gut:
out[titel] = gut
return out
def _section_markup(sec: dict) -> str:
"""Section-Text mit Sub-Markern (für Lese-Check/Fix), damit die Struktur erhalten bleibt."""
if not sec.get("subs"):
return sec["md"]
return "\n\n".join(f"<!-- sub: {s['stufe']} | {s['titel']} -->\n{s['md']}" for s in sec["subs"])
def _zuteilung_subs(chunk: list[dict], entries: dict[int, str], subs_by_titel: dict[str, list[dict]]) -> str:
"""Wie _zuteilung_text, aber listet pro Baustein seine Subbausteine mit Stufe."""
lines: list[str] = []
for ch in chunk:
lines.append(f"KAPITEL: {ch['title']}")
for num in ch["nums"]:
lines.append(f"- {entries[num]}")
for s in subs_by_titel.get(_titel(entries[num]), []):
lines.append(f" [{s['stufe']}] {s['titel']}")
return "\n".join(lines)
def _guide_files(content_path: Path) -> dict:
d, stem = content_path.parent, content_path.stem
runden = range(1, KONSENS_MAX_RUNDEN + 1)
@@ -459,7 +494,10 @@ async def _generate_sections(
# dieselbe Aufteilung: 1 Agent je ~30 Bausteine (gedeckelt).
total_sections = sum(len(c["nums"]) for c in plan)
chunks = _split_chunks(plan, min(WRITER_MAX, max(1, math.ceil(total_sections / WRITER_SECTIONS))))
zuteilungen = [_zuteilung_text(chunk, entries) for chunk in chunks]
# Subbausteine je Baustein (Sidecar). Fehlt sie → leer → Inhalte/Writer laufen
# auf Baustein-Granularität weiter (Fallback für Alt-Themen ohne Sidecar).
subs_by_titel = _load_subbausteine(topic)
zuteilungen = [_zuteilung_subs(chunk, entries, subs_by_titel) for chunk in chunks]
chunk_sizes = [sum(len(c["nums"]) for c in chunk) for chunk in chunks]
writer_count = len(chunks)
idx = _titel_index(entries)
@@ -616,11 +654,11 @@ async def _generate_sections(
chunk_nums = [[num for ch in chunk for num in ch["nums"] if num in by_num] for chunk in chunks]
def sections_text(nums: list[int]) -> str:
return "\n\n".join(f"SECTION: {_titel(entries[num])}\n{by_num[num]['md']}" for num in nums)
return "\n\n".join(f"SECTION: {_titel(entries[num])}\n{_section_markup(by_num[num])}" for num in nums)
def auftraege_text(nums: list[int], probleme: dict[int, str]) -> str:
return "\n\n".join(
f"SECTION: {_titel(entries[num])}\nPROBLEM: {probleme[num]}\nAKTUELLER INHALT:\n{by_num[num]['md']}"
f"SECTION: {_titel(entries[num])}\nPROBLEM: {probleme[num]}\nAKTUELLER INHALT:\n{_section_markup(by_num[num])}"
for num in nums
)
@@ -702,12 +740,16 @@ async def _generate_sections(
scope = [[num for num in nums if num in ersetzt] for nums in chunk_nums]
await _set_progress(guide_id, "Setze zusammen…")
def _section(num: int) -> dict:
sec = by_num[num]
d = {"num": num, "title": _titel(entries[num]), "md": sec["md"]}
if sec.get("subs"):
d["subbausteine"] = [{"stufe": s["stufe"], "titel": s["titel"], "md": s["md"]} for s in sec["subs"]]
return d
chapters: list[dict] = []
for ch in plan:
sections = [
{"num": num, "title": _titel(entries[num]), "md": by_num[num]["md"]}
for num in ch["nums"] if num in by_num
]
sections = [_section(num) for num in ch["nums"] if num in by_num]
if sections:
chapters.append({"title": ch["title"], "sections": sections})
geplant = {num for ch in plan for num in ch["nums"]}