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
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