* Union HTTP graph and source contracts
* test(group): Document HTTP source union follow-ups
---------
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
* fix(eval-server): localhost now doesn't normalize into IPv4 instead lets OS decide which to bind
* fix(eval-server): EADDRNOTAVAIL now treats as potential IPv6
* test(eval-server): new integration test for --host localhost
* docs(eval-server): updated eval/README.md based on latest update
* fix(eval-server): clarify EADDRNOTAVAIL diagnostic, guard server.address(), and soften localhost docs
* fix(ingestion): surface skipped large-file paths by default (#1659)
The 512 KB skip threshold in filesystem-walker is necessary, but the
existing warning only said "Skipped N large files" with no paths unless
GITNEXUS_VERBOSE=1 was set. In a repo with one or two oversized first-
party source files (e.g. a 17K-line cron handler), every IMPORTS/CALLS
edge from that file silently disappeared and the surface looked like a
Python resolver bug. Issue #1659 was filed against the resolver for
exactly that reason, but the resolver was fine; the file was being
dropped before parse.
Changes:
* Always print up to 5 skipped paths after the count line.
* If more than 5 were skipped, append "...and N more" with a hint to
set GITNEXUS_VERBOSE=1 for the full list.
* When running at the default threshold, emit a one-line hint about
GITNEXUS_MAX_FILE_SIZE=<KB> so operators know how to widen it.
* Cover the new behavior with three additional tests in the existing
filesystem-walker integration suite, plus a new describe block for
the >5 preview-cap case.
Verified end-to-end on a 680-file Python repo that hit #1659: before
the patch, "Skipped 3 large files (>512KB, ...)" was the only signal
and impact upstream of a function called from cron.py returned 1 of 5
real callers; after the patch the cron file is listed by name with the
hint, and running with GITNEXUS_MAX_FILE_SIZE=1024 brings the missing
callers back (impactedCount 1 -> 9).
* fix(ingestion): address #1661 adversarial review follow-ups (F1/F2/F3)
Three non-blocking nits flagged by the adversarial review on #1661:
F1 (output stability) — skippedLargePaths was populated by concurrent
fs.stat callbacks in batches of 32, so push order within a batch was
completion-order rather than input-order. The default preview's "first
5" could vary across runs on the same repo. Fix: sort the array before
slicing. New test asserts the verbose output is in sorted order.
F2 (boundary coverage) — the preview-cap describe block created 8
large files, so the SKIPPED_PREVIEW_CAP = 5 comparison was never
exercised at the exact <= boundary. A future off-by-one (<= → <) would
not fail the suite. Fix: add two tests, one with exactly 5 files (all
listed, no truncation) and one with exactly 6 files (5 listed plus
"...and 1 more").
F3 (hint accuracy) — isDefault compared effective bytes, so an
operator who explicitly set GITNEXUS_MAX_FILE_SIZE=512 (the same KB as
the default) would still see the "Set GITNEXUS_MAX_FILE_SIZE=<KB>..."
hint. Fix: gate the hint on whether the env var is unset, not on the
resulting byte value. New test pins the explicit-default-value case.
All 34 filesystem-walker tests pass (was 30; +4 new). Prettier clean,
typecheck clean for the changed files.
---------
Co-authored-by: scotjelinski <58397194+scotjelinski@users.noreply.github.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
* fix(detect-changes): guard resolveWorktreeCwd against overriding a separately-indexed worktree
When the repo registry entry points to a linked worktree (both main
checkout and worktree indexed separately), resolveWorktreeCwd was
incorrectly replacing the correct worktree repoPath with the server's
main-checkout launch directory. Both share the same canonical root so
the existing same-repo check passed, causing git diff to run from the
wrong directory and return 0 changes (issue #1659).
Fix: early-exit guard — if tryRealpath(repoPath) differs from
tryRealpath(getCanonicalRepoRoot(repoPath)), repoPath is itself a
linked worktree and is returned unchanged. Auto-detection only fires
when repoPath equals the canonical main-checkout root.
Also normalises the launchCanonical comparison in the auto-detect path
to use tryRealpath for cross-platform consistency.
Regression test: 'returns worktreeDir unchanged when repoPath IS a
linked worktree and launchCwd is the main checkout'.
* test(detect-changes): add worktreeA→worktreeB case and assumption comment
Cover the missing case from the production-readiness review:
repoPath = wt-A (indexed), launchCwd = wt-B (server on a different
linked worktree). The guard fires on repoPath being a worktree
regardless of launchCwd, so wt-A is returned unchanged.
Also add an inline comment documenting the assumption that repoPath
is a git root or linked-worktree root (not an arbitrary subdirectory),
as noted in Finding 2 of the review.
* refactor(detect-changes): validate repoPath is a git root before canonical comparison
Instead of relying on a comment asserting repoPath is always a git
root, call getGitRoot(repoPath) first. Only if the result matches
repoPath itself do we call getCanonicalRepoRoot and apply the guard.
This eliminates the over-classification risk for subdirectory repoPath
values and makes the assumption explicit in code. repoCanonical is
shared across both the guard and the auto-detect block.
---------
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
* fix(lbug): probe-then-load FTS extension on Windows (#1690)
The Windows skip-on-process.platform==='win32' guard in pool-adapter.ts
hard-skipped loadFTSExtension() for every Windows host, even when the
FTS extension binary was already present locally at
~/.lbdb/extension/<version>/win_amd64/fts/libfts.lbug_extension.
That left BM25 silently degraded on Windows hosts that had a working
extension on disk, with no error path — `gitnexus doctor` still reported
FTS as available, but query returned 0 BM25 hits.
This patch adds hasLocalWinFtsExtension() which probes
~/.lbdb/extension/*/win_amd64/fts/ before the Windows skip. When a binary
is on disk we call loadFTSExtension(..., { policy: 'load-only' }); the
crashing install path documented in #1199 / #1217 is never exercised at
query time, and LadybugDB's version-specific resolution combined with
the ExtensionManager's tryLoad try/catch handles stale or zero-byte
sibling version dirs cleanly (no dlopen attempted on a stale binary).
When no binary is on disk at all, we fall back to the upstream skip so
install-time SIGSEGV continues to be avoided.
Verified on Windows 10 + Node 22.19.0 + gitnexus 1.6.5 +
@ladybugdb/core 0.16.1 with the FTS extension cached at 0.16.0:
* BM25 timing goes from 0 → ~250-326ms on previously-zero queries
* gitnexus context / impact / cypher unaffected
* Adversarial-mixed-state run (real 0.16.0 binary + zero-byte stubs at
0.15.0, 0.16.1, 0.17.0): exits 0, no SIGSEGV, FTS resolves to the
real 0.16.0 binary, BM25 returns real hits
* Stub-only state at the resolution path (0.16.0, zero-byte): exits 0,
emits "FTS extension unavailable; load-only policy: extension not
pre-installed", FTS marked unavailable cleanly via markUnavailable
in extension-loader.ts — no silent greenlight
Closes#1690
* test(lbug): cover hasLocalWinFtsExtension probe + format pool-adapter
- Export hasLocalWinFtsExtension and add lbug-pool-win-fts-probe.test.ts
with 7 cases against a real tmpdir + os.homedir spy:
* missing ~/.lbdb/extension dir -> false
* extension root present but no version dirs -> false
* one version dir with binary present -> true
* zero-byte stub at probe path -> true (LOAD failure handled downstream)
* multi-version with binary only in a non-first dir -> true
* multi-version with no binary anywhere (Nix/Bazel/MDM tree) -> false
* fs.readdir throws (EACCES) -> false
The Windows conditional in doInitLbug / initLbugWithDb is intentionally
not unit-isolated: it reduces to `probe ? load : true` over a fully
constructed lbug.Database + Connection pool, which the
test/integration/lbug-pool*.test.ts suites already exercise on the
windows-latest CI matrix.
- Apply prettier format to the fs.stat() call in pool-adapter.ts,
resolving the quality/format CI failure surfaced by gitnexus/autofix.
Addresses DoD §2.7 test-coverage blocker raised in the production-
readiness review on #1692, and the dir-exists-no-file regression case
raised on #1690.
Refs #1690.
---------
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
ipKeyGenerator('') returned '' as the rate-limit key when both req.ip and
req.socket?.remoteAddress were undefined, silently merging all anonymous
requests into an empty-string bucket instead of the intended 'unknown' sentinel.
Switch to a conditional: only call ipKeyGenerator when an IP is present,
otherwise fall back to 'unknown'. Restores the IPv6 /56 normalisation
comment dropped in aa36869 (see issue #1360).
* feat(eval-server): added --host for user configured host IP instead of system hardcoded IP (127.0.0.1)
* fix(eval-server): localhost value in --host now returns 127.0.0.1 instead of the raw input to fix wrong address, handled error for ipv6 disabled containers
* feat(eval-server): add --host flag with validation and error handling
Co-Authored-By: Val Vladescu <val.vladescu@thirdbridge.com>
* fix(eval-server): bracketed IPv6 addresses to remove ambiguity
* docs(eval-server): document --host flag, READY signal format, and parser migration note
* fix(eval-server): use actual bound port in READY signal; strengthen --host e2e tests
Co-Authored-By: Val Vladescu <val.vladescu@thirdbridge.com>
* feat(eval): wire eval-server --host through gitnexus_docker.py
* docs(eval): added guidance for docker user
* docs(eval): revise the imprecise documentation
* fix(e2e): updated original stdout for new format
* perf(scope-resolution): use owner-keyed lookup for Step 2 member resolution (#1656)
* chore(autofix): apply prettier + eslint fixes via /autofix command
* fix(scope-resolution): index Const/Static in FieldRegistry for Step 2 lookup
Extend FieldRegistry to hold multiple defs per (owner, name), reconcile Const and Static into the owner-keyed index, and wire lookupAllByOwner through the production hook so Step 2 does not drop field kinds the registry never indexed. Pass explicitReceiver on read/write reference sites and document undefined-vs-empty hook semantics for defs fallback.
Co-authored-by: Cursor <cursoragent@cursor.com>
* perf(scope-resolution): centralize O(1) owned-member hook and guard hot path
Extract lookupOwnedMembersByOwner for the production Step 2 hook so merges stay O(1) per registry with no defs.byId scan. Add a perf-contract unit test that throws if byId.values runs when the hook is wired. Reuse a frozen empty sentinel on double miss to avoid per-probe allocations.
Co-authored-by: Cursor <cursoragent@cursor.com>
* chore: drop unused buildFieldRegistry import
* chore(scope-resolution): apply ce-code-review safe_auto fixes
- Drop unreachable return + unused values() capture in perf-contract trap (Finding #7)
- Type lookupOwnedMembersByOwner ownerDefId as DefId (Finding #9)
- Add Static-kind Step 2 lookup test mirroring the Const case (Finding #11)
* docs(field-registry): document lookupFieldByOwner first-wins semantics
Audit of all 6 production callers (call-processor.ts:2279, walkers.ts:535,
receiver-bound-calls.ts:380+730, type-env.ts:627+631) confirms none depends
on last-wins precedence — all treat the return as a generic 'field with
this name owned by this class'. Clarify the JSDoc to surface the semantic
change introduced when FieldRegistry moved from last-wins to append-order
storage (ce-code-review finding #2).
* test(scope-resolution): extend Step 2 perf contract to implicit-self, MRO, field paths
Adds three sibling tests under the Step 2 perf contract describe block, each
asserting defs.byId.values() does NOT execute when ownedMembersByOwner is wired:
- implicit-self receiver via typeBindings.self (no explicitReceiver branch)
- 2-level MRO chain (Child extends Parent, save resolves on Parent at depth 1)
- FieldRegistry read via Step 2 (property lookup, separate registry path)
Pins the perf invariant on every distinct entry into walkReceiverTypeBinding
so a regression bypassing the hook on any sub-path now fails CI immediately
(ce-code-review finding #8).
* test(resolve-references): cover arity-overload filtering via resolveReferenceSites
Pins the orchestration-layer wiring of providers.arityCompatibility:
hook returns [save(arity 1), save(arity 2)], referenceSite.arity = 1,
arityCompatibility verdicts 'compatible'/'incompatible' by parameterCount,
exactly one reference emitted with toDef = the arity-1 overload.
registries.test.ts already covered arity at the buildMethodRegistry level;
this adds the missing entry-point check that resolveReferenceSites threads
providers correctly through to lookupCore.Step5 (ce-code-review finding #10).
* test(resolve-references): add hook-on vs hook-off parity test
Runs resolveReferenceSites twice on the same fixture (Parent.save method
hit + Child.name field hit, Child extends Parent MRO chain) — once with
ownedMembersByOwner wired to a synthetic registry, once with the hook
absent so collectOwnedMembers takes the defs.byId fallback. Asserts:
- stats are identical (sitesProcessed / referencesEmitted / unresolved)
- referenceIndex.bySourceScope entries have equal length
- toDef sets are equal
- each per-site reference (including evidence and depth) is .toEqual
Locks the semantic-parity claim in code while both paths still exist.
Will be removed alongside the fallback in finding #1 (ce-code-review #3).
* test(typescript): probe Step 2 MRO walk against ambient (declare class) base
Adds typescript-ambient-base-class fixture with an export declare class
AmbientBase + Derived extends AmbientBase and a call site d.ambientMethod().
Integration assertions:
- Both classes are detected
- EXTENDS edge Derived → AmbientBase emitted
- CALLS edge to ambient.ts:ambientMethod resolved via MRO walk
Probes the ce-code-review #6 concern that ambient-only owners (whose
bodies are never parsed) might be silently skipped by Step 2 after the
owner-keyed lookup change. Result: the call resolves correctly — the
method signature inside the declare class body still flows through
reconcileOwnership into model.methods, so the hook returns the right
ancestor hits. Residual risk is empirically closed.
* feat(scope-resolution): route nested types via owner-keyed TypeRegistry
Closes the Step 2 contract footgun where 'hook returns [] = authoritative
miss' silently dropped any owned def whose NodeLabel was outside the
method/field if-chain in reconcileOwnership.
- TypeRegistry: add nestedByOwner Map + lookupAllByOwner(owner, simple)
+ registerByOwner(owner, simple, def). Mirrors MethodRegistry/
FieldRegistry shape; cleared with the rest on cascade clear.
- reconcileOwnership: route class-like NodeLabels (Class/Interface/Enum/
Struct/Union/Trait/TypeAlias/Typedef/Record/Delegate/Annotation/
Template/Namespace) via types.registerByOwner. New nestedTypesRegistered
stat. Idempotent skip via nodeId match.
- validateOwnershipParity: extend the I9 invariant check to nested types.
- lookupOwnedMembersByOwner: merge methods + fields + nested-type hits;
short-circuit when any one source contributes the full result.
Unblocks future receiver-MRO registries that need to resolve 'Outer.Inner'
through the receiver's type-binding chain (ce-code-review finding #5a).
* refactor(scope-resolution): make ownedMembersByOwner required; delete byId fallback
Per ce-code-review finding #1, the optional-hook design encoded a silent
O(|defs|) perf cliff into the type system: any RegistryContext built
without the hook regressed Step 2 to scanning every def per probe with
no warning. Production wires the hook unconditionally; the fallback was
exercised only by tests.
- RegistryContext.ownedMembersByOwner: required, returns readonly
SymbolDefinition[] (no | undefined). Implementations MUST return [] on
authoritative miss.
- collectOwnedMembers in lookup-core.ts collapses to a one-line forward
to the hook; the defs.byId.values() scan and simpleNameOf helper are
deleted (simpleNameOf had no other consumers).
- ResolveReferencesInput.ownedMembersByOwner: required to match.
- Tests: drop three fallback-path tests (registries Const fallback,
resolveReferenceSites no-hook fallback, resolveReferenceSites Const-
undefined fallback) and the hook-vs-fallback parity test added by
finding #3. makeCtx in registries.test.ts now defaults to a real
owner-keyed scan over the test fixture defs so tests that don't care
about the hook keep working.
* perf(free-call-fallback): cache global callables by simple name once per pass
pickUniqueGlobalCallable scanned scopes.defs.byId.values() on every
free-call fallback site. After PR #1656 fixed Step 2, this scan became
the dominant remaining O(|defs|) hot path on large repos (ce-code-review
finding #4).
- buildGlobalCallableIndex builds a Map<simpleName, SymbolDefinition[]>
over scopes.defs once at the top of emitFreeCallFallback. Same filter
the per-site scan applied: Function / Method / Constructor, keyed by
the last .-segment of qualifiedName.
- pickUniqueGlobalCallable consumes the prebuilt index via O(1) Map.get
instead of iterating every def. Per-site complexity drops from
O(|defs|) to O(|defs with this simple name|).
- Cost: O(|defs|) once per pass instead of O(|defs| * |free-call sites|).
Subsequent narrowing (arity, conversion-rank) and the model-side fallback
(model.symbols.lookupCallableByName + model.methods.lookupMethodByName)
are unchanged.
* chore(autofix): apply prettier + eslint fixes via /autofix command
* ci: trigger build
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Gergo Magyar <abhigyan1.patwari@gmail.com>
* feat(cpp): SFINAE-aware overload filter — drops candidates whose enable_if_t / requires constraints fail (#1579)
* fix(cpp): SFINAE follow-ups for is_integral_v/is_arithmetic_v bool and char support, an unqualified F1 test fixture, and parameter-lookup gap documentation (#1579) -> claude feedback
* revert: reverting all changes to .md files
* feat(cpp): add standard-conversion-sequence ranking to overload resolution (#1578)
Introduce `ConversionRankFn` abstraction and `cppConversionRank` implementation
to disambiguate C++ overloaded calls by argument-to-parameter conversion cost.
Exact type match (rank 0) beats standard arithmetic conversion (rank 2), which
beats non-viable mismatch (Infinity). Thread the rank function through
`narrowOverloadCandidates`, `pickImplicitThisOverload`, `pickOverload`, and
`pickUniqueGlobalCallable` via the `ScopeResolver.conversionRankFn` contract.
Add `findAllCallableBindingsInScope` scope walker for collecting all overloads
at the first binding scope. Guard against false ambiguity suppression when
candidates span different files (local-shadows-import preservation).
* fix: address Claude review findings on conversion-rank PR
Finding 1 (HIGH): add tests that exercise the conversion ranker.
- p('a') with p(int)/p(double): char→int promotion (rank 1) beats
char→double conversion (rank 2), forcing step 4b in
narrowOverloadCandidates. Exact-type filter misses both overloads.
- h(42, 2.5) with h(int,int)/h(double,double): multi-arg tied total
score forces the ranker, both candidates score 2 → suppressed.
Finding 2 (HIGH): unify multi-candidate suppression across all paths.
- Non-ADL free-call: suppress when narrowed.length > 1 (same-file
guard), mirroring ADL merged-candidate behavior.
- ADL ordinary-only: same pattern.
- pickOverload: return OVERLOAD_AMBIGUOUS when candidates.length > 1
after normalized-ambiguity check.
- Case 0.5 (this receiver): set ambiguous=true when narrowed > 1.
Finding 3+4 (MEDIUM): implement rank-1 integral promotions.
- char→int and bool→int now return rank 1 (ISO C++ [conv.prom]).
- Updated comment to remove misleading ISO table header; document
only the post-normalization ranking that is actually implemented.
- Updated ConversionRankFn JSDoc in overload-narrowing.ts.
218/218 C++ tests pass (registry-primary). Legacy: 186+32.
* fix: implement pairwise dominance comparison for overload ranking
Replace the summed per-slot conversion cost with ISO C++-aligned
pairwise dominance comparison ([over.ics.rank]). F1 is better than
F2 only when F1 is not worse for every argument and strictly better
for at least one. Non-dominated candidates are returned; if multiple
remain they are genuinely ambiguous.
This fixes false CALLS edges for asymmetric multi-arg overloads:
h('a', 2.5) against h(int,int) / h(double,double) — the old summed
cost picked h(double,double) (cost 2 < 3), but ISO C++ considers
the call ambiguous because h(int,int) is better at arg 0 via char
promotion. The pairwise check correctly finds neither dominates.
Add h('a', 2.5) test case asserting zero CALLS edges alongside
the existing h(42, 2.5) symmetric-tie test.
218/218 C++ tests pass (registry-primary). Legacy: 186+32.
* docs: update step 4b JSDoc to reflect pairwise dominance
---------
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
* Initial plan
* fix: add time-based deadline to cross-file type propagation to prevent stalling on large repos
Adds a 2-minute wall-clock time limit (DEFAULT_CROSS_FILE_ELAPSED_MS) to
runCrossFileBindingPropagation. When exceeded, the phase gracefully stops
and logs a warning. Users can override via GITNEXUS_CROSS_FILE_TIMEOUT_MS
env var. This prevents the analyze command from stalling for hours on very
large repositories where per-file re-resolution is expensive.
Fixes the reported issue where gitnexus analyze stalls at "Cross-file type
propagation" for several hours on repos with 15000+ files.
Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/b8341947-557c-4111-a3a8-991ba455ab01
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
* fix: root cause - cache tree-sitter queries across files, add live progress reporting
Root cause: cross-file propagation called processCalls() with 1 file at a time,
causing Parser.Query to be recompiled from the query string for every single file
(O(N) compilations vs O(1) for the whole phase). Additionally, progress was only
reported once at the start, making the phase appear completely frozen.
Fixes:
- Add optional `compiledQueryCache` parameter to `processCalls` so callers that
invoke it with single-file batches can share compiled query objects across calls.
The cross-file phase now compiles each language's query string exactly once and
reuses it for all files of that language (e.g. 1 TypeScript compile for 595+ files).
- Pre-count candidate files and emit onProgress every 25 files showing
"Cross-file type propagation (N/M files)..." so the UI shows real movement
instead of a frozen bar.
- Keep the wall-clock deadline (GITNEXUS_CROSS_FILE_TIMEOUT_MS) as a safety
net for pathological inputs.
Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/f5028cc8-4bc9-4309-8ffb-798fe2bd7a0a
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
* fix: address code review - use SupportedLanguages key type, rename queryCache to compiledQueryCache
Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/f5028cc8-4bc9-4309-8ffb-798fe2bd7a0a
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
* chore(autofix): apply prettier + eslint fixes via /autofix command
* fix(cross-file): remove wall-clock timeout from type propagation
The query compilation cache and live progress reporting address the
original stall; the 2-minute deadline could truncate cross-file work on
large repos. MAX_CROSS_FILE_REPROCESS (2000) remains as the only cap.
* test(cross-file): verify compiledQueryCache is shared across all processCalls invocations
Finding 1: O(N) query recompilation was fixed by sharing a compiledQueryCache Map
across all processCalls invocations in runCrossFileBindingPropagation. This test
verifies the fix is correctly wired: the same Map instance is passed as the
12th argument to every call, proving queries are compiled once per language,
not once per file.
Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/3ab768d9-3993-4882-9d8f-17f7fcbd086e
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
* test(cross-file): verify live progress events are emitted with N/M format
Finding 2: frozen progress display was fixed by emitting onProgress every 25 files
with "Cross-file type propagation (N/M files)..." messages instead of calling it
once at phase start. This test verifies the fix with 50 candidate files: expects
onProgress called 3 times (1 initial + at 25 + at 50) with correct N/M counters.
Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/3ab768d9-3993-4882-9d8f-17f7fcbd086e
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
* fix(cross-file): skip registry-primary language files before readFileContents
Finding 3 (from comment 4466231612): cross-file-impl was calling processCalls
for every candidate file even when that file's language is registry-primary
(TypeScript, C++, Python, Go, C#, PHP, C — since AGENTS.md v1.7.0). processCalls
would immediately skip those files via its own isRegistryPrimary guard, but
cross-file-impl still paid the full cost: readFileContents I/O, buildImportedReturnTypes,
buildImportedRawReturnTypes, and Map allocation — all discarded.
Fix: check isRegistryPrimary(lang) in both the totalCandidates pre-count loop
and the levelCandidates builder, before any file I/O or map building. This
eliminates 595+ no-op processCalls invocations on large TypeScript repos.
Test: mocks isRegistryPrimary to always return true and verifies that
processCalls is never invoked and result is 0. The mock also defaults to false
in beforeEach so existing tests using .ts files are unaffected.
Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/3ab768d9-3993-4882-9d8f-17f7fcbd086e
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
* refactor(test): address code review - simplify mock factory, name the arg index constant
Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/3ab768d9-3993-4882-9d8f-17f7fcbd086e
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>