fix(#4434): win32 unmeasured test files weigh the documented ~2.2x Windows-cost floor, not the Linux-measured mean (#4903)

* fix(#4434): win32 unmeasured test files weigh the documented ~2.2x Windows-cost floor, not the Linux-measured mean

test(#4434): failing-first — win32 unmeasured-file weight must use the
documented Windows-cost multiplier, not the plain table mean

fix(#4434): makeFileWeigher takes a platform and applies
WINDOWS_UNMEASURED_COST_MULTIPLIER (2.2) to the unmeasured-file fallback
on win32 only; measured files and other platforms are unaffected

chore(#4434): changeset fragment

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* test(#4434): add fast-check property coverage for the win32 unmeasured-file weight multiplier

CLAUDE.md requires a fast-check property test for budget-limit logic; the
prior example-based #4434 tests didn't satisfy that. Adds two seeded,
bounded property tests: the unmeasured-file fallback matches the platform
rule for any measured table, and a measured file's weight is
platform-invariant for any measured table.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* chore(#4434): backfill changeset PR number (4903)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(#4434): the Windows unmeasured-file multiplier must not apply when there is no timings table at all

Real Windows CI on this PR caught a regression my own linux-only gsd-test
verification couldn't see: makeFileWeigher applied
WINDOWS_UNMEASURED_COST_MULTIPLIER even when `timings` is null (missing/
corrupt/empty table), breaking the pre-#2456 "no table degrades to uniform
weight 1" invariant several existing tests depend on. The multiplier now
only applies to a file absent from an otherwise-loaded table — the actual
#4434 mechanism (a real, loaded, Linux-measured table with unmeasured
entries) — never to the no-table-at-all path.

Six pre-existing tests that called makeFileWeigher/pack helpers with no
explicit platform (silently inheriting whatever OS runs them) now pin an
explicit 'linux' platform, since they test the platform-agnostic mean-vs-
median and Object.prototype-safety invariants, not #4434's Windows
behavior. One subprocess-level test is isolated from the real committed
tests/test-timings.json via RUN_TESTS_TIMINGS_FILE, matching this file's
existing isolation convention for cost-profile-sensitive assertions.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: sim <sim@local>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-09-20 20:08:53 -04:00
committed by GitHub
parent ccfed63355
commit 029acd9158
3 changed files with 143 additions and 12 deletions

View File

@@ -0,0 +1,5 @@
---
type: Fixed
pr: 4903
---
**Windows conformance-tier CI no longer blows its own chunk timeout on unmeasured test files.** `scripts/run-tests.cjs` now weighs a test file absent from `tests/test-timings.json` at the documented ~2.2x Windows-cost floor instead of the plain (Linux-measured) table mean, on win32 only — a cluster of unmeasured conformance-tier files could otherwise pack into one chunk and exceed the 600s per-chunk backstop even though the chunk looked in-budget. (#4434)

View File

@@ -535,12 +535,36 @@ function loadTestTimings(timingsPath) {
return { timings, mean, medianWeight: median / mean };
}
// #4434: the table's own `sources` are Linux-only (test-events-linux-node22/24
// .jsonl — never a Windows event stream), and this runner's own chunk-kill
// diagnostic already tells operators "real Windows cost runs ~2.2x the
// recorded figure, so treat every number as a floor" (see the catch block
// around the per-chunk timeout, below). That string was, until this fix,
// advisory text ONLY — nothing in the weigher actually applied it. Verified
// live: `next` @ ccfed6335 (unrelated to the chunk's own diff — see #4434)
// killed Windows conformance shard 3/3 chunk 6/8 at 600016ms; 6 of that
// chunk's 17 files were wholly absent from the table and were packed at the
// table's plain mean, identically to how a Linux/macOS chunk would price
// them. A MEASURED file does not get this multiplier: #4733 already
// calibrates measured-file packing against a real Windows wall-clock via
// MAX_FILES_PER_CHUNK, so inflating measured weights again here would
// double-apply the correction. An unmeasured file has no real data at all —
// it is exactly the "floor, not a verdict" case the diagnostic already warns
// about, so only its fallback gets the multiplier, and only on win32.
const WINDOWS_UNMEASURED_COST_MULTIPLIER = 2.2;
// Build the packer's weight function from a loaded timing table.
//
// A file present in the table weighs its measured duration relative to the
// table mean. A file ABSENT from it weighs 1 — the table MEAN, the same
// value a null table (missing or unparseable file) yields for every file,
// because both states mean the same thing: cost unknown.
// because both states mean the same thing: cost unknown. On win32 the
// fallback is WINDOWS_UNMEASURED_COST_MULTIPLIER instead of 1 (see #4434,
// above) — but ONLY for a file absent from an otherwise-loaded table; a
// completely missing/corrupt/empty timings file (`timings` is `null`) still
// degrades to uniform weight 1 on every platform, matching the pre-#2456
// count-based-packing invariant many existing tests depend on. Every other
// platform keeps the plain mean.
//
// This was previously `timings.medianWeight`, on the claim that an absent
// file "costs chunk balance, never a red build." That claim is false. In a
@@ -550,11 +574,14 @@ function loadTestTimings(timingsPath) {
// cause a red build: Windows conformance shard 2/3, chunk 4/6 was killed at
// 600018ms with ZERO failing tests, because files absent from the table
// packed as if they were nearly free and the chunk blew the 600s cap.
// Empirically, mean is the right estimate for an unknown file: 9 unmeasured
// files that caused the incident averaged 6659ms against a table mean of
// 7152ms — within 7%.
function makeFileWeigher(timings) {
// Empirically, mean is the right estimate for an unknown file on the
// platform the table was MEASURED on: 9 unmeasured files that caused the
// incident averaged 6659ms against a table mean of 7152ms — within 7%. That
// equivalence does not hold on win32, where the table's own sources are
// Linux-only (#4434).
function makeFileWeigher(timings, platform = process.platform) {
if (!timings) return () => 1;
const unmeasuredWeight = platform === 'win32' ? WINDOWS_UNMEASURED_COST_MULTIPLIER : 1;
return (f) => {
const key = basename(f);
// Own-property check before the lookup. This is defense-in-depth, NOT a
@@ -567,7 +594,9 @@ function makeFileWeigher(timings) {
// keeps the lookup correct for arbitrary input, since this function is
// exported and does not control its caller's strings.
const ms = Object.hasOwn(timings.timings, key) ? timings.timings[key] : undefined;
return typeof ms === 'number' && Number.isFinite(ms) && ms >= 0 ? ms / timings.mean : 1;
return typeof ms === 'number' && Number.isFinite(ms) && ms >= 0
? ms / timings.mean
: unmeasuredWeight;
};
}
@@ -1192,7 +1221,7 @@ function main() {
let weigherMemo = null;
const fileWeightOf = () => {
if (weigherMemo === null) {
weigherMemo = makeFileWeigher(loadedTimings());
weigherMemo = makeFileWeigher(loadedTimings(), process.platform);
}
return weigherMemo;
};
@@ -1854,6 +1883,7 @@ module.exports = {
defaultMaxFilesPerChunk,
loadTestTimings,
makeFileWeigher,
WINDOWS_UNMEASURED_COST_MULTIPLIER,
makeMeasuredPredicate,
packChunks,
// 2026-09-07 (PR #4497): the codex-config.test.cjs chunk-isolation fix —

View File

@@ -409,6 +409,15 @@ test('ambient GSD workstream vars are stripped by the runner', () => {
const r = runHarness(tmpDir, [], {
RUN_TESTS_MAX_CMDLINE_CHARS: '100000',
RUN_TESTS_MAX_FILES_PER_CHUNK: '3',
// #4434: without this, these tiny-*.test.cjs names fall through to the
// REAL committed tests/test-timings.json as unmeasured entries, and on
// win32 an unmeasured entry in a loaded table now weighs
// WINDOWS_UNMEASURED_COST_MULTIPLIER (2.2), not 1 — breaking the exact
// {3,2,2} count-based split this test asserts. Point at a path that
// cannot exist so the harness takes the no-table branch (uniform
// weight 1 on every platform), matching this test's actual intent:
// pure file-count chunking, independent of any cost table.
RUN_TESTS_TIMINGS_FILE: path.join(tmpDir, 'no-such-timings-4434.json'),
});
assert.strictEqual(
r.status,
@@ -2294,6 +2303,7 @@ describe('bug #969 C — ensureBuiltHooks populates hooks/dist before concurrent
const {
packChunks,
makeFileWeigher,
WINDOWS_UNMEASURED_COST_MULTIPLIER,
loadTestTimings,
positiveNumberEnv,
DEFAULT_TIMINGS_PATH,
@@ -2428,13 +2438,99 @@ describe('chunk packing weights measured cost (#2456)', () => {
// not 20/30 (the median) — see #2456 follow-up, red-next 2026-09-14.
const t = tableFrom({ 'a.test.cjs': 10000, 'b.test.cjs': 20000, 'c.test.cjs': 60000 });
try {
const weigh = makeFileWeigher(loadTestTimings(t.path));
const weigh = makeFileWeigher(loadTestTimings(t.path), 'linux');
assert.strictEqual(weigh('brand-new-test.test.cjs'), 1);
} finally {
cleanup(t.dir);
}
});
test('#4434: on win32, a file missing from the table falls back to the documented Windows multiplier (2.2), not the mean', () => {
const t = tableFrom({ 'a.test.cjs': 10000, 'b.test.cjs': 20000, 'c.test.cjs': 60000 });
try {
const weigh = makeFileWeigher(loadTestTimings(t.path), 'win32');
assert.strictEqual(weigh('brand-new-test.test.cjs'), WINDOWS_UNMEASURED_COST_MULTIPLIER);
} finally {
cleanup(t.dir);
}
});
test('#4434: on linux/darwin, a file missing from the table still falls back to the plain mean (1)', () => {
const t = tableFrom({ 'a.test.cjs': 10000, 'b.test.cjs': 20000, 'c.test.cjs': 60000 });
try {
assert.strictEqual(makeFileWeigher(loadTestTimings(t.path), 'linux')('brand-new-test.test.cjs'), 1);
assert.strictEqual(makeFileWeigher(loadTestTimings(t.path), 'darwin')('brand-new-test.test.cjs'), 1);
} finally {
cleanup(t.dir);
}
});
test('#4434: on win32, a MEASURED file is unaffected by the unmeasured-file multiplier', () => {
const t = tableFrom({ 'a.test.cjs': 10000, 'b.test.cjs': 20000, 'c.test.cjs': 60000 });
try {
const weighWin = makeFileWeigher(loadTestTimings(t.path), 'win32');
const weighLinux = makeFileWeigher(loadTestTimings(t.path), 'linux');
assert.strictEqual(
weighWin('b.test.cjs'),
weighLinux('b.test.cjs'),
'a measured file must weigh identically regardless of platform',
);
} finally {
cleanup(t.dir);
}
});
test('#4434: a completely missing table still degrades to uniform weight 1 on win32 — the Windows multiplier only applies to a file absent FROM an otherwise-loaded table', () => {
const weigh = makeFileWeigher(null, 'win32');
assert.strictEqual(
weigh('anything.test.cjs'),
1,
'no table at all must keep the pre-#2456 uniform-weight invariant on every platform, including win32',
);
});
test('property: an unmeasured file weighs exactly the Windows multiplier on win32, and exactly 1 on every other platform, for any measured table', () => {
const fc = require('fast-check');
fc.assert(
fc.property(
fc.array(fc.integer({ min: 1, max: 500000 }), { minLength: 1, maxLength: 30 }),
fc.constantFrom('win32', 'linux', 'darwin', 'freebsd', 'sunos'),
(mss, platform) => {
const timingsMap = Object.fromEntries(
mss.map((ms, i) => [`p${String(i).padStart(3, '0')}.test.cjs`, ms]),
);
const mean = mss.reduce((a, b) => a + b, 0) / mss.length;
const timings = { timings: timingsMap, mean, medianWeight: 1 };
const weigh = makeFileWeigher(timings, platform);
const expected = platform === 'win32' ? WINDOWS_UNMEASURED_COST_MULTIPLIER : 1;
assert.strictEqual(weigh('never-measured.test.cjs'), expected);
},
),
{ numRuns: 200, seed: 44340 },
);
});
test('property: a MEASURED file weighs identically regardless of platform, for any measured table', () => {
const fc = require('fast-check');
fc.assert(
fc.property(
fc.array(fc.integer({ min: 1, max: 500000 }), { minLength: 1, maxLength: 30 }),
fc.constantFrom('win32', 'linux', 'darwin', 'freebsd', 'sunos'),
(mss, platform) => {
const timingsMap = Object.fromEntries(
mss.map((ms, i) => [`p${String(i).padStart(3, '0')}.test.cjs`, ms]),
);
const mean = mss.reduce((a, b) => a + b, 0) / mss.length;
const timings = { timings: timingsMap, mean, medianWeight: 1 };
const weighPlatform = makeFileWeigher(timings, platform);
const weighLinux = makeFileWeigher(timings, 'linux');
assert.strictEqual(weighPlatform('p000.test.cjs'), weighLinux('p000.test.cjs'));
},
),
{ numRuns: 200, seed: 44341 },
);
});
test('an unknown file packs without error rather than failing the run', () => {
const chunks = packMeasured([...FILES, 'never-measured.test.cjs'], 4);
assert.ok(
@@ -2496,7 +2592,7 @@ describe('chunk packing weights measured cost (#2456)', () => {
assert.ok(table.medianWeight < 0.05, 'fixture must actually be right-skewed');
const files = Array.from({ length: 30 }, (_, i) => `unmeasured-${i}.test.cjs`);
const chunks = packChunks(files, {
weightOf: makeFileWeigher(table),
weightOf: makeFileWeigher(table, 'linux'),
maxWeight: 6,
maxChars: ROOMY_CHARS,
fixedOverhead: FIXED_OVERHEAD,
@@ -2542,7 +2638,7 @@ describe('chunk packing weights measured cost (#2456)', () => {
table.medianWeight < 0.2,
`fixture must be right-skewed; got medianWeight=${table.medianWeight}`,
);
const weigh = makeFileWeigher(table);
const weigh = makeFileWeigher(table, 'linux');
assert.strictEqual(weigh('never-measured.test.cjs'), 1);
} finally {
cleanup(t.dir);
@@ -2552,7 +2648,7 @@ describe('chunk packing weights measured cost (#2456)', () => {
test('that matches what a MISSING table already does — both mean "unknown"', () => {
const t = tableFrom(SKEWED_MS);
try {
const weigh = makeFileWeigher(loadTestTimings(t.path));
const weigh = makeFileWeigher(loadTestTimings(t.path), 'linux');
const weighNull = makeFileWeigher(null);
assert.strictEqual(weighNull('anything.test.cjs'), 1);
assert.strictEqual(weighNull('anything.test.cjs'), weigh('never-measured.test.cjs'));
@@ -2772,7 +2868,7 @@ describe('chunk packing weights measured cost (#2456)', () => {
// present in the table weighs 1 (the mean), whatever it resolves to.
const t = tableFrom({ 'a.test.cjs': 10000, 'b.test.cjs': 20000, 'c.test.cjs': 60000 });
try {
const weigh = makeFileWeigher(loadTestTimings(t.path));
const weigh = makeFileWeigher(loadTestTimings(t.path), 'linux');
for (const name of ['constructor', 'toString', 'valueOf', 'hasOwnProperty', '__proto__']) {
const w = weigh(name);
assert.strictEqual(typeof w, 'number', `${name} must weigh a number, not a function`);