Skip to content

fix(dashboard): pdf_key-Drift-Varianten in _pdf_group_key kanonisieren#311

Merged
TillQuandel merged 1 commit into
masterfrom
fix/pdf-key-kanonisierung
Jul 16, 2026
Merged

fix(dashboard): pdf_key-Drift-Varianten in _pdf_group_key kanonisieren#311
TillQuandel merged 1 commit into
masterfrom
fix/pdf-key-kanonisierung

Conversation

@TillQuandel

Copy link
Copy Markdown
Owner

Kurzfassung

Problem Dieselbe Quelle (Bates 2017) stand unter bis zu 3 Schreibweisen im Dashboard; _version_pair_compare verlor sie deshalb still aus common_pdfs
Fix _PDF_GROUP_ALIASES-Map in _pdf_group_key (generative/eval_dashboard.py) — Anzeige-seitig, Bestandsdaten unangetastet
Belegte Aliase 4 (Bates x2, Jaiswal, Dhanasekhar) — je mit DB-Beleg, s. Tabelle unten
Bewusst nicht gemergt test-short.pdf (Inhalts-Identität unsicher)
Wirkung common_pdfs für v0.3.130/v0.3.143 (echte Daten): []["bates-2017"]
Tests 6 neu + 1 angepasst, RED verifiziert → GREEN
Suite 6035 passed, 3 skipped (unverändert ggü. vorher)
ruff clean (check + format)
HTML nicht angefasst

Problem (belegt)

U6 (UX-Review 2026-07-15): Im Dashboard standen bis zu 3 „Bates"-Schreibweisen nebeneinander.

B3 (Opus-Statistiker-Abnahme zu PR #305): _version_pair_compare("v0.3.130", "v0.3.143") lieferte common_pdfs=[], obwohl Bates in beiden Versionen evaluiert wurde. Ursache: _pdf_filter_key erkennt nur die Struktur "Autor - Jahr - Titel" (nimmt die ersten zwei " - "-Segmente). Rohdaten, die davon abweichen, fallen auf einen anderen Slug:

  • "Bates - 2017 - Information Behavior.pdf" / "bates-2017.pdf" → Slug bates-2017
  • "Bates - Information Behavior.pdf" (Jahr fehlt, ab v0.3.143) → Slug bates-information-behavior
  • "Bates" (bare, eval_version 1.3) → Slug bates

Drei verschiedene Gruppen-Keys für dieselbe Quelle.

Alias-Tabelle (jede Zuordnung mit Beleg aus den Bestandsdaten)

Ermittelt READ-ONLY aus C:\tmp\sweep-backup-20260715-213521\atomic_analytics.db (eval_versions 1.3+4.1) + gezielter Fensterprüfung im Haupt-Repo generative/.cache/quality_history.jsonl (eval_version 4.3, bestätigt dieselbe Drift-Variante).

Roh-Slug (vorher) Kanonischer Key (nachher) Beleg
bates-information-behavior ("Bates - Information Behavior.pdf", ab v0.3.143, bestätigt in eval_version 4.1 und 4.3) bates-2017 Thematische Note-Überschneidung mit der bates-2017-Gruppe: "Berrypicking", "Least-Effort-Prinzip (Informationssuche)" (v0.3.130) vs. "Follow the Information (Bates' Disciplinary Heuristic)", "Geschichte der Information-Behavior-Forschung" (v0.3.143) — deckungsgleich mit _PDF_META["bates"]s Themenbeschreibung (Berrypicking, Begriffsgeschichte).
bates (bare "Bates", note_evals.pdf, eval_version 1.3, Testlauf run_id=test-20260519-120000) bates-2017 DB-Join, kein Konjekt: derselbe run_id trägt in pipeline_runs.pdf_source = "Bates - 2017 - Information Behavior.pdf".
rl-information-seeking-quantum ("rl-information-seeking-quantum.pdf", v0.3.34) jaiswal-2020 Exakter Note-Titel-Treffer in beiden Runs: "Information Seeking als Reinforcement-Learning-Task.md" (v0.3.34 und v0.3.39, "Jaiswal - 2020 - Reinforcement Learning-driven Information Seeking A Quantum Probabilistic....pdf"). Zusätzlich zitiert der v0.3.34-Lauf selbst explizit "Jaiswal et al. 2020" (Note MoC-Quantum-inspired Reinforcement Learning Framework (Jaiswal et al. 2020).md).
cobaltite-paper ("cobaltite-paper.pdf", v0.3.51/v0.3.54) dhanasekhar-2025 Exakter Note-Titel-Treffer in beiden Runs: "AC magnetization studies.md" (v0.3.51/54 und v0.3.56/58, "Dhanasekhar - 2025 - Coexistence of magnetic and dielectric glassy states in alternating kagome and.pdf"), durchgängig dieselbe Fachterminologie (LuBaCo4O7, Kinetic Arrest, Dielectric/Magnetic Glassy State).

Geprüft, aber NICHT gemergt: test-short.pdf (v0.3.48) teilt dieselbe Fachterminologie mit der Dhanasekhar-Gruppe (LuBaCo4O7, Kinetic Arrest, Glassy State) — aber der Name ist rein synthetisch (kein Autor-/Titel-Bezug wie bei den anderen Kandidaten), und ob die Pipeline dieselbe Quelle oder einen bewusst anderen (kürzeren) Testausschnitt evaluiert hat, lässt sich ohne Diff der Quell-PDFs nicht verifizieren. Gemäß "bei Unsicherheit nicht zusammenführen" ausgelassen.

Alle 44 distinct pdf-Werte in note_evals (eval_versions 1.3+4.1) wurden gesichtet; keine weiteren belegbaren Drift-Paare gefunden (u. a. geprüft und bewusst getrennt gehalten: "Exploring information behaviour.pdf" — eigenständige Wilson-Quelle, nicht Bates; "Meehan - 2017 - Forster..." — Rezension von Forsters Buch, andere bibliografische Entität als "Forster - 2017 - ..."; Beutelspacher/zettelkasten-primer/Porst-2014-Auszug-S1-40 — stabil, keine Varianten).

Wirkungsnachweis: _version_pair_compare auf echten Daten (read-only)

Reale note_evals-Zeilen (eval_version=4.1, pipeline_version IN (v0.3.130, v0.3.143)) aus der Backup-DB, einmal mit geleerter _PDF_GROUP_ALIASES (= Stand vorher) und einmal mit der neuen Map gerechnet:

VORHER (ohne Alias-Map):
  common_pdfs: []
  only_a:      ['bates-2017']
  only_b:      ['bates-information-behavior', 'hrastinski-2008',
                's-hl-strohmenger-2008', 'schlebbe-und-greifeneder-2022',
                'zettelkasten-primer']

NACHHER (mit Alias-Map):
  common_pdfs: ['bates-2017']
  only_a:      []
  only_b:      ['hrastinski-2008', 's-hl-strohmenger-2008',
                'schlebbe-und-greifeneder-2022', 'zettelkasten-primer']

  per_pdf["bates-2017"]:
    n_a=10, n_b=4, paired=false
    hall_a=9.1%,  hall_b=27.6%,  delta=+18.5pp
    cov_a=67.8%,  cov_b=54.1%,   delta=-13.7pp

Bates ist jetzt Teil des Schnittmengen-Deltas — vorher fiel es komplett heraus (only_a/only_b, nie common_pdfs), JEDES v0.3.143-vs-alt-Paar hätte Bates so weiterhin verloren.

Konsumenten-Analyse

_pdf_group_key ist die SSoT-Gruppierungsfunktion; folgende Konsumenten wurden geprüft (alle beziehen ihren Gruppen-Key direkt oder transitiv aus dieser einen Funktion, kein Konsument dupliziert die Slug-Logik separat):

  • PDF-Dropdown (_dedupe_pdf_options) — Live-Check: genau 1 "Bates"-Option ("Bates - 2017 - Information Behavior").
  • PDF-Tabelle (_calc_pdf_table) — nutzt _pdf_group_key sowohl für Eval-Gruppen als auch für die Routing-Run-Zuordnung; vor dem Fix erzeugte die pdf_key='bates'-Mehrdeutigkeit (2 konkurrierende Eval-Gruppen bates-2017/bates-information-behavior) für v0.3.143 zusätzlich eine 3. Routing-only-Zeile (_calc_pdf_tables "mehrdeutiger Kurz-Key"-Regel, per-PDF-Tabelle: drei Datengrundlagen in einer Zeile, Substring-Doppelzählung, pdf_key-Drift, fehlende PDFs #194 P2) — mechanistisch die dritte der "bis zu 3" U6-Zeilen.
  • Versions×PDF-Matrix (_calc_version_pdf_matrix, _version_pair_compare) — Live-Check: genau 1 Matrix-Zeile "Bates (2017)" (vorher potenziell 2, je nach Versionsauswahl), 1 Zeile "Dhanasekhar (2025)"; keine rohen Alias-Quell-Keys (cobaltite, rl-information) mehr in der Anzeige.
  • Corpus-Overlap-Guard (eval_dashboard_server.py:781, pdf_notesversion_delta) — bekommt durch denselben Fix automatisch konsistente PDF-Zählung für den fix(eval-dashboard): Re-Eval-Dedup je Note in KPI-Aggregation + Corpus-Overlap-Guard fuer Versions-Delta #293-Guard.
  • internal/dashboard/eval_dashboard.html — NICHT angefasst: Frontend hat keine eigene Gruppierungs-/Slug-Logik (geprüft, kein Treffer für pdf_group_key/eigene Slug-Funktion), rendert nur die vom Server bereits kanonisierten Keys/Labels.

Bestehende Tests, die die alte Doppel-Anzeige NICHT testeten, aber zufällig "Bates.pdf" als generischen Platzhalter nutzten (test_pair_matrix_does_not_hardcode_exclude_known_artifact_row, Docstring selbst: "stellvertretend"), wurden auf einen neutralen Namen (Testquelle.pdf) umbenannt, um die Kollision mit dem neuen Alias zu vermeiden — keine Verhaltensänderung am eigentlich Getesteten (#232-Artefaktzeilen-Sichtbarkeit).

RED-Nachweis

6 neue Tests schlugen vor dem Fix exakt wie erwartet fehl:

FAILED test_dedupe_collapses_all_three_bates_drift_variants
FAILED test_group_key_collapses_missing_year_drift_variant     - 'bates-information-behavior' == 'bates-2017'
FAILED test_group_key_collapses_bare_author_drift_variant       - 'bates' == 'bates-2017'
FAILED test_group_key_collapses_rl_information_seeking_quantum_alias - 'rl-information-seeking-quantum' == 'jaiswal-2020'
FAILED test_group_key_collapses_cobaltite_paper_alias            - 'cobaltite-paper' == 'dhanasekhar-2025'
FAILED test_pair_compare_bates_drift_variant_counts_as_common_pdf - [] == ['bates-2017']
6 failed, 1 passed (Guard-Test, muss immer gelten)

Nach dem Fix: alle grün.

Testnachweis

  • generative/tests/test_dashboard_pdf_filter.py + generative/tests/test_dashboard_version_pdf_matrix.py: 60/60 grün.
  • Alle zuvor als potenziell betroffen identifizierten Testdateien (9 Dateien, u. a. test_dashboard_pdf_table.py, test_dashboard_delta_pdf_overlap.py, test_dashboard_hall_kpi.py, test_dashboard_followups.py, test_reeval_baseline_guard.py): 157/157 grün.
  • Volle Suite pytest generative lib/decision_engine/tests shared/tests -q: 6035 passed, 3 skipped, 8 deselected (keine Regressionen).
  • ruff check . + ruff format --check .: clean.

Sichtprüfung (Playwright, firefox-1532-Weg)

Read-only-Kopie der echten Bestandsdaten (Backup-DB + quality_history.jsonl) in .cache/ des Worktrees geladen, Server auf Port 8069, danach Datenkopien gelöscht + Server beendet.

  • PDF-Dropdown (#global-pdf, DOM-Text): genau 1 "Bates"-Option.
  • window._lastData.pair_matrix: genau 1 Zeile mit Key bates-2017 (Label "Bates (2017)"), genau 1 mit Key dhanasekhar-2025; compare["v0.3.130|v0.3.143"].common_pdfs == ["bates-2017"] (und 5 weitere Versionspaare zusätzlich bestätigt).
  • DOM-Gegenprobe: 0 Matrix-Zeilen mit Text "cobaltite" oder "rl-information" (Alias vollständig aufgelöst, keine rohen Keys sichtbar).
  • 0 Page-Errors.

Offene Punkte

  • test-short.pdf bewusst nicht gemergt (s. oben) — falls später doch als Dhanasekhar-Ausschnitt verifizierbar, wäre das ein eigener, separat belegter Alias.
  • Der pre-existierende Mismatch zwischen _PDF_LABELS/_PDF_META (Kurzschlüssel "bates") und _pdf_group_keys Konvention ("bates-2017" mit Jahr) besteht unverändert fort (Matrix-Label fällt für Bates auf den _pdf_short_name-Fallback "Bates (2017)" statt den registrierten Text "Bates 2017" zurück) — vorbestehend, außerhalb dieses PR-Scopes.

U6-Befund (UX-Review 2026-07-15): dieselbe Quelle (Bates - Information
Behavior) stand unter bis zu 3 Schreibweisen nebeneinander im Dashboard.
B3-Befund (Opus-Statistiker-Abnahme PR #305): _version_pair_compare verlor
Bates deshalb still aus common_pdfs -- jedes v0.3.143-vs-alt-Paar zeigte
"kein gemeinsamer PDF-Corpus", obwohl Bates in beiden Versionen evaluiert
wurde. Ursache: _pdf_filter_key erkennt nur Volltitel-Struktur "Autor - Jahr
- Titel"; "Bates - Information Behavior.pdf" (ab v0.3.143, Jahr verloren)
und bare "Bates" (eval_version 1.3) fallen deshalb NICHT auf denselben Slug
wie "bates-2017"/"Bates - 2017 - Information Behavior.pdf".

Fix: _PDF_GROUP_ALIASES-Map in _pdf_group_key (generative/eval_dashboard.py)
-- Post-Slug-Lookup fuer belegte Drift-Varianten, die die bestehende
Autor-Jahr-Slug-Logik nicht erkennt. Jeder Eintrag mit DB-Beleg (run_id-Join
bzw. exakte Note-Titel-Ueberschneidung, s. PR-Body) dokumentiert -- kein
geratener Merge. Reine Anzeige-seitige Kanonisierung, Bestandsdaten
unangetastet; da _pdf_group_key die SSoT-Gruppierungsfunktion fuer
PDF-Dropdown, -Tabelle, Versions×PDF-Matrix UND den Corpus-Overlap-Guard
(eval_dashboard_server.pdf_notes) ist, wirkt der Fix konsistent auf allen
Konsumenten.

Zwei zusaetzliche, gleich gut belegte Drift-Paare (exakte Note-Titel-Treffer
in beiden Runs) im selben Aufwasch mitgenommen: rl-information-seeking-
quantum.pdf -> jaiswal-2020, cobaltite-paper.pdf -> dhanasekhar-2025.
test-short.pdf trotz thematischer Naehe zu Dhanasekhar NICHT gemerged
(Inhalts-Identitaet ohne Quell-PDF-Diff nicht verifizierbar).

Ein bestehender, davon unabhaengiger Test nutzte "Bates.pdf" nur als
generischen Platzhalter (Docstring: "stellvertretend") fuer die
#232-Artefaktzeilen-Sichtbarkeit -- umbenannt auf "Testquelle.pdf", um die
Kollision mit dem neuen Alias zu vermeiden (keine Verhaltensaenderung am
Getesteten).

Tests: 6 neue + 1 angepasst (RED vor dem Fix verifiziert). Volle Suite
(generative, lib/decision_engine/tests, shared/tests): 6035 passed,
3 skipped (unveraendert ggue. vorher). ruff check + format: clean.
internal/dashboard/eval_dashboard.html nicht angefasst (Konsumenten-Analyse:
keine eigene Gruppierungslogik im Frontend). Sichtpruefung (Playwright/
firefox-1532, read-only Kopie der echten Produktionsdaten): PDF-Dropdown
und Versions×PDF-Matrix zeigen Bates/Jaiswal/Dhanasekhar je genau einmal,
0 Page-Errors.
@TillQuandel TillQuandel merged commit 64d8895 into master Jul 16, 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