From 6664e5c0a5b85a13b407ab80962d833486850160 Mon Sep 17 00:00:00 2001 From: ReidenXerx Date: Thu, 6 Aug 2026 03:02:38 +0300 Subject: [PATCH] docs(test): record the traced diagnosis for the unlinked alias field edge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Traced to the end rather than left as "needs investigation", so the next attempt starts from facts: 1. Graph side is COMPLETE and symmetric with the interface — Property:...:LiveModeConfig.bookSlots is owner-qualified and carries HAS_PROPERTY. 2. Resolution DOES reach resolveClassBindingForName('LiveModeConfig') (instrumented) and misses. 3. It misses because the module scope binds LiveModeIface:Interface, renderAlias, renderIface — and not LiveModeConfig. The alias has no binding on the receiver's scope chain at all. 4. The TS scope query tags aliases @declaration.type, but normalizeNodeLabel accepts only typealias / type_alias and has no "type" case, so it returns undefined. Kotlin and Dart use @declaration.type_alias; TypeScript is alone on the dead tag. 5. Retagging is NECESSARY BUT NOT SUFFICIENT — tried, and the binding still does not appear, so a second gate exists in how a declaration anchored on a node that is ALSO a @scope.class anchor is attached: the alias appears to bind inside its own scope rather than hoisting to Module, where interface_declaration evidently does hoist. An isShapeLike predicate (the nominal-vs-structural split: shapes declare members, nominal types participate in MRO) plus a mirrored findShapeBindingInScope were built and REVERTED along with the retag. With no binding on the chain they never fire, and shipping inert widening is worse than shipping none — the same standard applied to the earlier scope-index attempt. The design is recorded here; it is worth doing once step 5 is fixed, and it also unblocks Rust's parked union_item, which the MEMBER_OWNER_NODE_TYPES comment documents as the same gap in another language. Co-Authored-By: Claude Opus 5 (1M context) --- .../resolvers/typescript-alias-fields.test.ts | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/gitnexus/test/integration/resolvers/typescript-alias-fields.test.ts b/gitnexus/test/integration/resolvers/typescript-alias-fields.test.ts index d896c68dc..c21daf336 100644 --- a/gitnexus/test/integration/resolvers/typescript-alias-fields.test.ts +++ b/gitnexus/test/integration/resolvers/typescript-alias-fields.test.ts @@ -77,15 +77,31 @@ describe('TypeScript type-alias and interface members (A4)', () => { expect(readersOf('ifaceSlots')).toContain('renderIface'); }); - // The ALIAS half still does not link, and the remaining blocker is now - // exact: resolving `cfg: LiveModeConfig` to its members requires the name - // `LiveModeConfig` to resolve to a CLASS-LIKE def, and `isClassLike` is - // Class|Interface|Struct|Record|Enum|Trait — no TypeAlias. That predicate is - // consulted from ~12 sites including MRO and heritage, and every language - // mints TypeAlias (Rust type_item, Kotlin/Swift/Dart typealias, C typedef), - // so widening it would enrol aliases in linearization where they do not - // belong. Widening only the scope index was tried and is NOT sufficient — - // the type-name walkers gate on it independently. Needs a deliberate - // "shape-like" concept rather than more call-site widening. + // ALIAS field -> consumer is still unlinked. Diagnosis, traced to the end so + // the next attempt starts from facts rather than from this list again: + // + // 1. The graph side is COMPLETE and symmetric with the interface: + // `Property:contracts.ts:LiveModeConfig.bookSlots` is owner-qualified + // and carries `HAS_PROPERTY LiveModeConfig->bookSlots`. + // 2. Resolution enters `resolveClassBindingForName('LiveModeConfig')` + // (verified by instrumentation) and misses. + // 3. It misses because the module scope binds `LiveModeIface:Interface`, + // `renderAlias`, `renderIface` — and NOT `LiveModeConfig`. The alias has + // no binding on the receiver's scope chain at all. + // 4. The TS scope query tags aliases `@declaration.type`, but + // `normalizeNodeLabel` accepts only `typealias` / `type_alias` and has + // no `type` case, so it returns undefined. Kotlin and Dart use + // `@declaration.type_alias`; TypeScript is alone on the dead tag. + // 5. Retagging it to `@declaration.type_alias` is NECESSARY BUT NOT + // SUFFICIENT — tried, and the binding still does not appear on the + // chain, so a second gate exists in how a declaration anchored on a + // node that is ALSO a `@scope.class` anchor gets attached (the alias + // appears to bind inside its own scope instead of hoisting to Module, + // where `interface_declaration` evidently does hoist). + // + // A widened predicate (`isShapeLike`) plus a mirrored + // `findShapeBindingInScope` were also built and REVERTED: with no binding on + // the chain they never fire, and shipping inert widening is worse than none. + // Fix step 5 first; the rest is then a small, testable change. it.todo('links an alias field to its consumer'); });