Files
gstack/test/office-hours-budget.test.ts
T
garrytan 4973f96d98 test: move the full office-hours workflow to marathon; add a periodic design-draft checkpoint
The full startup workflow runs 1–3 real spec-review rounds (~280s each) and
hit its 1200s capture in run 36385945043 at finalize. Review depth is the
product's loop, so the case cannot fit a blocking lane without cutting
rounds. It is now marathon tier with every assertion unchanged.

skill-e2e-office-hours-design-draft.test.ts (periodic) runs the same fixed
interview only through the Write that creates the design (269s in that run)
and applies the full validator's design-draft checks, the required section
reads and the launch/foreign-skill-read guards. validateOfficeHoursDesignDraft
is extracted from validateOfficeHoursCompletion, which still applies it.

Selection: office-hours-design-draft is registered periodic; the marathon-only
file is already excluded from the gate and periodic plans by the B5 planner
rule. Tier-alignment regexes and the valid-tier check accept 'marathon'.
A type-only cast in plan-scope-selection.test.ts removes a diagnostic whose
union print order made the ratchet identity unstable; baseline tightened.
2026-09-29 15:29:46 +00:00

66 lines
3.4 KiB
TypeScript

import { expect, test } from 'bun:test';
import * as fs from 'node:fs';
import * as os from 'node:os';
import * as path from 'node:path';
import { DEFAULT_SHARD_TIMEOUT_MS } from '../scripts/test-paid-shards';
import { CAPTURE_LONG_MS } from './helpers/eval-budgets';
const casePath = path.join(import.meta.dir, 'skill-e2e-office-hours-section-loading.test.ts');
// Evaluate the real case registrations with inert test/describe functions.
// Imports are removed, and the captured paid callbacks are never invoked.
function registrations(file = casePath): Array<{ tier: string; options: unknown }> {
const source = new Bun.Transpiler({ loader: 'ts' }).transformSync(fs.readFileSync(file, 'utf8'))
.replace(/^import\b[^;]*;\s*$/gm, '');
const found: Array<{ tier: string; options: unknown }> = [];
new Function('test', 'describeE2ETier', 'CAPTURE_LONG_MS', source)(
(_name: string, _callback: unknown, options: unknown) => found.at(-1)!.options = options,
(tier: string) => (_name: string, register: () => void) => { found.push({ tier, options: undefined }); register(); },
CAPTURE_LONG_MS,
);
return found;
}
test('the full office-hours workflow is one marathon-tier registration', () => {
expect(registrations()).toEqual([{ tier: 'marathon', options: { timeout: 1_260_000, retry: 0 } }]);
});
test('the design-draft checkpoint is one periodic case inside the ordinary long capture budget', () => {
const draft = path.join(import.meta.dir, 'skill-e2e-office-hours-design-draft.test.ts');
expect(registrations(draft)).toEqual([{ tier: 'periodic', options: CAPTURE_LONG_MS }]);
const source = fs.readFileSync(draft, 'utf8');
expect(source).toContain('timeout: LONG_SECTION_CAPTURE_MS');
expect(source).toContain('stop after the Write that saves the complete design');
expect(source).toContain('Do not run the spec review, approval, relationship closing or handoff');
});
test('office-hours has one bounded attempt even under the paid runner CLI retry default', () => {
const options = registrations()[0]!.options as { timeout: number; retry: number };
expect(options).toEqual({ timeout: 1_260_000, retry: 0 });
expect(options.timeout + 120_000).toBeLessThanOrEqual(DEFAULT_SHARD_TIMEOUT_MS);
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-office-hours-retry-'));
try {
const fake = path.join(dir, 'retry.test.ts');
fs.writeFileSync(fake, `import { afterAll, expect, test } from 'bun:test';
let defaults = 0, officeHours = 0, two = 0;
test('default retry', () => { defaults++; expect(defaults).toBe(2); });
test('office-hours retry', () => {
officeHours++; throw new Error('intentional single-attempt failure');
}, ${JSON.stringify(options)});
test('existing two retries', () => { two++; expect(two).toBe(3); }, { retry: 2 });
afterAll(() => console.log('ATTEMPTS=' + JSON.stringify({ defaults, officeHours, two })));
`);
const child = Bun.spawnSync([process.execPath, 'test', '--retry', '1', fake], {
cwd: dir, stdout: 'pipe', stderr: 'pipe', timeout: 5_000,
});
const output = child.stdout.toString() + child.stderr.toString();
expect(child.exitCode).toBe(1); // the deliberate single-attempt failure stays failed
const attempts = output.match(/ATTEMPTS=(\{[^\n]+\})/);
expect(attempts, output).not.toBeNull();
expect(JSON.parse(attempts![1])).toEqual({ defaults: 2, officeHours: 1, two: 3 });
} finally {
fs.rmSync(dir, { recursive: true, force: true });
}
});