Skip to content

dashboard: something with hot reloading #114

Closed

Description

@quinn-dougherty

instead of a build-up-front website, should do something with bun dev thta hotreloads in-progress experiments.

Forget about presentation for now, focus on us / what we want for research.

Activity

  1. quinn-dougherty commented on Jun 11, 2026

    @quinn-dougherty
    MemberAuthor

    Design notes: a hot-reload research dashboard

    Proposed shape: bun create next-app → ./dashboard at monorepo root — a live job monitor, "like inspect view but fuzzing-shaped" (CPU/mem, exec/s, coverage & crash curves). Captuing the design discussion here.

    TL;DR — this is a data problem wearing a UI costume

    The stack choice is fine; the blocker is that we don't emit the live, fuzzing-shaped telemetry a hot-reload view needs. Fix the data feed first, the frontend is then a thin reader.

    What's missing on the Python side

    1. No live/incremental stream. save_manifest only fires at run-level transitions (mark_run_started/completed/failed), so polling the manifest gives "12 of 36 grid cells done," not the in-progress curves that are the point of this issue. Mid-run FuzzingState lives in Inspect's TaskState.store and never hits disk.
    2. No CPU/mem data at all. Today FuzzingStats captures execs_per_sec, total_execs, corpus_size, crashes_found, plus the oom_killed/timed_out flags — and they're point-in-time per cycle, not a time-series. The "CPU stats" ambition isn't backed by collected data; it needs docker stats sampling on the sandbox container inside the campaign loop.
    3. Don't couple to .eval. The Inspect ZIP log format is internal, and the pydantic-ai/logfire migration (Instrument Logfire on top of Inspect-AI (observability) #138) may delete it. A dashboard that parses .eval breaks on that migration.

    The load-bearing decision: a project-owned feed

    Define a JSON/JSONL "dashboard feed" contract that Python writes and TS reads, decoupled from both Inspect and logfire. The runner + campaign loop append one event per cycle; the dashboard is a thin reader (Next route handler tails the file server-side, pushes via SSE — or dumb 1s polling, since presentation is explicitly out of scope). This survives #138.

    Strawman event (per cycle, append-only results/<exp>/events.jsonl):

    { "run_id", "ts", "cycle",
      "execs_per_sec", "total_execs", "corpus_size", "unique_crashes",
      "line_coverage_pct", "branch_coverage_pct",
      "cpu_pct", "rss_bytes", "oom_killed", "timed_out",
      "tokens", "fuzz_seconds" }      // last two feed the #135 efficiency metrics
    

    The real fork (decide before scaffolding): vs. Logfire

    #138 adopts Logfire, which is itself a live job monitor (timeline, token usage, span drill-down). So:

    • Logfire-native — push fuzzing metrics as span attributes, build Logfire dashboards. Near-zero infra, but hosted/external and awkward for fuzzing-domain views (coverage-over-time, CASR crash clusters, swarm marginal-crash curve).
    • Bespoke ./dashboard — full control of fuzzing-shaped views, runs locally/offline against the results dir, but we build/maintain it.

    Recommendation: both, split by job. Logfire owns agent-trace + token drill-down (link out, don't reimplement). ./dashboard owns what Logfire can't show well: exec/s & coverage curves, crash dedup / CASR clusters, the #135 efficiency metrics (vulns_per_fuzz_hour, vulns_per_mtok_equiv), CPU/mem, and SwarmResult.marginal_crash_curve.

    Fit & footguns

    • ./dashboard parallels scaffold/ and comms/ cleanly. It subsumes the Streamlit viz/ (slated for overhaul) and stays distinct from comms/site — which is exactly the "build-up-front website" this issue says not to do. Clean split: dashboard = live research, comms/site = presentation.
    • Polyglot monorepo: the existing .github/workflows/ci.yml is scaffold-scoped (ruff/ty/pytest) and won't touch the TS app — add a separate dashboard job for lint/build.

    Thinnest de-risking slice

    1. Emit events.jsonl from the runner per cycle.
    2. Next route handler tails it + SSE.
    3. One page: run grid + per-run exec/s & crashes sparkline.

    CPU/mem is a fast-follow once docker stats sampling lands. This sequence proves the live-data pipe before any UI investment.

    Open decisions

    • Logfire-native vs bespoke vs both (recommend both, split by job)
    • Lock the events.jsonl schema + the runner/campaign emission points
    • Confirm ./dashboard replaces viz/
  2. quinn-dougherty commented on Jun 16, 2026

    @quinn-dougherty
    MemberAuthor

    Updated stance: lean on Logfire heavily; shrink the bespoke surface

    Since the "both, split by job" comment above, the ground has shifted in Logfire's favor:

    Revised recommendation: Logfire is the primary research dashboard. Build bespoke UI only for the residue Logfire genuinely can't express, and keep that residue as small as possible:

    This also collapses the live-data plumbing: no events.jsonl + SSE tail to build/maintain for anything Logfire already ingests. We get hot-reload-ish live views for free from Logfire's live tail.

    On viz/

    Maintainer says they don't care about viz/. So drop the "overhaul Streamlit viz" framing entirely — Logfire replaces viz/, it doesn't get rebuilt. comms/site stays as the separate presentation layer (the "build-up-front website" this issue says not to do for research).

    Updated open decisions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions