Fuenfter produktiver Parser nach NRW + BUND + BE + HH.
URL-Pattern verifiziert (WP8 Sitzungen 1, 10, 20, 30, 40, 42):
https://www.thueringer-landtag.de/uploads/tx_tltcalendar/protocols/Arbeitsfassung{n}.pdf
Anchor-Sprache (BE-aehnlich):
Wer dem zustimmt, ... Das sind die Stimmen aus den Fraktionen der
CDU, BSW, SPD und Die Linke. Wer stimmt gegen ...? Das sind die
Stimmen aus der Fraktion der AfD. Damit ist [...] mehrheitlich
angenommen.
Pattern:
- Result-Anchor: Damit ist [Subjekt] (mehrheitlich|einstimmig)?
(angenommen|abgelehnt)
- Vote-Block: Wer dem zustimmt / Wer stimmt gegen / Wer enthaelt sich
- Drucksachen-Lookup: 'Drucksache 8/N' rueckwaerts
Fraktions-Mapping WP8 (ab Mai 2024): CDU, AfD, BSW, Linke, SPD
(WP7-Faktionen GRUENE/FDP fuer Backfill ebenfalls im Mapping).
Cron-PROTO_TARGETS um TH-WP8 erweitert. Stub-Test angepasst.
Vor-WP-Coverage fuer beide neuen produktiven Parser:
- BUND WP19 (2017-2021, 239 Sitzungen)
- BE WP18 (Berlin, ~85 Sitzungen)
Cron probiert kontinuierlich nach: bei jedem Lauf werden 50 weitere
Sitzungen probiert ab letztem ingestetem Stand. Bei 3 aufeinander-
folgenden 404 → Ende fuer dieses BL/WP.
Hamburg hat keine vorhersagbare URL-Pattern (Blob-IDs + Hashes pro PDF).
Stattdessen: HH-Branch im Cron scraped die Protokoll-Liste auf
hamburgische-buergerschaft.de und ingestet jedes gefundene PDF, das
noch nicht in plenum_vote_results steht (idempotent).
Cron-Lauf morgens 06:30 zieht damit auch HH-Sitzungen automatisch nach,
sobald die Buergerschaft sie veroeffentlicht (typisch Tag nach der
Sitzung).
URL-Discovery-Pattern fuer Phase-2-BL mit aehnlich nicht-vorhersagbaren
URLs (z.B. SN, ggf. NI) — kann diese Index-Scrape-Logik wiederverwenden.
Dritter vollwertiger Plenarprotokoll-Parser nach NRW + BUND.
URL-Pattern verifiziert (WP19 Sitzungen 1, 10, 50, 80, 100):
https://www.parlament-berlin.de/ados/{wp}/IIIPlen/protokoll/plen{wp}-{n:03}-pp.pdf
Anchor-Sprache (NRW-aehnlich, mit Berliner-Eigenheit 'pro forma'):
Wer den Antrag auf Drucksache 19/X annehmen moechte, ... – Das sind
die Fraktionen Buendnis 90/Die Gruenen und Die Linke.
Wer stimmt dagegen? – Das sind die Fraktionen der CDU, SPD und AfD.
Wer enthaelt sich, pro forma? – Das ist niemand.
Damit ist der Antrag abgelehnt.
Pattern:
- Result-Anchor: Damit ist [Antrag/Aenderungsantrag/Gesetzentwurf/...]
(angenommen|abgelehnt)
- Vote-Block: 3 Q+A-Paare im Reden-Stil (annehmen moechte / dagegen /
enthaelt sich)
- Drucksachen-Lookup: 'Drucksache 19/N(-suffix)' rueckwaerts (1500-char Fenster)
Fraktions-Mapping WP19:
- Buendnis 90/Die Gruenen → GRÜNE
- Die Linke → LINKE
- CDU, SPD, AfD, FDP
21 Tests in test_protokoll_parsers_be.py.
Cron-PROTO_TARGETS erweitert um BE WP19 (~80 Sitzungen).
Stub-Test angepasst.
905 Tests gruen (889 → 905, +16 fuer BE).
Container hat kein sqlite3-CLI. docker exec sqlite3 schlug 'OCI runtime
exec failed' und last_n wurde zur Fehlermeldung statt einer Zahl,
woraufhin set -u im naechsten Arithmetic-Schritt knallte.
Fix: python -c mit sqlite3-Modul (Standard-Bibliothek, immer da). Plus
Numeric-Sanity-Check als Belt-and-Suspenders.
scripts/backfill-nrw-protocols.sh:
Probiert MMP{wp}-1.pdf bis MMP{wp}-200.pdf durch, ingestet alle 200er.
Bei 3 aufeinanderfolgenden 404 Abbruch.
Usage: backfill-nrw-protocols.sh [WP=18] [CONTAINER=gwoe-antragspruefer-dev]
Idempotent ueber plenum_vote_results-Compound-PK.
scripts/auto-ingest-protocols.sh:
BL-uebergreifend, Cron-tauglich. Liest fuer jeden konfigurierten
BL/WP das letzte ingestete Protokoll aus der DB, probiert die
naechste Sitzungsnummer, ingestet bis zur naechsten Luecke.
Aktuell konfiguriert: NRW WP18, NRW WP17 (Pattern leicht erweiterbar).
Beide rein deterministisch — keine LLM-Calls, keine Embedding-Calls,
keine Kosten. Reines PDF-Download + Regex-Parsing + SQLite-Insert.
Container-Duplikation fuer v1.x-Entwicklung:
- docker-compose.dev.yml: eigener Container gwoe-antragspruefer-dev,
Traefik-Host gwoe-dev.toppyr.de, Keycloak-Client gwoe-antragspruefer-dev,
ohne SMTP (Mail aus Dev = gar nicht), GITEA_FEEDBACK_LABELS=feedback,dev.
- scripts/deploy.sh: Branch-Guard verhindert Prod-Deploy aus main; Prod
geht nur aus release/1.0 (oder mit --force).
Dev-Server zieht main per Cron alle 5 Minuten und baut neu.
Bundesland-Auswahl:
- Topbar: einziger BL-Selektor mit localStorage.gwoe.bl-Persistenz
- BL-Felder entfernt aus durchsuchen.html, landtag_suche.html, neu.html, auswertungen.html
- Screens hoeren auf v2-bl-changed CustomEvent + initial via window.v2GetGlobalBl()
Sichtbarkeit (Sidebar):
- Durchsuchen + Tags: immer
- Merkliste / Neuer Antrag / Landtag-Suche / Auswertungen / Export / Feed: nur eingeloggt
- Cluster + Batch-Analyse + Administration: nur Admin
Server-Side Schutz:
- _v2_template_context()-Helper liefert is_authenticated, is_admin, v2_bundeslaender
- HTML-Routen mit Depends(require_auth) bzw. require_admin
- 401/403-Browser-Requests redirecten auf /?login=1 statt JSON-Error
Queue-Widget (#149):
- Neues Component-Partial v2/components/queue_widget.html
- Statusbar unten links + Hover-Tooltip mit den letzten 20 Jobs
- 5s-Polling auf /api/queue/status, blendet sich aus wenn keine Jobs
Smoke-Test angepasst an neue Auth-Erwartungen (302 fuer auth-protected Routen).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>