Skip to content

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

Merged
DeusData merged 3 commits into
mainfrom
distill/789-deadcode-ui
Jul 4, 2026
Merged

feat(graph-ui): dead-code filtering, node code preview, GitHub deep-links#863
DeusData merged 3 commits into
mainfrom
distill/789-deadcode-ui

Conversation

@DeusData

@DeusData DeusData commented Jul 4, 2026

Copy link
Copy Markdown
Owner

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

Distilled from #789 (safe features only). Original feature authorship: Andy Zehady
azehady@ciroos.ai. This PR takes the reviewable, low-risk parts of that 6-concern
bundle, drops the risky ones, and fixes the issues flagged in review.

Refs #789.

What this adds

Backend — dead-code classification (src/ui/layout3d.c / .h)

  • Parses node props is_entry_point / is_test / is_exported / route_path.
  • Computes the true full-graph incoming CALLS/USAGE degree via
    cbm_store_batch_count_degrees (chunked at 500 ids — the batch IN-clause caps at
    ~2045 placeholders and silently drops the tail beyond that, which would masquerade
    as dead code).
  • Emits status (dead / single / entry / test / exported / normal /
    structural) and in_calls into the layout JSON, plus qualified_name /
    start_line / end_line.
  • Fail-safe: a failed degree query defaults to non-dead, so an error never masquerades
    as dead code.

Backend — GET /api/repo-info (src/ui/http_server.c)

  • Reads the git origin remote via libgit2 and normalizes it (scp / ssh / https) to a
    web_base + blob_base for GitHub deep-links.

Frontend

  • Dead-code filtering UI: status palette + legend and toggles (color-by-status,
    show-only-dead, hide-entry-points, hide-tests). Pairs with the is_test backend
    already on main (fix(extract-rust): mark #[test]/#[tokio::test] fns is_test so they are filtered #857). (FilterPanel.tsx, GraphTab.tsx, lib/colors.ts,
    lib/types.ts)
  • Node code preview: the snippet fetched via the existing /rpc get_code_snippet tool,
    rendered as React-escaped text inside <pre> — never dangerouslySetInnerHTML /
    innerHTML. (NodeDetailPanel.tsx)
  • GitHub deep-links from the detail panel and tooltip, target="_blank" rel="noopener noreferrer". (NodeDetailPanel.tsx, NodeTooltip.tsx)

What was dropped (and why)

  • The render-cap revert (2000 → 50000). Kept main's current
    DEFAULT_MAX_NODES / HARD_MAX_NODES (src/ui/layout3d.c) and
    GRAPH_RENDER_NODE_LIMIT = 2000 (useGraphData.ts). useGraphData.test.ts (which
    asserts 2000) is unchanged and green.
  • The #include <git2/sys/alloc.h> build fix. Already on main via fix(build): gate libgit2 allocator support #829.
  • The sidebar regex-search refactor. Client-side new RegExp(search) per keystroke
    is a ReDoS smell and a separate concern — omitted entirely; Sidebar.tsx is untouched.

Security notes addressed (review fixes)

  • Credential stripping. /api/repo-info never echoes https://user:token@host/…:
    the returned remote_url is credential-stripped (cbm_ui_git_strip_credentials), and
    web_base / blob_base are built cred-free. Guarded by a reproduce-first test.
  • No per-request libgit2 init/shutdown. libgit2 is initialized once at process start
    by cbm_alloc_init (which binds its allocator to mimalloc); re-init/shutdown per HTTP
    request could drop the global refcount and tear that binding down. The handler reuses
    the global state.
  • Outbound-URL gate. The legitimate https:// blob-URL construction is added to
    scripts/security-allowlist.txt (URL:https://%s) so security-static passes; this
    is URL construction, not a network call.
  • Deep-link path encoding. githubUrl() percent-encodes each path segment
    (encodeURI/encodeURIComponent), so an unusual file_path can't break or escape the
    URL. The scheme is already https-forced by the backend.

Tests

  • tests/test_ui.clayout_dead_code_classification: dead / entry / test (flag and
    file-path) / exported / single / normal / structural, and in_calls degree counting;
    asserts the classification survives JSON serialization.
  • tests/test_httpd.crepo_info_web_base_normalizes_to_https and
    repo_info_strips_credentials_from_remote: https normalization across scp/ssh/https and
    credential stripping (incl. an @-in-path negative case).
  • graph-ui vitest — NodeDetailPanel.test.tsx proves the code preview renders a
    <script> payload as literal text (no injected element, no execution) and builds an
    https deep-link with URL-encoded path segments; GraphTab.deadcode.test.tsx covers the
    status filter toggles.

Verification

  • C: make -f Makefile.cbm cbm (-Werror clean), make -f Makefile.cbm lint-ci clean,
    security audit passes (URL gate clears), test-runner ui (17/17) + httpd (40/40) green.
  • Frontend: npx vitest run (20/20, incl. useGraphData at 2000), npx tsc -b clean.

…inks

Distilled from #789 (safe features only). Adds backend dead-code classification
(status + in_calls in the layout JSON), a GET /api/repo-info endpoint for GitHub
deep-links, and the frontend dead-code filters, node code preview, and deep-links.

The render-cap revert was dropped (kept 2000 for DEFAULT_MAX_NODES/HARD_MAX_NODES
and GRAPH_RENDER_NODE_LIMIT); the sidebar regex-search refactor was omitted.

Security fixes over the original: repo-info strips credentials from any returned
remote_url; the legitimate https blob-URL construction is allow-listed so the
static gate passes; libgit2 is not re-initialized/shutdown per request (reuses the
process-wide init from cbm_alloc_init); deep-link path segments are URL-encoded.

Co-authored-by: Andy Zehady <azehady@ciroos.ai>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData DeusData enabled auto-merge July 4, 2026 20:22
DeusData added 2 commits July 4, 2026 22:45
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>

# Conflicts:
#	graph-ui/src/components/FilterPanel.tsx
…tures (UI security audit)

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData DeusData merged commit b0b7d51 into main Jul 4, 2026
16 checks passed
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.

1 participant