diff -ruN /mnt/data/rx_baseline_ctx/src/Application/Reconciliation/ReconciliationApplicationService.php /mnt/data/rx_latest/src/Application/Reconciliation/ReconciliationApplicationService.php
--- /mnt/data/rx_baseline_ctx/src/Application/Reconciliation/ReconciliationApplicationService.php	2026-08-01 09:59:52.000000000 +0000
+++ /mnt/data/rx_latest/src/Application/Reconciliation/ReconciliationApplicationService.php	2026-08-16 07:58:21.018996662 +0000
@@ -164,6 +164,7 @@
                 rank: $index + 1,
                 score: $candidate->score,
                 candidateProviderUri: $candidate->candidateProviderUri,
+                qualifier: $this->candidateQualifier($candidate->metadata),
                 payload: $candidate->metadata,
             ));
         }
@@ -171,6 +172,15 @@
         return $result;
     }
 
+
+    /** @param array<string, mixed> $metadata */
+    private function candidateQualifier(array $metadata): ?string
+    {
+        $qualifier = trim((string)($metadata['qualifier'] ?? ''));
+
+        return $qualifier !== '' ? $qualifier : null;
+    }
+
     /**
      * @param list<DiscoveredCandidate> $discoveredCandidates
      */
diff -ruN /mnt/data/rx_baseline_ctx/src/OpenRefine/OpenRefineResponseMapper.php /mnt/data/rx_latest/src/OpenRefine/OpenRefineResponseMapper.php
--- /mnt/data/rx_baseline_ctx/src/OpenRefine/OpenRefineResponseMapper.php	2026-07-18 16:21:28.000000000 +0000
+++ /mnt/data/rx_latest/src/OpenRefine/OpenRefineResponseMapper.php	2026-08-16 07:58:21.019288807 +0000
@@ -23,9 +23,16 @@
             $results = [];
 
             foreach ($outcome->discoveredCandidates as $candidate) {
+                $name = $candidate->label;
+                $qualifier = trim((string)($candidate->metadata['qualifier'] ?? ''));
+
+                if ($qualifier !== '') {
+                    $name .= ' (' . $qualifier . ')';
+                }
+
                 $results[] = [
                     'id' => $candidate->uri,
-                    'name' => $candidate->label,
+                    'name' => $name,
                     'type' => [],
                     'score' => $candidate->score === null
                         ? 0
diff -ruN /mnt/data/rx_baseline_ctx/src/Provider/LocalStore/ReconciliationStoreProvider.php /mnt/data/rx_latest/src/Provider/LocalStore/ReconciliationStoreProvider.php
--- /mnt/data/rx_baseline_ctx/src/Provider/LocalStore/ReconciliationStoreProvider.php	2026-08-15 18:42:58.000000000 +0000
+++ /mnt/data/rx_latest/src/Provider/LocalStore/ReconciliationStoreProvider.php	2026-08-16 07:58:21.019103020 +0000
@@ -64,10 +64,9 @@
 
         foreach ($hits as $hit) {
             $score = (int)round(100 * (float)($hit['weight'] ?? 1));
-            $qualifier = empty($hit['qualifier']) ? null : ' (' . $hit['qualifier'] . ')';
             $candidates[] = new Candidate(
                 id: (string)$hit['id'],
-                label: ((string)$hit['label'] ?? null). $qualifier,
+                label: (string)($hit['label'] ?? ''),
                 score: $score,
                 match: $score >= 100,
                 meta: [
diff -ruN /mnt/data/rx_baseline_ctx/src/Provider/Xtree/XtreeJsonApiResultMapper.php /mnt/data/rx_latest/src/Provider/Xtree/XtreeJsonApiResultMapper.php
--- /mnt/data/rx_baseline_ctx/src/Provider/Xtree/XtreeJsonApiResultMapper.php	2026-06-24 15:09:59.000000000 +0000
+++ /mnt/data/rx_latest/src/Provider/Xtree/XtreeJsonApiResultMapper.php	2026-08-16 07:58:21.018857745 +0000
@@ -1,118 +1,125 @@
-<?php
-declare(strict_types=1);
-
-namespace App\Provider\Xtree;
-
-use App\Model\Candidate;
-
-final class XtreeJsonApiResultMapper
-{
-    /**
-     * xTree JSON API
-     * ->
-     * Candidate[]
-     *
-     * @return Candidate[]
-     */
-    public function mapSearchResponse(
-        array $response,
-        string $vocabularyUri,
-        int $limit = 20
-    ): array {
-
-        $items = $response['VocabularyItem'] ?? [];
-
-        if (!is_array($items)) {
-            return [];
-        }
-
-        $candidates = [];
-
-        foreach ($items as $item) {
-
-            $concept = $item['Concept'] ?? null;
-
-            if (!is_array($concept)) {
-                continue;
-            }
-
-            if (($concept['status'] ?? '') === 'deleted') {
-                continue;
-            }
-
-            $conceptId = (string)($concept['id'] ?? '');
-
-            if ($conceptId === '') {
-                continue;
-            }
-
-            $label = $this->extractPreferredLabel($concept);
-
-            if ($label === null) {
-                continue;
-            }
-
-            $candidates[] = new Candidate(
-                id: rtrim($vocabularyUri, '/') . '/' . $conceptId,
-                label: $label,
-                score: 80,
-                match: false,
-                meta: [
-                    'conceptId' => $conceptId,
-                    'status' => $concept['status'] ?? null,
-                ]
-            );
-
-            if (count($candidates) >= $limit) {
-                break;
-            }
-        }
-
-        return $candidates;
-    }
-
-    private function extractPreferredLabel(array $concept): ?string
-    {
-        $terms = $concept['Term'] ?? [];
-
-        if (!is_array($terms)) {
-            return null;
-        }
-
-        // prefLabel de
-
-        foreach ($terms as $term) {
-
-            if (
-                ($term['labelRole'] ?? '') === 'prefLabel'
-                && ($term['lang'] ?? '') === 'de'
-                && !empty($term['Term'])
-            ) {
-                return (string)$term['Term'];
-            }
-        }
-
-        // prefLabel beliebige Sprache
-
-        foreach ($terms as $term) {
-
-            if (
-                ($term['labelRole'] ?? '') === 'prefLabel'
-                && !empty($term['Term'])
-            ) {
-                return (string)$term['Term'];
-            }
-        }
-
-        // erster verfügbarer Term
-
-        foreach ($terms as $term) {
-
-            if (!empty($term['Term'])) {
-                return (string)$term['Term'];
-            }
-        }
-
-        return null;
-    }
-}
\ No newline at end of file
+<?php
+declare(strict_types=1);
+
+namespace App\Provider\Xtree;
+
+use App\Model\Candidate;
+
+final class XtreeJsonApiResultMapper
+{
+    /**
+     * xTree JSON API
+     * ->
+     * Candidate[]
+     *
+     * @return Candidate[]
+     */
+    public function mapSearchResponse(
+        array $response,
+        string $vocabularyUri,
+        int $limit = 20
+    ): array {
+
+        $items = $response['VocabularyItem'] ?? [];
+
+        if (!is_array($items)) {
+            return [];
+        }
+
+        $candidates = [];
+
+        foreach ($items as $item) {
+
+            $concept = $item['Concept'] ?? null;
+
+            if (!is_array($concept)) {
+                continue;
+            }
+
+            if (($concept['status'] ?? '') === 'deleted') {
+                continue;
+            }
+
+            $conceptId = (string)($concept['id'] ?? '');
+
+            if ($conceptId === '') {
+                continue;
+            }
+
+            $preferredTerm = $this->extractPreferredTerm($concept);
+
+            if ($preferredTerm === null) {
+                continue;
+            }
+
+            $candidates[] = new Candidate(
+                id: rtrim($vocabularyUri, '/') . '/' . $conceptId,
+                label: $preferredTerm['label'],
+                score: 80,
+                match: false,
+                meta: [
+                    'conceptId' => $conceptId,
+                    'status' => $concept['status'] ?? null,
+                    'qualifier' => $preferredTerm['qualifier'],
+                ]
+            );
+
+            if (count($candidates) >= $limit) {
+                break;
+            }
+        }
+
+        return $candidates;
+    }
+
+    /** @return array{label:string, qualifier:?string}|null */
+    private function extractPreferredTerm(array $concept): ?array
+    {
+        $terms = $concept['Term'] ?? [];
+
+        if (!is_array($terms)) {
+            return null;
+        }
+
+        // prefLabel de
+        foreach ($terms as $term) {
+            if (
+                ($term['labelRole'] ?? '') === 'prefLabel'
+                && ($term['lang'] ?? '') === 'de'
+                && !empty($term['Term'])
+            ) {
+                return $this->termData($term);
+            }
+        }
+
+        // prefLabel beliebige Sprache
+        foreach ($terms as $term) {
+            if (
+                ($term['labelRole'] ?? '') === 'prefLabel'
+                && !empty($term['Term'])
+            ) {
+                return $this->termData($term);
+            }
+        }
+
+        // erster verfügbarer Term
+        foreach ($terms as $term) {
+            if (!empty($term['Term'])) {
+                return $this->termData($term);
+            }
+        }
+
+        return null;
+    }
+
+    /** @return array{label:string, qualifier:?string} */
+    private function termData(array $term): array
+    {
+        $qualifier = trim((string)($term['qualifier'] ?? ''));
+
+        return [
+            'label' => (string)$term['Term'],
+            'qualifier' => $qualifier !== '' ? $qualifier : null,
+        ];
+    }
+}
diff -ruN /mnt/data/rx_baseline_ctx/tests/Application/Reconciliation/ApplicationFlowTest.php /mnt/data/rx_latest/tests/Application/Reconciliation/ApplicationFlowTest.php
--- /mnt/data/rx_baseline_ctx/tests/Application/Reconciliation/ApplicationFlowTest.php	2026-08-01 15:48:35.000000000 +0000
+++ /mnt/data/rx_latest/tests/Application/Reconciliation/ApplicationFlowTest.php	2026-08-16 07:58:34.973405033 +0000
@@ -38,6 +38,7 @@
                 match: false,
                 entityTypeUri: 'CONCEPT',
                 candidateProviderUri: 'http://localhost:8080/reconcile/v2/',
+                metadata: ['qualifier' => 'Architektur'],
             ),
         ];
     }
@@ -127,7 +128,9 @@
 );
 
 assertFlowSame(91, $response['q0']['result'][0]['score'], 'Normalized scores must be mapped back to the OpenRefine scale.');
-assertFlowSame('Altarbild', $response['q0']['result'][0]['name'], 'Candidate labels must enter the OpenRefine response.');
+assertFlowSame('Altarbild (Architektur)', $response['q0']['result'][0]['name'], 'OpenRefine must append a structured qualifier to the candidate display name.');
+assertFlowSame('Altarbild', $outcomes[0]->reconciliationResult->candidates()[0]->displayLabel(), 'CandidateItem displayLabel must remain qualifier-free.');
+assertFlowSame('Architektur', $outcomes[0]->reconciliationResult->candidates()[0]->qualifier(), 'CandidateItem qualifier must be persisted structurally.');
 assertFlowSame([], $response['q0']['result'][0]['type'], 'The current public type contract must remain unchanged.');
 assertFlowSame([], $response['q1']['result'], 'Incomplete queries must receive an empty result.');
 assertFlowSame(
diff -ruN /mnt/data/rx_baseline_ctx/tests/Infrastructure/Discovery/Adapter/LocalReconciliationStoreAdapterTest.php /mnt/data/rx_latest/tests/Infrastructure/Discovery/Adapter/LocalReconciliationStoreAdapterTest.php
--- /mnt/data/rx_baseline_ctx/tests/Infrastructure/Discovery/Adapter/LocalReconciliationStoreAdapterTest.php	2026-08-15 18:42:58.000000000 +0000
+++ /mnt/data/rx_latest/tests/Infrastructure/Discovery/Adapter/LocalReconciliationStoreAdapterTest.php	2026-08-16 07:58:34.973578151 +0000
@@ -119,8 +119,11 @@
     if (count($qualified) !== 1 || $qualified[0]->uri !== 'urn:test:altar-architektur') {
         throw new RuntimeException('Qualifier-aware local-store lookup failed.');
     }
-    if ($qualified[0]->label !== 'Altar (Architektur)') {
-        throw new RuntimeException('Qualifier-aware candidate label failed.');
+    if ($qualified[0]->label !== 'Altar') {
+        throw new RuntimeException('Local-store candidate label must remain qualifier-free.');
+    }
+    if (($qualified[0]->metadata['qualifier'] ?? null) !== 'Architektur') {
+        throw new RuntimeException('Local-store qualifier metadata mapping failed.');
     }
 
     $unknownQualifier = $adapter->discover(new ReconciliationCommand(
@@ -155,9 +158,12 @@
     if ($token[0]->score !== 0.68 || $token[0]->match) {
         throw new RuntimeException('Token fallback score mapping failed.');
     }
-    if ($token[0]->label !== 'Altar (Ausstattung)') {
+    if ($token[0]->label !== 'Altar') {
         throw new RuntimeException('Candidate label mapping failed.');
     }
+    if (($token[0]->metadata['qualifier'] ?? null) !== 'Ausstattung') {
+        throw new RuntimeException('Token fallback qualifier metadata mapping failed.');
+    }
 
     $unauthorized = new LocalReconciliationStoreAdapter(
         scopeVocabularyUri: $scope,
diff -ruN /mnt/data/rx_baseline_ctx/tests/Provider/Xtree/XtreeJsonApiResultMapperQualifierTest.php /mnt/data/rx_latest/tests/Provider/Xtree/XtreeJsonApiResultMapperQualifierTest.php
--- /mnt/data/rx_baseline_ctx/tests/Provider/Xtree/XtreeJsonApiResultMapperQualifierTest.php	1970-01-01 00:00:00.000000000 +0000
+++ /mnt/data/rx_latest/tests/Provider/Xtree/XtreeJsonApiResultMapperQualifierTest.php	2026-08-16 07:58:43.539389081 +0000
@@ -0,0 +1,62 @@
+<?php
+declare(strict_types=1);
+
+require_once dirname(__DIR__, 3) . '/src/bootstrap.php';
+
+use App\Provider\Xtree\XtreeJsonApiResultMapper;
+
+$mapper = new XtreeJsonApiResultMapper();
+$response = [
+    'VocabularyItem' => [
+        [
+            'Concept' => [
+                'id' => 'wk002306',
+                'status' => 'published',
+                'Term' => [
+                    [
+                        'Term' => 'Arc',
+                        'labelRole' => 'prefLabel',
+                        'lang' => 'en',
+                        'qualifier' => 'Architecture',
+                    ],
+                    [
+                        'Term' => 'Bogen',
+                        'labelRole' => 'prefLabel',
+                        'lang' => 'de',
+                        'qualifier' => 'Architektur',
+                    ],
+                ],
+            ],
+        ],
+        [
+            'Concept' => [
+                'id' => 'wk019195',
+                'status' => 'published',
+                'Term' => [
+                    [
+                        'Term' => 'Bogen',
+                        'labelRole' => 'prefLabel',
+                        'lang' => 'de',
+                    ],
+                ],
+            ],
+        ],
+    ],
+];
+
+$candidates = $mapper->mapSearchResponse($response, 'http://lvr.vocnet.org/wnk', 10);
+
+if (count($candidates) !== 2) {
+    throw new RuntimeException('Expected two mapped xTree candidates.');
+}
+if ($candidates[0]->label !== 'Bogen') {
+    throw new RuntimeException('Preferred label mapping changed unexpectedly.');
+}
+if (($candidates[0]->meta['qualifier'] ?? null) !== 'Architektur') {
+    throw new RuntimeException('Qualifier of the selected preferred term was not mapped.');
+}
+if (!array_key_exists('qualifier', $candidates[1]->meta) || $candidates[1]->meta['qualifier'] !== null) {
+    throw new RuntimeException('Missing qualifier must be mapped as null.');
+}
+
+echo "CTX-001D xTree Qualifier Result Mapping: OK\n";
