12 KiB
Auftrag: Inventar-Pipeline reparieren — zu viele, fehlende und schlecht benannte Bausteine
Kontext
Das Thema aak (Uni-Quelle uni/aak: Skript + Serien + Klausuren + Hausaufgaben) erzeugte 108 Bausteine. Soll-Abgleich mit dem Skript ergibt: sinnvoll wären ~60–70 (davon ~40–45 Skript-Kern). Der letzte QA-Lauf (storage/qa/aak/20260705-201016.json) zeigt 36 % Dubletten-Verdacht bei Note 10.0 und Lücken-Quote 0.0 — obwohl Kernkonzepte fehlen.
Zahlenfluss des Laufs (aus storage/topics/aak/arbeit/inventar-*.json):
~1150 Roh-Nennungen (24 Chunks × 2 Research-Pässe) → 203 Kandidaten → Filter degradiert 69, Recheck holt 17 zurück → 134 → Dedup prüft 183 Paare, merged nur 17 (9 %) → 117 → Gruppierung: 5 Umbrellas, 17 Umbrella-Merges per Type-Gate verworfen → Supplement +4 → 108.
Die Pipeline-Stages stehen in inventory_stages (backend/board_inventory.py:1614). Alle Zeilennummern unten beziehen sich auf den Branch refactor inkl. der offenen (uncommitteten) Diffs — siehe „Leitplanken".
Befund: sechs Root Causes
R1 — Extraktion erlaubt Beweisschritt-Granularität (Hauptursache „zu viele")
templates/Prompt/Blocks-Research.mderklärt „named theorems with their own statement" und jede „standalone REDUCTION" zum eigenen Baustein.templates/Prompt/Blocks-Source-Uni.mdnennt „formulas and theorems" als Zielkategorie, ohne Granularitätsgrenze.- Folge im aak-Lauf: 14 Beweisschritt-/Beweis-Objekt-Bausteine (z. B.
Type-I,Schedule D*,Gewichtsfunktion d2,Zick-Zack-Tour,Optimaler Rundweg OPT((Kn,d2)) = n,3-SAT ≤ K-COLOR: G=(V,E) Konstruktion) und 8 Bausteine für EIN Konzept („untere Schranken via ETH":Lower Bound via k/n/|E|/|T|+ 4 weitere). - Verstärker:
_is_named_statement(backend/blocks.py:1355) schützt alles mit Reduktions-Syntax vor Demotion — auch Konstruktionsdetails wie…: G=(V,E) Konstruktion.
R2 — Quellen-Nummern als Titel, Reparaturstufe greift nicht (Hauptursache „Benennung")
- Research-Pässe übernehmen Skript-Nummerierungen als Titel („Satz 7.13", „Bemerkung 7.22", „Definition 6.19"). 6 finale Bausteine tragen reine Satz-/Bemerkungs-Nummern.
_REFERENCE_RE(backend/blocks.py:1022) matcht nur nackte Referenzen („Bemerkung 7.22"), NICHT „Satz 7.13 (Christofides)" oder „Satz 7.6: Kriterium für Eulerschen Kreis" — die laufen als „gute" Titel durch.- Rename ist Best-Effort: In
clarifywird nur umbenannt, wenn ein Judge freiwilligrenameliefert (backend/board_inventory.py:663). Beispiel Cluster08c52a84: Judge j1 schlug für „Bemerkung 7.22" den korrekten Konzeptnamen vor („Untere Schranke für FPTAS …"), die Aggregation verwarf ihn. - Singletons überspringen Naming komplett:
_choose_titleläuft nur beilen(rows) > 1(backend/board_inventory.py:725und:802).
R3 — Titel-Split zerschneidet Namen (abgeschnittene Titel)
_title = entry.split(" — ")[0](backend/textkit.py:35) + aggressives_norm_dash(backend/textkit.py:77): ein en-Dash MIT einseitigem Space innerhalb eines Titels wird zum Separator → Split mitten im Titel.- Es gibt keine Klammer-Balance-Prüfung und keinen Repair. Ergebnis:
Aε-Algorithmus (Güte 1+ε, Laufzeit O(n3undN P via nicht-deterministische Turingmaschine (Definition 6.liefen wortwörtlich bisdone. - (Die 60-Zeichen-Kürzung in
backend/board_artefacts.py:81betrifft nur Ordnernamen, nicht Titel — kein Fix nötig.)
R4 — Dedup-Dämme brechen (36 % Verdacht überleben)
- Merge braucht Einstimmigkeit zweier Judges (
if ja1 and ja2,backend/board_inventory.py:1200); „uneinig" → kein Merge, kein Tiebreak. - Parameter-Familien werden als Paare je einzeln mit „nein" beschieden (
Lower Bound via k↔n↔|E|↔|T|, alle QA-Jaccard 1.0). - Kandidaten-Generierung verpasst Komposita:
_canonical_key(backend/blocks.py:1118) trennt „Cliquenproblem" nicht in „Clique"+Stopwort → „Clique" vs. „Cliquenproblem (k-Clique)" wird ggf. nie Judge-Kandidat. - Type-Gate der Gruppierung verwarf 17 Umbrella-Merges (
grund: "type-gate"ininventar-gruppierung.json) — exakt die späteren QA-Dubletten (Approximations-Grundbegriffe, Type-I/II+Schedule-Objekte, NP-Definitionen). - Filter-Recheck holte 17 korrekte Degradierungen zurück (
ueberstimmt/floor_vetoininventar-filter-535eb84c.json) — darunter die komplette Lower-Bound-Familie.
R5 — Echte Lücken trotz Quote 0.0 (Ursache „fehlende")
- Fehlend im aak-Inventar: SAT/Satz von Cook-Levin (zentralster Satz), MGA (Güte 2), Sahni-PTAS Ak, Satz von Lawler, Satz 6.16 (P=NP-Kriterium), Lastfunktion (Def 7.26, per Supplement teilweise nachgeholt).
- QA-Lücken sind token-basiert (
backend/qa.py:163): 108 übergranulare Bausteine decken jede Sektion irgendwie ab → Konzeptlücken unsichtbar, Supplement (_proc_gap_check) ergänzt zu wenig. - Verlust-Vektor upstream:
clarifyverlangt für Einzel-Reader-Funde Einstimmigkeit aller Judges (accept = v >= len(outs),backend/board_inventory.py:657) — ein einziges „nein" verwirft einen real existierenden Fund alsfailed-quorum.
R6 — QA-Note ist blind für das Problem
NOTE_GEWICHTE(backend/qa.py:40) enthält keine Dubletten. 36 % Verdacht + Verschlechterung zum Vorlauf (+0.06) ergeben trotzdem Note 10.0.
Maßnahmen (priorisiert; M1–M3 = Ursachen, M4–M5 = Dämme, M6 = Messung)
M1 — Titel-Hygiene, deterministisch
_norm_dash/Titel-Split klammer-bewusst machen: Dash innerhalb offener Klammer ist KEIN Separator. Nach dem Split: unbalancierte Klammern → Titel reparieren (bevorzugt: Split rückgängig / nächsten Separator nehmen)._REFERENCE_REerweitern: auchSatz 7.13 (Christofides),Satz 7.6: Kriterium …,… (Definition 6.19)erkennen. Deterministischer Strip: Referenz-Präfix/Suffix entfernen, Konzeptrest behalten („Satz 7.6: Kriterium für Eulerschen Kreis" → „Kriterium für Eulerschen Kreis"). Reine Nummern ohne Konzeptrest („Bemerkung 7.22") → Rename-PFLICHT (Judge muss Konzeptnamen liefern, sonst bleibt die Karte vordonehängen bzw. wird saniert), statt Best-Effort.- Naming/Sanierung auch für Singletons erzwingen, wenn Titel
_is_reference, klammer-unbalanciert oder >80 Zeichen ist (board_inventory.py:725,:802,_sanierung_noetig:492).
M2 — Granularitätsgrenze in den Prompts
Blocks-Research.md+Blocks-Source-Uni.md(und GeschwisterBlocks-Source-*.md): Negativ-Liste ergänzen — KEINE eigenen Bausteine sind: einzelne Beweisschritte, Hilfskonstruktionen/Beweis-Objekte (Hilfs-Schedules, Gewichtsfunktionen, konstruierte Touren), berechnete Einzel-Instanzen, Parameter-Instanzen desselben Arguments (dieselbe Technik „via k / via n / via |E|" = EIN Baustein). Solche Inhalte gehören als Aspekt in den Eltern-Baustein.- Titel-Regel in beide Naming-Prompts (
Blocks-Naming.md,Blocks-Klaerung.md,Blocks-Sanierung.md): Titel ist der KONZEPTNAME; Quellen-Nummerierungen („Satz 7.13") sind als Titel verboten, dürfen aber in der Beschreibung stehen. - Sätze bleiben erlaubt als Baustein, wenn sie ein eigenständig prüfbares Ergebnis sind (Cook-Levin, Christofides) — benannt nach dem Ergebnis, nicht der Nummer.
M3 — Fragment-Filter nachschärfen
_is_named_statement(blocks.py:1355) verengen: Reduktions-Syntax mit Konstruktions-Suffix (Doppelpunkt/Zusatz NACH der Relation, z. B.…≤ K-COLOR: G=(V,E) Konstruktion) ist NICHT geschützt, sondern fragment-verdächtig.- Recheck-Overturn erschweren:
ueberstimmtnur bei einstimmigem Recheck-Panel statt Mehrheit (board_inventory.py:1031). Beleg: 15 von 17 zurückgeholten Karten waren spätere QA-Dubletten. - Parameter-Varianten als Verdacht markieren: Titel-Paare, die sich nur durch ein Parameter-Token unterscheiden (
via k/via n/via |E|), in_filter_suspectbzw. als eigene Familien-Heuristik aufnehmen → Filter-/Dedup-Kandidat.
M4 — Dedup-Recall erhöhen (ohne Fehlmerge-Risiko aufzugeben)
- Die drei offenen Diffs (Richtungs-Guard
_direction_conflict, Judge-Kanal-Guard, Dedup-Prompt-Zeile) BEHALTEN — sie sind Teil der Lösung. - Tiebreak statt Veto: bei 1-1-Judge-Split (
uneinig,board_inventory.py:1200) einen dritten Judge entscheiden lassen. - Familien-Kollaps: Cluster von ≥3 Titeln, die sich nur im Parameter-Token unterscheiden, als EIN Merge-Fall (ein Judge-Call für die Familie) statt n² Einzelpaare.
_canonical_key(blocks.py:1118): Kompositum-Suffix „…problem" auch verklebt abtrennen („Cliquenproblem" → Stamm + Stopwort), damit solche Paare Kandidaten werden. Generisch halten (Suffix-Regel, keine Wortliste pro Domäne).- Type-Gate der Gruppierung (
_GROUP_STANDALONE-Pfad) lockern: Umbrella-Merge nicht allein wegen gemischter Content-Typen (Definition+Satz+Algorithmus) verwerfen, wenn das Judge-Panel die Gruppe bestätigt hat. Die 17 verworfenen Fälle ausinventar-gruppierung.jsonsind der Prüfmaßstab. - NICHT anfassen: die Varianten-Regel „k-X ≠ X / Max-X ≠ X" im Dedup-Prompt und das 2-Judge-Panel für klare Fälle. Bisher 0 Fehlmerges — das muss so bleiben.
M5 — Lücken schließen
clarify-Quorum für Einzel-Reader-Funde von Einstimmigkeit auf Mehrheit senken (board_inventory.py:657) ODER abgelehnte Funde als Fragment aufbewahren stattrejected, damitgap_check/Supplement sie wiederfinden kann.- Gap-Check konzeptbasiert ergänzen: benannte Ergebnisse des Korpus (Sätze/Definitionen mit eigener Aussage, Abschnittsüberschriften) gegen das Inventar prüfen, nicht nur Token-Abdeckung. Ein benanntes Kernresultat ohne zugeordneten Baustein = Lücke → Supplement-Kandidat.
- Prüffälle für aak (müssen nach einem Neulauf existieren): SAT/Cook-Levin, MGA, Sahni-PTAS Ak, Satz von Lawler, P=NP-Kriterium (Satz 6.16).
M6 — QA ehrlich machen
dubletten_verdachtinNOTE_GEWICHTEaufnehmen (qa.py:40), damit die Note das Nutzerproblem abbildet.- Optional: konzeptbasierte Lücken (aus M5.2) als eigene QA-Quote ausweisen.
Leitplanken
- Generisch bleiben: keine aak-/Komplexitätstheorie-Sonderregeln in Pipeline oder Prompts. aak ist nur der Prüffall. Alle Heuristiken müssen für beliebige Themen tragen.
- YAGNI: kleine, gezielte Diffs; bestehende Muster (Judge-Panels, Schema-Parser, Kanban-Stages) wiederverwenden; nichts Neues bauen, was eine Prompt-Zeile löst.
- Offene Diffs behalten:
backend/blocks.py,backend/board_inventory.py,templates/Prompt/Blocks-Dedup.mdenthalten uncommittete Änderungen (Richtungs-Guard). Nicht verwerfen, darauf aufbauen. - Niemals
git commitodergit push— der Nutzer committet selbst. - Fehlmerge-Bilanz: Recall-Erhöhungen (M4) dürfen keine falschen Merges einführen. Jede Lockerung braucht einen Judge-Beleg-Pfad; deterministische Auto-Merges bleiben streng.
- Keine Echtläufe ohne Freigabe:
make qa TOPIC=aakmit LLM-Judges und komplette Neuläufe kosten Tokens — nur nach Rückfrage beim Nutzer starten.
Validierung (in dieser Reihenfolge)
pytestinbackend/— bestehende Tests dürfen nicht brechen; für M1 (Titel-Split, Referenz-Regex) und M4.4 (_canonical_key) gezielte Unit-Tests ergänzen (Fixtures: die realen Schadensfälle aus diesem Auftrag).make test-e2e— Fake-E2E (backend/fake_agents.py) muss grün bleiben; Störfall-Matrix ggf. um Referenz-Titel und unbalancierte Klammern erweitern.- QA-Fehler-Injektion (Muster siehe QA-Modul-Tests): injizierte Satz-Nummern-Titel, Parameter-Familien und Konzeptlücken müssen von den geänderten Checks erkannt werden.
- Erst nach Nutzer-Freigabe: Neulauf aak +
make qa TOPIC=aak. Erfolgskriterien:- Baustein-Anzahl ~60–70 (statt 108),
dubletten_verdacht< 0.10 (statt 0.361),- die 5 Prüffall-Konzepte aus M5.3 existieren,
- kein Titel matcht die erweiterte Referenz-Erkennung, keine unbalancierten Klammern,
- Lücken-/Fremd-Quote nicht schlechter als der Referenzlauf
20260705-201016.json.