Skip to content

fix(eval): reeval_baseline.py fuer #232-Re-Eval-Sweep einsatzbereit machen#303

Merged
TillQuandel merged 1 commit into
masterfrom
fix/reeval-baseline-sweep-ready
Jul 15, 2026
Merged

fix(eval): reeval_baseline.py fuer #232-Re-Eval-Sweep einsatzbereit machen#303
TillQuandel merged 1 commit into
masterfrom
fix/reeval-baseline-sweep-ready

Conversation

@TillQuandel

Copy link
Copy Markdown
Owner

Ist-Zustand

python reeval_baseline.py --dry-run auf master (a720399, enthält #298) meldet „Zu evaluieren: 0 Notes" — alle 14 Ordner in generative/.cache/eval/baseline/ werden übersprungen. Zwei unabhängige Bugs:

  1. _already_done() prüft hartkodiert eval_version='4.1' (Zeile 92). Nach dem EVAL_VERSION-Bump auf 4.3 (fix(eval): CID-Font-Artefakte (U+0231/U+022C) im Quelltext zurückmappen — Grounder bestraft OCR-degradierte PDFs nicht mehr (#278) #298) markiert das jede historisch mit 4.1 evaluierte Note als „schon erledigt" — obwohl deren Re-Evaluierung unter der aktuellen Version der Zweck des Sweeps ist.
  2. PDF_MAP ist veraltet (verweist auf nicht-existierende Dateinamen wie „Bates - 2017 - Information Behavior.pdf"; kennt die meisten der 14 Ordner gar nicht) und nutzt Präfix-Matching (folder.startswith(prefix)).

Fix

# Punkt Vorher Nachher
1 Guard hartkodiert eval_version='4.1' scopt auf _eq.EVAL_VERSION (aktuell 4.3), additiv — alte Zeilen bleiben, Resume innerhalb einer Version bleibt erhalten
2 Abschluss-Report query_note_evals(eval_version="4.1") query_note_evals(eval_version=_eq.EVAL_VERSION)
3 PDF_MAP-Matching Präfix (folder.startswith(prefix)) — kollidiert real (s.u.) exakter Ordnername (PDF_MAP.get(folder_name))
4 PDF_MAP-Pfade hartkodierte C:/Users/tillq/OneDrive/...-Literale generative.config.LITERATURE_DIR (vorhandene Config-Konstante; CLAUDE.md-Pfadregel: keine hartkodierten C:/Users/...-Literale im Code)
5 Worktree-Fähigkeit BASELINE_DIR nicht überschreibbar neue --baseline-dir-Option (Default bleibt ROOT-relativ) + main(argv=...) für Tests/Funktionsnachweise

Die Präfix-Kollision konkret: "Porst-2014-Auszug-S1-40-bak-preclean-20260530" beginnt mit "Porst-2014-Auszug-S1-40" — unter Präfix-Matching hätte der Backup-Ordner denselben Eintrag geerbt wie der Hauptordner, obwohl er explizit ausgeschlossen sein soll. Test dafür (synthetisch, Foo/Foo-bak): TestFindPdfExactMatchNoPrefixCollision.

PDF_MAP — historischer Beleg je Eintrag

Rekonstruiert aus atomic_analytics.db (note_evals.pdf je vault__*.md-Datei des jeweiligen Ordners, read-only Query gegen die Bestandsdaten) + Existenz-Check gegen LITERATURE_DIR (C:/Users/tillq/OneDrive/Dokumente/Literatur/). Alle 14 aktuell existierenden Baseline-Ordner:

Ordner DB-Historie (note_evals.pdf) PDF existiert? Entscheidung
Bates - Information Behavior 4/5 Zeilen → „Bates - Information Behavior.pdf" (4 Notes), 1 Zeile → „bates-2017.pdf" (Note „Geschichte der Information-Behavior-Forschung.md", vermutlich Rename-Altlast) ja gemappt auf Mehrheitswert, Ordnername matcht exakt
Ebner und Gegenfurtner - 2019 - ... 2/2 Notes → exakt gleichnamiges PDF ja gemappt
Hrastinski - 2008 - ... 2/2 Notes → exakt gleichnamiges PDF ja gemappt
Schlebbe und Greifeneder - 2022 - ... 3 Notes; „Kritik am Information-Need-Konzept.md" hat 4 Zeilen → Schlebbe-PDF und 2 Zeilen → „Afzal - 2017 - ...pdf" (Titel identisch mit POISON_TITLE-Fixture in test_title_trust_cross_check.py/test_load_draft_state_roundtrip.py — vermutlich Testkontamination der Produktions-DB, nicht die reale Quelle); „Der rote Faden...md" → Schlebbe-PDF; „Information Need.md" ohne DB-Historie Schlebbe-PDF: ja. Afzal-PDF: nein gemappt auf Schlebbe (Mehrheit + Ordnername + Afzal-Datei existiert ohnehin nicht)
Spreitzer - ... 4/4 Notes → exakt gleichnamiges PDF ja gemappt
Sühl-Strohmenger - 2008 - ... 10/12 Notes → exakt gleichnamiges PDF (2 Notes ohne DB-Historie, vermutlich noch nie evaluiert) ja gemappt
Bates - 2017 - Information Behavior 0 Notes, 0 DB-Zeilen (Ordner ist komplett leer) n/a ausgeschlossen — vermutlich Alt-Ordner vor Umbenennung zu „Bates - Information Behavior"
bates-2017 1/2 Notes → „bates-2017.pdf" (n=3) nein ausgeschlossen — historisches PDF fehlt; NICHT durch „Bates - Information Behavior.pdf" ersetzt (kein Beleg, dass es dieselbe Quelle ist)
Porst-2014-Auszug-S1-40 2/2 Notes → „Porst-2014-Auszug-S1-40.pdf" (Auszug S1-40) nein (nur Voll-PDFs „Porst - 2011/2014 - Fragebogen ... Arbeitsbuch.pdf" vorhanden) ausgeschlossen — Auszug-PDF fehlt, bewusst NICHT durchs Voll-PDF ersetzt (mehr Chunks → Score-Verwässerung); offener Punkt s.u.
Porst-2014-Auszug-S1-40-bak-preclean-20260530 0 Notes, 0 DB-Zeilen n/a ausgeschlossen — Backup-Ordner (Suffix -bak-preclean)
zettelkasten-primer 7/8 Notes → „zettelkasten-primer.pdf" nein ausgeschlossen — historisches PDF fehlt
flags 0 DB-Zeilen; Note-Frontmatter source-file: "flags.pdf" n/a ausgeschlossen — Pytest-Fixture-Note (Test-/Struktur-Ordner, keine echte Baseline)
fresh 0 DB-Zeilen; Note-Frontmatter analog n/a ausgeschlossen — Pytest-Fixture-Note
src 0 DB-Zeilen; Note-Frontmatter source-file: "src.pdf" n/a ausgeschlossen — Pytest-Fixture-Note

6 Ordner gemappt, 8 explizit ausgeschlossen (jeweils mit Grund im Code-Kommentar bei PDF_MAP, kein stilles Weglassen).

Sonderfall-Entscheide (Auftrag Punkt 3)

  • Porst-2014-Auszug-S1-40: historische Zuordnung zeigt eindeutig auf ein Auszug-PDF (S1-40), nicht das Voll-PDF. Da dieses Auszug-PDF nicht mehr existiert, wird der Ordner geskippt — keine Substitution durch das Voll-PDF, weil das die Chunk-Anzahl und damit die Scores gegenüber der historischen Baseline verzerren würde.
  • Porst-2014-Auszug-S1-40-bak-preclean-20260530: 0 Notes vorhanden (leer), zusätzlich explizit als Backup ausgeschlossen (nicht nur zufällig leer — falls dort je wieder Dateien landen, greift der Ausschluss trotzdem).
  • flags / fresh / src: enthalten vault__*.md-Dateien, aber deren Frontmatter (source-file: "flags.pdf" bzw. "src.pdf") zeigt eindeutig Pytest-Fixtures — keine echten Baseline-Notes. Sauber geskippt (kein PDF im Mapping, Skip-Meldung „kein PDF für: …").
  • zettelkasten-primer: historische Quelle „zettelkasten-primer.pdf" ermittelt, existiert aber nicht in LITERATURE_DIR → Skip + Dokumentation.

Dry-Run — Vorher/Nachher

Vorher (master, unverändert): Zu evaluieren: 0 Notes

Nachher (--baseline-dir gegen das Haupt-Repo-Cache, ATOMIC_DB_PATH/ATOMIC_AGENT_PDF_BASE auf die echten Pfade gesetzt, read-only — kein LLM-Call, kein DB-Write):

  [skip] kein PDF für: Bates - 2017 - Information Behavior
  [skip] kein PDF für: bates-2017
  [skip] kein PDF für: flags
  [skip] kein PDF für: fresh
  [skip] kein PDF für: Porst-2014-Auszug-S1-40
  [skip] kein PDF für: Porst-2014-Auszug-S1-40-bak-preclean-20260530
  [skip] kein PDF für: src
  [skip] kein PDF für: zettelkasten-primer
Zu evaluieren: 27 Notes
...
[dry-run] Fertig: 27 neu evaluiert, 0 übersprungen, 0 Fehler

27 Notes über 6 Ordner (Bates - Information Behavior 4, Ebner 2, Hrastinski 2, Schlebbe 3, Spreitzer 4, Sühl-Strohmenger 12), 0 „übersprungen" (bereits mit 4.3 evaluiert) — korrekt, da alle 27 bisher nur 4.1-Historie haben. 8 Ordner sauber geskippt. 6 + 8 = 14, deckt alle real existierenden Baseline-Ordner ab.

Tests (TDD)

Neue Datei generative/tests/test_reeval_baseline_guard.py, 12 Tests, alle vorher gegen den unveränderten Code als RED verifiziert (9 schlugen erwartungsgemäß fehl, 3 bestanden bereits als Baseline-Sanity-Checks):

  • TestAlreadyDoneUsesCurrentEvalVersion — Guard nutzt _eq.EVAL_VERSION, nicht 4.1 (RED: assert False is True bzw. assert True is False gegen Alt-Code).
  • TestFindPdfExactMatchNoPrefixCollision — exakter Abgleich, synthetisch (Foo/Foo-bak), deckt die reale Präfix-Kollision ab.
  • TestPdfMapRealBaselineFolders — Regression-Lock der obigen Beleg-Tabelle (6 gemappte + 8 ausgeschlossene Ordner).
  • test_no_hardcoded_literature_path_in_source — Regression-Guard analog eval_figure_feasibility.py (keine OneDrive/Dokumente/Literatur-Literale).
  • TestBaselineDirOption — neue CLI-Option + argv-Parameter.

Ergebnis: 12/12 GREEN, keine Regression in test_baseline_run_namespace.py (bestehende reeval_baseline-Tests, 13/13 weiterhin grün).

Volle Suite (generative + lib/decision_engine/tests + shared/tests): 5969 passed, 3 skipped, 8 deselected (keine Failures).

ruff: ruff check clean, ruff format --check clean (nach ruff format auf beide geänderten Dateien angewendet).

Offene Punkte

  1. Porst-2014-Auszug-S1-40 bleibt dauerhaft ausgeschlossen, bis das Auszug-PDF (S1-40) wiederbeschafft/rekonstruiert wird. Betrifft 2 Notes.
  2. bates-2017 und zettelkasten-primer bleiben ausgeschlossen, da ihre historischen PDF-Dateinamen nicht in LITERATURE_DIR liegen. Falls diese PDFs nachträglich in die Literatur-Sammlung aufgenommen werden, PDF_MAP entsprechend ergänzen (nicht automatisch durch ein "ähnliches" PDF ersetzen).
  3. ATOMIC_AGENT_PDF_BASE ist auf diesem Rechner aktuell nicht gesetzt (weder in generative/.env noch als User-/Machine-Umgebungsvariable) — LITERATURE_DIR fällt dann auf das nicht existierende ~/Documents/Literatur zurück. Für den echten Sweep muss die Variable (oder ein Eintrag in generative/.env) auf den OneDrive-Literatur-Ordner zeigen, sonst melden alle 6 gemappten Ordner „PDF nicht gefunden". Für den Dry-Run-Nachweis in diesem PR wurde sie inline im Kommando gesetzt — kein Repo-File geändert.
  4. Die einzelnen Abweichungen bei „Bates - Information Behavior" (1/5 DB-Zeilen zeigt „bates-2017.pdf") und „Schlebbe ...## (2 Zeilen zeigen auf das nicht-existierende „Afzal"-PDF, vermutlich Testkontamination) sind nicht weiter verifizierbar ohne zusätzliche Quellen — Mehrheitsentscheid + Ordnername-Übereinstimmung + Datei-Existenz waren die Entscheidungsbasis (s. Tabelle oben).

Kein echter Sweep in diesem PR (keine LLM-Calls, kein DB-Write) — der läuft separat nach Merge.

…achen

Ist-Zustand (Dry-Run auf master a720399): "Zu evaluieren: 0 Notes" — alle 14
Baseline-Ordner in .cache/eval/baseline/ wurden uebersprungen.

Zwei Bugs:
1. _already_done() pruefte hartkodiert eval_version='4.1'. Nach dem
   EVAL_VERSION-Bump auf 4.3 (#298) markierte das jede historisch mit 4.1
   evaluierte Note als "schon erledigt" — obwohl deren Re-Evaluierung unter
   der aktuellen Version der Zweck des Sweeps ist.
2. PDF_MAP war veraltet (verwies auf nicht-existierende Dateinamen, kannte
   die meisten der 14 Ordner gar nicht) und nutzte Praefix-Matching
   (folder.startswith(prefix)) — das kollidiert real: "Porst-2014-Auszug-
   S1-40-bak-preclean-20260530" beginnt mit "Porst-2014-Auszug-S1-40" und
   haette denselben Eintrag geerbt, obwohl der Backup-Ordner ausgeschlossen
   sein soll.

Fix:
- Guard scopt auf _eq.EVAL_VERSION (additiv — Alt-Zeilen bleiben, Resume
  innerhalb einer Version bleibt erhalten).
- PDF_MAP komplett rekonstruiert aus der historischen Note->PDF-Zuordnung in
  atomic_analytics.db (note_evals.pdf je vault__*.md-Datei, eval_version=4.1)
  + Existenz-Check gegen LITERATURE_DIR (Config-Konstante statt hartkodierter
  OneDrive-Pfade — CLAUDE.md-Pfadregel). Exakter Ordnername statt Praefix.
  6 Ordner gemappt, 8 explizit ausgeschlossen (dokumentiert im Code-Kommentar
  je Eintrag): leerer Alt-Ordner, Backup, 3x Test-/Struktur-Fixture, 2x
  fehlendes historisches PDF (bates-2017.pdf, zettelkasten-primer.pdf), 1x
  Auszug-PDF fehlt (Porst — bewusst NICHT durchs Voll-PDF ersetzt, Score-
  Verwaesserung durch mehr Chunks; offener Punkt s. PR-Body).
- Neue --baseline-dir-Option (Default ROOT-relativ) fuer Funktionsnachweise
  aus einem isolierten Worktree ohne eigenes .cache.

Dry-Run danach (--baseline-dir gegen das Haupt-Repo-Cache, read-only): 27
Notes ueber 6 Ordner zu evaluieren, 0 uebersprungen, 8 Ordner sauber geskippt.

Tests: TDD (9 RED -> GREEN, test_reeval_baseline_guard.py neu). Volle Suite
(generative + lib/decision_engine/tests + shared/tests): 5969 passed, 3
skipped, 8 deselected.
@TillQuandel TillQuandel merged commit 8b4f500 into master Jul 15, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants