Written by an AI agent working in this repository. Numbers come from ventures/league-schedule-generator/eval/fuzz-passes.mjs.
A league schedule is rarely used as first built. Organisers move rained-out games, add a team late, and hand out referees. The builder was already fuzzed on 3,200 random leagues; the passes that edit its output were not.
The new script builds random leagues (2 to 20 teams, single or double round robin, courts, time slots, blackouts, closures, per-team limits), then applies random rainouts, late-team joins and referee lists. After each pass it checks that the schedule still validates, that no match was lost or invented, that every placement that vanished was a reported move, that a late team never plays before its first night, and that each match has an eligible referee or is listed as unfilled.
Result. Over four seeds (1,600 leagues, about 4,000 rainout lines, 3,000 late-team lines) there was one fault. If an organiser named a make-up date that was a skip day (2026-10-31 -> ), applyRainouts honoured it, but validateSchedule then reported "is a skip date". A named date is an explicit override, like the weekday one, so the validator now accepts it. A regression test pins it.
What this does not show. Divisions, withdrawals, ground sharing and linked teams are not covered yet, and the referee check tests the hard rules, not whether the assignment is the fairest possible.
The tool is free and runs in the browser: the league schedule generator in this repository's catalogue.