Neues Modul quellen/ki_hilfe.py (konsistent zum dedup-LLM-Muster):
- Struktur-Erkennung: bei verdächtig leerem Parser-Ergebnis schlägt das
LLM Pagination-/Filter-Folge-URLs vor; hart gefiltert auf gleiche
Domain, max. 20 je Seite, nicht erreichbare Vorschläge brechen den
Lauf nicht ab.
- Feld-Extraktion: nur unsichere Treffer (fehlender Verlag, verdächtiger
Titel); korrigiert ausschließlich titel/verlag/autor, niemals die URL.
- Env-Konfiguration SPIELE_NEUHEITEN_KI_* (AKTIV default 0,
KONFIDENZ_MIN default 0.7), OpenAI-kompatible Chat-Completions via
httpx mit Timeout und genau einem Retry.
- Fallback-Pflicht: ohne Konfiguration oder bei jedem Fehler läuft exakt
der klassische Crawler; KI-Fehler blockieren den Sync nie.
- Audit: KI-Eingriffe je Quelle und Lauf ins audit-log (Modell,
Konfidenz, korrigierte Felder, verfolgte Folge-URLs).
20 neue Tests (gemocktes HTTP/LLM): Fallback-Fälle, Konfidenz-Schwelle,
Domain-Filter, Max-20-Grenze, URL-Unveränderbarkeit, Audit.
BoardGameGeek verlangt für die XML API2 jetzt Bearer-Authentifizierung
(Thread 3602374); ohne Token antwortet die API mit 401.
- BggClient: neuer Parameter token, sendet Authorization: Bearer … auf
allen Requests; Token kommt aus SPIELE_BGG_TOKEN (vor jedem Sync gelesen)
- HTTP 401 → klarer BggAuthFehler ('BGG hat die Anfrage abgelehnt (401) —
bitte gültigen API-Token in SPIELE_BGG_TOKEN hinterlegen.') statt
generischer Meldung, kein Retry
- Ohne konfigurierten Token wird der Sync übersprungen ('Kein BGG-API-Token
konfiguriert (SPIELE_BGG_TOKEN) — Sync übersprungen.'), statt Requests zu
feuern; Meldung erscheint im Sync-Ergebnis, UI-Banner und Protokoll
- SyncService: BggAuthFehler bricht den Lauf ab (weitere Suchbegriffe
scheitern zwangsläufig gleich), Teilergebnisse bleiben erhalten
- Tests: Bearer-Header, 401-Fall (Client/Sync/UI), Skip ohne Token;
bestehende Sync-UI-Tests setzen Test-Token
- README: neue Env-Variable SPIELE_BGG_TOKEN + Hinweis auf Token-Pflicht
- Datenmodell + eigene Migration 0001_neuheiten_tabelle (Tabelle neuheiten:
Titel, Verlag, Autor, Erscheinungsjahr, BGG-ID, Status 'neuheit', Quelle,
Zeitstempel; bgg_id eindeutig als Merge-Kriterium)
- BoardGameGeek XML API2-Client (search + thing, Batches à 20 IDs):
Rate-Limit >= 1 s zwischen Requests, Retry mit exponentiellem Backoff bei
5xx/429/Netzwerkfehlern, HTTP 202 gemäß Retry-After, robustes XML-Parsing;
Transport/Uhr/Sleep injizierbar (keine echten Calls in Tests)
- Filter: Erweiterungen (boardgameexpansion) auf Request- und Elementebene
ausgeschlossen; Prototypen per Titel-Heuristik (BGG hat keinen Marker)
- Sync-Service mit Update-statt-Duplikat-Logik über die eindeutige BGG-ID
(Status bleibt erhalten); Fehler je Suchbegriff brechen den Lauf nicht ab
- APScheduler-Hintergrundjob (Standard 24 h) mit Überlappungsschutz,
abschaltbar/intervallkonfigurierbar per Env; manueller
'Jetzt synchronisieren'-Endpunkt nur für Admin/Redakteur, optional mit
Sofort-Suchbegriff
- UI /neuheiten: sortier-/filterbare Tabelle mit Volltextsuche (HTMX-Teilladung,
noscript-fähig), deutsche Oberfläche, BGG-Links, Ergebnis-Banner
- Plugin-Loader: idempotentes Laden (Modul-Caching), damit mehrere
create_app()-Aufrufe dieselben Plugin-Klassen/Tabellen nutzen
- Tests: Parsing, Erweiterungs-/Prototyp-Filter, Rate-Limit/Backoff/202,
Update-statt-Duplikat, Rollen am Sync-Endpunkt, Scheduler-Lifecycle —
ausschließlich mit gemockten BGG-Antworten (uv run pytest: 96 grün)
- README/AGENTS: Plugin-Doku, Env-Variablen, Fortschrittstabelle aktualisiert