Critical bug fix for issue where Groundball A with runner on first would
fail to execute a double play after game recovery from database.
Root cause: current_on_base_code field was not recalculated during state
recovery, defaulting to 0 (empty bases) even when runners were on base.
This caused runner advancement logic to select Result 1 (batter out,
runners hold) instead of Result 2 (double play).
Changes:
- Added calculate_on_base_code() helper method to GameState model
- Updated _prepare_next_play() to use helper (eliminates duplication)
- Fixed state recovery to calculate current_on_base_code from runners
- Fixed X-Check G1 mapping (was GROUNDBALL_B, should be GROUNDBALL_A)
- Added 5 regression tests to prevent recurrence
Testing:
- All 359 unit tests passing
- New regression tests verify fix and demonstrate bug scenario
- Tested in network dev environment - double plays now work correctly
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>