Skip to content

feat(graph-ui): dead-code filtering, node code preview & GitHub deep-links#789

Open
brishtiteveja wants to merge 4 commits into
DeusData:mainfrom
brishtiteveja:feat/graph-dead-code-filter
Open

feat(graph-ui): dead-code filtering, node code preview & GitHub deep-links#789
brishtiteveja wants to merge 4 commits into
DeusData:mainfrom
brishtiteveja:feat/graph-dead-code-filter

Conversation

@brishtiteveja

Copy link
Copy Markdown

Summary

Adds dead-code discovery and code navigation to the graph UI, plus a couple of sidebar fixes and a build fix.

Dead-code filtering + status coloring

  • layout3d classifies each node and emits status (dead | single | entry | test | exported | normal | structural) and in_calls.
  • Dead = Function/Method with zero incoming CALLS and zero USAGE that is not an entry point, route, test, or exported symbol.
  • Caller counts come from the full graph via cbm_store_batch_count_degrees (not the sampled render edges, which would falsely mark sampled-in functions as uncalled), batched in chunks of 500 to stay within the store's bound-IN-clause capacity.
  • FilterPanel gains a Dead code section: color-by-status, show-only-dead, hide-entry-points, hide-tests, and a live dead count. GraphTab recolors nodes by status when enabled.

Node code preview + GitHub deep-links

  • layout3d emits qualified_name, start_line, end_line per node.
  • New GET /api/repo-info?project= returns the indexed repo's git remote normalized to a web base + blob_base (https://host/org/repo/blob/<branch>), read via libgit2. Handles scp-style (git@host:org/repo.git), ssh://, and https:// remotes.
  • Hover tooltip enriched with file:lines, dead-code status, and caller count.
  • Node detail panel: Show code (fetches the snippet via the existing /rpc get_code_snippet tool) and Open on GitHub deep-link to the exact lines.

Sidebar fixes

  • Search is now a case-insensitive regex (matches name / file_path / qualified_name), falling back to literal substring on invalid regex, with an inline hint. Result cap raised 50 → 500.
  • Whole left sidebar scrolls as one region; the tree no longer nests its own scroll so the (now taller) filter panel can't clip the search/tree.

Fixes

  • restore 50k node render limit — the prior 2000-node cap collapsed stellar degree-coloring to uniform red and dropped nearly all edges. Restored to 50000 (tunable via CBM_UI_MAX_RENDER_NODES), which also makes dead-code classification meaningful.
  • include git2/sys/alloc.h for git_allocator — the git2.h umbrella header does not pull in sys/ headers, breaking the build under libgit2 1.9.

Verification

Built cbm-with-ui clean. Verified over /api/* on a 78k-node project: in_calls matches graph ground truth exactly, repo-info yields the correct GitHub base, layout nodes carry qn+lines, and get_code_snippet returns real source for a node's qualified_name.

azehady added 4 commits July 1, 2026 10:45
The git2.h umbrella header does not pull in the sys/ headers, so
git_allocator (used to bind libgit2 to mimalloc) was an unknown type
under libgit2 1.9. Include git2/sys/alloc.h explicitly.
Classify each node in the layout and surface it in the graph UI so
dead code is visible and filterable.

Backend (layout3d.c):
- Parse per-node flags (is_entry_point/is_test/is_exported/route_path)
  from properties_json and compute a `status`:
  dead | single | entry | test | exported | normal | structural.
- Dead = Function/Method with zero incoming CALLS and zero USAGE that
  is not an entry point, route, test, or exported symbol.
- Caller counts come from the full graph via cbm_store_batch_count_degrees,
  NOT the sampled render edges (which drop edges to off-screen nodes and
  would falsely mark sampled-in functions as uncalled). Batched in chunks
  of 500 to stay within the store's bound-IN-clause capacity.
- Emit `status` and `in_calls` in the layout JSON.

Frontend:
- GraphNode gains status/in_calls; colors.ts adds a status palette + legend.
- FilterPanel: "Dead code" section — color-by-status toggle, show-only-dead,
  hide-entry-points, hide-tests, and a live dead count.
- GraphTab wires the filters and recolors nodes by status when enabled.

Note: filters act on the rendered node sample (name-ordered, default 2000,
cap via CBM_UI_MAX_RENDER_NODES) like all existing filters.

Also gitignore the generated src/ui/embedded_assets.c build artifact.
Commit d9d7065 capped the graph render limit to 2000 nodes (hard max
10000). At that size almost every node has degree 0-1, so the stellar
degree-coloring collapses to uniform red and nearly all edges are dropped
(both endpoints must be in-sample), losing the connected overview.

Restore the pre-cap limit: DEFAULT_MAX_NODES and HARD_MAX_NODES back to
50000 and the frontend GRAPH_RENDER_NODE_LIMIT to 50000. On samay this
brings back the full 50,000-node / 120,755-edge view with varied stellar
colors, and makes the dead-code classification meaningful (913 dead vs 0
in the tiny sample). Tune down at runtime via CBM_UI_MAX_RENDER_NODES.
… regex search

Hovering/clicking a node now surfaces its code and location.

Backend:
- layout3d emits qualified_name, start_line, end_line per node.
- New GET /api/repo-info?project= returns the indexed repo's git remote
  normalized to a web base + blob_base (https://host/org/repo/blob/<branch>),
  read via libgit2. Handles scp-style (git@host:org/repo.git), ssh:// and
  https:// remotes; empty fields when there is no remote.

Frontend:
- Hover tooltip enriched: file:lines, dead-code status + caller count.
- NodeDetailPanel: file:line range, "Show code" (fetches the snippet via the
  existing /rpc get_code_snippet tool and renders it), and "Open on GitHub"
  deep-link to the exact lines. Code resets when the selected node changes.
- GraphTab fetches repo-info per project and passes it + project to the panel.

Sidebar fixes (reported):
- Search is now a case-insensitive regex (matches name, file_path,
  qualified_name), falling back to literal substring on invalid regex, with an
  inline hint. Result cap raised 50 -> 500 with a "refine the search" notice.
- Whole left sidebar scrolls as one region (overflow-y-auto); Sidebar gains an
  `inline` mode so the tree no longer nests its own scroll and the tall filter
  panel can't clip the search/tree.
@brishtiteveja brishtiteveja requested a review from DeusData as a code owner July 2, 2026 22:18
@phpmac

phpmac commented Jul 3, 2026

Copy link
Copy Markdown

v12 pls audit

@DeusData DeusData added enhancement New feature or request ux/behavior Display bugs, docs, adoption UX priority/normal Standard review queue; useful PR with ordinary maintainer urgency. labels Jul 3, 2026
@DeusData

DeusData commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Thanks for the graph UI work. Triage: graph UI/UX enhancement, but this is larger than a pure frontend change because it also touches UI server/layout code and .gitignore.

Review will focus on bounded file/code preview behavior, dead-code classification against full graph degrees, path/link generation, and making sure the UI changes do not introduce unbounded reads or confusing external-link behavior. Please keep the scope tight around graph UI discovery/navigation.

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

Labels

enhancement New feature or request priority/normal Standard review queue; useful PR with ordinary maintainer urgency. ux/behavior Display bugs, docs, adoption UX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants