mirror of
https://github.com/garrytan/gbrain.git
synced 2026-07-30 11:22:34 +00:00
(1) test-status never read needs.brainbench.result: a failing gate job left the branch-protection aggregate green — merge-bypassable. Now in the loop. (2) The first-landing path verifies the run against the COMMITTED baseline (an unverified initial merge could seed a doctored baseline for every future PR). (3) One stored fact row may satisfy at most one gold probe (merged/ broad extractions inflated fidelity via unconstrained find()). (4) The slug-granularity limit of source-isolation detection is disclosed in the methodology doc with a pointer to the engine-layer fuzz that covers the content-leak case. Plus 30s timeouts on engine-touching tests (observed 5s default flaking at load avg 20).
102 lines
4.5 KiB
TypeScript
102 lines
4.5 KiB
TypeScript
/**
|
|
* BrainBench continuity — writer fixture replays through harness A, its
|
|
* decision persists via the production write-back pipeline, reader fixture
|
|
* replays through harness B on the SAME brain, and the decision must be
|
|
* recallable. Scores land on the reader's cell.
|
|
*/
|
|
import { afterAll, beforeAll, describe, expect, test } from 'bun:test';
|
|
import { createBenchmarkBrain } from '../src/eval/longmemeval/harness.ts';
|
|
import type { PGLiteEngine } from '../src/core/pglite-engine.ts';
|
|
import { loadCorpus } from '../src/eval/brainbench/fixtures.ts';
|
|
import { runBrainBench } from '../src/eval/brainbench/harness.ts';
|
|
import { factKeywordProbe, scoreContinuityPair } from '../src/eval/brainbench/metrics/continuity.ts';
|
|
import type { LoadedCorpus } from '../src/eval/brainbench/types.ts';
|
|
|
|
let pairCorpus: LoadedCorpus;
|
|
|
|
beforeAll(async () => {
|
|
const corpus = await loadCorpus('evals/brainbench/fixtures', 'evals/brainbench/gold');
|
|
const pair = corpus.fixtures.filter(
|
|
(f) => f.fixture.continuity?.pair_id === 'cont-001',
|
|
);
|
|
expect(pair.length).toBe(2);
|
|
pairCorpus = { ...corpus, fixtures: pair };
|
|
});
|
|
|
|
describe('writer openclaw → reader codex (and reverse) on a shared brain', () => {
|
|
test('decision recalled in both directions; cells assigned to the READER harness', async () => {
|
|
const out = await runBrainBench(pairCorpus, {
|
|
harnesses: ['openclaw', 'codex'],
|
|
suites: ['continuity', 'write-back'],
|
|
includeHoldout: true,
|
|
llm: false,
|
|
});
|
|
expect(out.seed_failures).toEqual([]);
|
|
const contCells = out.cells.filter((c) => c.suite === 'continuity');
|
|
expect(contCells.map((c) => c.harness).sort()).toEqual(['codex', 'openclaw']);
|
|
for (const c of contCells) {
|
|
expect(c.gold_total).toBe(1); // one decision probe per reader direction
|
|
expect(c.gold_failed).toBe(0);
|
|
expect(c.metrics.continuity_rate).toBe(1);
|
|
}
|
|
// Reader turn rows exist and carry the continuity suite tag.
|
|
const readerRows = out.turn_rows.filter((r) => r.suite === 'continuity');
|
|
expect(readerRows.length).toBeGreaterThan(0);
|
|
expect(readerRows.every((r) => r.fixture_id === 'cont-001-widget-pass-reader')).toBe(true);
|
|
}, 30_000);
|
|
|
|
test('single-harness run falls back to the diagonal (writer == reader) instead of vanishing', async () => {
|
|
const out = await runBrainBench(pairCorpus, {
|
|
harnesses: ['openclaw'],
|
|
suites: ['continuity'],
|
|
includeHoldout: true,
|
|
llm: false,
|
|
});
|
|
const cell = out.cells.find((c) => c.suite === 'continuity' && c.harness === 'openclaw');
|
|
expect(cell).toBeDefined();
|
|
expect(cell!.metrics.continuity_rate).toBe(1);
|
|
}, 30_000);
|
|
});
|
|
|
|
describe('factKeywordProbe + the miss path', () => {
|
|
let engine: PGLiteEngine;
|
|
|
|
beforeAll(async () => {
|
|
engine = await createBenchmarkBrain();
|
|
await engine.insertFact( // gbrain-allow-direct-insert: keyword-probe semantics test in a throwaway benchmark brain
|
|
{ fact: 'Decided to pass on the widget-co round', source: 'bench:test', embedding: null },
|
|
{ source_id: 'default' },
|
|
);
|
|
const expired = await engine.insertFact( // gbrain-allow-direct-insert: expired-row exclusion probe in a throwaway benchmark brain
|
|
{ fact: 'Decided to lead the acme-example round', source: 'bench:test', embedding: null },
|
|
{ source_id: 'default' },
|
|
);
|
|
await engine.expireFact(expired.id);
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await engine.disconnect();
|
|
});
|
|
|
|
test('AND semantics: every keyword must match; partial sets fail', async () => {
|
|
expect(await factKeywordProbe(engine, 'default', ['pass', 'widget-co'])).toBe(true);
|
|
expect(await factKeywordProbe(engine, 'default', ['pass', 'no-such-keyword'])).toBe(false);
|
|
}, 30_000);
|
|
|
|
test('expired facts are excluded — a superseded decision is not "recalled"', async () => {
|
|
expect(await factKeywordProbe(engine, 'default', ['lead', 'acme-example'])).toBe(false);
|
|
}, 30_000);
|
|
|
|
test('a decision neither injected nor stored counts into gold_failed with a named item', async () => {
|
|
const score = await scoreContinuityPair(engine, 'default', 'pair-x', [], [
|
|
{ decision_id: 'd-missing', expected_slugs: ['decisions/nope'], match_keywords: ['never', 'stored'] },
|
|
{ decision_id: 'd-hit', expected_slugs: [], match_keywords: ['pass', 'widget-co'] },
|
|
]);
|
|
expect(score.gold_total).toBe(2);
|
|
expect(score.gold_failed).toBe(1);
|
|
expect(score.hits['d-missing']).toBe(false);
|
|
expect(score.hits['d-hit']).toBe(true);
|
|
expect(score.failed_items[0]).toContain('pair-x/d-missing');
|
|
}, 30_000);
|
|
});
|