EvidenceList
MoleculeThe rows an AI answer cites, drawn with the same DOM as kui-react: a number, a kind icon and label, a title that opens the row, a summary, source and time. Claims dropped for citing nothing openable are listed apart with a text indicator. `activeId` highlights a row at render time and `KuiEvidence.setActive(listRoot, id)` does it in the browser; the page's `:target` highlights too. `onOpen` is truthy to give a row without an `href` an Open button; links and the button fire the bubbling DOM event `kui:evidence-open` { id, href }. Timestamps use `locale` and `timeZone` (a server formats in its own zone unless `timeZone` is given).
Checkout errors started after payments 4.12.0 was rolled out [3]. The failures are gateway timeouts [1][2], and the error ratio rose above 3 % [4]. The database was the bottleneck [7].
Evidence
-
[1]
412 errors between 08:02 and 08:07.
loki · Oct 18, 2026, 8:02:00 AM
-
[2]
payment.charge spent 140 ms and timed out.
tempo · Oct 18, 2026, 8:04:00 AM
-
[3]
Deploy payments 4.12.0
Rolled out at 07:58.
deploys · Oct 18, 2026, 7:58:00 AM
-
[4]
Metric checkout error ratio
Rose from 0.4 % to 3.1 %.
prometheus
Dropped claims: 1 claims removed: they cited no evidence you can open.
These statements are not part of the answer.
- The database was the bottleneck.(Reason: cited evidence 7, which does not exist)
<%- include('modules/ui/CitedText', { text: answer, evidence: evidence }) %>
<%- include('modules/ui/EvidenceList', { items: evidence, droppedClaims: dropped, onOpen: true }) %>
<script>
var list = document.querySelector('section');
document.addEventListener('kui:citation-select', function (e) { KuiEvidence.setActive(list, e.detail.evidenceId); });
document.addEventListener('kui:evidence-open', function (e) { KuiEvidence.setActive(list, e.detail.id); });
</script>
Evidence
No evidence was cited.
<%- include('modules/ui/EvidenceList', { items: [] }) %>
-
[1]
Protokoll payments: gateway timeout burst
412 errors between 08:02 and 08:07.
loki · 18.10.2026, 10:02:00
-
[2]
payment.charge spent 140 ms and timed out.
tempo · 18.10.2026, 10:04:00
-
[3]
Auslieferung payments 4.12.0
Rolled out at 07:58.
deploys · 18.10.2026, 09:58:00
<%- include('modules/ui/EvidenceList', { items: evidence, heading: false, idPrefix: 'belege', locale: 'de-DE', timeZone: 'Europe/Berlin', messages: { heading: 'Belege', kinds: { log: 'Protokoll' } } }) %>
<%
// EvidenceList — the rows an AI answer cites: a number, a kind icon and label, a title that opens the row, a
// summary, source and time; claims dropped for citing nothing openable are listed apart. Same DOM and classes as
// kui-react modules/ui/Evidence (EvidenceList).
//
// Locals:
// items — [{ id, index?, kind, title, summary?, href?, timestamp?, source? }]
// index — the number a chip cites (default: position + 1)
// kind — log | trace | metric | alert | incident | deploy | config | doc | query | other, or any text
// (shown as is, with the generic icon)
// href — where the row opens (a link)
// timestamp — epoch ms or an ISO string
// droppedClaims — [{ id, text, reason? }] claims removed for citing nothing openable
// activeId — the row to highlight (the :target of the page highlights too)
// onOpen — truthy gives a row without an href an Open button (React takes a callback there); links and the
// button fire the bubbling DOM event 'kui:evidence-open' { id, href } on themselves
// idPrefix — same prefix as the chips (default 'evidence'); a row's id is idPrefix + '-' + item.id
// heading — heading text (default messages.heading); false hides it
// locale, timeZone — for the timestamps (a server formats in its own zone unless timeZone is given)
// messages — { heading, empty, open, openNamed, droppedHeading, droppedSummary, droppedHint, reason,
// kinds: { log, ... } }; '{title}' and '{count}' are placeholders
// className — extra classes on the root (appended, no conflict resolution)
// loadRuntime — default true: inline Evidence/scripts/evidence.js (see Evidence/_runtime.ejs)
//
// Hooks for the runtime (not in React): data-ev-row on a row, data-ev-open on a link or Open button.
var L = {};
include('./Evidence/_logic', { L: L });
var _msg = L.messages(locals.messages);
var _items = Array.isArray(locals.items) ? locals.items : [];
var _dropped = Array.isArray(locals.droppedClaims) ? locals.droppedClaims : [];
var _prefix = locals.idPrefix != null ? locals.idPrefix : 'evidence';
var _headingText = locals.heading === undefined ? _msg.heading : locals.heading;
var _activeId = locals.activeId != null ? locals.activeId : null;
var _onOpen = !!locals.onOpen;
var _extra = locals.className ? ' ' + locals.className : '';
var _btn = 'inline-flex items-center rounded border border-border bg-surface-base px-2.5 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-surface-overlay disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus';
%>
<section<% if (_headingText === false) { %> aria-label="<%= _msg.heading %>"<% } %> class="flex flex-col gap-3<%= _extra %>">
<% if (_headingText !== false) { %><h3 class="text-sm font-semibold text-text-primary"><%= _headingText %></h3><% } %>
<% if (_items.length === 0) { %>
<p class="text-sm text-text-secondary"><%= _msg.empty %></p>
<% } else { %>
<ol class="flex flex-col gap-2">
<% _items.forEach(function (item, i) {
var n = item.index != null ? item.index : i + 1;
var known = L.isKnownKind(item.kind);
var kindLabel = known ? _msg.kinds[item.kind] : item.kind;
var when = L.timeText(item.timestamp, locals.locale, locals.timeZone);
var active = _activeId === item.id;
var meta = [item.source, when].filter(Boolean).join(' · ');
%>
<li id="<%= L.domId(_prefix, item.id) %>"<% if (active) { %> data-active="true"<% } %> data-kind="<%= item.kind %>" data-ev-row="<%= item.id %>" tabindex="-1" class="flex gap-3 rounded-md border <%= active ? '' : 'border-border bg-surface-raised ' %>p-3 text-sm target:border-primary target:bg-primary-subtle focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus<%= active ? ' border-primary bg-primary-subtle' : '' %>">
<span class="mt-0.5 inline-flex h-5 min-w-5 shrink-0 items-center justify-center rounded bg-primary-subtle px-1 text-xs font-semibold text-primary">[<%= n %>]</span>
<div class="flex min-w-0 flex-1 flex-col gap-1">
<div class="flex flex-wrap items-center gap-x-2 gap-y-1">
<span class="inline-flex items-center gap-1 rounded-full bg-surface-sunken px-2 py-0.5 text-xs text-text-secondary"><i class="<%= L.KIND_ICON[known ? item.kind : 'other'] %> h-3 w-3" aria-hidden="true"></i><%= kindLabel %></span>
<% if (item.href) { %>
<a href="<%= item.href %>" data-ev-open="<%= item.id %>" class="inline-flex min-w-0 items-center gap-1 font-medium text-primary hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus"><span class="truncate"><%= item.title %></span><i class="fa-solid fa-arrow-up-right-from-square h-3 w-3 shrink-0 rtl:-scale-x-100" aria-hidden="true"></i></a>
<% } else { %>
<span class="min-w-0 truncate font-medium text-text-primary"><%= item.title %></span>
<% } %>
</div>
<% if (item.summary) { %><p class="break-words text-text-secondary"><%= item.summary %></p><% } %>
<% if (when || item.source) { %><p class="text-xs text-text-disabled"><%= meta %></p><% } %>
</div>
<% if (!item.href && _onOpen) { %>
<button type="button" aria-label="<%= L.fill(_msg.openNamed, { title: item.title }) %>" data-ev-open="<%= item.id %>" class="h-fit shrink-0 rounded border border-border bg-surface-base px-2 py-1 text-xs transition-colors hover:bg-surface-overlay focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus"><%= _msg.open %></button>
<% } %>
</li>
<% }); %>
</ol>
<% } %>
<% if (_dropped.length > 0) { %>
<div role="status" data-part="dropped" class="flex flex-col gap-2 rounded-md border border-dashed border-warning bg-warning-subtle p-3 text-sm text-warning-fg">
<p class="flex items-center gap-2 font-medium"><i class="fa-solid fa-ban h-3.5 w-3.5" aria-hidden="true"></i><span><%= _msg.droppedHeading %>: <%= L.fill(_msg.droppedSummary, { count: _dropped.length }) %></span></p>
<p class="text-xs"><%= _msg.droppedHint %></p>
<ul class="flex flex-col gap-1.5">
<% _dropped.forEach(function (c) { %>
<li class="rounded bg-surface-base/60 p-2 text-text-primary"><span class="line-through decoration-warning"><%= c.text %></span><% if (c.reason) { %><span class="ms-2 text-xs text-text-secondary">(<%= _msg.reason %>: <%= c.reason %>)</span><% } %></li>
<% }); %>
</ul>
</div>
<% } %>
</section>
<% if (locals.loadRuntime !== false) { %><%- include('./Evidence/_runtime') %><% } %>