feat(evals): planner/executor/report modes — the CI re-platform surface

One PLANNER computes diff selection + the slice plan ONCE and writes a
manifest (--emit-plan <path> --slices K); K executors consume it
(--plan <path> --slice i), never self-selecting, and write slice-result
artifacts; a REPORT reconciles results against the manifest (--report
<dir>) fail-closed: a slice whose artifact never landed is a FAILURE,
a planned shard nobody reported fails, wrong-slice/duplicate/cross-tier
results fail. Kills per-slice selector divergence and hollow-lane
aggregation at the root.

- hollow-shard guard: under EVALS_ALL, exit 0 with ZERO executed tests
  (bun's 'Ran N tests' now captured by the classifier — additive) is
  'passed-empty' and fails the run; selective runs keep it 'passed'
  with one warning (in-file diff/tier self-skips are legitimate there);
  unknown counts are never guessed hollow
- retry parity: --retry 1 default + RETRY_OVERRIDES literals for the
  three files whose old matrix rows earned retries: 2 (stale entries
  pinned against disk)
- live smoke: gate plan = 48 shards across 6 slices; report mode exits
  1 on a fabricated missing slice, 0 when complete

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-08-29 05:42:16 +00:00
co-authored by Claude Fable 5
parent c7512da67c
commit f7ef0cc0ce
3 changed files with 536 additions and 9 deletions
+17 -4
View File
@@ -19,7 +19,7 @@ const ROOT = path.resolve(import.meta.dir, '..');
const ANSI_ESCAPE = /\u001B\[[0-?]*[ -/]*[@-~]/g;
const BUN_FAIL_RESULT = /^\(fail\) .+ \[(?:\d+(?:\.\d+)?)(?:ns|us|µs|ms|s)\]$/;
const BUN_BETWEEN_TESTS_ERROR = '# Unhandled error between tests';
const BUN_TERMINAL_SUMMARY = /^Ran \d+ tests? across (\d+) files?\. \[(?:\d+(?:\.\d+)?)(?:ns|us|µs|ms|s)\]$/;
const BUN_TERMINAL_SUMMARY = /^Ran (\d+) tests? across (\d+) files?\. \[(?:\d+(?:\.\d+)?)(?:ns|us|µs|ms|s)\]$/;
export type BunTestOutputFinding = 'failed-test' | 'unhandled-between-tests';
@@ -27,6 +27,8 @@ export interface BunTestOutputSummary {
failedTests: number;
unhandledBetweenTests: number;
terminalFileCounts: number[];
/** Test counts from the same terminal lines — feeds the hollow-shard guard. */
terminalTestCounts: number[];
}
export type ForwardedTerminationSignal = 'SIGINT' | 'SIGTERM';
@@ -196,9 +198,15 @@ export function classifyBunTestOutputLine(rawLine: string): BunTestOutputFinding
}
export function parseBunTerminalSummaryLine(rawLine: string): number | null {
return parseBunTerminalSummary(rawLine)?.files ?? null;
}
export function parseBunTerminalSummary(rawLine: string): { tests: number; files: number } | null {
const line = stripAnsiLine(rawLine);
const match = BUN_TERMINAL_SUMMARY.exec(line);
return match ? Number.parseInt(match[1], 10) : null;
return match
? { tests: Number.parseInt(match[1], 10), files: Number.parseInt(match[2], 10) }
: null;
}
/**
@@ -220,6 +228,7 @@ export class BunTestOutputClassifier {
private failedTests = 0;
private unhandledBetweenTests = 0;
private terminalFileCounts: number[] = [];
private terminalTestCounts: number[] = [];
write(chunk: Uint8Array | string, origin: ClassifierOrigin = 'stdout'): void {
this.pending[origin] += typeof chunk === 'string'
@@ -242,6 +251,7 @@ export class BunTestOutputClassifier {
failedTests: this.failedTests,
unhandledBetweenTests: this.unhandledBetweenTests,
terminalFileCounts: [...this.terminalFileCounts],
terminalTestCounts: [...this.terminalTestCounts],
};
}
@@ -258,8 +268,11 @@ export class BunTestOutputClassifier {
const finding = classifyBunTestOutputLine(line);
if (finding === 'failed-test') this.failedTests += 1;
if (finding === 'unhandled-between-tests') this.unhandledBetweenTests += 1;
const terminalFileCount = parseBunTerminalSummaryLine(line);
if (terminalFileCount !== null) this.terminalFileCounts.push(terminalFileCount);
const terminal = parseBunTerminalSummary(line);
if (terminal !== null) {
this.terminalFileCounts.push(terminal.files);
this.terminalTestCounts.push(terminal.tests);
}
}
}