GWÖ-Antragsprüfer: Automatische Gemeinwohl-Bilanzierung von Parlamentsanträgen nach der GWÖ-Matrix 2.0
Go to file
Dotty Dotter bd591b9246 refactor(programme): WAHLPROGRAMME → programme.PROGRAMME konsolidiert (#222)
Schließt #222. Entfernt die Doppelung zwischen ``wahlprogramme.WAHLPROGRAMME``
und ``programme.PROGRAMME``. Single source of truth ist jetzt
``programme.PROGRAMME`` als Literal mit allen 287 Programmen
(Wahlprogramme + Bundes- + Landes-Grundsatzprogramme, historisch + aktuell).

Schema schmaler — Felder ohne Konsumenten entfallen:
- ``regierungsbildung`` / ``regierungsende`` → gehören zu
  ``legislaturen.REGIERUNGEN``. Verbindung Programm→Regierung läuft jetzt
  über ``legislaturen.regierung_zum_zeitpunkt(bl, datum)``.
- ``partei`` (Langform "CDU NRW") → ableitbar aus partei + bundesland.
- ``jahr`` → ableitbar aus ``gueltig_ab[:4]``.
- ``beschluss`` / ``wahl`` / ``hinweis`` → keine App-Konsumenten.

Felder im neuen Schema: id, typ, partei, bundesland, wp, gueltig_ab,
gueltig_bis, name, titel (Slogan, optional), pdf, seiten.

Daten-Migration einmalig via ``tools/build_programme_literal.py``:
- Basis: bisherige embeddings.PROGRAMME (alle 287 IDs + gueltig_ab/bis)
- titel aus WAHLPROGRAMME für die ~80 aktuellen Wahlprogramme +
  Land-Grundsatzprogramm-Slogans (ehem. _ARCHIVED_SKELETONS)
- seiten via ``fitz.open(p).page_count`` für alle 287 PDFs

Aufrufer migriert:
- app/main.py:4055 — ``aktuelles_wahlprogramm(bl, partei).pdf``
- app/wahlprogramm_check.py — ``parteien_mit_wahlprogramm(bl)``
- app/redline_utils.py — Reverse-Lookup über ``all_programme()``
- app/wahlprogramm_fetch.py (3 Stellen) — ``aktuelles_wahlprogramm()``
- tests/test_redline_parser.py — Programm-Lookup statt WAHLPROGRAMME

``wahlprogramme.py`` schrumpft auf den Such-Code: Keyword-Fallback +
PDF-Text-Loader + ein dünner ``get_wahlprogramm``-Compat-Adapter zu
``programme.aktuelles_wahlprogramm``.

Drei Helper gelöscht (keine App-Konsumenten):
``regierungsbildung_for``, ``regierungsende_for``, ``regierung_aktuell``.
Wer das Datum der Regierungsbildung will, fragt
``legislaturen.aktuelle_regierung(bl).get('von')``.

Test-Suite: 1217 grün (vorher 1244, Differenz 27 = entfernte
regierungs-Helper-Tests + obsolete WAHLPROGRAMME-Strukturtests).
2026-05-09 00:37:35 +02:00
app refactor(programme): WAHLPROGRAMME → programme.PROGRAMME konsolidiert (#222) 2026-05-09 00:37:35 +02:00
docs docs: Roadmap Programme/Legislaturen mit 11 Entscheidungen 2026-05-08 09:03:20 +02:00
scripts feat(Phase 11b): Bypass-DB-Logging + Auto-Rotation-Skript 2026-05-06 23:31:51 +02:00
tests refactor(programme): WAHLPROGRAMME → programme.PROGRAMME konsolidiert (#222) 2026-05-09 00:37:35 +02:00
tools refactor(programme): WAHLPROGRAMME → programme.PROGRAMME konsolidiert (#222) 2026-05-09 00:37:35 +02:00
.coveragerc build(#134): Coverage-Schwelle 45% → 50% nach Test-Backfill-Welle 2026-04-28 11:14:09 +02:00
.dockerignore Initial commit: GWÖ-Antragsprüfer v1.0 2026-03-28 22:30:24 +01:00
.env.example Initial commit: GWÖ-Antragsprüfer v1.0 2026-03-28 22:30:24 +01:00
.gitignore build(#134): Coverage-Baseline (.coveragerc) + pytest-cov in dev-deps 2026-04-28 02:05:39 +02:00
.tarignore Initial commit: GWÖ-Antragsprüfer v1.0 2026-03-28 22:30:24 +01:00
CHANGELOG.md release(1.0): README + CHANGELOG + DATA-LICENSE (CC-BY-4.0) 2026-04-25 20:59:28 +02:00
DATA-LICENSE release(1.0): README + CHANGELOG + DATA-LICENSE (CC-BY-4.0) 2026-04-25 20:59:28 +02:00
docker-compose.dev.yml feat: DEBUG_AUTH_TOKEN Bypass fuer Diagnose-Sessions auf dev 2026-05-06 22:26:39 +02:00
docker-compose.yml ops: GITEA_TOKEN + GITEA_*-Settings im docker-compose.yml durchreichen 2026-04-28 01:06:57 +02:00
Dockerfile fix(security): Dockerfile auf python:3.12-alpine fuer 0 CRITICAL CVEs 2026-05-08 12:15:23 +02:00
LICENSE Initial commit: GWÖ-Antragsprüfer v1.0 2026-03-28 22:30:24 +01:00
mkdocs.yml docs(Phase 19): ADR 0012 DEBUG_AUTH_TOKEN-Bypass 2026-05-06 23:53:55 +02:00
pytest.ini docs+ops: ADRs 0006/0008, DDD-Bewertung, Zugriffsrechte, Smoke-Test, Cron-Scripts 2026-04-25 20:55:57 +02:00
README.md release(1.0): README + CHANGELOG + DATA-LICENSE (CC-BY-4.0) 2026-04-25 20:59:28 +02:00
requirements-dev.txt build(#134): Coverage-Baseline (.coveragerc) + pytest-cov in dev-deps 2026-04-28 02:05:39 +02:00
requirements.txt #43 Keycloak SSO: JWT-Middleware + UI-Guiding 2026-04-10 14:28:57 +02:00

GWÖ-Antragsprüfer

Automatische Gemeinwohl-Bilanzierung von Parlamentsanträgen nach der GWÖ-Matrix 2.0 für Gemeinden

Python FastAPI Code-License Data-License Version

Live unter https://gwoe.toppyr.de/.

Was macht das Tool?

Der GWÖ-Antragsprüfer analysiert Anträge aus deutschen Landesparlamenten und dem Bundestag und bewertet sie nach den Kriterien der Gemeinwohl-Ökonomie (GWÖ):

  • GWÖ-Score (010) — Wie gut entspricht der Antrag den GWÖ-Werten?
  • Matrix-Zuordnung — Welche der 25 Felder der GWÖ-Matrix für Gemeinden werden adressiert?
  • Programm-Treue — Passt der Antrag zum Wahl- und Grundsatzprogramm jeder Fraktion?
  • Verbesserungsvorschläge — Konkrete Textänderungen mit GWÖ-Begründung im Redline-Format
  • Zitate mit Verifikation — Belege aus den Wahl-/Grundsatzprogrammen, server-seitig gegen Original-Chunks geprüft (siehe ADR 0001)

Aktive Datenquellen (Stand Release 1.0)

16 Bundesländer + Bundestag — alle aktiven Adapter:

BL Wahlperiode Quelle
BUND 21 (20252029) bundestag.de DIP
BW 17 (20212026) PARLIS
BY 19 (20232028) Bayern Landtag
BE 19 (20232026) Berlin AGH
BB 8 (20242029) StarWeb
HB 21 (20232027) ParlDok
HH 23 (20252029) ParlDok
HE 21 (20242029) Hessen Landtag
MV 8 (20212026) ParlDok
NI NILAS (login-protected, deferred)
NRW 18 (20222027) OPAL
RP 18 (20212026) StarWeb
LSA 8 (20212026) StarWeb
SL 17 (20222027) Umbraco
SN 8 (20242029) XML-Export
SH 20 (20222027) Schleswig-Holstein
TH 8 (20242029) StarWeb

Plus abgeordnetenwatch.de-Integration für strukturierte namentliche Abstimmungen (alle 16 BL + BT).

Features

Frontend (v2, ECOnGOOD-CD)

  • Listenansicht mit Score-Band-Filter, BL-Chip-Filter, Sort-Dropdown (8 Optionen), Live-Suche
  • Antragsdetail mit ScoreHero, Matrix 5×5, Zitaten, Redline-Diff, Programm-Treue pro Fraktion, Versionshistorie, namentlichem Abstimmungsverhalten (wenn vorhanden)
  • Bookmark-Liste (server-seitig pro User), Kommentare, Voting, Share-Buttons (Threads/X/Mastodon mit LLM-Texten), Re-Analyze
  • Auswertungen mit BL×Partei-Matrix, Themen×Fraktion-Heatmap, Cluster-Bubble-Chart
  • Tag-Cloud, Cluster-Liste, Landtag-Live-Suche, Methodik, Quellen
  • Admin-Panel Freischaltungen / Queue / Abos / Wahlprogramme
  • Dark-Mode, Phosphor-Icons, Avenir/Nunito-Sans, Keyboard-Shortcuts (j/k/Enter/Esc/?/⏎)

Backend

  • FastAPI + Jinja2 + Vanilla JS (kein Build-Tool)
  • SQLite mit aiosqlite (Source of Truth)
  • Qwen-Plus (DashScope) für die LLM-Bewertung — austauschbar via LlmBewerter-Port (ADR 0008)
  • Embeddings v4 für die Zitat-Verifikation (ADR 0006)
  • Keycloak SSO mit Direct-Access-Grant (Login-Modal in der App, kein Redirect)
  • Background-Queue mit 3 parallelen Workern + Graceful Shutdown
  • Daily-Digest-Mail für Abonnent:innen
  • Monitoring-Scan aller Adapter mit Kosten-Schätzung — Beobachtung ohne Auto-Fetch
  • OG-Cards (Open-Graph-Bilder pro Antrag, Playwright-gerendert)
  • WeasyPrint für PDF-Reports

Tests

  • 574 Tests, 13 skipped — Unit + Integration + Property + Bug-Regression + DDD
  • Live-Adapter-Tests gegen alle 17 Quellen (pytest -m integration)
  • Citation-Substring-Verification gegen Original-PDFs
  • E2E-Browser-Tests via Playwright (pytest -m e2e)

Architektur

Detailliert in docs/:

DDD-Lightweight-Migration ist Tag 1-4 abgeschlossen (Ports, Adapter, Repositories, Domain-Verhalten — siehe ADR 0008). Callsite-Migration in main.py ist Folge-PR.

Schnellstart

Voraussetzungen

  • Docker + Docker Compose
  • Python 3.12 (für lokale Tests)
  • DashScope API-Key (Qwen)
  • Keycloak (optional, für Login)

Installation

git clone https://repo.toppyr.de/tobias/gwoe-antragspruefer
cd gwoe-antragspruefer/webapp
cp .env.example .env       # API-Keys eintragen
docker compose up -d --build

App auf http://localhost:8000.

Tests

python3 -m pytest tests/ -q                  # Unit-Suite (574 Tests, < 2 s)
python3 -m pytest tests/ -m integration      # Live-Adapter-Tests (langsam)
./scripts/smoke-test.sh                       # Gesamt-Funktionsprüfung gegen Live

Deploy (Server)

./scripts/deploy.sh                           # mit Uptime-Kuma-Wartungsmodus
./scripts/run-digest.sh                       # Daily-Mail-Digest (Cron 07:00)
./scripts/run-monitoring-scan.sh              # Monitoring-Scan (manuell oder Cron)

Lizenz

Zwei getrennte Lizenzen:

  • QuellcodeMIT
  • Bewertungs-Daten und -Berichte (Assessments, Matrix-Zuordnungen, Verbesserungsvorschläge, Themen-Tags etc.) — CC BY 4.0

Wahlprogramme und Antrags-PDFs der Parlamente unterliegen der jeweiligen Urheber-Lizenz der Quelle und werden hier nur zur Verifikation referenziert.

Mitwirken

Issues unter https://repo.toppyr.de/tobias/gwoe-antragspruefer. Pull Requests willkommen — beachte ADR 0004 (Deployment-Workflow) und die Test-Konventionen in pytest.ini.

Statistiken (Stand Release 1.0)

  • 16 BL + Bundestag aktiv
  • 85 Wahlprogramme indexiert (Embeddings v4)
  • 71 produktive Bewertungen in der Live-DB
  • 28 977 abgeordnetenwatch-Votes (BUND)
  • 11 789 LOC Python in app/