From c740d716be258f590206dcdf7ac7573d2c276a8d Mon Sep 17 00:00:00 2001 From: Navid EMAD Date: Mon, 24 Aug 2026 20:38:00 +0200 Subject: [PATCH] fix(zig): address tenth gitnexus-check review pass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `normalizeZigDepPath`: normalize backslashes BEFORE the absolute-path check. A UNC dep (`\\server\share\dep`) used to slip past the check and normalize to the repo-relative `server/share/dep`; root-relative `\dep` had the same hole. Both now return null. Regression case added to the absolute-spellings test with the files those misreadings would resolve. - `bindPayloads`: a pointer capture `for (pages) |*p|` now records `*Page` (declaredSpelling) instead of `Page` — the `*` is an anonymous payload child before the identifier. Method dispatch is unchanged (`rawName` strips the sigil), but a deref projection `const q = p.*;` now sees the pointer layer. New fixture fn `viaPtrCaptureDeref` + assertion; fails on the previous code (verified by stashing the src fix). - `optional-grammar-gate.test.ts`: renamed the `typescript:tsx` case — the key IS a registry row; what makes it inert is the missing gate entry. Now also asserts a key no registry yields. - `structural-pair-coverage.test.ts`: header updated — ten tables (not eleven) are absent from every rule's target side; `Union` left the set when Zig made it linkable. - `language-classification.ts`: doc comment now names zig in the experimental set (added after Ring 1). Not re-fixed (invalid findings): - "owner-hook contract wired to an undeclared variable": stale-diff read — `findEnclosingClassInfo` declares `resolveFileTypeOwner` / `resolveContainerTypeOwner` as optional parameters (ast-helpers.ts:905, 917) and parse-worker threads them at every call site; tsc compiles clean. - "optional Zig grammar added unconditionally to the parsing fixture suite": the cited block only `fs.readFile`s the committed fixture file to assert it is non-empty — no parser or grammar load is involved. --- .../language-classification.ts | 3 +++ gitnexus/src/core/ingestion/language-config.ts | 11 +++++++---- .../ingestion/languages/zig/range-binding.ts | 9 +++++++-- .../zig-filestruct/src/flow.zig | 8 ++++++++ .../test/integration/resolvers/zig.test.ts | 3 +++ .../structural-pair-coverage.test.ts | 7 ++++--- .../test/unit/optional-grammar-gate.test.ts | 7 ++++++- gitnexus/test/unit/zig-import-resolver.test.ts | 18 ++++++++++++++++-- 8 files changed, 54 insertions(+), 12 deletions(-) diff --git a/gitnexus-shared/src/scope-resolution/language-classification.ts b/gitnexus-shared/src/scope-resolution/language-classification.ts index 11b737a22..20059c3e9 100644 --- a/gitnexus-shared/src/scope-resolution/language-classification.ts +++ b/gitnexus-shared/src/scope-resolution/language-classification.ts @@ -12,6 +12,9 @@ * - experimental: vue (embedded-language / SFC complexity), * cobol (regex-provider path) * - quarantined: (none) + * + * Added after Ring 1: zig enters as `experimental` (new language + * integration; promotion to `production` is a separate governance PR). */ import { SupportedLanguages } from '../languages.js'; diff --git a/gitnexus/src/core/ingestion/language-config.ts b/gitnexus/src/core/ingestion/language-config.ts index f4064a2fc..a50ce16e6 100644 --- a/gitnexus/src/core/ingestion/language-config.ts +++ b/gitnexus/src/core/ingestion/language-config.ts @@ -594,11 +594,14 @@ export async function loadZigBuildConfig(repoRoot: string): Promise { } }); - it('is inert for a grammar-key variant nobody registered', () => { + // `typescript:tsx` IS a registry key (`listGrammarSources()` yields it) — + // what makes it inert is that OPTIONAL_GRAMMAR_ENV has no entry for it, the + // grammar being mandatory. A key no registry ever yields is inert the same + // way; both stay ungated no matter what env vars are set. + it('is inert for a grammar key with no gate entry, registered or not', () => { process.env[envVar] = '1'; expect(isOptionalGrammarRequired('typescript:tsx')).toBe(false); + expect(isOptionalGrammarRequired('no-such:grammar')).toBe(false); }); // Languages with no entry must never be gated — an unregistered language diff --git a/gitnexus/test/unit/zig-import-resolver.test.ts b/gitnexus/test/unit/zig-import-resolver.test.ts index 3e3376ffb..2ddf4e799 100644 --- a/gitnexus/test/unit/zig-import-resolver.test.ts +++ b/gitnexus/test/unit/zig-import-resolver.test.ts @@ -136,13 +136,27 @@ describe('resolveZigImportInternal', () => { it('returns null for absolute `.path` deps, POSIX and Windows spellings alike', () => { // `normalizeZigDepPath` promises null for anything outside the repo; a - // `/`-only check let `C:\\local_dep` through as the relative `C:/local_dep`. + // `/`-only check let `C:\\local_dep` through as the relative `C:/local_dep`, + // and an absolute check that ran BEFORE backslash normalization let the + // UNC `\\\\server\\share\\local_dep` (and root-relative `\\local_dep`) + // through as relative paths. The `root.zig` entries below are the files + // those misreadings WOULD resolve — each spelling must reject, not merely + // miss. const files = new Set([ 'src/main.zig', 'C:/local_dep/src/dep.zig', 'local_dep/src/dep.zig', + 'local_dep/src/root.zig', + 'server/share/local_dep/src/root.zig', ]); - for (const abs of ['/local_dep', 'C:\\local_dep', 'c:/local_dep', 'D:\\x\\local_dep']) { + for (const abs of [ + '/local_dep', + 'C:\\local_dep', + 'c:/local_dep', + 'D:\\x\\local_dep', + '\\\\server\\share\\local_dep', + '\\local_dep', + ]) { const zon = { pathDeps: new Map([['dep', abs]]) }; expect(resolveZigImportInternal('src/main.zig', 'dep', files, zon)).toBeNull(); }