Parteinamen-Mapper: zentrale app/parteien.py mit kontext-sensitiver normalize_partei() #55

Closed
opened 2026-04-09 10:16:33 +02:00 by tobias · 2 comments
Owner

Problem

Parteinamen werden im Repo an mindestens 6 Stellen erzeugt und konsumiert, ohne zentralen Mapper. Schreibweisen driften zwischen Adapter-Output, bundeslaender.py-Listen, wahlprogramme.py-Keys, wahlprogramme.py-partei-Metafeld, embeddings.py-PROGRAMME-Dict und LLM-Prompts. Konsequenz: Lookup-Misses, stille Fehlmatches, vier identische _normalize_fraktion()-Implementierungen in parlamente.py (DRY-Verstoß), Workaround-Hack in embeddings.py:496.

Bestehende Inkonsistenzen (Auswahl)

Partei bundeslaender.py wahlprogramme.py Keys wahlprogramme.py partei-Feld embeddings.py
Grüne GRÜNE GRÜNE BÜNDNIS 90/DIE GRÜNEN GRÜNE
Linke LINKE LINKE DIE LINKE LINKE
Freie Wähler FW (BY), FREIE WÄHLER (RP) FREIE WÄHLER (RP) FREIE WÄHLER Rheinland-Pfalz FREIE WÄHLER
CSU/SSW/BiW nur in bundeslaender.py

Komplikation: 'Freie Wähler' ist mehrdeutig

Mindestens 5 verschiedene Organisationen mit 'Freie Wähler' im Namen, programmatisch und organisatorisch nicht identisch:

  1. Bundesvereinigung FREIE WÄHLER (Bundespartei seit 2010, Landesvereinigungen in allen 16 BL — z.B. RP-Landesverband)
  2. Landesvereinigung Freie Wähler Bayern (seit 1998, eigene Wählergruppe für bayerische Landtagswahlen, strukturell unabhängig von der Bundespartei)
  3. Bundesverband der Freien Wähler / Landesverband Bayern (alter Dachverband, lehnt das Parteikonstrukt ab)
  4. Freie Wähler Saarland (eigenständige Partei seit 2011, konkurriert mit der Bundesvereinigungs-Landesvereinigung im Saarland)
  5. BVB/FREIE WÄHLER Brandenburg (eigene Partei 'Brandenburger Vereinigte Bürgerbewegung', explizit kein Teil der Partei Freie Wähler — sitzt aktuell als eigene Fraktion im BB-Landtag)

Konsequenz: ein BB-Antrag der BVB/FW-Fraktion darf nicht gegen das RP-FW-Programm gescort werden — das wäre genau die Bug-Klasse 17 (Cross-Bundesland-Zitat), nur eine Pipeline-Stufe früher.

Lösungs-Vorschlag: zentrale app/parteien.py

Neue Datei mit Tabelle als Single Source of Truth + zwei Funktionen normalize_partei(raw, *, bundesland=None) und display_name(canonical, *, long=False). Für mehrdeutige Aliase wie 'FREIE WÄHLER' wird bundesland zur Pflicht (sonst None + log.warning), damit BVB-FW-BB / FW-BAYERN / FW-RLP / FW-SL nicht versehentlich gegeneinander gescort werden.

Kanonische Keys (Vorschlag): CDU, CSU, SPD, GRÜNE, FDP, LINKE, AfD, BSW, SSW, BiW, FW-BAYERN, FW-RLP, BVB-FW-BB, FW-SL.

Acceptance Criteria

  • app/parteien.py mit PARTEIEN-Tabelle + normalize_partei() + display_name()
  • normalize_partei() macht bundesland für mehrdeutige Aliase wie FREIE WÄHLER/FW zur Pflicht
  • Vier _normalize_fraktion()-Methoden in parlamente.py durch zentralen Aufruf ersetzt
  • Workaround embeddings.py:496 entfernt
  • wahlprogramme.find_relevant_quotes() Lookup nutzt normalize_partei()
  • Templates nutzen display_name(p, long=True) für Anzeige
  • Sub-Issue-A test_adapters_live.py Fraktion-Plausibilitäts-Check umgestellt auf normalize_partei()
  • Neue Unit-Tests tests/test_parteien.py mit ≥ 20 Roundtrip-Asserts inkl. Freie-Wähler-Disambiguierung

Bewusst NICHT in scope

  • Keine DB-Migration der existierenden Assessments
  • Keine Umbenennung der wahlprogramme.py-Keys
  • Keine BVB-FW-BB-Programm-Beschaffung (separates Folge-Issue)

Bezug zu offenen Test-Suiten

  • Sub-Issue A (#51): Fraktion-Plausibilität wird viel präziser
  • Sub-Issue D (#54): Cross-Bundesland-Bug-Klasse 17 wird früher in der Pipeline gefangen
  • Sub-Issue C (#53): Wahlprogramm-Lookup wird robust gegen Schreibvarianten
## Problem Parteinamen werden im Repo an mindestens 6 Stellen erzeugt und konsumiert, ohne zentralen Mapper. Schreibweisen driften zwischen Adapter-Output, bundeslaender.py-Listen, wahlprogramme.py-Keys, wahlprogramme.py-partei-Metafeld, embeddings.py-PROGRAMME-Dict und LLM-Prompts. Konsequenz: Lookup-Misses, stille Fehlmatches, vier identische _normalize_fraktion()-Implementierungen in parlamente.py (DRY-Verstoß), Workaround-Hack in embeddings.py:496. ## Bestehende Inkonsistenzen (Auswahl) | Partei | bundeslaender.py | wahlprogramme.py Keys | wahlprogramme.py partei-Feld | embeddings.py | |---|---|---|---|---| | Grüne | GRÜNE | GRÜNE | BÜNDNIS 90/DIE GRÜNEN <Land> | GRÜNE | | Linke | LINKE | LINKE | DIE LINKE <Land> | LINKE | | Freie Wähler | FW (BY), FREIE WÄHLER (RP) | FREIE WÄHLER (RP) | FREIE WÄHLER Rheinland-Pfalz | FREIE WÄHLER | | CSU/SSW/BiW | nur in bundeslaender.py | — | — | — | ## Komplikation: 'Freie Wähler' ist mehrdeutig Mindestens 5 verschiedene Organisationen mit 'Freie Wähler' im Namen, programmatisch und organisatorisch nicht identisch: 1. Bundesvereinigung FREIE WÄHLER (Bundespartei seit 2010, Landesvereinigungen in allen 16 BL — z.B. RP-Landesverband) 2. Landesvereinigung Freie Wähler Bayern (seit 1998, eigene Wählergruppe für bayerische Landtagswahlen, strukturell unabhängig von der Bundespartei) 3. Bundesverband der Freien Wähler / Landesverband Bayern (alter Dachverband, lehnt das Parteikonstrukt ab) 4. Freie Wähler Saarland (eigenständige Partei seit 2011, konkurriert mit der Bundesvereinigungs-Landesvereinigung im Saarland) 5. BVB/FREIE WÄHLER Brandenburg (eigene Partei 'Brandenburger Vereinigte Bürgerbewegung', explizit kein Teil der Partei Freie Wähler — sitzt aktuell als eigene Fraktion im BB-Landtag) Konsequenz: ein BB-Antrag der BVB/FW-Fraktion darf nicht gegen das RP-FW-Programm gescort werden — das wäre genau die Bug-Klasse 17 (Cross-Bundesland-Zitat), nur eine Pipeline-Stufe früher. ## Lösungs-Vorschlag: zentrale app/parteien.py Neue Datei mit Tabelle als Single Source of Truth + zwei Funktionen `normalize_partei(raw, *, bundesland=None)` und `display_name(canonical, *, long=False)`. Für mehrdeutige Aliase wie 'FREIE WÄHLER' wird `bundesland` zur Pflicht (sonst None + log.warning), damit BVB-FW-BB / FW-BAYERN / FW-RLP / FW-SL nicht versehentlich gegeneinander gescort werden. Kanonische Keys (Vorschlag): CDU, CSU, SPD, GRÜNE, FDP, LINKE, AfD, BSW, SSW, BiW, FW-BAYERN, FW-RLP, BVB-FW-BB, FW-SL. ## Acceptance Criteria - [ ] app/parteien.py mit PARTEIEN-Tabelle + normalize_partei() + display_name() - [ ] normalize_partei() macht bundesland für mehrdeutige Aliase wie FREIE WÄHLER/FW zur Pflicht - [ ] Vier _normalize_fraktion()-Methoden in parlamente.py durch zentralen Aufruf ersetzt - [ ] Workaround embeddings.py:496 entfernt - [ ] wahlprogramme.find_relevant_quotes() Lookup nutzt normalize_partei() - [ ] Templates nutzen display_name(p, long=True) für Anzeige - [ ] Sub-Issue-A test_adapters_live.py Fraktion-Plausibilitäts-Check umgestellt auf normalize_partei() - [ ] Neue Unit-Tests tests/test_parteien.py mit ≥ 20 Roundtrip-Asserts inkl. Freie-Wähler-Disambiguierung ## Bewusst NICHT in scope - Keine DB-Migration der existierenden Assessments - Keine Umbenennung der wahlprogramme.py-Keys - Keine BVB-FW-BB-Programm-Beschaffung (separates Folge-Issue) ## Bezug zu offenen Test-Suiten - Sub-Issue A (#51): Fraktion-Plausibilität wird viel präziser - Sub-Issue D (#54): Cross-Bundesland-Bug-Klasse 17 wird früher in der Pipeline gefangen - Sub-Issue C (#53): Wahlprogramm-Lookup wird robust gegen Schreibvarianten
Author
Owner

Phase B aus Roadmap #59 deployed (Commit eb045d0).

  • app/parteien.py mit 14 Einträgen + FW-Familien-Disambiguierung
  • 4 Adapter-Methoden in app/parlamente.py durch zentralen Shim ersetzt (~120 Zeilen Duplikation entfernt)
  • embeddings.py Workaround-Hack entfernt
  • 52 neue Unit-Tests in tests/test_parteien.py + 4 Adapter-Roundtrip-Tests

157 Unit-Tests grün. Live verifiziert: NRW-Search liefert weiterhin Daten.

Phase B aus Roadmap #59 deployed (Commit `eb045d0`). - `app/parteien.py` mit 14 Einträgen + FW-Familien-Disambiguierung - 4 Adapter-Methoden in `app/parlamente.py` durch zentralen Shim ersetzt (~120 Zeilen Duplikation entfernt) - `embeddings.py` Workaround-Hack entfernt - 52 neue Unit-Tests in `tests/test_parteien.py` + 4 Adapter-Roundtrip-Tests 157 Unit-Tests grün. Live verifiziert: NRW-Search liefert weiterhin Daten.
Author
Owner

Erledigt durch Roadmap-Phase B / Commit eb045d0. app/parteien.py mit 14 PARTEIEN-Einträgen, normalize_partei() mit FW-Familien-Disambiguierung, extract_fraktionen() als Funnel für die 4 alten Adapter-Methoden. 52 neue Unit-Tests, Live verifiziert. Adapter-Migration komplett, embeddings.py-Hack entfernt.

Erledigt durch Roadmap-Phase B / Commit eb045d0. app/parteien.py mit 14 PARTEIEN-Einträgen, normalize_partei() mit FW-Familien-Disambiguierung, extract_fraktionen() als Funnel für die 4 alten Adapter-Methoden. 52 neue Unit-Tests, Live verifiziert. Adapter-Migration komplett, embeddings.py-Hack entfernt.
Sign in to join this conversation.
No description provided.