5.3 KiB
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/<name>/ (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+Beispiel pro Atom → 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)
E3.5 Diagramme je Baustein: planen (welche+Typ: DAG-deterministisch | Judge) → Spec-JSON
(LLM, kein rohes Mermaid) → deterministisch → Mermaid → Parse-Gate →
Grounding-Panel. Optional; Platzierung macht der Guide-Writer per Marker.
E4 Guide je Baustein: Writer (Facts inline, Atom-Marker, `<!-- diagramm: id -->`)
→ det. Checks → Prüfer → Fix; Assembly tauscht Marker gegen ```mermaid-Fence
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-onlyquellen(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)lernziele(id, topic, text, soll_id, status)bausteine(id, topic, ziel_id, titel, ord, status)diagramme(id, topic, baustein_id, typ, quelle dag|llm, spec JSON, mermaid, status geplant|kandidat|verifiziert|verworfen|kein, befunde JSON)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.
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).