docs: Roadmap Programme/Legislaturen mit 11 Entscheidungen

Strategische Klärungs-Runde im Anschluss an ADR 0013 — alle 11 offenen
Fragen entschieden, in 5 Implementierungs-Blöcke strukturiert:

Block 1 — Schema-Refactor (kurz):
- gueltig_ab umstellen von Regierungsbildung auf Wahltag (B1+B2)
- CSU als Alias auf CDU-BTW-Eintrag (B3)

Block 2 — Daten-Beschaffung:
- ~50 historische Wahlprogramme indizieren (A1)
- BIW Bremen + BVB/FW Brandenburg historisch (A2)
- BSW Manifest 2023 als parteiprogramm-Eintrag (B4)

Block 3 — Infrastruktur:
- Eigener PDF-Mirror auf Toppyr-Server (C3)
- Monatlicher Cron: Parteiwebseiten-Update-Check (C1)
- Täglicher Cron: inkrementelle Reindexierung (C2)

Block 4 — Auswertungen + UI:
- Eigene Detail-Views: Regierung-im-Detail, Wahlperiode (D2)
- Programmwechsel-Diff, Treuequote-Zeitreihe, Koalitions-Shift (D1)

Block 5 — Konsolidierung + Release:
- WAHLPROGRAMME als View über programme.PROGRAMME (E2)
- analyzer.py auf zeitpunktige Helper
- v1.1.0 Production-Release (E1)

Plus Detail-Gotchas und nächster konkreter Schritt (Block 1).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dotty Dotter 2026-05-08 09:03:20 +02:00
parent 9f2f805aff
commit 176b7c5018

View File

@ -0,0 +1,161 @@
# 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.