Trust layer and grounding indicators
How Conviro keeps the assistant from stating wrong prices, stock or order facts, and how your team can see what an answer was based on. Plan P6.1–P6.2. Code: apps/api/src/modules/temporal/commerce/commerce-grounding.ts (d160e5da), apps/api/src/modules/commerce-trust/ (1a4f55fc), chat pipeline (aa085d1e), inbox indicator (a98996a0). Code and tests only — not deployed, not run against the Magento test stack, the inbox view not yet opened in a browser.
Where facts come from
Every commerce fact handed to the AI carries a source class and provenance (provider, store view, when it was read, how long the read took):
| Source class | What it is | Allowed to state |
|---|---|---|
Live store (LIVE_STORE) | Read from your Magento store's REST API during the conversation | price, stock, order status and total, tracking, product information |
Your policy (MERCHANT_POLICY) | Return window (days) and Warranty length (months) from the module's AI Capabilities (and their per-language overrides in Conviro) | return window, warranty |
Knowledge base (KNOWLEDGE_BASE) | Conviro's synced product entries and your own documents | product information; return window / warranty only when no policy is set |
Inferred (INFERENCE) | Conclusions drawn over live state, e.g. "this order can still be cancelled" | eligibility |
Precedence is fixed: a stronger source always wins; when a weaker source disagrees (say, a knowledge-base price that differs from the live price), it is kept as a recorded conflict and the AI is told to ignore it — it is never promoted. Price, stock and order facts are stated as fact only from the live store.
Checks on the reply
- Before sending (existing validator, in commerce conversations): a reply that quotes a price found nowhere in what the AI was given is blocked and replaced. If you set a return window or warranty length, a reply stating a different one is blocked too.
- After generation (new in this release, flags, does not rewrite): every amount next to a currency and every quantity next to a stock word in the final reply is compared with the live facts of that turn, in any language and number format. A claim no live fact backs is logged (
[COMMERCE_UNGROUNDED]), recorded as a hallucination event (sourcecommerce-check, modewarn) and shown to your team. Order numbers, dates, SKUs and bare quantities are not claims.
Grounding indicator in the inbox
Under an assistant answer that used store data, your team sees one line, for example:
- "Grounded in live Magento catalog · 430 ms"
- "Grounded in live Magento order data"
- "Checked the live Magento store: nothing matched"
- "Unverified claims: 1" (warning style)
Expanding it shows the facts given to the AI with their source and when they were read, the store view, the losing side of any conflict ("Conflicting sources (the stronger one was used)"), and price / stock claims in the reply not backed by a live fact, with the reason (no live price, amount differs, currency differs, no live stock, quantity differs). "Only your team sees this."
The record lives in its own staff-only table (chat_message_grounding, one row per answer), not on the chat message the widget reads, so it never reaches the shopper's browser. Access: owners, admins, and agents with sessions: read, with the same conversation scope as the inbox.
Aggregates per day and per source class (grounded answers, ungrounded counts, average latency) are available at GET /api/commerce-grounding/stats?days=1..90 for owners and admins.
In the Magento admin (514d99b0 API, f9e583f6 module): Stores › Configuration › Conviro › AI Chat › AI Answers and Revenue shows, for today and the last 7 days, how many commerce answers there were, how many rested on live store data (LIVE_STORE) versus other sources, and how many ungrounded price / stock claims the post-check flagged — counts only, no conversation content. The config page renders a placeholder and loads the card afterwards (conviro/insights/cards: admin session, URL secret key and Conviro_AiChat::config), so a slow Conviro never delays the page; Service/Insights/ConviroInsights calls GET /v1/api/magento/stats/grounding with the store's API key (3 s connect / 4 s total; cached 5 minutes, 1 minute after a failure; the route has a per-key throttle and takes kb:write, chat:read or the connect-minted magento:module scope). Measured on the local stack (attribution.sh, c3374a58): rendered from the stats endpoint, a failing Conviro gives a message instead of numbers, no admin session gives no card. The same card shows revenue influenced by Conviro (Privacy).
What you control
- AI Capabilities decide which live reads the assistant may make (AI permissions).
- Return window / warranty turn your policy into facts the AI must follow.
- Store-view selection decides which store views may be read (Multi-store).
Limits
- The post-generation check flags; it does not rewrite (a rewrite would destroy correct answers that quote, say, a shipping threshold from your knowledge base).
- The knowledge base is per SKU and its price line is the base-currency
priceattribute; live reads are what the AI may state as the price.
Measured (unit tests): precedence over all 120 permutations of the source classes, claim extraction in 10 reply languages with both decimal conventions, no false positives on order-number / quantity replies (commerce-grounding.spec 48/48).