dashboard keystone: fix experiment cost/pass-rate aggregation + donut at 100%
Experiment detail (/app/keystone/experiments/[id]):
- API: paginate the trace fetch with .range() loop. PostgREST caps a
single .select() at 1000 rows, so an 8.5k-trace experiment was only
summing the first 1000 traces (~$0.12 of an actual $11.23 total). - API: when results_json has no sandbox_id (older runs ship
{}),
per-row cost matching returns null and the row showed $0. Distribute
the unmatched portion of expCost (and tools/tokens) evenly across
rows that didn't match so per-row cost reflects its share. - Page: KPI Pass Rate now aggregates weighted invariant outcomes across
every result row instead of taking latestResult.pass_rate (a single
binary 0/1). 15 rows of 1/9 invariants will now show ~11% in the KPI. - Page: KPI Scenarios sums passed/total_scenarios across all rows
instead of just the latest row. - Page: Traces-tab span tree connectors rebuilt to match the Dash0
reference — every depth>0 row gets the arm+arrow, parent collapse
boxes sit AFTER the connector with a vertical drop to children, name
uses two-tone dim-prefix/bright-leaf styling. Inter-row dividers and
the trailing "complete" phase suffix removed.
Dashboard overview (/app/keystone):
- DonutPie at 100% rendered as a 3/4 ring because strokeDashoffset=c/4
was shifting the start past the path's end. Switched to the standard
${dash} ${c-dash}pattern with rotation via transform only, so a
full ring renders as a complete circle.