gwoe-antragspruefer/app/wahlprogramme.py
Dotty Dotter 4e7f7dac25 chore: konsolidiere Working-Tree mit dev-Stand nach Nextcloud-Sync-Resolution
Mehrtaegiger Sync-Stillstand hatte ueber 50 conflicted-copy-Dateien im
Working-Tree erzeugt. Die jeweils neuere Version wurde basierend auf
md5-Hash-Vergleich zum laufenden gwoe-antragspruefer-dev-Container
eingespielt.

Konsolidiert (38 modifiziert):
- analyzer.py, auswertungen.py, auth.py, config.py, database.py,
  drucksache_typen.py, embeddings.py, main.py, models.py, parlamente.py,
  ports/llm_bewerter.py, presse_generator.py, redline_utils.py, report.py,
  validators.py, wahlprogramm_fetch.py, wahlprogramm-links.yaml,
  wahlprogramm-shas.lock.json
- v2-Templates: base, components/{icon, matrix_mini, queue_widget,
  result_row}, screens/{admin_queue, admin_stand, aktuelle-themen,
  antrag_detail, auswertungen, cluster, landtag_suche, merkliste,
  methodik, tags}, static/v2/v2.css
- Tests: test_embeddings (Strict-Mode-Drop in reconstruct_zitate),
  test_endpoints_smoke, test_presse_generator, test_report,
  test_wahlprogramme (mit TestRegierungsbildung-Block, +120 LOC)
- docker-compose.dev.yml, docs/adr/index.md, docs/reference/api.md, mkdocs.yml

Neuzugaenge:
- app/marker.py, app/pm_render.py — Konsistenz-Marker, PM-Render-Adapter
- app/templates/v2/screens/scorecard{,_portrait,_werkstatt}.html — Cloud-Design-Scorecard
- app/static/v3/, app/templates/v3/ — v3-Layout-Hierarchie
- docs/adr/0010-stimmverhalten-gwoe-aggregat.md
- docs/adr/0011-aktuelle-themen-pm-generator.md
- docs/adr/0012-debug-auth-token-bypass.md
- scripts/{auto-rate-orphans, pm-quality-audit, pm-sample-bundle, rotate-debug-token}.sh
- tests/e2e/test_smoke_browser.py, tests/test_{auto_rate_runs, icons,
  marker, pm_render, presse_generator_style, thread_splitter,
  v2_pdf_consistency}.py

Plus inhaltlich uebernommen aus dem Conflict-Stand:
- embeddings.py: fw-by-2023.partei korrigiert von "FW" zu "FREIE WAEHLER"
  (war Mismatch zu wahlprogramme.py)
- embeddings.py: detailliertere Naming der BTW-2025-Wahlprogramme

Test-Suite-Stand: 1209 passed, 73 skipped (4 pre-existing failures in
test_presse_generator_style.py + 1 collection error in
integration/test_citations_substring.py — beide nicht durch dieses
Konsolidierungs-Commit verursacht).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 00:19:41 +02:00

403 lines
33 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Wahlprogramm-Referenzsystem mit Zitaten und Seitenreferenzen.
Bundesland-bewusst seit Issue #5: ``WAHLPROGRAMME[bundesland][partei]`` statt
flach. Konsumiert ``BUNDESLAENDER`` aus ``bundeslaender.py`` für die
Regierungsfraktionen-Lookup und für Plausibilitätsprüfungen.
Verantwortlich für die schlüsselwortbasierte Fallback-Suche in den
paged-Textversionen der Wahlprogramme. Die semantische Suche lebt in
``embeddings.py``.
"""
import re
from pathlib import Path
from typing import Optional
from .bundeslaender import BUNDESLAENDER
# WAHLPROGRAMME[bundesland][partei] -> Metadaten
#
# Pflichtfelder: file, titel, partei, jahr, seiten
# Geltungsdaten: regierungsbildung (ISO YYYY-MM-DD) — Tag der Vereidigung der
# Regierung, die nach der Wahl aus diesem Programm hervorging.
# NICHT das Wahldatum: das Programm wird mit der Regierungs-
# bildung wirksam (Koalitionsvertrag, Kabinett vereidigt).
# regierungsende (ISO YYYY-MM-DD oder None) — Ende der
# Regierungs-Geltung. ``None`` = aktuell laufende Regierung.
#
# Beim Hinzufügen eines neuen Bundeslands: Eintrag hier UND parallel
# in WAHLPROGRAMM_KONTEXT_FILES.
WAHLPROGRAMME: dict[str, dict[str, dict]] = {
# NRW — LTW 15.05.2022. Kabinett Wüst II (CDU+GRÜNE) vereidigt 29.06.2022.
"NRW": {
"CDU": {"file": "cdu-nrw-2022.pdf", "titel": "Machen, worauf es ankommt", "partei": "CDU NRW", "jahr": 2022, "seiten": 109, "regierungsbildung": "2022-06-29", "regierungsende": None},
"SPD": {"file": "spd-nrw-2022.pdf", "titel": "Unser Land von morgen", "partei": "SPD NRW", "jahr": 2022, "seiten": 116, "regierungsbildung": "2022-06-29", "regierungsende": None},
"GRÜNE": {"file": "gruene-nrw-2022.pdf","titel": "Von hier an Zukunft", "partei": "BÜNDNIS 90/DIE GRÜNEN NRW", "jahr": 2022, "seiten": 100, "regierungsbildung": "2022-06-29", "regierungsende": None},
"FDP": {"file": "fdp-nrw-2022.pdf", "titel": "Nie gab es mehr zu tun", "partei": "FDP NRW", "jahr": 2022, "seiten": 96, "regierungsbildung": "2022-06-29", "regierungsende": None},
"AfD": {"file": "afd-nrw-2022.pdf", "titel": "Wer sonst.", "partei": "AfD NRW", "jahr": 2022, "seiten": 68, "regierungsbildung": "2022-06-29", "regierungsende": None},
},
# Sachsen-Anhalt — LTW 06.06.2021. Kabinett Haseloff III (CDU+SPD+FDP) vereidigt 16.09.2021.
"LSA": {
"CDU": {"file": "cdu-lsa-2021.pdf", "titel": "Unsere Heimat. Unsere Verantwortung.", "partei": "CDU Sachsen-Anhalt", "jahr": 2021, "seiten": 82, "regierungsbildung": "2021-09-16", "regierungsende": None},
"SPD": {"file": "spd-lsa-2021.pdf", "titel": "Zusammenhalt und neue Chancen. Politik fürs ganze Land", "partei": "SPD Sachsen-Anhalt", "jahr": 2021, "seiten": 77, "regierungsbildung": "2021-09-16", "regierungsende": None},
"GRÜNE": {"file": "gruene-lsa-2021.pdf","titel": "Verlässlich für Sachsen-Anhalt", "partei": "BÜNDNIS 90/DIE GRÜNEN Sachsen-Anhalt","jahr": 2021, "seiten": 164,"regierungsbildung": "2021-09-16", "regierungsende": None},
"FDP": {"file": "fdp-lsa-2021.pdf", "titel": "Wahlprogramm der FDP Sachsen-Anhalt zur Landtagswahl 2021", "partei": "FDP Sachsen-Anhalt", "jahr": 2021, "seiten": 76, "regierungsbildung": "2021-09-16", "regierungsende": None},
"AfD": {"file": "afd-lsa-2021.pdf", "titel": "Alles für unsere Heimat! Programm der AfD Sachsen-Anhalt zur Landtagswahl 2021","partei": "AfD Sachsen-Anhalt", "jahr": 2021, "seiten": 64, "regierungsbildung": "2021-09-16", "regierungsende": None},
"LINKE": {"file": "linke-lsa-2021.pdf", "titel": "Wahlprogramm zur Landtagswahl 2021", "partei": "DIE LINKE Sachsen-Anhalt", "jahr": 2021, "seiten": 88, "regierungsbildung": "2021-09-16", "regierungsende": None},
},
# Mecklenburg-Vorpommern — LTW 26.09.2021. Kabinett Schwesig II (SPD+LINKE) vereidigt 15.11.2021.
"MV": {
"CDU": {"file": "cdu-mv-2021.pdf", "titel": "Zusammen. Den Blick nach vorn. Gemeinsam die Zukunft meistern", "partei": "CDU Mecklenburg-Vorpommern", "jahr": 2021, "seiten": 56, "regierungsbildung": "2021-11-15", "regierungsende": None},
"SPD": {"file": "spd-mv-2021.pdf", "titel": "Verantwortung für heute und morgen — Regierungsprogramm 20212026", "partei": "SPD Mecklenburg-Vorpommern", "jahr": 2021, "seiten": 95, "regierungsbildung": "2021-11-15", "regierungsende": None},
"GRÜNE": {"file": "gruene-mv-2021.pdf","titel": "Für Klima, Land und ein besseres Miteinander", "partei": "BÜNDNIS 90/DIE GRÜNEN Mecklenburg-Vorpommern","jahr": 2021, "seiten": 88, "regierungsbildung": "2021-11-15", "regierungsende": None},
"FDP": {"file": "fdp-mv-2021.pdf", "titel": "Wahlprogramm der Freien Demokraten Mecklenburg-Vorpommern zur Landtagswahl 2021","partei": "FDP Mecklenburg-Vorpommern", "jahr": 2021, "seiten": 120,"regierungsbildung": "2021-11-15", "regierungsende": None},
"AfD": {"file": "afd-mv-2021.pdf", "titel": "Landeswahlprogramm der AfD Mecklenburg-Vorpommern 2021", "partei": "AfD Mecklenburg-Vorpommern", "jahr": 2021, "seiten": 84, "regierungsbildung": "2021-11-15", "regierungsende": None},
"LINKE": {"file": "linke-mv-2021.pdf", "titel": "Das ist links! — Zukunftsprogramm für Mecklenburg-Vorpommern", "partei": "DIE LINKE Mecklenburg-Vorpommern", "jahr": 2021, "seiten": 82, "regierungsbildung": "2021-11-15", "regierungsende": None},
},
# Berlin — AGH-Wahl 26.09.2021, Wiederholungswahl 12.02.2023. Senat Wegner I (CDU+SPD) vereidigt 27.04.2023.
"BE": {
"CDU": {"file": "cdu-be-2023.pdf", "titel": "Unser Berlin. Mehr geht nur gemeinsam. — Berlin-Plan der CDU Berlin 20212026", "partei": "CDU Berlin", "jahr": 2021, "seiten": 135, "regierungsbildung": "2023-04-27", "regierungsende": None},
"SPD": {"file": "spd-be-2023.pdf", "titel": "Ganz sicher Berlin — Wahlprogramm der SPD Berlin zur Abgeordnetenhauswahl 2021", "partei": "SPD Berlin", "jahr": 2021, "seiten": 86, "regierungsbildung": "2023-04-27", "regierungsende": None},
"GRÜNE": {"file": "gruene-be-2023.pdf","titel": "Unser Plan für Berlin — Landeswahlprogramm BÜNDNIS 90/DIE GRÜNEN Berlin 2021", "partei": "BÜNDNIS 90/DIE GRÜNEN Berlin", "jahr": 2021, "seiten": 280, "regierungsbildung": "2023-04-27", "regierungsende": None},
"LINKE": {"file": "linke-be-2023.pdf", "titel": "rot. radikal. realistisch. — Unser Programm für die soziale Stadt", "partei": "DIE LINKE Berlin", "jahr": 2021, "seiten": 130, "regierungsbildung": "2023-04-27", "regierungsende": None},
"AfD": {"file": "afd-be-2023.pdf", "titel": "Wahlprogramm der AfD Berlin für die Wahl des Abgeordnetenhauses am 26. September 2021","partei": "AfD Berlin", "jahr": 2021, "seiten": 166, "regierungsbildung": "2023-04-27", "regierungsende": None},
},
# Thüringen — LTW 01.09.2024. Kabinett Voigt I (CDU+BSW+SPD, Brombeer) vereidigt 12.12.2024.
"TH": {
"CDU": {"file": "cdu-th-2024.pdf", "titel": "Wahlprogramm der CDU Thüringen 2024", "partei": "CDU Thüringen", "jahr": 2024, "seiten": 83, "regierungsbildung": "2024-12-12", "regierungsende": None},
"AfD": {"file": "afd-th-2024.pdf", "titel": "AfD Thüringen Landtagswahlprogramm 2024","partei": "AfD Thüringen", "jahr": 2024, "seiten": 100, "regierungsbildung": "2024-12-12", "regierungsende": None},
"LINKE": {"file": "linke-th-2024.pdf", "titel": "DIE LINKE Thüringen Wahlprogramm 2024", "partei": "DIE LINKE Thüringen", "jahr": 2024, "seiten": 100, "regierungsbildung": "2024-12-12", "regierungsende": None},
"BSW": {"file": "bsw-th-2024.pdf", "titel": "BSW Thüringen Wahlprogramm 2024", "partei": "BSW Thüringen", "jahr": 2024, "seiten": 50, "regierungsbildung": "2024-12-12", "regierungsende": None},
"SPD": {"file": "spd-th-2024.pdf", "titel": "SPD Thüringen Wahlprogramm 2024", "partei": "SPD Thüringen", "jahr": 2024, "seiten": 100, "regierungsbildung": "2024-12-12", "regierungsende": None},
},
# Brandenburg — LTW 22.09.2024. Kabinett Woidke III (SPD+BSW) vereidigt 11.12.2024.
"BB": {
"SPD": {"file": "spd-bb-2024.pdf", "titel": "SPD Brandenburg Wahlprogramm 2024", "partei": "SPD Brandenburg", "jahr": 2024, "seiten": 100, "regierungsbildung": "2024-12-11", "regierungsende": None},
"AfD": {"file": "afd-bb-2024.pdf", "titel": "AfD Brandenburg Wahlprogramm 2024", "partei": "AfD Brandenburg", "jahr": 2024, "seiten": 100, "regierungsbildung": "2024-12-11", "regierungsende": None},
"CDU": {"file": "cdu-bb-2024.pdf", "titel": "CDU Brandenburg Wahlprogramm 2024", "partei": "CDU Brandenburg", "jahr": 2024, "seiten": 100, "regierungsbildung": "2024-12-11", "regierungsende": None},
"BSW": {"file": "bsw-bb-2024.pdf", "titel": "BSW Brandenburg Wahlprogramm 2024", "partei": "BSW Brandenburg", "jahr": 2024, "seiten": 50, "regierungsbildung": "2024-12-11", "regierungsende": None},
},
# Hamburg — Bürgerschaftswahl 02.03.2025. Senat Tschentscher III (SPD+GRÜNE) vereidigt 07.05.2025.
"HH": {
"SPD": {"file": "spd-hh-2025.pdf", "titel": "SPD Hamburg Wahlprogramm Bürgerschaftswahl 2025", "partei": "SPD Hamburg", "jahr": 2025, "seiten": 100, "regierungsbildung": "2025-05-07", "regierungsende": None},
"CDU": {"file": "cdu-hh-2025.pdf", "titel": "CDU Hamburg Wahlprogramm Bürgerschaftswahl 2025", "partei": "CDU Hamburg", "jahr": 2025, "seiten": 100, "regierungsbildung": "2025-05-07", "regierungsende": None},
"GRÜNE": {"file": "gruene-hh-2025.pdf","titel": "Gute Gründe für Grün — Regierungsprogramm BÜNDNIS 90/DIE GRÜNEN Hamburg 2025", "partei": "BÜNDNIS 90/DIE GRÜNEN Hamburg", "jahr": 2025, "seiten": 100, "regierungsbildung": "2025-05-07", "regierungsende": None},
"LINKE": {"file": "linke-hh-2025.pdf", "titel": "DIE LINKE Hamburg Wahlprogramm Bürgerschaftswahl 2025", "partei": "DIE LINKE Hamburg", "jahr": 2025, "seiten": 100, "regierungsbildung": "2025-05-07", "regierungsende": None},
"AfD": {"file": "afd-hh-2025.pdf", "titel": "AfD Hamburg Wahlprogramm Bürgerschaftswahl 2025", "partei": "AfD Hamburg", "jahr": 2025, "seiten": 100, "regierungsbildung": "2025-05-07", "regierungsende": None},
},
# Schleswig-Holstein — LTW 08.05.2022. Kabinett Günther II (CDU+GRÜNE) vereidigt 29.06.2022.
"SH": {
"CDU": {"file": "cdu-sh-2022.pdf", "titel": "CDU Schleswig-Holstein Wahlprogramm 2022", "partei": "CDU Schleswig-Holstein", "jahr": 2022, "seiten": 100, "regierungsbildung": "2022-06-29", "regierungsende": None},
"SPD": {"file": "spd-sh-2022.pdf", "titel": "SPD Schleswig-Holstein Wahlprogramm 2022", "partei": "SPD Schleswig-Holstein", "jahr": 2022, "seiten": 100, "regierungsbildung": "2022-06-29", "regierungsende": None},
"GRÜNE": {"file": "gruene-sh-2022.pdf","titel": "BÜNDNIS 90/DIE GRÜNEN Schleswig-Holstein Wahlprogramm 2022", "partei": "BÜNDNIS 90/DIE GRÜNEN Schleswig-Holstein", "jahr": 2022, "seiten": 100, "regierungsbildung": "2022-06-29", "regierungsende": None},
"FDP": {"file": "fdp-sh-2022.pdf", "titel": "FDP Schleswig-Holstein Wahlprogramm 2022", "partei": "FDP Schleswig-Holstein", "jahr": 2022, "seiten": 100, "regierungsbildung": "2022-06-29", "regierungsende": None},
"SSW": {"file": "ssw-sh-2022.pdf", "titel": "SSW Schleswig-Holstein Wahlprogramm 2022", "partei": "SSW", "jahr": 2022, "seiten": 80, "regierungsbildung": "2022-06-29", "regierungsende": None},
},
# Baden-Württemberg — LTW 14.03.2021. Kabinett Kretschmann III (GRÜNE+CDU) vereidigt 12.05.2021.
"BW": {
"GRÜNE": {"file": "gruene-bw-2021.pdf","titel": "Wachsen wir über uns hinaus — Landtagswahlprogramm BÜNDNIS 90/DIE GRÜNEN Baden-Württemberg 2021", "partei": "BÜNDNIS 90/DIE GRÜNEN Baden-Württemberg", "jahr": 2021, "seiten": 100, "regierungsbildung": "2021-05-12", "regierungsende": None},
"CDU": {"file": "cdu-bw-2021.pdf", "titel": "Neue Ideen für eine neue Zeit — Regierungsprogramm der CDU Baden-Württemberg zur Landtagswahl 2021", "partei": "CDU Baden-Württemberg", "jahr": 2021, "seiten": 100, "regierungsbildung": "2021-05-12", "regierungsende": None},
"AfD": {"file": "afd-bw-2021.pdf", "titel": "AfD Baden-Württemberg Landtagswahlprogramm 2021", "partei": "AfD Baden-Württemberg", "jahr": 2021, "seiten": 100, "regierungsbildung": "2021-05-12", "regierungsende": None},
"SPD": {"file": "spd-bw-2021.pdf", "titel": "SPD Baden-Württemberg Wahlprogramm zur Landtagswahl 2021", "partei": "SPD Baden-Württemberg", "jahr": 2021, "seiten": 100, "regierungsbildung": "2021-05-12", "regierungsende": None},
"FDP": {"file": "fdp-bw-2021.pdf", "titel": "FDP Baden-Württemberg Landtagswahlprogramm 2021", "partei": "FDP Baden-Württemberg", "jahr": 2021, "seiten": 100, "regierungsbildung": "2021-05-12", "regierungsende": None},
},
# Rheinland-Pfalz — LTW 14.03.2021. Kabinett Dreyer III (SPD+GRÜNE+FDP) vereidigt 18.05.2021;
# seit 10.07.2024 fortgeführt als Schweitzer I in derselben WP18.
"RP": {
"SPD": {"file": "spd-rp-2021.pdf","titel": "Wir mit Ihr — Regierungsprogramm der SPD Rheinland-Pfalz 20212026", "partei": "SPD Rheinland-Pfalz", "jahr": 2021, "seiten": 100, "regierungsbildung": "2021-05-18", "regierungsende": None},
"CDU": {"file": "cdu-rp-2021.pdf","titel": "Regierungsprogramm der CDU RLP 202126", "partei": "CDU Rheinland-Pfalz", "jahr": 2021, "seiten": 100, "regierungsbildung": "2021-05-18", "regierungsende": None},
"AfD": {"file": "afd-rp-2021.pdf","titel": "AfD Rheinland-Pfalz Wahlprogramm 2021", "partei": "AfD Rheinland-Pfalz", "jahr": 2021, "seiten": 100, "regierungsbildung": "2021-05-18", "regierungsende": None},
"GRÜNE": {"file": "gruene-rp-2021.pdf","titel": "BÜNDNIS 90/DIE GRÜNEN Rheinland-Pfalz Landtagswahlprogramm 2021", "partei": "BÜNDNIS 90/DIE GRÜNEN Rheinland-Pfalz", "jahr": 2021, "seiten": 100, "regierungsbildung": "2021-05-18", "regierungsende": None},
"FREIE WÄHLER": {"file": "fw-rp-2021.pdf", "titel": "FREIE WÄHLER Rheinland-Pfalz Wahlprogramm 2021", "partei": "FREIE WÄHLER Rheinland-Pfalz", "jahr": 2021, "seiten": 80, "regierungsbildung": "2021-05-18", "regierungsende": None},
"FDP": {"file": "fdp-rp-2021.pdf","titel": "FDP Rheinland-Pfalz Landtagswahlprogramm 2021", "partei": "FDP Rheinland-Pfalz", "jahr": 2021, "seiten": 100, "regierungsbildung": "2021-05-18", "regierungsende": None},
},
# Bayern — LTW 08.10.2023. Kabinett Söder III (CSU+FREIE WÄHLER) vereidigt 07.11.2023.
"BY": {
"CSU": {"file": "csu-by-2023.pdf", "titel": "CSU Bayern Bayernplan 2023", "partei": "CSU Bayern", "jahr": 2023, "seiten": 100, "regierungsbildung": "2023-11-07", "regierungsende": None},
"FREIE WÄHLER": {"file": "fw-by-2023.pdf", "titel": "FREIE WÄHLER Bayern Wahlprogramm 2023", "partei": "FREIE WÄHLER Bayern", "jahr": 2023, "seiten": 80, "regierungsbildung": "2023-11-07", "regierungsende": None},
"GRÜNE": {"file": "gruene-by-2023.pdf","titel": "BÜNDNIS 90/DIE GRÜNEN Bayern Regierungsprogramm 2023", "partei": "BÜNDNIS 90/DIE GRÜNEN Bayern", "jahr": 2023, "seiten": 100, "regierungsbildung": "2023-11-07", "regierungsende": None},
"SPD": {"file": "spd-by-2023.pdf", "titel": "SPD Bayern Zukunftsprogramm 2023", "partei": "SPD Bayern", "jahr": 2023, "seiten": 100, "regierungsbildung": "2023-11-07", "regierungsende": None},
"AfD": {"file": "afd-by-2023.pdf", "titel": "AfD Bayern Wahlprogramm 2023", "partei": "AfD Bayern", "jahr": 2023, "seiten": 100, "regierungsbildung": "2023-11-07", "regierungsende": None},
},
# Bremen — Bürgerschaftswahl 14.05.2023. Senat Bovenschulte II (SPD+GRÜNE+LINKE) vereidigt 04.07.2023.
# AfD war wegen Listenstreit nicht zur Wahl zugelassen.
"HB": {
"SPD": {"file": "spd-hb-2023.pdf", "titel": "SPD Bremen Wahlprogramm Bürgerschaftswahl 2023", "partei": "SPD Bremen", "jahr": 2023, "seiten": 100, "regierungsbildung": "2023-07-04", "regierungsende": None},
"CDU": {"file": "cdu-hb-2023.pdf", "titel": "CDU Bremen Wahlprogramm Bürgerschaftswahl 2023", "partei": "CDU Bremen", "jahr": 2023, "seiten": 100, "regierungsbildung": "2023-07-04", "regierungsende": None},
"GRÜNE": {"file": "gruene-hb-2023.pdf","titel": "BÜNDNIS 90/DIE GRÜNEN Bremen Wahlprogramm 2023", "partei": "BÜNDNIS 90/DIE GRÜNEN Bremen", "jahr": 2023, "seiten": 100, "regierungsbildung": "2023-07-04", "regierungsende": None},
"LINKE": {"file": "linke-hb-2023.pdf", "titel": "DIE LINKE Bremen Wahlprogramm Bürgerschaftswahl 2023", "partei": "DIE LINKE Bremen", "jahr": 2023, "seiten": 100, "regierungsbildung": "2023-07-04", "regierungsende": None},
},
# Hessen — LTW 08.10.2023. Kabinett Rhein II (CDU+SPD) vereidigt 18.01.2024.
"HE": {
"CDU": {"file": "cdu-he-2023.pdf", "titel": "CDU Hessen Regierungsprogramm 2023", "partei": "CDU Hessen", "jahr": 2023, "seiten": 100, "regierungsbildung": "2024-01-18", "regierungsende": None},
"SPD": {"file": "spd-he-2023.pdf", "titel": "SPD Hessen Wahlprogramm 2023", "partei": "SPD Hessen", "jahr": 2023, "seiten": 100, "regierungsbildung": "2024-01-18", "regierungsende": None},
"GRÜNE": {"file": "gruene-he-2023.pdf","titel": "BÜNDNIS 90/DIE GRÜNEN Hessen Wahlprogramm 2023", "partei": "BÜNDNIS 90/DIE GRÜNEN Hessen", "jahr": 2023, "seiten": 100, "regierungsbildung": "2024-01-18", "regierungsende": None},
"FDP": {"file": "fdp-he-2023.pdf", "titel": "FDP Hessen Wahlprogramm 2023", "partei": "FDP Hessen", "jahr": 2023, "seiten": 100, "regierungsbildung": "2024-01-18", "regierungsende": None},
"AfD": {"file": "afd-he-2023.pdf", "titel": "AfD Hessen Wahlprogramm 2023", "partei": "AfD Hessen", "jahr": 2023, "seiten": 100, "regierungsbildung": "2024-01-18", "regierungsende": None},
},
# Niedersachsen — LTW 09.10.2022. Kabinett Weil III (SPD+GRÜNE) vereidigt 08.11.2022.
"NI": {
"SPD": {"file": "spd-ni-2022.pdf", "titel": "SPD Niedersachsen Regierungsprogramm 2022", "partei": "SPD Niedersachsen", "jahr": 2022, "seiten": 100, "regierungsbildung": "2022-11-08", "regierungsende": None},
"CDU": {"file": "cdu-ni-2022.pdf", "titel": "CDU Niedersachsen Regierungsprogramm 2022", "partei": "CDU Niedersachsen", "jahr": 2022, "seiten": 100, "regierungsbildung": "2022-11-08", "regierungsende": None},
"GRÜNE": {"file": "gruene-ni-2022.pdf","titel": "BÜNDNIS 90/DIE GRÜNEN Niedersachsen Wahlprogramm 2022", "partei": "BÜNDNIS 90/DIE GRÜNEN Niedersachsen", "jahr": 2022, "seiten": 100, "regierungsbildung": "2022-11-08", "regierungsende": None},
"AfD": {"file": "afd-ni-2022.pdf", "titel": "AfD Niedersachsen Wahlprogramm 2022", "partei": "AfD Niedersachsen", "jahr": 2022, "seiten": 100, "regierungsbildung": "2022-11-08", "regierungsende": None},
},
# Saarland — LTW 27.03.2022. Kabinett Rehlinger I (SPD-Alleinregierung) vereidigt 25.04.2022.
"SL": {
"SPD": {"file": "spd-sl-2022.pdf", "titel": "SPD Saarland Regierungsprogramm 2022", "partei": "SPD Saarland", "jahr": 2022, "seiten": 100, "regierungsbildung": "2022-04-25", "regierungsende": None},
"CDU": {"file": "cdu-sl-2022.pdf", "titel": "CDU Saarland Wahlprogramm 2022", "partei": "CDU Saarland", "jahr": 2022, "seiten": 100, "regierungsbildung": "2022-04-25", "regierungsende": None},
"AfD": {"file": "afd-sl-2022.pdf", "titel": "AfD Saarland Wahlprogramm 2022", "partei": "AfD Saarland", "jahr": 2022, "seiten": 100, "regierungsbildung": "2022-04-25", "regierungsende": None},
},
# Sachsen — LTW 01.09.2024. Kabinett Kretschmer III (CDU+SPD, Minderheit) vereidigt 18.12.2024.
"SN": {
"CDU": {"file": "cdu-sn-2024.pdf", "titel": "CDU Sachsen Wahlprogramm 2024", "partei": "CDU Sachsen", "jahr": 2024, "seiten": 100, "regierungsbildung": "2024-12-18", "regierungsende": None},
"SPD": {"file": "spd-sn-2024.pdf", "titel": "SPD Sachsen Wahlprogramm 2024", "partei": "SPD Sachsen", "jahr": 2024, "seiten": 100, "regierungsbildung": "2024-12-18", "regierungsende": None},
"AfD": {"file": "afd-sn-2024.pdf", "titel": "AfD Sachsen Wahlprogramm 2024", "partei": "AfD Sachsen", "jahr": 2024, "seiten": 100, "regierungsbildung": "2024-12-18", "regierungsende": None},
"BSW": {"file": "bsw-sn-2024.pdf", "titel": "BSW Sachsen Wahlprogramm 2024", "partei": "BSW Sachsen", "jahr": 2024, "seiten": 50, "regierungsbildung": "2024-12-18", "regierungsende": None},
"LINKE": {"file": "linke-sn-2024.pdf", "titel": "DIE LINKE Sachsen Wahlprogramm 2024", "partei": "DIE LINKE Sachsen", "jahr": 2024, "seiten": 100, "regierungsbildung": "2024-12-18", "regierungsende": None},
"GRÜNE": {"file": "gruene-sn-2024.pdf","titel": "BÜNDNIS 90/DIE GRÜNEN Sachsen Wahlprogramm 2024","partei": "BÜNDNIS 90/DIE GRÜNEN Sachsen", "jahr": 2024, "seiten": 100, "regierungsbildung": "2024-12-18", "regierungsende": None},
},
# Bundestag — BTW 23.02.2025. Kabinett Merz I (CDU+CSU+SPD) vereidigt 06.05.2025.
# Aktiv die BTW-2025-Wahlprogramme aller acht im 21. Bundestag relevanten
# Parteien. Grundsatzprogramme bleiben in embeddings.PROGRAMME als
# zweite Referenz erhalten.
"BUND": {
"CDU": {"file": "cdu-bund-2025.pdf", "titel": "Politikwechsel für Deutschland — Wahlprogramm CDU/CSU BTW 2025", "partei": "CDU", "jahr": 2025, "seiten": 82, "regierungsbildung": "2025-05-06", "regierungsende": None},
"CSU": {"file": "csu-bund-2025.pdf", "titel": "Politikwechsel für Deutschland — Wahlprogramm CDU/CSU BTW 2025 (CSU)", "partei": "CSU", "jahr": 2025, "seiten": 81, "regierungsbildung": "2025-05-06", "regierungsende": None},
"SPD": {"file": "spd-bund-2025.pdf", "titel": "Mehr für Dich. Besser für Deutschland. — SPD Regierungsprogramm BTW 2025", "partei": "SPD", "jahr": 2025, "seiten": 68, "regierungsbildung": "2025-05-06", "regierungsende": None},
"GRÜNE": {"file": "gruene-bund-2025.pdf","titel": "Zusammen wachsen — Regierungsprogramm BÜNDNIS 90/DIE GRÜNEN BTW 2025", "partei": "BÜNDNIS 90/DIE GRÜNEN", "jahr": 2025, "seiten": 160, "regierungsbildung": "2025-05-06", "regierungsende": None},
"FDP": {"file": "fdp-bund-2025.pdf", "titel": "Alles lässt sich ändern — FDP Wahlprogramm BTW 2025", "partei": "FDP", "jahr": 2025, "seiten": 52, "regierungsbildung": "2025-05-06", "regierungsende": None},
"AfD": {"file": "afd-bund-2025.pdf", "titel": "Zeit für Deutschland — AfD Bundestagswahlprogramm 2025", "partei": "AfD", "jahr": 2025, "seiten": 177, "regierungsbildung": "2025-05-06", "regierungsende": None},
"LINKE": {"file": "linke-bund-2025.pdf", "titel": "Alle wollen regieren. Wir wollen verändern. — DIE LINKE Wahlprogramm BTW 2025", "partei": "DIE LINKE", "jahr": 2025, "seiten": 60, "regierungsbildung": "2025-05-06", "regierungsende": None},
"BSW": {"file": "bsw-bund-2025.pdf", "titel": "Unser Land verdient mehr — BSW Wahlprogramm BTW 2025", "partei": "BSW", "jahr": 2025, "seiten": 45, "regierungsbildung": "2025-05-06", "regierungsende": None},
},
}
# Pro Bundesland: Markdown-Übersichtsdatei mit Wahlprogramm-Zusammenfassungen,
# wird als Kontext in den LLM-Prompt geladen (nicht für die Suche).
WAHLPROGRAMM_KONTEXT_FILES: dict[str, str] = {
"NRW": "wahlprogramme-nrw-2022.md",
}
REFERENZEN_PATH = Path(__file__).parent / "static" / "referenzen"
KONTEXT_PATH = Path(__file__).parent / "kontext"
def get_wahlprogramm(bundesland: str, partei: str) -> Optional[dict]:
"""Liefert die Wahlprogramm-Metadaten oder None, wenn keins vorliegt."""
return WAHLPROGRAMME.get(bundesland, {}).get(partei)
def parteien_mit_wahlprogramm(bundesland: str) -> list[str]:
"""Liste der Parteien, für die im gegebenen Bundesland ein Wahlprogramm vorliegt."""
return list(WAHLPROGRAMME.get(bundesland, {}).keys())
def regierungsbildung_for(bundesland: str) -> Optional[str]:
"""Datum der Regierungsbildung (Vereidigung) der aktuellen Regierung des
Bundeslands, oder ``None`` wenn nicht hinterlegt."""
parteien = WAHLPROGRAMME.get(bundesland, {})
for info in parteien.values():
rb = info.get("regierungsbildung")
if rb is not None:
return rb
return None
def regierungsende_for(bundesland: str) -> Optional[str]:
"""Datum, ab dem die aktuelle Regierungsperiode endet. ``None`` solange
laufend."""
parteien = WAHLPROGRAMME.get(bundesland, {})
for info in parteien.values():
return info.get("regierungsende")
return None
def regierung_aktuell(bundesland: str) -> bool:
"""True, wenn die hinterlegte Regierungsperiode noch läuft (bildung
gesetzt, ende=None)."""
parteien = WAHLPROGRAMME.get(bundesland, {})
if not parteien:
return False
info = next(iter(parteien.values()))
return info.get("regierungsbildung") is not None and info.get("regierungsende") is None
def load_wahlprogramm_text(bundesland: str, partei: str) -> dict[int, str]:
"""Lädt Wahlprogramm-Text mit Seitenzuordnung.
Returns:
Dict mit Seitennummer -> Text. Leer, wenn kein Wahlprogramm hinterlegt
oder die paged-Textdatei fehlt.
"""
info = get_wahlprogramm(bundesland, partei)
if not info:
return {}
# Versuche paged-Textdatei zu laden
paged_file = KONTEXT_PATH / info['file'].replace('.pdf', '-paged.txt')
if not paged_file.exists():
# Fallback: Normale Textdatei
txt_file = KONTEXT_PATH / info['file'].replace('.pdf', '.txt')
if txt_file.exists():
return {1: txt_file.read_text()}
return {}
text = paged_file.read_text()
pages = {}
current_page = 1
current_text = []
for line in text.split('\n'):
if line.startswith('--- PAGE '):
if current_text:
pages[current_page] = '\n'.join(current_text)
match = re.search(r'PAGE (\d+)', line)
if match:
current_page = int(match.group(1))
current_text = []
else:
current_text.append(line)
if current_text:
pages[current_page] = '\n'.join(current_text)
return pages
def search_wahlprogramm(
bundesland: str,
partei: str,
keywords: list[str],
max_results: int = 3,
) -> list[dict]:
"""Sucht relevante Passagen in einem Wahlprogramm.
Args:
bundesland: Bundesland-Code (NRW, LSA, …)
partei: Partei-Kürzel (CDU, SPD, GRÜNE, FDP, AfD, …)
keywords: Suchbegriffe
max_results: Maximale Anzahl Ergebnisse
Returns:
Liste von {bundesland, partei, seite, text, score, url, quelle}
"""
info = get_wahlprogramm(bundesland, partei)
if not info:
return []
pages = load_wahlprogramm_text(bundesland, partei)
if not pages:
return []
results = []
keywords_lower = [k.lower() for k in keywords]
for page_num, text in pages.items():
text_lower = text.lower()
score = sum(1 for kw in keywords_lower if kw in text_lower)
if score > 0:
paragraphs = text.split('\n\n')
relevant_paragraphs = []
for para in paragraphs:
para_clean = para.strip()
if len(para_clean) < 50:
continue
para_lower = para_clean.lower()
if any(kw in para_lower for kw in keywords_lower):
relevant_paragraphs.append(para_clean)
if relevant_paragraphs:
best_para = max(
relevant_paragraphs,
key=lambda p: sum(1 for kw in keywords_lower if kw in p.lower()),
)
if len(best_para) > 300:
best_para = best_para[:297] + "..."
results.append({
"partei": partei,
"bundesland": bundesland,
"seite": page_num,
"text": best_para,
"score": score,
"url": f"/static/referenzen/{info['file']}#page={page_num}",
"quelle": f"{info['partei']} Wahlprogramm {info['jahr']}, S. {page_num}",
})
results.sort(key=lambda x: x['score'], reverse=True)
return results[:max_results]
def find_relevant_quotes(
antrag_text: str,
fraktionen: list[str],
bundesland: str,
) -> dict[str, list[dict]]:
"""Findet relevante Zitate aus Wahlprogrammen für einen Antrag.
Args:
antrag_text: Volltext des Antrags
fraktionen: Liste der einreichenden Fraktionen
bundesland: Bundesland-Code (Pflichtparameter; bestimmt, welche
Wahlprogramme durchsucht werden und welche Regierungsfraktionen
zusätzlich einbezogen werden).
Returns:
Dict mit Partei -> Liste von Zitaten
"""
if bundesland not in BUNDESLAENDER:
raise ValueError(f"Unbekanntes Bundesland: {bundesland}")
# Extrahiere Keywords aus Antrag (einfache Heuristik)
stopwords = {
'der', 'die', 'das', 'und', 'oder', 'für', 'mit', 'von', 'zu', 'auf',
'ist', 'sind', 'wird', 'werden', 'hat', 'haben', 'ein', 'eine', 'einer',
'den', 'dem', 'des', 'im', 'in', 'an', 'bei', 'nach', 'über', 'unter',
'durch', 'als', 'auch', 'nur', 'noch', 'aber', 'wenn', 'dass', 'sich',
'nicht', 'wie', 'so', 'aus', 'zum', 'zur', 'vom', 'beim', 'seit', 'bis',
}
words = re.findall(r'\b[A-Za-zäöüÄÖÜß]{4,}\b', antrag_text)
keywords = [w for w in words if w.lower() not in stopwords]
word_freq: dict[str, int] = {}
for w in keywords:
w_lower = w.lower()
word_freq[w_lower] = word_freq.get(w_lower, 0) + 1
top_keywords = sorted(word_freq.keys(), key=lambda x: word_freq[x], reverse=True)[:15]
# Antragsteller + Regierungsfraktionen des Bundeslands
regierungsfraktionen = BUNDESLAENDER[bundesland].regierungsfraktionen
parteien_to_search = set(fraktionen) | set(regierungsfraktionen)
quotes: dict[str, list[dict]] = {}
for partei in parteien_to_search:
if get_wahlprogramm(bundesland, partei):
found = search_wahlprogramm(bundesland, partei, top_keywords, max_results=2)
if found:
quotes[partei] = found
return quotes
def format_quote_for_prompt(quotes: dict[str, list[dict]]) -> str:
"""Formatiert Zitate für den LLM-Prompt."""
if not quotes:
return ""
lines = ["\n## Relevante Passagen aus Wahlprogrammen\n"]
lines.append("Nutze diese Originalzitate als Belege in deiner Bewertung:\n")
for partei, zitate in quotes.items():
for z in zitate:
lines.append(f"### {z['quelle']}")
lines.append(f'> "{z["text"]}"')
lines.append("")
return "\n".join(lines)