Three review follow-ups on the conditioning change:
- reconcileAdvancers no longer flips a result that is locked in from real
match data. Locked advancers are kept out of the demotion pool and
locked-eliminated teams out of the promotion pool; they are only touched
as a last resort when there aren't enough non-locked teams to reach the
8-advancer target (a genuinely inconsistent snapshot). buildStageInitialRecords
now also returns the lockedAdvanced set for this.
- simulateChampionsStage only honors recorded bracket results when the real
bracket pairings are actually in use (realBracket). Previously a recorded
winner could be applied to a fictitious Elo-seeded pairing.
- Per-stage Swiss W-L reconstruction is loop-invariant, so it is now computed
once per event in CSMajorSimulator.simulate and passed in via
options.swissRecords instead of being re-derived on every Monte Carlo
iteration.
Adds direct unit coverage for reconcileAdvancers (protection + last-resort
fallback) and for the bracket-gating behavior.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018zMG6JFng8bMqZYweffVuE