Architektur-Entscheidung aus Issue #62: Diátaxis-Framework für Doku- Pflege ohne Drift. Pflege im Repo, ADRs immutable, Stale-Snapshots explizit als Archiv markiert. Phase 1 — Architecture Decision Records: - docs/README.md — Diátaxis-Index, Erklärung was wo dokumentiert wird - docs/adr/README.md — ADR-Workflow + Index - docs/adr/template.md — Vorlage für neue ADRs - docs/adr/0001-llm-citation-binding.md — Issue #60 Doppel-Fix-Story (A=ENUM-Anker, B=server-seitige Rekonstruktion, warum Option C verworfen) - docs/adr/0002-adapter-architecture.md — ParlamentAdapter-Basisklasse + Registry, Klassen vs. Strategy vs. Modul-pro-Adapter - docs/adr/0003-citation-property-tests.md — Sub-D Strategie, warum Property-Test gegen echte PDFs statt Schema-Tests oder Online-Verify - docs/adr/0004-deployment-workflow.md — Docker-Compose + Volumes Standard-Workflow + SN-XML-Sonderpfad + Container-UTC-Gotcha Phase 3 — Stale Doku archiviert: - DOKUMENTATION.md (24.März, Skript-Architektur vor Webapp-Migrate) → docs/archive/DOKUMENTATION-2026-03-24.md - STATUS-2026-03-28.md (Tagesstand-Snapshot) → docs/archive/STATUS-2026-03-28.md - README.md (28.März, listet nur NRW-Adapter, vor 16 weiteren BLs) → docs/archive/README-2026-03-28.md - docs/archive/README.md erklärt warum die Files da sind und warum niemand sie überschreiben oder ersetzen sollte Plus neue Top-Level-README.md im Project-Root (außerhalb git, da project-root kein Repo ist) als Folder-Index für den User. CLAUDE.md ergänzt um Doku-Sektion mit Verweis auf docs/adr/. Phase 2 (mkdocs Setup) folgt separat — braucht eine Docker-Image- Erweiterung, die ich nicht autark einrollen will ohne Decision. Tests: 194/194 grün (keine Code-Änderung). Refs: #62
294 lines
10 KiB
Markdown
294 lines
10 KiB
Markdown
# GWÖ-Antragsprüfer — Projektdokumentation
|
||
|
||
**Stand:** 28.03.2026, 23:58 Uhr
|
||
**Telegram-Topic:** [🌱 GWÖ-Antragsprüfer](https://t.me/c/3823618505/4247) (thread_id 4247)
|
||
|
||
## 🎯 Projektziel
|
||
|
||
Automatische Bewertung von Parlamentsanträgen nach der **Gemeinwohl-Ökonomie (GWÖ) Matrix 2.0 für Gemeinden**. Das Tool analysiert Anträge aus Landesparlamenten und bewertet sie nach GWÖ-Kriterien, vergleicht mit Wahl- und Parteiprogrammen und schlägt konkrete Textverbesserungen vor.
|
||
|
||
---
|
||
|
||
## 🌐 Live-System
|
||
|
||
| Was | URL |
|
||
|-----|-----|
|
||
| **Webapp** | https://gwoe.toppyr.de |
|
||
| **Git-Repository** | https://repo.toppyr.de/tobias/gwoe-antragspruefer |
|
||
| **Server** | VServer 152.53.119.77 |
|
||
| **Container** | `/opt/gwoe-antragspruefer/` |
|
||
|
||
---
|
||
|
||
## 🏗️ Architektur
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ Frontend │
|
||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
|
||
│ │ Durchsuchen │ │ 🏷️ Tags │ │ Prüfen │ │
|
||
│ │ (Liste) │ │ (Wolke) │ │ (Upload/Analyse) │ │
|
||
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ FastAPI Backend │
|
||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
|
||
│ │ /api/ │ │ /api/ │ │ /api/ │ │ /api/ │ │
|
||
│ │assessments│ │search- │ │analyze- │ │assessment/ │ │
|
||
│ │ │ │landtag │ │drucksache│ │pdf │ │
|
||
│ └──────────┘ └──────────┘ └──────────┘ └─────────────┘ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
│ │ │
|
||
▼ ▼ ▼
|
||
┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐
|
||
│ SQLite │ │ OPAL API │ │ DashScope (Qwen) │
|
||
│ gwoe-antraege│ │ (Landtag │ │ qwen-plus-latest │
|
||
│ .db │ │ NRW) │ │ (LLM Analyse) │
|
||
└─────────────┘ └─────────────┘ └─────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 📁 Projektstruktur
|
||
|
||
```
|
||
webapp/
|
||
├── app/
|
||
│ ├── main.py # FastAPI-Endpoints + Security Middleware
|
||
│ ├── analyzer.py # LLM-Analyse mit v5-Prompt + Retry-Logik
|
||
│ ├── database.py # SQLite (aiosqlite) Persistenz
|
||
│ ├── models.py # Pydantic Assessment-Model
|
||
│ ├── parlamente.py # OPAL-Adapter für NRW Landtag
|
||
│ ├── report.py # PDF-Generierung (WeasyPrint)
|
||
│ ├── config.py # Settings + Environment
|
||
│ ├── embeddings.py # Wahlprogramm-Embeddings (optional)
|
||
│ ├── kontext/
|
||
│ │ ├── gwoe-matrix-2.0.md # GWÖ-Matrix Referenz
|
||
│ │ ├── wahlprogramme-nrw-2022.md # Zusammenfassungen
|
||
│ │ ├── parteiprogramme.md # Grundsatzprogramme
|
||
│ │ └── *-nrw-2022-paged.txt # Volltext (paginiert)
|
||
│ ├── templates/
|
||
│ │ ├── index.html # Haupt-UI (Jinja2)
|
||
│ │ └── quellen.html # Quellenübersicht
|
||
│ └── static/
|
||
│ └── referenzen/ # Original-PDFs der Programme
|
||
├── data/ # SQLite-DBs (Docker Volume)
|
||
│ └── gwoe-antraege.db # Haupt-Datenbank
|
||
├── reports/ # Generierte PDFs (Docker Volume)
|
||
├── docker-compose.yml # Traefik + Let's Encrypt
|
||
├── Dockerfile # Python 3.12 + WeasyPrint
|
||
├── requirements.txt
|
||
├── .env.example
|
||
├── .gitignore
|
||
├── .dockerignore
|
||
├── LICENSE (MIT)
|
||
└── README.md
|
||
```
|
||
|
||
---
|
||
|
||
## ✨ Features (Stand 28.03.2026)
|
||
|
||
### Analyse
|
||
- [x] GWÖ-Score (0-10) mit Matrix-Zuordnung
|
||
- [x] Bewertungssymbole (++/+/○/−/−−) pro Matrix-Feld
|
||
- [x] Wahlprogrammtreue (0-10) pro Fraktion
|
||
- [x] Parteiprogrammtreue (0-10) pro Fraktion
|
||
- [x] **Verbesserungsvorschläge im Redline-Format**
|
||
- Original-Zitat aus dem Antrag
|
||
- Konkreter Verbesserungsvorschlag
|
||
- GWÖ-Begründung
|
||
- [x] Themen-Tags für Kategorisierung
|
||
- [x] Retry-Logik (3 Versuche) bei JSON-Parse-Fehlern
|
||
|
||
### UI
|
||
- [x] Score-Filter (Alle / 8-10 / 5-7 / 0-4)
|
||
- [x] **Partei-Filter** (Dropdown)
|
||
- [x] **Durchschnittswerte pro Partei** (kompakte Stats-Bar)
|
||
- [x] **Tag-Wolke** mit Multi-Select (Schnittmenge)
|
||
- [x] Landtag-Suche via OPAL-API
|
||
- [x] "Jetzt prüfen"-Button für neue Anträge
|
||
- [x] Detail-Ansicht mit allen Bewertungen
|
||
- [x] PDF-Download pro Antrag
|
||
|
||
### Security
|
||
- [x] Content-Security-Policy
|
||
- [x] X-Frame-Options: DENY
|
||
- [x] X-Content-Type-Options: nosniff
|
||
- [x] X-XSS-Protection
|
||
- [x] Referrer-Policy
|
||
- [x] Permissions-Policy
|
||
- [x] /docs, /redoc, /openapi.json deaktiviert
|
||
|
||
### Infrastruktur
|
||
- [x] Docker Compose mit Traefik Reverse Proxy
|
||
- [x] Let's Encrypt SSL
|
||
- [x] **Persistente SQLite-DB** (Volume, überlebt Container-Neustarts)
|
||
- [x] Git-Repository auf repo.toppyr.de
|
||
|
||
---
|
||
|
||
## 🔧 Konfiguration
|
||
|
||
### Environment-Variablen (.env)
|
||
|
||
```bash
|
||
DASHSCOPE_API_KEY=sk-... # Alibaba DashScope API
|
||
KEYCLOAK_URL=https://sso.toppyr.de # Optional: SSO
|
||
KEYCLOAK_REALM=collaboration
|
||
KEYCLOAK_CLIENT_ID=gwoe-antragspruefer
|
||
```
|
||
|
||
### LLM-Modelle
|
||
|
||
| Modell | Verwendung | Kosten |
|
||
|--------|------------|--------|
|
||
| `qwen-plus-latest` | Standard (Free Tier) | Kostenlos |
|
||
| `qwen-plus` | Fallback (Paid) | ~$0.80/MTok |
|
||
| `qwen-max` | Premium | ~$2.40/MTok |
|
||
|
||
---
|
||
|
||
## 📊 API-Endpoints
|
||
|
||
| Methode | Pfad | Beschreibung |
|
||
|---------|------|--------------|
|
||
| GET | `/` | Web-UI |
|
||
| GET | `/health` | Health Check |
|
||
| GET | `/quellen` | Quellenübersicht |
|
||
| GET | `/api/assessments` | Alle Bewertungen (JSON) |
|
||
| GET | `/api/assessment?drucksache=18/12345` | Einzelne Bewertung |
|
||
| GET | `/api/search?q=Klima` | Interne DB-Suche |
|
||
| GET | `/api/search-landtag?q=Klima` | Landtag OPAL-Suche |
|
||
| POST | `/api/analyze-drucksache` | Neue Analyse starten |
|
||
| GET | `/api/assessment/pdf?drucksache=18/12345` | PDF-Download |
|
||
| GET | `/api/bundeslaender` | Verfügbare Bundesländer |
|
||
| GET | `/status/{job_id}` | Job-Status abfragen |
|
||
|
||
---
|
||
|
||
## 🧠 Prompt v5 — Kern-Features
|
||
|
||
Der Analyse-Prompt fordert:
|
||
|
||
1. **GWÖ-Treue (0-10)** mit Matrix-Zuordnung:
|
||
- Matrix-Feld (z.B. "D1 Menschenwürde")
|
||
- Symbol (++/+/○/−/−−)
|
||
- Kurzbegründung
|
||
|
||
2. **Programmtreue** für Antragsteller UND Regierungsfraktionen:
|
||
- Wahlprogramm-Score (0-10)
|
||
- Parteiprogramm-Score (0-10)
|
||
- Begründungen
|
||
|
||
3. **Verbesserungsvorschläge** (max. 3):
|
||
```json
|
||
{
|
||
"original": "Zitat aus dem Antrag",
|
||
"vorschlag": "Konkret **verbesserter** Text",
|
||
"begruendung": "Stärkt GWÖ-Wert X durch Y"
|
||
}
|
||
```
|
||
|
||
4. **Themen-Tags** für Kategorisierung
|
||
|
||
---
|
||
|
||
## 🚀 Deployment
|
||
|
||
### Erstinstallation
|
||
|
||
```bash
|
||
ssh vserver
|
||
cd /opt
|
||
git clone https://repo.toppyr.de/tobias/gwoe-antragspruefer.git
|
||
cd gwoe-antragspruefer
|
||
|
||
# .env erstellen
|
||
cp .env.example .env
|
||
nano .env # DASHSCOPE_API_KEY eintragen
|
||
|
||
# Starten
|
||
docker compose up -d
|
||
```
|
||
|
||
### Update
|
||
|
||
```bash
|
||
# Lokal
|
||
cd ~/Nextcloud/dotty/projekte/2026-03-23\ GWÖ-Antragsprüfer\ _WIP_/webapp
|
||
git add . && git commit -m "Update" && git push
|
||
|
||
# Auf Server
|
||
ssh vserver 'cd /opt/gwoe-antragspruefer && git pull && docker compose up -d --build'
|
||
```
|
||
|
||
### Manuelles Deploy (ohne Git auf Server)
|
||
|
||
```bash
|
||
cd ~/Nextcloud/dotty/projekte/2026-03-23\ GWÖ-Antragsprüfer\ _WIP_/webapp
|
||
tar czf /tmp/gwoe-webapp.tar.gz --exclude='venv' --exclude='__pycache__' --exclude='data' --exclude='reports' --exclude='.env' .
|
||
scp /tmp/gwoe-webapp.tar.gz vserver:/tmp/
|
||
ssh vserver 'cd /opt/gwoe-antragspruefer && tar xzf /tmp/gwoe-webapp.tar.gz && docker compose up -d --build'
|
||
```
|
||
|
||
---
|
||
|
||
## 📈 Statistiken (28.03.2026)
|
||
|
||
| Metrik | Wert |
|
||
|--------|------|
|
||
| Analysierte Anträge | 20 |
|
||
| Ø GWÖ-Score gesamt | 4.6 |
|
||
| Ø SPD | 7.7 |
|
||
| Ø GRÜNE | 6.0 |
|
||
| Ø CDU | 6.0 |
|
||
| Ø FDP | 4.8 |
|
||
| Ø AfD | 1.5 |
|
||
|
||
---
|
||
|
||
## 🐛 Bekannte Issues / TODOs
|
||
|
||
### Offen
|
||
- [ ] Keycloak SSO-Integration aktivieren
|
||
- [ ] Weitere Bundesländer (BY, BW) anbinden
|
||
- [ ] Batch-Analyse für viele Anträge
|
||
- [ ] Wahlprogramm-Zitate mit Seitenzahlen
|
||
- [ ] Export als CSV/Excel
|
||
|
||
### Gelöst (28.03.2026)
|
||
- [x] JSON-Parse-Fehler bei LLM-Output → Retry-Logik
|
||
- [x] DB nicht persistent → Dockerfile gefixt, data/ als Volume
|
||
- [x] Alte Assessments überschreiben neue → JSON-Import deaktiviert
|
||
- [x] Partei-Filter zeigt "Suchfehler" → JS-Bug gefixt
|
||
|
||
---
|
||
|
||
## 📝 Changelog
|
||
|
||
### v1.0.0 (28.03.2026)
|
||
- Initial Release
|
||
- GWÖ-Matrix 2.0 Analyse für NRW
|
||
- Verbesserungsvorschläge im Redline-Format
|
||
- Tag-Wolke mit Multi-Select
|
||
- Partei-Filter + Durchschnittswerte
|
||
- Security Headers
|
||
- Docker Deployment
|
||
|
||
---
|
||
|
||
## 📚 Quellen
|
||
|
||
- [GWÖ-Matrix 2.0 für Gemeinden (Arbeitsbuch)](https://econgood.org)
|
||
- [ECOnGOOD Corporate Design Manual 2024](https://econgood.org)
|
||
- [NRW OPAL Parlamentsdokumentation](https://www.landtag.nrw.de)
|
||
- Wahlprogramme NRW 2022 (CDU, GRÜNE, SPD, FDP, AfD)
|
||
- Grundsatzprogramme der Parteien
|
||
|
||
---
|
||
|
||
**Entwickelt von Tobias Rödel mit Unterstützung von Dotty** 👻
|