Files
gstack/test/strict-output.test.ts
T
Garry TanandClaude Fable 5 ccb91c3afb fix: pre-landing review fixes for the v2 port wave
Review army (checklist + 5 specialists) + coverage/plan audits on the
assembled branch. Genuine correctness/security/hygiene fixes:

- test-paid-shards: strictTestExitCode now receives expectedFiles on the
  real bun path, so a shard that runs fewer files than planned (harness
  crash, nothing loaded) with exit 0 is no longer recorded 'passed' — the
  invisible-non-execution class the runner exists to kill. Pinned by the
  new test/strict-output.test.ts (also covers the chunk-boundary classifier).
- test-paid-shards: EVALS_TIER env is validated (gate|periodic) like the
  --tier flag, so a typo can't self-skip every test and exit 0 green.
- package.json: test:periodic:sharded sets EVALS_ALL=1, restoring the
  full-tier semantics the pre-shard script had (CI already set it; local
  eval:bg:periodic silently under-measured without it).
- brain-sync.test: run() pins HOME to the temp home so gstack-artifacts-init
  stops writing/clobbering the operator's real ~/.gstack-artifacts-remote.txt
  every free-suite run; afterEach now also scrubs the current filename.
- egress-receipt: cap each receipt field at 512B so a serialized line always
  fits the 4KB tail-read window — a longer line would make the next append
  hash a truncated prior line and verifyLedger report a permanent false
  TAMPER. warnLedgerSize short-circuits before statSync once fired (append
  hot path).
- gstack-egress: import.meta.dir (Windows-safe) instead of new URL().pathname
  so grants doesn't silently report defaults on Windows; strip control chars
  from ledger-derived fields on render so a crafted receipt can't spoof the
  auditor's view.
- extension/background.js + CLAUDE.md: renumber the identity-pin migration
  refs v1.62 -> v1.63 (main claimed 1.62.0.0; this wave queue-advances).
- egress-receipt-wiring: pin lib/context-bill.ts unconditionally (both land
  together now); drop the dead RunShardsOptions.tier field.

All fix-affected test files green; gate failures triaged as external-env
(codex/gemini CLI drift) or pre-existing (hermetic-canary fails identically
on base). Deferred polish tracked in the PR body + decision store.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-12 16:02:11 -07:00

62 lines
2.7 KiB
TypeScript

/**
* Pins scripts/test-strict-output.ts — the verdict-integrity layer of the
* sharded paid runner. Its whole reason to exist is refusing to trust a zero
* exit when failures were printed OR fewer files ran than planned; paid-shards'
* fake commands never emit real Bun result lines, so without this file that
* core was exercised nowhere and a regex regression would silently revert the
* paid tier to trusting exit codes.
*/
import { describe, expect, it } from 'bun:test';
import { BunTestOutputClassifier, strictTestExitCode } from '../scripts/test-strict-output';
describe('strictTestExitCode', () => {
it('trusts a clean zero exit when the expected file count ran', () => {
const summary = { failedTests: 0, unhandledBetweenTests: 0, terminalFileCounts: [1] };
expect(strictTestExitCode(0, summary, 1)).toBe(0);
});
it('refuses a zero exit when fewer files ran than expected (invisible non-execution)', () => {
const summary = { failedTests: 0, unhandledBetweenTests: 0, terminalFileCounts: [1] };
expect(strictTestExitCode(0, summary, 2)).toBe(1);
});
it('refuses a zero exit when failure lines were printed', () => {
const summary = { failedTests: 1, unhandledBetweenTests: 0, terminalFileCounts: [1] };
expect(strictTestExitCode(0, summary, 1)).toBe(1);
});
it('refuses a zero exit on an unhandled error between tests', () => {
const summary = { failedTests: 0, unhandledBetweenTests: 1, terminalFileCounts: [1] };
expect(strictTestExitCode(0, summary, 1)).toBe(1);
});
it('propagates a non-zero child exit regardless of expectedFiles', () => {
const summary = { failedTests: 0, unhandledBetweenTests: 0, terminalFileCounts: [1] };
expect(strictTestExitCode(1, summary, 1)).toBe(1);
});
});
describe('BunTestOutputClassifier', () => {
it('counts a (fail) line split across write chunks', () => {
const c = new BunTestOutputClassifier();
c.write('(fail) my te');
c.write('st [3.42ms]\nRan 4 tests across 1 files. [2.10s]\n');
const summary = c.end();
expect(summary.failedTests).toBe(1);
expect(summary.terminalFileCounts).toEqual([1]);
// exit 0 + a printed failure must not be trusted
expect(strictTestExitCode(0, summary, 1)).toBe(1);
});
it('records the terminal file count from the summary line', () => {
const c = new BunTestOutputClassifier();
c.write('Ran 0 tests across 1 files. [0.01s]\n');
const summary = c.end();
expect(summary.terminalFileCounts).toEqual([1]);
// a fully diff-skipped single-file shard (0 tests, 1 file loaded) still
// passes: 1 file ran, which is what was expected
expect(strictTestExitCode(0, summary, 1)).toBe(0);
});
});