Reading the Observation Pane¶
The right-hand pane is not a progress spinner. It is the study itself — every card is rendered from an artifact on disk, so what you see is exactly what the run will use. This page walks the cards top to bottom.

The pipeline rail¶
One chip per stage: sv-init, sv-build-model (from-scratch studies only),
sv-build-environment, sv-build-population, sv-run, sv-report. Click a
chip to open that stage's detail card.
The chip's state is meaningful:
| state | what it tells you |
|---|---|
| done | this stage's artifact is current |
| stale | the artifact predates something upstream it depends on — it needs re-running |
| forked | this study was derived from a reference study (a study-level fork) and the artifact still comes from that source |
| from v\<n> | this version or branch carries its parent's artifact unchanged — expected, not a warning |
| 待复核 / review | a carried stage the current version has not reviewed yet |
The review state is the one people miss: after an iteration, stages the change
didn't touch still have to be checked before the pipeline counts as finished.
Exactly two things clear the flag — re-authoring the stage through its skill, or
validating the carried artifact and posting that stage's reasoning note for this
version. The assistant does one or the other and tells you which. Where the
review starts is fixed when the version is created (resume_from_stage on the
versions.json entry): see
Versions & the controllable research loop.
Stage detail¶
Whichever chip is selected, its card shows what that stage produced:
- sv-init — the scoped question, the horizon, the metrics with their one-line meanings, and the grounded facts found by the opening search.
- sv-build-environment — the environment layers with their
modality/scope/dynamics, and the intervention timeline: every intervention
(a scheduled event or a broadcast) with the step it fires on and, for a
broadcast, its audience. On a branch, interventions before the fork step
are dimmed and tagged
inherited— they are replayed from the parent run, not decided again here. - sv-build-population — the pool size and, importantly, the composition: how the personas distribute across their attributes. This is where you check the population is who you meant before spending anything on a run.
- sv-run — the run configuration, including what one step means in real
time (
time_unit/step_meaning). A trajectory should read as months or weeks, not as anonymous ticks. - sv-report — the rendered report.
Each card also carries a short reasoning note the stage wrote about its own choices. That's the assistant explaining itself at the point where the decision was made.
A run note, when the run doesn't belong here
Some studies wrap a heavy external pipeline — a reinforcement-learning trainer, for instance — that isn't appropriate to run inside the hosted service. Those carry a run note on the run card telling you to clone the repository and run it locally, and how to import the results back. Drug procurement is the worked example.
Metric timeline¶
Every metric the study declares for display, as a line, with a marker at each
step where an intervention fired — a scheduled event or a broadcast, read
from the environment bundle's scheduled_events and broadcasts. Hovering a
step shows the values and that step's intervention note, so a turning point is
labelled with what caused it.
- Hover a legend entry to see what that metric actually measures — its units and which direction is "more".
- Click a legend entry to hide that series, which is the fastest way to read a metric whose scale is drowned out by the others.
- The chart streams during a run: the curve grows step by step rather than appearing at the end.
- Once a study has more than one node in the version box, each node gets a
compare (对比 / ⇄) action. Choosing a baseline overlays it as dashed lines
in the same colour, draws each node's intervention markers separately, and
prints a Δ config chip row for what differs —
n_steps,seed, added (+) or removed (−) events and broadcasts, persona count. It affects only this card. - When the two nodes being compared are a branch and the version it branched from, the legend stops saying current / baseline and says treatment / control. That pair is a paired contrast: same individuals, same replayed history up to the fork step, one declared intervention after it.
Figures¶
The report's images, as a carousel — per-step maps for spatial studies, distributions otherwise, plus the metric timeline rendering that goes into the report file.
Agents¶
The panel data, made inspectable. A list of every agent in the pool; select one and you get its trajectory:
- its state at each step, in the study's own dimensions;
- its decision at each step;
- its output, where the behaviour produces something (a post, a survey answer, a chosen destination);
- and for LLM-driven studies, that agent's reason — one sentence, in the simulated person's own voice, explaining the choice as they would explain it to a peer.
That last one is the difference between a number changing and a number changing for a reason you can read. It is also live: the panel fills in during the run, not only after it.
This is the longitudinal payoff
Aggregate curves tell you the system moved. The agent panel tells you who moved, when, and why — the same individuals, followed across every step. That's what makes the output panel data rather than a sequence of snapshots.
Events¶
A log of what happened to the study: which stage produced what and when, the
reasoning note each stage posted, and every version or branch that was created
(a purple version chip with its id and note). build_events() in
dashboard/server/app.py reconstructs it on every request from artifact mtimes
plus versions.json, and version snapshots preserve those mtimes, so an earlier
line never disappears because a later iteration re-ran the same stage.
Fired interventions are logged on the run rather than here: they land in the
trajectory store's events table (step, note) and surface as the markers on
the metric timeline above.
Versions and branches¶
Once a study has been iterated, the version box lists every node in its history with its note. Two kinds of node live here, and the badge on each one says which:
| badge | what the edit was | what actually ran |
|---|---|---|
| version / 版本 | any edit to the study state — population P, behaviour function f, run settings Θ, or an environment entry before the fork step |
a cold run from step 0 |
| branch / 分支 | interventions added to the environment at or after a fork step t*, and nothing else |
steps 0..t*-1 replayed from the parent's stored actions (no model calls), steps t* onward actually simulated |
A branch prints its origin under the note — branched from v1 · at step 5 —
so the lineage reads without opening anything. A ⚠ downgraded to version chip
means the opposite happened: the node was created as a branch, but the edits in
the workspace reached beyond the environment (the population, the study's code,
the seed, or an intervention before the fork step), so the invariant check
downgraded it and it ran cold as a version. Nothing fails and nothing is lost —
the node simply no longer claims to be a counterfactual of its parent.
Selecting an older node renders it read-only from its snapshot, marked
archived · read-only — artifacts, results and figures exactly as that node had
them. Creating a new version or branch jumps the view to it, unless you are
deliberately inspecting an older one. ⇄ pins a node as the baseline for the
metric timeline above; + Intervene & branch drops a prefilled request into
the conversation, where the assistant still runs the version gate on it.
The box is a rendering of versions.json in the study directory:
versions_view() in dashboard/server/app.py serves each entry's kind,
fork_step, warm_start.source and downgraded_from_branch to the UI as
kind, fork_step, branch_of and downgraded. Which edits qualify for a
branch — and why a study that wraps an existing simulator, or runs several
interaction rounds per step, can only take versions — is
Iterate: versions and branches.
Grounding¶
Where the study's numbers came from: facts with their sources, modeling
references, and declared assumptions, each labelled sourced, proxy, or
assumed. The same ledger is rendered as the final section of the report.
Read Grounding & Provenance for what the three bases mean and why the distinction is load-bearing.