# Roadmap Programme/Legislaturen — Entscheidungen 2026-05-08 Ergebnis der strategischen Klärungs-Runde im Anschluss an [ADR 0013](adr/0013-programme-legislaturen-zeitpunktige-bewertung.md). Alle 11 offenen Fragen entschieden. ## Entscheidungen im Überblick | ID | Frage | Entscheidung | |----|-------|--------------| | A1 | Historische Indexierung | **Volle historische Indexierung** (~50 PDFs, 3 Vorperioden × 16 BL) | | A2 | Kleine/historische Fraktionen | **Auch historische** (BIW Bremen, BVB/FW Brandenburg) | | B1 | Antrag vor Regierungsbildung | **Programm gilt ab Wahltag** | | B2 | Opposition vs. Regierung | **Alle ab Wahltag** (löst B1 implizit) | | B3 | CDU+CSU teilen Programm | **CSU als Alias auf CDU-Eintrag** | | B4 | BSW kein Grundsatzprogramm | **Manifest 2023 als parteiprogramm-Eintrag** | | C1 | Programm-Updates verfolgen | **Cron: monatlich Parteiwebseiten checken** | | C2 | Reindexierung | **Cron: täglich, nur fehlende** | | C3 | PDF-Quellen-Stabilität | **+ Eigener Mirror auf Toppyr-Server** | | D1 | Neue Auswertungen | **Alle vier:** Programmwechsel, Treuequote, Koalitions-Shift, Regierung-im-Detail | | D2 | UI-Investition | **Eigene Detail-Views** für Regierung & Wahlperiode | | E1 | Prod-Deploy | **Erst nach historischer Indexierung** (v1.1.0 als Belohnung) | | E2 | WAHLPROGRAMME konsolidieren | **Erst nach historischer Indexierung** | ## Implementierungs-Reihenfolge (logische Abhängigkeiten) ### Block 1 — Schema-Refactor (ohne neue Daten, schnell) **1.1** B1+B2: `gueltig_ab` umstellen von Regierungsbildung auf Wahltag - Migration: pro Wahlprogramm-Eintrag das `wahltermin` aus `legislaturen.py` holen → `gueltig_ab = wahltermin` - `regierungsbildung` bleibt erhalten für die UI-Anzeige "Regierung zur Antragszeit" (Bewertungs-Kontext) - Tests anpassen: B1 (vor-Regierungsbildung) liefert nun das Wahlprogramm ab Wahltag **1.2** B3: CSU-Alias-Mechanismus - Optionales `alias_of`-Feld im Programm-Schema - `csu-bund-2025` wird zu `{"alias_of": "cdu-bund-2025", ...}` - Lookup-Helper resolvt Aliase automatisch **Aufwand:** kurz (1-2h Code + Tests) ### Block 2 — Daten-Beschaffung (Background-Agents parallel) **2.1** A1: 50 historische Wahlprogramme beschaffen - 16 BL × ~3-5 Vorperioden × ~5 Parteien = ~50 PDFs - Per Bundesland Liste + URLs zusammensuchen (Background-Agent) - Lokale Mirrors anlegen (siehe C3) - SHA-256 in `wahlprogramm-shas.lock.json` pinnen **2.2** A2: Historische Fraktionen ergänzen - BIW Bremen 2023-Programm beschaffen + im Schema (HB-Eintrag) ergänzen - BVB/FREIE WÄHLER Brandenburg WP7 (2019-2024) beschaffen - In `legislaturen.REGIERUNGEN` ggf. aktualisieren falls nötig **2.3** B4: BSW Manifest 2023 indizieren - PDF beschaffen (URL: bsw-vg.de/wp-content/uploads/2024/01/BSW_Parteiprogramm.pdf oder neuere Version) - Als `bsw-manifest` in `embeddings.PROGRAMME` einbauen mit `gueltig_ab="2023-10-23"` - programme.py: Eintrag als `grundsatzprogramm-bund` registrieren **Aufwand:** mittel — eigene Session(en), DashScope-API-Last ### Block 3 — Infrastruktur (Cron + Mirror) **3.1** C3: Mirror-Server-Setup - Auf Toppyr-Server: `/var/www/programme-mirror/` als statisches PDF-Archiv - Spiegel via rsync von `app/static/referenzen/` - URLs in `wahlprogramm-links.yaml` um `mirror_url`-Feld erweitern **3.2** C1: Monatlicher Cron — Parteiwebseiten-Update-Check - `scripts/check-programm-updates.sh` per Cron alle 30 Tage - Liest `wahlprogramm-links.yaml`, ruft jede URL ab, vergleicht SHA-256 - Bei Hash-Mismatch oder 404: Telegram-Notification an Topic 4247 - Output in `data/programm-updates.log` **3.3** C2: Täglicher Cron — inkrementelles Reindexing - `scripts/reindex-fehlende.sh` per Cron 03:00 Uhr - Nutzt vorhandene `reindex_embeddings.py`-Logik (skip-already-indexed) - Loggt in `auto_rate_runs`-ähnliche Tracking-Tabelle **Aufwand:** kurz-mittel ### Block 4 — Auswertungen + UI (Detail-Views) **4.1** D2: "Regierung im Detail"-View (`/regierung/{name}`) - Pro Kabinett: Anträge der Amtszeit, Score-Verteilung, Auffälligkeiten, Programm-Treue-Quote der Regierungsfraktionen **4.2** D1: Programmwechsel-Diff (`/partei/{name}/programmwechsel`) - Wahlprogramm 2017 vs. 2022 — semantischer Diff via Embeddings - Heatmap pro GWÖ-Wert: hat sich die Programmatik verschoben? **4.3** D1: Treuequote-Zeitreihe (`/auswertungen/treuequote`) - Pro Regierung: % der Anträge, die ≥7 Treue-Score zum eigenen Wahlprogramm haben → Erfüllungsgrad der Wahlversprechen **4.4** D1: Koalitions-Shift (`/partei/{name}/koalitionen`) - Stimmverhalten der gleichen Partei in verschiedenen Koalitionen vergleichen **Aufwand:** lang — eigenes Feature-Projekt ### Block 5 — Konsolidierung + Release **5.1** E2: WAHLPROGRAMME als View über programme.PROGRAMME - `wahlprogramme.WAHLPROGRAMME` wird `@property` auf `programme.PROGRAMME`-Filter - `embeddings.PROGRAMME` analog - ~1h Code, alle Tests müssen grün bleiben **5.2** analyzer.py auf zeitpunktige Helper migrieren - `wahlprogramm_zum_zeitpunkt(bl, partei, antrag.datum)` statt `WAHLPROGRAMME[bl][partei]` - `find_relevant_chunks` mit Datum-Filter (nur Programme mit `gueltig_ab ≤ antrag.datum < gueltig_bis`) - Smoke-Test gegen 5 historische Anträge: stimmen die Ergebnisse? **5.3** E1: Production-Release v1.1.0 - main → release/1.1 branch - Tag v1.1.0 - Deploy auf prod (gwoe.toppyr.de) mit komplettem Stack - ADR 0014 für Release-Bilanz **Aufwand:** mittel ## Grobe Zeitplanung | Block | Sessions | Wann | |-------|----------|------| | Block 1 (Schema-Refactor) | 1 | jederzeit | | Block 2 (Daten-Beschaffung) | 3-5 | nach Block 1 | | Block 3 (Infra) | 1-2 | parallel zu Block 2 möglich | | Block 4 (Auswertungen) | 4-6 | nach Block 2 | | Block 5 (Konsolidierung + Release) | 1-2 | als Letztes | ## Gotchas und offene Detail-Fragen - **B1+B2 Migration:** muss in einem einzigen Commit passieren (Schema-Bruch). Tests refactoren. - **A2 historische Fraktionen:** BVB/FW Brandenburg ist ein Wahlbündnis, nicht eine Partei — wie modellieren? (Optionen: als Alias auf BVB + FW separat, oder als eigenständigen Schlüssel.) - **B3 Alias:** wenn `csu-bund-2025` ein Alias auf `cdu-bund-2025` ist, muss die UI klar machen "CDU+CSU teilen sich dieses Programm" und nicht zwei separate Bewertungs-Quellen suggerieren. - **C1 Cron:** wie unterscheidet er "neue Version desselben Programms" von "Webseiten-Layout-Änderung mit gleichem PDF"? SHA-256-only reicht für Layout-Tolerance nicht — alternativ: nur PDF-Bytes prüfen. - **D1 Programmwechsel-Diff:** semantischer Diff zwischen zwei Wahlprogrammen ist nicht trivial. Embedding-Cosine pro Chunk-Paar? Oder summarized-by-LLM? Eigene Architektur-Entscheidung. ## Nächster konkreter Schritt **Block 1 anfangen** — Schema-Refactor `gueltig_ab = Wahltag` und CSU-Alias-Mechanismus. Das ist eine geschlossene Session, baut direkt auf den bestehenden Modulen auf, und macht das Schema sauberer für alles, was folgt.