Skip to content

feat(shared): resolveTypeRef strict type resolver (#916, RFC #909 Ring 2 SHARED)#959

Merged
magyargergo merged 1 commit into
mainfrom
rfc/scope-resolution/916-resolve-type-ref
Apr 18, 2026
Merged

feat(shared): resolveTypeRef strict type resolver (#916, RFC #909 Ring 2 SHARED)#959
magyargergo merged 1 commit into
mainfrom
rfc/scope-resolution/916-resolve-type-ref

Conversation

@magyargergo

Copy link
Copy Markdown
Collaborator

Closes #916. Stacked on #913 (rfc/scope-resolution/913-indexes) — rebase to main once #958 merges.

Scope

Implements RFC §4.6 (resolveTypeRef): a strict, single-return type-reference resolver. Narrower contract than Registry.lookup — no name-only global fallback, no confidence ranking, no arity.

  • gitnexus-shared/src/scope-resolution/resolve-type-ref.ts
  • gitnexus/test/unit/scope-resolution/resolve-type-ref.test.ts (22 tests)

Algorithm

  1. Scope-chain walk from ref.declaredAtScope via scope.parent:
    • Return the first binding of rawName whose origin ∈ {local, import, namespace, reexport} AND whose def.type is a type-kind (class-like / interface-like / enum-like / alias-like).
    • If bindings exist at a scope but none qualify (non-type shadow, wildcard-only origin) → return null immediately. No fallthrough to the global qname index.
  2. Dotted fallback via QualifiedNameIndex.byQualifiedName — only when rawName.includes('.') and the scope walk produced nothing. Accepts a unique type-kind hit; ambiguous → null.

Design notes

Dependency note

Issue #916 lists Depends on: #910 #911 #912. Practical deps: #910 (types), #911 (hooks — none used here, but part of the Ring 1 surface), #913 (DefIndex/QualifiedNameIndex for the dotted fallback). The issue's dependency on #912 is aspirational — we only need the minimal ScopeLookup interface, which lives in this PR.

Tests (22, all passing)

  • Scope-chain walk: local hit · parent walk (return-annotation) · inner shadows outer
  • Import origins: plain named · aliased (import { X as Y }) · namespace returns null (not a type kind) · re-export · wildcard ignored · strict origin wins over non-strict at same scope
  • Shadowing: local var shadows outer import · same-scope Method → null · shadow prevents qname fallthrough
  • Dotted fallback: unique qname hit · fallback only for dotted names · ambiguous qname → null · filters non-type hits · no type hits → null
  • Robustness: missing type → null · unknown declaredAtScope → null · broken parent chain → null · cycle guard · all 7 TypeRef.source values uniformly

Verification

  • tsc --noEmit clean (both gitnexus-shared and gitnexus)
  • gitnexus-shared build clean
  • 22/22 new tests pass
  • Combined scope-resolution / model / shadow suite: 151/151 pass

Part of

@vercel

vercel Bot commented Apr 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
gitnexus Ready Ready Preview, Comment Apr 18, 2026 3:03pm

Request Review

Base automatically changed from rfc/scope-resolution/913-indexes to main April 18, 2026 14:59
… RFC #909 Ring 2 SHARED)

Implements RFC §4.6: a strict, pure resolver for `TypeRef`s used by
`Registry.lookup` Step 2 (type-binding propagation) and by any caller that
wants the single best type-target for an annotation without paying for the
full evidence pipeline.

Algorithm (strict):

  1. Walk the scope chain from `ref.declaredAtScope`:
     - Return the first binding for `rawName` whose origin is in
       `{'local','import','namespace','reexport'}` AND whose `def.type` is a
       type-kind (class-like, interface-like, enum-like, alias-like).
     - If bindings exist but none qualify (non-type shadow, wildcard-only
       origin), return null immediately — do NOT fall through to the global
       qualified-name index.
  2. If `rawName` is dotted and the scope walk produced no match, consult
     `QualifiedNameIndex.byQualifiedName`. Only accept a UNIQUE type-kind
     hit; ambiguous or non-type results return null.

`'wildcard'` is deliberately excluded from strict origins — a
wildcard-expanded name is too loose to anchor type resolution.

Module placement: `gitnexus-shared/src/scope-resolution/resolve-type-ref.ts`
(alongside sibling indexes) rather than the issue's suggested
`gitnexus-shared/src/resolve-type-ref.ts`, for consistency with the rest of
the RFC §2/§3 surface.

A minimal `ScopeLookup` interface is declared inline so #916 ships
standalone; #912's `ScopeTree` will satisfy this contract without change.

Closes part of #909.
@magyargergo

Copy link
Copy Markdown
Collaborator Author

@claude Act as a senior reviewer for GitNexus. Your job is to determine whether this PR is production-ready for this repo, not to give a generic code review.

You are reviewing a PR in the GitNexus monorepo:

  • gitnexus/ → CLI + MCP
  • gitnexus-web/
  • gitnexus-shared/

Your task has 2 phases, in this exact order:

PHASE 1 — DEFINE THE BAR
Before reviewing the diff, establish a concise repo-specific definition of “production-ready” for GitNexus, based only on the repo docs and the affected area.
Keep this definition practical and reviewable. Do not invent standards that are not grounded in the repo.

PHASE 2 — REVIEW THE PR AGAINST THAT BAR
Review the actual diff only after defining the bar.
Stay tightly scoped to the changed code and its direct consequences.


CONTEXT TO LOAD FIRST
Read these before reviewing:

  • AGENTS.md
  • GUARDRAILS.md
  • CONTRIBUTING.md
  • TESTING.md
  • ARCHITECTURE.md

Additional context:


PRIMARY OBJECTIVE
Decide whether this PR is safe, correct, maintainable, and operationally acceptable to merge into production for GitNexus.

Do not optimize for completeness at the expense of signal.
Do not pad the review.
Do not propose unrelated refactors.
Do not restate the PR description unless needed for verification.


REVIEW RULES

  • Every finding must be grounded in specific evidence from the diff or directly relevant surrounding code.
  • Every finding must include path:line.
  • If you make a behavioral claim, cite the code that proves it.
  • If you make a performance claim, explain the mechanism.
  • If something cannot be verified from the diff alone, explicitly say so.
  • Distinguish clearly between:
    • verified issue
    • plausible risk
    • unverified concern
  • Avoid vague wording like “might be better” or “could be improved” unless you explain exactly why.
  • Keep the review focused on this PR’s scope only.

For each finding, assign one severity:

  • BLOCKING → must be fixed before merge
  • NON-BLOCKING → valid issue, but merge may still be acceptable
  • NIT → stylistic/minor, not merge-relevant

REPO-SPECIFIC REVIEW CHECKLIST
Use these exact headings.

1. Correctness & functional completeness

Check:

  • Does the implementation actually satisfy the PR claim?
    • ManifestExtractor is truly invoked
    • config.links produces non-zero cross-links where expected
  • Resolver contracts are preserved:
    • resolveSymbol remains exact-match
    • label-scoped Cypher remains correct per contract type
    • flag any regression toward fuzzy or unscoped matching
  • Graph schema integrity is preserved:
    • no silent changes to node labels
    • no silent changes to edge types
    • no silent changes to ID generation (generateId)
  • Call out any missing wiring, partial integration, dead branch, or mismatch between tests and runtime behavior

2. Code clarity & clean code

Check:

  • naming quality
  • local cohesion
  • dead code
  • unnecessary abstraction
  • hidden control flow
  • confusing indirection
  • adherence to repo conventions:
    • direct imports from gitnexus-shared
    • no barrel re-export regressions
    • no // removed comments
    • no unused re-exports
  • no drive-by refactors outside stated scope per CONTRIBUTING.md and GUARDRAILS.md § Scope

3. Test coverage & change safety

Evaluate against TESTING.md:

  • Are there unit tests under gitnexus/test/unit/ covering the newly wired path?
  • Is there a regression guard for 0-link → N-link behavior?
  • Are assertions meaningful rather than tautological?
  • Are fixtures realistic for manifest inputs?
  • If memoization/cache was introduced, is there a test proving hit/miss behavior and correctness?
  • Is there evidence the expected validation path would pass for staged gitnexus/ files?
    • tsc --noEmit
    • vitest run --project default
      If not verifiable, say exactly what is missing.

4. Performance

Inspect for:

  • hot-path overhead in ingestion/group sync
  • excess allocations per manifest entry
  • redundant Cypher round-trips
  • missed batching or missed parallelism (Promise.all) where it materially matters
  • O(n²) or repeated lookup patterns on large repos
  • memoization tradeoffs:
    • correctness
    • invalidation
    • bounded vs unbounded memory growth
      Do not speculate casually; explain the mechanism and likely impact.

5. Operational risk

Check:

  • Windows/cross-platform safety:
    • stream lifecycle
    • FD/file handle lifecycle
    • path separator assumptions
    • anything resembling prior ENOTEMPTY-style lifecycle regressions
  • LadybugDB single-writer invariant is preserved
  • Embeddings preservation:
    • no silent breakage of --embeddings
    • .gitnexus/meta.json.stats.embeddings not silently zeroed by changed paths
  • MCP contracts remain compatible:
    • group_*
    • query
    • context
    • impact
    • detect_changes
    • rename
    • cypher
      Flag any schema or contract break without migration note
  • staleness behavior still triggers correctly (gitnexus/src/mcp/staleness.ts)
  • rollback safety:
    • can this PR be reverted safely without re-analyze?
    • if not, explain why

6. Maintainability

Check:

  • Does the change respect Pipeline Phase DAG boundaries?
  • Is cross-phase coupling being introduced?
  • Are manifest-extractor entry points discoverable from group/sync.ts?
  • Would the next contributor know where to extend this?
  • Is shared logic placed appropriately:
    • in gitnexus-shared/
    • or gitnexus/src/core/**/utils.ts
    • and not duplicated between CLI and web bridge (server/api.ts)?

NON-NEGOTIABLES TO VERIFY
From GUARDRAILS.md / CONTRIBUTING.md:

  • no secrets, tokens, or machine-specific paths committed
  • no blind find-and-replace renames
  • if a symbol rename occurred, rename MCP tool or equivalent careful review was used
  • upstream impact was considered for modified shared symbols
  • no HIGH/CRITICAL impact left unaddressed
  • PR title follows conventional commit style + [area] Short description
  • PolyForm Noncommercial license headers/metadata untouched

OUTPUT FORMAT

Production-ready bar for this PR

Give a concise repo-specific definition in 5–10 bullets.

Findings

For each finding, use this structure exactly:

[BLOCKING|NON-BLOCKING|NIT] Short title

  • Evidence: path:line, path:line
  • Why it matters: ...
  • Recommendation: ...
  • Confidence: High / Medium / Low

Only include findings that are real and supported.
If there are no findings in a section, say:

  • No issues found in this area based on the diff and reviewed context.

What I could not fully verify

List any behavior you could not prove from the diff, tests, or available context.

Final verdict

Choose exactly one:

  • ✅ Ready to merge — no blocking issues.
  • ⚠️ Merge after addressing blocking items.
  • ❌ Not ready — fundamental concerns.

If verdict is not ready, list the blocking items in priority order.


IMPORTANT REVIEW BEHAVIOR

  • Be strict on correctness and contracts.
  • Be conservative about operational risk.
  • Be explicit about uncertainty.
  • Do not suggest unrelated refactors.
  • Do not turn nits into blockers.
  • Do not reward intent; review actual implementation.

You must also ensure we are on track with the RFC plan! Check the issue tickets involved!

@github-actions

github-actions Bot commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

Claude finished @magyargergo's task in 3m 18s —— View job


Senior Review — PR #959 feat(shared): resolveTypeRef (RFC #909 Ring 2 SHARED #916)


Production-ready bar for this PR

For a pure shared-library addition in gitnexus-shared/src/scope-resolution/:

  1. Pure function, no side effects — no DB writes, no filesystem access, no network. Safe to call from any pipeline phase or consumer.
  2. RFC §4.6 contract honoured — strictly narrower than Registry.lookup: no wildcard fallback, no confidence ranking, no arity, single-return.
  3. Type compatibility — all types (BindingRef, TypeRef, Scope, SymbolDefinition, DefIndex, QualifiedNameIndex) imported from the existing RFC §2 data model in gitnexus-shared; no re-definitions.
  4. ScopeLookup interface ships inline — correct strategy to decouple from RING2-SHARED-1: Scope / ScopeTree / PositionIndex in gitnexus-shared #912's ScopeTree until it lands; must satisfy the forthcoming concrete type verbatim.
  5. Barrel exports cleangitnexus-shared/src/index.ts additions are non-breaking and complete; no unused re-exports.
  6. Unit tests live under gitnexus/test/unit/ — correct location per TESTING.md, importing from gitnexus-shared (no barrel regressions).
  7. tsc --noEmit clean for both gitnexus-shared and gitnexus — claimed in PR and consistent with the code being entirely typed with existing contracts.
  8. PR title follows conventional-commit formatfeat(shared): …
  9. No secrets, no machine paths, no find-and-replace renames — pure new-file addition.
  10. RFC Meta: Pure Scope-Based Resolution in the Semantic Model #909 Ring 2 milestone progress — this piece correctly unblocks RING2-SHARED-6: ClassRegistry / MethodRegistry / FieldRegistry + evidence composition #917 (Registry.lookup Step 2) and is consistent with the Ring 2 merge order.

Findings

1. Correctness & functional completeness

'Type' NodeLabel is absent from TYPE_KINDS — unverified concern

  • Evidence: gitnexus-shared/src/scope-resolution/resolve-type-ref.ts:87-100, gitnexus-shared/src/graph/types.ts:13
  • NodeLabel includes the value 'Type' (line 23 of graph/types.ts). This label is absent from TYPE_KINDS. If any language extractor emits SymbolDefinition.type === 'Type' (e.g., as a catch-all for abstract or synthesised type nodes that don't fit TypeAlias/Typedef/Class), such definitions would be treated as non-type-kind and resolution would silently return null.
  • ARCHITECTURE.md's LadybugDB schema table list does not enumerate a Type table (it lists TypeAlias, Typedef, and CodeElement), which suggests 'Type' is either unmapped/legacy or maps to CodeElement. If the label is never emitted by the ingestion pipeline for type-annotation targets, this is a non-issue. Cannot verify from the diff alone.
  • Recommendation: Confirm via a grep of gitnexus/src/core/ingestion/ whether type: 'Type' is ever emitted for annotation-relevant symbols. If yes, add 'Type' to TYPE_KINDS with a note. If no, add a comment to TYPE_KINDS documenting the deliberate exclusion.
  • Confidence: Medium
  • Severity: NON-BLOCKING

No other issues found in Correctness & functional completeness. The scope-chain walk, shadowing semantics, wildcard exclusion, dotted fallback, and uniqueness enforcement all implement the RFC §4.6 spec correctly and are verified by the test suite.

2. Code clarity & clean code

NIT: Test name says "resolves" but expects null

  • Evidence: gitnexus/test/unit/scope-resolution/resolve-type-ref.test.ts:142
  • The test is named 'resolves a namespace-origin binding (e.g., \import * as np`)'but the assertion istoBeNull()`. The body comment clarifies the intent, but the name is misleading for anyone scanning the test output summary.
  • Recommendation: Rename to 'returns null for a namespace-origin binding whose def is not a type kind' to match the failure-case intent.
  • Confidence: High
  • Severity: NIT

No other code clarity issues. Naming, cohesion, and imports are clean. No // removed comments. No barrel regressions. No drive-by refactors. The ScopeLookup inline declaration is correctly justified in the PR description.

3. Test coverage & change safety

  • No issues found in this area based on the diff and reviewed context.
  • 22 tests cover: local/parent scope walk, all 5 BindingRef.origin values, shadowing (non-type, method, qname-fallthrough guard), dotted qname fallback (unique, ambiguous, non-dotted, non-type hit, no-type hit), and all 4 robustness cases (missing type, unknown scope, broken chain, cycle guard). All 7 TypeRef.source values are exercised in one parametric test.
  • Assertions are non-tautological (toBe(userClass) using reference equality against the exact constructed fixture object, not reconstructed values).
  • No memoization introduced — no cache tests needed.
  • PR claims tsc --noEmit clean and 22/22 + combined 151/151 passing. Cannot re-run CI from this context but the code is consistent with the stated results.

4. Performance

  • No issues found in this area based on the diff and reviewed context.
  • new Set<ScopeId>() (cycle guard) is allocated per call. For a typical scope depth of 5–20, this is negligible.
  • Scope walk is O(depth × bindings-per-scope). Both are bounded in well-formed scope trees.
  • Dotted fallback iterates a frozen DefId[] from QualifiedNameIndex.get() — O(candidates) linear scan, negligible for this data shape.
  • No O(n²) patterns introduced.

5. Operational risk

  • No issues found in this area based on the diff and reviewed context.
  • Pure in-memory function, no streams, no file handles, no DB writes. No cross-platform risk.
  • No MCP contract changes. No schema changes. No generateId changes.
  • LadybugDB single-writer invariant unaffected.
  • Embeddings unaffected.
  • Rollback is safe: removing this export from index.ts and deleting the file would revert cleanly; no migrations, no persistent state.

6. Maintainability


RFC #909 Ring 2 — plan check

Ticket Status Note
#910 types ✅ Merged Prerequisite; BindingRef, TypeRef, Scope, etc. imported correctly
#911 hooks ✅ Merged Prerequisite; no hooks called here
#913 indexes (#958) ✅ Merged DefIndex + QualifiedNameIndex dependency satisfied
#916 resolveTypeRef This PR Implements RFC §4.6; unblocks #917
#918 shadow diff ✅ Merged (#951) No dependency from this PR; already exported in index.ts
#912 ScopeTree 🔲 Pending ScopeLookup interface here is forward-compatible per design
#917 Registry.lookup 🔲 Pending Unblocked by this PR

Stacking note: PR description says "rebase to main once #958 merges." Commit ac2012e confirms #958 is already merged into main. This PR should be rebased (or the stacking dependency is now resolved — check if the branch already incorporates it).


What I could not fully verify

  1. Whether type: 'Type' is ever emitted by the ingestion pipeline for annotation-relevant symbols. Requires grepping gitnexus/src/core/ingestion/ extraction code, which is outside this diff.
  2. CI passing — cannot re-run tsc --noEmit or vitest from this context. The PR claims both clean; code is consistent with that claim.
  3. RING2-SHARED-1: Scope / ScopeTree / PositionIndex in gitnexus-shared #912 ScopeTree's concrete interface — cannot verify that it will satisfy ScopeLookup verbatim until RING2-SHARED-1: Scope / ScopeTree / PositionIndex in gitnexus-shared #912 lands, but the PR design intent is sound.

Final verdict

Ready to merge — no blocking issues.

The implementation correctly and completely delivers RFC §4.6. Algorithm, type safety, test coverage, barrel exports, and operational posture are all sound. The one NON-BLOCKING finding ('Type' NodeLabel) should be confirmed before #917 consumes this API at scale, but does not block merge. The NIT test-name fix is optional.

Before or alongside #917: confirm via ingestion code grep that type: 'Type' is never emitted for type-annotation targets (or add it to TYPE_KINDS if it is).

@magyargergo magyargergo merged commit 56e32b3 into main Apr 18, 2026
12 checks passed
@magyargergo magyargergo deleted the rfc/scope-resolution/916-resolve-type-ref branch April 18, 2026 15:09
@github-actions

Copy link
Copy Markdown
Contributor

CI Report

All checks passed

Pipeline Status

Stage Status Details
✅ Typecheck success tsc --noEmit
✅ Tests success unit tests, 3 platforms
✅ E2E success gitnexus-web changes only

Test Results

Tests Passed Failed Skipped Duration
6680 6583 0 97 259s

✅ All 6583 tests passed

97 test(s) skipped — expand for details
  • Swift MethodExtractor > isTypeDeclaration > recognizes class_declaration
  • Swift MethodExtractor > isTypeDeclaration > recognizes protocol_declaration
  • Swift MethodExtractor > isTypeDeclaration > rejects import_declaration
  • Swift MethodExtractor > visibility > extracts public method
  • Swift MethodExtractor > visibility > extracts private method
  • Swift MethodExtractor > visibility > defaults to internal when no modifier
  • Swift MethodExtractor > protocol methods > marks protocol method as abstract
  • Swift MethodExtractor > static and class methods > detects static func as isStatic
  • Swift MethodExtractor > static and class methods > detects class func as isStatic
  • Swift MethodExtractor > parameters > extracts parameters with types and default values
  • Swift MethodExtractor > return type > extracts return type from -> annotation
  • Swift MethodExtractor > annotations > extracts @objc attribute
  • Swift MethodExtractor > isFinal > detects final func
  • Swift MethodExtractor > isFinal > is false when not final
  • Swift MethodExtractor > isAsync > detects async func
  • Swift MethodExtractor > isOverride > detects override method
  • buildTypeEnv > constructor inference (Tier 1 fallback) > lookupClassByName regression coverage > Swift lookupClassByName regression coverage > Swift cross-file constructor inference uses lookupClassByName
  • buildTypeEnv > constructor inference (Tier 1 fallback) > lookupClassByName regression coverage > Swift lookupClassByName regression coverage > Swift explicit init inference uses lookupClassByName
  • buildTypeEnv > constructor inference (Tier 1 fallback) > lookupClassByName regression coverage > Swift lookupClassByName regression coverage > Swift cross-file constructor inference does not bind plain functions
  • buildTypeEnv > known limitations (documented skip tests) > Ruby block parameter: users.each { |user| } — closure param inference, different feature
  • Swift constructor-inferred type resolution > detects User and Repo classes, both with save methods
  • Swift constructor-inferred type resolution > resolves user.save() to Models/User.swift via constructor-inferred type
  • Swift constructor-inferred type resolution > resolves repo.save() to Models/Repo.swift via constructor-inferred type
  • Swift constructor-inferred type resolution > emits exactly 2 save() CALLS edges (one per receiver type)
  • Swift self resolution > detects User and Repo classes, each with a save function
  • Swift self resolution > resolves self.save() inside User.process to User.save, not Repo.save
  • Swift parent resolution > detects BaseModel and User classes plus Serializable protocol
  • Swift parent resolution > emits EXTENDS edge: User → BaseModel
  • Swift parent resolution > emits IMPLEMENTS edge: User → Serializable (protocol conformance)
  • Swift cross-file User.init() inference > resolves user.save() via User.init(name:) inference
  • Swift cross-file User.init() inference > resolves user.greet() via User.init(name:) inference
  • Swift return type inference > detects User class and getUser function
  • Swift return type inference > detects save function on User (Swift class methods are Function nodes)
  • Swift return type inference > resolves user.save() to User#save via return type of getUser() -> User
  • Swift return-type inference via function return type > resolves user.save() to User#save via return type of getUser()
  • Swift return-type inference via function return type > user.save() does NOT resolve to Repo#save
  • Swift return-type inference via function return type > resolves repo.save() to Repo#save via return type of getRepo()
  • Swift implicit imports (cross-file visibility) > detects UserService class in Models.swift
  • Swift implicit imports (cross-file visibility) > resolves UserService() constructor call across files (no explicit import)
  • Swift implicit imports (cross-file visibility) > resolves service.fetchUser() member call across files
  • Swift implicit imports (cross-file visibility) > creates IMPORTS edges between files in the same module
  • Swift extension deduplication > detects Product class
  • Swift extension deduplication > resolves Product() constructor despite extension creating duplicate class node
  • Swift extension deduplication > resolves product.save() to Product.swift (primary definition)
  • Swift constructor call fallback (no new keyword) > resolves OCRService() as constructor call across files
  • Swift constructor call fallback (no new keyword) > resolves ocr.recognize() member call via constructor-inferred type
  • Swift export visibility (internal vs private) > resolves PublicService() constructor across files
  • Swift export visibility (internal vs private) > resolves internalHelper() across files (internal = module-scoped)
  • Swift if let / guard let binding resolution > detects User and Repo classes
  • Swift if let / guard let binding resolution > resolves user.save() inside if-let to User#save
  • Swift if let / guard let binding resolution > resolves repo.save() inside guard-let to Repo#save
  • Swift if let / guard let binding resolution > user.save() in if-let does NOT resolve to Repo#save
  • Swift await / try expression unwrapping > resolves user.save() via await fetchUser() return type
  • Swift await / try expression unwrapping > resolves repo.save() via try parseRepo() return type
  • Swift await / try expression unwrapping > detects fetchUser and parseRepo as functions
  • Swift for-in loop element type inference > detects User and Repo classes
  • Swift for-in loop element type inference > creates implicit import edges between files
  • Swift field-type resolution > detects classes and their properties
  • Swift field-type resolution > emits HAS_PROPERTY edges from class to field
  • Swift field-type resolution > resolves field-chain call user.address.save() → Address#save
  • Swift field-type resolution > emits ACCESSES edges for field reads in chains
  • Swift field-type resolution > populates field metadata (visibility, declaredType) on Property nodes
  • Swift call-result binding > resolves call-result-bound method call user.save() → User#save
  • Swift call-result binding > getUser() is present as a defined function
  • Swift call-result binding > emits processUser -> getUser CALLS edge for let-assigned free function call
  • Swift method enrichment > detects Animal protocol and Dog class
  • Swift method enrichment > emits IMPLEMENTS edge Dog -> Animal
  • Swift method enrichment > emits HAS_METHOD edges for Dog methods
  • Swift method enrichment > marks protocol Animal.speak as isAbstract
  • Swift method enrichment > marks Dog.speak as NOT isAbstract
  • Swift method enrichment > marks breathe as isFinal
  • Swift method enrichment > marks classify as isStatic
  • Swift method enrichment > captures @objc annotation on breathe
  • Swift method enrichment > populates parameterTypes for classify(_ name: String)
  • Swift method enrichment > records parameterCount for classify
  • Swift method enrichment > records returnType for speak
  • Swift method enrichment > resolves dog.speak() CALLS edge
  • Swift method enrichment > resolves Dog.classify("dog") CALLS edge
  • Swift abstract dispatch > detects Repository protocol and SqlRepository class
  • Swift abstract dispatch > emits IMPLEMENTS edge SqlRepository -> Repository
  • Swift abstract dispatch > emits HAS_METHOD edges for Repository.find and Repository.save
  • Swift abstract dispatch > emits HAS_METHOD edges for SqlRepository.find and SqlRepository.save
  • Swift abstract dispatch > marks base Repository.find as isAbstract
  • Swift abstract dispatch > marks base Repository.save as isAbstract
  • Swift abstract dispatch > marks concrete SqlRepository.find as NOT isAbstract
  • Swift abstract dispatch > resolves repo.find(id: 42) CALLS edge
  • Swift abstract dispatch > resolves repo.save(entity: user) CALLS edge
  • Swift abstract dispatch > populates parameterTypes for Repository.find
  • Swift abstract dispatch > populates parameterTypes for Repository.save
  • Swift abstract dispatch > records returnType for SqlRepository.find
  • Swift abstract dispatch > emits METHOD_IMPLEMENTS edges from SqlRepository methods → Repository protocol methods
  • Swift overloaded method disambiguation > detects 2 distinct find Method nodes on SqlRepository
  • Swift overloaded method disambiguation > emits METHOD_IMPLEMENTS edges for both find overloads
  • Swift overloaded method disambiguation > emits METHOD_IMPLEMENTS edge for save
  • Swift overloaded method disambiguation > emits exactly 3 METHOD_IMPLEMENTS edges total
  • Swift Child extends Parent — inherited method resolution (SM-9) > detects Parent and Child classes
  • Swift Child extends Parent — inherited method resolution (SM-9) > resolves c.parentMethod() to Parent.parentMethod via first-wins MRO walk

Code Coverage

Tests

Metric Coverage Covered Base Delta Status
Statements 73.25% 17890/24423 73.25% = 0.0 🟢 ██████████████░░░░░░
Branches 62.3% 11384/18271 62.3% = 0.0 🟢 ████████████░░░░░░░░
Functions 77.84% 1694/2176 77.84% = 0.0 🟢 ███████████████░░░░░
Lines 75.8% 16215/21390 75.8% = 0.0 🟢 ███████████████░░░░░

📋 View full run · Generated by CI

github714801013 pushed a commit to github714801013/GitNexus that referenced this pull request Apr 28, 2026
…gyanpatwari#916, RFC abhigyanpatwari#909 Ring 2 SHARED) (abhigyanpatwari#959)

Implements RFC §4.6: a strict, pure resolver for `TypeRef`s used by
`Registry.lookup` Step 2 (type-binding propagation) and by any caller that
wants the single best type-target for an annotation without paying for the
full evidence pipeline.

Algorithm (strict):

  1. Walk the scope chain from `ref.declaredAtScope`:
     - Return the first binding for `rawName` whose origin is in
       `{'local','import','namespace','reexport'}` AND whose `def.type` is a
       type-kind (class-like, interface-like, enum-like, alias-like).
     - If bindings exist but none qualify (non-type shadow, wildcard-only
       origin), return null immediately — do NOT fall through to the global
       qualified-name index.
  2. If `rawName` is dotted and the scope walk produced no match, consult
     `QualifiedNameIndex.byQualifiedName`. Only accept a UNIQUE type-kind
     hit; ambiguous or non-type results return null.

`'wildcard'` is deliberately excluded from strict origins — a
wildcard-expanded name is too loose to anchor type resolution.

Module placement: `gitnexus-shared/src/scope-resolution/resolve-type-ref.ts`
(alongside sibling indexes) rather than the issue's suggested
`gitnexus-shared/src/resolve-type-ref.ts`, for consistency with the rest of
the RFC §2/§3 surface.

A minimal `ScopeLookup` interface is declared inline so abhigyanpatwari#916 ships
standalone; abhigyanpatwari#912's `ScopeTree` will satisfy this contract without change.

Closes part of abhigyanpatwari#909.
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.

RING2-SHARED-5: resolveTypeRef strict helper

1 participant