Commit Graph
9 Commits
Author SHA1 Message Date
Zadak 4efa22cd95 fix(graph-ui): navigate Windows drive breadcrumbs to real paths
The index file picker built breadcrumb targets as '/' + segments, so on a Windows drive path (C:/Users/rap) clicking a crumb browsed to '/C:/...', which the backend rejected as 'not a directory'. Only the '.. (up)' button worked.

Build drive-aware crumb targets (C:/, C:/Users) and drop the bogus unified '/' root crumb on Windows drive paths; POSIX behavior is unchanged. Add a regression test for Windows breadcrumb navigation and cleanup() for test isolation.

Signed-off-by: Zadak <rarepops@protonmail.com>
2026-07-04 09:39:28 +02:00
Martin Vogelandsahil-mangla cfc73f8d0b fix(graph-ui): surface indexing-job failures instead of silently completing
The backend /api/index-status reports status:"error" plus an error
message for failed indexing jobs, but IndexProgress treated any
non-"indexing" state as successful completion: the spinner vanished
with no feedback (e.g. after an OOM-killed indexer subprocess), the
project never appeared, and no error was shown.

Render a visible error banner (path + error text) with a Dismiss
button instead, and keep the success flow unchanged. Beyond the
original PR:

- Restore the empty-jobs guard the PR dropped: the backend keeps
  finished jobs listed as "done"/"error" (handle_index_status only
  skips idle slots), so an empty list mid-index only occurs on
  transient state loss and must not be treated as completion.
- Route the new user-facing strings through the i18n system
  (projects.indexingFailed, common.dismiss; EN + zh entries).
- Cover error banner + dismiss, success flow and the empty-jobs
  guard with vitest cases on the now-exported IndexProgress.

Distilled from #549.

Refs #524

Co-authored-by: sahil-mangla <manglasahil2017@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-07-03 20:28:27 +02:00
Zadak a0e970d78d fix(graph-ui): keep filter sidebar visible when all nodes are filtered out
Clicking "None" (disable all filters) clears every label and edge type,
making filteredData.nodes empty. The early return then replaced the whole
layout — including the left filter sidebar — with a centered "All nodes
filtered out / Reset Filters" message, leaving no way to re-enable
individual filters without resetting everything.

Narrow the early return to the genuinely-empty / no-data case and render
the "all filtered out" state inside the graph area instead, so the
FilterPanel and Sidebar stay mounted. As a side effect, a project with
zero nodes now correctly reads "No nodes in this project" rather than
"All nodes filtered out".

Add a regression test that disables all filters via "None" and asserts the
Filters sidebar remains in the document.

Signed-off-by: Zadak <rarepops@protonmail.com>
2026-06-30 21:27:41 +02:00
Martin Vogel d5414111b3 feat(ui): add i18n and index picker UX
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-28 21:21:32 +02:00
Martin Vogel d9d70656b4 fix(ui): cap graph rendering and index spawn
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-06-28 20:57:14 +02:00
Nan 550a2cc65c fix(ui): render graph labels without remote font fetches (#496)
Signed-off-by: Nan <630971265@qq.com>
2026-06-22 22:04:54 +02:00
Martin Vogelandsponger94 7290c1fd2b feat(ui): satellite galaxy radius spacing + cross-galaxy edge rendering
Two visualization gaps in the cross-repo graph view:

1. Fixed LAYOUT_GALAXY_SPACING=600 buried satellite galaxies inside the
   primary cluster on any non-trivial project — a 1000-node primary
   cluster has bounding radius ~1500. Added layout_radius() (max distance
   from origin across all node positions) and compute the per-satellite
   distance as primary_radius + sat_radius + LAYOUT_GALAXY_PAD, with the
   old constant retained as a lower bound for tiny projects.

2. cross_edges was hard-coded to an empty array (TODO placeholder), so
   inter-galaxy CROSS_* edges never rendered even when the matcher had
   produced them. Populate from a join on the source store's CROSS_*
   edges → Route node qualified_name, then resolve the canonical QN in
   the linked store to get its node id. The Route QN is the cross-repo
   matching contract; properties.target_function isn't unique.

Required keeping both `store` and `lp_store` open through the linked-
projects loop instead of closing them right after layout compute.
Added cbm_store_close to all early-error paths to balance the lifetime.

Frontend side:
- EdgeLines accepts an optional targetNodes prop so a single component
  can render edges with source in one node array and target in another
  (offset-adjusted satellite nodes).
- GraphScene renders an EdgeLines layer per linked project for its
  cross_edges, using primary nodes as source and offsetNodes as target.
- GraphTab folds linked-project labels and edge types into the filter
  init / enableAll / filteredData paths so cross_edges respect the
  current filter state.
- Edge color palette extended with GRPC/GRAPHQL/TRPC/CROSS_* tones.

Co-authored-by: sponger94 <45746997+sponger94@users.noreply.github.com>
2026-05-10 18:56:30 +02:00
test b6eefe014c Add multi-galaxy UI layout and cross-repo architecture summary
Backend (http_server.c):
- Layout API detects CROSS_* edges and loads linked project graphs
- Each linked project computed at radial offset as satellite galaxy
- Response includes linked_projects with nodes, edges, offset

Frontend:
- LinkedProject type in types.ts
- GraphScene renders satellite galaxies at offset positions
- NodeCloud/EdgeLines accept opacity prop for dimmed rendering

Tool integration (mcp.c):
- get_architecture includes cross_repo_links summary
- Extract append_cross_repo_summary helper for linter compliance
2026-04-15 23:53:42 +02:00
Martin Vogel 18fa9979ee Replace vmem with mimalloc global allocator, add extraction-phase prescan, fix __init__.py QN collision
Memory management:
- Vendor mimalloc v2.1.9 as global allocator (MI_OVERRIDE=1 in prod)
- New mem.h/mem.c: RSS-based budget tracking via mi_process_info()
- Remove vmem.c/vmem.h (mmap-based budget tracking)
- Remove slab tier2 bump allocator (~300 LOC); >64B goes to mimalloc
- Slab tier1 pages from malloc (= mimalloc) instead of vmem
- Arena blocks from malloc instead of vmem
- Budget raised from 35% to 50% RAM (no more untracked C++ heap)

Extraction-phase prescan (eliminates disk re-reads):
- HTTP call sites: keyword check + URL extraction during extraction
- HTTP routes: decorator + source-based extraction during extraction
- Config file refs: regex scan during extraction
- httplinks: 41.8s → 13ms on Linux kernel (3,212x faster)
- configlink: 41.4s → 0.8s on Linux kernel (54x faster)
- Linux kernel fast-mode total: 2m38s → 1m18s

Bug fixes:
- __init__.py Module QN no longer collides with Folder QN
- index.ts same fix for JS/TS packages
- 13 regression tests for QN collision at FQN + extraction layers
- search_graph/search_code default limit raised from 10 to 500k
- Resolve all clang-tidy, cppcheck, and clang-format warnings

Repo cleanup:
- tree-sitter-form, tree-sitter-magma moved to tools/
- .gitignore: build/, node_modules/, graph-ui/dist/, TEST_PLAN.md
2026-03-17 22:05:57 +01:00