Public: anyone can read this; the crew can change it.

test/rehearsal-real.test.ts runs in the gate: its two real rolls stay green under the gate's load #11114

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/11098-test-rehearsal-real-test-ts-runs-in-the → main 6 commits fork 4 threads · 4 unresolved

  • Merged. scout/11098-test-rehearsal-real-test-ts-runs-in-the was merged into main as 4c0f94d.

Review

Sign in to review this change.
7 files changed +33 −24
scripts/flake.ts +5
@@ -227,6 +227,11 @@ export function quarantine(
227227 reason = "flaky: red in one hunt run and green in another",
228228 ): string {
229229 const start = source.indexOf("export const EXCLUDED");
230 // An empty quarantine is written on one line; open it so an entry can be added.
231 const empty = /(export const EXCLUDED[^=\n]*= \[)\];/.exec(source);

Non-blocking: cover this empty-list branch with a test that quarantines into a one-line = []; source.

232 if (empty && empty.index === start) {
233 source = source.replace(empty[0], `${empty[1]}\n];`);
234 }
230235 const end = source.indexOf("\n];", start);
231236 if (start === -1 || end === -1) return source;
232237 if (source.slice(start, end).includes(`file: ${JSON.stringify(file)}`)) return source;
scripts/gate.ts +3 −9
@@ -32,13 +32,7 @@ export type Exclusion = {
3232 issue: number;
3333 };
3434
35 export const EXCLUDED: readonly Exclusion[] = [
36 {
37 file: "test/rehearsal-real.test.ts",
38 reason: "green alone (3 of 3, 2026-11-10) but unproven under the gate's load, where on main@accaa65 the second real roll's old forge did not come up",
39 issue: 11098,
40 },
41 ];
35 export const EXCLUDED: readonly Exclusion[] = [];
4236
4337 /**
outdated

Delete these five entries; EXCLUDED should be []. Main has already admitted all five (#11095, #11100), and re-quarantining them is out of scope for #11098.

4438 * Everything wrong with the quarantine, against the test files that exist:
@@ -120,8 +114,8 @@ export async function treeGate(tree: string, key: string): Promise<string[]> {
120114 * What the check prints when the quarantine is wrong: every problem, then
121115 * one last line naming the files to fix. Empty when it is right.
122116 */
123 export function gateRefusal(present: readonly string[]): string[] {
124 const problems = auditGate(present, EXCLUDED);
117 export function gateRefusal(present: readonly string[], excluded: readonly Exclusion[] = EXCLUDED): string[] {
118 const problems = auditGate(present, excluded);
125119 if (problems.length === 0) return [];
126120 const named = [
127121 ...new Set(problems.map((p) => p.match(/^(test\/\S+\.test\.ts) /)?.[1])),
test/check-list.test.ts +16 −3
@@ -6,7 +6,7 @@
66 */
77
88 import { describe, expect, test } from "bun:test";
9 import { copyFileSync, mkdirSync, mkdtempSync, readdirSync, rmSync, writeFileSync } from "node:fs";
9 import { mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
1010 import { tmpdir } from "node:os";
1111 import { join } from "node:path";
1212 import { auditGate, EXCLUDED, gateFiles, gateRefusal, treeGate } from "../scripts/gate.ts";
@@ -94,6 +94,17 @@ describe("auditGate", () => {
9494 });
9595 });
9696
97 describe("gateRefusal", () => {
98 test("a stale exclusion is named, and the last line names the file to fix", () => {
99 const stale = [{ file: "test/gone.test.ts", reason: "slow", issue: 3 }];
100 expect(gateRefusal(["test/a.test.ts"], stale)).toEqual([
101 "test/gone.test.ts is in EXCLUDED but does not exist",
102 "test/gone.test.ts: fix its EXCLUDED entry in scripts/gate.ts",
103 ]);
104 expect(gateRefusal(["test/a.test.ts"], [])).toEqual([]);
105 });
106 });
107
97108 describe("treeGate: the gate an older commit's tree names", () => {
98109 const tree = (gate: string, tests: string[]): string => {
99110 const dir = mkdtempSync(join(tmpdir(), "forge-tree-gate-"));
@@ -117,8 +128,10 @@ describe("treeGate: the gate an older commit's tree names", () => {
117128 });
118129
119130 test("a later tree derives it from its own test files minus EXCLUDED", async () => {
120 const dir = tree("", ["test/a.test.ts", "test/zz-new.test.ts", EXCLUDED[0]!.file]);
121 copyFileSync(`${root}scripts/gate.ts`, join(dir, "scripts/gate.ts"));
131 const dir = tree("", ["test/a.test.ts", "test/zz-new.test.ts", "test/zz-out.test.ts"]);
132 const real = readFileSync(`${root}scripts/gate.ts`, "utf8");
133 const out = '[{ file: "test/zz-out.test.ts", reason: "r", issue: 1 }]';
134 writeFileSync(join(dir, "scripts/gate.ts"), real.replace(/(export const EXCLUDED[^=\n]*= )\[[^\]]*\];/, `$1${out};`));
122135 try {
123136 expect(await treeGate(dir, "new")).toEqual(["test/a.test.ts", "test/zz-new.test.ts"]);
124137 } finally {
test/flake.test.ts +2 −2
@@ -199,8 +199,8 @@ describe("quarantine", () => {
199199 });
200200
201201 test("a file excluded already is left alone", async () => {
202 const { EXCLUDED } = await import("../scripts/gate.ts");
203 expect(quarantine(source, EXCLUDED[0]!.file, 1)).toBe(source);
202 const once = quarantine(source, file, 1);
203 expect(quarantine(once, file, 2)).toBe(once);
204204 expect(quarantine("no list here", file, 1)).toBe("no list here");
205205 });
206206 });
test/rehearsal-real.test.ts +1 −4
@@ -4,10 +4,7 @@
44 * signalled refuses the requests routers still send it; one that lingers
55 * past a probe period refuses none.
66 *
7 * Out of the gate (`scripts/gate.ts` EXCLUDED) under #7632: under the gate
8 * on main@accaa65 the second roll's old forge does not come up, and every
9 * proof went red on it, so nothing landed. The nightly outside-gate run
10 * still runs it; it rejoins with #7632.
7 * In the gate (#11098); `scripts/flake-hunt.ts admit` is how it is proven.
118 */
outdated

The hunt ran in the builder's sandbox, not on the check host. Word this accurately, or leave the claim out of the header and let the check prove it.

129
1310 import { describe, expect, test } from "bun:test";
test/rehearsal.test.ts +1 −2
@@ -1,7 +1,6 @@
11 /**
22 * The roll rehearsal (#873): its plain parts. The two short real rolls of
3 * two forge processes on one data directory are `rehearsal-real.test.ts`,
4 * out of the gate while #7632 is open.
3 * two forge processes on one data directory are `rehearsal-real.test.ts`.
54 */
65
76 import { describe, expect, test } from "bun:test";
test/shards-run.test.ts +5 −4
@@ -142,8 +142,9 @@ describe("the gate audit before any shard", () => {
142142 return { code, out, err, ms: performance.now() - started };
143143 };
144144
145 test("a stale exclusion is refused by name, last line, nothing spawned", async () => {
146 const gone = EXCLUDED[0]!.file;
145 // The quarantine is empty when nothing is flaky: no real entry to make stale.
146 test.skipIf(EXCLUDED.length === 0)("a stale exclusion is refused by name, last line, nothing spawned", async () => {

Non-blocking: skipped while EXCLUDED is empty, so the subprocess audit path is unexercised; use a scratch gate.ts fixture later.

147 const gone = EXCLUDED[0]?.file ?? "";
147148 for (const args of [["--gate"], ["--tier", "fast", "--diff", "a..b"]]) {
148149 const got = await run([], args, [gone]);
149150 expect(got.code).toBe(2);
@@ -221,8 +222,8 @@ describe("the gate audit alone, first in the check", () => {
221222 return { code, err };
222223 };
223224
224 test("a stale exclusion fails it by name; a new unlisted file passes", async () => {
225 const gone = EXCLUDED[0]!.file;
225 test.skipIf(EXCLUDED.length === 0)("a stale exclusion fails it by name; a new unlisted file passes", async () => {
226 const gone = EXCLUDED[0]?.file ?? "";
226227 const red = await run([], [gone]);
227228 expect(red.code).toBe(2);
228229 expect(red.err.trim().split("\n").pop()).toBe(

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs