From 989681bbd2e4b23a16453c3e81ab3c15491ffd7d Mon Sep 17 00:00:00 2001 From: ReidenXerx Date: Thu, 6 Aug 2026 16:35:13 +0300 Subject: [PATCH] fix(lbug): declare TypeAlias member pairs so analyze does not abort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Making object-type aliases member owners emits HAS_PROPERTY from a `TypeAlias`, and the relation schema declared no such pair. The emit therefore threw `UndeclaredRelationPairError` and the ENTIRE analyze died on any repo containing `type X = { ... }` — a hard stop, not a dropped edge. Found by running the analyzer over a real 16k-node TypeScript repo, not by a test. `Method` is declared alongside `Property`: a member written `type Handler = { onClick(): void }` is a method_signature and would fail in exactly the same way. Why every existing test missed it: the resolver suites build an in-memory graph via `runPipelineFromRepo` and never write to LadybugDB, so the schema constraint was never exercised. `structural-pair-coverage.test.ts` is the one suite that does run the emitters against the declared pairs — and its own docstring names the gap: coverage is bounded by NON_BRIDGE_CORPUS, "a new structural emitter should land with an entry here". This adds that entry, pinning TypeAlias|Property and Interface|Property as sentinels. Verified the guard is not vacuous: removing the pair again makes the suite fail with undeclaredPairs: ["TypeAlias|Property"]. Co-Authored-By: Claude Opus 5 (1M context) --- gitnexus/src/core/lbug/schema.ts | 2 ++ .../integration/structural-pair-coverage.test.ts | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/gitnexus/src/core/lbug/schema.ts b/gitnexus/src/core/lbug/schema.ts index 0b0c27e6b..4d6b490de 100644 --- a/gitnexus/src/core/lbug/schema.ts +++ b/gitnexus/src/core/lbug/schema.ts @@ -492,6 +492,8 @@ export const STRUCTURAL_PAIR_DDL = ` FROM File TO Folder, FROM \`Impl\` TO \`Impl\`, FROM \`TypeAlias\` TO \`Trait\`, FROM \`TypeAlias\` TO Class, + FROM \`TypeAlias\` TO \`Property\`, + FROM \`TypeAlias\` TO Method, FROM \`Record\` TO Method, FROM \`Record\` TO \`Constructor\`, FROM \`Record\` TO \`Property\`, diff --git a/gitnexus/test/integration/structural-pair-coverage.test.ts b/gitnexus/test/integration/structural-pair-coverage.test.ts index 0d525fc2f..09226d0d4 100644 --- a/gitnexus/test/integration/structural-pair-coverage.test.ts +++ b/gitnexus/test/integration/structural-pair-coverage.test.ts @@ -109,6 +109,18 @@ const NON_BRIDGE_CORPUS = [ emitter: 'tools-phase HANDLES_TOOL', sentinels: ['Class|Tool'], }, + { + // A TypeScript object-type alias owns its members, so it emits + // HAS_PROPERTY from a `TypeAlias` — a label on the ELEVEN-table list this + // suite exists for, and one no rule reaches. Shipped once without the pair + // declared: emit threw `UndeclaredRelationPairError` and the whole analyze + // died on any repo containing `type X = { ... }`. Every resolver test still + // passed, because they build an in-memory graph and never write to the DB — + // this suite is the only place that difference shows up. + fixture: 'typescript-alias-fields', + emitter: 'object-type alias HAS_PROPERTY', + sentinels: ['TypeAlias|Property', 'Interface|Property'], + }, ] as const satisfies readonly CorpusEntry[]; /*