strat-gameplay-webapp/.claude/implementation/XCHECK_TEST_VALIDATION.md
Cal Corum fb282a5e54 CLAUDE: Fix critical X-Check bugs and improve dice rolling
Fixed two critical bugs in Phase 3D X-Check implementation plus
improved dice audit trail for better tracking.

BUG #1: on_base_code Mapping Error (Sequential vs Bit Field)
============================================================
The implementation incorrectly treated on_base_code as a bit field
when it is actually a sequential lookup mapping.

WRONG (bit field):
  Code 3 (0b011) → R1 + R2
  Code 4 (0b100) → R3 only

CORRECT (sequential):
  Code 3 → R3 only
  Code 4 → R1 + R2

Fixed:
- build_advancement_from_code() decoder (sequential mapping)
- build_flyball_advancement_with_error() decoder (sequential mapping)
- 13 test on_base_code values (3↔4 corrections)
- Updated documentation to clarify NOT a bit field

BUG #2: Table Data Not Matching Official Charts
================================================
7 table entries in G1_ADVANCEMENT_TABLE and G2_ADVANCEMENT_TABLE
did not match the official rulebook charts provided by user.

Fixed table entries:
- G1 Code 1, Infield In: Changed Result 3 → 2
- G1 Code 3, Normal: Changed Result 13 → 3
- G1 Code 3, Infield In: Changed Result 3 → 1
- G1 Code 4, Normal: Changed Result 3 → 13
- G1 Code 4, Infield In: Changed Result 4 → 2
- G2 Code 3, Infield In: Changed Result 3 → 1
- G2 Code 4, Normal: Changed Result 5 → 4

Also fixed 7 test expectations to match corrected tables.

IMPROVEMENT: Better Dice Audit Trail
=====================================
Updated _resolve_x_check() in PlayResolver to use proper
dice_system.roll_fielding() instead of manual die rolling.

Benefits:
- All dice tracked in audit trail (roll_id, timestamp, position)
- Automatic error_total calculation (no manual 3d6 addition)
- Consistent with codebase patterns
- Position recorded for historical analysis

Testing:
- All 59 X-Check advancement tests passing (100%)
- All 9 PlayResolver tests passing (100%)
- All table entries validated against official charts
- Complete codebase scan: no bit field operations found

Files modified:
- backend/app/core/x_check_advancement_tables.py
- backend/tests/unit/core/test_x_check_advancement_tables.py
- backend/app/core/play_resolver.py
- .claude/implementation/PHASE_3D_CRITICAL_FIX.md (documentation)
- .claude/implementation/GROUNDBALL_CHART_REFERENCE.md (new)
- .claude/implementation/XCHECK_TEST_VALIDATION.md (new)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 23:09:16 -06:00

11 KiB

X-Check Test Validation Table

Purpose: Map each test to its correct expected GroundballResultType based on official charts Source: Images #1 (G1), #2 (G2), #3 (G3) Date: 2025-11-02


Result Type Reference (from Images #4-5)

1  = BATTER_OUT_RUNNERS_HOLD
2  = DOUBLE_PLAY_AT_SECOND
3  = BATTER_OUT_RUNNERS_ADVANCE
4  = BATTER_SAFE_FORCE_OUT_AT_SECOND
5  = CONDITIONAL_ON_MIDDLE_INFIELD
6  = CONDITIONAL_ON_RIGHT_SIDE
7  = BATTER_OUT_FORCED_ONLY
8  = BATTER_OUT_FORCED_ONLY_ALT
9  = LEAD_HOLDS_TRAIL_ADVANCES
10 = DOUBLE_PLAY_HOME_TO_FIRST
11 = BATTER_SAFE_LEAD_OUT
12 = DECIDE_OPPORTUNITY
13 = CONDITIONAL_DOUBLE_PLAY

G1 Chart Reference (Image #1)

Bases (on_base_code) Infield Normal Infield In
Empty (0) 1 N/A
1st (1) 2 2
2nd (2) 12 12
3rd (3) 3 1
1st & 2nd (4) 13 2
1st & 3rd (5) 2 1
2nd & 3rd (6) 3 1
Loaded (7) 2 10

G2 Chart Reference (Image #2)

Bases (on_base_code) Infield Normal Infield In
Empty (0) 1 N/A
1st (1) 4 4
2nd (2) 12 12
3rd (3) 5 1
1st & 2nd (4) 4 4
1st & 3rd (5) 4 1
2nd & 3rd (6) 5 1
Loaded (7) 4 11

G3 Chart Reference (Image #3)

Bases (on_base_code) Infield Normal Infield In
Empty (0) 1 N/A
1st (1) 3 3
2nd (2) 12 3
3rd (3) 3 12 (DECIDE)
1st & 2nd (4) 3 3
1st & 3rd (5) 3 3
2nd & 3rd (6) 3 12 (DECIDE)
Loaded (7) 3 11

Test Validation - G1 Tests

test_g1_bases_empty_normal_no_error

  • Scenario: G1, Empty, Normal, NO
  • Current on_base_code: 0
  • Current defender_in: False
  • Expected Result: 1 (BATTER_OUT_RUNNERS_HOLD)
  • Current Expectation: BATTER_OUT_RUNNERS_HOLD
  • Status: CORRECT

test_g1_r1_only_normal_no_error

  • Scenario: G1, 1st, Normal, NO
  • Current on_base_code: 1
  • Current defender_in: False
  • Expected Result: 2 (DOUBLE_PLAY_AT_SECOND)
  • Current Expectation: DOUBLE_PLAY_AT_SECOND
  • Status: CORRECT

test_g1_r1_only_infield_in_no_error

  • Scenario: G1, 1st, In, NO
  • Current on_base_code: 1
  • Current defender_in: True
  • Expected Result: 2 (DOUBLE_PLAY_AT_SECOND)
  • Chart Says: 2
  • Current Expectation: BATTER_OUT_RUNNERS_ADVANCE (3)
  • Status: WRONG - Should be DOUBLE_PLAY_AT_SECOND (2)

test_g1_r2_only_normal_no_error

  • Scenario: G1, 2nd, Normal, NO
  • Current on_base_code: 2
  • Current defender_in: False
  • Expected Result: 12 (DECIDE_OPPORTUNITY)
  • Current Expectation: DECIDE_OPPORTUNITY
  • Status: CORRECT

test_g1_r1_r2_normal_no_error

  • Scenario: G1, 1st & 2nd, Normal, NO
  • Current on_base_code: 4
  • Current defender_in: False
  • Expected Result: 13 (CONDITIONAL_DOUBLE_PLAY)
  • Chart Says: 13
  • Current Expectation: BATTER_OUT_RUNNERS_ADVANCE (3)
  • Status: WRONG - Should be CONDITIONAL_DOUBLE_PLAY (13)

test_g1_r1_r2_infield_in_no_error

  • Scenario: G1, 1st & 2nd, In, NO
  • Current on_base_code: 4
  • Current defender_in: True
  • Expected Result: 2 (DOUBLE_PLAY_AT_SECOND)
  • Chart Says: 2
  • Current Expectation: BATTER_SAFE_FORCE_OUT_AT_SECOND (4)
  • Status: WRONG - Should be DOUBLE_PLAY_AT_SECOND (2)

test_g1_r3_only_normal_no_error

  • Scenario: G1, 3rd, Normal, NO
  • Current on_base_code: 3
  • Current defender_in: False
  • Expected Result: 3 (BATTER_OUT_RUNNERS_ADVANCE)
  • Chart Says: 3
  • Current Expectation: CONDITIONAL_DOUBLE_PLAY (13)
  • Status: WRONG - Should be BATTER_OUT_RUNNERS_ADVANCE (3)

test_g1_r3_only_infield_in_no_error

  • Scenario: G1, 3rd, In, NO
  • Current on_base_code: 3
  • Current defender_in: True
  • Expected Result: 1 (BATTER_OUT_RUNNERS_HOLD)
  • Chart Says: 1
  • Current Expectation: BATTER_OUT_RUNNERS_ADVANCE (3)
  • Status: WRONG - Should be BATTER_OUT_RUNNERS_HOLD (1)

test_g1_loaded_normal_no_error

  • Scenario: G1, Loaded, Normal, NO
  • Current on_base_code: 7
  • Current defender_in: False
  • Expected Result: 2 (DOUBLE_PLAY_AT_SECOND)
  • Current Expectation: DOUBLE_PLAY_AT_SECOND
  • Status: CORRECT

test_g1_loaded_infield_in_no_error

  • Scenario: G1, Loaded, In, NO
  • Current on_base_code: 7
  • Current defender_in: True
  • Expected Result: 10 (DOUBLE_PLAY_HOME_TO_FIRST)
  • Current Expectation: DOUBLE_PLAY_HOME_TO_FIRST
  • Status: CORRECT

Test Validation - G2 Tests

test_g2_bases_empty_normal_no_error

  • Scenario: G2, Empty, Normal, NO
  • Current on_base_code: 0
  • Current defender_in: False
  • Expected Result: 1 (BATTER_OUT_RUNNERS_HOLD)
  • Current Expectation: BATTER_OUT_RUNNERS_HOLD
  • Status: CORRECT

test_g2_r1_only_normal_no_error

  • Scenario: G2, 1st, Normal, NO
  • Current on_base_code: 1
  • Current defender_in: False
  • Expected Result: 4 (BATTER_SAFE_FORCE_OUT_AT_SECOND)
  • Current Expectation: BATTER_SAFE_FORCE_OUT_AT_SECOND
  • Status: CORRECT

test_g2_r1_r2_normal_no_error

  • Scenario: G2, 1st & 2nd, Normal, NO
  • Current on_base_code: 4
  • Current defender_in: False
  • Expected Result: 4 (BATTER_SAFE_FORCE_OUT_AT_SECOND)
  • Chart Says: 4
  • Current Expectation: CONDITIONAL_ON_MIDDLE_INFIELD (5)
  • Status: WRONG - Should be BATTER_SAFE_FORCE_OUT_AT_SECOND (4)

test_g2_r1_r2_infield_in_no_error

  • Scenario: G2, 1st & 2nd, In, NO
  • Current on_base_code: 4
  • Current defender_in: True
  • Expected Result: 4 (BATTER_SAFE_FORCE_OUT_AT_SECOND)
  • Current Expectation: BATTER_SAFE_FORCE_OUT_AT_SECOND
  • Status: CORRECT

test_g2_r3_only_normal_no_error

  • Scenario: G2, 3rd, Normal, NO
  • Current on_base_code: 3
  • Current defender_in: False
  • Expected Result: 5 (CONDITIONAL_ON_MIDDLE_INFIELD)
  • Current Expectation: CONDITIONAL_ON_MIDDLE_INFIELD
  • Status: CORRECT

test_g2_r3_only_infield_in_no_error

  • Scenario: G2, 3rd, In, NO
  • Current on_base_code: 3
  • Current defender_in: True
  • Expected Result: 1 (BATTER_OUT_RUNNERS_HOLD)
  • Chart Says: 1
  • Current Expectation: BATTER_OUT_RUNNERS_ADVANCE (3)
  • Status: WRONG - Should be BATTER_OUT_RUNNERS_HOLD (1)

test_g2_loaded_normal_no_error

  • Scenario: G2, Loaded, Normal, NO
  • Current on_base_code: 7
  • Current defender_in: False
  • Expected Result: 4 (BATTER_SAFE_FORCE_OUT_AT_SECOND)
  • Current Expectation: BATTER_SAFE_FORCE_OUT_AT_SECOND
  • Status: CORRECT

test_g2_loaded_infield_in_no_error

  • Scenario: G2, Loaded, In, NO
  • Current on_base_code: 7
  • Current defender_in: True
  • Expected Result: 11 (BATTER_SAFE_LEAD_OUT)
  • Current Expectation: BATTER_SAFE_LEAD_OUT
  • Status: CORRECT

Test Validation - G3 Tests

test_g3_bases_empty_normal_no_error

  • Scenario: G3, Empty, Normal, NO
  • Current on_base_code: 0
  • Current defender_in: False
  • Expected Result: 1 (BATTER_OUT_RUNNERS_HOLD)
  • Current Expectation: BATTER_OUT_RUNNERS_HOLD
  • Status: CORRECT

test_g3_r1_only_normal_no_error

  • Scenario: G3, 1st, Normal, NO
  • Current on_base_code: 1
  • Current defender_in: False
  • Expected Result: 3 (BATTER_OUT_RUNNERS_ADVANCE)
  • Current Expectation: BATTER_OUT_RUNNERS_ADVANCE
  • Status: CORRECT

test_g3_r2_only_normal_no_error

  • Scenario: G3, 2nd, Normal, NO
  • Current on_base_code: 2
  • Current defender_in: False
  • Expected Result: 12 (DECIDE_OPPORTUNITY)
  • Current Expectation: DECIDE_OPPORTUNITY
  • Status: CORRECT

test_g3_r2_only_infield_in_no_error

  • Scenario: G3, 2nd, In, NO
  • Current on_base_code: 2
  • Current defender_in: True
  • Expected Result: 3 (BATTER_OUT_RUNNERS_ADVANCE)
  • Current Expectation: BATTER_OUT_RUNNERS_ADVANCE
  • Status: CORRECT

test_g3_r3_only_infield_in_decide

  • Scenario: G3, 3rd, In, NO
  • Current on_base_code: 3
  • Current defender_in: True
  • Expected Result: 12 (DECIDE_OPPORTUNITY)
  • Current Expectation: DECIDE_OPPORTUNITY
  • Status: CORRECT

test_g3_r2_r3_infield_in_decide

  • Scenario: G3, 2nd & 3rd, In, NO
  • Current on_base_code: 6
  • Current defender_in: True
  • Expected Result: 12 (DECIDE_OPPORTUNITY)
  • Current Expectation: DECIDE_OPPORTUNITY
  • Status: CORRECT

test_g3_loaded_normal_no_error

  • Scenario: G3, Loaded, Normal, NO
  • Current on_base_code: 7
  • Current defender_in: False
  • Expected Result: 3 (BATTER_OUT_RUNNERS_ADVANCE)
  • Current Expectation: BATTER_OUT_RUNNERS_ADVANCE
  • Status: CORRECT

test_g3_loaded_infield_in_no_error

  • Scenario: G3, Loaded, In, NO
  • Current on_base_code: 7
  • Current defender_in: True
  • Expected Result: 11 (BATTER_SAFE_LEAD_OUT)
  • Current Expectation: BATTER_SAFE_LEAD_OUT
  • Status: CORRECT

Summary of Test Failures

Total Tests with Wrong Expectations: 6

Tests That Need Fixing:

  1. test_g1_r1_only_infield_in_no_error

    • Current: BATTER_OUT_RUNNERS_ADVANCE (3)
    • Should be: DOUBLE_PLAY_AT_SECOND (2)
  2. test_g1_r1_r2_normal_no_error

    • Current: BATTER_OUT_RUNNERS_ADVANCE (3)
    • Should be: CONDITIONAL_DOUBLE_PLAY (13)
  3. test_g1_r1_r2_infield_in_no_error

    • Current: BATTER_SAFE_FORCE_OUT_AT_SECOND (4)
    • Should be: DOUBLE_PLAY_AT_SECOND (2)
  4. test_g1_r3_only_normal_no_error

    • Current: CONDITIONAL_DOUBLE_PLAY (13)
    • Should be: BATTER_OUT_RUNNERS_ADVANCE (3)
  5. test_g1_r3_only_infield_in_no_error

    • Current: BATTER_OUT_RUNNERS_ADVANCE (3)
    • Should be: BATTER_OUT_RUNNERS_HOLD (1)
  6. test_g2_r1_r2_normal_no_error

    • Current: CONDITIONAL_ON_MIDDLE_INFIELD (5)
    • Should be: BATTER_SAFE_FORCE_OUT_AT_SECOND (4)
  7. test_g2_r3_only_infield_in_no_error

    • Current: BATTER_OUT_RUNNERS_ADVANCE (3)
    • Should be: BATTER_OUT_RUNNERS_HOLD (1)

Next Steps

  1. Validation table complete
  2. Fix the 7 tests with wrong expectations
  3. Re-run test suite to verify 59/59 passing
  4. Create git commit with ALL fixes (on_base_code + expectations)