Files
gbrain/test/autopilot-parser-probe-wiring.test.ts
T
Paolo BelcastroandClaude Fable 5 7639493e8c feat(autopilot): wire the nightly conversation-parser probe into the loop
The v0.41.16.0 probe module (runConversationParserNightlyProbe) shipped as
a callable phase with its scheduler wire-up deferred; the follow-up never
landed. Result: zero call sites — the enable flag did nothing, the D10
tokenmax default-on never fired, and doctor's conversation_parser_probe_health
was a hardcoded 'Skipped' stub that ignored config and mode.

This adds the deferred wiring as autopilot step 4.6, mirroring the nightly
quality probe (4.5):

- Flag reads dual-plane (DB row from gbrain config set wins; file plane
  fallback); search.mode=tokenmax keeps the probe default-on per D10.
- Fixtures resolve from the gbrain package root (the committed
  test/fixtures/conversation-formats/), NOT the brain repoPath. Compiled
  binaries carry no source tree: skip quietly with a once-per-process
  stderr note instead of writing failure rows that would flip doctor to
  WARN on every binary install.
- New parser-probe audit trail (audit-parser-probe.ts, shared audit-writer
  primitive, parser-probe-YYYY-Www.jsonl). rate_limited outcomes are NOT
  logged: the loop ticks every few minutes, so auditing each skip would
  flood the file. The 24h gate (parserProbeRanWithin) reads real outcomes.
- Doctor stub replaced with computeConversationParserProbeHealthCheck:
  enable hint when off+silent, WARN on any non-pass run in 7 days.
- try/catch posture identical to 4.5 — a probe failure never crashes the
  loop and never bumps consecutiveErrors.

Tests: audit round-trip + rate-limit gate, doctor check branches, and
source-shape pins for the wiring protections.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FQgByq4aqQq2PP8UHCdnfk
2026-07-06 14:11:16 +02:00

78 lines
3.4 KiB
TypeScript

/**
* Source-shape regression tests for the autopilot wiring of
* `runConversationParserNightlyProbe` (step 4.6).
*
* Same rationale as autopilot-nightly-probe-wiring.test.ts: the loop is
* hard to drive end-to-end, so these pin the structural protections —
* the dual-plane flag read, the D10 tokenmax mode-gate, the package-root
* fixture resolution, the audit-flood guard, and the try/catch posture.
*
* The probe's own gate/scoring logic is pinned by the module's unit
* tests; the audit trail by audit-parser-probe.serial.test.ts.
*/
import { describe, test, expect } from 'bun:test';
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
const AUTOPILOT_SRC = resolve('src/commands/autopilot.ts');
const SOURCE = readFileSync(AUTOPILOT_SRC, 'utf-8');
describe('autopilot wiring: conversation-parser probe', () => {
test('invokes the phase module and the audit trail', () => {
expect(SOURCE).toContain(`runConversationParserNightlyProbe`);
expect(SOURCE).toContain(`conversation-parser/nightly-probe`);
expect(SOURCE).toContain(`logParserProbeEvent`);
expect(SOURCE).toContain(`audit-parser-probe`);
});
test('flag reads dual-plane: DB row (gbrain config set) wins, file plane fallback', () => {
expect(SOURCE).toContain(`getConfig('autopilot.conversation_parser_probe.enabled')`);
expect(SOURCE).toContain(`cfg?.autopilot?.conversation_parser_probe?.enabled === true`);
});
test('D10 mode-gate present: tokenmax brains run the probe by default', () => {
expect(SOURCE).toMatch(/parserEnabled \|\| searchMode === 'tokenmax'/);
});
test('fixtures resolve from the gbrain package root, NOT the brain repoPath', () => {
// The committed fixtures live in the gbrain source tree; resolving
// them against sync.repo_path would point into the user's brain repo.
expect(SOURCE).toMatch(/fileURLToPath\(new URL\('\.\.\/\.\.', import\.meta\.url\)\)/);
expect(SOURCE).toContain(`'conversation-formats', 'all.jsonl'`);
expect(SOURCE).toContain(`'conversation-formats', 'adversarial.jsonl'`);
});
test('missing fixtures skip quietly (no audit row, once-per-process stderr note)', () => {
// Compiled-binary installs carry no source tree; writing failure rows
// would flip doctor to WARN on every binary install.
expect(SOURCE).toContain(`parserProbeFixtureWarned`);
});
test('rate_limited outcomes are NOT audit-logged (flood guard)', () => {
expect(SOURCE).toMatch(/outcome !== 'rate_limited'\) logParserProbeEvent\(result\)/);
});
test('rate-limit gate delegates to the audit module, not inline event reads', () => {
expect(SOURCE).toContain(`parserProbeRanWithin(24 * 60 * 60 * 1000)`);
});
test('LLM-key gate reads gateway.isAvailable("chat") in-process', () => {
expect(SOURCE).toContain(`isAvailable('chat')`);
});
test('probe call wrapped in try/catch that does NOT bump consecutiveErrors', () => {
expect(SOURCE).toMatch(/catch[\s\S]*?autopilot\.parser_probe[\s\S]*?do NOT bump consecutiveErrors/);
});
test('DI shape: the exact 7 fields of the parser probe NightlyProbeDeps', () => {
expect(SOURCE).toContain(`isEnabled:`);
expect(SOURCE).toContain(`searchMode:`);
expect(SOURCE).toContain(`hasLlmKey:`);
expect(SOURCE).toContain(`resolveFixturePath:`);
expect(SOURCE).toContain(`resolveAdversarialPath:`);
expect(SOURCE).toContain(`shouldSkipForRateLimit:`);
expect(SOURCE).toContain(`now:`);
});
});