BuyingAgent/.specs/buying-agent-source-discovery-spec-v0.3.md
Lars d784248e28
Some checks failed
Deploy Development / deploy (push) Successful in 55s
Test Suite / pytest-backend (push) Failing after 30s
Test Suite / smoke-dev (push) Successful in 0s
Test Suite / frontend-checks (push) Successful in 26s
Schliesse das Notebook-Source-Mapping, damit Wizard und Taxonomie ohne leere Kategorie starten.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-04 14:17:56 +02:00

26 KiB
Raw Permalink Blame History

Buying Agent – Source & Discovery Specification v0.3

Status: Review Candidate – vor Implementierung erneut durch den Coding-Agenten zu prüfen
Spezifikationsversion: 0.3
Stand: 2026-10-04

Ersetzt vollständig: buying-agent-source-discovery-spec-v0.3.md

Gilt zusammen mit:

  1. buying-agent-v0.1-spec-v1.1.md
  2. buying-agent-architecture-addendum-v1.md
  3. buying-agent-frontend-mvp-spec-v0.3.md

Bei Widersprüchen innerhalb des Source-/Discovery-Bereichs hat diese v0.3 Vorrang.


1. Ziel

Diese Spezifikation definiert den Source-/Discovery-Pfad des funktionierenden MVP.

Sie ist ausdrücklich kein Skeleton und kein theoretischer POC.

Der MVP gilt in diesem Bereich erst dann als funktionsfähig, wenn der reale Pfad:

Produktkategorie wählen
    ↓
SourceCategory bestimmen
    ↓
Geizhals-Taxonomie technisch lernen
    ↓
Filter und URL-Konstrukte verifizieren
    ↓
Kriterien über API/UI anbieten
    ↓
Such-URL aus ProjectCriteria erzeugen
    ↓
SearchRun ausführen
    ↓
Ergebnisse und Attribute parsen
    ↓
Produkte identifizieren / historisieren
    ↓
Diffing
    ↓
Kandidaten / Ranking / Shortlist
    ↓
UI

end-to-end funktioniert.

Initiale Source: Geizhals
Pilotkategorie: Notebooks

Die Architektur darf nicht notebook-spezifisch sein.


2. Grundprinzipien

  1. Geizhals ist Discovery-Quelle, nicht Decision Engine.
  2. Source-Kriterien bilden für unterstützte Kategorien zunächst den primären Kriterienkatalog.
  3. Es gibt keine separate Canonical-Criteria-Schicht.
  4. Jedes gelernte Source-Kriterium erhält eine stabile interne CriterionDefinition.id (UUID).
  5. SearchFilter und Ergebnisattribute werden auf dieselbe CriterionDefinition.id gemappt.
  6. INTERNAL-Kriterien werden nur ergänzt, wenn die Source relevante Eigenschaften nicht kennt.
  7. URL-Encoding wird aus beobachtetem Source-Verhalten gelernt, nicht erfunden.
  8. Nur verifizierte Mappings werden produktiv verwendet.
  9. Taxonomy Learning und normale SearchRuns sind getrennte Prozesse.
  10. Produktidentität bleibt konservativ.
  11. Historie wird strukturiert gespeichert, kein HTML-Archiv.
  12. Discovery, Ranking und Decision bleiben getrennt.
  13. Vollständige Reconciliation darf nur auf vollständigen SearchRuns beruhen.

2.1 Konkret beobachtete Geizhals-Mechanismen für den Notebook-Pilot

Die aktuelle Notebook-Kategorie zeigt bereits ausreichend konkrete Muster, um den MVP-Pfad präziser festzulegen:

  • zahlreiche Filter werden als auswählbare Optionen/Links dargestellt,
  • Filtergruppen umfassen u. a. Hersteller, Diagonale, Auflösung, CPU-Hersteller, CPU-Serie, RAM, Speicher, Grafik, Betriebssystem und Gewicht,
  • Preis, Gewicht und Diagonale sind typische Kandidaten für Range-/Input-Verhalten,
  • die Ergebnisliste enthält bereits einen wesentlichen Teil der für den MVP relevanten Produktdaten, darunter Betriebssystem, Display, CPU, RAM, Speicher, Grafik, Modell-/Produktreferenz, Angebote und Bestpreis.

Diese Beobachtungen dienen als Pilotannahmen und müssen vor finaler Parser-Implementierung am echten Live-DOM validiert werden.


3. ProductCategory und SourceCategory

3.1 ProductCategory

Interner stabiler Katalog:

ProductCategory
id
name
status

Beispiel:

id = notebook
name = Notebooks

3.2 SourceCategory

Mapping zur Source:

SourceCategory
id
source
external_category_key
product_category_id
source_url
status
taxonomy_status
last_taxonomy_scan_at
last_verified_at

Beispiel:

source = geizhals
external_category_key = nb
product_category_id = notebook

4. SourceCategory Readiness

Eine SourceCategory besitzt einen technischen Readiness-Status:

NOT_LEARNED
LEARNING
READY
DEGRADED
BROKEN
BLOCKED

4.1 READY

Eine SourceCategory ist READY, wenn mindestens:

  • Baseline-Kategorieseite erreichbar ist
  • Taxonomie technisch gelesen werden kann
  • relevante Filterdefinitionen persistiert sind
  • verwendbare URL-Encoding-Regeln verifiziert sind
  • Query-Generation erfolgreich getestet wurde
  • Result-Parsing mindestens für Basisdaten funktioniert
  • kein aktiver Block-/Captcha-Zustand vorliegt

4.2 DEGRADED

DEGRADED, wenn:

  • ein Teil der Filter nicht verifizierbar ist
  • einzelne Mappings BROKEN sind
  • Result-Parsing teilweise funktioniert
  • Kategorie grundsätzlich weiter nutzbar ist

4.3 BROKEN

BROKEN, wenn Kernfunktionen nicht mehr zuverlässig arbeiten, z. B.:

  • DOM-Struktur vollständig inkompatibel
  • keine Query-Generierung mehr möglich
  • Result Parser liefert keine verwertbaren Produkte

4.4 BLOCKED

BLOCKED, wenn Sourcezugriff aktuell durch:

  • 403
  • Captcha
  • Challenge
  • wiederholte 429

nicht weitergeführt werden soll.


5. Taxonomy Learning – operativer Algorithmus

Taxonomie wird on demand gelernt.

Der technische Ablauf ist verbindlich.

5.1 Schritt 1 – Baseline laden

Lade die Baseline-Kategorieseite, z. B.:

https://geizhals.de/?cat=nb

Speichere:

source_category
baseline_url
http_status
loaded_at

Keine HTML-Archivierung als Produktfunktion.

Fixtures dürfen für Tests aufgezeichnet werden.

5.2 Schritt 2 – Filtergruppen und Controls erkennen

Der Geizhals-Adapter analysiert die DOM-Struktur.

Zu erkennen sind, soweit vorhanden:

  • Filtergruppen
  • Filterlabel
  • Checkboxen
  • Radio-Optionen
  • Dropdowns
  • Multi-Selects
  • Min/Max-Felder
  • Range-Eingaben
  • freie Texteingaben
  • Links / hrefs
  • optionale source-interne Filter-IDs
  • Einheiten
  • Wertebereiche
  • sichtbare Optionslabels

Primärziel ist nicht die visuelle Darstellung, sondern die strukturelle Filtersemantik.

5.3 Schritt 3 – Filtermechanismus klassifizieren

Jeder erkannte Filter wird genau einem primären Lernweg zugeordnet:

Bevorzugter Weg.

Wenn Geizhals für eine Filteroption einen nutzbaren Link / href bereitstellt, wird dieser direkt ausgewertet.

Beispiel konzeptionell:

<a href="?cat=nb&xf=17023_ab+24GB">ab 24 GB</a>

Der Adapter extrahiert:

label
option_label
href

Typ B – Range-/Input-Control

Für Controls wie Preis, Gewicht oder Diagonale, bei denen der Nutzer Werte eingibt oder einen Bereich setzt:

  1. Baseline-URL erfassen.
  2. einen kontrollierten Testwert setzen,
  3. resultierende Navigation/Query-Änderung erfassen,
  4. Query-Diff bestimmen,
  5. Parametermuster persistieren,
  6. mit einem zweiten Testwert prüfen, ob das Muster reproduzierbar ist.

Typ C – JS-only Control

Nur wenn weder href noch statisch erkennbare Parameterstruktur vorhanden sind:

Playwright-Fallback

Der Browser setzt den Filterzustand und beobachtet die resultierende URL bzw. Query.

Damit gilt die Priorität:

A: href/link
→ B: Range/Input
→ C: Playwright-Fallback

5.4 Schritt 4 – Query-Diff bestimmen

Vergleiche Baseline-Query und Filter-Query.

Beispiel:

Baseline:

?cat=nb

Filterzustand:

?cat=nb&xf=17023_ab+24GB

Query-Diff:

parameter = xf
value = 17023_ab+24GB

Für Preis können z. B. getrennte Parameter wie bpmin / bpmax erkannt werden.

5.5 Schritt 5 – Filterdefinition speichern

Erzeuge / aktualisiere:

SourceFilterDefinition

Mindestens:

id
source_category_id
criterion_definition_id
external_filter_key nullable
label
filter_type
unit nullable
encoding_type
status
last_seen_at
last_verified_at

Filtertypen:

BOOLEAN
ENUM
MULTI_ENUM
NUMERIC_RANGE
NUMERIC_THRESHOLD
TEXT
UNKNOWN

Encoding-Typen mindestens:

OPTION_TOKEN
RANGE_PARAMETERS
BOOLEAN_PARAMETER
TEXT_PARAMETER
UNKNOWN

6. SourceFilterOption / SourceFilterRange

6.1 Diskrete Optionen

SourceFilterOption
- id
- source_filter_definition_id
- source_label
- normalized_value nullable
- operator nullable
- unit nullable
- query_parameter
- query_value
- status

6.2 Range-Filter

SourceFilterRange
- source_filter_definition_id
- min_parameter nullable
- max_parameter nullable
- minimum nullable
- maximum nullable
- step nullable
- unit nullable

7. Playwright-Fallback für JS-only Controls

Wenn ein Filter kein direkt verwertbares href bzw. keine statisch erkennbare Query-Struktur liefert:

Taxonomy Learning
    ↓
Playwright

Ablauf:

  1. Kategorieseite öffnen
  2. Ziel-Filter lokalisieren
  3. Filterwert setzen
  4. Navigation / URL-Änderung abwarten
  5. resultierende URL erfassen
  6. Query-Diff zur Baseline berechnen
  7. Filterzustand wieder zurücksetzen

Wichtig:

  • Playwright ist Fallback, nicht Primärmechanismus.
  • Playwright wird für Taxonomy Learning verwendet, nicht für jeden normalen SearchRun.
  • Kein Captcha-Bypass.
  • Kein Login-Bypass.
  • Kein Umgehen technischer Schutzmechanismen.

8. Mapping Lifecycle

Filter-/Encoding-Mappings besitzen Status:

DISCOVERED
LEARNED_UNVERIFIED
VERIFIED
BROKEN
DISABLED

Nur VERIFIED wird für produktive Query-Generierung verwendet.


9. Roundtrip-Verifikation

Die Roundtrip-Verifikation ist verbindlich.

Beispiel:

RAM >= 24 GB
↓
gelernte Query-Regel
↓
URL selbst generieren
↓
Geizhals aufrufen
↓
aktiven Filterzustand prüfen

Das Mapping wird nur VERIFIED, wenn der Adapter auf der Zielseite eindeutig erkennt, dass der erwartete Filter aktiv ist.

Wenn Verifikation fehlschlägt:

LEARNED_UNVERIFIED

Wenn vorher VERIFIED und nun nicht mehr reproduzierbar:

BROKEN

10. Erkennung von Source-Änderungen

Taxonomy Learning vergleicht:

vorheriger Filterbestand
vs.
aktueller Filterbestand

Zu erkennen sind mindestens:

  • Filter neu
  • Filter verschwunden
  • Filterlabel geändert
  • externe Filter-ID geändert
  • Optionen geändert
  • Encoding geändert
  • Unit geändert
  • Control-Typ geändert

Bei relevanter Änderung:

mapping_version++

Betroffene DiscoverySearches werden:

OUT_OF_SYNC

wenn ihre Query auf geänderten Mappings basiert.


11. CriterionDefinition

Jedes Source-Kriterium erhält eine stabile interne ID:

CriterionDefinition
- id UUID
- origin SOURCE | INTERNAL
- product_category_id
- source_id nullable
- source_category_id nullable
- label
- value_type
- unit nullable
- scoring_attribute_key nullable
- status

CriterionDefinition.id ist Referenzidentität, keine globale Ontologie.


12. SourceAttributeMapping

Suchfilter und Produktattribute müssen verbunden werden.

Dafür:

SourceAttributeMapping
- id
- source_category_id
- source_attribute_key nullable
- source_attribute_label
- criterion_definition_id
- normalizer_id nullable
- status

Matching-Priorität:

  1. stabile Source-Attribute-ID
  2. bekannte SourceAttributeMapping-Regel
  3. normalisiertes Label-Matching
  4. ansonsten UNMAPPED

Keine aggressive automatische Zuordnung bei Unsicherheit.


13. available-criteria

Endpoint:

GET /api/v1/product-categories/{product_category_id}/available-criteria?source=geizhals

Nur verwendbare Kriterien werden dem Standardnutzer als Discovery-Filter angeboten.

Mindestens:

criterion_definition_id
label
filter_type
unit
operators
options / range
mapping_status
supports_discovery

14. Query Generation

Die Source-URL wird ausschließlich aus:

SourceCategory
+
aktuelle ProjectCriteria
+
VERIFIED SourceFilterMappings

erzeugt.

Keine URL-Templates aus LLM.

Keine hartcodierten notebook-spezifischen Query-Fragmente außerhalb des Geizhals-Adapters / Source-Datenmodells.

Die Query-Generierung muss deterministisch, reproduzierbar, testbar und versionsgebunden sein.


15. SearchRun

Ein SearchRun hält mindestens:

discovery_search_id
criteria_version
mapping_version
generated_url
started_at
finished_at
status
result_count
page_count
new_count
changed_count
unchanged_count
missing_count

16. Ergebnisabruf und Pagination

Ein Full SearchRun versucht grundsätzlich die vollständige Ergebnismenge zu lesen.

Wenn nicht alle Seiten vollständig gelesen werden:

SearchRun.status = PARTIAL

Ein PARTIAL-Run darf keine:

MISSING
DISAPPEARED

Transitions erzeugen.


17. TOO_BROAD

Eine DiscoverySearch darf einen konfigurierbaren Schwellenwert besitzen.

Beispiel:

broad_result_threshold = 300

Bei Überschreitung:

SearchRun.status = TOO_BROAD

Kein stilles Top-N-Limit.

Ein technischer Safety-Cap ist zulässig, wenn er explizit konfiguriert und sichtbar dokumentiert ist; der Lauf gilt dann nicht als Full Run.


18. Zweistufige Datenerfassung

Die Suchergebnisliste ist die primäre Datenquelle des MVP.

Der Notebook-Pilot muss zunächst möglichst viel aus der Ergebnisliste gewinnen, bevor zusätzliche Produktdetailseiten geladen werden.

18.1 Stufe A – Suchergebnisliste

Jeder SearchRun liest aus der Ergebnisliste mindestens:

source_product_url
title
manufacturer/model soweit sichtbar
best_price
currency
availability soweit sichtbar
seller_count soweit sichtbar
sichtbare Attribute

Für die Notebook-Kategorie sind insbesondere folgende sichtbare Basisattribute als realistische MVP-Felder zu validieren:

Betriebssystem
Display
CPU
RAM
Speicher
Grafik
Modell-/Produktreferenz
Angebote
Bestpreis

Die genaue DOM-Struktur und die Verfügbarkeit einzelner Felder dürfen nicht vorab erfunden werden; sie werden im technischen Spike und Live-Pilot bestätigt.

18.2 Stufe B – Produktdetailseite

Produktdetailseiten werden nicht blind für alle Treffer geladen.

Sie werden für relevante Kandidaten geladen, insbesondere:

  • Shortlist
  • Top-N nach ProductScore
  • Kandidaten mit fehlenden für Ranking relevanten Attributen
  • Kandidaten mit unsicherer Identität, wenn Detailseite helfen kann

Der Notebook-Pilot muss praktisch feststellen, welche Daten auf Liste und Detailseite verfügbar sind.


19. SourceProductReference

Mindestens:

id
source_id
source_category_id
source_url
source_title
manufacturer nullable
model nullable
manufacturer_sku nullable
gtin_ean nullable
normalized_spec_fingerprint nullable
match_status
lifecycle_status
first_seen_at
last_seen_at

20. Produktidentität – konservativer Pilot

Signalreihenfolge:

  1. stabile Source-ID, falls entdeckt
  2. GTIN/EAN
  3. Hersteller-SKU
  4. kanonische Source-URL
  5. normalisierter Titel
  6. Hersteller + Modell
  7. differenzierende Specs

Bei Unsicherheit:

MATCH_UNCERTAIN

Kein automatisches Merge.


21. ProductObservation

ProductObservation
- id
- source_product_reference_id
- search_run_id
- observed_at
- raw_title
- best_price
- currency
- availability nullable
- seller_count nullable

22. ProductAttributeObservation

ProductAttributeObservation
- product_observation_id
- criterion_definition_id nullable
- raw_name
- raw_value
- normalized_value nullable
- unit nullable
- mapping_status

Wenn kein Mapping existiert:

criterion_definition_id = null
mapping_status = UNMAPPED

Unmapped Felder dürfen für spätere Admin-Korrektur sichtbar bleiben.


23. Normalisierung

Normalizer arbeitet kriteriumsabhängig.

Beispiele:

"32 GB" -> 32 / GB
"1 TB" -> 1024 / GB, falls Zielunit GB
"1,45 kg" -> 1.45 / kg

Zu speichern:

raw_value
normalized_value
unit
normalizer_version

24. Diffing

Verglichen werden nur vollständige Runs derselben DiscoverySearch.

Run Diff:

NEW
CHANGED
UNCHANGED
MISSING

CHANGED mindestens bei relevanter Änderung von:

best_price
currency
availability
seller_count
normalisierte Attribute

25. Product Lifecycle

ACTIVE
DISAPPEARED
ARCHIVED

Regeln:

1 Full Run fehlend -> Run Diff MISSING
3 aufeinanderfolgende Full Runs fehlend -> Lifecycle DISAPPEARED

26. Ranking und Shortlist

Bestehende Scoring-Engine kann über:

CriterionDefinition.scoring_attribute_key

angesprochen werden.

Ohne Ranking-Konfiguration:

ranking_status = NOT_CONFIGURED

Mit Ranking:

ProductScore
product_eligibility

Shortlist Default: 5


27. Scheduling und Backoff

Default:

180 Minuten

auf DiscoverySearch.

Defensives Verhalten:

  • Timeout
  • Retry mit exponentiellem Backoff
  • Jitter
  • 429 -> BACKOFF
  • 403 -> BLOCKED
  • Captcha / Challenge -> BLOCKED
  • wiederholte Parsing-Fehler -> DEGRADED/BROKEN

Keine Schutzumgehung.


28. UI-Reaktion auf SourceCategory Readiness

READY

Normale Kriterienauswahl und Suchanlage.

NOT_LEARNED

UI zeigt: „Kriterien für diese Produktkategorie werden gerade vorbereitet.“

LEARNING

Loading-/Progress-Zustand.

DEGRADED

VERIFIED Kriterien dürfen angeboten werden; Warnung anzeigen.

BROKEN

Keine neue produktive Suche.

BLOCKED

Quelle derzeit nicht automatisiert abfragbar.


29. Taxonomy Learning API

Mindestens:

POST /api/v1/sources/{source}/categories/{category}/discover-taxonomy
GET  /api/v1/sources/{source}/categories/{category}/taxonomy-status
GET  /api/v1/sources/{source}/categories/{category}/filters

Response mindestens:

source_category_status
filters_discovered
filters_verified
filters_unverified
filters_broken
mapping_version
last_scan_at

30. Source Adapter Contract

class DiscoverySourceAdapter(Protocol):
    def load_category_baseline(category_ref): ...
    def discover_filter_controls(document): ...
    def extract_filter_links(document): ...
    def derive_query_diff(baseline_url, filtered_url): ...
    def verify_filter_roundtrip(filter_definition, encoded_query): ...
    def build_query(criteria, mappings): ...
    def fetch_result_page(url): ...
    def parse_result_page(document): ...
    def parse_product_detail(document): ...
    def extract_active_filters(document): ...
    def normalize_source_attribute(raw_attribute): ...

Playwright darf intern als Fallback-Service genutzt werden.


31. Technische Module

Mindestens logisch getrennt:

sources/geizhals/
  category_loader
  taxonomy_parser
  filter_encoder
  roundtrip_verifier
  result_parser
  product_detail_parser

discovery/
  taxonomy_service
  criterion_service
  mapping_service
  search_execution_service
  identity_service
  observation_service
  diff_service
  candidate_service
  shortlist_service

Keine Geizhals-DOM-Logik außerhalb sources/geizhals.


32. Verpflichtender technischer Geizhals-Spike vor finalem Parserbau

Vor der finalen Implementierung der Geizhals-Parser muss der Coding-Agent die echte Notebook-Seite technisch inspizieren.

Der Spike muss dokumentieren:

  1. stabile DOM-Anker bzw. semantisch belastbare Selektoren,
  2. tatsächliche Struktur der Filtergruppen,
  3. Klassifikation der Filter in Typ A/B/C,
  4. konkrete href-/Query-Muster mehrerer Filter,
  5. tatsächliches Verhalten von Preis, Gewicht und Diagonale,
  6. Pagination-Struktur,
  7. Produktkarten-/Ergebnisstruktur,
  8. verfügbare Felder direkt in der Ergebnisliste,
  9. Unterschiede zwischen Listen- und Produktdetaildaten,
  10. auffällige dynamische/JS-geladene Bereiche.

Wichtig:

  • keine CSS-Klassen, DOM-Pfade oder Selektoren vorab erfinden,
  • bevorzugt stabile semantische Attribute oder Source-eigene IDs verwenden,
  • fragile rein visuelle Selektoren nur, wenn keine robustere Alternative existiert,
  • die Ergebnisse des Spikes müssen unmittelbar in Fixtures und Parser-Tests überführt werden.

Der Spike ist Teil der MVP-Umsetzung, nicht optionale Vorarbeit.


34. Fixtures

Fixtures sind für reproduzierbare Tests Pflicht.

Mindestens:

  • Notebook Baseline Category HTML
  • Kategorie mit gesetztem RAM-Filter
  • Kategorie mit Preisbereich
  • Ergebnisliste Seite 1
  • Ergebnisliste Seite 2
  • Produktdetailseite
  • geänderte DOM-Version / broken fixture
  • Captcha/Challenge fixture, soweit technisch sinnvoll
  • 429/403 als HTTP-Testzustände

34. Unit Tests

Mindestens:

Taxonomy

  • Filtergruppen erkannt
  • Filterlabel erkannt
  • href extrahiert
  • Query-Diff korrekt
  • Filteroption gespeichert
  • Range-Parameter erkannt
  • JS-only Control nutzt Fallback-Pfad
  • Mapping Lifecycle korrekt
  • Roundtrip -> VERIFIED
  • Roundtrip fail -> LEARNED_UNVERIFIED
  • ehemals VERIFIED + fail -> BROKEN

Attribute Mapping

  • RAM -> richtige CriterionDefinition
  • unbekanntes Label -> UNMAPPED
  • Source-ID hat Vorrang vor Label
  • Unit-Normalisierung korrekt

Query Generation

  • nur VERIFIED
  • deterministisch
  • criteria_version/mapping_version gebunden
  • INTERNAL ohne Source-Mapping beeinflusst URL nicht

35. Integration Tests

Mindestens:

Taxonomy Fixture
→ DB
→ available-criteria
→ ProjectCriteria
→ Query Generation
→ SearchRun Fixture
→ Result Parse
→ SourceProductReference
→ ProductObservation
→ ProductAttributeObservation
→ Diff
→ Candidate DTO

36. Manueller Live-Notebook-Pilot

Der MVP gilt im Source-/Discovery-Bereich nicht als abgenommen, solange kein dokumentierter Live-Pilot gegen die echte Geizhals-Notebook-Kategorie erfolgreich durchgeführt wurde.

Der Pilot muss mindestens zeigen:

  1. Notebook-Kategorie wird erreichbar geladen.
  2. reale Filter werden erkannt.
  3. mehrere unterschiedliche Filtertypen werden gelernt.
  4. RAM-Filter wird technisch korrekt gelernt.
  5. Preisfilter wird technisch korrekt gelernt.
  6. Roundtrip-Verifikation funktioniert.
  7. available-criteria liefert reale Filter.
  8. daraus wird eine reale Such-URL generiert.
  9. reale Suchergebnisse werden gelesen.
  10. mindestens Titel + Produktlink + Preis werden extrahiert.
  11. sichtbare Produktattribute werden gemappt.
  12. mindestens zwei SearchRuns erzeugen History/Diff.
  13. UI kann daraus Kandidaten anzeigen.

Der Live-Pilot muss mindestens einen vollständigen technischen Kettennachweis enthalten:

echte Filtergruppe erkannt
→ href/Input-Verhalten ermittelt
→ Query-Regel gelernt
→ Roundtrip verifiziert
→ reale Ergebnisse geparst
→ reale Attribute auf CriterionDefinition gemappt

Live-Pilot wird manuell/dokumentiert ausgeführt, nicht in CI.


37. Fehlerfälle

DOM geändert

DEGRADED oder BROKEN

Filter nicht verifizierbar

LEARNED_UNVERIFIED

URL-Encoding geändert

früher VERIFIED, Roundtrip scheitert:

BROKEN
mapping_version++
DiscoverySearch -> OUT_OF_SYNC

Result Parser unvollständig

teilweise Daten -> DEGRADED
keine verwertbaren Produkte -> BROKEN

Source blockiert

BLOCKED

Taxonomie teilweise verfügbar

VERIFIED Kriterien dürfen weiter angeboten werden.


38. Kein stiller Fallback

Nicht erlaubt:

  • Filter-Encoding raten
  • unbekannte Source-Attribute automatisch mergen
  • unvollständigen Run als vollständigen Run behandeln
  • BROKEN Mapping weiterverwenden
  • fehlende Kriterien durch frei erfundene Defaults ersetzen
  • Candidate Ranking mit nicht belegten Attributen auffüllen

39. Definition of Done

Taxonomy / URL Learning

  • Kategorieseite wird real gelesen.
  • Filter werden aus dem DOM erkannt.
  • href-basierte Filter werden automatisch gelernt.
  • Query-Diff funktioniert.
  • Range-Parameter funktionieren.
  • Playwright-Fallback existiert für JS-only Controls.
  • Roundtrip-Verifikation existiert.
  • Mapping Lifecycle funktioniert.
  • Geizhals-Strukturänderungen werden erkannt.
  • SourceCategory Readiness funktioniert.

Criteria / Mapping

  • Source-Kriterien erhalten stabile CriterionDefinition-UUIDs.
  • SearchFilter referenziert CriterionDefinition.
  • SourceAttributeMapping referenziert dieselbe CriterionDefinition.
  • UNMAPPED Attribute bleiben sichtbar.
  • INTERNAL-Kriterien möglich.
  • available-criteria basiert auf real gelernter Taxonomie.

Search / Results

  • Query-Generierung nutzt nur VERIFIED Mappings.
  • Full Pagination funktioniert.
  • PARTIAL wird korrekt erkannt.
  • PARTIAL löst kein MISSING/DISAPPEARED aus.
  • Basisdaten aus Ergebnisliste werden extrahiert.
  • Produktdetailseite kann gezielt angereichert werden.
  • SourceProductReference funktioniert.
  • ProductObservation funktioniert.
  • ProductAttributeObservation funktioniert.
  • Attribute werden normalisiert/historisiert.

Diff / Candidate

  • NEW / CHANGED / UNCHANGED / MISSING funktionieren.
  • DISAPPEARED nach drei Full Runs.
  • Candidate DTOs werden erzeugt.
  • Ranking nutzt nur vorhandene gemappte Daten.
  • Shortlist funktioniert, wenn Ranking konfiguriert.

MVP Acceptance

  • Notebook Live-Pilot vollständig dokumentiert.
  • echte Geizhals-Kriterien im UI sichtbar.
  • echte Such-URL aus UI-Kriterien generiert.
  • echte Resultate eingelesen.
  • echte Preise/Attribute angezeigt.
  • History/Diff über mindestens zwei Runs sichtbar.
  • Source-/Discovery-Pfad end-to-end über UI nutzbar.

40. Arbeitsauftrag an den Coding-Agenten

Diese Datei ersetzt buying-agent-source-discovery-spec-v0.2.md vollständig.

Bitte noch nicht implementieren.

Prüfe erneut den aktuellen Repository-Stand gegen:

  1. buying-agent-v0.1-spec-v1.1.md
  2. buying-agent-architecture-addendum-v1.md
  3. buying-agent-source-discovery-spec-v0.3.md
  4. buying-agent-frontend-mvp-spec-v0.3.md

Prüfe insbesondere:

  • ob der Taxonomy-Learning-Algorithmus vollständig implementierbar beschrieben ist,
  • ob DOM/href-basierte Discovery ausreicht bzw. welche konkreten Geizhals-Strukturen im Live-Pilot validiert werden müssen,
  • ob Playwright-Fallback sauber begrenzt ist,
  • ob Query-Diff + Roundtrip-Verifikation widerspruchsfrei sind,
  • ob SourceFilterMapping und SourceAttributeMapping klar getrennt sind,
  • ob dieselbe CriterionDefinition-ID Search und Result Attributes verbindet,
  • ob Readiness-Status ausreichend definiert sind,
  • ob zweistufige Datenerfassung (Liste/Detailseite) implementierbar ist,
  • ob Full/PARTIAL-Semantik vollständig ist,
  • ob der Notebook Live-Pilot als echte MVP-Abnahme genügt,
  • ob der technische Geizhals-Spike vor finalem Parserbau ausreichend konkret beschrieben ist,
  • ob stabile DOM-Anker und Pagination im Live-DOM ohne erfundene Selektoren verifiziert werden können,
  • ob Ergebnislisten-Daten für den MVP tatsächlich ausreichen und welche Felder zwingend Detailseiten benötigen.

Berichte ausschließlich:

  • verbleibende echte fachliche Widersprüche,
  • fehlende technische Verträge,
  • technisch riskante Annahmen,
  • notwendige Backend-Änderungen,
  • notwendige Frontend-Änderungen.

Keine neue Fachlogik erfinden.

Wenn keine blockierenden Punkte mehr bestehen:

  1. aktualisierten vertikalen Implementierungsplan erstellen,
  2. jeder Slice muss über die UI prüfbar sein,
  3. Taxonomy Learning + Query Generation + Result Parsing früh implementieren,
  4. Live-Notebook-Pilot vor Abschluss durchführen,
  5. Implementierung erst nach ausdrücklicher Freigabe des Reviews starten.