fix(enrich): roh-extrahierter DOI übersteht CrossRef-Fehlschlag (#282) - #299
Merged
Conversation
Ein per Regex im Kopfbereich gefundener, format-valider DOI ging bisher komplett verloren, wenn CrossRef ihn nicht kennt — betrifft strukturell alle DataCite-registrierten DOIs (peDOCS, edoc.hu-berlin.de u.ä.), da CrossRef diese grundsätzlich nicht führt (keine transiente Störung, sondern eine Registry-Lücke). Der Quality-Agent setzte dadurch fälschlich das Flag "kein DOI", obwohl der DOI wörtlich im Dokument stand und geloggt wurde; die #263-Durchreiche-Kette blieb für diese Quellenklasse wirkungslos. Fix: enrich() merkt sich den Stage-1-Rohtreffer (_raw_doi) und übernimmt ihn am Ende in meta["doi"], falls keine spätere Stage (Zotero-Dateiname, Titelsuche) selbst einen DOI geliefert hat. Kein doi_from_title-Marker — das ist keine Titel-Heuristik, sondern eine harte, wörtliche Quelle. Überschreibt nie einen bereits gesetzten (auch titel-geratenen) DOI, damit die #263-Provenienz-Markierung unangetastet bleibt. orchestrator.py/quality.py mussten nicht angefasst werden: die #263-Durchreiche-Kette (orchestrator.py ~2083) und das "kein DOI"-Flag (quality.py:138, nur bei doi=None) funktionieren bereits korrekt, sobald enrich() den DOI liefert. Tests: 3 neue Fälle in test_pdf_enrich.py (Positivfall DataCite-DOI, Negativkontrolle ohne Format-Treffer, #263-Gegenprobe: Titel-geratener DOI wird nicht überschrieben). Volle Suite 5956 passed/3 skipped/8 deselected, ruff clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Der Quality-Agent fragt für die DOI-Auflösung ausschließlich⚠️ kein DOI", obwohl der DOI wörtlich im Dokument stand und beim Enrichment geloggt wurde.
api.crossref.orgab. Wenn ein direkt aus dem PDF-Text extrahierter, format-valider DOI bei CrossRef nicht auflösbar ist, ging er bisher komplett verloren — die Note trug fälschlich das Flag „Betrifft strukturell alle DataCite-registrierten DOIs (z. B. deutsche Repositorien wie peDOCS oder edoc.hu-berlin.de) — keine transiente Störung, sondern eine Registry-Lücke: CrossRef kennt DataCite-DOIs grundsätzlich nicht.
Beleg aus der Testlauf-Serie (siehe Issue):
10.25656/01:11173(peDOCS) im PDF-Text gefunden und geloggt, CrossRef-Lookup lieferte nichts → alle 5 Notes fälschlich „kein DOI".10.18452/35926(HU-Berlin, DataCite-Präfix), websuch-verifiziert, aber CrossRef-only-Abfrage findet ihn strukturell nicht → alle 5 Notes fälschlich „kein DOI".Ursache
generative/tools/pdf_enrich.py::enrich(), Stage 1:extract_doi(header_text)findet den DOI per Regex und loggt ihn, aber wenncrossref_lookup(doi)Noneliefert (oder unvollständige Daten), wurde der Roh-Treffer nirgends zwischengespeichert. Lieferte eine spätere Stage (z. B. Stage 5, Zotero-Dateiname) Autor/Titel/Jahr ohne eigenen DOI, bliebmeta["doi"]leer →quality.check_quality(doi=None, ...)setzt das „kein DOI"-Flag (quality.py:138) → die #263-Durchreiche-Kette (orchestrator.py, Stage 0) hatte strukturell nie eine Chance, weil ihr Input bereits leer war.Fix
enrich()merkt sich den Stage-1-Rohtreffer (_raw_doi) und übernimmt ihn am Ende inmeta["doi"], falls keine spätere Stage selbst einen DOI geliefert hat. Keindoi_from_title-Marker — das ist keine Titel-Heuristik (#263), sondern eine harte, wörtliche Quelle. Überschreibt nie einen bereits gesetzten (auch titel-geratenen) DOI, damit die #263-Provenienz-Markierung unangetastet bleibt.orchestrator.py/quality.pymussten nicht angefasst werden: die #263-Durchreiche-Kette (orchestrator.py~2083, verschoben durch den zwischenzeitlichen #280/#281-Merge, Logik unverändert) und das „kein DOI"-Flag (quality.py:138, nur beidoi=None) funktionieren bereits korrekt, sobaldenrich()einen DOI liefert — das war exakt die Lücke.Bewusst nicht umgesetzt: DataCite als Zweit-Registry
Das Issue nennt als Fix-Richtung „…und/oder zusätzlich DataCite als zweite Registry-Quelle abfragen". Das würde zusätzlich Peer-Review-Signal/Zitationszahl/CrossRef-Cross-Check auch für DataCite-DOIs liefern (aktuell bleiben
peer_reviewed/citation_countfür sieNone). Bewusst ausgeklammert, weil:grep -ri datacitefand nur die neuen Kommentare/Tests dieses Fixes).Vorschlag: eigenes Folge-Issue für „DataCite als Zweit-Registry im Quality-Agent" (Sandbox
api.test.datacite.orgzum Schema-Verifizieren nutzen), falls das Peer-Review-/Zitations-Signal für diese Quellenklasse gewünscht ist.Verwertung der Vorarbeit
Der Worktree enthielt bereits unfertige, uncommittete Arbeit an
pdf_enrich.py+test_pdf_enrich.pyaus einer abgebrochenen Session. Diff geprüft: deckt sich exakt mit der im Issue vorgeschlagenen Fix-Richtung (Format-Validierung statt Registry-Bestätigung als Mindestkriterium) und respektiert die #263-Provenienz-Semantik. Übernommen und eigenständig verifiziert (siehe Testnachweis unten) — keine Änderungen an der Vorarbeit nötig.Testnachweis
RED (Fix gestasht, nur neue Tests gegen alten Code):
(Die zwei Kontroll-Tests sind by design bereits vorher grün — Negativkontrolle und #263-Gegenprobe greifen nicht in den gefixten Pfad ein.)
GREEN (Fix zurückgeholt):
test_pdf_enrich.py92 passed.Volle Suite (
generative lib/decision_engine/tests shared/tests): 5956 passed, 3 skipped, 8 deselected (441s).ruff (geänderte Dateien):
ruff check— All checks passed.ruff format --check— 2 files already formatted.Offene Punkte
git checkout -B ... origin/masterauf den aktuellen master (1e3b035, inkl. [MITTEL] Stiller Konzeptverlust via <!--END--> ohne Retry — traf Kernkonzepte in 3 von 6 Läufen #280/[MITTEL] Lauf mit Totalverlust endet mit "Fertig."/Exit 0 — Fehlersignal nur in stderr #281/fix: Retry bei stillem <!--END-->-Drop + unterscheidbarer Exit-Code bei Totalverlust (#280, #281) #297) gehoben — konfliktfrei, da die zwischenzeitlichen Commitspdf_enrich.py/test_pdf_enrich.pynicht berührten (nurorchestrator.py, unbetroffener Bereich).Fixes #282