gwoe-antragspruefer/tests
Dotty Dotter b76c08d92e Sub-D Citation-Test: PDF-Bindestrich + Token-Resolver + Anker-Match
Erster Live-Run von Sub-Issue D gegen die Prod-DB im Container hat 15 von
39 Citation-Tests fehlschlagen lassen. Detail-Analyse: 12 davon waren
Test-False-Positives (zwei Schichten von Brittleness im Test selbst), 3
sind echte LLM-Halluzinationen.

Drei Härtungen am Test-Resolver, damit er nur noch echte Halluzinationen
fängt:

1. **PDF-Bindestrich-Bridging in `_normalize`**:
   PyMuPDF zerlegt Wörter über Zeilenumbrüche mit `-\n`. Nach unserer
   Whitespace-Normalisierung wird daraus `- `, sodass aus
   "Investitionsoffensive" im LLM-Snippet das PDF "investiti- onsoffensive"
   gegenübersteht. Neue Regex `_RE_HYPHEN_BREAK` bridged das in einem
   Konvergenz-Loop, damit auch mehrere aufeinanderfolgende Wort-Wraps
   sauber verschmelzen.

2. **Token-Coverage-Resolver in `_resolve_quelle_to_programm_id`**:
   Zwei-stufig — erst die alte strict-substring-Strategie (deckt
   Adapter-konformes LLM-Output), dann ein Token-Coverage-Fallback. Der
   zerlegt jeden PROGRAMME-Namen in (Partei + Bundesland + Jahr) mit
   Aliasen (GRÜNE/Bündnis 90, LSA/Sachsen-Anhalt, …) und akzeptiert
   eine Quelle, wenn alle drei Tokens in irgendeiner Reihenfolge in der
   Quelle vorkommen. Fängt damit z.B. "Landtagswahlprogramm 2021 BÜNDNIS
   90/DIE GRÜNEN Sachsen-Anhalt" → `gruene-lsa-2021`, ohne dass die LLM
   den exakten Adapter-Label-Wortlaut treffen muss.

3. **Anker-Match-Fallback in `_is_substring`**:
   Ein 200-Zeichen-Snippet, das nur in einem Wort kürzt, scheitert sonst
   am Volltext-Substring-Check. Neuer Anker-Match zerlegt den Snippet
   in 5-Wort-Sequenzen und akzeptiert, wenn mindestens eine wortwörtlich
   im Seitentext steht. Erfundene Snippets haben keine 5-Wort-Sequenz,
   die wortwörtlich im PDF steht — die false-negative-Rate für echte
   Halluzinationen bleibt damit bei 0.

Live-Run nach dem Patch: **15 → 3 Failures** (39 Cases, 24 → 36 grüne).
Die verbleibenden 3 sind echte LLM-Bugs:

- 18/9605 NRW GRÜNE S.58 ('Wahlalter auf 16/14 absenken') — Snippet
  und PDF-Seite zeigen komplett andere Themen, das LLM hat die Seite
  oder den Snippet erfunden
- 18/18100 NRW B90/Grüne S.36 (Grundsatzprogramm 2020, Plattform-
  Regulierung)
- 8/6645 LSA SPD S.37 ('Wir Sozialdemokratinnen ächten ...') — PDF
  S.37 enthält dort Zweitstudiengebühren-Text

Diese drei werden als separates LLM-Bug-Issue erfasst.

13 Helper-Unit-Tests bleiben grün.

Refs: #54, #59 (Sub-D Live-Verifikation)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 11:36:02 +02:00
..
integration Sub-D Citation-Test: PDF-Bindestrich + Token-Resolver + Anker-Match 2026-04-09 11:36:02 +02:00
__init__.py Add pytest suite + fix two regex bugs uncovered by it (#46) 2026-04-08 23:26:06 +02:00
conftest.py Add pytest suite + fix two regex bugs uncovered by it (#46) 2026-04-08 23:26:06 +02:00
test_analyzer.py Add pytest suite + fix two regex bugs uncovered by it (#46) 2026-04-08 23:26:06 +02:00
test_auswertungen.py Phase C: Auswertungen-Dashboard #58 + CSV-Export #45 (Roadmap #59) 2026-04-09 11:25:57 +02:00
test_bundeslaender.py Activate Baden-Württemberg via PARLISAdapter (#29, Phase 1) 2026-04-08 23:38:04 +02:00
test_embeddings.py Add pytest suite + fix two regex bugs uncovered by it (#46) 2026-04-08 23:26:06 +02:00
test_main_validators.py Phase A: Audit-Restbefunde #57.3/4/7 (Roadmap #59) 2026-04-09 11:15:16 +02:00
test_parlamente.py Phase B: Parteinamen-Mapper #55 (Roadmap #59) 2026-04-09 11:22:13 +02:00
test_parteien.py Phase B: Parteinamen-Mapper #55 (Roadmap #59) 2026-04-09 11:22:13 +02:00
test_report.py Security hotfixes #1, #2, #6 from audit (#57) 2026-04-09 10:45:43 +02:00
test_wahlprogramme.py Add pytest suite + fix two regex bugs uncovered by it (#46) 2026-04-08 23:26:06 +02:00