Compare commits

...
Author SHA1 Message Date
Time Attakc ffc23d636a Merge branch 'master' into fix/backlog-c60 2026-07-22 11:01:22 -07:00
e47639a553 fix(test): isolate GBRAIN_HOME in hybrid-reranker integration test (#1527)
The four "reranker enabled (reorder)" cases stub the gateway at 1536 dims,
but hybridSearch resolves the embedding column via loadConfig(), whose
precedence puts cfg.embedding_dimensions above the gateway stub. On any
machine whose ~/.gbrain/config.json sets a different dimension (e.g. 1280),
the stub vector fails the dim check, search silently degrades to
keyword-only, and the reranker never fires — deterministic 4-test failure
for contributors, green in CI only because fresh runners have no config.

Fix (test-only): point GBRAIN_HOME at an empty tmpdir in beforeAll so
loadConfig() returns null and the stub's dims win; restore + clean up in
afterAll. Same idiom as emptyHome() in
test/ai/gateway-probe-chat-model.test.ts.

Verified with a planted 1280-dim config.json: 2 pass / 4 fail before,
6 pass / 0 fail after; still 6/6 with no config. typecheck clean.

Takeover of #2640.

Co-authored-by: Willisbest <Willisbest@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 14:25:17 -07:00
@@ -27,9 +27,24 @@ import {
} from '../../src/core/ai/gateway.ts';
import type { PageInput, SearchOpts } from '../../src/core/types.ts';
import type { RerankInput, RerankResult } from '../../src/core/ai/gateway.ts';
import { mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
let engine: PGLiteEngine;
// These tests stub the gateway at 1536 dims (DIMS). Since v0.36.3.0 hybridSearch
// resolves the embedding column via loadConfig(), whose precedence is
// cfg.embedding_dimensions > gateway dims > default — so a contributor's real
// ~/.gbrain/config.json (e.g. text-embedding-3-small at 1280) outranks the stub,
// the 1536-d stub vector then fails the gateway dim check, search silently falls
// back to keyword-only, and the reranker never runs (0 docs → 4 tests fail). CI
// is green only because a fresh runner has no config file (#1527). Isolate
// GBRAIN_HOME to an empty tmpdir so loadConfig() returns null and the stub's dims
// win — same idiom as emptyHome() in test/ai/gateway-probe-chat-model.test.ts.
let prevGbrainHome: string | undefined;
let isolatedHome: string;
const DIMS = 1536; // gateway default embedding dim
const FAKE_EMB = Array.from({ length: DIMS }, (_, j) => (j === 0 ? 1 : 0.01));
@@ -40,6 +55,12 @@ function stubEmbeddings(): void {
}
beforeAll(async () => {
// Hermetic config home: ignore the machine's real ~/.gbrain so its
// embedding_dimensions can't outrank the 1536-d stub (see note above, #1527).
prevGbrainHome = process.env.GBRAIN_HOME;
isolatedHome = mkdtempSync(join(tmpdir(), 'gbrain-rerank-home-'));
process.env.GBRAIN_HOME = isolatedHome;
engine = new PGLiteEngine();
await engine.connect({});
await engine.initSchema();
@@ -85,6 +106,9 @@ afterAll(async () => {
__setEmbedTransportForTests(null);
resetGateway();
await engine.disconnect();
if (prevGbrainHome === undefined) delete process.env.GBRAIN_HOME;
else process.env.GBRAIN_HOME = prevGbrainHome;
rmSync(isolatedHome, { recursive: true, force: true });
});
describe('hybridSearch — reranker disabled (pass-through)', () => {