From 975dedb6d2a9489af7ca63ff0163756d9339b5cd Mon Sep 17 00:00:00 2001 From: Gergo Magyar Date: Thu, 30 Jul 2026 08:23:53 +0000 Subject: [PATCH] refactor(shared): move MixedChainStep into gitnexus-shared MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit U3. The shared package owns the ScopeExtractor output contract, and a receiver chain is about to become part of it, so the type moves to sit beside `ReferenceSite` — the interface that will carry it. Type-only move. `extractMixedChain` stays in the analyzer: it walks a tree-sitter AST, so it cannot follow. `MAX_CHAIN_DEPTH` stays with it for the same reason — nothing shared needs the bound yet, and moving it now would be moving it on speculation. `call-analysis.ts` re-exports the type so its existing importers keep a single import site. The re-export is `import type` + `export type` rather than a bare `export type { X } from`, which creates no local binding and left the file's own two uses of the name unresolved. Verified: `tsc --noEmit` clean in both packages, and the receiver-resolution gate green end to end. (The unit suite has seven failures on this tree, all subprocess-spawning CLI tests timing out. Three pass in isolation — load flake. The fourth, `skip-git-cli.test.ts`, fails harder on untouched `main` in this sandbox — six failures there against four here — so it is environmental and predates this branch.) --- gitnexus-shared/src/index.ts | 7 ++++++- .../src/scope-resolution/reference-site.ts | 15 +++++++++++++++ .../src/core/ingestion/utils/call-analysis.ts | 12 ++++++++++-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/gitnexus-shared/src/index.ts b/gitnexus-shared/src/index.ts index 860558016a..0ac74b1ed3 100644 --- a/gitnexus-shared/src/index.ts +++ b/gitnexus-shared/src/index.ts @@ -83,7 +83,12 @@ export type { ResolveTypeRefContext } from './scope-resolution/resolve-type-ref. // ScopeExtractor output contracts (RFC §3.2 Phase 1; Ring 2 PKG #919) export type { ParsedFile } from './scope-resolution/parsed-file.js'; -export type { ReferenceSite, ReferenceKind, CallForm } from './scope-resolution/reference-site.js'; +export type { + ReferenceSite, + ReferenceKind, + CallForm, + MixedChainStep, +} from './scope-resolution/reference-site.js'; export type { CallableFlowOperand, CallableFlowExpectedSignature, diff --git a/gitnexus-shared/src/scope-resolution/reference-site.ts b/gitnexus-shared/src/scope-resolution/reference-site.ts index 5ced6e1762..1632bfd20b 100644 --- a/gitnexus-shared/src/scope-resolution/reference-site.ts +++ b/gitnexus-shared/src/scope-resolution/reference-site.ts @@ -124,3 +124,18 @@ export interface ReferenceSite { */ readonly argumentTypeClasses?: readonly ParameterTypeClass[]; } + +/** + * One step in a mixed receiver chain — the decoded form of a receiver that is + * itself an expression rather than a bare name. + * + * For `svc.getUser().address.save()`, the receiver of `save` decodes to + * `[{ kind: 'call', name: 'getUser' }, { kind: 'field', name: 'address' }]` + * over a base receiver of `svc`. + * + * Lives here rather than beside its producer because it is part of the + * ScopeExtractor output contract that this package owns: the producer + * (`extractMixedChain`) walks a tree-sitter AST and so must stay in the + * analyzer, but the shape it yields crosses into resolution. + */ +export type MixedChainStep = { kind: 'field' | 'call'; name: string }; diff --git a/gitnexus/src/core/ingestion/utils/call-analysis.ts b/gitnexus/src/core/ingestion/utils/call-analysis.ts index c7eb8e45fd..831045b0c1 100644 --- a/gitnexus/src/core/ingestion/utils/call-analysis.ts +++ b/gitnexus/src/core/ingestion/utils/call-analysis.ts @@ -1,3 +1,5 @@ +import type { MixedChainStep } from 'gitnexus-shared'; + import type { SyntaxNode } from './ast-helpers.js'; import { CALL_ARGUMENT_LIST_TYPES } from './ast-helpers.js'; @@ -362,8 +364,14 @@ const FIELD_ACCESS_NODE_TYPES = new Set([ 'member_binding_expression', // C# null-conditional (user?.Address) ]); -/** One step in a mixed receiver chain. */ -export type MixedChainStep = { kind: 'field' | 'call'; name: string }; +/** + * One step in a mixed receiver chain. + * + * Owned by `gitnexus-shared` — it is part of the ScopeExtractor output + * contract, and resolution consumes it. Re-exported here so the producer's + * existing importers keep a single import site. + */ +export type { MixedChainStep }; /** * Walk a receiver AST node that is itself a call expression, accumulating the