Ja. Ich würde jetzt **nicht den großen Discovery-Profile-Umbau in einem Zug machen**. Wir können Geschwindigkeit und Struktur verbinden, wenn wir in zwei unmittelbar aufeinanderfolgenden Refactorings arbeiten und dabei die 150 E004-Fälle als Regressionstest benutzen.

## Zielbild

Wir zerlegen den heutigen RxStore funktional in drei Bereiche:

```text
                         Reconcilix
                            │
              ┌─────────────┼─────────────┐
              ▼             ▼             ▼
       Normalization     Discovery     Fachwissen
        generisch         generisch       extern
              │             │             │
              │             │      Mapping Vocabulary
              │             │          Dehio → MCT
              └─────────────┼─────────────┘
                            ▼
                      CandidateItems
```

Damit bekommen wir genau die gewünschte Trennung:

**A – generische Normalisierung**
providerunabhängig, später für RxStore und xTree nutzbar.

**B – generische Discovery Methods**
`EXACT_STRING`, `*_TRUNCATED`, später `LEVENSHTEIN` usw.

**C – Dehio-Fachwissen**
raus aus PHP und hinein in die Mapping Resource.

---

## Phase 1 – zuerst das Fachwissen aus dem RxStore bergen

Das würde ich **vor dem eigentlichen Refactoring** machen. Sonst besteht die Gefahr, dass wir beim Aufräumen Wissen verlieren, das im Juni ergebnisgetrieben entstanden ist.

Wir nehmen `QueryTokenizer` und die angrenzende RxStore-Logik und klassifizieren jede Regel:

```text
bestehende Regel
       │
       ├── GENERIC_NORMALIZATION
       │
       ├── GENERIC_DISCOVERY
       │
       ├── DEHIO_MAPPING
       │
       ├── RANKING
       │
       └── LEGACY / unklar
```

Für `DEHIO_MAPPING` prüfen wir anschließend gegen das vorhandene Mappingvokabular:

```text
bereits vorhanden
→ nichts tun

fehlt, fachlich eindeutig aus bisheriger Arbeit
→ ergänzen

widerspricht vorhandenem Mapping
→ nicht automatisch ändern
→ Review-Liste

unklar/riskant
→ Review-Liste
```

Das ist wichtig. Ich würde beispielsweise **nicht automatisch aus der PHP-Suffixliste 30 neue Dehio-Mappings generieren**. `Wolfsburg → Burg` hat uns bereits gezeigt, weshalb.

Dagegen können Informationen wie eine bereits explizit kuratierte Entsprechung sehr wahrscheinlich übernommen werden.

Am Ende erhalten wir also zusätzlich:

```text
Dehio Mapping Vocabulary vNext
+
Mapping Review List
```

Damit haben wir zuerst unser historisches Wissen gesichert.

---

## Phase 2 – RxStore auf einen sauberen generischen Kern reduzieren

Danach würde ich `exact-with-token-fallback` nicht weiterentwickeln, sondern schrittweise ablösen.

Zunächst brauchen wir nur **eine** sauber definierte Method:

```text
LexicalDiscoveryMethod
└── EXACT_STRING
```

und einen klar abgegrenzten Normalizer davor.

Sinngemäß:

```text
SourceValue
   ↓
GenericNormalizer
   ↓
EXACT_STRING
   ↓
RxStore
```

Der `GenericNormalizer` darf zunächst nur Dinge enthalten, bei denen wir uns sicher sind:

```text
Unicode-/Case-Normalisierung
Whitespace-Normalisierung
definierte Interpunktionsnormalisierung
```

Morphologie würde ich im ersten Commit noch nicht großzügig hineinnehmen. Gerade `Herrenhauses → Herrenhaus` zeigt zwar die Richtung, aber bevor wir eine selbstgebaute deutsche Lemmatisierung erzeugen, sollten wir definieren, was `MORPHOLOGICAL_NORMALIZATION` tatsächlich leisten soll.

Der alte `QueryTokenizer` bleibt währenddessen noch vorhanden, aber als **Legacy-Pfad**. Damit müssen wir nicht Big Bang spielen.

---

## Phase 3 – `MAPPED_VOCABULARY` implementieren

Das wäre unmittelbar danach der zweite neue Methodentyp:

```text
family: MappingDiscoveryMethod
method: MAPPED_VOCABULARY
resource: Dehio-Mappingvokabular
```

Dann können wir bereits unser erstes echtes Profil ausführen:

```text
DEHIO_MCT_V01

Step 1
  family: LexicalDiscoveryMethod
  method: EXACT_STRING
  condition: ALWAYS

Step 2
  family: MappingDiscoveryMethod
  method: MAPPED_VOCABULARY
  resource: dehio-mct
  condition: ON_ZERO_RESULTS
```

**Das würde ich als erstes produktives Discovery Profile bauen.**

Warum nicht zuerst alle vier `*_TRUNCATED`? Weil wir für Dehio das Mappingvokabular bereits besitzen und evaluieren können. Damit bekommen wir schneller einen fachlich sinnvollen neuen RxStore als mit einem kompletten generischen Lexical-Framework.

---

## Phase 4 – Profile zunächst klein halten

Für die Persistenz brauchen wir keine Ontologie-Engine und keinen Rule Interpreter.

Eine erste Konfiguration kann strukturell schon sauber sein:

```json
{
  "profile": "DEHIO_MCT_V01",
  "steps": [
    {
      "sequence": 1,
      "family": "LexicalDiscoveryMethod",
      "method": "EXACT_STRING",
      "condition": "ALWAYS"
    },
    {
      "sequence": 2,
      "family": "MappingDiscoveryMethod",
      "method": "MAPPED_VOCABULARY",
      "resource": "dehio-mct",
      "condition": "ON_ZERO_RESULTS"
    }
  ]
}
```

`options` ist Bestandteil des Schemas, auch wenn diese beiden Methods zunächst keine benötigen:

```json
"options": {}
```

Damit verbauen wir Levenshtein etc. nicht:

```json
{
  "method": "LEVENSHTEIN",
  "options": {
    "max_distance": 2
  }
}
```

---

## Phase 5 – anschließend xTree auf dieselbe Semantik bringen

Erst wenn Profil B im RxStore funktioniert, würde ich xTree anschließen.

Das Ziel ist dann wirklich:

```text
                     EXACT_STRING
                     /          \
                    /            \
             RxStoreAdapter    XtreeAdapter
                │                  │
          exactString()       exactString()
                                   │
                              xTree API
                         searchType=exactString
```

Und:

```text
                  MAPPED_VOCABULARY
                     /          \
                    /            \
             RxStoreAdapter    XtreeAdapter
```

Wobei wir noch prüfen müssen, **wo** das Mapping sinnvoll ausgeführt wird. Ich würde nicht automatisch voraussetzen, dass xTree selbst `MAPPED_VOCABULARY` implementieren muss. Es kann auch eine Rx-seitige Method sein, deren Resultat anschließend auf das Zielvokabular verweist.

Das sollten wir beim Design konkret entscheiden.


So, 06.09.2026: Plan für Phase 5

```text
5.1 Discovery Step Execution
Plan ↔ tatsächliche Step-Ausführung persistent machen

5.2 Candidate Discovery Evidence
Candidate ↔ ausführender Step n:m nachvollziehbar machen

5.3 Discovery Capture Integration
Raw Provider Response ↔ Step Execution verbinden

5.4 Workbench Projection
Discovery-Verlauf und Candidate-Herkunft anzeigen

5.5 Phase-6 Readiness
Profile/Run-Vergleich auf Step-Ebene

```
---

## Phase 6 – danach generische Lexical Methods

Erst anschließend:

```text
EXACT_STRING
RIGHT_TRUNCATED
LEFT_TRUNCATED
BOTH_TRUNCATED
LEVENSHTEIN
```

Dann implementieren RxStore und xTree dieselbe definierte Semantik.

Damit können wir beispielsweise ein generisches Profil anbieten:

```text
LEXICAL_EXTENDED_V01

EXACT_STRING
    ↓ ON_ZERO_RESULTS
RIGHT_TRUNCATED
    ↓ ON_ZERO_RESULTS
LEFT_TRUNCATED
    ↓ ON_ZERO_RESULTS
BOTH_TRUNCATED
```

und ein anderes:

```text
LEXICAL_FUZZY_V01

EXACT_STRING
    ↓ ON_ZERO_RESULTS
LEVENSHTEIN
    options.max_distance = 2
```




2026-09-07: next: OR-Runs → Testbench/xTreeAPI sauber trennen 
→ Profile/Scoring 
→ kleine Workbench-Anpassungen 
→ xTree/RxStore Regression 
→ anschließend Architekturentscheid Qdrant/Lobid GND.
```
Ja, so ist die Reihenfolge für mich deutlich klarer. Ich würde sie genau so strukturieren und nur an zwei Stellen etwas schärfen, damit wir uns nicht wieder unterschiedliche Ebenen vermischen.

Für den **unmittelbaren nächsten Block** sehe ich vier Punkte:

1. **OpenRefine bekommt ebenfalls echte Runs.**
   Der normale OR-Pfad sollte wie die Testbench `ReconciliationRun` und `ReconciliationRunItem` erzeugen. Dann sind Profile, Steps, Candidate Evidence und spätere Vergleiche nicht nur in der Testbench, sondern auch im produktiven Adapterpfad sauber nachvollziehbar.

2. **Testbench: Profile auch explizit über xTreeAPI testen.**
   Hier würde ich zwei Testarten unterscheiden:

    * direkt `xTreeAPI` mit einer einzelnen Method wie `EXACT_STRING`
    * `PROFILE`, das intern mehrere xTree-Methoden sequenziert

   Damit können wir später sauber unterscheiden: *Adapter-/API-Verhalten* versus *Profile Execution*.

3. **Danach Profile/Scoring abstimmen.**
   Das halte ich für den richtigen Zeitpunkt. Erst wenn mehrere Methods tatsächlich laufen und Evidence vorhanden ist, können wir vernünftig entscheiden:

    * ob Scores methodenabhängig interpretiert werden,
    * wie Kandidaten aus mehreren Steps zusammengeführt werden,
    * ob ein späterer Step einen bestehenden Candidate nur ergänzt oder neu bewertet,
    * wie `rank`, `score`, `method` und ggf. Step-Priorität zusammenspielen.

4. **Kleine Workbench-Anpassungen.**
   Erst nach der Scoring-Entscheidung. Sonst bauen wir Anzeigeelemente auf eine noch nicht stabile Semantik.

Danach würde ich den zweiten Block genau in deiner Richtung aufziehen:

* **xTreeAPI weiter testen**, insbesondere unterschiedliche Vocabulary-/Scope-Konstellationen und Profile mit mehreren Methods.
* **RxStore mit Profilen testen**, damit wir verifizieren, dass dieselbe Profile-Semantik providerunabhängig funktioniert und nicht versehentlich xTree-spezifisch geworden ist.
* **Qdrant und Lobid GND anschließend separat bewerten.**

Gerade beim letzten Punkt würde ich **nicht automatisch voraussetzen, dass jedes Backend sofort dieselbe Profilmechanik braucht**.

```












---

## Und was machen wir mit der linguistischen Normalisierung?

Die würde ich parallel konzeptionell vorbereiten, aber **nicht zum Blocker für Profil v0.1 machen**.

Ich sehe inzwischen diese Grenze:

```text
Interpretation / Normalization
        │
        │ erzeugt/transformiert Suchausdruck
        ▼
Discovery Profile
        │
        │ findet Kandidaten
        ▼
CandidateItems
```

Damit wäre beispielsweise langfristig:

```text
Wirtschaftsgebäuden
       ↓
MORPHOLOGICAL_NORMALIZATION
       ↓
Wirtschaftsgebäude
       ↓
EXACT_STRING
```

sauberer als ein `EXACT_STRING`, das heimlich deutsche Flexion behandelt.

Das passt außerdem zu unserem bestehenden `InterpretationNode.technique` und den früher diskutierten Techniken `LEMMATIZATION`, `TOKENIZATION`, `NER`. Wir sollten aber erst anhand der herausgelösten Juni-Regeln entscheiden, welche Techniken wir wirklich benötigen.

---

## Damit wäre mein konkreter Arbeitsplan

| Schritt                                | Ergebnis                        | Risiko       |
| -------------------------------------- | ------------------------------- | ------------ |
| **1. Juni-Regeln inventarisieren**     | vollständige Regelmatrix        | sehr gering  |
| **2. Dehio-Wissen extrahieren**        | Mappingvok vNext + Review-Liste | gering       |
| **3. `EXACT_STRING` sauber isolieren** | erste generische Method         | gering       |
| **4. `MAPPED_VOCABULARY`**             | zweite Method                   | überschaubar |
| **5. `DEHIO_MCT_V01`**                 | erstes echtes Discovery Profile | überschaubar |
| **6. E004/150 Regression**             | Alt/Neu-Vergleich               | gering       |
| **7. xTree angleichen**                | providerunabhängige Methods     | mittel       |
| **8. `*_TRUNCATED`, Levenshtein**      | generisches Lexical Profile     | später       |
| **9. linguistische Normalisierung**    | sauberer Interpretation-Layer   | separat      |

Der wichtige Sicherheitsmechanismus ist **E004**. Wir kennen die heutigen 150 RxStore-Ergebnisse. Nach jedem Umbau können wir vergleichen:

```text
Legacy exact-with-token-fallback
             vs.
DEHIO_MCT_V01
```

Dabei muss das Ziel ausdrücklich **nicht 100 % Ergebnisidentität** sein. Einige Abweichungen wollen wir gerade erreichen, weil problematische fachliche Heuristiken aus dem generischen Code verschwinden. Aber jede Abweichung muss erklärbar sein.

### Mein Vorschlag für jetzt

Ich würde mit **Schritt 1 + 2 gemeinsam** anfangen und noch keinen Runtime-Code ändern:

> Den aktuellen RxStore vollständig nach `GENERIC_NORMALIZATION / GENERIC_DISCOVERY / DEHIO_MAPPING / RANKING / LEGACY-UNCLEAR` zerlegen und für `DEHIO_MAPPING` einen konkreten Änderungsvorschlag gegen das bestehende Hilfsvokabular erstellen.

Das kann ich auf Basis des aktuellen ZIPs und unseres vorhandenen Mappingvokabulars machen. Das Ergebnis wäre eine **Regelmatrix plus Mapping-Diff**. Danach können wir sehr schnell entscheiden: *diese Informationen ziehen wir aus PHP heraus, diese bleiben als generischer Mechanismus, diese werfen wir weg.*

Das wäre für mich die schnellste Route, ohne neue technische Schulden zu produzieren.
