From 7538812cfdf19d983775727b978faae0ca7bc0b8 Mon Sep 17 00:00:00 2001 From: team3 Date: Mon, 12 Oct 2026 15:20:10 +0200 Subject: [PATCH] Spezialisierung je Thema: begrenzt den Umfang auf einen Ausschnitt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- API.md | 9 +++++---- README.md | 2 +- backend/main.py | 7 ++++--- backend/pipeline.py | 26 +++++++++++++++----------- backend/prompts.py | 8 ++++++++ backend/state.py | 4 ++-- frontend/src/App.vue | 5 ++++- frontend/src/api.js | 2 +- frontend/src/components/Lauf.vue | 2 +- prompts/gliederung.md | 4 ++-- prompts/kapitel.md | 4 ++-- prompts/pruefung.md | 4 ++-- prompts/recherche.md | 4 ++-- 13 files changed, 49 insertions(+), 32 deletions(-) diff --git a/API.md b/API.md index b4c806a..befeb3e 100644 --- a/API.md +++ b/API.md @@ -12,9 +12,10 @@ Ohne `v2` gilt die neueste Version. ## Themen und Versionen -- `GET /api/themen` → `[{slug, name, titel, hinweise, angelegt, status, laeuft, stufe, versionen: [{v, status, laeuft, stufe, angelegt, kosten_usd}]}]` +- `GET /api/themen` → `[{slug, name, titel, hinweise, spezialisierung, angelegt, status, laeuft, stufe, versionen: [{v, status, laeuft, stufe, angelegt, kosten_usd}]}]` – `status/laeuft/stufe` gelten für die neueste Version; `status`: `neu | laeuft | pausiert | fertig | fehler` -- `POST /api/themen` `{name, hinweise}` → Thema wie oben (legt `v1` an) +- `POST /api/themen` `{name, hinweise, spezialisierung}` → Thema wie oben (legt `v1` an) + – `hinweise`: wie das Thema zu verstehen ist (fügt hinzu); `spezialisierung`: Grenze des Umfangs, nur was dafür gebraucht wird (nimmt weg) - `GET /api/themen/{slug}` → Thema wie oben - `DELETE /api/themen/{slug}` – ganzes Thema - `POST /api/themen/{slug}/versionen` → `{"v": N}` – nächste Version, gleiche Eingaben, ohne Start @@ -37,7 +38,7 @@ Alte Zustände ohne diese Stufe bekommen sie beim Laden nachgetragen. ```json { - "slug": "godot-4", "name": "Godot 4", "version": 1, "titel": "Godot 4", "hinweise": "…", + "slug": "godot-4", "name": "Godot 4", "version": 1, "titel": "Godot 4", "hinweise": "…", "spezialisierung": "", "status": "laeuft", "grund": "", "stufe": "schreiben", "angelegt": "2026-09-28T10:00:00Z", "deutung": {"titel": "Godot 4", "untertitel": "…", "deutung": "…", "buchtyp": "werkzeug|wissen", "zielgruppe": "…"}, "stufen": [ @@ -91,7 +92,7 @@ Solange ein Lauf läuft, enthält `buch` die bereits geschriebenen Kapitel (Stat ``` storage// - thema.json {name, slug, titel, hinweise, angelegt} + thema.json {name, slug, titel, hinweise, spezialisierung, angelegt} v1/, v2/, … je Version: state.json Zustand wie oben (ohne Buch) deutung.json vom Recherche-Agenten diff --git a/README.md b/README.md index fc42dea..3b9a5c3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # buchwerk -Aus einem Thema (plus optionalen Hinweisen) entsteht ein deutschsprachiges Sachbuch. Ein Python-Backend +Aus einem Thema (plus optionalen Hinweisen und einer optionalen Spezialisierung, die den Umfang begrenzt) entsteht ein deutschsprachiges Sachbuch. Ein Python-Backend steuert Agenten des Claude Agent SDK (Opus 5.5): Recherche und Deutung, Gliederung, Kapitel parallel schreiben, jedes Kapitel durch einen unabhängigen Agenten prüfen, Querverweise abgleichen, Vorwort, Montage (Markdown, README, PDF). Das Buch wird im Browser als Leseansicht gezeigt. diff --git a/backend/main.py b/backend/main.py index 0060e20..9102da8 100644 --- a/backend/main.py +++ b/backend/main.py @@ -29,6 +29,7 @@ app.add_middleware(GZipMiddleware, minimum_size=1000) # Buchdaten sind 1–2 MB class ThemaNeu(BaseModel): name: str hinweise: str = "" + spezialisierung: str = "" class Position(BaseModel): @@ -67,7 +68,7 @@ def _thema_info(t: dict) -> dict | None: if not vs: return None neueste = vs[-1] - return {"slug": t["slug"], "name": t["name"], "titel": t["titel"], "hinweise": t.get("hinweise", ""), + return {"slug": t["slug"], "name": t["name"], "titel": t["titel"], "hinweise": t.get("hinweise", ""), "spezialisierung": t.get("spezialisierung", ""), "angelegt": t.get("angelegt", ""), "status": neueste["status"], "laeuft": neueste["laeuft"], "stufe": neueste["stufe"], "versionen": vs} @@ -83,7 +84,7 @@ async def thema_anlegen(body: ThemaNeu): if not state.name_ok(name): raise HTTPException(400, "Ungültiger Name") try: - return _thema_info(state.anlegen(name, body.hinweise)) + return _thema_info(state.anlegen(name, body.hinweise, body.spezialisierung)) except ValueError as e: raise HTTPException(409, str(e)) @@ -114,7 +115,7 @@ async def zustand(slug: str, n: int): key = _key(slug, n) t = _thema(slug) st = state.zustand(key) - return {"slug": slug, "name": t["name"], "version": n, "titel": t["titel"], "hinweise": t.get("hinweise", ""), **st, + return {"slug": slug, "name": t["name"], "version": n, "titel": t["titel"], "hinweise": t.get("hinweise", ""), "spezialisierung": t.get("spezialisierung", ""), **st, "deutung": st.get("deutung") or state.deutung(key), "ereignisse": st["ereignisse"][-100:]} diff --git a/backend/pipeline.py b/backend/pipeline.py index babe0ec..c1c62fb 100644 --- a/backend/pipeline.py +++ b/backend/pipeline.py @@ -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") diff --git a/backend/prompts.py b/backend/prompts.py index 4e8a058..563fae3 100644 --- a/backend/prompts.py +++ b/backend/prompts.py @@ -11,3 +11,11 @@ def laden(name: str, **werte: str) -> str: def hinweise_block(hinweise: str) -> str: return f"Hinweise des Auftraggebers (verbindlich): {hinweise}\n" if hinweise else "" + + +def spezialisierung_block(spezialisierung: str) -> str: + """Hinweise fügen hinzu, die Spezialisierung nimmt weg: sie begrenzt den Umfang des Buchs auf einen Ausschnitt des Themas.""" + if not spezialisierung: + return "" + return (f"Spezialisierung (verbindliche Grenze des Umfangs): {spezialisierung}. Das Buch behandelt vom Thema nur, was dafür " + "gebraucht wird; alles andere entfällt, auch wenn es zum Thema gehört. Grundlagen nur, soweit sie dafür nötig sind.\n") diff --git a/backend/state.py b/backend/state.py index 49d3968..0eddcf3 100644 --- a/backend/state.py +++ b/backend/state.py @@ -119,12 +119,12 @@ def themen() -> list[dict]: return aus -def anlegen(name: str, hinweise: str) -> dict: +def anlegen(name: str, hinweise: str, spezialisierung: str = "") -> dict: d = config.STORAGE / name if d.exists(): raise ValueError("Thema existiert schon") d.mkdir(parents=True) - t = {"name": name, "slug": slug_frei(name), "titel": name, "hinweise": hinweise.strip(), "angelegt": jetzt()} + t = {"name": name, "slug": slug_frei(name), "titel": name, "hinweise": hinweise.strip(), "spezialisierung": spezialisierung.strip(), "angelegt": jetzt()} _schreiben(d / "thema.json", t) version_anlegen(name) return t diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 8fe54db..cdf343a 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -35,6 +35,7 @@ const state = ref(null) const fehler = ref('') const neuName = ref('') const neuHinweise = ref('') +const neuSpezialisierung = ref('') const navAuf = ref(false) let timer = null @@ -104,9 +105,10 @@ async function anlegen() { const name = neuName.value.trim() if (!name) return try { - const t = await api.anlegen(name, neuHinweise.value.trim()) + const t = await api.anlegen(name, neuHinweise.value.trim(), neuSpezialisierung.value.trim()) neuName.value = '' neuHinweise.value = '' + neuSpezialisierung.value = '' await topicsLaden() themaWaehlen(t.slug) } catch (e) { fehler.value = String(e.message || e) } @@ -170,6 +172,7 @@ function tokens(n) { return n >= 1e6 ? (n / 1e6).toFixed(1) + 'M' : n >= 1e3 ? M
+
diff --git a/frontend/src/api.js b/frontend/src/api.js index e61727f..5cadd76 100644 --- a/frontend/src/api.js +++ b/frontend/src/api.js @@ -18,7 +18,7 @@ const e = encodeURIComponent const v = (slug, n) => `/themen/${e(slug)}/v${n}` export const api = { themen: () => req('/themen'), - anlegen: (name, hinweise = '') => req('/themen', { method: 'POST', body: { name, hinweise } }), + anlegen: (name, hinweise = '', spezialisierung = '') => req('/themen', { method: 'POST', body: { name, hinweise, spezialisierung } }), loeschen: (slug) => req(`/themen/${e(slug)}`, { method: 'DELETE' }), versionAnlegen: (slug) => req(`/themen/${e(slug)}/versionen`, { method: 'POST' }), versionLoeschen: (slug, n) => req(v(slug, n), { method: 'DELETE' }), diff --git a/frontend/src/components/Lauf.vue b/frontend/src/components/Lauf.vue index 0aced15..1042f86 100644 --- a/frontend/src/components/Lauf.vue +++ b/frontend/src/components/Lauf.vue @@ -45,7 +45,7 @@ function neueVersion() { if (confirm('Neue Version erzeugen? Gleiche Eingaben, k - + {{ statusText[state.status] || state.status }} {{ usd(state.kosten_usd) }} diff --git a/prompts/gliederung.md b/prompts/gliederung.md index 4a3095e..c4ddd2c 100644 --- a/prompts/gliederung.md +++ b/prompts/gliederung.md @@ -1,9 +1,9 @@ Du entwirfst die Gliederung eines deutschsprachigen Sachbuchs zum Thema „{{thema}}“. -{{hinweise_block}} +{{hinweise_block}}{{spezialisierung_block}} Lies zuerst vollständig: `buch/STIL.md`, `quellen/QUELLEN.md` und `deutung.json`. Verschaffe dir dann anhand der Quellen unter `quellen/` (Inhaltsverzeichnisse der Doku, Klassenlisten, Titel der Studien) einen Überblick, was das Thema umfasst – die Gliederung muss aus dem Stoff kommen, nicht aus dem Gedächtnis. Anforderungen – der Stoff bestimmt den Umfang, nicht eine Zielzahl: -- Ein Kapitel ist ein eigenständiges Thema mit eigener Leitfrage. Verwandte Themen zusammenlegen, wenn sie gemeinsam unter 4 Abschnitte passen. Keine Kapitel der Vollständigkeit halber – aber Grundlagen des Fachgebiets bleiben drin, notfalls als `(kurz)`-Abschnitt; weggelassen wird nur, was außerhalb der Deutung liegt. Ab 8 Kapiteln in Teile gruppieren. +- Ein Kapitel ist ein eigenständiges Thema mit eigener Leitfrage. Verwandte Themen zusammenlegen, wenn sie gemeinsam unter 4 Abschnitte passen. Keine Kapitel der Vollständigkeit halber – aber Grundlagen des Fachgebiets bleiben drin, notfalls als `(kurz)`-Abschnitt; weggelassen wird nur, was außerhalb der Deutung liegt. Bei einer Spezialisierung bekommt nur Stoff ein Kapitel oder einen Abschnitt, der dafür gebraucht wird; Grundlagen nur, soweit sie dafür nötig sind. Ab 8 Kapiteln in Teile gruppieren. - Je Kapitel so viele Abschnitte, wie es getrennte Fragen gibt: typisch 4, mindestens 2, höchstens 7. Reihenfolge nach dem, was man zuerst wissen muss. - Jeder Abschnitt bekommt ein Gewicht, das seine Länge festlegt: `(kurz)` ≈ 800 Wörter für Abgrenzung, Überblick, Einordnung; ohne Angabe = mittel ≈ 1.300 Wörter, der Normalfall; `(lang)` ≈ 2.000 Wörter für Kernverfahren mit Herleitung und Beispiel. - Ein Kapitel soll in einer Lesesitzung zu schaffen sein: Summe der Richtwerte höchstens 8.000 Wörter. Braucht ein Thema mehr, wird es geteilt, nicht gestapelt. diff --git a/prompts/kapitel.md b/prompts/kapitel.md index 3c3bde6..0baafac 100644 --- a/prompts/kapitel.md +++ b/prompts/kapitel.md @@ -1,5 +1,5 @@ Du schreibst ein Kapitel für ein deutschsprachiges Sachbuch zum Thema „{{thema}}“. - +{{spezialisierung_block}} Lies zuerst vollständig: `buch/STIL.md`, `buch/GLIEDERUNG.md`, `quellen/QUELLEN.md`. Aufgabe: **Kapitel {{n}} – {{kapitel_titel}}**, Datei `buch/{{datei}}`, mit genau den Abschnitten aus der Gliederung. Das Gewicht hinter dem Abschnittstitel – `(kurz)` ≈ 800 Wörter, ohne Angabe ≈ 1.300, `(lang)` ≈ 2.000 – ist der Richtwert für die Länge; es gehört nicht in die Überschrift. @@ -8,7 +8,7 @@ Arbeite in diesem Loop: 1. RECHERCHE in den lokalen Quellen (siehe QUELLEN.md): Verstehe die Sache anhand von Quellcode, Referenz, Doku bzw. Abstracts, bevor du schreibst. Online nur, wenn lokal nicht klärbar und QUELLEN.md es erlaubt. 2. SCHREIBEN mit Write (bei Länge in mehreren Schritten, dann anhängen). Am Ende des Kapitels der Abschnitt `## N.M Merken` nach STIL.md: Bullet-Liste „Begriff: Kern“, fünf bis zehn Zeilen. 3. VERIFIZIEREN: Lies das fertige Kapitel vollständig. Prüfe JEDE Tatsachenangabe (Bezeichner, Signaturen, Versionsangaben, Namen, Jahre, Zahlen, Studienergebnisse) gegen die Quellen; führe Codebeispiele aus, wo STIL.md das verlangt – im Gerüst unter `arbeit/`, ins Buch kommt nur der Kern. Korrigiere oder entschärfe alles Unbelegte. -4. PRÜFEN gegen STIL.md: Überschriften exakt wie in der Gliederung, keine Übungen/Merkkästen/Zusammenfassungen/Literaturlisten, Prosa statt Listenwüste, keine Verweisklammern, keine Wiederholung von Themen anderer Kapitel, Umfang, Umlaute. Überarbeite, bis alles passt. +4. PRÜFEN gegen STIL.md: Überschriften exakt wie in der Gliederung, keine Übungen/Merkkästen/Zusammenfassungen/Literaturlisten, Prosa statt Listenwüste, keine Verweisklammern, keine Wiederholung von Themen anderer Kapitel, falls oben eine Spezialisierung steht: nichts außerhalb davon, auch nicht als Beispiel oder Exkurs; Umfang, Umlaute. Überarbeite, bis alles passt. Arbeitsdateien (Testskripte, Notizen) nur unter `arbeit/kapitel-{{n}}/` anlegen, nicht in `buch/` oder `quellen/`. Keine persönlichen Daten an externe Dienste senden. diff --git a/prompts/pruefung.md b/prompts/pruefung.md index 1b3f9a8..7b86ba2 100644 --- a/prompts/pruefung.md +++ b/prompts/pruefung.md @@ -1,5 +1,5 @@ Du bist unabhängiger Fachlektor und Faktenprüfer für ein deutschsprachiges Sachbuch zum Thema „{{thema}}“. Du hast das Kapitel nicht geschrieben und traust ihm nicht. - +{{spezialisierung_block}} Lies zuerst: `buch/STIL.md`, `buch/GLIEDERUNG.md`, `quellen/QUELLEN.md`. Prüfe vollständig: `buch/{{datei}}` (Kapitel {{n}} – {{kapitel_titel}}). @@ -11,7 +11,7 @@ Loop, bis nichts mehr zu korrigieren ist: 1. Lies das Kapitel komplett. Extrahiere alle überprüfbaren Behauptungen: Bezeichner und Signaturen, Versionsangaben, Studien (Autoren, Jahr, Design, Stichprobe, Ergebnis, Effektgröße), Zahlen, Zitate, Verhaltensbeschreibungen („was passiert wann“), Zuschreibungen („X hat Y eingeführt“), Textdiagramme (jedes Element und jeder Pfeil gegen Quellcode/Doku) und Ausgabeblöcke (gegen den eigenen Testlauf). 2. Verifiziere möglichst ALLE gegen die lokalen Quellen (QUELLEN.md). Priorisiere nach Fehlerwahrscheinlichkeit. Führe Codebeispiele aus bzw. teste beschriebenes Verhalten mit kleinen Skripten, wo STIL.md das vorsieht. Versionsangaben gegen Tags/Changelogs prüfen. Achte besonders auf: falsche Zuschreibungen, verdrehte Effektrichtungen, überzogene Kausalaussagen aus Korrelationsstudien, erfundene Stichprobengrößen, veraltete oder erfundene Bezeichner, Doku-Aussagen, die dem Quellcode widersprechen (dann gilt der Quellcode). 3. Korrigiere Fehler direkt in der Datei mit Edit (minimal-invasiv, Stil beibehalten). Unbelegbares vorsichtiger formulieren oder streichen. -4. Prüfe Form: Überschriften exakt wie GLIEDERUNG.md, dazu als letzter Abschnitt `## N.M Merken` (fortlaufend nummeriert), als Bullet-Liste „Begriff: Kern“ mit fünf bis zehn Zeilen aus ganzen, allein verständlichen Sätzen, ohne Beispiele, Herleitungen oder Absätze, der nichts enthält, was das Kapitel nicht erklärt (Stichwortreihen zu Sätzen machen, über 120 Wörter kürzen); keine Übungen/Merkkästen/Zusammenfassungen/Literaturlisten; keine Verweisklammern „(→ …)“ und keine Rückverweise auf frühere Abschnitte; Vorausverweise nur als Halbsatz und nur, wenn das Thema dort laut Gliederung steht; keine größeren Doppelungen mit Themen, die in andere Kapitel gehören (dann kürzen und verweisen); Rechtschreibung, Umlaute, Markdown. Satzbau: Sätze über 30 Wörter in mehrere auflösen, Inhalt unverändert; Zielschnitt unter 20 Wörter je Satz. Sätze mit drei und mehr Code-Bezeichnern entflechten: in Worten erklären, Namenslisten streichen. Verständlichkeit: Begriffe, die der Abschnitt benutzt, ohne sie bis dahin eingeführt zu haben, kurz erklären oder auf die Einführung verweisen; Interna, die kein sichtbares Verhalten erklären, streichen; Zwischenabschnitte unter 150 Wörtern mit dem Nachbarn zusammenlegen; Gedankensprünge schließen, wo zwischen zwei Sätzen oder Absätzen die Verbindung fehlt. Umfang: Abschnitte über 120 % ihres Richtwerts aus der Gliederung (`(kurz)` ≈ 800, ohne Angabe ≈ 1.300, `(lang)` ≈ 2.000 Wörter) straffen – zuerst Wiederholungen und Quellenformeln ohne Informationswert, keine Fakten oder Beispiele streichen. +4. Prüfe Form: Überschriften exakt wie GLIEDERUNG.md, dazu als letzter Abschnitt `## N.M Merken` (fortlaufend nummeriert), als Bullet-Liste „Begriff: Kern“ mit fünf bis zehn Zeilen aus ganzen, allein verständlichen Sätzen, ohne Beispiele, Herleitungen oder Absätze, der nichts enthält, was das Kapitel nicht erklärt (Stichwortreihen zu Sätzen machen, über 120 Wörter kürzen); keine Übungen/Merkkästen/Zusammenfassungen/Literaturlisten; keine Verweisklammern „(→ …)“ und keine Rückverweise auf frühere Abschnitte; Vorausverweise nur als Halbsatz und nur, wenn das Thema dort laut Gliederung steht; keine größeren Doppelungen mit Themen, die in andere Kapitel gehören (dann kürzen und verweisen); falls oben eine Spezialisierung steht: Stoff außerhalb davon streichen, auch Beispiele und Exkurse; Rechtschreibung, Umlaute, Markdown. Satzbau: Sätze über 30 Wörter in mehrere auflösen, Inhalt unverändert; Zielschnitt unter 20 Wörter je Satz. Sätze mit drei und mehr Code-Bezeichnern entflechten: in Worten erklären, Namenslisten streichen. Verständlichkeit: Begriffe, die der Abschnitt benutzt, ohne sie bis dahin eingeführt zu haben, kurz erklären oder auf die Einführung verweisen; Interna, die kein sichtbares Verhalten erklären, streichen; Zwischenabschnitte unter 150 Wörtern mit dem Nachbarn zusammenlegen; Gedankensprünge schließen, wo zwischen zwei Sätzen oder Absätzen die Verbindung fehlt. Umfang: Abschnitte über 120 % ihres Richtwerts aus der Gliederung (`(kurz)` ≈ 800, ohne Angabe ≈ 1.300, `(lang)` ≈ 2.000 Wörter) straffen – zuerst Wiederholungen und Quellenformeln ohne Informationswert, keine Fakten oder Beispiele streichen. 5. Wiederhole, bis du keine Fehler mehr findest. Ändere nur `buch/{{datei}}`. Arbeitsdateien nur unter `arbeit/pruefung-{{n}}/`. Keine persönlichen Daten an externe Dienste senden. diff --git a/prompts/recherche.md b/prompts/recherche.md index b4816c5..85c94b9 100644 --- a/prompts/recherche.md +++ b/prompts/recherche.md @@ -1,10 +1,10 @@ Du bereitest ein deutschsprachiges Sachbuch zum Thema „{{thema}}“ vor. -{{hinweise_block}} +{{hinweise_block}}{{spezialisierung_block}} Du arbeitest im Verzeichnis dieses Buchprojekts (aktuelles Arbeitsverzeichnis). Unterordner: `quellen/` (Rohmaterial), `buch/` (Buchdateien), `berichte/`. Deine Aufgaben, in dieser Reihenfolge: -1. **Deutung.** Kläre, was mit dem Thema gemeint ist. Bei mehrdeutigen Namen wähle die wahrscheinlichste Deutung selbst (keine Rückfragen möglich). Lege den Buchtyp fest: `werkzeug` (Software, Framework, Engine, Sprache – der Leser soll verstehen, wie sie gebaut ist und warum sie sich so verhält; Anwendung ist nicht das Ziel) oder `wissen` (Wissenschaft, Fachgebiet, Phänomen – der Leser soll den Forschungsstand verstehen). Zielgruppe und Anspruch: Standard sind Leser ohne Vorkenntnisse im Thema – bei Software Programmiergrundlagen in irgendeiner Sprache, aber keine Erfahrung mit dem Werkzeug; bei Wissensthemen allgemeine Bildung. Anspruch: die Sache lesend verstehen und einordnen, nicht selbst umsetzen. Von diesem Standard nur abweichen, wenn die Hinweise oben es verlangen. +1. **Deutung.** Kläre, was mit dem Thema gemeint ist. Bei mehrdeutigen Namen wähle die wahrscheinlichste Deutung selbst (keine Rückfragen möglich). Lege den Buchtyp fest: `werkzeug` (Software, Framework, Engine, Sprache – der Leser soll verstehen, wie sie gebaut ist und warum sie sich so verhält; Anwendung ist nicht das Ziel) oder `wissen` (Wissenschaft, Fachgebiet, Phänomen – der Leser soll den Forschungsstand verstehen). Zielgruppe und Anspruch: Standard sind Leser ohne Vorkenntnisse im Thema – bei Software Programmiergrundlagen in irgendeiner Sprache, aber keine Erfahrung mit dem Werkzeug; bei Wissensthemen allgemeine Bildung. Anspruch: die Sache lesend verstehen und einordnen, nicht selbst umsetzen. Von diesem Standard nur abweichen, wenn die Hinweise oben es verlangen. Eine Spezialisierung oben ist die Grenze des Buchs: Deutung und Quellen beschränken sich auf diesen Ausschnitt des Themas. 2. **Quellen beschaffen – lokal, prüfbar.** Lege alles unter `quellen/` ab, damit die späteren Autoren und Prüfer ohne Websuche arbeiten können (das Websuch-Kontingent je Agent ist begrenzt): - Software: Quellcode und offizielle Dokumentation der aktuellen stabilen Version per `git clone --depth 1` (Tag der aktuellen Version ermitteln), ggf. auch der Vorversion für Vergleiche; Klassenreferenzen; wenn eine ausführbare Version frei erhältlich ist (z. B. ein Engine-Binary, ein CLI), herunterladen und einen kurzen Testlauf machen, damit Beispiele später ausgeführt werden können; Upgrade-/Changelog-Dateien.