# QDR-001A – Discovery Run Foundation

**Status:** FOR ARCHITECTURE REVIEW  
**Adressat:** LA – Lead Architecture  
**Erstellt durch:** ED – Engineering  
**Datum:** 2026-08-29  
**Scope:** Einführung einer Run-Ebene zur Gruppierung und Vergleichbarkeit von Reconciliation-/Discovery-Verarbeitungen  
**Depends on:** ADR002 – Source Delivery Model, WP3 Discovery Framework, Source Delivery Import v0.1  
**Blocks:** QDR-001B, QDR-001C

---

## 1. Ausgangslage

Reconcilix kann eine `SourceDelivery` mit mehreren `SourceValue` persistieren. Für dieselben `SourceValue` sollen künftig unterschiedliche Discovery- und Reconciliation-Verfahren ausgeführt und anschließend miteinander verglichen werden.

Beispiel:

```text
SourceDelivery
  └── 100 SourceValue
```

Dieselbe Lieferung wird anschließend beispielsweise verarbeitet über:

```text
Run A: xTree / lexical discovery
Run B: Qdrant / vector similarity
Run C: Qdrant / vector similarity + andere Context-Auswahl
Run D: zukünftig LLM-gestützte Interpretation oder Candidate Assessment
```

Das bestehende Modell kann mehrere `InterpretationGraph` pro `SourceValue` speichern. Es fehlt jedoch eine fachlich und technisch eindeutige Klammer, die festhält, welche Graphen zu **demselben konkreten Verarbeitungslauf** gehören.

Ohne diese Ebene kann zwar ein einzelnes Ergebnis persistiert werden, ein belastbarer Vergleich kompletter Läufe ist jedoch nicht eindeutig modelliert.

---

## 2. Ziel

Einführung einer expliziten Run-Entität, die eine konkrete Verarbeitung einer `SourceDelivery` beschreibt und alle dabei erzeugten `InterpretationGraph` gruppiert.

Zielmodell:

```text
SourceDelivery 1 ───── n DiscoveryRun

DiscoveryRun   1 ───── n InterpretationGraph

SourceValue    1 ───── n InterpretationGraph

InterpretationGraph
               1 ───── n InterpretationNode

InterpretationNode
               1 ───── n ReconciliationResult

ReconciliationResult
               1 ───── n CandidateItem
```

Für eine Lieferung mit 100 SourceValues entsteht damit beispielsweise:

```text
SourceDelivery
  ├── DiscoveryRun A: xTree
  │     ├── SourceValue 1  → InterpretationGraph
  │     ├── SourceValue 2  → InterpretationGraph
  │     └── ...
  │
  └── DiscoveryRun B: Qdrant
        ├── SourceValue 1  → InterpretationGraph
        ├── SourceValue 2  → InterpretationGraph
        └── ...
```

---

## 3. Architekturfrage für LA

Der Arbeitsname lautet zunächst:

```text
DiscoveryRun
```

Vor Implementierung ist zu prüfen, ob dieser Begriff langfristig ausreichend weit gefasst ist.

Hintergrund: Die Run-Ebene wird kurzfristig für Discovery-Vergleiche benötigt, perspektivisch aber möglicherweise auch für:

- LLM-basierte Interpretation,
- LLM Candidate Assessment,
- unterschiedliche Prompt-Versionen,
- experimentelle Verarbeitungspipelines,
- kombinierte Discovery-/Interpretationsläufe.

Mögliche Alternativen:

```text
DiscoveryRun
ProcessingRun
ReconciliationRun
```

### ED-Votum

Für den aktuellen Scope ist `DiscoveryRun` fachlich verständlich und ausreichend. Falls LA jedoch davon ausgeht, dass dieselbe Entität künftig eindeutig auch nicht-discovery-zentrierte Verarbeitung kapseln soll, wäre `ProcessingRun` der allgemeinere Begriff.

Die Entscheidung sollte jetzt fallen, bevor der Name in Domain Model, Persistenz, Mappern und Tests verankert wird.

---

## 4. Semantik der Run-Ebene

Ein Run repräsentiert **eine konkrete Ausführung mit einer konkreten Konfiguration** gegen eine definierte `SourceDelivery`.

Ein Run ist damit nicht identisch mit:

- einer Discovery Method,
- einem Adapter,
- einem `InterpretationGraph`,
- einem `ReconciliationResult`,
- einer fachlichen Matching Strategy.

Beispiel:

```text
Run 17
method = VECTOR_SIMILARITY
context_role = item_discovery
rerank = false

Run 18
method = VECTOR_SIMILARITY
context_role = structural_context_discovery
rerank = true
```

Beide Runs verwenden dieselbe Discovery Method, sind aber methodisch unterschiedliche Experimente.

---

## 5. Abgrenzung zu bestehenden Objekten

### 5.1 SourceDelivery

`SourceDelivery` beschreibt die Herkunft und Gruppierung der gelieferten `SourceValue`.

```text
SourceDelivery
→ Was wurde gemeinsam geliefert?
```

Sie beschreibt nicht, wie diese Daten später verarbeitet wurden.

### 5.2 DiscoveryRun

`DiscoveryRun` beschreibt eine konkrete Verarbeitung der gesamten oder einer Teilmenge der `SourceDelivery`.

```text
DiscoveryRun
→ Welche Verarbeitung wurde mit welcher Konfiguration ausgeführt?
```

### 5.3 InterpretationGraph

`InterpretationGraph` bleibt an einen einzelnen `SourceValue` gebunden.

```text
InterpretationGraph
→ Welche Interpretation bzw. welcher Verarbeitungspfad wurde für diesen SourceValue erzeugt?
```

Der Graph gehört zusätzlich genau einem Run.

### 5.4 ReconciliationResult

`ReconciliationResult` beschreibt ein Ergebnis eines konkreten `InterpretationNode`.

```text
ReconciliationResult
→ Mit welcher Matching-/Discovery-Strategie wurde für diesen Node gesucht und welches Resultat entstand?
```

`matching_strategy_uri` bzw. die bestehende Matching-Strategy-Semantik bleibt bestehen und wird durch die Run-Ebene nicht ersetzt.

### 5.5 CandidateItem

`CandidateItem` bleibt das einzelne Candidate-Ergebnis eines `ReconciliationResult`.

Der von Qdrant gelieferte Score wird unverändert in `candidate_item.score` gespeichert.

---

## 6. Vorgeschlagenes Minimalmodell

Für v0.1 wird folgende Persistenz vorgeschlagen:

```text
discovery_run
-------------
id
source_delivery_id
discovery_method
target_vocabulary_uri
scope_vocabulary_uri
started_at
finished_at
status
configuration_json
```

Zusätzlich:

```text
interpretation_graph.discovery_run_id
```

### 6.1 id

Stabile Run-ID gemäß bestehender Reconcilix-Identifier-Strategie.

### 6.2 source_delivery_id

Pflichtreferenz auf genau eine `SourceDelivery`.

### 6.3 discovery_method

Beispiel:

```text
VECTOR_SIMILARITY
```

Für klassische Discovery ist die bestehende WP3-Terminologie zu verwenden.

### 6.4 target_vocabulary_uri

Fachlicher Zielwortschatz des konkreten Runs.

### 6.5 scope_vocabulary_uri

Optionaler eingeschränkter Suchraum innerhalb des Target Vocabulary.

### 6.6 status

Vorgeschlagene Minimalwerte:

```text
CREATED
RUNNING
COMPLETED
FAILED
```

Die endgültigen Statusbezeichnungen sollen an bestehende Reconcilix-Konventionen angepasst werden.

### 6.7 configuration_json

Enthält run-spezifische, technisch variable Optionen, die nicht als stabile fachliche Vergleichsachsen modelliert werden müssen.

Beispiel Qdrant:

```json
{
  "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": 100,
  "rerank": false,
  "output_language": "de"
}
```

---

## 7. Warum `matching_strategy` die Run-Ebene nicht ersetzt

Ein `matching_strategy`-Wert wie

```text
VECTOR_SIMILARITY
```

beschreibt die Art des Matchings.

Er kann jedoch nicht unterscheiden zwischen:

- unterschiedlichen Context-Auswahlen,
- unterschiedlichem Rerank-Modus,
- unterschiedlichen technischen Clients,
- unterschiedlichen Scope-Vocabularies,
- unterschiedlichen Prompt-/Modellversionen,
- Wiederholung desselben Verfahrens zu einem späteren Zeitpunkt.

Deshalb gilt:

```text
Matching Strategy
→ fachliche/technische Matching-Art

DiscoveryRun
→ konkrete Ausführung mit konkreter Konfiguration
```

---

## 8. Vergleichbarkeit von Runs

Durch die Run-Ebene kann für denselben `SourceValue` eindeutig verglichen werden:

```text
SourceValue X
  ├── Graph aus Run A / xTree
  │     └── Candidates
  │
  └── Graph aus Run B / Qdrant
        └── Candidates
```

Mögliche spätere Auswertungen:

- gleicher Top-1 Candidate?
- Candidate nur in Run A / Run B?
- Rangverschiebungen?
- Candidate Count?
- Score-Verteilung?
- Trefferquote gegen Expert Decision?
- Unterschied mit/ohne Rerank?
- Unterschied nach Context-Rolle?

Die Run-Ebene ist damit gleichzeitig Grundlage für spätere Evaluation.

---

## 9. Teilmengen einer SourceDelivery

Ein Run muss nicht zwingend alle `SourceValue` einer `SourceDelivery` verarbeiten.

Die Testbench unterstützt deshalb:

```text
Offset
Anzahl
```

Beispiel:

```text
SourceDelivery: 100 SourceValues
Run: Offset 0, Anzahl 10
```

Der Run bleibt trotzdem der `SourceDelivery` zugeordnet. Welche konkreten SourceValues verarbeitet wurden, ergibt sich über die ihm zugeordneten `InterpretationGraph`.

Damit ist keine zusätzliche Run-to-SourceValue-Zwischentabelle notwendig.

### ED-Votum

Für v0.1 keine zusätzliche Join-Tabelle einführen.

---

## 10. Zukünftige LLM-Metadaten

Mit LLM-Verarbeitung werden zusätzliche Run-Metadaten relevant, beispielsweise:

- Provider,
- Modell,
- Modellversion,
- Prompt-ID,
- Prompt-Version,
- Temperatur,
- weitere Inference-Parameter.

Diese Daten sollen nicht unstrukturiert auf `InterpretationGraph`, `InterpretationNode` oder `CandidateItem` verteilt werden.

Für v0.1 wird noch kein LLM-spezifisches Schema eingeführt.

Die Run-Ebene soll jedoch so gestaltet werden, dass entsprechende Metadaten später ergänzt werden können.

### ED-Votum

Stabile fachliche Identifikatoren später gegebenenfalls als eigene Felder; variable provider-/modell-spezifische Parameter weiterhin in strukturiertem JSON.

---

## 11. Lebenszyklus

Vorgeschlagener Ablauf:

```text
1. Run erzeugen
2. Status CREATED
3. Ausführung starten
4. Status RUNNING
5. je SourceValue InterpretationGraph + Resultate persistieren
6. erfolgreicher Abschluss → COMPLETED
7. Fehler → FAILED
```

Offen für LA/ED:

- Soll bei Teilfehlern ein zusätzlicher Status `COMPLETED_WITH_ERRORS` vorgesehen werden?
- Soll die Run-Ebene Fehlerstatistiken direkt erhalten oder werden diese ausschließlich über Audit/Logging ermittelt?

### ED-Votum v0.1

KISS: zunächst nur `CREATED`, `RUNNING`, `COMPLETED`, `FAILED`.

---

## 12. Migrationswirkung

Die Einführung betrifft mindestens:

- neue Tabelle für Run-Entität,
- FK `interpretation_graph.discovery_run_id`,
- Domain Object / Value Object für Run,
- Mapper,
- Repository,
- Rehydration,
- Tests.

### Abwärtskompatibilität

Bestehende `InterpretationGraph` wurden ohne Run-Kontext erzeugt.

Deshalb sollte `discovery_run_id` in der ersten Migration **nullable** eingeführt werden.

Neue QDR-Testbench-Läufe müssen dagegen immer einen Run referenzieren.

Eine spätere Verschärfung auf `NOT NULL` wäre separat zu entscheiden.

---

## 13. Nicht im Scope von QDR-001A

Nicht Bestandteil dieses Arbeitspakets sind:

- Qdrant HTTP Client,
- Qdrant Credentials,
- Request-/Response-Mapping,
- GUI,
- Candidate Rendering,
- OpenRefine,
- LLM Candidate Assessment,
- Promptverwaltung,
- Score-Normalisierung,
- Evaluation-Metriken.

Diese Punkte folgen in QDR-001B/C oder späteren Arbeitspaketen.

---

## 14. Entscheidungsfragen an LA

1. Ist die zusätzliche Run-Ebene fachlich korrekt und notwendig?
2. Soll die Entität `DiscoveryRun`, `ProcessingRun` oder anders heißen?
3. Ist die Kardinalität `SourceDelivery 1:n Run` korrekt?
4. Ist die Doppelreferenz des `InterpretationGraph` auf `SourceValue` und Run korrekt?
5. Soll `interpretation_graph.discovery_run_id` zunächst nullable bleiben?
6. Reicht `configuration_json` für variable technische Run-Parameter?
7. Sind `target_vocabulary_uri` und `scope_vocabulary_uri` stabile Run-Eigenschaften und damit eigene Felder?
8. Ist der Verzicht auf eine direkte Run-to-SourceValue-Zwischentabelle für v0.1 sinnvoll?
9. Kann dieselbe Run-Ebene perspektivisch LLM-bezogene Verarbeitung aufnehmen oder sollte hierfür frühzeitig ein allgemeinerer Name gewählt werden?

---

## 15. ED-Empfehlung

ED empfiehlt die Einführung der Run-Ebene **vor** der ersten persistierten Qdrant-Testbench-Ausführung.

Die zusätzliche Entität ist kein Qdrant-Sonderfall, sondern schließt eine bereits jetzt sichtbare Modelllücke: mehrere Verarbeitungen derselben `SourceDelivery` müssen reproduzierbar gruppiert und miteinander verglichen werden können.

Nach LA-Freigabe wird QDR-001A implementiert und bildet die technische Voraussetzung für QDR-001B und QDR-001C.
