# RetrieX Patch 20f - Explicit Shop Routing Guard

## Purpose

Patch 20f fixes a critical routing regression observed after the p20 series:

```text
shop testomat 808
```

This must always enter the Shop path. After p20e it could still fall back to RAG-only with `Shop-Treffer: nicht angefragt`.

## Root cause

The p20 series added LLM/fuzzy input normalization and several referential follow-up routing helpers. The follow-up fixes were too focused on table/price references and did not provide a hard safety net for explicit user routing terms such as `shop`, `preis`, `kostet`, `suche`, `kaufen`, etc.

If the normal commerce detector or a normalized routing prompt failed to preserve that signal, an explicit Shop request could still fall into the non-commerce/RAG-only branch.

## Change

`AgentRunner` now applies an explicit Shop routing guard before the normal Commerce intent decision:

- Checks the original user prompt and the routing prompt for configured commercial signal terms from YAML.
- If the original prompt explicitly says `shop`/price/search/etc., the routing prompt is restored to the original prompt unless this is a commercial table follow-up.
- Forces `CommerceIntentLite::PRODUCT_SEARCH` for explicit commercial routing signals.
- Keeps the existing p20 LLM input normalization and p20e commercial table follow-up handling.
- Adds logging for forced explicit Shop routing.

## Files changed

- `src/Agent/AgentRunner.php`

## Important design note

This is not a new typo list and not a scoring change. It is a routing invariant:

> Explicit Shop/commercial wording must never result in `Shop-Treffer: nicht angefragt`.

The signal terms are still read from existing YAML config (`follow_up_context.explicit_commercial_signal_terms`).

## Recommended checks

```bash
bin/console mto:agent:config:validate
bin/console mto:agent:regression:test
bin/console mto:agent:config:audit-source --details
bin/console mto:agent:config:audit-patterns --details
```

## Manual regression tests

```text
shop testomat 808
```

Expected: Shop search is requested.

```text
was kpstet der indikator
```

Expected: typo normalization/fuzzy routing still turns this into a price/shop follow-up.

```text
welche grenzwerte kann der testomat 808 messen
die tabelle mit preisen
```

Expected: table-price follow-up is routed to Shop using the previous Testomat 808 / indicator context.

```text
ich suche eine preiswerte Lösung zur messung von pH & Chlor für mein schwimmbad
```

Expected: advisory product/shop routing is requested.
