Repository navigation
fix eight dashboard defects found by driving the live dashboard - #110
Merged
Merged
Conversation
The empty state told users to run `rgctl discover . --languages java --cfg`, which neither enables taint (that needs --with-taint) nor applies to a non-Java repo. `--with-taint` implies the CFG/PDG pass, so it is the only flag the message needs to name. dashboard/src/TaintView.tsx:96-104 (cherry picked from commit d1d28e2) Signed-off-by: Sami Jan <sami.jan@gmail.com>
The Field mutations (CPG) panel seeded its type filter with "ShoppingCart" — a value that only exists in the CoolStore sample project. On any other repo the filter matched nothing, so a working feature rendered "0 shown" on first paint and read as broken. An empty filter already matches every write (matchesType returns true when `want` is empty), so start empty and derive the placeholder from the types that were actually indexed. dashboard/src/MutationsPanel.tsx:48,115 (cherry picked from commit d8cb093) Signed-off-by: Sami Jan <sami.jan@gmail.com>
ViewLegend renders its `hint` prop as visible muted body copy. The blast view passed it "Sidebar meta: impact score · direct callers · impact zone", a note-to-self about the sidebar, so users read it as a caption. The view has no colour or shape encoding, so the legend is dropped rather than given a legend it cannot justify. The import goes with it. dashboard/src/BlastView.tsx:182-185 (cherry picked from commit 0ef13f1) Signed-off-by: Sami Jan <sami.jan@gmail.com>
rgctl does not run Louvain, and does not run Leiden either: what ships is label propagation (Raghavan et al. 2007) with Newman modularity scoring, as docs/design/graph-metrics-design.md:87 already states outright. Two user-visible strings still claimed Louvain. The serialized field name `louvain_community_id` is deliberately untouched — renaming it would break the migration JSON contract for existing consumers. dashboard/src/GraphView.tsx:366, dashboard/src/MigrationView.tsx:550 (cherry picked from commit 08c148b) Signed-off-by: Sami Jan <sami.jan@gmail.com>
"Filtered Nodes" read `manifest.graph.node_count` — the same expression as the "Total Nodes" card beside it — and there is no filter state anywhere in the shell for it to reflect. On the audited repo both cards rendered 5345. The card is removed rather than wired up: with no filter active the honest value is the total, which is already on screen. dashboard/src/App.tsx:104 (cherry picked from commit 21a3fe6) Signed-off-by: Sami Jan <sami.jan@gmail.com>
The footer printed a repo-internal doc path and the payload format codename in Bootstrap's pink <code> styling, so users saw "docs/dashboard-design.md · manifest v1 · columnar_v2" on every page. It now shows what a user can act on: when the graph was indexed, the graph digest (truncated, full value on hover), and the dashboard version for bug reports. The digest is the same identity the temporal/diff surfaces key on. dashboard/src/App.tsx:168-171 (cherry picked from commit 28f6761) Signed-off-by: Sami Jan <sami.jan@gmail.com>
The Functions table showed "—" for BC, Harm and Blast on every row of the
audited repo, which read as a broken column. The plumbing is actually fine:
`function_metrics.json` reaches the browser and joins on node index
(dashboard/src/worker.ts:106-114). The columns are empty for three separate
reasons, and the formatter hid all of them by collapsing `0` and
`undefined` into the same glyph:
- betweenness is computed but genuinely sparse — 12 of 5345 rows nonzero
on the audited repo (sampled Brandes above 500 nodes)
- harmonic is opt-in and hard-zeroed unless --with-harmonic is passed
(crates/rgctl-analysis/src/centrality.rs:788)
- blast is never bulk-filled on a flat call graph, so it is 0 of 5345
(src/cli/discover_impl.rs:884, blast_radius_scc.rs:202)
`—` now means "not available for this node" and a computed zero renders as
`0`, so the table tells the truth instead of looking dead. The column
tooltips also state the gating, which was previously undocumented in the UI.
dashboard/src/functionListUtils.ts:31-70
(cherry picked from commit fd7fc5d)
Signed-off-by: Sami Jan <sami.jan@gmail.com>
The CFG sidebar rendered two distinct functions as byte-identical rows:
same name, same "…/src/App.tsx · 2 blocks" meta, different function ids.
`shortPath` kept only the last two path segments, so any two files sharing
a final directory collapsed together (e.g. src/routes/orders.ts and
src/coolstore/routes/orders.ts both became "…/routes/orders.ts").
The index is not at fault: cfg_index.json is keyed by stable_key
(crates/rgctl-analysis/src/storage.rs:196-207) and contained no duplicate
ids in the audit — only the display collided.
- keep three trailing segments, which separates the observed collisions
- return paths that already fit verbatim, instead of prefixing "…" to
paths that never needed eliding (src/App.tsx read as "…/src/App.tsx")
- expose the full path via title, so a row can always be identified
dashboard/src/functionListUtils.ts:160-169, FunctionListSidebar.tsx:193
(cherry picked from commit 82a2aab)
Signed-off-by: Sami Jan <sami.jan@gmail.com>
The eight fixes in this branch changed dashboard/src, but the built bundle is a separate committed artifact and the binary embeds it at compile time (crates/rgctl-dashboard/src/bundle.rs:7). Without this commit the fixes were inert: users would see the old dashboard until someone rebuilt. That mismatch was the exception, not the norm — three of upstream's last four dashboard commits updated src and dist together: 9038146 kantra dashboard support src 9 dist 24 e331284 default under user home src 12 dist 23 d9b0f15 move to rgctl src 8 dist 5 f706150 semantic index vocab src 2 dist 0 Rebuilt with the real toolchain rather than the build script's fallback: rustup target add wasm32-unknown-unknown brew install wasm-pack wasm-pack build crates/rgctl-wasm --target web --out-dir dashboard/wasm \ --release --no-opt cd dashboard && npm run build scripts/build-dashboard.sh:13-19 writes a *throwing stub* rgctl_wasm.js when wasm-pack is absent, which the bundler then bakes in — so rebuilding without wasm-pack would have replaced the real engine with a stub. Verified instead that the new module is genuine (197,295 bytes, WebAssembly MVP magic) and that the old 190,188-byte module is gone. Also verified the fixes are present in the built output, not just the source: the --with-harmonic tooltip, the footer graph-digest receipt, and the three-segment path shortening all appear in the new chunks, and the leaked "Sidebar meta" stub string does not. The two remaining "ShoppingCart" hits are documentation examples (the Guide's CLI samples and the Dataflow tab description), not the removed default — MutationsPanel.tsx now contains zero. Incidental: dashboard/wasm/package.json was stale at 0.4.17 and is now 0.4.19, which is what wasm-pack regenerates. tsc -b passes (it previously failed on the missing ../wasm/rgctl_wasm.js module, which is a real prerequisite, not test noise). 21/21 dashboard tests pass after the rebuild. Signed-off-by: Sami Jan <sami.jan@gmail.com>
samiujan
force-pushed
the
upstream/dashboard-defect-fixes
branch
from
October 13, 2026 19:01
e91188d to
33e6e0c
Compare
Contributor
Author
|
Two force-pushes on this branch after opening it — apologies for the noise, both were fixes to my own
I also replaced the original description, which still claimed No review has happened yet, so nothing was invalidated — but I would rather flag it than leave you |
samiujan
added a commit
to samiujan/rgctl
that referenced
this pull request
Oct 14, 2026
…monstrate
Two rows were out of date after the rebase onto main:
- `dashboard/dist` regen was marked **blocked**, "source fixes are not in the
embedded bundle until dist is rebuilt". That landed in 8f09655 as
sshaaf#110. The row now says done, and says why it mattered: `dist` is
compile-time embedded, so until it is rebuilt the source fixes are invisible in
a built binary while every test passes.
- Change 7 was blocked on two `rgctl slice` defects. Both are now fixed and under
review (issues sshaaf#113/sshaaf#114, PRs sshaaf#115/sshaaf#116), so the row records what actually
gates it.
Also adds open question 4, because the more interesting problem is a gap rather than
a stale value: the maintainer's parking comment on sshaaf#61 names the code browser as the
missing piece, and no change in this sequence is the code browser. Change 1 is the
shell, changes 2-6 are rooms, and none renders source. The prototype does not cover
for it either — the Code lens shows a count of source lines, not source, and Spine
renders an empty state. The one requirement singled out is the one this design
cannot demonstrate.
Recorded as an open question, not invented as a change number: folding source
rendering into change 1 versus giving it its own change ahead of the rooms is a
scoping decision, not a correction.
Signed-off-by: Sami Jan <sami.jan@gmail.com>
samiujan
added a commit
to samiujan/rgctl
that referenced
this pull request
Oct 14, 2026
…monstrate
Two rows were out of date after the rebase onto main:
- `dashboard/dist` regen was marked **blocked**, "source fixes are not in the
embedded bundle until dist is rebuilt". That landed in 8f09655 as
sshaaf#110. The row now says done, and says why it mattered: `dist` is
compile-time embedded, so until it is rebuilt the source fixes are invisible in
a built binary while every test passes.
- Change 7 was blocked on two `rgctl slice` defects. Both are now fixed and under
review (issues sshaaf#113/sshaaf#114, PRs sshaaf#115/sshaaf#116), so the row records what actually
gates it.
Also adds open question 4, because the more interesting problem is a gap rather than
a stale value: the maintainer's parking comment on sshaaf#61 names the code browser as the
missing piece, and no change in this sequence is the code browser. Change 1 is the
shell, changes 2-6 are rooms, and none renders source. The prototype does not cover
for it either — the Code lens shows a count of source lines, not source, and Spine
renders an empty state. The one requirement singled out is the one this design
cannot demonstrate.
Recorded as an open question, not invented as a change number: folding source
rendering into change 1 versus giving it its own change ahead of the rooms is a
scoping decision, not a correction.
Signed-off-by: Sami Jan <sami.jan@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Eight independent fixes found by auditing the shipping dashboard against a live
rgctl serveindexing aTypeScript repo (5,345 nodes / 11,801 edges / 1,479 functions), driving each tab over the Chrome DevTools
Protocol and capturing DOM evidence. Each fix is its own commit so any of them can be dropped or
cherry-picked independently.
Fixes #112
dashboard/distis rebuilt in this branch, not left stale. These fixes changedashboard/src, butthe built bundle is a separate committed artifact that the binary embeds at compile time — several
upstream dashboard commits update both together. Rebuilding needed a real
wasm-packbuild (the buildscript substitutes a throwing stub engine when it is missing), so the last commit here carries the
rebuilt assets. Details in Additional Notes.
Type of Change
Changes Made
One commit each, in the order they appear on the branch:
discover . --languages java --cfg;--cfgdoes not produce a taint index (--with-taintdoes, andit already implies the CFG pass —
src/cli/discover_impl.rs:116), and it hardcoded a language on aTypeScript repo.
dashboard/src/TaintView.tsx:96-104useState("ShoppingCart")meant the Fieldmutations panel rendered "0 shown" on every other repo — a working feature that looked broken. An
empty filter already matches everything (
MutationsPanel.tsx:19), so it now starts empty and derivesits placeholder from
index.types.dashboard/src/MutationsPanel.tsx:48,115ViewLegendrenders itshintprop as visible body copy(
ViewLegend.tsx:24), and the blast view passed it "Sidebar meta: impact score · direct callers ·impact zone". Of nine
hint=call sites, only this one was a note-to-self; the rest are legitimatelegend headings. The view has no colour or shape encoding, so the legend was removed rather than
given a fake one.
dashboard/src/BlastView.tsx:182-1850andundefinedrendered as the same glyph.—for BC/Harm/Blast on nearly every row, withnothing explaining why. The plumbing is fine — three separate data causes: betweenness is genuinely
sparse (12 of 5,345 rows nonzero), harmonic is opt-in and hard-zeroed
(
crates/rgctl-analysis/src/centrality.rs:788), and blast is never bulk-filled on a flat call graph(
src/cli/discover_impl.rs:884; 0 of 5,345).—now means unavailable, a computed zero renders as0, and the column tooltips state the gating, which was previously undocumented in the UI.dashboard/src/functionListUtils.ts:31-70Nodes" (
App.tsx:98and:104), and there is no filter state in the shell for it to reflect.dashboard/src/App.tsx:104Bootstrap's pink
<code>styling, on every page. Replaced with the graph receipt: index time,truncated graph digest (full value on hover), dashboard version.
dashboard/src/App.tsx:168-171Apptwice withbyte-identical meta for two different
function_ids.shortPathkept only the last two pathsegments, so any two files sharing a final directory collapsed (
src/routes/orders.tsandsrc/coolstore/routes/orders.tsboth became…/routes/orders.ts). The index is not at fault —cfg_index.jsonis keyed bystable_key(storage.rs:196-207); an instrumented run produced 155entries / 155 unique ids / 0 duplicate pairs. Now keeps three segments, returns short paths verbatim
instead of prefixing
…needlessly, and exposes the full path viatitle.dashboard/src/functionListUtils.ts:160-169,FunctionListSidebar.tsx:193propagation with Newman modularity, as
docs/design/graph-metrics-design.md:87already statesoutright. Fixed two user-visible strings; the serialized field name
louvain_community_idisdeliberately left alone, since renaming it would break the migration JSON contract.
dashboard/src/GraphView.tsx:366,MigrationView.tsx:550New tests:
functionListUtils.metrics.test.ts(6) andfunctionListUtils.paths.test.ts(4), split soeach commit's tests pass independently.
Testing
Unit tests added/updated
Integration tests added/updated —
cargo test --test dashboard_bundle(project gate)Tested with
cargo test— the dashboard bundle gate; full suite not run, no Rust changesManual testing performed
npx vitest run— 21 passed / 21 across 5 files (10 of them new).npx tsc -b— passes, after the wasm build below produceddashboard/wasm/rgctl_wasm.js. On a cleancheckout this fails with
src/worker.ts(3,53): Cannot find module '../wasm/rgctl_wasm.js', which is agenuine build prerequisite rather than test noise.
cargo test --test dashboard_bundle— 2 passed, confirming the rebuiltdistis structurally validfor the
include_dir!embed and that discover writes the bundle correctly on the tiny fixture.wasm-pack build crates/rgctl-wasm --target web --release --no-opt— the engine is real, not the buildscript's stub fallback: new module 197,295 bytes, old 190,188-byte module deleted.
cargo testwas not run in full — no Rust code changed. Note that two lib tests fail on a clean tree(
cli::agent_pack::tests::embedded_pack_lists_cursor_skills,languages::registry::tests::test_registry_creation); verified identical before and after thesechanges.
Test environment:
Checklist
cargo fmt) — n/a, no Rust changescargo test) — not run; no Rust code changedcargo clippy --all-targets -- -D warnings) — not run; no Rust code changeddocs/changes neededSigned-off-by: Sami Jan <sami.jan@gmail.com>)Performance Impact
All changes are presentational. The only extra work is
index.types[0]for a placeholder anddigest.slice(0, 12)for the footer.Breaking Changes
None. No API, schema, or serialized field changed.
Screenshots (if applicable)
Not attached — these were diagnosed from CDP screenshots and DOM dumps; happy to attach
before/after captures if useful.
Additional Notes
dashboard/distis rebuilt in the final commit of this branch.dashboard/distis tracked(
.gitignore:34only ignores the root/dist) and compile-time embedded viainclude_dir!("…/dashboard/dist")(crates/rgctl-dashboard/src/bundle.rs:7), so source changes underdashboard/src/have no effect on the shipped dashboard untildistis rebuilt and committed. Upstreamusually does both together — three of the last four dashboard commits updated
srcanddist(
9038146,e331284,d9b0f15).Built with the real toolchain:
Verified rather than assumed: the new
rgctl_wasm_bg-*.wasmis a genuine 197,295-byte WebAssemblymodule and the old 190,188-byte one is gone; the fixes appear in the built chunks (the
--with-harmonictooltip, the footer graph-digest receipt, three-segment path shortening) and theleaked "Sidebar meta" string does not;
tsc -bpasses; 21/21 dashboard tests pass; andcargo test --test dashboard_bundlepasses. Rebuiltdistassets change hashed filenames, so thecommit is mostly renames plus
index.html— normal for a bundle rebuild in this repo.Separately worth fixing, not folded in here:
scripts/build-dashboard.sh:13-19silently writes athrowing stub
rgctl_wasm.jswhenwasm-packis absent, andnpm run buildthen bundles it happily —so a contributor without
wasm-packcan replace the real ~190 KB engine with a stub that throws atruntime, and commit the result. It should fail loudly, or refuse to overwrite an existing real engine.
Happy to open that separately.
Two defects found in the same audit are not fixed here, deliberately:
bar treats lenses (CFG, Dataflow, Slice, Blast) as destinations, which is an information-architecture
problem. Patching the wrap would entrench it.
<link rel="icon">and no icon indist/).