diff --git a/gitnexus-shared/src/index.ts b/gitnexus-shared/src/index.ts index 4024bf070..8f9bbdb3b 100644 --- a/gitnexus-shared/src/index.ts +++ b/gitnexus-shared/src/index.ts @@ -23,3 +23,36 @@ export type { MroStrategy } from './mro-strategy.js'; // Pipeline progress export type { PipelinePhase, PipelineProgress } from './pipeline.js'; + +// ─── Scope-based resolution — RFC #909 (Ring 1 #910) ──────────────────────── +// Data model (RFC §2) +export type { SymbolDefinition } from './scope-resolution/symbol-definition.js'; +export type { + ScopeId, + DefId, + ScopeKind, + Range, + Capture, + BindingRef, + ImportEdge, + TypeRef, + Scope, + ResolutionEvidence, + Resolution, + Reference, + ReferenceIndex, + LookupParams, + RegistryContributor, +} from './scope-resolution/types.js'; + +// Evidence + tie-break constants (RFC Appendix A, Appendix B) +export { EvidenceWeights, typeBindingWeightAtDepth } from './scope-resolution/evidence-weights.js'; +export { ORIGIN_PRIORITY } from './scope-resolution/origin-priority.js'; +export type { OriginForTieBreak } from './scope-resolution/origin-priority.js'; + +// Language classification (RFC §6.1 Ring 3/4 governance) +export { + LanguageClassifications, + isProductionLanguage, +} from './scope-resolution/language-classification.js'; +export type { LanguageClassification } from './scope-resolution/language-classification.js'; diff --git a/gitnexus-shared/src/scope-resolution/evidence-weights.ts b/gitnexus-shared/src/scope-resolution/evidence-weights.ts new file mode 100644 index 000000000..d1f46dabb --- /dev/null +++ b/gitnexus-shared/src/scope-resolution/evidence-weights.ts @@ -0,0 +1,90 @@ +/** + * `EvidenceWeights` — RFC Appendix A (authoritative values). + * + * Starting calibration for scope-based resolution. Shadow-first rollout + * tunes these against legacy DAG parity. Every `ResolutionEvidence.weight` + * value in the codebase MUST reference this map; inline magic numbers are a + * lint violation. Extends issue #429 (centralize hardcoded confidence values). + * + * Evidence composes additively inside `composeEvidence`; the sum is capped + * at 1.0 in `Resolution.confidence`. + */ + +/** + * Authoritative weight map. Keys are a mix of `ResolutionEvidence.kind` + * values and special modifiers (scope-chain depth, MRO depth decay, + * unlinked-import multiplicative cap). + */ +export const EvidenceWeights = { + // ─── Where-found signals (visibility) ───────────────────────────────────── + /** `BindingRef.origin === 'local'` */ + local: 0.55, + /** `BindingRef.origin === 'import'` */ + import: 0.45, + /** `BindingRef.origin === 'reexport'` */ + reexport: 0.4, + /** `BindingRef.origin === 'namespace'` */ + namespace: 0.4, + /** `BindingRef.origin === 'wildcard'` */ + wildcard: 0.3, + + // ─── Scope-chain deduction (per-hop) ────────────────────────────────────── + /** Deducted per parent-hop taken (depth-0 = 0, depth-1 = −0.02, …). */ + scopeChainPerDepth: -0.02, + + // ─── Receiver-type-binding signal (decays by MRO depth) ─────────────────── + /** + * Weight applied when the receiver's type binding resolves to a class that + * declares the candidate as a method/field. Decays by MRO depth: direct + * class = index 0; 1 parent hop = index 1; etc. Falls back to the last + * value for depths beyond the table. + */ + typeBindingByMroDepth: [0.5, 0.42, 0.36, 0.32, 0.3] as const, + + // ─── Corroborating signals ──────────────────────────────────────────────── + /** `def.ownerId === resolvedReceiver.def.id` (exact owner match). */ + ownerMatch: 0.2, + /** Explanatory only — retained for debuggability. Never discriminates + * because surviving candidates already passed `acceptedKinds`. */ + kindMatch: 0.0, + + // ─── Arity compatibility (from `provider.arityCompatibility`) ───────────── + /** `provider.arityCompatibility(...) === 'compatible'` */ + arityMatchCompatible: 0.1, + /** `provider.arityCompatibility(...) === 'unknown'` */ + arityMatchUnknown: 0.0, + /** `provider.arityCompatibility(...) === 'incompatible'` — penalizes; + * candidates filtered only when a compatible candidate exists. */ + arityMatchIncompatible: -0.15, + + // ─── Global fallback (only when nothing lexically visible) ──────────────── + /** Hit via `QualifiedNameIndex.byQualifiedName`. */ + globalQualified: 0.35, + /** Fallback hit in a `byName` index (and nothing was lexically visible). */ + globalName: 0.1, + + // ─── Degraded signals ───────────────────────────────────────────────────── + /** Call/reference flowing through a `dynamic-unresolved` edge. */ + dynamicImportUnresolved: 0.02, + + // ─── Unresolved-import cap (multiplicative, applied per-signal) ─────────── + /** + * Multiplicative cap on the edge-derived evidence signal + * (`import`/`wildcard`/`reexport`/`namespace`) when + * `ImportEdge.linkStatus === 'unresolved'`. Independent corroborating + * signals on the same candidate (`owner-match`, `arity-match`, + * `type-binding`) are NOT penalized. + */ + unlinkedImportMultiplier: 0.5, +} as const; + +/** + * Look up the `type-binding` signal weight for a given MRO depth, falling + * back to the last tabulated value for depths beyond the table. + */ +export function typeBindingWeightAtDepth(mroDepth: number): number { + const table = EvidenceWeights.typeBindingByMroDepth; + if (mroDepth < 0) return table[0]; + if (mroDepth >= table.length) return table[table.length - 1]; + return table[mroDepth]; +} diff --git a/gitnexus-shared/src/scope-resolution/language-classification.ts b/gitnexus-shared/src/scope-resolution/language-classification.ts new file mode 100644 index 000000000..10c556cda --- /dev/null +++ b/gitnexus-shared/src/scope-resolution/language-classification.ts @@ -0,0 +1,49 @@ +/** + * `LanguageClassification` — RFC §6.1 Ring 3 / Ring 4 governance. + * + * Classifies each `SupportedLanguages` member for the rollout. Ring 4 (DAG + * retirement) is gated on *all production languages* being registry-primary + * and stable for one release cycle; `experimental` and `quarantined` + * languages do not block. + * + * Initial classification (locked in Ring 1 #910): + * - production: javascript, typescript, python, java, c, cpp, csharp, go, + * ruby, rust, php, kotlin, swift, dart + * - experimental: vue (embedded-language / SFC complexity), + * cobol (regex-provider path) + * - quarantined: (none) + */ + +import { SupportedLanguages } from '../languages.js'; + +export type LanguageClassification = 'production' | 'experimental' | 'quarantined'; + +/** + * The canonical classification for each supported language. Governance + * changes (promote `experimental` → `production`, quarantine a language, …) + * update this map in a dedicated PR. + */ +export const LanguageClassifications: Readonly> = + { + [SupportedLanguages.JavaScript]: 'production', + [SupportedLanguages.TypeScript]: 'production', + [SupportedLanguages.Python]: 'production', + [SupportedLanguages.Java]: 'production', + [SupportedLanguages.C]: 'production', + [SupportedLanguages.CPlusPlus]: 'production', + [SupportedLanguages.CSharp]: 'production', + [SupportedLanguages.Go]: 'production', + [SupportedLanguages.Ruby]: 'production', + [SupportedLanguages.Rust]: 'production', + [SupportedLanguages.PHP]: 'production', + [SupportedLanguages.Kotlin]: 'production', + [SupportedLanguages.Swift]: 'production', + [SupportedLanguages.Dart]: 'production', + [SupportedLanguages.Vue]: 'experimental', + [SupportedLanguages.Cobol]: 'experimental', + }; + +/** Convenience predicate: is this language gating Ring 4 retirement? */ +export function isProductionLanguage(lang: SupportedLanguages): boolean { + return LanguageClassifications[lang] === 'production'; +} diff --git a/gitnexus-shared/src/scope-resolution/origin-priority.ts b/gitnexus-shared/src/scope-resolution/origin-priority.ts new file mode 100644 index 000000000..c5068c274 --- /dev/null +++ b/gitnexus-shared/src/scope-resolution/origin-priority.ts @@ -0,0 +1,30 @@ +/** + * `ORIGIN_PRIORITY` — RFC Appendix B (authoritative values). + * + * Tie-break ordering applied inside `Registry.lookup` Step 7 when + * `|Δconfidence| < 0.001` between two `Resolution` candidates. Lower number + * = stronger (wins the tie). + * + * Full tie-break order (§4.2 Step 7): + * confidence DESC → scope depth ASC → MRO depth ASC → ORIGIN_PRIORITY ASC + * → DefId.localeCompare + */ + +export type OriginForTieBreak = + | 'local' + | 'import' + | 'reexport' + | 'namespace' + | 'wildcard' + | 'global-qualified' + | 'global-name'; + +export const ORIGIN_PRIORITY: Readonly> = { + local: 0, + import: 1, + reexport: 2, + namespace: 3, + wildcard: 4, + 'global-qualified': 5, + 'global-name': 6, +}; diff --git a/gitnexus-shared/src/scope-resolution/symbol-definition.ts b/gitnexus-shared/src/scope-resolution/symbol-definition.ts new file mode 100644 index 000000000..d07dbf38b --- /dev/null +++ b/gitnexus-shared/src/scope-resolution/symbol-definition.ts @@ -0,0 +1,35 @@ +/** + * `SymbolDefinition` — the canonical shape of an indexed symbol record. + * + * Historically defined in `gitnexus/src/core/ingestion/model/symbol-table.ts`; + * moved into `gitnexus-shared` as part of RFC #909 Ring 1 (#910) so the + * scope-resolution types that reference it can live in the shared package + * alongside their consumers (`gitnexus/` and `gitnexus-web/`). + * + * Shape is unchanged from the prior local definition. + */ + +import type { NodeLabel } from '../graph/types.js'; + +export interface SymbolDefinition { + nodeId: string; + filePath: string; + type: NodeLabel; + /** Canonical dot-separated qualified type name for class-like symbols + * (e.g. `App.Models.User`). Falls back to the simple symbol name when no + * package/namespace/module scope exists or no explicit qualified metadata is provided. */ + qualifiedName?: string; + parameterCount?: number; + /** Number of required (non-optional, non-default) parameters. + * Enables range-based arity filtering: argCount >= requiredParameterCount && argCount <= parameterCount. */ + requiredParameterCount?: number; + /** Per-parameter type names for overload disambiguation (e.g. ['int', 'String']). + * Populated when parameter types are resolvable from AST (any typed language). */ + parameterTypes?: string[]; + /** Raw return type text extracted from AST (e.g. 'User', 'Promise') */ + returnType?: string; + /** Declared type for non-callable symbols — fields/properties (e.g. 'Address', 'List') */ + declaredType?: string; + /** Links Method/Constructor/Property to owning Class/Struct/Trait nodeId */ + ownerId?: string; +} diff --git a/gitnexus-shared/src/scope-resolution/types.ts b/gitnexus-shared/src/scope-resolution/types.ts new file mode 100644 index 000000000..3ee1763b4 --- /dev/null +++ b/gitnexus-shared/src/scope-resolution/types.ts @@ -0,0 +1,264 @@ +/** + * Scope-resolution type definitions — RFC §2 data model (authoritative source). + * + * See: https://www.notion.so/346dc50b6ed281cfaacbe480bf231d50 + * + * Anti-drift rule: every type, interface, and enum defined here is the single + * source of truth. Later code that references these names must import them + * from `gitnexus-shared`; it must not re-define them locally. + * + * Lifecycle contract (RFC §2.8): scopes are **constructed during extraction, + * linked during finalize, immutable after finalize**. All fields are + * `readonly` at the type level; `Object.freeze` is applied at runtime in dev + * builds. `ReferenceIndex` is the sole structure populated after freeze — by + * resolution, before emission. + */ + +import type { NodeLabel } from '../graph/types.js'; +import type { SymbolDefinition } from './symbol-definition.js'; + +// ─── §2.1 Type aliases ────────────────────────────────────────────────────── + +/** Stable per-(file, range, kind) scope identifier; interned for identity-fast equality. */ +export type ScopeId = string; + +/** Stable symbol-definition identifier (graph nodeId). */ +export type DefId = string; + +/** Kinds of lexical scope a `Scope` node can represent. */ +export type ScopeKind = + | 'Module' // file root + | 'Namespace' // C++ namespace, C# namespace, Kotlin package-object, Rust mod + | 'Class' // class/struct/trait/interface body + | 'Function' // function/method/closure/lambda body + | 'Block' // { ... }, if-body, for-body, with-body, match arms + | 'Expression'; // comprehensions, for-init, pattern bindings, lambda param lists + +// ─── Range + Capture (parser-agnostic) ────────────────────────────────────── + +/** Source-text range. 1-based `startLine`/`endLine`; 0-based `startCol`/`endCol`. */ +export interface Range { + readonly startLine: number; + readonly startCol: number; + readonly endLine: number; + readonly endCol: number; +} + +/** + * Tagged capture emitted by a LanguageProvider's `emitScopeCaptures` hook. + * + * Parser-agnostic: tree-sitter queries and COBOL's regex tagger both produce + * `Capture[]`. The central `ScopeExtractor` consumes captures without + * knowing which parser produced them. + */ +export interface Capture { + /** Capture name, including leading `@` (e.g., `'@scope.module'`, `'@declaration.class'`). */ + readonly name: string; + readonly range: Range; + /** The captured source text. */ + readonly text: string; +} + +// ─── §2.4 ImportEdge ──────────────────────────────────────────────────────── + +/** + * A cross-file import edge attached to a module/namespace scope. + * + * Raw (unlinked) edges are emitted during parse (Phase 1); `targetModuleScope` + * and `targetDefId` are filled in during finalize (Phase 2) via SCC-aware + * bounded-fixpoint linking (RFC §3.2). + */ +export interface ImportEdge { + /** How this scope sees the imported name (after alias). */ + readonly localName: string; + /** Exporting file; `null` only when `kind === 'dynamic-unresolved'`. */ + readonly targetFile: string | null; + /** The name under which the target exports this symbol. */ + readonly targetExportedName: string; + /** Pre-resolved at finalize: the module scope of the exporting file. */ + readonly targetModuleScope?: ScopeId; + /** Pre-resolved at finalize: the exported symbol's `DefId`. */ + readonly targetDefId?: DefId; + readonly kind: + | 'named' + | 'alias' + | 'namespace' + | 'wildcard-expanded' + | 'reexport' + | 'dynamic-unresolved'; + /** Re-export chain, for provenance (e.g., `['./y']` when re-exported via `./y`). */ + readonly transitiveVia?: readonly string[]; + /** Set to `'unresolved'` when the SCC fixpoint could not link this edge. */ + readonly linkStatus?: 'unresolved'; +} + +// ─── §2.3 BindingRef ──────────────────────────────────────────────────────── + +/** + * A name binding visible at a scope, with provenance. + * + * Provenance stays at the visibility layer — a name being visible because it + * is local vs imported vs wildcard-expanded vs re-exported is a property of + * the binding itself. This keeps evidence emission and `import-use` reference + * stamping first-class instead of reconstructing provenance from a side table. + */ +export interface BindingRef { + readonly def: SymbolDefinition; + readonly origin: 'local' | 'import' | 'namespace' | 'wildcard' | 'reexport'; + /** Non-null for non-local origins; carries the `ImportEdge` that brought the name into this scope. */ + readonly via?: ImportEdge; +} + +// ─── §2.5 TypeRef ─────────────────────────────────────────────────────────── + +/** + * A reference to a named type, anchored at its declaration site. + * + * Design choice: raw name + declaration-site scope, resolved at lookup time. + * Pre-resolution would invert the extraction/resolution wall. Deferred thunks + * add no capability. Structured type systems are months of work per language. + * This shape keeps V1 tractable while preserving correctness for aliases, + * re-exports, and nested modules. Generics deferred to V2 via `typeArgs`. + */ +export interface TypeRef { + /** The name as written in source (e.g., `'User'`, `'models.User'`, `'List'`). */ + readonly rawName: string; + /** Anchor for resolving `rawName` — the scope where the annotation/inference was written. */ + readonly declaredAtScope: ScopeId; + readonly source: + | 'annotation' + | 'parameter-annotation' + | 'return-annotation' + | 'self' + | 'assignment-inferred' + | 'constructor-inferred' + | 'receiver-propagated'; + /** Reserved for V2+: generic type arguments (`List` → `[TypeRef('User')]`). V1 ignores. */ + readonly typeArgs?: readonly TypeRef[]; +} + +// ─── §2.2 Scope ───────────────────────────────────────────────────────────── + +/** + * The canonical lexical-scope node. Forms the spine of the SemanticModel. + * + * ScopeId shape (RFC §2.2): `scope:{filePath}#{startLine}:{startCol}-{endLine}:{endCol}:{kind}` + * — deterministic, stable across reparses of the same source, interned. + */ +export interface Scope { + readonly id: ScopeId; + readonly parent: ScopeId | null; + readonly kind: ScopeKind; + readonly range: Range; + readonly filePath: string; + + /** Names visible from this scope. Provenance preserved via `BindingRef.origin`. */ + readonly bindings: ReadonlyMap; + + /** Defs structurally owned by this scope (e.g., methods owned by a class body scope). */ + readonly ownedDefs: readonly SymbolDefinition[]; + + /** Import edges attached to this scope. Mostly module/namespace scopes, but some + * languages allow local imports (Python `def f(): from x import Y`, Rust + * fn-local `use`, TS dynamic `import()`). */ + readonly imports: readonly ImportEdge[]; + + /** Local type facts visible from this scope (parameter annotations, `self` binding, etc.). */ + readonly typeBindings: ReadonlyMap; +} + +// ─── §2.6 Resolution + ResolutionEvidence ─────────────────────────────────── + +/** + * One piece of evidence for a `Resolution`. Multiple signals corroborate a + * single match; their weights compose additively to produce `confidence`. + * + * Weights come from `EvidenceWeights` (see `./evidence-weights.ts`). + */ +export interface ResolutionEvidence { + readonly kind: + | 'local' + | 'scope-chain' + | 'import' + | 'type-binding' + | 'owner-match' + | 'kind-match' + | 'arity-match' + | 'global-name' + | 'global-qualified' + | 'dynamic-import-unresolved'; + /** Signal weight, sourced from `EvidenceWeights`. Additive; sum capped at 1.0. */ + readonly weight: number; + /** Optional debug annotation (e.g., `'matched via self: User'`). */ + readonly note?: string; +} + +/** + * A ranked resolution candidate returned by `ClassRegistry.lookup` / + * `MethodRegistry.lookup` / `FieldRegistry.lookup`. Evidence composes + * additively; callers read `[0]` for the one-shot answer or inspect the + * evidence trace for debugging. + */ +export interface Resolution { + readonly def: SymbolDefinition; + /** Σ of `evidence[].weight`, capped at 1.0. */ + readonly confidence: number; + readonly evidence: readonly ResolutionEvidence[]; + /** Optional debug trace: scopes walked to reach `def`. */ + readonly path?: readonly ScopeId[]; +} + +// ─── §2.7 Reference + ReferenceIndex ──────────────────────────────────────── + +/** + * A post-resolution usage fact: some code at `atRange` inside `fromScope` + * references `toDef` with the given confidence/evidence. Materialized by the + * resolution phase; emitted as graph edges (`CALLS`/`READS`/`WRITES`/etc.) + * during the emit phase. + */ +export interface Reference { + /** Innermost lexical scope containing `atRange`. */ + readonly fromScope: ScopeId; + readonly toDef: DefId; + /** Location of the reference in source. */ + readonly atRange: Range; + readonly kind: 'call' | 'read' | 'write' | 'type-reference' | 'inherits' | 'import-use'; + readonly confidence: number; + readonly evidence: readonly ResolutionEvidence[]; +} + +/** + * Two-way index over `Reference` records, populated during the resolution + * phase. Scopes stay immutable after finalize; references accumulate here. + */ +export interface ReferenceIndex { + readonly bySourceScope: ReadonlyMap; + readonly byTargetDef: ReadonlyMap; +} + +// ─── §4.1 LookupParams ────────────────────────────────────────────────────── + +/** + * Opaque placeholder for the per-kind registry passed as the owner-scoped + * contributor. Typed concretely in Ring 2 SHARED (#917); kept as `unknown` + * here so Ring 1 can ship without pulling in the registry implementation. + */ +export type RegistryContributor = unknown; + +/** + * Parameters accepted by `Registry.lookup`. Three registries (Class/Method/ + * Field) run the same 7-step algorithm with different parameter tuples; see + * RFC §4.4 for per-registry specializations. + */ +export interface LookupParams { + readonly acceptedKinds: readonly NodeLabel[]; + /** Class lookups: false. Method/Field lookups: true. */ + readonly useReceiverTypeBinding: boolean; + readonly ownerScopedContributor: RegistryContributor | null; + /** Optional arity hint fed to `provider.arityCompatibility`. */ + readonly arityHint?: number; + /** Explicit receiver name (e.g., `'user'` in `user.save()`). When present, + * the receiver's type binding at the callsite scope is used; otherwise + * the enclosing method's implicit `self`/`this` is consulted. See §4.1. */ + readonly explicitReceiver?: { readonly name: string }; +} diff --git a/gitnexus/src/core/ingestion/call-processor.ts b/gitnexus/src/core/ingestion/call-processor.ts index c30d83848..7d8a9da27 100644 --- a/gitnexus/src/core/ingestion/call-processor.ts +++ b/gitnexus/src/core/ingestion/call-processor.ts @@ -1,11 +1,7 @@ import { KnowledgeGraph } from '../graph/types.js'; import { ASTCache } from './ast-cache.js'; -import type { - SymbolDefinition, - SymbolTableReader, - HeritageMap, - ExtractedHeritage, -} from './model/index.js'; +import type { SymbolDefinition } from 'gitnexus-shared'; +import type { SymbolTableReader, HeritageMap, ExtractedHeritage } from './model/index.js'; import { CLASS_TYPES, CALL_TARGET_TYPES, lookupMethodByOwnerWithMRO } from './model/index.js'; import type { DispatchDecision, ReceiverEnriched } from './call-types.js'; diff --git a/gitnexus/src/core/ingestion/model/field-registry.ts b/gitnexus/src/core/ingestion/model/field-registry.ts index 45fe5c86a..62376c889 100644 --- a/gitnexus/src/core/ingestion/model/field-registry.ts +++ b/gitnexus/src/core/ingestion/model/field-registry.ts @@ -5,7 +5,7 @@ * Stores Property symbols keyed by `ownerNodeId\0fieldName` for O(1) lookup. */ -import type { SymbolDefinition } from './symbol-table.js'; +import type { SymbolDefinition } from 'gitnexus-shared'; // --------------------------------------------------------------------------- // Public read-only interface diff --git a/gitnexus/src/core/ingestion/model/index.ts b/gitnexus/src/core/ingestion/model/index.ts index 49f200285..d5398e6b7 100644 --- a/gitnexus/src/core/ingestion/model/index.ts +++ b/gitnexus/src/core/ingestion/model/index.ts @@ -26,7 +26,6 @@ export { type SymbolTableReader, type SymbolTableWriter, createSymbolTable, - type SymbolDefinition, type AddMetadata, CLASS_TYPES, CLASS_TYPES_TUPLE, @@ -36,6 +35,8 @@ export { type FreeCallableLabel, CALL_TARGET_TYPES, } from './symbol-table.js'; +// `SymbolDefinition` moved to `gitnexus-shared` (RFC #909 Ring 1 #910). +// Consumers should import it directly from `gitnexus-shared`, not via this barrel. // Type registry (classes, structs, interfaces, enums, records, impls) export { diff --git a/gitnexus/src/core/ingestion/model/method-registry.ts b/gitnexus/src/core/ingestion/model/method-registry.ts index be28e5782..327f568e7 100644 --- a/gitnexus/src/core/ingestion/model/method-registry.ts +++ b/gitnexus/src/core/ingestion/model/method-registry.ts @@ -7,7 +7,7 @@ * (array values) and arity-based filtering. */ -import type { SymbolDefinition } from './symbol-table.js'; +import type { SymbolDefinition } from 'gitnexus-shared'; // --------------------------------------------------------------------------- // Public read-only interface diff --git a/gitnexus/src/core/ingestion/model/registration-table.ts b/gitnexus/src/core/ingestion/model/registration-table.ts index a5bb14f21..6e0e2646d 100644 --- a/gitnexus/src/core/ingestion/model/registration-table.ts +++ b/gitnexus/src/core/ingestion/model/registration-table.ts @@ -49,8 +49,8 @@ * `NodeLabel` is missing from all three sets. */ -import type { NodeLabel } from 'gitnexus-shared'; -import type { SymbolDefinition, ClassLikeLabel, FreeCallableLabel } from './symbol-table.js'; +import type { NodeLabel, SymbolDefinition } from 'gitnexus-shared'; +import type { ClassLikeLabel, FreeCallableLabel } from './symbol-table.js'; import { FREE_CALLABLE_TYPES } from './symbol-table.js'; import type { MutableTypeRegistry } from './type-registry.js'; import type { MutableMethodRegistry } from './method-registry.js'; diff --git a/gitnexus/src/core/ingestion/model/resolution-context.ts b/gitnexus/src/core/ingestion/model/resolution-context.ts index b56524b36..45f94d698 100644 --- a/gitnexus/src/core/ingestion/model/resolution-context.ts +++ b/gitnexus/src/core/ingestion/model/resolution-context.ts @@ -18,7 +18,8 @@ * (three O(1) index lookups with a narrow, type-specific result set). */ -import type { SymbolDefinition, SymbolTableReader } from './symbol-table.js'; +import type { SymbolDefinition } from 'gitnexus-shared'; +import type { SymbolTableReader } from './symbol-table.js'; import type { MutableSemanticModel } from './semantic-model.js'; import { createSemanticModel } from './semantic-model.js'; diff --git a/gitnexus/src/core/ingestion/model/resolve.ts b/gitnexus/src/core/ingestion/model/resolve.ts index c05945b2d..62653a762 100644 --- a/gitnexus/src/core/ingestion/model/resolve.ts +++ b/gitnexus/src/core/ingestion/model/resolve.ts @@ -6,7 +6,7 @@ * on resolution-context.ts (circular dependency risk). */ -import type { SymbolDefinition } from './symbol-table.js'; +import type { SymbolDefinition } from 'gitnexus-shared'; import type { SemanticModel } from './semantic-model.js'; import type { HeritageMap } from './heritage-map.js'; import type { MroStrategy } from 'gitnexus-shared'; diff --git a/gitnexus/src/core/ingestion/model/semantic-model.ts b/gitnexus/src/core/ingestion/model/semantic-model.ts index deee4ad93..35a2628a5 100644 --- a/gitnexus/src/core/ingestion/model/semantic-model.ts +++ b/gitnexus/src/core/ingestion/model/semantic-model.ts @@ -53,12 +53,8 @@ import type { FieldRegistry, MutableFieldRegistry } from './field-registry.js'; import { createTypeRegistry } from './type-registry.js'; import { createMethodRegistry } from './method-registry.js'; import { createFieldRegistry } from './field-registry.js'; -import type { - SymbolTableReader, - SymbolTableWriter, - SymbolDefinition, - AddMetadata, -} from './symbol-table.js'; +import type { SymbolDefinition } from 'gitnexus-shared'; +import type { SymbolTableReader, SymbolTableWriter, AddMetadata } from './symbol-table.js'; import { createSymbolTable } from './symbol-table.js'; import { createRegistrationTable } from './registration-table.js'; diff --git a/gitnexus/src/core/ingestion/model/symbol-table.ts b/gitnexus/src/core/ingestion/model/symbol-table.ts index 75abb9731..c22f63acb 100644 --- a/gitnexus/src/core/ingestion/model/symbol-table.ts +++ b/gitnexus/src/core/ingestion/model/symbol-table.ts @@ -34,7 +34,7 @@ * logic up the dependency chain instead. */ -import type { NodeLabel } from 'gitnexus-shared'; +import type { NodeLabel, SymbolDefinition } from 'gitnexus-shared'; /** * Class-like NodeLabels — used for qualifiedName fallback inside @@ -113,28 +113,10 @@ export const CALL_TARGET_TYPES: ReadonlySet = new Set([ 'Constructor', ]); -export interface SymbolDefinition { - nodeId: string; - filePath: string; - type: NodeLabel; - /** Canonical dot-separated qualified type name for class-like symbols - * (e.g. `App.Models.User`). Falls back to the simple symbol name when no - * package/namespace/module scope exists or no explicit qualified metadata is provided. */ - qualifiedName?: string; - parameterCount?: number; - /** Number of required (non-optional, non-default) parameters. - * Enables range-based arity filtering: argCount >= requiredParameterCount && argCount <= parameterCount. */ - requiredParameterCount?: number; - /** Per-parameter type names for overload disambiguation (e.g. ['int', 'String']). - * Populated when parameter types are resolvable from AST (any typed language). */ - parameterTypes?: string[]; - /** Raw return type text extracted from AST (e.g. 'User', 'Promise') */ - returnType?: string; - /** Declared type for non-callable symbols — fields/properties (e.g. 'Address', 'List') */ - declaredType?: string; - /** Links Method/Constructor/Property to owning Class/Struct/Trait nodeId */ - ownerId?: string; -} +// `SymbolDefinition` moved to `gitnexus-shared` as part of RFC #909 Ring 1 +// (see #910). It is imported at the top of this file from `gitnexus-shared` +// and re-used unchanged throughout. Consumers should import +// `SymbolDefinition` directly from `gitnexus-shared`, not via this file. /** * Optional metadata accepted by {@link SymbolTable.add}. Kept as a separate diff --git a/gitnexus/src/core/ingestion/model/type-registry.ts b/gitnexus/src/core/ingestion/model/type-registry.ts index 95d52dbc1..3f9fdc5f4 100644 --- a/gitnexus/src/core/ingestion/model/type-registry.ts +++ b/gitnexus/src/core/ingestion/model/type-registry.ts @@ -6,7 +6,7 @@ * Also includes a separate index for Rust Impl blocks. */ -import type { SymbolDefinition } from './symbol-table.js'; +import type { SymbolDefinition } from 'gitnexus-shared'; // --------------------------------------------------------------------------- // Public read-only interface diff --git a/gitnexus/test/unit/model/field-registry.test.ts b/gitnexus/test/unit/model/field-registry.test.ts index 4c6e093d7..ff1f749b1 100644 --- a/gitnexus/test/unit/model/field-registry.test.ts +++ b/gitnexus/test/unit/model/field-registry.test.ts @@ -8,7 +8,7 @@ import { describe, it, expect } from 'vitest'; import { createFieldRegistry } from '../../../src/core/ingestion/model/field-registry.js'; -import type { SymbolDefinition } from '../../../src/core/ingestion/model/symbol-table.js'; +import type { SymbolDefinition } from 'gitnexus-shared'; import { makeDef as makeBaseDef } from './helpers.js'; const makeDef = (overrides: Partial = {}): SymbolDefinition => diff --git a/gitnexus/test/unit/model/helpers.ts b/gitnexus/test/unit/model/helpers.ts index 04856f8d3..00c5fef06 100644 --- a/gitnexus/test/unit/model/helpers.ts +++ b/gitnexus/test/unit/model/helpers.ts @@ -6,7 +6,7 @@ * test file that uses it. */ -import type { SymbolDefinition } from '../../../src/core/ingestion/model/symbol-table.js'; +import type { SymbolDefinition } from 'gitnexus-shared'; /** * Build a {@link SymbolDefinition} with sensible defaults. Every field diff --git a/gitnexus/test/unit/model/registration-table.test.ts b/gitnexus/test/unit/model/registration-table.test.ts index 067b7fc20..fe37d0bbb 100644 --- a/gitnexus/test/unit/model/registration-table.test.ts +++ b/gitnexus/test/unit/model/registration-table.test.ts @@ -9,7 +9,7 @@ import { createTypeRegistry } from '../../../src/core/ingestion/model/type-regis import { createMethodRegistry } from '../../../src/core/ingestion/model/method-registry.js'; import { createFieldRegistry } from '../../../src/core/ingestion/model/field-registry.js'; import { ALL_NODE_LABELS } from '../../../src/core/ingestion/model/index.js'; -import type { SymbolDefinition } from '../../../src/core/ingestion/model/symbol-table.js'; +import type { SymbolDefinition } from 'gitnexus-shared'; import { makeDef as makeBaseDef } from './helpers.js'; // --------------------------------------------------------------------------- diff --git a/gitnexus/test/unit/model/type-registry.test.ts b/gitnexus/test/unit/model/type-registry.test.ts index 8f0eee838..9eaf61c4e 100644 --- a/gitnexus/test/unit/model/type-registry.test.ts +++ b/gitnexus/test/unit/model/type-registry.test.ts @@ -10,7 +10,7 @@ import { describe, it, expect } from 'vitest'; import { createTypeRegistry } from '../../../src/core/ingestion/model/type-registry.js'; -import type { SymbolDefinition } from '../../../src/core/ingestion/model/symbol-table.js'; +import type { SymbolDefinition } from 'gitnexus-shared'; import { makeDef as makeBaseDef } from './helpers.js'; const makeDef = (overrides: Partial = {}): SymbolDefinition => diff --git a/gitnexus/test/unit/type-env.test.ts b/gitnexus/test/unit/type-env.test.ts index 27f449f91..dffbc047e 100644 --- a/gitnexus/test/unit/type-env.test.ts +++ b/gitnexus/test/unit/type-env.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, vi } from 'vitest'; import { buildTypeEnv, type TypeEnvironment } from '../../src/core/ingestion/type-env.js'; import { BindingAccumulator } from '../../src/core/ingestion/binding-accumulator.js'; -import { type SymbolDefinition } from '../../src/core/ingestion/model/symbol-table.js'; +import { type SymbolDefinition } from 'gitnexus-shared'; import { createSemanticModel, type SemanticModel,