GitNexus/ARCHITECTURE.md
Gergő Magyar 5a7c0fdbb1
feat: same-arity overload disambiguation via type-hash suffix (#651) (#658)
* feat: same-arity overload disambiguation via type-hash suffix (#651)

Add ~type1,type2 suffix to Method/Constructor node IDs when same-arity
overloads with different parameter types exist in the same class. Also add
$const suffix for C++ const-qualified method overloads via new isConst field.

Key changes:
- typeTagForId() detects same-arity collisions and appends ~typeTag
- constTagForId() detects const/non-const collisions and appends $const
- TS/JS excluded from type-hashing (overload signatures collapse to impl body)
- Sequential findEnclosingFunction fixed: falls through on ambiguous same-class
  candidates instead of picking first; fallback path includes typeTag + constTag
- Per-call-site integration tests across Java, C#, Kotlin, C++, TypeScript
- Cross-file + chain resolution tests for all 5 languages
- C++ isConst extraction via tree-sitter type_qualifier in function_declarator

1710 integration + 18 unit tests pass.

* fix: preserve generic/template args in type-hash, perf + type safety fixes

- Add rawType field to ParameterInfo preserving full type text (vector<int>)
  while type stays simplified (vector). typeTagForId uses rawType for tags.
- Populate rawType in all 11 language method extractors
- Add buildCollisionGroups() to pre-group methods by name#arity (O(N) once
  per class instead of O(N) per method call)
- Cache method extraction in call-processor findEnclosingFunction fallback
- Fix null guards on getLanguageFromFilename in all findEnclosing paths
- Tighten SKIP_TYPE_HASH_LANGUAGES to ReadonlySet<SupportedLanguages>
- Document ID stability invariant on first overload introduction
- C++ integration tests: template overloads (vector<int> vs vector<string>),
  cross-file template + chain resolution, out-of-class method definitions

1718 integration + 20 unit tests pass.

* fix: add rawType to method-extraction unit test assertions

All 26 parameter .toEqual() assertions in method-extraction.test.ts
needed the new rawType field added to match ParameterInfo schema change.

* perf: cache tempMap/groups per class, consolidate extractFromNode

- Cache derived method map + collision groups per classNode.id in
  parsing-processor (avoids rebuild per method in same class)
- Replace per-call extractFromNode with cached class extraction +
  funcName:line lookup in call-processor fallback (avoids AST walk
  per call site)
- Remove dead clearEnclosingFunctionCache export, fix JSDoc

* test: add sequential-path integration test for same-arity overloads

Add skipWorkers option to PipelineOptions to force sequential parsing.
New test suite verifies type-hash disambiguation produces identical
results through the sequential path (parsing-processor + call-processor
findEnclosingFunction) as the worker path.
2026-04-05 21:51:55 +01:00

7.6 KiB

Architecture — GitNexus

This repository is a monorepo with two main products: the CLI / MCP package (gitnexus/) and the browser UI (gitnexus-web/). Supporting folders ship editor integrations and plugins without changing the core graph engine.

Repository layout

Path Role
gitnexus/ Published npm package gitnexus: CLI, MCP server (stdio), local HTTP API for bridge mode, ingestion pipeline, LadybugDB graph, embeddings (optional).
gitnexus-web/ Vite + React UI: in-browser indexing (WASM), graph visualization, optional connection to gitnexus serve.
.claude/, gitnexus-claude-plugin/, gitnexus-cursor-integration/ Packaged skills and plugin metadata so agents discover the same workflows as documented in AGENTS.md.
eval/ Evaluation harnesses and docs for benchmarking tool usage.
.github/ CI workflows (quality, unit, integration, E2E) and composite actions.

End-to-end flow: index → graph → tools

  1. Ingestion (gitnexus analyze)

    • Entry: gitnexus/src/cli/analyze.tsrunPipelineFromRepo in gitnexus/src/core/ingestion/pipeline.ts.
    • Walks the git working tree, parses supported languages via Tree-sitter, resolves imports/calls/inheritance, detects communities and processes (execution flows), and builds an in-memory knowledge graph (gitnexus/src/core/graph/).
    • Output is loaded into LadybugDB under .gitnexus/ at the repo root (lbug/, meta.json, etc.). Optional FTS indexes and embeddings attach to the same store.
    • The repo is registered in ~/.gitnexus/registry.json so MCP can find it from any working directory.
  2. Persistence & metadata

    • gitnexus/src/storage/repo-manager.ts — paths, registry, cleanup of legacy Kuzu artifacts.
    • gitnexus/src/core/lbug/lbug-adapter.ts — graph load, queries, embedding restore batches.
  3. Query & agents

    • MCP (stdio): gitnexus/src/cli/mcp.tsstartMCPServerLocalBackend (gitnexus/src/mcp/local/local-backend.ts) opens registered repos and serves tools from gitnexus/src/mcp/tools.ts and resources from gitnexus/src/mcp/resources.ts.
    • Bridge HTTP: gitnexus/src/cli/serve.ts → Express app in gitnexus/src/server/api.ts (CORS-limited) exposes REST + MCP-over-HTTP for the web UI.
    • CLI tools (no MCP): gitnexus query, context, impact, cypher in gitnexus/src/cli/tool.ts call the same backend for scripts and CI.
  4. Staleness

    • gitnexus/src/mcp/staleness.ts compares indexed lastCommit to HEAD and surfaces hints when the graph is behind git.

MCP tools (summary)

Tool Purpose
list_repos Discover indexed repositories when more than one is registered.
query Natural-language / keyword search over the graph (hybrid BM25 + optional vectors).
cypher Ad hoc Cypher against the schema (see resource gitnexus://repo/{name}/schema).
context Callers, callees, processes for one symbol (with disambiguation).
impact Blast radius (upstream/downstream) with depth and risk summary.
detect_changes Map git diffs to affected symbols and processes.
rename Graph-assisted rename with dry_run preview (graph vs text_search confidence).

Where to change what

If you are changing… Start in…
CLI commands / flags gitnexus/src/cli/ (index.ts, per-command modules).
Parsing or graph construction gitnexus/src/core/ingestion/ (pipeline, processors, resolvers, type-extractors).
Graph schema / DB access gitnexus/src/core/lbug/ (schema.ts, lbug-adapter.ts), gitnexus/src/mcp/core/lbug-adapter.ts if MCP-specific.
MCP protocol, tools, resources gitnexus/src/mcp/server.ts, tools.ts, resources.ts.
Search ranking gitnexus/src/core/search/ (BM25, hybrid fusion).
Embeddings gitnexus/src/core/embeddings/, phases in analyze.ts.
Wiki generation gitnexus/src/core/wiki/.
Web UI behavior gitnexus-web/src/ (components, workers, graph client).
CI .github/workflows/*.yml, .github/actions/setup-gitnexus/.

Known limitations

Overloaded method resolution

Method and Constructor node IDs include an arity suffix (#<paramCount>) to disambiguate overloaded methods. Two overloads with different parameter counts produce distinct graph nodes: Method:file:Class.method#1 vs Method:file:Class.method#2.

Same-arity overload disambiguation: When two overloads share the same parameter count but differ in types (e.g. save(int) vs save(String)), a type-hash suffix ~type1,type2 is appended to produce distinct node IDs: Method:file:Class.save#1~int vs Method:file:Class.save#1~String. The suffix is only added when a same-arity collision is detected within a class and all parameters have non-null type annotations. Languages without type info (Python, Ruby, JS) fall back to arity-only IDs. TypeScript/JavaScript overload signatures are intentionally excluded from type-hashing because they are declaration-only contracts that should collapse to the implementation body's node ID. See issue #651.

C++ const-qualified overload disambiguation: Methods overloaded by const qualification (e.g. begin() vs begin() const) are disambiguated via an isConst property and a $const ID suffix appended to the const-qualified variant when a non-const collision exists. The $const suffix appears after the type-hash suffix: e.g. Method:file:Container.begin#0$const.

Generic/template type preservation in type-hash: The type-hash suffix uses rawType (full AST text including generic/template args) rather than the simplified type from extractSimpleTypeName. This means C++ template overloads like process(vector<int>) vs process(vector<string>) produce distinct IDs: ~vector<int> vs ~vector<std::string>. Java generic overloads like process(List<String>) vs process(List<Integer>) are a compile error due to type erasure, so this gap is theoretical for Java.

ID stability on first overload: Type and const tags are collision-only. When a class has save(int) as its only save method, the ID is save#1 (no tag). Adding save(String) changes the original to save#1~int. This is correct for fresh analysis but means IDs are not stable across overload additions. Future incremental re-analysis should account for this.

Variadic method matching: When one side is variadic (parameterCount undefined) and the other has a fixed count, METHOD_IMPLEMENTS edges are emitted with confidence 0.7 instead of 1.0. Variadic methods like foo(String... args) may superficially match foo(String s) by type but are not guaranteed to be interchangeable across all languages (Java/Kotlin accept this via varargs sugar; TypeScript, C#, Rust do not).

Confidence tiering for METHOD_IMPLEMENTS edges:

Match quality Confidence When
Exact parameter types match 1.0 Both sides have parameterTypes arrays and they match
Arity (count) matches 1.0 Both sides have parameterCount, types unavailable
Variadic vs fixed 0.7 One side is variadic, other has fixed count
Lenient (insufficient info) 0.7 One or both sides lack type and count data
  • MIGRATION.md — breaking changes and migration guidance.
  • RUNBOOK.md — operational commands and recovery.
  • GUARDRAILS.md — safety boundaries for humans and agents.
  • TESTING.md — how to run tests.
  • AGENTS.md / CLAUDE.md — agent workflows and tool usage expectations for this repo when indexed by GitNexus.