Scatter chart
Every run as a dot by cost and eval score, sized by tokens, with quadrants and a drag to select.
A scatter chart plots every run as a dot by its x (cost along the bottom) and y (eval score up
the side), sized by its size (tokens). Each series has a colour and a shape, so it reads without
colour too. Dashed median lines cut the plot into four named quadrants; pointing snaps to the
nearest run and shows a tooltip, and a drag draws a box that selects the runs in it. Pass ringed
ids to circle outliers, and an onAsk handler to add "Ask the agent why" to a selection.
Usage
<!-- include core.css + scatter-chart.css -->
<div class="dm-cvq dm-panel">
<div class="dm-cvq-h">
<div class="dm-cvq-t"><b>Cost vs quality</b><span class="dm-muted">48 runs this week</span></div>
<div class="dm-cvq-lg"><!-- one legend key per series --></div>
</div>
<div class="dm-cvq-pl" tabindex="0" role="group" aria-roledescription="scatter chart">
<svg class="dm-cvq-svg"><!-- gridlines, axes, medians, dots --></svg>
<div class="dm-cvq-tt"></div>
</div>
<div class="dm-cvq-ft" aria-live="polite"><span class="dm-cvq-msg"></span></div>
</div>Properties
| Name | Type | Description |
|---|---|---|
runs | ScatterRun[] | Each run is a dot: id, series, x (along), y (up) and size. |
series | ScatterSeries[] | key, label, optional color and shape (circle | square | triangle). |
title | string | The bold heading. Defaults to "Cost vs quality". |
subtitle | string | The quieter line beside the title. |
xDomain / yDomain | [number, number] | The [min, max] of each axis. |
xTicks / yTicks | number[] | Where the labels and gridlines go. A narrow chart keeps the two ends and the middle. |
xTitle / yTitle | string | The axis titles, clear of the ticks. |
formatX / formatY / formatSize | (n) => string | Writes the axis values and the tooltip's token count. |
quadrants | [string, string, string, string] | The four names the medians make, from the top left, clockwise. A narrow chart leaves them out. |
ringed | (string | number)[] | Runs to ring, like outliers the agent found. |
note | string | The line under the chart while nothing is selected. |
selected | (string | number)[] | The selected runs, by id. Leave it out to let the chart hold the selection. |
onSelectedChange | (ids) => void | Fires when the drag selection changes. |
onAsk | (runs) => string | Promise<string> | Adds "Ask the agent why" to a selection; the answer streams in. |
Theming
Works in light and dark (data-theme="dark") and in the Soft style (data-style="soft"). The dots
take the chart palette (--dm-c1…--dm-c6); the gridlines, axes, median lines and the selection box
are mixed from the line and foreground tokens, and the tooltip sits on the ink token — so the chart
reads on either theme without any hard-coded colours.