Property Value
Type refactor
Status active
Date 2026-04-06
Parent RFC #568
Prerequisite #665 (lookupMethodByOwner — merged)

Vision

Today, GitNexus call resolution works like this: tree-sitter queries produce raw captures, per-language extractors scatter type information across TypeEnv, and resolveCallTarget glues it together with fuzzy name-based lookups and cascading heuristics.

The target architecture inverts this. Language providers feed a language-independent semantic model. All resolution flows through the model, not through name-matching.

CURRENT                                    TARGET
═══════                                    ══════

tree-sitter queries                        Language Providers (languages/)
  → raw captures                             → LanguageProvider interface
    → per-language extractors                  → feed SemanticModel
      → TypeEnv (per-file, discarded)            (symbols, types, ownership, heritage)
        → call-processor.ts                        → SemanticModel drives resolution
          → resolveCallTarget                        (O(1) owner-scoped lookups)
            → lookupFuzzy (global scan)                → knowledge graph
              → heuristic filtering
                → knowledge graph

The language providers already exist (languages/ directory with LanguageProvider interface). The extractors already exist (type-extractors, method-extractors, field-extractors, import-resolvers, named-bindings — all per-language). What's missing is the model they should be feeding and the resolution layer that consumes it.


Problem Frame

The fuzzy lookup tax

lookupFuzzy(name) returns every symbol named name across the entire project. For save in a 5000-file repo, this might return 40 candidates from 40 unrelated classes. The caller then spends 5 stages filtering:

  1. Filter by callable type (Method/Function/Constructor)
  2. Resolve receiver type → get typeFiles and typeNodeIds
  3. Widen to global scope via a second lookupFuzzy (D2)
  4. Filter by file path (D3)
  5. Filter by ownerId (D4)

This is a name → filter → filter → filter pipeline. A semantic model makes it owner + name → direct hit.

The TypeEnv gap

TypeEnv is built per-file, used during call processing, then discarded. It cannot: