Der Schnitt aus CLAUDE.md ist durchgehalten: - Fetch (deterministisch, kein LLM): marktguru-Adapter mit geprüftem Ortsbezug (zipCode), Wochen-Cache, robots.txt-Respekt, ehrlicher Regel-4- Abbruch bei fehlendem Beleg statt Krücke. - Kategorisierung (einziger LLM-Ort): geschlossene Liste + Daten-Integrität als Code erzwungen; austauschbar via Protokoll (OpenRouter/Anthropic), mit Drosselung/Retry und ehrlichem Abbruch. - FastAPI-Web-UI als dünne Schicht: Modellauswahl (Liste/Suche/Refresh), Live-Fortschritt, gruppierte Ergebnisse mit Filtern, Ergebnis-Cache. - 36 Tests gegen die Architektur-Regeln (kein Auffüllen, Abbruch, Integrität, geschlossene Liste, Unsicherheit, Schnitt) und die Web-Schicht. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.5 KiB
Angebots-Übersicht
Ortskonkrete, händlerübergreifende Übersicht wöchentlicher Supermarkt-Angebote, geordnet nach Produktgruppen. Neutral, nicht als Hochglanzprospekt.
Der Gedanke
Die Aufgabe sieht nach einer KI-Aufgabe aus, ist es aber nur zur Hälfte. Sie zerfällt in zwei strikt getrennte Teile:
- Daten holen -- deterministisch, ohne LLM. (Skill
angebote-fetch) - Kategorisieren -- die echte Ambiguität, hier gehört das LLM hin.
(Skill
angebote-kategorisieren)
Wer alles dem Modell gibt, bekommt erfundene Preise. Wer alles deterministisch löst, scheitert an der Einordnung. Die Architektur erzwingt den Schnitt.
Der zweite Punkt, der dieses Projekt trägt: Qualitätsregeln stehen nicht als gut gemeinte Bitten im Code, sondern als prüfbare Bedingungen -- kein Auffüllen, nur Belegtes, Abbruch statt stiller Drift. Genau dadurch "sagt das System, wenn es scheitert": nicht aus Einsicht des Modells, sondern weil eine externe Bedingung es erzwingt.
Entwicklung mit Claude Code
CLAUDE.md ist der verbindliche Leitfaden. Die beiden SKILL.md in
.claude/skills/ sind die Spezifikationen der zwei Teile. Claude Code liest
sie automatisch -- beim Arbeiten am jeweiligen Teil zuerst die passende
SKILL.md lesen.
Setup
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
Nutzung
# PLZ direkt (immer verlässlich):
python -m angebote 60487
# Ortsname (nur für die in config.py hinterlegte Auswahl großer Städte;
# unbekannter Ort -> ehrlicher Abbruch mit Vorschlag, keine Notlösung):
python -m angebote "Frankfurt"
# Ohne Kategorisierung (kein LLM, flache belegte Liste):
python -m angebote 60487 --no-llm
Der Kategorisier-Schritt braucht ANTHROPIC_API_KEY in der Umgebung. Fehlt er
und es wird kein --no-llm gesetzt, bricht das Programm ehrlich ab, statt
ungeordnet weiterzulaufen.
Stand der Implementierung (ehrlich)
requirements.txt-- vorhanden.src/angebote/-- vorhanden: Datenmodell, Adapter-Schnittstelle, Fetch-Orchestrator, Kategorisier-Schritt, Übersicht-Renderer, CLI.tests/-- vorhanden: Architektur-Tests (kein Auffüllen, Abbruch bei leerem/unauflösbarem Ort, Daten-Integrität nach Kategorisierung, geschlossene Kategorienliste, Unsicherheits-Flag, Schnitt-Test "kein LLM im Fetch-Teil"). Laufen offline, ohne Netz und ohne LLM.- Live bestätigt: der marktguru-Adapter wurde gegen die echte API getestet
(PLZ 60487) und liefert reale, belegte Angebote (u. a. ALDI SÜD, PENNY, Lidl,
REWE, Kaufland, nahkauf). Erkenntnisse aus dem echten Lauf, die direkt in den
Code geflossen sind:
offers/searchist query-orientiert -- leeresqliefert 0 Treffer. Der Adapter aggregiert daher über Kategorie-Seedbegriffe (config) und weist diese Teilabdeckung ehrlich aus, statt Vollständigkeit zu behaupten.- Die pauschale Annahme "Aldi/Lidl fehlen bei Aggregatoren" wurde von den Daten widerlegt (beide sind enthalten). Die Abdeckung wird deshalb datengetrieben ausgewiesen (beobachtete Händler), nicht hartkodiert.
- marktgurus Marken-Sentinel
thisisnobrand123wird als "keine Marke" behandelt, nicht als Beleg durchgereicht.
- Voraussetzungen für den Live-Lauf: installiertes
requests(certifi für TLS), erreichbares Netz, von der Seite lesbare API-Schlüssel. Fehlt eines davon, ist das der vorgesehene Abbruchfall (Regel 4) mit zutreffend benannter Ursache -- keine Krücke.
Struktur
CLAUDE.md Leitfaden / Architektur
README.md dieses Dokument
requirements.txt Abhängigkeiten
.claude/skills/angebote-fetch/ Spec: deterministischer Datenabruf
.claude/skills/angebote-kategorisieren/ Spec: LLM-gestützte Einordnung
src/angebote/ Implementierung
modell.py eingefrorenes Angebot-Datenmodell
fehler.py AbbruchFehler (Regel 4)
config.py Quellenliste, Produktgruppen, Orts-Auflösung
quellen/ ein Adapter pro Quelle (rein = Ort, raus = [Angebot])
basis.py Adapter-Schnittstelle + Ort
marktguru.py erster echter Adapter, geprüfter Ortsbezug
fetch.py Orchestrator (Ort rein, belegte Angebote raus)
kategorisieren.py LLM-Schritt hinter einer Schnittstelle (offline testbar)
uebersicht.py Gruppierung + Rendering
cli.py / __main__.py CLI-Einstieg
tests/ Architektur-Tests