Why
Studio v0.77+ writes a per-trial stimulus-quality verdict into every run log ({"type":"log","event":"trial_quality", "trials":[{trial, pattern, status: pass|fail|unknown, slow_reads, stalls, max_read_ms, max_age_ms, coverage, …}]}, plus one display_gap event per stall). The Studio flags, never auto-excludes (selection-bias rule). The dashboard currently parses these logs fine (verified 2026-09-14 on rig03-sr's 13 runs: 0 parse errors, frames/steps/metadata correct) but ignores both events, so a flagged trial is plotted like any other.
First field case, 2026-09-14 rig03-sr: 6 of 638 trials flagged — each a ≈ 400 ms card-internal stall on pattern 41 (firmware #54, comment of 2026-09-14). The experimenter has no way to see them in the dashboard today; the list had to be posted by hand.
What
In dashboard/data-browser (shared logic preferably in js/, vendored like runlog-format.js):
- Read
trial_quality (last one in the file wins; a run may have a deferred rewrite) and attach status + the reason (stalls, max_read_ms, max_age_ms, coverage) to each step/trial by trial number → step mapping (trial is 1-based over the sequence's trialParams steps).
- Show it: a per-trial badge/colour in the step table and trial plots (pass = nothing, flagged = ⚠ with tooltip "N stalls, max read X ms", unknown = ? "coverage incomplete"); a run-level line in the header ("56 trials · 1 flagged · 0 unknown").
- Exclude toggle, off by default: "hide flagged trials" checkbox for the aggregate plots; the excluded count stays visible. Never exclude silently.
- Optional: mark
display_gap events on the time axis of the per-trial trace.
- Old logs (no
trial_quality) render exactly as today.
Format authority
docs/development/telemetry-logging-reference.md (events section) and js/trial-quality.js (field names). Reader rule: any string-tagged array row ("cc"/"cf"/"cs") is a stream and must stay skipped.
Tests
Extend the dashboard/reader tests with a fixture containing a trial_quality event (one pass, one fail, one unknown) and assert the per-step attachment + header counts; keep tests/test-runlog-format.js copy-identity check green.
Why
Studio v0.77+ writes a per-trial stimulus-quality verdict into every run log (
{"type":"log","event":"trial_quality", "trials":[{trial, pattern, status: pass|fail|unknown, slow_reads, stalls, max_read_ms, max_age_ms, coverage, …}]}, plus onedisplay_gapevent per stall). The Studio flags, never auto-excludes (selection-bias rule). The dashboard currently parses these logs fine (verified 2026-09-14 on rig03-sr's 13 runs: 0 parse errors, frames/steps/metadata correct) but ignores both events, so a flagged trial is plotted like any other.First field case, 2026-09-14 rig03-sr: 6 of 638 trials flagged — each a ≈ 400 ms card-internal stall on pattern 41 (firmware #54, comment of 2026-09-14). The experimenter has no way to see them in the dashboard today; the list had to be posted by hand.
What
In
dashboard/data-browser(shared logic preferably injs/, vendored likerunlog-format.js):trial_quality(last one in the file wins; a run may have a deferred rewrite) and attachstatus+ the reason (stalls,max_read_ms,max_age_ms,coverage) to each step/trial by trial number → step mapping (trialis 1-based over the sequence's trialParams steps).display_gapevents on the time axis of the per-trial trace.trial_quality) render exactly as today.Format authority
docs/development/telemetry-logging-reference.md(events section) andjs/trial-quality.js(field names). Reader rule: any string-tagged array row ("cc"/"cf"/"cs") is a stream and must stay skipped.Tests
Extend the dashboard/reader tests with a fixture containing a
trial_qualityevent (one pass, one fail, one unknown) and assert the per-step attachment + header counts; keeptests/test-runlog-format.jscopy-identity check green.