Schließt #21 (HB-Scraper) und #33 (UI-Aktivierung). Eigenständige
``PARiSHBAdapter``-Klasse für paris.bremische-buergerschaft.de.
Backend (HAR-Trace TEMP/paris.bremische-buergerschaft.de.har):
- Single-POST gegen ``/starweb/paris/servlet.starweb`` mit
form-urlencoded Body
- ``path=paris/LISSHFL.web``, ``format=LISSH_BrowseVorgang_Report``
- ``01_LISSHFL_Themen=<query>`` (Volltext-Thesaurus)
- ``02_LISSHFL_PARL=S OR L`` (Stadt + Landtag in einem Rutsch)
- ``03_LISSHFL_WP=21`` (aktuelle Wahlperiode; Multi-WP-Range
timeout-t den Server bei 60s)
- Wildcards (``*``) timeout-en ebenfalls — bei leerer Query verwenden
wir das hochfrequente Stoppwort ``"der"`` als Catch-all
Hit-Format aus dem Single-Page-HTML:
- ``<tbody name="RecordRepeater"><tr name="Repeat_TYP">``
- Title in ``<h2><a>``
- ``Drs <b>21/730 S</b>`` mit S/L-Suffix für Stadtbürgerschaft vs
Landtag — Drucksachen-IDs werden als ``21/730S`` (ohne Space)
gespeichert
- ``Änderungsantrag vom 23.02.2026`` (Typ + Datum)
- Fraktionen-Liste nach ``<br/>``
- PDF-Link mit ``target="new"`` auf bremische-buergerschaft.de
Pipeline:
- ``search()`` mit client-side ``"antrag"``-Filter (analog #61),
fängt ``"Antrag"``, ``"Änderungsantrag"`` etc.
- ``get_document()`` linearer Lookup
- ``download_text()`` PDF-via-fitz
BL-Eintrag in ``bundeslaender.py``:
- ``HB.aktiv = True``
- ``doku_system="PARiS"`` (statt der alten Klassifikation "StarWeb" —
PARiS ist eine deutlich abweichende Servlet-Variante, kein eUI)
- ``drucksache_format="21/1234S"``
- Test ``test_hb_is_starweb_not_paris`` umbenannt in
``test_hb_is_paris_starweb_variant``, prüft jetzt auf "PARiS"
Live-Probe:
```
21/730S 2026-02-23 | [SPD,GRÜNE,LINKE] | Änderungsantrag | Haushaltsgesetze ...
21/1449 2025-11-05 | [SPD,GRÜNE,LINKE] | Antrag | Finanzierung der Bremischen Häfen
21/555S 2025-06-17 | [CDU] | Antrag | Clima-Campus zügig beantworten
```
176 Unit-Tests grün, Live-Verifikation Sub-A im Container nach Deploy.
Refs: #21, #33, #59 (Phase I)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>