Docs / dashboard-design · Edit on GitHub

rgBuilder static dashboard — engineering design (living document)

Status: Phase 8 complete (taint tab); Query Guide + HTTP serve integrated
Last updated: 2026-07-13
Owner: rgBuilder core / export pipeline

This document is the running source of truth for the WASM + WebGL dashboard replacement. Update the Implementation status section at the end of every phase PR.

Related: cli-io-sanity-qe.md, Code_structure.md, json-api.md.


Goals

GoalTarget
Scale300k+ nodes (community view); full exploration at smaller sizes
DistributionSelf-contained .rgbuilder/dashboard/ — no CDN, works offline
DataReuse columnar v2 graph.snapshot.bin as graph_payload.bin (no third graph format)
AnalysisRust/WASM worker; UI thread stays at 60 FPS
LegacyDelete monolithic html.rs — no parallel stacks

Repository layout

dashboard/                      # Vite + Preact + Bootstrap 5 (bundled, offline)
  src/styles.css                # Bootstrap import + graph layout tweaks
  src/App.tsx                   # Tab shell, stat toolbar
  src/worker.ts                 # Loads WASM + graph_payload.bin
  dist/                         # Built assets (npm run build) — embedded at compile time

crates/rgbuilder-dashboard/      # Rust: export bundle on discover
  src/lib.rs                    # export_dashboard_bundle()
  src/manifest.rs               # manifest.json schema
  src/bundle.rs                 # Copy/extract static assets

crates/rgbuilder-wasm/           # WASM engine (Phase 1+)
  src/lib.rs                    # Columnar v2 header parse, future graph ops

.rgbuilder/dashboard/            # Runtime output (per repo, gitignored)
  index.html
  assets/                       # Hashed JS/CSS from Vite
  manifest.json                 # Counts, paths, phase flags
  graph_payload.bin             # Copy of graph.snapshot.bin (columnar v2)
  wasm/                         # rgbuilder_engine.wasm + JS glue

Phase map (with mandatory removal)

PhaseBuildRemove
0Preact shell, bundle export, manifestcrates/rgbuilder-export/src/html.rs, CDN D3 dashboard
1graph_payload.bin, WASM header parse, worker bootJSON-in-HTML graph embed (already gone with html.rs)
2Sigma.js metanode view @ 50k+Placeholder graph renderer
3LOD drill-down, bitmask filters, function tablePlaceholder function tab text
4CFG/dominance from cfg_pdg.archive.binall_analyses.json (removed)
5Slice + CodeMirrorClient computeBackwardSlice
6Blast radius + depth slider in WASMClient blast BFS
7Dataflow (PDG def-use visualization)
8Taint from archiveEmbedded taint JSON
9Decommission auditAny remaining legacy grep hits

Phase 0 — Shell + bundle export

What it does

  1. discover writes .rgbuilder/dashboard/ instead of monolithic dashboard.html.
  2. UI: responsive tab bar matching legacy areas (graph, functions, CFG, slice, blast, guide).
  3. Stat cards read manifest.json (no inline graph JSON).
  4. Static assets bundled at compile time via include_dir from dashboard/dist/.

How to build the UI

cd dashboard && npm ci && npm run build
cargo build --release   # rgbuilder-dashboard embeds dashboard/dist

How to open after discover

rg-build discover .
# Option A — rg-build HTTP server (dashboard + POST /api/query)
rg-build serve --open
# Option B — local static server (WASM fetch; no query API)
cd .rgbuilder/dashboard && python3 -m http.server 8765
open http://localhost:8080   # or :8765 for Option B

Lookup

QuestionWhere
Export entrypointrgbuilder_dashboard::export_dashboard_bundle
Discover hooksrc/cli/discover_impl.rs
Manifest schemacrates/rgbuilder-dashboard/src/manifest.rs
Embedded UI filescrates/rgbuilder-dashboard/src/bundle.rs

Phase 1 — Binary payload + WASM loader

What it does

  1. graph_payload.bin — byte copy of .rgbuilder/graph.snapshot.bin (columnar v2).
  2. manifest.jsonpayload_format: "columnar_v2", node/edge counts, digest.
  3. Web worker fetches payload + instantiates WASM.
  4. WASM parses columnar header (magic, version, counts) — no full graph hydrate.

Worker message protocol (v1)

DirectionMessagePayload
UI → worker{ type: "init" }
worker → UI{ type: "ready", nodeCount, edgeCount, schemaVersion, wasm: true }
worker → UI{ type: "error", message }

Future phases add filter, blast_radius, compute_slice, etc.

Columnar v2 header (first 136 bytes)

See crates/rgbuilder-graph/src/columnar_snapshot.rs:

  • [0..4] magic RBGR
  • [4..8] format version 2
  • [8..12] schema version
  • [12..20] node count (u64 LE)
  • [20..28] edge count (u64 LE)
  • [28..92] digest (64-byte UTF-8, null padded)

WASM duplicates minimal parse in crates/rgbuilder-wasm/src/lib.rs (no full graph crate in WASM yet).

Lookup

QuestionWhere
WASM APIEngineContext::from_bytes in crates/rgbuilder-wasm
Build WASMscripts/build-dashboard.sh or wasm-pack build in crates/rgbuilder-wasm
Workerdashboard/src/worker.ts

manifest.json (schema v1)

{
  "schema_version": 1,
  "dashboard_version": "0.1.0",
  "phases": { "0": "complete", "1": "complete" },
  "graph": {
    "payload_path": "graph_payload.bin",
    "payload_format": "columnar_v2",
    "node_count": 798,
    "edge_count": 1506,
    "digest": "sha256:..."
  },
  "metrics": {
    "function_count": 120,
    "class_count": 45,
    "calls_count": 890,
    "avg_complexity": 2.4,
    "high_blast_radius_count": 3
  },
  "generated_at": "2026-07-03T20:00:00Z"
}

Sanity checks

Golden repo (run after every phase): /Users/sshaaf/git/java/gbuilder
Override: RGBUILDER_DASHBOARD_GOLDEN_REPO=/path/to/repo

# One-shot phase gate (build UI + WASM + both tests)
./scripts/test-dashboard-golden.sh

# Or manually:
./scripts/build-dashboard.sh
cargo build --release
cargo test --release --test dashboard_bundle --test dashboard_gbuilder -- --nocapture

# Preview gbuilder dashboard
cd /Users/sshaaf/git/java/gbuilder/.rgbuilder/dashboard && python3 -m http.server 8765

Test targets

TestRepoPurpose
dashboard_bundletests/fixtures/tiny_polyglot_repo (temp copy)Fast CI / minimal graph
dashboard_gbuilder/Users/sshaaf/git/java/gbuilderReal Java graph (~2k nodes)

Shared assertions: tests/dashboard_harness.rsassert_dashboard_bundle_with_meta().

Phase 2 artifacts

FileRole
metagraph.jsonPackage-level metanodes + aggregated call edges
manifest.viewMetagraph path, counts, mode, community_only flag

UI loads ./metagraph.json in the Graph tab (Sigma.js). At ≥50k source nodes, community_only is set: function_metrics.json carries schema metadata only (no per-function rows); use the metagraph and WASM node list for hotspots. member_indices are omitted from metagraph.json at this scale to keep export fast.

Phase 3 — LOD + filters

FeatureWhere
member_indices on metanodesmetagraph.json schema v2
WASM columnar expand / listEngineContext::expandIndices, listNodes
Worker messagesexpand, list_nodes in dashboard/src/worker.ts
Graph drill-downDouble-click metanode or Drill down in inspector
Type bitmask filterNodeTypeFilter — Function, Class, Struct, …
Function tableFunctionsView — virtual scroll via WASM pagination

Worker protocol (v2):

DirectionMessagePayload
UI → worker{ type: "expand", indices, typeMask }columnar row indices
worker → UI{ type: "subgraph", payload }nodes + internal call edges
UI → worker{ type: "list_nodes", typeMask, offset, limit }paginated scan
worker → UI{ type: "node_list", payload }{ total, offset, items }

Implementation status

Update this table when a phase lands.

ComponentPhaseStatusNotes
docs/dashboard-design.md0doneThis document
dashboard/ Preact shell0doneTabs + stat cards from manifest
rgbuilder-dashboard crate0doneexport_dashboard_bundle, embed dist
Discover → bundle (not html)0doneReplaces export_html_dashboard
Delete html.rs0doneRemoved from rgbuilder-export
graph_payload.bin copy1doneFrom graph.snapshot.bin
rgbuilder-wasm header parse1doneCounts from columnar v2
Worker + WASM boot in UI1doneStatus bar shows engine stats
tests/dashboard_bundle.rs0+1doneTiny fixture subprocess
tests/dashboard_gbuilder.rs0+1donegbuilder golden repo gate
scripts/test-dashboard-golden.sh0+1donePhase gate script
Sigma.js graph2doneGraphView.tsx — package metagraph WebGL
Community metanodes2donemetagraph.json export + inspector
tests/dashboard_harness.rs2doneAsserts metagraph.json, manifest.view, phase 2
WASM columnar LOD3doneexpandIndices / listNodes
Graph drill-down3doneSigma subgraph + breadcrumb
Bitmask type filters3doneGraph + Functions tabs
Functions virtual table3doneWASM paginated list
tests/dashboard_harness.rs3donephase 3 + member_indices
Bootstrap UI restore3+doneFull-height tabs, worker URL fix
CFG index + detail export4donecfg_index.json, cfg/*.json, archive copy; detail_mode: archive_only on large repos
CFG / dominance tab4doneCfgView.tsx Sigma CFG + idom table; on-demand record fetch when archive_only
Remove all_analyses.json4doneDiscover no longer writes consolidated JSON
Slice index + PDG export5doneslice_index.json, slice/*.json with source + PDG
CodeMirror slice tab5doneSliceView.tsx, worker compute_slice on exported PDG
tests/dashboard_harness.rs5donephase 5 + slice_index.json
WASM blastRadius API6doneReverse call-graph BFS with depth limit; score matches CLI macro impact
Blast radius tab6doneBlastView.tsx + depth slider
blast_index.json export6doneOptional snapshot copy
tests/dashboard_harness.rs6donephase 6 + blast_index.json
Dataflow index export7donedataflow_index.json → PDG in slice/
Dataflow tab (Sigma PDG)7doneDataflowView.tsx, worker compute_dataflow
tests/dashboard_harness.rs7donephase 7 + dataflow_index.json
Taint index + detail export8donetaint_index.json, taint/*.json from .rgbuilder/analysis/
Taint tab (flows table)8doneTaintView.tsx — source→sink paths from archive
tests/dashboard_harness.rs8donephase 8 + taint_index.json
tests/dashboard_metasfresh.rs8+manualmetasfresh discover --with-cfg --with-security --with-taint; ./scripts/test-dashboard-metasfresh.sh
Query Guide tab9doneGuideView.tsx + guideCliWorkflows.ts; validated by validate-guide-cli-gbuilder.sh
HTTP serve integration9donerg-build serve serves bundle + /api/query; see http-api.md
Migration tab live weights9doneMigrationView.tsx mirrors Rust scoring; exports in .rgbuilder/dashboard/

Removed (Phase 0)

  • crates/rgbuilder-export/src/html.rs (~2700 lines)
  • export_html_dashboard public API
  • Monolithic .rgbuilder/dashboard.html default output

Removed (Phase 4)

  • all_analyses.json writer in discover (discover --with-cfg still writes per-function storage + archive)

Not yet removed (later phases)

  • Discover-time blast radius string properties on nodes (Phase 6, dashboard only)

Query Guide (Phase 9)

The Query Guide tab (GuideView.tsx, dashboard/src/guideCliWorkflows.ts) documents CLI equivalents for each dashboard view. Workflows are validated against real repos via dashboard/scripts/validate-guide-cli-gbuilder.sh. End-user walkthrough: dashboard-user-guide.md.

Large-repo CFG (archive_only)

When function count exceeds the inline JSON budget, cfg_index.json sets detail_mode: "archive_only". The CFG and Dataflow tabs show a banner and load per-function records on demand from cfg_pdg.archive.bin sidecars (record_index_path, record_data_path).


PR checklist (every phase)

  • Build — new behavior documented in this file
  • Remove — deleted code listed in Implementation status
  • Sanity./scripts/test-dashboard-golden.sh passes (gbuilder + tiny fixture)
  • Docs — cli-getting-started path updated if user-visible