# QDR-001C – Rx Discovery Testbench

**Status:** IMPLEMENTED / SERVER TEST PENDING  
**Datum:** 2026-08-30  
**Depends on:** QDR-001A Reconciliation Run Foundation, QDR-001B Vector Discovery Infrastructure

## Ziel

QDR-001C stellt ein internes Web-GUI bereit, mit dem bereits importierte `SourceDelivery`-/`SourceValue`-Bestände als expliziter `ReconciliationRun` gegen Vector Discovery/Qdrant ausgeführt werden können.

Entrypoint:

```text
public/discovery-testbench.php
```

## GUI v0.1

Die Testbench enthält:

- SourceDelivery-Auswahl (`external_delivery_id` als Anzeige, `source_delivery.id` als Value)
- `targetVocabularyUri`
- `scopeVocabularyUri`
- Context-Type-Auswahl, initial `https://reconcilix.vocnet.org/context/0001`
- Context-Role-Auswahl: `item_discovery`, `structural_context_discovery`, `NULL`
- Sprachfilter, Default `*`
- `Start` / `Anzahl` für die SourceValue-Population
- Qdrant-Tab mit `rerank`
- sichtbaren, noch leeren LLM-Tab
- einfache Run-/Candidate-Ergebnisansicht

Qdrant Candidate Limit ist für QDR-001C v0.1 bewusst auf `10` gesetzt. Es ist von `Start` / `Anzahl` zu unterscheiden; letztere begrenzen die zu verarbeitenden SourceValues.

## Ablauf

```text
SourceDelivery auswählen
  ↓
SourceValues anhand Delivery + Sprache + Offset/Limit bestimmen
  ↓
ReconciliationRun erzeugen
  ↓
ReconciliationRunItems = explizite Run-Population
  ↓
Run RUNNING
  ↓
pro SourceValue:
  ContextItems nach context_type_uri + context_role filtern
  ↓
  VectorCandidateDiscoveryAdapter
  ↓
  Qdrant
  ↓
  InterpretationGraph + Root Node
  ↓
  ReconciliationResult
    matching_strategy_uri = VECTOR_SIMILARITY
  ↓
  CandidateItem[]
    score = Qdrant score unverändert
    rank = Response-Reihenfolge
  ↓
  RunItem COMPLETED / FAILED
  ↓
Run COMPLETED
```

Einzelne fehlgeschlagene RunItems führen entsprechend QDR-001A nicht automatisch zu `Run FAILED`. Das Item wird `FAILED`; der Run kann nach Verarbeitung der gesamten Population `COMPLETED` werden.

## Run-Konfiguration

Der immutable Snapshot in `reconciliation_run.configuration_json` enthält u. a.:

```json
{
  "discovery_method": "VECTOR_SIMILARITY",
  "adapter_id": "vector-qdrant",
  "client_id": "qdrant-marburg",
  "context_type_uris": [
    "https://reconcilix.vocnet.org/context/0001"
  ],
  "context_roles": [
    "item_discovery",
    "structural_context_discovery"
  ],
  "language": "*",
  "offset": 0,
  "limit": 1,
  "candidate_limit": 10,
  "output_language": "de",
  "rerank": false
}
```

Credentials werden nicht gespeichert.

## Context-Semantik

`context_role` wird ausschließlich Rx-seitig für die Auswahl genutzt. An den Vector-Service gehen weiterhin getrennte Contract-Items:

```json
{
  "typeUri": "https://reconcilix.vocnet.org/context/0001",
  "value": "..."
}
```

Die Rolle wird nicht in den Qdrant-Contract eingeschleust.

## Persistierung

Pro erfolgreich verarbeitetem SourceValue entstehen:

- ein run-gebundener `InterpretationGraph`
- ein Root-`InterpretationNode`
- ein `ReconciliationResult`
- null bis n `CandidateItem`

`CandidateItem.score` übernimmt den Vector-Score ohne Normalisierung.

Die Persistierung von Graph + Result + RunItem-COMPLETED erfolgt pro SourceValue in einer DB-Transaktion. Schlägt dieser Block fehl, wird zurückgerollt und das RunItem anschließend als `FAILED` markiert.

## Neue Dateien

```text
src/Application/DiscoveryTestbench/DiscoveryTestbenchQuery.php
src/Application/DiscoveryTestbench/DiscoveryTestbenchRequest.php
src/Application/DiscoveryTestbench/DiscoveryTestbenchService.php
src/Application/DiscoveryTestbench/VectorDiscoveryAdapterFactory.php
src/Infrastructure/Discovery/Testbench/PdoDiscoveryTestbenchQuery.php
src/Infrastructure/Discovery/Testbench/ConfiguredVectorDiscoveryAdapterFactory.php
public/discovery-testbench.php
tests/Application/DiscoveryTestbench/DiscoveryTestbenchServiceTest.php
```

Geändert:

```text
src/Infrastructure/Composition/ReconciliationCompositionRoot.php
```

## Tests

Lokal grün:

```text
QDR-001C Discovery Testbench Service: OK
QDR-001B Vector Candidate Discovery Adapter: OK
QDR-001B Discovery Method Routing: OK
QDR-001A ReconciliationRun Service: OK
QDR-001A ReconciliationRun Domain: OK
PHP syntax checks: OK
```

## Server-Test

Nach Einspielen sind keine Migrationen erforderlich.

Zuerst:

```bash
php tests/Application/DiscoveryTestbench/DiscoveryTestbenchServiceTest.php
php tests/Infrastructure/Discovery/Adapter/VectorCandidateDiscoveryAdapterTest.php
php tests/Infrastructure/Discovery/Routing/VectorDiscoveryMethodRoutingTest.php
```

Danach Web-GUI öffnen, z. B. abhängig vom Apache Mapping:

```text
https://<rx-host>/v2/discovery-testbench.php
```

Empfohlener erster Realtest:

```text
SourceDelivery: eine Lieferung mit 1 Testrecord
Target: http://matcult-the.vocnet.org
Scope:  http://matcult-the.vocnet.org/00000019
Context Type: .../context/0001
Context Role: item_discovery
Sprache: *
Start: 0
Anzahl: 1
Rerank: aus
```

Danach denselben SourceValue mit `structural_context_discovery` und anschließend mit Rerank ausführen. Jeder Klick erzeugt bewusst einen eigenen `ReconciliationRun`.

## Nicht Scope

- Run-vs.-Run-Vergleichsansicht
- LLM-Verarbeitung
- Modell-/Prompt-Konfiguration
- produktive Benutzer-/Rollenlogik speziell für die Testbench
- Score-Normalisierung
- Candidate-Entscheidungen

## Hotfix 2026-08-30 – Vector API validation details

The Testbench benefits from the corrected Qdrant client error propagation. If the Vector API returns a JSON error such as HTTP 422 with a string `detail`, the per-item error display now includes that detail. No Testbench-specific parsing is required.
