Spezialisierung je Thema: begrenzt den Umfang auf einen Ausschnitt

Drittes Feld neben Thema und Hinweisen. Hinweise fügen hinzu, die
Spezialisierung nimmt weg: Recherche, Gliederung, Kapitel und Prüfung
bekommen sie als verbindliche Grenze; nur Stoff, der dafür gebraucht
wird, Grundlagen nur soweit nötig.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
team3
2026-10-12 15:20:10 +02:00
parent efd3bc8598
commit 7538812cfd
13 changed files with 49 additions and 32 deletions

View File

@@ -72,9 +72,9 @@ def _offen(name: str) -> None:
s["status"] = "offen"
def _thema(name: str) -> tuple[str, str]:
def _thema(name: str) -> tuple[str, str, str]:
t = state.thema(name) or {}
return t.get("titel") or name, t.get("hinweise", "")
return t.get("titel") or name, t.get("hinweise", ""), t.get("spezialisierung", "")
def _kapitel(name: str) -> list[dict]:
@@ -108,12 +108,13 @@ async def _parallel(name: str, sid: str, aufgaben: list) -> None:
# ---- Stufen -------------------------------------------------------------------
async def st_recherche(name: str) -> None:
thema, hinweise = _thema(name)
thema, hinweise, spez = _thema(name)
s = state.stufe(name, "recherche")
s.update(gesamt=1, fertig=0)
v = state.verzeichnis(name)
if not state.bericht_lesen(name, "recherche"):
p = prompts.laden("recherche", thema=thema, hinweise_block=prompts.hinweise_block(hinweise),
spezialisierung_block=prompts.spezialisierung_block(spez),
stil_basis=(config.PROMPTS / "stil_basis.md").read_text())
r = await agenten.laufen(name, "recherche", "recherche", "Thema deuten und Quellen beschaffen", p)
if r["status"] != "fertig":
@@ -132,7 +133,7 @@ async def st_recherche(name: str) -> None:
async def st_gliederung(name: str) -> None:
thema, hinweise = _thema(name)
thema, hinweise, spez = _thema(name)
s = state.stufe(name, "gliederung")
s.update(gesamt=1, fertig=0)
p = state.verzeichnis(name) / "buch" / "GLIEDERUNG.md"
@@ -140,7 +141,8 @@ async def st_gliederung(name: str) -> None:
for versuch in (1, 2):
if p.exists() and not gliederung.parsen(p.read_text())["fehler"] and state.bericht_lesen(name, "gliederung"):
break
pr = prompts.laden("gliederung", thema=thema, hinweise_block=prompts.hinweise_block(hinweise)) + hinweis
pr = prompts.laden("gliederung", thema=thema, hinweise_block=prompts.hinweise_block(hinweise),
spezialisierung_block=prompts.spezialisierung_block(spez)) + hinweis
r = await agenten.laufen(name, "gliederung", "gliederung", "Gliederung entwerfen", pr)
if r["status"] != "fertig":
raise Abbruch("Gliederung gescheitert: " + r["bericht"][:200])
@@ -156,14 +158,15 @@ async def st_gliederung(name: str) -> None:
async def st_schreiben(name: str) -> None:
thema, _ = _thema(name)
thema, _, spez = _thema(name)
kap = _kapitel(name)
s = state.stufe(name, "schreiben")
offen = [k for k in kap if not state.bericht_lesen(name, f"kapitel-{k['n']:02d}")]
s.update(gesamt=len(kap), fertig=len(kap) - len(offen))
aufgaben = []
for k in offen:
p = prompts.laden("kapitel", thema=thema, n=str(k["n"]), kapitel_titel=k["titel"], datei=k["datei"])
p = prompts.laden("kapitel", thema=thema, n=str(k["n"]), kapitel_titel=k["titel"], datei=k["datei"],
spezialisierung_block=prompts.spezialisierung_block(spez))
if (state.verzeichnis(name) / "buch" / k["datei"]).exists():
p += "\n\nHinweis: `buch/" + k["datei"] + "` existiert bereits aus einem abgebrochenen Lauf – prüfe sie und vervollständige oder ersetze sie."
aufgaben.append((f"kapitel-{k['n']:02d}", f"Kapitel {k['n']} schreiben", p))
@@ -171,7 +174,7 @@ async def st_schreiben(name: str) -> None:
async def st_pruefung(name: str) -> None:
thema, _ = _thema(name)
thema, _, spez = _thema(name)
kap = _kapitel(name)
s = state.stufe(name, "pruefung")
offen = [k for k in kap if not state.bericht_lesen(name, f"pruefung-{k['n']:02d}")]
@@ -179,14 +182,15 @@ async def st_pruefung(name: str) -> None:
aufgaben = []
for k in offen:
autor = state.bericht_lesen(name, f"kapitel-{k['n']:02d}") or "(kein Autorenbericht vorhanden)"
p = prompts.laden("pruefung", thema=thema, n=str(k["n"]), kapitel_titel=k["titel"], datei=k["datei"], autor_bericht=autor)
p = prompts.laden("pruefung", thema=thema, n=str(k["n"]), kapitel_titel=k["titel"], datei=k["datei"], autor_bericht=autor,
spezialisierung_block=prompts.spezialisierung_block(spez))
aufgaben.append((f"pruefung-{k['n']:02d}", f"Kapitel {k['n']} prüfen", p))
await _parallel(name, "pruefung", aufgaben)
async def st_lektorat(name: str) -> None:
"""Geprüfte Kapitel sprachlich glätten; Marker: berichte/lektorat-NN.md."""
thema, _ = _thema(name)
thema, _, _ = _thema(name)
kap = [k for k in _kapitel(name) if (state.verzeichnis(name) / "buch" / k["datei"]).exists()]
s = state.stufe(name, "lektorat")
offen = [k for k in kap if state.bericht_lesen(name, f"pruefung-{k['n']:02d}") and not state.bericht_lesen(name, f"lektorat-{k['n']:02d}")]
@@ -209,7 +213,7 @@ async def st_lektorat(name: str) -> None:
async def st_konsistenz(name: str) -> None:
thema, _ = _thema(name)
thema, _, _ = _thema(name)
kap = _kapitel(name)
gruppen = [kap[i:i + config.KONSISTENZ_GRUPPE] for i in range(0, len(kap), config.KONSISTENZ_GRUPPE)]
s = state.stufe(name, "konsistenz")