diff --git a/gitnexus/scripts/cross-platform-shard.ts b/gitnexus/scripts/cross-platform-shard.ts index 2c52dd86b..0cd9fe8d9 100644 --- a/gitnexus/scripts/cross-platform-shard.ts +++ b/gitnexus/scripts/cross-platform-shard.ts @@ -36,9 +36,9 @@ * * Only files heavy enough to matter are listed; everything else is carried by * {@link PER_FILE_OVERHEAD_SEC} alone. These are load-balancing hints, NOT - * assertions — no - * test asserts a runtime, and drift only makes the split slightly less even, so - * a stale entry is harmless and refreshing them is optional. Deliberately not + * assertions — no test measures elapsed time against this table. Missing or + * stale heavy entries can still overload a shard; refresh them from failed + * CI logs and replay that profile in the partition tests. Deliberately not * auto-generated: a committed table is reviewable and works offline, and the * alternative (timing files at CI runtime to decide the split) would make the * partition depend on the very machine load it is trying to protect against. @@ -49,13 +49,15 @@ export const WINDOWS_WEIGHTS_SEC: Readonly> = { 'test/integration/cli-e2e.test.ts': 621, 'test/integration/worker-pool.test.ts': 222, 'test/unit/incremental-vector-extension-ordering.test.ts': 87, - // ESTIMATE, not a measurement (#2841): this suite drives more full - // `runFullAnalysis` cycles than the VECTOR sibling above, so the 8 s - // PER_FILE_OVERHEAD floor would badly under-charge it and skew the Windows - // split — the failure mode that produced the job timeouts this table exists - // to prevent. Scaled from the sibling's measured 87 s by analyze-run count. - // Replace with a real figure after the first green Windows matrix run. - 'test/unit/incremental-index-extension-dml-gate.test.ts': 180, + // Measured on Windows in run 34014266125 (#3190, 2026-09-06). These DB + // suites landed together on shard 3: the old 180s estimate and missing + // entries made a ~27-minute recorded load look like an ~12-minute shard. + // Upstream speedups may reduce these figures; retaining conservative weights + // keeps the expensive suites distributed without changing the watchdog. + 'test/unit/incremental-index-extension-dml-gate.test.ts': 414, + 'test/integration/skills-e2e.test.ts': 444, + 'test/integration/fts-extension-e2e.test.ts': 146, + 'test/integration/analyze-wal-checkpoint-failure.test.ts': 86, 'test/integration/cli-limit-e2e.test.ts': 75, 'test/unit/hooks.test.ts': 26, 'test/integration/analyze-heap-oom-e2e.test.ts': 23, diff --git a/gitnexus/test/unit/cross-platform-shard.test.ts b/gitnexus/test/unit/cross-platform-shard.test.ts index d5e83552e..30a6ecd1d 100644 --- a/gitnexus/test/unit/cross-platform-shard.test.ts +++ b/gitnexus/test/unit/cross-platform-shard.test.ts @@ -29,6 +29,33 @@ const allShards = (files: readonly string[], total: number): readonly (readonly Array.from({ length: total }, (_unused, i) => shardFiles(files, i + 1, total)); describe('cross-platform shard partition', () => { + it('does not recreate the overloaded Windows shard from the #3190 CI run', () => { + // Run 34014266125: these serialized DB suites were missing or undercharged + // in the scheduling table. Keep the observed profile independent of the + // table so deleting a weight cannot make this regression pass again. + const observed: Readonly> = { + 'test/integration/skills-e2e.test.ts': 444, + 'test/unit/incremental-index-extension-dml-gate.test.ts': 414, + 'test/integration/fts-extension-e2e.test.ts': 146, + 'test/integration/analyze-wal-checkpoint-failure.test.ts': 86, + }; + const floor = weightOf('test/unmeasured.test.ts'); + const loads = allShards(ALL_CROSS_PLATFORM, SHARD_TOTAL).map((files) => + files.reduce((sum, file) => sum + Math.max(weightOf(file), (observed[file] ?? 0) + floor), 0), + ); + // This is a deterministic replay of recorded weights, not a timing test. + // The runner's existing watchdog remains 20 minutes. + expect(Math.max(...loads)).toBeLessThan(20 * 60); + const shards = allShards(ALL_CROSS_PLATFORM, SHARD_TOTAL); + const heavyweightLocations = [ + 'test/integration/cli-e2e.test.ts', + 'test/integration/skills-e2e.test.ts', + 'test/unit/incremental-index-extension-dml-gate.test.ts', + ].map((file) => shards.findIndex((files) => files.includes(file))); + expect(heavyweightLocations).not.toContain(-1); + expect(new Set(heavyweightLocations).size).toBe(SHARD_TOTAL); + }); + it('covers every file exactly once, with no overlap between shards', () => { const shards = allShards(ALL_CROSS_PLATFORM, SHARD_TOTAL); const seen = shards.flatMap((s) => [...s]); @@ -48,7 +75,7 @@ describe('cross-platform shard partition', () => { expect(Math.max(...weights)).toBeLessThanOrEqual(ideal * 1.34); }); - it('never puts the two heaviest suites on the same shard', () => { + it('keeps the CLI and worker-pool suites on different shards', () => { // The exact shape of the outage: cli-e2e and worker-pool are 621 s and // 222 s, so together they are most of a shard's budget before anything else // is scheduled.