Skip to content

Add a local web viewer for experiment runs#122

Open
merlerm wants to merge 10 commits into
mainfrom
results-viewer
Open

Add a local web viewer for experiment runs#122
merlerm wants to merge 10 commits into
mainfrom
results-viewer

Conversation

@merlerm

@merlerm merlerm commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Inspecting a sweep meant opening results.json by hand and hunting for the matching GIFs and sandbox git history across output directories. This puts the viewer I have been using locally into the repo.

experiments/results_viewer.py is a stdlib-only HTTP server that serves a browsable index of every run found under --root:

  • metrics, including the gen_* generation metrics
  • per-episode success/failure GIFs, with an on-demand re-render for episodes that were not recorded
  • the sandbox git history of the generated approach.py, with per-commit diffs and the agent's reasoning matched from stream.jsonl

Browsing needs only the Python stdlib. hydra, numpy, and the robocode packages are imported lazily on the first render, so a downloaded outputs/ folder can be inspected on a machine without the full environment.

python experiments/results_viewer.py --root . --port 8000

The scan walks --root recursively and picks up runs wherever they live (outputs/, multirun/, or a curated collection), skipping re-eval passes. viewer_runs/ is gitignored as the conventional spot for a curated collection.

Checks: pylint 10.00/10, mypy clean. Smoke-tested against 19 local runs: index, static assets, /api/runs, /api/stamp, and run detail all return 200 with correct metrics, 100 episodes, and history detected.

Inspecting a sweep meant opening results.json by hand and hunting for the
matching GIFs and sandbox git history across output directories.

experiments/results_viewer.py serves a browsable index of every run found
under --root: metrics, per-episode success/failure GIFs, and the sandbox
git history of the generated approach.py with per-commit diffs and the
agent's reasoning pulled from stream.jsonl. It can also re-render a GIF for
any episode on the current or a past approach version.

Browsing needs only the Python stdlib; hydra, numpy, and the robocode
packages are imported lazily on the first render, so a downloaded outputs/
folder can be inspected on a machine without the full environment.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a stdlib-only local HTTP results viewer to make it easier to browse experiment run outputs (metrics, per-episode GIFs, and sandbox approach.py git history) without manually navigating results.json and run directories.

Changes:

  • Introduces experiments/results_viewer.py, a small HTTP server + embedded frontend for indexing runs and rendering/serving per-episode GIFs and approach history.
  • Documents how to launch the viewer from the README.
  • Adds viewer_runs/ to .gitignore as a conventional curated runs collection directory.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 6 comments.

File Description
README.md Documents launching the new results viewer.
experiments/results_viewer.py New local web UI + API for browsing runs and (optionally) re-rendering GIFs and viewing sandbox history.
.gitignore Ignores viewer_runs/ as a curated run collection directory.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread experiments/results_viewer.py Outdated
Comment thread experiments/results_viewer.py
Comment thread experiments/results_viewer.py
Comment thread experiments/results_viewer.py Outdated
Comment thread experiments/results_viewer.py Outdated
Comment thread experiments/results_viewer.py
Three fixes from review:

- The render worker composed its replay config with `primitives=[]`. A
  generated approach.py indexes the exact primitives it was written against,
  so re-rendering any run that used primitives raised KeyError. Resolve the
  run's own set from its .hydra directory instead, preferring the recorded
  override and falling back to the resolved list in config.yaml.
- `_safe` compared resolved paths with a string prefix, which admits a
  sibling directory sharing the prefix (/runs/ab passes a /runs/a check).
  Use Path.is_relative_to.
- The server bound 0.0.0.0, exposing run logs and files to anyone who could
  reach the port. Bind 127.0.0.1 by default, with --host to opt back out.
@merlerm
merlerm requested a review from tomsilver July 21, 2026 14:48

@tomsilver tomsilver left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not checking this carefully but seems useful :)

@merlerm
merlerm enabled auto-merge (squash) July 22, 2026 08:03
@merlerm
merlerm disabled auto-merge July 22, 2026 08:05
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.

3 participants