mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-08-28 05:25:25 +00:00
* feat(graph-view): add tree and circles layout modes
Add alternate graph layouts to the web viewer with new graph view state, canvas controls, adapters, and Sigma layout logic for tree and concentric-circle rendering. Include layout and adapter tests plus tree-view E2E coverage aligned with the English UI labels, and tune node visibility, edge layering, large-graph behavior, and tree-layer spacing so the new views stay readable. Follow up the tree-view work by keeping noisy variables hidden by default and mapping Property/Const icons so filter coverage stays in sync with the expanded node taxonomy.
Co-authored-by: OpenAI Codex <noreply@openai.com>
AI-model: GPT-5 Codex
* fix(web): cap tree layout spring iterations and remove unused variable
Finding A (blocker): calculateTreeLayout runs 14 synchronous spring
iterations over all edges and nodes — O(N×E×14) + O(N log N) per layer
per iteration — with no size guard. At 10K+ nodes this freezes the
main thread for several seconds.
Fix: make SPRING_ITERATIONS adaptive:
- N > 10 000 → 0 iterations (proportional initial layout only)
- N > 3 000 → 4 iterations
- otherwise → 14 iterations (unchanged behaviour for small graphs)
Also removes the unused `const r` at useSigma.ts:1314, which was a
leftover after the radial-resistance decomposition was removed.
This clears the CodeQL "unused variable" warning (Finding G).
Co-authored-by: Claude <noreply@anthropic.com>
AI-model: claude-sonnet-4-6
* test(graph-adapter): add circles adapter tests and tree layout perf bound
Finding B (high): knowledgeGraphToCirclesGraphology had zero test
coverage. Adds three new tests:
- ring placement: verifies Folder→ring 0, File→ring 1, Function→ring 3
and confirms circles-specific attributes (circlesRing, circlesAnchorX/Y)
are set while tree attributes (treeAnchorX/Y) are absent.
- edge styling: CONTAINS is marked isHierarchyEdge=true with the
hierarchy colour; CALLS is cross-cutting with its own colour.
- CALLS cross-cutting: a lone CALLS edge between two Functions is
correctly identified as a non-hierarchy edge.
Also adds a performance-bound test for the tree adapter at 2 000 nodes /
4 000 edges (the adaptive 14-iteration path) asserting completion within
2 s — catches regressions to the O(N×E×iterations) main-thread blocking
that Finding A identified.
Co-authored-by: Claude <noreply@anthropic.com>
AI-model: claude-sonnet-4-6
* refactor(web): rename Tree View → Sequential Layout, Circles → Radial Layout
Aligns the UI labels with standard graph layout terminology from the
Cambridge Intelligence taxonomy (cambridge-intelligence.com/blog/automatic-graph-layouts):
Tree View → Sequential Layout (顺序布局)
Circles → Radial Layout (径向布局)
Force Graph → Force Graph (unchanged)
Internal graphViewMode keys ('tree', 'circles', 'force') are unchanged —
only the displayed strings in en/zh-CN locales and the E2E button selectors
are updated.
Co-authored-by: Claude <noreply@anthropic.com>
AI-model: claude-sonnet-4-6
* perf(web): add adaptive large-graph guards to sequential layout physics
For graphs with N > 5 000 nodes, each rAF frame of runTreeLayout was
doing O(N log N) sort + O(N × k) repulsion pair comparisons (k ≈ 2 400
for a 20 K-node graph spread across 1 080 px at range 130). At that
scale each frame took hundreds of ms, making the canvas appear completely
frozen even though the physics loop was still running.
Fix mirrors the circles layout adaptive strategy:
N > 5 000 (large):
- Skip repulsion pass (O(N × k) → 0)
- Skip spread-force sort (O(N log N) → 0)
- Velocity cap raised to ±12 / ±6 px so nodes cover ground faster
- Damping 0.58, 1 sim step/frame, 30 s max duration
- Looser early-stop thresholds (max v 0.05, avg v 0.03, active 2 %)
N > 1 500 (medium):
- Velocity cap raised to ±6 / ±3 px
- 24 s max duration
- Repulsion and spread still active
N ≤ 1 500 (small):
- Unchanged behaviour (velocity ±3/±2, 18 s, all forces active)
Layer gravity (O(N)) and edge springs (O(E)) run for all graph sizes —
they provide the structural pull that replaces repulsion at large N.
Co-authored-by: Claude <noreply@anthropic.com>
AI-model: claude-sonnet-4-6
* fix(web): fix stale closure in sigma event handlers breaking node selection
The sigma 'clickNode', 'clickStage', 'enterNode', and 'leaveNode' handlers
are registered in a one-time useEffect (empty dep array). They captured
options.onNodeClick via closure, so they always called the initial version
of handleNodeClick — the one created before the graph loaded where
`if (!graph) return` exits immediately.
Consequence: clicking a node in the canvas never updated the app-level
selectedNode state. This broke:
- The Focus Depth filter (warning "Select a node to apply depth filter"
persisted even after a canvas click)
- The depth hop filter not applying (selectedNode was always null)
- The code panel not opening on canvas node click
Fix: store the three callback props in refs (onNodeClickRef, onNodeHoverRef,
onStageClickRef) and update them synchronously on every render. The sigma
event handlers now read from the refs, so they always invoke the latest
version of the callbacks without needing to re-register.
Co-authored-by: Claude <noreply@anthropic.com>
AI-model: claude-sonnet-4-6
* fix(web): address three code-review bugs in graph rendering
Bug 1 (useSigma.ts): forces in the tree physics loop were computed once
before the sub-steps loop and reused for every step, causing 2× displacement
on slow frames (>64ms, simulationSteps>1). Fix: move forceX/forceY Maps and
all force accumulation (layer gravity, edge springs, repulsion, spread) inside
the loop so each sub-step integrates from current node positions.
Bug 2 (graph-adapter.ts): all three adapters used `graph.hasEdge(src,tgt)`
as a dedup guard, which silently drops any second edge between the same node
pair. A CALLS relationship between nodes that also have a CONTAINS edge was
always lost. Fix: switch from `new Graph()` to `new MultiGraph()` (allows
multiple edges per pair) and dedup by `rel.id` instead of by node pair.
Bug 3 (graph-adapter.test.ts): the cross-cutting edge styling test never
executed its CALLS branch because Bug 2 dropped the CALLS edge before the
assertion ran. Fix: assert `sigmaGraph.size === 2` and verify both edges
individually after collecting attrs by relationType.
Co-authored-by: Claude <noreply@anthropic.com>
AI-model: claude-sonnet-4-5
* fix(web): address three code-review bugs in graph rendering
- Move radial layout force accumulation inside the sub-step loop so
forces are recomputed from updated node positions each iteration
instead of using stale forces computed before the loop began
- Revert knowledgeGraphToGraphology from MultiGraph back to Graph with
node-pair deduplication to prevent ForceAtlas2 from double-applying
spring forces for node pairs that share multiple relation types
- Add Target to the lucide-icons import in FileTreePanel.tsx so the
Const node type icon resolves without a ReferenceError
Co-authored-by: Claude <noreply@anthropic.com>
AI-model: claude-sonnet-4-6
* fix(web): address four more PR review comments
Edge visibility (useSigma.ts): HAS_METHOD / HAS_PROPERTY edges were hidden
when any edge-type filter was active because those types are not in the EdgeType
union. Normalize HAS_METHOD → DEFINES and HAS_PROPERTY → CONTAINS before the
visibleTypes.includes() guard so Kotlin/Java hierarchy edges follow the same
filter logic as their semantic equivalents.
Force-mode edge styles (graph-adapter.ts): HAS_METHOD / HAS_PROPERTY fell back
to the default gray color in the force-graph adapter because EDGE_STYLES had no
entries for them. Added explicit entries using the same hues as DEFINES/CONTAINS
so force mode renders Kotlin/Java hierarchy edges consistently with tree/circles.
Accessibility (GraphCanvas.tsx, locales): the layout-mode switcher (Force /
Tree / Circles) had no ARIA semantics. Added role="tablist" on the container
and role="tab" + aria-selected on each button. Added the viewModes.label i18n
key (used as aria-label on the tablist) to en and zh-CN locale files.
Flaky test (graph-adapter.test.ts): replaced the hard 2 s wall-clock assertion
with a structural check (node count + edge count) that is deterministic across
CI hardware. Timing tests are inherently flaky and provide no correctness signal.
Co-authored-by: Claude <noreply@anthropic.com>
AI-model: claude-sonnet-4-5
---------
Co-authored-by: OpenAI Codex <noreply@openai.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
|
||
|---|---|---|
| .. | ||
| e2e | ||
| src | ||
| test | ||
| .gitignore | ||
| index.html | ||
| package-lock.json | ||
| package.json | ||
| playwright.config.ts | ||
| tsconfig.app.json | ||
| tsconfig.json | ||
| tsconfig.node.json | ||
| vercel.json | ||
| vite.config.ts | ||
| vitest.config.ts | ||