Covers three improvements to /runs/🆔 prompt/error header callouts, client-side span filter/search, and an interactive waterfall with hover tooltips and inline detail drawers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.8 KiB
Run Detail Improvements — Design
Date: 2026-04-25
Scope: run-detail.js, style.css
Pages affected: Run detail (/runs/:id)
Goal
Make the run detail page the best possible trace viewer for diagnosing what an agent did and what went wrong. Three focused improvements: surfacing prompt and error context in the header, adding span filter/search, and upgrading the waterfall to an interactive view.
Section 1: Run Header — Prompt Preview & Error Detail
Prompt preview strip
Below the meta-tiles, add a collapsible block showing the first ~200 characters of the run's prompt. The data is already returned by /v1/runs/:id via payload.prompt_preview or payload.message_preview on the run.start event — it is just not currently rendered.
- Styled as a
<pre>block inside a callout pill - Muted background (
var(--surface-2)), monospace font, left border invar(--accent) - "Show more" expands to the full text inline; "Show less" collapses it
- Only rendered when
prompt_previewis non-empty
Error detail callout
When r.status === 'error', render a prominent callout box between the meta-tiles and the spans section.
- Pulls error message/stack from the first error-status span's payload, or from the
run.endevent payload - Left border in
var(--error), background invar(--error-bg), message in monospace - Copy button on the error message
- If no error detail is available in the payload, shows a minimal "Run ended with error" notice
Files touched
cmd/web-ui/static/modules/pages/run-detail.js—renderRun()onlycmd/web-ui/static/style.css— new callout/prompt-preview rules
No API changes required.
Section 2: Span Filter & Search Bar
Add client-side filtering controls above the spans container. No API calls — filtering operates on the spans array captured at render time.
Controls
Text search input
- Filters span rows in real time by matching against span name (case-insensitive substring)
- Clears on
✕button click orEscape - Filter persists when switching between Table and Waterfall views
Kind filter pills
- One pill per span kind present in the current run (
tool,agent,unknown, etc.) - Pills are generated dynamically from the spans array — only kinds that exist are shown
- Multiple kinds can be active simultaneously; all active = show all
- Clicking a pill toggles it; at least one must remain active
Errors-only toggle
- Binary toggle:
All/Errors only - When active, only spans with
status === 'error'are shown
Filter state
let spanFilter = { query: '', kinds: new Set(), errorsOnly: false };
Filter state is module-level, reset on cleanup().
Integration with views
- Table view: Non-matching rows are hidden (
display: none) - Waterfall view: Non-matching bars are dimmed (
opacity: 0.2) rather than hidden — so the timescale and relative positioning remain meaningful
Files touched
cmd/web-ui/static/modules/pages/run-detail.js—renderRun(),renderRunSpansRows(),renderSpanWaterfall(), newapplySpanFilter()helpercmd/web-ui/static/style.css— filter bar layout, pill styles
Section 3: Waterfall — Hover Detail & Visual Improvements
Hover tooltip
Replace the plain title attribute on waterfall bars with a styled floating tooltip.
Tooltip contents:
- Span name and kind badge
- Duration and start offset from run start
- Status
- One-line payload preview (tool input snippet or token count)
Implementation:
- Single shared tooltip DOM element, positioned via
mousemoveon the waterfall container - Hidden on
mouseleave - No per-row DOM overhead
Clickable bars → inline detail drawer
Clicking a waterfall bar opens an inline detail drawer below that waterfall row, rendering the same renderSpanPayload() content used in the table view. A second click collapses it. At most one drawer open at a time.
Visual polish
- Minimum bar width: Raised so short-duration spans remain clickable
- Error spans: Pulsing red left edge (consistent with
tr-errorin table view) - Timescale ticks: Snap to human-friendly intervals (100ms, 500ms, 1s, 5s, 10s, 30s, 1m) rather than always dividing into 5 equal parts
Filter integration
Spans dimmed by the Section 2 filter get opacity: 0.2 on their bars. They remain positioned correctly for timing context.
Files touched
cmd/web-ui/static/modules/pages/run-detail.js—renderSpanWaterfall(), newbindWaterfallInteractions()helpercmd/web-ui/static/style.css— tooltip, drawer, error pulse rules
Summary of changes
| File | Sections |
|---|---|
cmd/web-ui/static/modules/pages/run-detail.js |
1, 2, 3 |
cmd/web-ui/static/style.css |
1, 2, 3 |
No backend changes. No new dependencies. All data already returned by existing API endpoints.