Skip to content

Add interactive Plotly HTML result dashboards#28

Merged
dbroeglin merged 4 commits into
mainfrom
dbroeglin-experiment-result-charts
Jul 6, 2026
Merged

Add interactive Plotly HTML result dashboards#28
dbroeglin merged 4 commits into
mainfrom
dbroeglin-experiment-result-charts

Conversation

@dbroeglin

Copy link
Copy Markdown
Owner

Why

Until now the tool could only show results as Rich terminal tables and a plain summary.md. There was no crisp, shareable visual output. This adds high-quality interactive dashboards inspired by the DeepSWE leaderboard and the GitHub Copilot agentic-harness benchmarking report, so a finished run can be understood at a glance and passed around without a server.

What

Each Pier run now renders into a single self-contained summary.html: a clean header, KPI cards, a ranked leaderboard, and four interactive Plotly charts:

  • Task resolution - success rate per agent, grouped by task on multi-task runs.
  • Resolution vs. cost - success rate against average cost per task with +/-1 sigma error bars ("up and to the left is better").
  • Cost efficiency - average AIU/token cost per agent with spread.
  • Per-task success heatmap - shown only when a run has more than one task.

Usage:

uv run copilot-experiments chart --last --open      # embedded, offline-viewable
uv run copilot-experiments chart <job>/<run> --cdn  # tiny CDN-backed file

run also emits summary.html automatically whenever Plotly is installed.

Approach and design notes

  • New charts.py module is the whole rendering surface (build_dashboard_html, write_dashboard, plotly_available, ChartError). It consumes the existing summary.json shape rather than re-deriving metrics, keeping analysis data separate from rendering.
  • Plotly is an optional [charts] extra. The dashboard degrades gracefully: run silently skips it when Plotly is missing, and chart exits with an install hint. Core behavior and all offline tests never require Plotly.
  • Offline vs CDN builds: by default the ~4.5 MB plotly.js bundle is embedded for zero-dependency viewing; --cdn produces a ~40 KB file that loads plotly.js from the CDN.
  • Aggregates: to feed the charts I populated the previously-stubbed variance/coverage fields in pier_results.py (std_*/cv_* for AIU and tokens, mean_resolved_rate, resolved_at_k_rate, per-task resolved_rate) and fixed a CV key mismatch in report.py. These fields also benefit show and are documented in results-format.md.

Testing

  • Added tests/test_charts.py plus aggregate and CLI tests. Chart tests use the cdn=True path (fast) or monkeypatch the import to assert graceful degradation, so they stay offline.
  • Full suite passes (182 tests). One pre-existing test_cli_validate_checks_pier_config failure is environment-specific (it assumes Docker is absent, but Docker is installed on this machine) and I confirmed it fails identically without this change.

Notes for reviewers

  • Docs added/updated: docs/visualizing-results.md, docs/results-format.md, README, and ADR 0021-interactive-html-dashboards.md.
  • The scaffold template now installs the [charts] extra so chart works out of the box in generated experiment repos.
  • ruff-clean and formatted.

dbroeglin and others added 4 commits July 6, 2026 08:46
Render each Pier run into a self-contained summary.html dashboard with KPI
cards, a ranked leaderboard, and four interactive charts, inspired by the
DeepSWE leaderboard and the Copilot agentic-harness report. Good clean,
shareable rendering was the goal, so the file opens straight from disk with
no server.

- New charts.py module (build_dashboard_html / write_dashboard /
  plotly_available) behind an optional [charts] extra; degrades gracefully
  with an install hint when Plotly is absent.
- New `chart` CLI command (--last/--out/--cdn/--open); `run` now emits
  summary.html automatically when Plotly is installed.
- Populate the previously stubbed variance/coverage aggregates in
  pier_results.py (std/cv for AIU and tokens, mean_resolved_rate,
  resolved_at_k_rate, per-task resolved_rate) and fix a CV key mismatch in
  report.py.
- Offline tests (test_charts.py plus aggregate and CLI tests), docs
  (visualizing-results.md, results-format.md, ADR 0021), and scaffold
  template updates.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The interactive HTML dashboards were gated behind a [charts] optional extra, so common install flows (uvx copilot-experiments, uv tool install --editable .) shipped without Plotly and failed the chart command with an install hint. Move Plotly into the core dependencies and drop the extra; the import stays guarded defensively so a broken install still raises a clear ChartError instead of ImportError.

Also update the scaffold template, docs, and ADR 0021 to describe Plotly as a required dependency.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
When every agent scored 100 percent, all points landed on the top line and their names (rendered with textposition top center) were cut off by the plot's top edge, plus the outermost labels overflowed the left/right edges. Add headroom above 100 percent, pad the x-range, set cliponaxis=False, and widen the chart's side margins so the labels are always fully visible.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
On-point text labels in the resolution-vs-cost scatter overlapped
horizontally when two agents landed at similar costs, because Plotly has
no collision avoidance for scatter text. Switch the trace to markers-only
and identify agents through the horizontal legend, which wraps cleanly at
any width. Drop the redundant on-plot '_ better' annotation (the panel
subtitle already says 'up and to the left is better') so it no longer
collides with the best point, and relax the now-unneeded x-axis label
inset padding.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@dbroeglin
dbroeglin merged commit 36d04f7 into main Jul 6, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant