# Design creator2 Beschlossen am 2026-07-09 (Diskussion Nutzer + Claude). Ersetzt `../creator`. ## Warum Neubau Der Vorgänger gruppierte nach Entitäts-Ähnlichkeit (Clustering → Naming → Umbrella → Dedup → Degradier-Pass). Der Guide las sich als Aneinanderreihung von Bausteinen. Viele Fixes waren Symptomreparatur an dieser Kerneinheit. creator2 wechselt das Kriterium: gruppiert wird nach „lernt sich gut zusammen" (Backward Design), nicht nach „ist dieselbe Entität". ## Pipeline ``` E0 Korpus Themen: N Recherche-Sweeps (Curricula/Lehrbuch/Syllabus/Übungen) → Snapshots Uni: Dateien aus topics// (txt/md/pdf) → Snapshots Soll-Extraktion je Quelle → Konsens (Punkt braucht ≥2 unabhängige Quellen) Themen: Runden bis Sättigung (Runde ohne neuen Soll-Punkt) → Auto-Freeze E1 Inventar Abschnitte (~12k Zeichen) → 2 Reader je Abschnitt → Atome mit Verbatim-Anker Dedup: Anker-Overlap (auto) → Embedding-Kandidaten → 2er-Panel (einstimmig) Soll-Zuordnung je Atom; Soll-Punkt ohne Atom → gezielte Nachextraktion E2 Artefakte je Soll-Punkt-Gruppe: Flashcards + 1 typisiertes Beispiel pro Atom (Form: text|mathe|code|tabelle, beste Passung) → Form-Gate (Syntax/Struktur parse-only, kein Ausführen) → Verify-Panel gegen Anker → Fix E3 Struktur Lernziele+Zuordnung aus Atomen (je Soll-Punkt) → Ziel-Check → Kanten auflösen → Zyklen brechen (Judge) → Bausteine = Ziel-Gruppen im Band (split/merge) → topologische Ordnung (Bausteine + Atome darin) E4 Guide je Baustein: Writer (Facts inline, Atom-Marker; Ausgabe DELIMITED, nicht JSON — LaTeX-Backslashes) → det. Checks → Prüfer → Fix (Fix-Cap gegen Churn). Beispiel-Marker setzt der Code DETERMINISTISCH (nicht der Writer); Assembly tauscht Marker gegen ```-Fence/Tabelle. ``` Jede Ebene endet mit `qa.messen(ebene)`; `auto_loop` fährt QA→Repair bis Note 10,0, Stillstand oder 10 Iterationen. Erst dann startet die nächste Ebene. ## Datenmodell (SQLite, backend/db.py) - `topics(name, titel, art thema|uni, status, provider)` - `runs(id, topic, status running|paused|done|failed|budget, gestartet, beendet, git_hash, git_dirty, budget_tokens, grund)` - `events(run_id, ts, ebene, stage, item, template, template_hash, provider, model, role, status, dur_ms, wait_ms, tok_in, tok_out, tok_cache_read, tok_cache_write, meta)` — Ledger, append-only - `quellen(id, topic, art web|datei, titel, url, snapshot, hash, runde, status)` - `soll(id, topic, punkt, status kandidat|bestaetigt, belege JSON [{quelle,zitat}])` - `atome(id, topic, titel, typ, definition, level, status, soll_id, ziel_id, baustein_id, ord, merged_into)` - `anker(atom_id, quelle_id, start, ende, zitat)` - `kanten(topic, von_atom, zu_atom, art braucht|verwandt, status)` - `artefakte(id, atom_id, typ flashcard|beispiel, inhalt JSON, status kandidat|verifiziert|verworfen)` — beispiel-`inhalt` trägt `form` + formspezifische Felder (text|code+sprache|tabelle); code/tabelle kommen verbatim via `` in den Guide (Assembly-Swap) - `lernziele(id, topic, text, soll_id, status)` - `bausteine(id, topic, ziel_id, titel, ord, status)` - `sections(baustein_id, stage, text_kompakt, text_lang, befunde JSON)` - `leitner(artefakt_id, box, faellig, historie)` - `befunde(run_id, ebene, art, item, detail, status offen|repariert|freigesprochen)` Alles status-basiert → Resume = Lauf neu starten, fertige Items werden übersprungen. ## QA (backend/qa.py) **Invarianten (deterministisch, gated):** - E0: jeder bestätigte Soll-Punkt hat ≥2 Belege aus verschiedenen Quellen; Korpus nicht leer - E1: jedes Atom hat Anker (Zitat verbatim in Quelle gefunden), Definition, Typ, genau einen Soll-Punkt; jeder Soll-Punkt ≥1 Atom - E2: jedes Atom ≥1 verifizierte Flashcard; Beispiel-Status entschieden - E3: Partition (jedes Atom genau ein Baustein via Ziel), Bandgröße, DAG azyklisch, keine Kante von spätem zu frühem Baustein - E4: jeder Atom-Marker vorhanden, Ziel-Anker im Text, Längenband, keine Vorwärtsverweise (Titel eines späteren Atoms fällt nicht früher) **LLM-Stichproben (nur wo nötig, immer 2 unabhängige Bestätiger):** fachlich-falsch im Guide. Note = 10 · (1 − gewichtete Befundquote); 10,0 nur bei null offenen Befunden. ## Nebenläufigkeit Einfache Wellen (`asyncio.gather` + Semaphoren in agents.py), keine Streaming-Engine. Innerhalb einer Ebene laufen unabhängige KETTEN (gen→verify je Chunk/Baustein) parallel; Stage-Barrieren nur, wo ein Schritt global rechnet (Dedup, Level, Ordnung, Konsens). Panels = n parallele Calls + Konsensregel. Hedge: Slot ohne Ergebnis nach max(90 s, timeout/2) bekommt einen Zwilling, erstes valides Ergebnis gewinnt. Live-Board trotzdem: jeder Statuswechsel → WebSocket-Broadcast. ## Provider Wie Vorgänger: `claude`-CLI, `opencode` (MiniMax), MiniMax-Text-API direkt (tool-lose Calls). Rollen quick|judge|guide|fast je Provider-Stack, Routing via env (`ROLE_JUDGE=claude`). `CREATOR_FAKE_AGENTS=1` → fake_agents.py. ## Frontend (Vue 3 + Vite) Tabs: **Board** (Spalten = Ebenen, ALLE Karten, scrollbar, live via WS) · **Guide** (marked+KaTeX+highlight, Level-Filter) · **Üben** (Leitner-Boxen) · **Kennzahlen** (Tokens/Zeit je Ebene/Stage/Template aus dem Ledger). ## Bewusst gestrichen Delta-Läufe (Material vollständig), Abnahme-Benchmark, Projekt-/Link-Quellen, Chat/Prüfungs-Features, ELO/Stufen-Ansichten (Level-Feld existiert, Ansichten später).