fix(shared): PDF-Pfade mit Apostroph-Varianten ueber Glob-Fallback aufloesen#214
Merged
Conversation
…floesen (closes #186) Typografischer Apostroph (U+2019) vs. gerades ' im PDF-Pfad liess die Existenz-Pruefung an 3 Stellen (extractive/orchestrator.py, generative/eval_chunk_recall.py, generative/gui/app.py) mit einer nackten "PDF nicht gefunden"-Meldung scheitern -- ohne erkennbar zu machen, welches Zeichen das Matching bricht. Neuer Helper shared/path_safety.resolve_source_path(): bei exaktem Treffer unveraendert zurueckgegeben; sonst Glob-Fallback im selben Verzeichnis mit Apostroph-/Anfuehrungszeichen-Varianten (' U+2019 U+2018 ` U+00B4) als Wildcard (Rest via glob.escape). Genau 1 Treffer -> verwenden + Hinweis auf stderr; 0 oder >1 Treffer -> FileNotFoundError mit repr(str(source)) und bei Mehrdeutigkeit den Kandidaten. Alle 3 Aufrufer auf try/except umgestellt.
…hestrator-CLI-Pfad angeschlossen (#186 Nachbesserung)
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
PDF-Pfade mit typografischem Apostroph (U+2019) statt geradem
'(oder umgekehrt) liessen die Existenz-Pruefung an 3 Stellen mit einer nacktenFehler: PDF nicht gefunden-Meldung scheitern -- ohne Diagnose, welches Zeichen das Matching bricht:extractive/orchestrator.py:76generative/eval_chunk_recall.py:213generative/gui/app.py:784Fix-Ansatz
Neuer Helper
shared/path_safety.resolve_source_path(source) -> Path(importierbar vonextractiveUNDgenerative, dashared/bereits von beiden genutzt wird):sourceexakt: unveraendert zurueckgeben.' ’ ‘ \´) im Dateinamen werden durch?ersetzt (Rest viaglob.escape`), Kandidaten danach strikt nachgefiltert (siehe Nachbesserung Punkt 1).FileNotFoundErrormitrepr(str(source)), bei Mehrdeutigkeit inkl. Kandidatenliste.Alle Aufrufer auf
try: resolve_source_path(...) / except FileNotFoundErrorumgestellt (Fehlertext bleibt je Aufrufer im bisherigen Format:sys.exit,print+return 1,JSONResponse). Die Funktion wirftFileNotFoundErrormit fertig formatierter Meldung, damit alle Aufrufer denselben Text bekommen statt ihn zu duplizieren (SSoT).In
generative/gui/app.pywirdpdfnach erfolgreicher Aufloesung auf den resolvten String gesetzt, damit ein Glob-Fallback-Treffer auch tatsaechlich fuer den Pipeline-Lauf (nicht nur fuer die Fehlermeldung) verwendet wird.Bekannte Grenze
Apostroph-/Anfuehrungszeichen-Varianten im Verzeichnisnamen selbst (nicht im Dateinamen) werden nicht geheilt -- der Glob-Fallback sucht nur innerhalb von
path.parent, nicht rekursiv ueber Verzeichnis-Namensvarianten. In diesem Fall bleibt es bei derrepr()-Diagnose (kein automatischer Fallback), analog zum Verhalten bei fehlenden Dateien.RED-Beweis (vor dem Fix)
shared/tests/test_path_safety.pyimportierte die noch nicht existierende Funktion:Tests
6 Tests in
shared/tests/test_path_safety.py(tmp_path-Fixture): exakter Treffer, gerader Apostroph findet Datei mit U+2019 und umgekehrt, Fehlermeldung enthaeltrepr(str(source)), Mehrdeutigkeit listet beide Kandidaten, kein Fallback ohne Apostroph-Zeichen im Namen. Plus die Nachbesserungs-Tests unten.Cross-Model-Review (Mistral magistral-medium-latest)
1 Fund (niedrig,
generative/gui/app.py): Vorschlag, den stderr-Fallback-Hinweis zusaetzlich in die JSONResponse aufzunehmen. Der von Mistral gezeigte "korrigierte" Code war identisch zum Original -> laut Fake-Fund-Kriterium verworfen. 0 reale Funde, 0 Fixes noetig.Nachbesserung (Cross-Model-Review Fable+Qwen, 3x konvergent + Runtime-Pruefung)
Drei extern verifizierte Funde nachgebessert:
resolve_source_path: Das?-Glob matcht JEDES Zeichen, nicht nur Quote-Varianten -- real belegt anPorstXs-Buch.pdf/Porst_s-Buch.pdf/Porst5s-Buch.pdf, die bei einer Apostroph-Query faelschlich als "Apostroph-Variante" durchgingen; auch Verzeichnisse zaehlten als Kandidat. Fix: Kandidaten nach dem Glob zusaetzlich streng gefiltert -- Name muss nach Normalisierung aller Quote-Zeichen exakt dem normalisierten Query-Namen entsprechen, plusis_file()-Filter. 4 neue RED-Tests (3 Fehlmatch-Faelle + Verzeichnis-Fall).generative/orchestrator.py(Haupt-CLI-Pfad,--sourceohne--load-drafts): nutzte noch einen nacktensys.exit(f"Datei nicht gefunden: {source_path}")stattresolve_source_path-- dieselbe Bugklasse wie die 3 im Issue genannten Stellen, dort im Review uebersehen. Jetzt aufresolve_source_pathumgestellt (gleiches Muster wie die anderen 3 Stellen; Hunk bewusst minimal wegen paralleler orchestrator-PRs fix(generative): Timeout-Retry im legacy-Profil + verlorene Konzepte sichtbar (#210) #216/fix(generative): pipeline_runs-Insert vom Inline-Eval entkoppeln + Test-Traces nach tmp (#198 P1+P2) #218/feat(generative): Stage-Outcome-Events + Drop-Gründe an den Gate-Punkten (#197 Schritt 1+2) #220). 2 neue Tests (test_orchestrator_source_resolution.py, mit autouse-Fixture gegen_LLM_RUNTIME_SETTINGS-Leak:orchestrator.mainsetzt sonst globalen Backend-State, dertest_phoenix_span.pybricht).generative/gui/app.py:resolve_source_pathlief vor dem_allowed_roots-Check -- der Glob-Fallback haette so Verzeichnisse ausserhalb der erlaubten Roots durchsuchen koennen (Defense-in-Depth-Aufweichung, im Threat-Model toleriert aber unnoetig). Fix: Root-Check auf den Elternordner des rohen Pfads laeuft jetzt VORresolve_source_path; der bestehende Check auf den aufgeloesten Pfad bleibt zusaetzlich bestehen. 1 neuer Test (spy aufresolve_source_path, darf fuer nicht-erlaubte Verzeichnisse nicht aufgerufen werden).Suite-Ergebnis (nach Nachbesserung)
pytest generative lib/decision_engine/tests shared/tests -q: 5706 passed, 0 failed, 3 skipped, 4 deselected (5699 vom bisherigen PR-Stand + 7 Nachbesserungs-Tests).ruff format --check .undruff check .: sauber.Hinweis: Das Haupt-venv hat den
extractive-Extra (pdfplumber/gliner) nicht installiert -- vorbestehend, nicht Teil dieses Fixes;extractive/testsist entsprechend nicht Teil der kanonischen Suite (AGENTS.md).Closes #186