From 38d737bb50120a56f1b00fb2e10048c27c1cfd64 Mon Sep 17 00:00:00 2001 From: Gergo Magyar Date: Fri, 24 Jul 2026 22:01:16 +0000 Subject: [PATCH] fix(test): remove literal NUL byte and cover streamGraphEmit phase gating MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two review findings, both verified before accepting. 1. The round-trip test contained a literal NUL byte as a key separator, which made Git treat the whole .ts file as BINARY — `git show --numstat` reported `-\t-` for it, so the file would not diff or blame and CI text tooling would skip it. Replaced with the escaped \\u0000 sequence; behaviour is identical, the file is text again. (Found by the Codex swarm lane.) 2. buildPhaseList's four new streamGraphEmit gating predicates and the flag-off default path had no test that would fail on revert — two review lanes flagged this independently. Reversing any enabledWhen condition would have passed the suite silently, which matters because an ungated taintSummaries yields an empty taint layer rather than an error. Added four cases: the streamed run drops communities/processes/ taintSummaries/callSummaries; it keeps mro/di (their reads are all in RETAINED_REL_TYPES); the flag-off list is untouched; and skipGraphPhases still works independently. Refs #2680 --- .../graph-emit-streaming-roundtrip.test.ts | Bin 7223 -> 7229 bytes .../unit/stream-graph-emit-config.test.ts | 45 ++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/gitnexus/test/integration/graph-emit-streaming-roundtrip.test.ts b/gitnexus/test/integration/graph-emit-streaming-roundtrip.test.ts index fe895fb61ca6f7e6e46220f7ff88bc0f7f475ea3..279b3cfd7db1045ef465f69a52b52ba75f1ae3d6 100644 GIT binary patch delta 27 hcmdmPvDae5H$J8qgU#RhE-|vjlo|lR=2HT>+yI{&3Qhn3 delta 21 bcmdmMvE5?BH$Fy&%|G}qF#@Rz0=e7(WJm}y diff --git a/gitnexus/test/unit/stream-graph-emit-config.test.ts b/gitnexus/test/unit/stream-graph-emit-config.test.ts index 2ba2a23c2..9072fa2a2 100644 --- a/gitnexus/test/unit/stream-graph-emit-config.test.ts +++ b/gitnexus/test/unit/stream-graph-emit-config.test.ts @@ -14,6 +14,7 @@ import { describe, it, expect, vi, afterEach } from 'vitest'; import { resolveStreamGraphEmit } from '../../src/core/run-analyze.js'; +import { buildPhaseList } from '../../src/core/ingestion/pipeline.js'; import { createKnowledgeGraph } from '../../src/core/graph/graph.js'; import { pruneLocalValueSymbols } from '../../src/core/ingestion/local-symbol-pruner.js'; import type { GraphNode } from 'gitnexus-shared'; @@ -115,3 +116,47 @@ describe('pruneLocalValueSymbols under streamed emit', () => { expect(stats).toMatchObject({ candidateNodes: 1, prunedNodes: 1 }); }); }); + +describe('buildPhaseList under streamGraphEmit', () => { + const names = (o: Parameters[0]) => buildPhaseList(o).map((p) => p.name); + + it('drops every phase that consumes the whole CALLS graph', () => { + // CALLS is exactly what streams out, so leaving these enabled yields + // silently empty results rather than an error. + const streamed = names({ streamGraphEmit: true, pdg: true, force: true }); + + expect(streamed).not.toContain('communities'); + expect(streamed).not.toContain('processes'); + expect(streamed).not.toContain('taintSummaries'); + expect(streamed).not.toContain('callSummaries'); + }); + + it('keeps mro and di, whose reads are all in the retained set', () => { + const streamed = names({ streamGraphEmit: true, pdg: true, force: true }); + + expect(streamed).toContain('mro'); + expect(streamed).toContain('di'); + expect(streamed).toContain('parse'); + expect(streamed).toContain('scopeResolution'); + expect(streamed).toContain('pruneLocalSymbols'); + }); + + it('leaves the phase list untouched when the flag is off', () => { + // Guards the default path: the gating predicates must not filter anything + // for existing (flag-off) users. + const withPdg = names({ pdg: true, force: true }); + + expect(withPdg).toContain('communities'); + expect(withPdg).toContain('processes'); + expect(withPdg).toContain('taintSummaries'); + expect(withPdg).toContain('callSummaries'); + }); + + it('still honours skipGraphPhases independently of the streaming flag', () => { + const skipped = names({ skipGraphPhases: true }); + + expect(skipped).not.toContain('communities'); + expect(skipped).not.toContain('processes'); + expect(skipped).toContain('pruneLocalSymbols'); + }); +});