Skip to content

The Run Dashboard

A study's state lives in files, and files are hard to watch. The bundled dashboard is a local, read-only web view over studies/<id>/ that compresses the workflow down to what you actually want to see: which stage is done, what artifact it produced, the metric curve as it fills in, and each agent's trajectory.

It has zero third-party dependencies — it runs on the same Python you installed SocioVerse with, no pip install. The data tables read the DuckDB stores, so they need duckdb in that interpreter, which the SocioVerse install already provides; without it only those tables stay empty.

Start it

python dashboard/server/app.py --port 8787 --open
# then visit http://127.0.0.1:8787

--open launches your browser. In practice you rarely type this: the agentic workflow starts the dashboard for you — /sv-init launches it as its first action, opens a tab, and prints the URL; every later sv-* stage reuses the same server silently.

One server per workspace

Launching no-ops if 8787 is already up, so several Claude Code sessions on the same workspace share one dashboard instead of fighting over the port. Idle self-reap is off by default — once launched the server holds the port for the whole session, so a backgrounded tab or a paused run never loses it. Set SV_DASH_IDLE=<seconds> if you'd rather it quit when nothing is happening.

flag default effect
--port 8787 port to bind
--host 127.0.0.1 bind address; use 0.0.0.0 to serve from inside a container
--root the repo's studies/ point the view at a different studies directory
--open off open a browser tab on start
env var default effect
SV_DASH_PORT 8787 port the workflow's hooks talk to
SV_DASH_OPEN 1 0 = announce the URL but don't open a browser
SV_DASH_IDLE 0 (off) seconds of idleness before self-shutdown
SV_DASH_DISABLE — set to anything = the workflow never launches or announces it
SV_DASH_SHOW_TEMPLATES — 1 = also list the bare abm_* template shells

What's on screen

┌ top bar ── title · path · research question · run status · study switcher ─┐
├ pipeline ─┬─ active-stage detail ──────────────────────────────────────────┤
│ sv-init ✓ │  per-stage card (init facts / env layers / run config / report)│
│ …model  – │                                                                │
│ …env    ✓ │                                                                │
│ …pop    ✓ ├─ metric timeline ───────────────┬─ figure carousel ───────────┤
│ …run    ✓ │  lines + intervention markers   │  reports/figures/*.png      │
│ …report ◔ ├─ event feed ────────────────────┴─────────────────────────────┤
└───────────┴─ compressed, semantic-only (no raw tool spam) ─────────────────┘
  • Pipeline rail — one chip per sv-* stage with its status (see the vocabulary below). Clicking a stage opens its detail card.
  • Stage detail — the artifact that stage wrote, rendered: sv-init's grounded facts, the environment's layers and scheduled interventions, the population's composition, the run config (including time_unit / step_meaning), the report. Each card also carries a short Reasoning note the skill self-reported when it ran.
  • Metric timeline — every declared metric as a line, with markers where interventions fired. Legend entries carry each metric's metric_descriptions text as a tooltip; clicking one hides that series.
  • Figure carousel — the PNGs under reports/figures/.
  • Agents card — every instantiated agent, and for the selected one its per-step state, decision, and output. This is the panel data made visible: an agent's trajectory is its memory.
  • Event feed — a log of what happened, reconstructed in full on every request, so earlier lines never vanish when a later iteration re-runs a stage.
  • Versions & branches — the /sv-iterate tree of research states. Every node carries a kind badge: version (a cold re-run) or branch (only new interventions, its history before the fork step replayed from the parent — "branched from v1 · at step 5"). A branch whose workspace edits went beyond the environment carries an amber downgraded to version chip: it ran cold. Selecting an archived node renders it read-only from its snapshot.

Status vocabulary

The colours mean specific things, and the distinctions are the point:

badge meaning
done this stage's artifact is current
stale (coral, "re-run") the artifact predates a build artifact it depends on — something upstream changed under it
inherited (amber) a Path-A fork copied this artifact from its source and you haven't re-authored it yet
from v\<parent> (neutral) a version deliberately reuses its parent's artifact — reuse is intended, not a warning
archived (purple) you are viewing a frozen versions/vN/ snapshot, not the live directory

Live during a run

The dashboard streams while /sv-run is working. The engine appends trajectory/progress.jsonl each step, and a lock-free trajectory/panel_live.jsonl mirrors the panel rows (DuckDB is write-locked mid-run) — so the step bar advances, the chart grows, and the agent inspector updates before the run finishes. The browser reconnects over SSE by itself if the server restarts.

A top banner and the tab title (⏳ waiting for you) flip on when the workflow is blocked on your answer, so a backgrounded tab still signals.

Compare versions and branches

The metric timeline card's title row has a vs selector. Picking a baseline overlays it on the timeline as dashed lines in the same hue, draws each node's intervention markers separately, and shows a Δ-config strip: what changed in n_steps / seed, which scheduled events and broadcasts were added or removed, and how the persona count differs. It affects only that card — the rest of the view stays on your current version.

When the baseline is the version a branch came from, the pair is labelled control (the source) and treatment (the branch): the two share an identical history up to the fork step, so the distance between the curves is the declared intervention's effect. Any other pair compares two research designs, which is what the Δ-config strip is for.

Where the data comes from

Two channels, deliberately separated:

  1. Files are authoritative. The server watches studies/<id>/ and reconstructs everything from the artifacts the skills already write — study.yaml, environment.json, population.json, simulation.json, trajectory/progress.jsonl, metrics_history.json, reports/, versions.json. That makes the view robust to Claude Code restarts, subprocess writes, and hand-edits.
  2. POST /ingest carries reasoning. Each stage self-reports a one-line narrative, merged onto its card and into the feed. Nothing else is pushed — there is no raw tool-call stream.

The HTTP surface is small and stable enough to script against:

route purpose
GET /api/state study list + progress + current selection
GET /api/study/<id> full reconstructed detail for one study
GET /api/study/<id>/agents · …/agent/<aid> the agent inspector
GET /api/study/<id>/version/<v> an archived version's detail (…/agents, …/figure/<name> too)
GET /api/stream SSE nudge on any artifact write
POST /ingest record a stage narrative
curl -X POST http://127.0.0.1:8787/ingest -H 'Content-Type: application/json' \
  -d '{"study_id":"chicago_schelling","stage":"sv-init",
       "narrative":"Routed to Path A — matched on domain=urban-segregation; forked the baseline."}'

Read-only, by design

The dashboard never writes to a study. It cannot start a run, edit an artifact, or delete a version — those are workflow actions. The one exception is the hosted service, where a chat panel appears next to the same view; see the hosted workbench.

Export a static copy

To share results without shipping the server (a paper appendix, a project page), export a self-contained snapshot:

python scripts/export_dashboard_static.py \
  --studies opinion_diffusion consumer_confidence chicago_schelling \
  --out ./gallery

The output is plain HTML + JSON with deep links (index.html?study=<id>) and needs nothing but a static file server.