Skip to content

fix(crossrepo): treat only "::" as a namespace marker - #82

Merged
dejo1307 merged 1 commit into
mainfrom
fix/crossrepo-nested-types-fabricate-dependency
Jul 9, 2026
Merged

fix(crossrepo): treat only "::" as a namespace marker#82
dejo1307 merged 1 commit into
mainfrom
fix/crossrepo-nested-types-fabricate-dependency

Conversation

@dejo1307

@dejo1307 dejo1307 commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

linkSharedSymbols guards against linking two repos in different languages that merely share a domain type name. The guard is skipped for identities it considers namespace-qualified, and isQualifiedIdentity counted any dot as qualifying.

By the time it runs, typeIdentity has already stripped the module prefix, so a residual dot means type nesting, not a namespace. Kotlin and Swift both emit nested declarations as "Outer.Inner". Two apps that model the same product in different languages therefore cleared minSharedSymbols on nested names alone, bypassed the guard, and were given a bidirectional depends_on -- a 2-cycle in the service graph, and an edge no parser justifies. traverse, find_path and impact_analysis route through it, and coverage_report overstates each app's outbound edge count.

Replace isQualifiedIdentity with isNamespaceQualified, matching "::" only, at both call sites: the same-language guard and the isDistinctiveIdentity short-circuit. Nested identities are now unqualified, so they fall under the language guard and under the length/generic-name filters.

Coverage:

  • TestComputeLinks_SharedSymbolsCrossLanguageNestedTypesSkipped, which failed before this change with the exact bidirectional pair.
  • TestComputeLinks_SharedSymbolsSameLanguageNestedTypesLink, guarding the over-correction: a nested identity is now unqualified and so newly depends on the language guard; same-language repos must still link.
  • testdata/repos/kotlin_swift_multirepo, the first golden fixture pairing two different-language repos. The bug lives between what the extractors name symbols and what the linker assumes a dot means, and every input in crossrepo_test.go is a hand-built fact, so no synthetic-fact test can reach it. Verified by reinstating the bug and watching the golden fail.

No cacheVersion bump: linkCrossRepo runs after runExtractors and after the extractor cache is saved, so no extractor output changes. The linker's synthetic facts do land in facts.jsonl, so goldens were regenerated; the pre-existing 16 are byte-identical.

linkSharedSymbols guards against linking two repos in different languages
that merely share a domain type name. The guard is skipped for identities
it considers namespace-qualified, and isQualifiedIdentity counted any dot
as qualifying.

By the time it runs, typeIdentity has already stripped the module prefix,
so a residual dot means type nesting, not a namespace. Kotlin and Swift
both emit nested declarations as "Outer.Inner". Two apps that model the
same product in different languages therefore cleared minSharedSymbols on
nested names alone, bypassed the guard, and were given a bidirectional
depends_on -- a 2-cycle in the service graph, and an edge no parser
justifies. traverse, find_path and impact_analysis route through it, and
coverage_report overstates each app's outbound edge count.

Replace isQualifiedIdentity with isNamespaceQualified, matching "::" only,
at both call sites: the same-language guard and the isDistinctiveIdentity
short-circuit. Nested identities are now unqualified, so they fall under
the language guard and under the length/generic-name filters.

Coverage:
  - TestComputeLinks_SharedSymbolsCrossLanguageNestedTypesSkipped, which
    failed before this change with the exact bidirectional pair.
  - TestComputeLinks_SharedSymbolsSameLanguageNestedTypesLink, guarding
    the over-correction: a nested identity is now unqualified and so newly
    depends on the language guard; same-language repos must still link.
  - testdata/repos/kotlin_swift_multirepo, the first golden fixture pairing
    two different-language repos. The bug lives between what the extractors
    name symbols and what the linker assumes a dot means, and every input in
    crossrepo_test.go is a hand-built fact, so no synthetic-fact test can
    reach it. Verified by reinstating the bug and watching the golden fail.

No cacheVersion bump: linkCrossRepo runs after runExtractors and after the
extractor cache is saved, so no extractor output changes. The linker's
synthetic facts do land in facts.jsonl, so goldens were regenerated; the
pre-existing 16 are byte-identical.
@dejo1307
dejo1307 merged commit d60547e into main Jul 9, 2026
4 checks passed
@dejo1307
dejo1307 deleted the fix/crossrepo-nested-types-fabricate-dependency branch July 18, 2026 06:54
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.

1 participant