GitNexus/gitnexus/test/unit/scope-resolution
Gergo Magyar d5e9c8e650 fix(resolution): stop the fold fabricating edges, and harden the epistemic lookup
Addresses every finding from the multi-engine review of this PR.

P0 — THE FOLD FABRICATED A CALLS EDGE.
`foldReceiverChain` resolved its base through `resolveCompoundReceiverClass`,
whose bare-identifier branch falls through to a plain class-name lookup EVEN
WHEN a receiver typeBinding exists but names no class. The dotted-chain head
is deliberately narrower — it consults the class namespace only when there is
no binding at all. So a local that merely SHADOWS a class name was typed as
that class:

    const Config = make(1);   // a number
    Config.db.query();        // emitted entry -> Database.query

A/B, reverting only the fold wiring:
    with fold:     ["entry -> query", "entry -> make", "Config -> Database"]
    without fold:  ["entry -> make", "Config -> Database"]

A confident wrong edge, and a direct violation of R4 — the one outcome this
whole line of work exists to prevent. Fixed with an opt-in `strictBaseBinding`
that makes the fold's base obey the same rule as the cascade's head. The flag
is OFF for the cascade, so no existing edge moves; measured, every shape that
resolved before still resolves and no other language's drop count changed.

P0 — `impact()` INTERPOLATED A FUNCTION INTO USER-FACING TEXT.
`summary?.counts?.[symName]` walks `Object.prototype`, so `constructor`,
`toString`, `valueOf`, `hasOwnProperty` and friends returned a Function rather
than `undefined` — and `NaN <= 0` is false, so the `<= 0` guard let it through:

    impact({target: "constructor"})
      -> "function Object() { [native code] } call sites invoking `constructor`…"

plus a bogus `epistemic: 'lower-bound'`. `constructor` is an ordinary member
name in a code graph, so this was reachable in normal use. The lookup is now one
exported, prototype-safe helper (`lookupUnresolvedCallCount`) that both the
backend and its test use, instead of an inline index expression.

P1 — BOTH SCHEMA CONSTANTS WERE BUMPED BEFORE THE FINAL DIVERGENCE.
`SCHEMA_BUMP` 32 landed at the TypeScript-only commit and `INCREMENTAL_SCHEMA_VERSION`
26 before the fold's semantics were final, but the rollout to the other 13
languages then changed captures AND edges under the same numbers. An index or
cache stamped by an intermediate build was therefore treated as current at HEAD
while serving pre-rollout captures for 13 languages and the fabricated edges
above. Re-bumped to 33 / 27 so each number tracks the FINAL state rather than
the first divergence, with the reuse-gate ladder updated to match.

P2 — the summary counted property reads and writes as "call sites". It now
filters on the `siteKind` this series added for exactly that purpose. On the
fixture corpus that is 25 of 124 drops, so names whose CALL count was never
short no longer report `lower-bound`, and the consumer's "N call sites invoking
X" is now literally true.

P2 — two tests did not test what they claimed. The negative assertion named a
member (`noSuchMember`) that appeared nowhere else in the repo, so it could not
fail; it now uses a chain with a genuinely broken middle step and asserts the
tail does not bind while the head still does. And "resolves a mixed call/field
chain through the fold" used a shape the pre-existing cascade already handled —
it now uses an optional-chained spelling, verified to FAIL with the fold
reverted.

P3s: stale "NOT WIRED" JSDoc removed (it was wired 71 lines below); the
zero-width character class added to `isEncodableSegment` (`\s` misses U+200B-F
and U+FEFF, a trojan-source vector that would encode, persist, then silently
match nothing); the unreachable `?? ''` replaced; the store sanitizer's doc no
longer claims parity with `sanitizeCallableFlowSites` it does not have; the
truncation marker documented as a reserved forward-compatible contract rather
than live; `--check`'s scope stated plainly so a green run is not read as a
performance guard; and the orphaned "current stamp passes the gate" comment and
its duplicate assertion removed.

Test gaps closed: behavioural proof for a SECOND language (`cpp-receiver-chain-arrow`,
the `->` base the rollout actually fixed, with the value-dot control that shows
why `cpp-chain-call/` could never catch it); the `hoistTypeBindingsToModule: false`
branch that six wired languages run; adversarial payloads through
`decodeReceiverChain`; the MAX_CHAIN_DEPTH boundary that must still WORK; and
per-field sanitation proven to leave a VALID sibling's chain intact.

Every regression test was verified to fail without its fix.

4412 tests green, tsc clean in both packages, all bench gates pass.
2026-07-30 18:51:54 +00:00
..
c fix(scope-resolution): resolve callable reference flows (#2437) (#2522) 2026-07-17 17:20:02 +01:00
cpp fix(scope-resolution): resolve callable reference flows (#2437) (#2522) 2026-07-17 17:20:02 +01:00
csharp fix(csharp): qualified/alias constructor names, : base/: this initializers, generic type-arg strip (#2046) 2026-06-05 07:04:57 +01:00
go fix(go): capture multi-name declarations (#2032) 2026-06-06 04:47:17 +01:00
java fix(java): JLS binary-name identities for local classes, enums, records & interfaces (#2562) (#2653) 2026-07-24 11:58:53 +01:00
javascript fix(scope-resolution): resolve callable reference flows (#2437) (#2522) 2026-07-17 17:20:02 +01:00
php fix(scan): lock in Rust publish order and guard PHP suffix roots 2026-07-16 08:42:07 +00:00
python fix(python): resolve calls through constructor-injected fields (#2628) 2026-07-22 16:32:53 +01:00
ruby perf(ingestion): linearize scope-capture across all languages + Python import resolution (O(n²)→O(n)) (#1918) 2026-05-30 19:44:22 +01:00
rust fix(rust): qualify items by their enclosing mod chain so same-named ones stay distinct (#2742) (#2745) 2026-07-30 17:08:00 +01:00
swift fix(ingestion): migrate all languages' inheritance to scope-resolution on the worker path (#1951) (#1956) 2026-06-01 17:04:27 +01:00
typescript fix(scope-resolution): resolve callable reference flows (#2437) (#2522) 2026-07-17 17:20:02 +01:00
callable-flow-captures.test.ts fix(scope-resolution): resolve callable reference flows (#2437) (#2522) 2026-07-17 17:20:02 +01:00
callable-value-flow-worklist.test.ts fix(scope-resolution): resolve callable reference flows (#2437) (#2522) 2026-07-17 17:20:02 +01:00
callable-value-target-index.test.ts fix(scope-resolution): parse def coordinates after file paths (#2743) 2026-07-30 07:34:32 +01:00
construction-syntax-wiring.test.ts fix(resolution): type inline constructor receivers in every spelling (#2708) (#2737) 2026-07-29 16:19:53 +01:00
def-index.test.ts feat(shared): DefIndex / ModuleScopeIndex / QualifiedNameIndex (#913, RFC #909 Ring 2 SHARED) (#958) 2026-04-18 15:59:34 +01:00
definition-id.test.ts fix(scope-resolution): parse def coordinates after file paths (#2743) 2026-07-30 07:34:32 +01:00
emit-references.test.ts feat(ingestion): emit-references drains ReferenceIndex to graph edges (#925, RFC #909 Ring 2 PKG) (#973) 2026-04-18 23:36:10 +01:00
finalize-algorithm.test.ts feat(ingestion): TypeScript registry-primary scope resolution (Ring 3) (#1050) 2026-04-26 08:23:08 +01:00
finalize-orchestrator.test.ts fix(scope-resolution): avoid variadic reference site aggregation (#1112) 2026-04-27 12:44:21 +01:00
import-target-adapter.test.ts feat(ingestion): per-language resolveImportTarget adapter (#922, RFC #909 Ring 2 PKG) (#971) 2026-04-18 21:11:24 +01:00
imported-return-types.test.ts fix(ingestion): two-channel binding lifecycle (closes #1066) + scope-resolution I8 hardening (#1082) 2026-04-26 12:16:09 +01:00
method-dispatch-index.test.ts chore(shared): apply Ring 2 SHARED review follow-ups in one diff (#964) 2026-04-18 18:40:29 +01:00
module-scope-index.test.ts feat(shared): DefIndex / ModuleScopeIndex / QualifiedNameIndex (#913, RFC #909 Ring 2 SHARED) (#958) 2026-04-18 15:59:34 +01:00
namespace-channel-lookup.test.ts fix(csharp): eliminate global-namespace typeBindings O(files²) OOM (#1871) (#1954) 2026-05-31 18:21:07 +01:00
node-lookup-determinism.test.ts fix(ingestion): canonicalize parse node insertion 2026-07-16 09:21:38 +07:00
overload-narrowing.test.ts feat(cpp): sfinae filter (#1623) 2026-05-16 20:23:13 +01:00
parse-worker-scope-integration.test.ts fix(php): synthesize module scope for namespace-less PHP files (.phtml) (#1801) 2026-05-24 20:37:17 +01:00
pick-implicit-this-overload.test.ts feat(php): migrate PHP to scope-based resolution model (#938) [supersedes #1124] (#1497) 2026-05-12 16:56:31 +01:00
pick-unique-global-callable.test.ts perf(ingestion): Linux-kernel-scale analysis — worker-pool parse + finalize O(n²) + scope-resolution memory wall (#1983) (#2038) 2026-06-06 22:46:34 +01:00
pick-unique-global-class.test.ts feat(swift): migrate Swift to scope-based registry resolution (#937) (#1948) 2026-05-31 16:56:47 +01:00
position-index.test.ts chore(shared): apply Ring 2 SHARED review follow-ups in one diff (#964) 2026-04-18 18:40:29 +01:00
qualified-name-index.test.ts chore(shared): apply Ring 2 SHARED review follow-ups in one diff (#964) 2026-04-18 18:40:29 +01:00
receiver-chain-fold.test.ts fix(resolution): stop the fold fabricating edges, and harden the epistemic lookup 2026-07-30 18:51:54 +00:00
receiver-chain-wiring.test.ts feat(languages): roll the receiver chain out to every emitter 2026-07-30 18:21:31 +00:00
reconcile-ownership.test.ts fix(cpp): suppress deleted overload winners (#2094) 2026-06-10 18:41:30 +01:00
registries.test.ts perf(scope-resolution): use owner-keyed lookup for Step 2 member resolution (#1657) 2026-05-18 13:14:27 +01:00
resolve-ambiguous-inheritance-base.test.ts fix(ingestion): migrate all languages' inheritance to scope-resolution on the worker path (#1951) (#1956) 2026-06-01 17:04:27 +01:00
resolve-references.test.ts perf(scope-resolution): use owner-keyed lookup for Step 2 member resolution (#1657) 2026-05-18 13:14:27 +01:00
resolve-type-ref.test.ts chore(shared): apply Ring 2 SHARED review follow-ups in one diff (#964) 2026-04-18 18:40:29 +01:00
run-progress.test.ts feat(progress): add per-language progress reporting to scope-resolution phase (#1813) 2026-05-25 11:53:54 +01:00
scope-extractor.test.ts fix(scope-resolution): resolve callable reference flows (#2437) (#2522) 2026-07-17 17:20:02 +01:00
scope-id.test.ts feat(shared): ScopeTree + PositionIndex + makeScopeId (#912, RFC #909 Ring 2 SHARED) (#961) 2026-04-18 16:41:38 +01:00
scope-source-content-policy.test.ts feat(spring): build bean candidate inventory (#2494) 2026-07-20 09:28:23 +01:00
scope-tree.test.ts fix(scope-resolution): allow same-range Module-as-parent for top-level scopes (closes #1086) (#1087) 2026-04-27 11:06:54 +01:00
strip-cast-wrappers.test.ts fix: Java cast-wrapped and this.method() call edges (#2357) 2026-07-02 17:19:33 +01:00
unresolved-receivers.test.ts fix(resolution): stop the fold fabricating edges, and harden the epistemic lookup 2026-07-30 18:51:54 +00:00
validate-bindings-immutability.test.ts fix(csharp): eliminate global-namespace typeBindings O(files²) OOM (#1871) (#1954) 2026-05-31 18:21:07 +01:00
walkers-augmentations.test.ts fix(scope-resolution): gate C#/Kotlin free calls by instance ownership (#2563) (#2654) 2026-07-24 13:31:56 +01:00
workspace-index.test.ts fix(ingestion): classify Python class methods as Method (#1102) 2026-04-27 09:04:50 +01:00