Files
gbrain/test/bench-cli-dispatch.test.ts
T
948ccc7b4f fix(cli): wire gbrain bench publish dispatcher + honor DB-plane eval.capture
Two backlog fixes:

1. Takeover of #1476 (closes #1474): 'bench' was missing from CLI_ONLY and
   runBenchPublish was imported nowhere, so the documented
   'gbrain bench publish' hit 'Unknown command'. Adds the 'bench' token to
   master's current CLI_ONLY set (the original PR rewrote the line from a
   stale v0.41.14 snapshot, deleting ~15 newer commands), routes bench
   through a no-DB bypass (bench publish is pure file I/O), and adds
   'bench' to CLI_ONLY_SELF_HELP so --help reaches bench-publish's own
   usage text.

2. Fixes #1475: 'gbrain config set eval.capture true' persisted to the DB
   plane but was never read — the capture gate reads the sync file-plane
   ctx.config. loadConfigWithEngine now sparse-merges eval.capture /
   eval.scrub_pii (file wins per key), connectEngine stashes the merged
   values on GBRAIN_EVAL_CAPTURE / GBRAIN_EVAL_SCRUB_PII (same pattern as
   the multimodal flags), and the gates consult the stash when the file
   plane is silent.

Co-authored-by: Mr-B-1 <Mr-B-1@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 14:30:23 -07:00

68 lines
2.6 KiB
TypeScript

// #1474: the v0.41.1 wave shipped bench-publish.ts + docs/eval-bench.md
// advertising `gbrain bench publish`, but the cli.ts dispatcher case was never
// added — the documented command hit 'Unknown command'. These tests spawn the
// real CLI (no DB needed; bench publish is pure file I/O) and fail on any
// regression of the dispatcher wiring.
import { describe, expect, test } from 'bun:test';
import { mkdtempSync, writeFileSync, existsSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { spawnSync } from 'node:child_process';
function runCli(args: string[]): { stdout: string; stderr: string; code: number } {
const result = spawnSync(process.execPath, ['run', 'src/cli.ts', 'bench', ...args], {
encoding: 'utf8',
cwd: process.cwd(),
env: { ...process.env },
});
return { stdout: result.stdout ?? '', stderr: result.stderr ?? '', code: result.status ?? -1 };
}
describe('gbrain bench dispatcher (#1474)', () => {
test('bench --help reaches bench-publish help without a DB (was: Unknown command)', () => {
const { stdout, stderr, code } = runCli(['--help']);
expect(stderr).not.toContain('Unknown command');
expect(code).toBe(0);
expect(stdout).toContain('gbrain bench publish');
expect(stdout).toContain('--from');
});
test('unknown bench subcommand exits 2 with usage', () => {
const { stderr, code } = runCli(['bogus']);
expect(code).toBe(2);
expect(stderr).toContain('Unknown bench subcommand');
expect(stderr).toContain('bench publish');
});
test('bench publish roundtrip: captured NDJSON in, baseline file out', () => {
const tmp = mkdtempSync(join(tmpdir(), 'bench-cli-'));
try {
const row = {
tool_name: 'query',
query: 'hello world',
retrieved_slugs: ['slug-a'],
retrieved_chunk_ids: [1],
source_ids: ['default'],
expand_enabled: false,
detail: 'medium',
detail_resolved: 'medium',
vector_enabled: true,
expansion_applied: false,
latency_ms: 100,
remote: false,
job_id: null,
subagent_id: null,
};
const from = join(tmp, 'captured.ndjson');
const to = join(tmp, 'personal.baseline.ndjson');
writeFileSync(from, `${JSON.stringify(row)}\n`);
const { code, stderr } = runCli(['publish', '--from', from, '--to', to]);
expect(stderr).not.toContain('Unknown command');
expect(code).toBe(0);
expect(existsSync(to)).toBe(true);
} finally {
rmSync(tmp, { recursive: true, force: true });
}
});
});