From df2d3a8a814375349f4066d1c075c30b392fc19c Mon Sep 17 00:00:00 2001 From: Gergo Magyar Date: Mon, 20 Apr 2026 17:42:27 +0100 Subject: [PATCH] fix(ci): prettier formatting + Python-migration test adjustments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI run 24666612657 failed on three jobs. Fixes: quality/format: - Prettier --check flagged 3 files after the accumulated branch work. Ran prettier --write from repo root (CI's invocation cwd) to apply: simple-hooks.ts, resolve-references.ts, python-hooks.test.ts. tests/{ubuntu,macos,windows} — 9 assertion failures, all traceable to Python landing in MIGRATED_LANGUAGES (default-on registry-primary): - registry-primary-flag.test.ts (3 tests): the 'returns false by default' / 'primaryLanguages empty' / 'Python mid-process mutation' assertions were written in Ring 2 when MIGRATED_LANGUAGES was empty. Rewrote to assert MIGRATED_LANGUAGES membership is the default, use Java (unmigrated) for the no-stale-cache test, and verify env overrides work in both directions (migrated-off, unmigrated-on). - call-processor.test.ts (6 tests in SM-10 + D2-widen blocks): these exercise the LEGACY call-resolution DAG on .py fixtures. processCalls now gates Python out (isRegistryPrimary === true by default), returning 0 edges. Added REGISTRY_PRIMARY_PYTHON=false override in the relevant beforeEach + restore in afterEach, so the legacy DAG runs for these test-local fixtures without affecting the production-default behavior. Local verification: 4126/4126 unit tests pass, prettier clean. --- .../languages/python/simple-hooks.ts | 9 +--- .../src/core/ingestion/resolve-references.ts | 4 +- gitnexus/test/unit/call-processor.test.ts | 24 +++++++++- .../test/unit/registry-primary-flag.test.ts | 44 +++++++++++++------ .../python/python-hooks.test.ts | 25 +++-------- 5 files changed, 61 insertions(+), 45 deletions(-) diff --git a/gitnexus/src/core/ingestion/languages/python/simple-hooks.ts b/gitnexus/src/core/ingestion/languages/python/simple-hooks.ts index 399d7c891..914ae235c 100644 --- a/gitnexus/src/core/ingestion/languages/python/simple-hooks.ts +++ b/gitnexus/src/core/ingestion/languages/python/simple-hooks.ts @@ -63,10 +63,7 @@ export function pythonImportOwningScope( * * Implemented as an explicit pass-through so reviewers don't have to * re-derive the analysis from absence. */ -export function pythonShouldShadow( - _scope: Scope, - _bindings: readonly BindingRef[], -): boolean { +export function pythonShouldShadow(_scope: Scope, _bindings: readonly BindingRef[]): boolean { return true; } @@ -77,7 +74,5 @@ export function pythonShouldShadow( * non-Function scopes. */ export function pythonReceiverBinding(functionScope: Scope): TypeRef | null { if (functionScope.kind !== 'Function') return null; - return ( - functionScope.typeBindings.get('self') ?? functionScope.typeBindings.get('cls') ?? null - ); + return functionScope.typeBindings.get('self') ?? functionScope.typeBindings.get('cls') ?? null; } diff --git a/gitnexus/src/core/ingestion/resolve-references.ts b/gitnexus/src/core/ingestion/resolve-references.ts index 0c375961a..be95df7ba 100644 --- a/gitnexus/src/core/ingestion/resolve-references.ts +++ b/gitnexus/src/core/ingestion/resolve-references.ts @@ -179,9 +179,7 @@ function lookupForSite( case 'call': { const opts: Parameters[2] = { ...(site.arity !== undefined ? { callsite: { arity: site.arity } } : {}), - ...(site.explicitReceiver !== undefined - ? { explicitReceiver: site.explicitReceiver } - : {}), + ...(site.explicitReceiver !== undefined ? { explicitReceiver: site.explicitReceiver } : {}), }; return methodRegistry.lookup(site.name, site.inScope, opts); } diff --git a/gitnexus/test/unit/call-processor.test.ts b/gitnexus/test/unit/call-processor.test.ts index 4bbc5d4b0..f8c72b28e 100644 --- a/gitnexus/test/unit/call-processor.test.ts +++ b/gitnexus/test/unit/call-processor.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { processCalls, processCallsFromExtracted, @@ -2227,10 +2227,22 @@ describe('processCallsFromExtracted — interface dispatch', () => { describe('processCalls — D0 MRO fast path (SM-10)', () => { let graph: ReturnType; let ctx: ResolutionContext; + let prevRegistryPython: string | undefined; beforeEach(() => { graph = createKnowledgeGraph(); ctx = createResolutionContext(); + // These tests exercise the LEGACY call-resolution DAG directly + // using .py fixtures. Python defaults to registry-primary now + // (MIGRATED_LANGUAGES), which gates call-processor out for + // Python files. Force the flag off so the legacy DAG runs. + prevRegistryPython = process.env['REGISTRY_PRIMARY_PYTHON']; + process.env['REGISTRY_PRIMARY_PYTHON'] = 'false'; + }); + + afterEach(() => { + if (prevRegistryPython === undefined) delete process.env['REGISTRY_PRIMARY_PYTHON']; + else process.env['REGISTRY_PRIMARY_PYTHON'] = prevRegistryPython; }); const setupChildParent = () => { @@ -2974,10 +2986,20 @@ describe('processAssignmentsFromExtracted', () => { describe('D2 widen path: lookupCallableByName via module alias', () => { let graph: ReturnType; let ctx: ResolutionContext; + let prevRegistryPython: string | undefined; beforeEach(() => { graph = createKnowledgeGraph(); ctx = createResolutionContext(); + // Force legacy DAG for .py fixtures — Python is registry-primary + // by default (MIGRATED_LANGUAGES) which would gate processCalls out. + prevRegistryPython = process.env['REGISTRY_PRIMARY_PYTHON']; + process.env['REGISTRY_PRIMARY_PYTHON'] = 'false'; + }); + + afterEach(() => { + if (prevRegistryPython === undefined) delete process.env['REGISTRY_PRIMARY_PYTHON']; + else process.env['REGISTRY_PRIMARY_PYTHON'] = prevRegistryPython; }); it('resolves method via module alias widen using lookupCallableByName', async () => { diff --git a/gitnexus/test/unit/registry-primary-flag.test.ts b/gitnexus/test/unit/registry-primary-flag.test.ts index 20a547e24..759114af5 100644 --- a/gitnexus/test/unit/registry-primary-flag.test.ts +++ b/gitnexus/test/unit/registry-primary-flag.test.ts @@ -12,6 +12,7 @@ import { envVarNameFor, isRegistryPrimary, primaryLanguages, + MIGRATED_LANGUAGES, } from '../../src/core/ingestion/registry-primary-flag.js'; // ─── Test isolation ───────────────────────────────────────────────────────── @@ -58,9 +59,12 @@ describe('envVarNameFor', () => { // ─── isRegistryPrimary ───────────────────────────────────────────────────── describe('isRegistryPrimary', () => { - it('returns false by default (no env var set)', () => { + it('returns MIGRATED_LANGUAGES membership by default (no env var set)', () => { + // Ring 3: languages in MIGRATED_LANGUAGES are registry-primary by + // default — operators don't need to set an env var for the rolled-out + // migration to take effect. Unmigrated languages default to false. for (const lang of Object.values(SupportedLanguages)) { - expect(isRegistryPrimary(lang)).toBe(false); + expect(isRegistryPrimary(lang)).toBe(MIGRATED_LANGUAGES.has(lang)); } }); @@ -104,16 +108,21 @@ describe('isRegistryPrimary', () => { it('isolates flags per-language (one on does not affect others)', () => { process.env['REGISTRY_PRIMARY_PYTHON'] = 'true'; expect(isRegistryPrimary(SupportedLanguages.Python)).toBe(true); + // Java and Go are not in MIGRATED_LANGUAGES — default false stays + // false regardless of Python's flag. expect(isRegistryPrimary(SupportedLanguages.Java)).toBe(false); expect(isRegistryPrimary(SupportedLanguages.Go)).toBe(false); }); it('respects a mid-process env-var mutation (no stale cache)', () => { - expect(isRegistryPrimary(SupportedLanguages.Python)).toBe(false); - process.env['REGISTRY_PRIMARY_PYTHON'] = 'true'; - expect(isRegistryPrimary(SupportedLanguages.Python)).toBe(true); - delete process.env['REGISTRY_PRIMARY_PYTHON']; - expect(isRegistryPrimary(SupportedLanguages.Python)).toBe(false); + // Use Java — not in MIGRATED_LANGUAGES — so the unset default is + // deterministically `false`, independent of which languages have + // been flipped to registry-primary. + expect(isRegistryPrimary(SupportedLanguages.Java)).toBe(false); + process.env['REGISTRY_PRIMARY_JAVA'] = 'true'; + expect(isRegistryPrimary(SupportedLanguages.Java)).toBe(true); + delete process.env['REGISTRY_PRIMARY_JAVA']; + expect(isRegistryPrimary(SupportedLanguages.Java)).toBe(false); }); it('handles the CPlusPlus → REGISTRY_PRIMARY_CPP mapping correctly', () => { @@ -129,19 +138,26 @@ describe('isRegistryPrimary', () => { // ─── primaryLanguages ────────────────────────────────────────────────────── describe('primaryLanguages', () => { - it('returns an empty set when no flags are set', () => { - expect(primaryLanguages().size).toBe(0); + it('returns MIGRATED_LANGUAGES when no flags are set', () => { + // Default-on for migrated languages (Ring 3); unmigrated stay off. + const enabled = primaryLanguages(); + expect(enabled.size).toBe(MIGRATED_LANGUAGES.size); + for (const lang of MIGRATED_LANGUAGES) { + expect(enabled.has(lang)).toBe(true); + } }); - it('returns exactly the flipped languages', () => { - process.env['REGISTRY_PRIMARY_PYTHON'] = 'true'; + it('returns exactly the flipped languages (env opts in unmigrated, opts out migrated)', () => { + // Python is migrated (default-on), explicitly off via env var. + // Go and Java are unmigrated (default-off); Go opted in, Java left off. + process.env['REGISTRY_PRIMARY_PYTHON'] = 'false'; process.env['REGISTRY_PRIMARY_GO'] = '1'; - process.env['REGISTRY_PRIMARY_JAVA'] = 'false'; // explicitly off const enabled = primaryLanguages(); - expect(enabled.has(SupportedLanguages.Python)).toBe(true); + expect(enabled.has(SupportedLanguages.Python)).toBe(false); expect(enabled.has(SupportedLanguages.Go)).toBe(true); expect(enabled.has(SupportedLanguages.Java)).toBe(false); - expect(enabled.size).toBe(2); + // Only Go is on: migrated-default-Python overridden off, Go explicitly on. + expect(enabled.size).toBe(1); }); it('returns a plain Set (not a frozen proxy) — consistent shape', () => { diff --git a/gitnexus/test/unit/scope-resolution/python/python-hooks.test.ts b/gitnexus/test/unit/scope-resolution/python/python-hooks.test.ts index 2b425fe78..c729abf5d 100644 --- a/gitnexus/test/unit/scope-resolution/python/python-hooks.test.ts +++ b/gitnexus/test/unit/scope-resolution/python/python-hooks.test.ts @@ -69,37 +69,25 @@ describe('pythonArityCompatibility', () => { it('compatible when argCount sits inside [required, total]', () => { expect( - pythonArityCompatibility( - def({ parameterCount: 3, requiredParameterCount: 1 }), - callsite(2), - ), + pythonArityCompatibility(def({ parameterCount: 3, requiredParameterCount: 1 }), callsite(2)), ).toBe('compatible'); }); it('compatible at the lower bound', () => { expect( - pythonArityCompatibility( - def({ parameterCount: 3, requiredParameterCount: 1 }), - callsite(1), - ), + pythonArityCompatibility(def({ parameterCount: 3, requiredParameterCount: 1 }), callsite(1)), ).toBe('compatible'); }); it('incompatible when argCount is below required', () => { expect( - pythonArityCompatibility( - def({ parameterCount: 3, requiredParameterCount: 2 }), - callsite(1), - ), + pythonArityCompatibility(def({ parameterCount: 3, requiredParameterCount: 2 }), callsite(1)), ).toBe('incompatible'); }); it('incompatible when argCount exceeds total and no varargs are declared', () => { expect( - pythonArityCompatibility( - def({ parameterCount: 2, requiredParameterCount: 0 }), - callsite(5), - ), + pythonArityCompatibility(def({ parameterCount: 2, requiredParameterCount: 0 }), callsite(5)), ).toBe('incompatible'); }); @@ -123,10 +111,7 @@ describe('pythonArityCompatibility', () => { it('"unknown" for negative or non-finite arities (defensive)', () => { expect( - pythonArityCompatibility( - def({ parameterCount: 3, requiredParameterCount: 1 }), - callsite(-1), - ), + pythonArityCompatibility(def({ parameterCount: 3, requiredParameterCount: 1 }), callsite(-1)), ).toBe('unknown'); }); });