This commit is contained in:
Team3
2026-07-04 19:20:48 +02:00
parent 92c69c1561
commit c05421a8c1
14 changed files with 695 additions and 277 deletions

View File

@@ -618,73 +618,75 @@ async def run_guide_board(guide_id: str, topic: str, format_name: str, entries:
import uuid
from datetime import datetime, timezone
db.set_current_run(topic, f"{datetime.now(timezone.utc).strftime('%Y%m%d-%H%M')}-g{uuid.uuid4().hex[:4]}")
spec = (TEMPLATES_DIR / "Format" / "Section.md").read_text(encoding="utf-8")
subs_raw = await _load_subblocks(topic)
project = source_folder(topic)
fallback = (_prompt("Guide-Facts-Projekt", project=project) if project
else _prompt("Guide-Facts-Thema"))
env = _Env(ctx, guide_id, topic, format_name, instructions, content_path,
subs_raw, await _chapter_map(topic, entries), fallback, spec)
for num, line in entries.items():
title = _title(line)
await db.upsert_guide_card(topic, format_name, _norm_title(title), title)
cards = await db.list_guide_cards(topic, format_name)
open_cards = [c for c in cards if c["stage"] != "done"]
if open_cards:
sem = asyncio.Semaphore(CARD_CONCURRENCY)
try:
spec = (TEMPLATES_DIR / "Format" / "Section.md").read_text(encoding="utf-8")
subs_raw = await _load_subblocks(topic)
project = source_folder(topic)
fallback = (_prompt("Guide-Facts-Projekt", project=project) if project
else _prompt("Guide-Facts-Thema"))
env = _Env(ctx, guide_id, topic, format_name, instructions, content_path,
subs_raw, await _chapter_map(topic, entries), fallback, spec)
for num, line in entries.items():
title = _title(line)
await db.upsert_guide_card(topic, format_name, _norm_title(title), title)
cards = await db.list_guide_cards(topic, format_name)
open_cards = [c for c in cards if c["stage"] != "done"]
if open_cards:
sem = asyncio.Semaphore(CARD_CONCURRENCY)
async def _progress():
while True:
counts = await db.guide_stage_counts(topic, format_name)
done = counts.get("done", 0)
total = sum(counts.values())
await db.update_guide(guide_id, progress=f"Board: {done}/{total} Karten fertig")
await asyncio.sleep(2.0)
async def _progress():
while True:
counts = await db.guide_stage_counts(topic, format_name)
done = counts.get("done", 0)
total = sum(counts.values())
await db.update_guide(guide_id, progress=f"Board: {done}/{total} Karten fertig")
await asyncio.sleep(2.0)
reporter = asyncio.create_task(_progress())
try:
await asyncio.gather(*[_run_card(env, c, sem) for c in open_cards])
finally:
reporter.cancel()
db.set_current_run(topic, None)
else:
reporter = asyncio.create_task(_progress())
try:
await asyncio.gather(*[_run_card(env, c, sem) for c in open_cards])
finally:
reporter.cancel()
if is_guide_cancelled(guide_id):
return None
# assembly — identical shape to the legacy pipeline
cards = await db.list_guide_cards(topic, format_name)
chapters: list[dict] = []
by_chapter: dict[str, list[dict]] = {}
order: list[str] = []
for c in sorted(cards, key=lambda c: (c["ord"], c["block_norm"])):
if c["stage"] != "done":
_log(topic, f"Guide: Karte '{c['block']}' nicht fertig ({c['stage']}) — Abschnitt fehlt")
continue
sec = _first_section(c["md"])
if sec is None:
continue
ch = c["chapter"] or "Inhalte"
if ch not in by_chapter:
by_chapter[ch] = []
order.append(ch)
by_chapter[ch].append({
"num": c["ord"], "title": c["block"], "md": sec["md"],
"compact": sec.get("compact", ""), "anchor": sec.get("anchor", ""),
"anker_compact": sec.get("anker_compact", ""), "subs": sec.get("subs", []),
"checkable": format_name == "Guide" or bool(
any(s.get("relevance") == "relevant" for s in subs_raw.get(c["block"], []))),
})
for ch in order:
chapters.append({"title": ch, "sections": by_chapter[ch]})
if chapters:
try: # Abschluss-Guide-QA (best-effort): speist das Badge mit einer frischen Note
import guide_qa
rep = await guide_qa.guide_qa_report(topic, llm=True)
if rep:
await asyncio.to_thread(guide_qa._write_report, rep)
except Exception:
log.exception("[%s] Abschluss-Guide-QA fehlgeschlagen", topic)
return chapters or None
finally:
# erst NACH der Abschluss-Guide-QA leeren: deren Judge-Events gehören zum
# Lauf — vorher fielen sie ohne run_id aus jeder Run-Aggregation
db.set_current_run(topic, None)
if is_guide_cancelled(guide_id):
return None
# assembly — identical shape to the legacy pipeline
cards = await db.list_guide_cards(topic, format_name)
chapters: list[dict] = []
by_chapter: dict[str, list[dict]] = {}
order: list[str] = []
for c in sorted(cards, key=lambda c: (c["ord"], c["block_norm"])):
if c["stage"] != "done":
_log(topic, f"Guide: Karte '{c['block']}' nicht fertig ({c['stage']}) — Abschnitt fehlt")
continue
sec = _first_section(c["md"])
if sec is None:
continue
ch = c["chapter"] or "Inhalte"
if ch not in by_chapter:
by_chapter[ch] = []
order.append(ch)
by_chapter[ch].append({
"num": c["ord"], "title": c["block"], "md": sec["md"],
"compact": sec.get("compact", ""), "anchor": sec.get("anchor", ""),
"anker_compact": sec.get("anker_compact", ""), "subs": sec.get("subs", []),
"checkable": format_name == "Guide" or bool(
any(s.get("relevance") == "relevant" for s in subs_raw.get(c["block"], []))),
})
for ch in order:
chapters.append({"title": ch, "sections": by_chapter[ch]})
if chapters:
try: # Abschluss-Guide-QA (best-effort): speist das Badge mit einer frischen Note
import guide_qa
rep = await guide_qa.guide_qa_report(topic, llm=True)
if rep:
await asyncio.to_thread(guide_qa._write_report, rep)
except Exception:
log.exception("[%s] Abschluss-Guide-QA fehlgeschlagen", topic)
return chapters or None
async def done_step(topic: str, format_name: str) -> int: