Skip to content

feat(dashboard): Run detail page + flamegraph#29

Merged
Exelord merged 1 commit into
mainfrom
claude/dashboard-run-detail
May 12, 2026
Merged

feat(dashboard): Run detail page + flamegraph#29
Exelord merged 1 commit into
mainfrom
claude/dashboard-run-detail

Conversation

@Exelord
Copy link
Copy Markdown
Member

@Exelord Exelord commented May 12, 2026

Final PR of the dashboard 10-PR sequence. Stacked on #28
(which is stacked on #27). Adds the #/runs/:id page that
visualises a single vzn run invocation as a flamegraph of task
wall-clock spans, plus a task table.

Pieces

  • src/flamegraph.ts — pure layout function:
    • one lane per project
    • bars positioned by wallclockStartNs (ns-precise when present,
      startedAt-relative ms fallback for legacy rows)
    • colorForTask() classifies status × cacheHit
    • unit-tested independent of rendering (4 layout cases, 5 color
      cases)
  • src/components/Flamegraph.tsx — absolute-positioned bars.
    No canvas, no SVG library — just position:absolute + calc().
    Hover sets a footer detail strip (project:task • duration •
    status • cache-hit).
  • src/pages/RunDetail.tsx — header summary cards (tasks /
    duration / started / OK / cached / failed), the Flamegraph, then
    a task table with CPU + peak-RSS columns and a StatusBadge
    component (cache-hit beats raw status).

Wiring

Test plan

  • bun run format clean
  • bun run lint clean
  • bun test packages/*/src/ apps/*/src/ — 277 pass / 0 fail
  • bun x vite build — 38 modules, 53 KB / 18 KB gzipped JS,
    7 KB CSS

Dashboard 10-PR track is now complete

PRs #19#29:

  1. feat(cache): schema v11 — analytics columns on runs table (dashboard PR 1/10) #19 Cache schema v11 — analytics columns
  2. feat(runner+sandbox): capture cpuMs + peakRssBytes via Bun.spawn rusage (dashboard 2/10) #20 Bun.spawn resourceUsage propagation
  3. feat(orchestrator): run_id ULID + hrtime spans per task #21 Run ID (ULID) + hrtime spans
  4. feat(dashboard): vzn dashboard subcommand + JSON API #22 vzn dashboard CLI + JSON API
  5. feat(dashboard): static UI shell + Overview & Cache pages #23 Static UI bundle (legacy, since deleted)
  6. feat(dashboard): Tasks + Runs UI pages #24 Overview + Cache pages
  7. (in this track) Tasks + Runs pages
  8. chore: re-monorepo — move @vzn/run code under packages/run/ #25 Re-monorepo (packages/run + apps/*)
  9. feat(dashboard): scaffold apps/dashboard with Vite + Solid + UnoCSS #26 apps/dashboard scaffold (Vite + Solid + UnoCSS)
  10. feat(dashboard): port Overview/Cache/Tasks/Runs pages to Solid #27 Port pages to Solid
  11. feat(dashboard): serve apps/dashboard/dist; remove legacy dashboard-ui/ #28 Serve apps/dashboard/dist; delete legacy UI
  12. feat(dashboard): Run detail page + flamegraph #29 (this PR) Run detail + flamegraph

Generated by Claude Code

Exelord added a commit that referenced this pull request May 12, 2026
…ents (#27)

PR 8/10 of the dashboard track. Replaces the legacy static-HTML page
modules (still living in packages/run/src/dashboard-ui/, to be removed
in PR #28) with proper Solid components.

- @solidjs/router HashRouter — URLs stay shaped like the legacy app
  (#/overview, #/runs, #/runs/:id) and the bundle works as a flat
  static asset without SPA-fallback server config
- src/api.ts: response types (OverviewResponse, RunSummary,
  SlowestTask, CacheEntryRow) + fetchJson<T>
- src/format.ts: formatAge / formatPercent / shortHash / shortRunId
  added, with tests; pre-existing formatBytes / formatDurationMs /
  formatRelativeTime kept
- Shared chrome via a <Shell> root component; pages render into it
  via the router's outlet
- <AsyncView resource={r}> for uniform loading/error/data handling
  on top of createResource
- Card / Empty primitives for the recurring summary-card and
  empty-state shapes

Run-detail + flamegraph land in PR #29; legacy dashboard-ui/ removal
+ server-side static-serving rewrite is PR #28.

Production bundle: ~46 KB raw / 16 KB gzipped JS, 5 KB CSS.

Co-authored-by: Claude <noreply@anthropic.com>
Exelord pushed a commit that referenced this pull request May 12, 2026
PR 9/10. Wires the JSON API server to the built Solid bundle and
deletes the inlined vanilla-JS UI.

- DashboardServerOptions: new required `uiDir` field
- handleRequest(db, req, uiDir): static-serving path is uiDir-relative
- resolveUiDir(): VZN_DASHBOARD_DIST env override → repo-relative
  apps/dashboard/dist; throws DashboardUiMissingError with a
  'bun --cwd apps/dashboard run build' fixit when missing
- Static-serving tests rewritten for the Vite layout
  (index.html + assets/<hashed>.{js,css}) and a path-traversal guard
- beforeAll builds the dist lazily on cold local runs; CI gets an
  explicit 'Build dashboard UI' step so test logs don't mix in vite
  output

Run-detail + flamegraph is the last dashboard PR (#29).
@Exelord Exelord force-pushed the claude/dashboard-serve-built branch from 94b902b to ba32df2 Compare May 12, 2026 08:14
@Exelord Exelord force-pushed the claude/dashboard-run-detail branch from b5f3f6e to 4aa6034 Compare May 12, 2026 08:15
Exelord pushed a commit that referenced this pull request May 12, 2026
PR 9/10. Wires the JSON API server to the built Solid bundle and
deletes the inlined vanilla-JS UI.

- DashboardServerOptions: new required `uiDir` field
- handleRequest(db, req, uiDir): static-serving path is uiDir-relative
- resolveUiDir(): VZN_DASHBOARD_DIST env override → repo-relative
  apps/dashboard/dist; throws DashboardUiMissingError with a
  'bun --cwd apps/dashboard run build' fixit when missing
- Static-serving tests rewritten for the Vite layout
  (index.html + assets/<hashed>.{js,css}) and a path-traversal guard
- beforeAll builds the dist lazily on cold local runs; CI gets an
  explicit 'Build dashboard UI' step so test logs don't mix in vite
  output

Run-detail + flamegraph is the last dashboard PR (#29).
@Exelord Exelord force-pushed the claude/dashboard-serve-built branch from ba32df2 to eee970a Compare May 12, 2026 08:16
@Exelord Exelord force-pushed the claude/dashboard-run-detail branch from 4aa6034 to dcd76cc Compare May 12, 2026 08:17
Exelord pushed a commit that referenced this pull request May 12, 2026
PR 9/10. Wires the JSON API server to the built Solid bundle and
deletes the inlined vanilla-JS UI.

- DashboardServerOptions: new required `uiDir` field
- handleRequest(db, req, uiDir): static-serving path is uiDir-relative
- resolveUiDir(): VZN_DASHBOARD_DIST env override → repo-relative
  apps/dashboard/dist; throws DashboardUiMissingError with a
  'bun --cwd apps/dashboard run build' fixit when missing
- Static-serving tests rewritten for the Vite layout
  (index.html + assets/<hashed>.{js,css}) and a path-traversal guard
- beforeAll builds the dist lazily on cold local runs; CI gets an
  explicit 'Build dashboard UI' step so test logs don't mix in vite
  output

Run-detail + flamegraph is the last dashboard PR (#29).
@Exelord Exelord force-pushed the claude/dashboard-serve-built branch from eee970a to b433a80 Compare May 12, 2026 08:19
Exelord added a commit that referenced this pull request May 12, 2026
…i/ (#28)

PR 9/10. Wires the JSON API server to the built Solid bundle and
deletes the inlined vanilla-JS UI.

- DashboardServerOptions: new required `uiDir` field
- handleRequest(db, req, uiDir): static-serving path is uiDir-relative
- resolveUiDir(): VZN_DASHBOARD_DIST env override → repo-relative
  apps/dashboard/dist; throws DashboardUiMissingError with a
  'bun --cwd apps/dashboard run build' fixit when missing
- Static-serving tests rewritten for the Vite layout
  (index.html + assets/<hashed>.{js,css}) and a path-traversal guard
- beforeAll builds the dist lazily on cold local runs; CI gets an
  explicit 'Build dashboard UI' step so test logs don't mix in vite
  output

Run-detail + flamegraph is the last dashboard PR (#29).

Co-authored-by: Claude <noreply@anthropic.com>
PR 10/10 of the dashboard track. Adds the #/runs/:id page that
visualises a single 'vzn run' invocation as a flamegraph of task
wall-clock spans, plus a task table.

- src/flamegraph.ts: pure layout (one lane per project; bars
  positioned by wallclockStartNs ns-precise when present, ms-epoch
  fallback for legacy rows); colorForTask classifies status x
  cacheHit. Unit-tested independent of rendering.
- src/components/Flamegraph.tsx: absolute-positioned bars (no canvas,
  no SVG library); hover sets a footer detail strip
- src/pages/RunDetail.tsx: header summary cards (tasks / duration /
  started / OK / cached / failed), the Flamegraph, then a task
  table with CPU + peak-RSS columns and a StatusBadge component
- Wired into the HashRouter as /runs/:id; the Runs page already
  links via #/runs/<id>
@Exelord Exelord force-pushed the claude/dashboard-run-detail branch from dcd76cc to bbff024 Compare May 12, 2026 08:20
@Exelord Exelord changed the base branch from claude/dashboard-serve-built to main May 12, 2026 08:20
@Exelord Exelord merged commit f30ac35 into main May 12, 2026
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.

2 participants