Commit Graph

57 Commits

Author SHA1 Message Date
Cal Corum
6d1bc77e38 CLAUDE: Fix Docker build for UV migration
Fixed Docker build issues to complete UV migration.

## Changes

### README.md
- Created backend README.md (required by hatchling build system)
- Simple quick start guide referencing CLAUDE.md

### Dockerfile
- Added `build-essential` for compiling native extensions (pendulum Rust code)
- Updated copy steps to include README.md in both dev and prod stages
- Dockerfile now successfully builds both development and production images

### .dockerignore
- Added exception `!README.md` to allow README.md through
- Keeps other *.md files excluded as intended

## Testing
-  Development image builds successfully (paper-dynasty-backend:dev-uv)
-  Production image builds successfully (paper-dynasty-backend:prod-uv)
-  Container starts and UV installs dependencies correctly
-  Application attempts to start (fails only on missing .env, as expected)

## Build Results
- Dev image: 73 packages installed (with dev deps)
- Prod image: 57 packages installed (no dev deps)
- Both stages use `uv sync --frozen` for reproducible builds
- Build time: ~1-2 minutes per stage

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 09:19:30 -06:00
Cal Corum
9a9018aab4 CLAUDE: Migrate backend to UV package management
Migrated from pip to UV (v0.9.7) for faster, more reliable package management.

## Changes

### Package Management
- Created `pyproject.toml` with project metadata and dependencies
- Generated `uv.lock` for reproducible builds (198KB)
- Migrated all dependencies from requirements.txt:
  - Production: 20 packages (FastAPI, SQLAlchemy, Pydantic, etc.)
  - Development: 6 packages (pytest, black, mypy, flake8)
- Virtual environment moved from `venv/` to `.venv/` (UV default)

### Dockerfile Updates
- Updated base image: python:3.11-slim → python:3.13-slim
- Added UV installation via official image copy
- Development stage: Uses `uv sync --frozen` for all deps
- Production stage: Uses `uv sync --frozen --no-dev` for prod only
- Commands now use `uv run` prefix for auto-activation
- Set UV environment variables:
  - UV_LINK_MODE=copy (for Docker compatibility)
  - UV_COMPILE_BYTECODE=1 (performance)
  - UV_PYTHON_DOWNLOADS=never (use system Python)

### Code Fixes
- Fixed Pydantic model circular import in `app/models/game_models.py`
  - Added runtime import of PositionRating at end of file
  - Called `model_rebuild()` on LineupPlayerState and GameState
  - Resolves "not fully defined" errors in tests

### Documentation
- Updated `backend/CLAUDE.md` with UV usage:
  - Package management section with UV commands
  - Updated all code examples to use `uv run`
  - Daily development workflow now uses UV
  - Added dependency management guide (add/remove/update)
  - Updated virtual environment location (.venv/)

### Project Files
- Added `.python-version` (3.13) for UV Python version tracking
- Removed UV template files (main.py, README.md)
- Kept existing .gitignore (already includes venv/ and .venv/)

## Testing
-  All imports work correctly
-  55/55 game model tests passing
-  500+ unit tests passing (same as before migration)
-  Test failures are pre-existing (not UV-related)

## Benefits
- 10-100x faster dependency resolution
- 2-3x faster installation
- Better dependency conflict resolution
- Single tool for everything (replaces pip, pip-tools, virtualenv)
- Reproducible builds with uv.lock

## Migration Path for Team
```bash
# One-time: Install UV
curl -LsSf https://astral.sh/uv/install.sh | sh

# In project
cd backend
uv sync  # Creates .venv and installs everything

# Daily usage
uv run python -m app.main
uv run pytest tests/ -v
```

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 08:52:11 -06:00
Cal Corum
b15b63fabe
Merge pull request #3 from calcorum/claude/review-terminal-client-gaps-011CUnv9ai4Bb42rumf5Wriu 2025-11-04 08:37:36 -06:00
Claude
263e1536a9
CLAUDE: Add interrupt plays, jump roll, and fielding roll testing commands to terminal client
Implemented features:
- Interrupt play commands:
  * force_wild_pitch - Force wild pitch interrupt (advances runners 1 base)
  * force_passed_ball - Force passed ball interrupt (advances runners 1 base)

- Jump roll testing commands:
  * roll_jump [league] - Roll jump dice for steal testing (1d20 + 2d6/1d20)
  * test_jump [count] [league] - Test jump roll distribution with statistics

- Fielding roll testing commands:
  * roll_fielding <position> [league] - Roll fielding dice (1d20 + 3d6 + 1d100)
  * test_fielding <position> [count] [league] - Test fielding roll distribution

All commands include:
- Rich terminal formatting with colored output
- Comprehensive help text and examples
- TAB completion for all arguments
- Input validation
- Statistical analysis for test commands

Jump rolls show:
- Pickoff attempts (5% chance, check_roll=1)
- Balk checks (5% chance, check_roll=2)
- Normal jump (90%, 2d6 for steal success)

Fielding rolls show:
- Range check (1d20)
- Error total (3d6, range 3-18)
- Rare play detection (SBA: d100=1, PD: error_total=5)

Testing commands provide:
- Distribution tables with percentages
- Visual bar charts
- Expected vs observed statistics
- Average calculations

Files modified:
- terminal_client/commands.py: Added 6 new command methods
- terminal_client/repl.py: Added 6 new REPL commands with help
- terminal_client/completions.py: Added TAB completion support
2025-11-04 13:54:51 +00:00
Cal Corum
d1619b4a1f CLAUDE: Phase 3 - Substitution System Core Logic
Implemented comprehensive substitution system with DB-first pattern:

## Core Components (1,027 lines)

1. SubstitutionRules (345 lines)
   - Validates pinch hitter, defensive replacement, pitching change
   - Enforces no re-entry, roster eligibility, active status
   - Comprehensive error messages with error codes

2. SubstitutionManager (552 lines)
   - Orchestrates DB-first pattern: validate → DB → state
   - Handles pinch_hit, defensive_replace, change_pitcher
   - Automatic state sync and lineup cache updates

3. Database Operations (+115 lines)
   - create_substitution(): Creates sub with full metadata
   - get_eligible_substitutes(): Lists inactive players

4. Model Enhancements (+15 lines)
   - Added get_player_by_card_id() to TeamLineupState

## Key Features

-  DB-first pattern (database is source of truth)
-  Immutable lineup history (audit trail)
-  Comprehensive validation (8+ rule checks)
-  State + DB sync guaranteed
-  Error handling at every step
-  Detailed logging for debugging

## Architecture Decisions

- Position flexibility (MVP - no eligibility check)
- Batting order inheritance (pinch hitter takes spot)
- No re-entry (matches real baseball rules)
- Validation uses in-memory state (fast)

## Remaining Work

- WebSocket event handlers (2-3 hours)
- Comprehensive testing (2-3 hours)
- API documentation (1 hour)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 23:50:33 -06:00
Cal Corum
adf7c7646d CLAUDE: Phase 3E-Final - Redis Caching & X-Check WebSocket Integration
Completed Phase 3E-Final with Redis caching upgrade and WebSocket X-Check
integration for real-time defensive play resolution.

## Redis Caching System

### New Files
- app/services/redis_client.py - Async Redis client with connection pooling
  * 10 connection pool size
  * Automatic connect/disconnect lifecycle
  * Ping health checks
  * Environment-configurable via REDIS_URL

### Modified Files
- app/services/position_rating_service.py - Migrated from in-memory to Redis
  * Redis key pattern: "position_ratings:{card_id}"
  * TTL: 86400 seconds (24 hours)
  * Graceful fallback if Redis unavailable
  * Individual and bulk cache clearing (scan_iter)
  * 760x performance improvement (0.274s API → 0.000361s Redis)

- app/main.py - Added Redis startup/shutdown events
  * Connect on app startup with settings.redis_url
  * Disconnect on shutdown
  * Warning logged if Redis connection fails

- app/config.py - Added redis_url setting
  * Default: "redis://localhost:6379/0"
  * Override via REDIS_URL environment variable

- app/services/__init__.py - Export redis_client

### Testing
- test_redis_cache.py - Live integration test
  * 10-step validation: connect, cache miss, cache hit, performance, etc.
  * Verified 760x speedup with player 8807 (7 positions)
  * Data integrity checks pass

## X-Check WebSocket Integration

### Modified Files
- app/websocket/handlers.py - Enhanced submit_manual_outcome handler
  * Serialize XCheckResult to JSON when present
  * Include x_check_details in play_resolved broadcast
  * Fixed bug: Use result.outcome instead of submitted outcome
  * Includes defender ratings, dice rolls, resolution steps

### New Files
- app/websocket/X_CHECK_FRONTEND_GUIDE.md - Comprehensive frontend documentation
  * Event structure and field definitions
  * Implementation examples (basic, enhanced, polished)
  * Error handling and common pitfalls
  * Test scenarios with expected data
  * League differences (SBA vs PD)
  * 500+ lines of frontend integration guide

- app/websocket/MANUAL_VS_AUTO_MODE.md - Workflow documentation
  * Manual mode: Players read cards, submit outcomes
  * Auto mode: System generates from ratings (PD only)
  * X-Check resolution comparison
  * UI recommendations for each mode
  * Configuration reference
  * Testing considerations

### Testing
- tests/integration/test_xcheck_websocket.py - WebSocket integration tests
  * Test X-Check play includes x_check_details 
  * Test non-X-Check plays don't include details 
  * Full event structure validation

## Performance Impact

- Redis caching: 760x speedup for position ratings
- WebSocket: No performance impact (optional field)
- Graceful degradation: System works without Redis

## Phase 3E-Final Progress

-  WebSocket event handlers for X-Check UI
-  Frontend integration documentation
-  Redis caching upgrade (from in-memory)
-  Redis connection pool in app lifecycle
-  Integration tests (2 WebSocket, 1 Redis)
-  Manual vs Auto mode workflow documentation

Phase 3E-Final: 100% Complete
Phase 3 Overall: ~98% Complete

## Testing Results

All tests passing:
- X-Check table tests: 36/36 
- WebSocket integration: 2/2 
- Redis live test: 10/10 steps 

## Configuration

Development:
  REDIS_URL=redis://localhost:6379/0  (Docker Compose)

Production options:
  REDIS_URL=redis://10.10.0.42:6379/0  (DB server)
  REDIS_URL=redis://your-redis-cloud.com:6379/0  (Managed)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 22:46:59 -06:00
Cal Corum
7d150183d4 CLAUDE: Update documentation for Phase 3E-Main completion
Updated NEXT_SESSION.md to reflect Phase 3E-Main completion:
- Marked Phase 3E-Main as 100% complete (position ratings integration)
- Overall Phase 3E progress now 90%
- Updated Phase 3 overall progress to ~95%
- Documented all accomplishments and live test results
- Outlined remaining Phase 3E-Final tasks (10%):
  * WebSocket event handlers for X-Check UI
  * Redis caching upgrade from in-memory
  * Full defensive lineup evaluation
  * Manual vs Auto mode workflows

Included comprehensive session handoff:
- Live API test results with player 8807 (7 positions)
- Performance metrics (16,601x cache speedup)
- All files created/modified
- Quick start guide for next session
- Technical architecture notes

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 21:40:09 -06:00
Cal Corum
02e816a57f CLAUDE: Phase 3E-Main - Position Ratings Integration for X-Check Resolution
Complete integration of position ratings system enabling X-Check defensive plays
to use actual player ratings from PD API with intelligent fallbacks for SBA.

**Live API Testing Verified**: 
- Endpoint: GET https://pd.manticorum.com/api/v2/cardpositions?player_id=8807
- Response: 200 OK, 7 positions retrieved successfully
- Cache performance: 16,601x faster (API: 0.214s, Cache: 0.000s)
- Data quality: Real defensive ratings (range 1-5, error 0-88)

**Architecture Overview**:
- League-aware: PD league fetches ratings from API, SBA uses defaults
- StateManager integration: Defenders retrieved from lineup cache
- Self-contained GameState: All data needed for X-Check in memory
- Graceful degradation: Falls back to league averages if ratings unavailable

**Files Created**:

1. app/services/pd_api_client.py (NEW)
   - PdApiClient class for PD API integration
   - Endpoint: GET /api/v2/cardpositions?player_id={id}&position={pos}
   - Async HTTP client using httpx (already in requirements.txt)
   - Optional position filtering: get_position_ratings(8807, ['SS', '2B'])
   - Returns List[PositionRating] for all positions player can play
   - Handles both list and dict response formats
   - Comprehensive error handling with logging

2. app/services/position_rating_service.py (NEW)
   - PositionRatingService with in-memory caching
   - get_ratings_for_card(card_id, league_id) - All positions
   - get_rating_for_position(card_id, position, league_id) - Specific position
   - Cache performance: >16,000x faster on hits
   - Singleton pattern: position_rating_service instance
   - TODO Phase 3E-Final: Upgrade to Redis

3. app/services/__init__.py (NEW)
   - Package exports for clean imports

4. test_pd_api_live.py (NEW)
   - Live API integration test script
   - Tests with real PD player 8807 (7 positions)
   - Verifies caching, filtering, GameState integration
   - Run: `python test_pd_api_live.py`

5. test_pd_api_mock.py (NEW)
   - Mock integration test for CI/CD
   - Demonstrates flow without API dependency

6. tests/integration/test_position_ratings_api.py (NEW)
   - Pytest integration test suite
   - Real API tests with player 8807
   - Cache verification, SBA skip logic
   - Full end-to-end GameState flow

**Files Modified**:

1. app/models/game_models.py
   - LineupPlayerState: Added position_rating field (Optional[PositionRating])
   - GameState: Added get_defender_for_position(position, state_manager)
   - Uses StateManager's lineup cache to find active defender by position
   - Iterates through lineup.players to match position + is_active

2. app/config/league_configs.py
   - SbaConfig: Added supports_position_ratings() → False
   - PdConfig: Added supports_position_ratings() → True
   - Enables league-specific behavior without hardcoded conditionals

3. app/core/play_resolver.py
   - __init__: Added state_manager parameter for X-Check defender lookup
   - _resolve_x_check(): Replaced placeholder defender ratings with actual lookup
   - Uses league config to check if ratings supported
   - Fetches defender via state.get_defender_for_position()
   - Falls back to defaults (range=3, error=15) if ratings unavailable
   - Detailed logging for debugging rating lookups

4. app/core/game_engine.py
   - Added _load_position_ratings_for_lineup() method
   - Loads all position ratings at game start for PD league
   - Skips loading for SBA (league config check)
   - start_game(): Calls rating loader for both teams before marking active
   - PlayResolver instantiation: Now passes state_manager parameter
   - Logs: "Loaded X/9 position ratings for team Y"

**X-Check Resolution Flow**:
1. League check: config.supports_position_ratings()?
2. Get defender: state.get_defender_for_position(pos, state_manager)
3. If PD + defender.position_rating exists: Use actual range/error
4. Else if defender found: Use defaults (range=3, error=15)
5. Else: Log warning, use defaults

**Position Rating Loading (Game Start)**:
1. Check if league supports ratings (PD only)
2. Get lineup from StateManager cache
3. For each player:
   - Fetch rating from position_rating_service (with caching)
   - Set player.position_rating field
4. Cache API responses (16,000x faster on subsequent access)
5. Log success: "Loaded X/9 position ratings for team Y"

**Live Test Results (Player 8807)**:
```
Position   Range    Error    Innings
CF         3        2        372
2B         3        8        212
SS         4        12       159
RF         2        2        74
LF         3        2        62
1B         4        0        46
3B         3        65       34
```

**Testing**:
-  Live API: Player 8807 → 7 positions retrieved successfully
-  Caching: 16,601x performance improvement
-  League config: SBA=False, PD=True
-  GameState integration: Defender lookup working
-  Existing tests: 27/28 config tests passing (1 pre-existing URL failure)
-  Syntax validation: All files compile successfully

**Benefits**:
-  X-Check now uses real defensive ratings in PD league
-  SBA league continues working with manual entry (uses defaults)
-  No breaking changes to existing functionality
-  Graceful degradation if API unavailable
-  In-memory caching reduces API calls by >99%
-  League-agnostic design via config system
-  Production-ready with live API verification

**Phase 3E Status**: Main complete (85% → 90%)
**Next**: Phase 3E-Final (WebSocket events, Redis upgrade, full defensive lineup)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 21:00:37 -06:00
Cal Corum
d560844704 CLAUDE: Phase 3E-Prep - Refactor GameState to use full LineupPlayerState objects
**Architectural Improvement**: Unified player references in GameState

**Changed**: Make all player references consistent
- BEFORE: current_batter/pitcher/catcher were IDs (int)
- AFTER: current_batter/pitcher/catcher are full LineupPlayerState objects
- Matches pattern of on_first/on_second/on_third (already objects)

**Benefits**:
1. Consistent API - all player references use same type
2. Self-contained GameState - everything needed for resolution
3. No lookups needed - direct access to player data
4. Sets foundation for Phase 3E-Main (adding position ratings)

**Files Modified**:
- app/models/game_models.py: Changed current_batter/pitcher/catcher to objects
- app/core/game_engine.py: Updated _prepare_next_play() to populate full objects
- app/core/state_manager.py: Create placeholder batter on game creation
- tests/unit/models/test_game_models.py: Updated all 27 GameState tests

**Database Operations**:
- No schema changes needed
- Play table still stores IDs (for referential integrity)
- IDs extracted from objects when saving: state.current_batter.lineup_id

**Testing**:
- All 27 GameState tests passing
- No regressions in existing functionality
- Type checking passes

**Next**: Phase 3E-Main - Add PositionRating dataclass and load ratings at game start

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:11:40 -06:00
Cal Corum
7417a3f450 Offline catchup 2025-11-03 12:43:54 -06:00
Cal Corum
fc0e2f100c CLAUDE: Integrate X-Check advancement with full GameState support
Updated X-Check runner advancement functions to properly delegate to
existing result handlers for non-error cases.

Changes:
- Updated x_check_g1/g2/g3 signatures to accept GameState, hit_location,
  and defensive_decision parameters
- Updated x_check_f1/f2/f3 signatures to accept GameState and hit_location
- Implemented delegation logic: error cases use simple tables, non-error
  cases delegate to existing tested result handlers (_execute_result,
  _fb_result_*)
- Updated PlayResolver._get_x_check_advancement() to pass new parameters
- Updated all tests to provide required GameState fixtures

Benefits:
- Reuses 13 existing groundball + 4 flyball result handlers (DRY)
- No DP probability needed - X-Check d20 already tested defender
- Full game context: real lineup IDs, outs count, conditional logic
- Error cases remain simple and efficient

Test Results: 264/265 core tests passing (1 pre-existing dice failure)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 00:21:52 -06:00
Cal Corum
5f42576694 CLAUDE: Remove double-dipping on double play probability
Fixed incorrect double play logic that was rolling for probability
twice - once for the chart result and again for execution.

Changes:
- Removed _calculate_double_play_probability() method entirely
- Updated _gb_result_2() to execute DP deterministically
- Updated _gb_result_10() to execute DP deterministically
- Updated _gb_result_13() to execute DP deterministically
- Removed TestDoublePlayProbability test class (5 tests)
- Updated DP tests to reflect deterministic behavior

Logic: Chart already determines outcome via dice roll. When chart
says "Result 2: Double Play", the DP happens (if <2 outs and runner
on 1st exists). No additional probability roll needed.

Tests: 55/55 runner advancement tests passing

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 23:58:19 -06:00
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
Cal Corum
7f74dc6662 CLAUDE: Update documentation for Phase 3C completion
Added comprehensive Phase 3C documentation to CLAUDE.md:
- X-Check resolution logic implementation details
- Helper methods and integration points
- Key features and algorithms
- Placeholders for future phases
- Test coverage and verification results

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 14:51:37 -06:00
Cal Corum
10515cb20d CLAUDE: Implement Phase 3C - X-Check Resolution Logic
Implemented complete X-Check resolution system in PlayResolver with
defense range and error table lookups.

Changes:
- Added X_CHECK case to resolve_outcome() method
- Implemented _resolve_x_check() main resolution method
- Added _adjust_range_for_defensive_position() for playing in logic
- Added _lookup_defense_table() for defense range table lookups
- Added _apply_hash_conversion() for G2#/G3# to SI2 conversion
- Added _lookup_error_chart() for error determination
- Added _determine_final_x_check_outcome() for final outcome mapping
- Added XCheckResult to PlayResult dataclass
- Integrated all Phase 3B tables (defense, error, holding runners)

Features:
- Full defense table lookup (infield, outfield, catcher)
- Error chart lookup with priority ordering (RP > E3 > E2 > E1 > NO)
- Range adjustment for playing in (+1, max 5)
- Hash conversion based on playing in OR holding runner
- Error overrides outs to ERROR outcome
- Rare play handling
- Detailed X-Check audit trail in XCheckResult

Placeholders (to be completed in later phases):
- Defender retrieval from lineup (currently uses placeholder ratings)
- SPD test implementation (currently defaults to G3)
- Batter handedness from player model
- Runner advancement tables (Phase 3D)

Testing:
- All 9 PlayResolver tests passing
- All 36 X-Check table tests passing
- All 51 runner advancement tests passing
- 325/327 total tests passing (2 pre-existing failures unrelated)
- play_resolver.py compiles successfully

Phase 3C Status: 100% COMPLETE 
Ready for Phase 3D (Runner Advancement Tables)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 14:48:17 -06:00
Cal Corum
cc5bf43e84 CLAUDE: Complete Phase 3B - Add all 6 infield error charts
Added complete error chart data for all infield positions to finalize
Phase 3B X-Check league config tables implementation.

Changes:
- Added CATCHER_ERROR_CHART (17 ratings: 0-16)
- Added FIRST_BASE_ERROR_CHART (31 ratings: 0-30)
- Added SECOND_BASE_ERROR_CHART (40 ratings: 0-71, sparse)
- Added THIRD_BASE_ERROR_CHART (45 ratings: 0-65, sparse)
- Added SHORTSTOP_ERROR_CHART (43 ratings: 0-88, sparse)
- Added PITCHER_ERROR_CHART (40 ratings: 0-51, sparse)

All charts follow same structure as outfield charts with E3 field
(empty for infield positions). Total ~250 lines of error chart data.

Testing:
- Updated test_infield_error_charts_complete() to verify charts populated
- All 36 X-Check table tests passing
- Verified chart structure matches outfield charts

Phase 3B Status: 100% COMPLETE 
All defense tables complete, all error charts complete, ready for Phase 3C

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 14:33:59 -06:00
Cal Corum
0b6076d5b8 CLAUDE: Implement Phase 3B - X-Check league config tables
Complete X-Check resolution table system for defensive play outcomes.

Components:
- Defense range tables (20×5) for infield, outfield, catcher
- Error charts for LF/RF and CF (ratings 0-25)
- Placeholder error charts for P, C, 1B, 2B, 3B, SS (awaiting data)
- get_fielders_holding_runners() - Complete implementation
- get_error_chart_for_position() - Maps all 9 positions
- 6 X-Check placeholder advancement functions (g1-g3, f1-f3)

League Config Integration:
- Both SbaConfig and PdConfig include X-Check tables
- Shared common tables via league_configs.py
- Attributes: x_check_defense_tables, x_check_error_charts, x_check_holding_runners

Testing:
- 36 tests for X-Check tables (all passing)
- 9 tests for X-Check placeholders (all passing)
- Total: 45/45 tests passing

Documentation:
- Updated backend/CLAUDE.md with Phase 3B section
- Updated app/config/CLAUDE.md with X-Check tables documentation
- Updated app/core/CLAUDE.md with X-Check placeholder functions
- Updated tests/CLAUDE.md with new test counts (519 unit tests)
- Updated phase-3b-league-config-tables.md (marked complete)
- Updated NEXT_SESSION.md with Phase 3B completion

What's Pending:
- 6 infield error charts need actual data (P, C, 1B, 2B, 3B, SS)
- Phase 3C will implement full X-Check resolution logic

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-01 19:50:55 -05:00
Cal Corum
a1f42a93b8 CLAUDE: Implement Phase 3A - X-Check data models and enums
Add foundational data structures for X-Check play resolution system:

Models Added:
- PositionRating: Defensive ratings (range 1-5, error 0-88) for X-Check resolution
- XCheckResult: Dataclass tracking complete X-Check resolution flow with dice rolls,
  conversions (SPD test, G2#/G3#→SI2), error results, and final outcomes
- BasePlayer.active_position_rating: Optional field for current defensive position

Enums Extended:
- PlayOutcome.X_CHECK: New outcome type requiring special resolution
- PlayOutcome.is_x_check(): Helper method for type checking

Documentation Enhanced:
- Play.check_pos: Documented as X-Check position identifier
- Play.hit_type: Documented with examples (single_2_plus_error_1, etc.)

Utilities Added:
- app/core/cache.py: Redis cache key helpers for player positions and game state

Implementation Planning:
- Complete 6-phase implementation plan (3A-3F) documented in .claude/implementation/
- Phase 3A complete with all acceptance criteria met
- Zero breaking changes, all existing tests passing

Next: Phase 3B will add defense tables, error charts, and advancement logic

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-01 15:32:09 -05:00
Cal Corum
a696473d0a CLAUDE: Integrate flyball advancement with RunnerAdvancement system
Major Phase 2 refactoring to consolidate runner advancement logic:

**Flyball System Enhancement**:
- Add FLYOUT_BQ variant (medium-shallow depth)
- 4 flyball types with clear semantics: A (deep), B (medium), BQ (medium-shallow), C (shallow)
- Updated helper methods to include FLYOUT_BQ

**RunnerAdvancement Integration**:
- Extend runner_advancement.py to handle both groundballs AND flyballs
- advance_runners() routes to _advance_runners_groundball() or _advance_runners_flyball()
- Comprehensive flyball logic with proper DECIDE mechanics per flyball type
- No-op movements recorded for state recovery consistency

**PlayResolver Refactoring**:
- Consolidate all 4 flyball outcomes to delegate to RunnerAdvancement (DRY)
- Eliminate duplicate flyball resolution code
- Rename helpers for clarity: _advance_on_single_1/_advance_on_single_2 (was _advance_on_single)
- Fix single/double advancement logic for different hit types

**State Recovery Fix**:
- Fix state_manager.py game recovery to build LineupPlayerState objects properly
- Use get_lineup_player() helper to construct from lineup data
- Correctly track runners in on_first/on_second/on_third fields (matches Phase 2 model)

**Database Support**:
- Add runner tracking fields to play data for accurate recovery
- Include batter_id, on_first_id, on_second_id, on_third_id, and *_final fields

**Type Safety Improvements**:
- Fix lineup_id access throughout runner_advancement.py (was accessing on_first directly, now on_first.lineup_id)
- Make current_batter_lineup_id non-optional (always set by _prepare_next_play)
- Add type: ignore for known SQLAlchemy false positives

**Documentation**:
- Update CLAUDE.md with comprehensive flyball documentation
- Add flyball types table, usage examples, and test coverage notes
- Document differences between groundball and flyball mechanics

**Testing**:
- Add test_flyball_advancement.py with 21 flyball tests
- Coverage: all 4 types, DECIDE scenarios, no-op movements, edge cases

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 17:04:23 -05:00
Cal Corum
23a0a1db4e CLAUDE: Update tests to match Phase 2 model changes
- Update test fixtures to provide required current_batter_lineup_id field
- Update validator tests for new infield depth values (infield_in, normal, corners_in)
- Update runner advancement tests to match refactored runner management
- Update game model tests to work with direct base references
- Update play resolver tests for enhanced logic
- Add missing imports in test files

All changes ensure tests align with recent Phase 2 implementation updates
including the transition from RunnerState list to direct base references
(on_first, on_second, on_third) in GameState model.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 16:11:39 -05:00
Cal Corum
76e24ab22b CLAUDE: Refactor ManualOutcomeSubmission to use PlayOutcome enum + comprehensive documentation
## Refactoring
- Changed `ManualOutcomeSubmission.outcome` from `str` to `PlayOutcome` enum type
- Removed custom validator (Pydantic handles enum validation automatically)
- Added direct import of PlayOutcome (no circular dependency due to TYPE_CHECKING guard)
- Updated tests to use enum values while maintaining backward compatibility

Benefits:
- Better type safety with IDE autocomplete
- Cleaner code (removed 15 lines of validator boilerplate)
- Backward compatible (Pydantic auto-converts strings to enum)
- Access to helper methods (is_hit(), is_out(), etc.)

Files modified:
- app/models/game_models.py: Enum type + import
- tests/unit/config/test_result_charts.py: Updated 7 tests + added compatibility test

## Documentation
Created comprehensive CLAUDE.md files for all backend/app/ subdirectories to help future AI agents quickly understand and work with the code.

Added 8,799 lines of documentation covering:
- api/ (906 lines): FastAPI routes, health checks, auth patterns
- config/ (906 lines): League configs, PlayOutcome enum, result charts
- core/ (1,288 lines): GameEngine, StateManager, PlayResolver, dice system
- data/ (937 lines): API clients (planned), caching layer
- database/ (945 lines): Async sessions, operations, recovery
- models/ (1,270 lines): Pydantic/SQLAlchemy models, polymorphic patterns
- utils/ (959 lines): Logging, JWT auth, security
- websocket/ (1,588 lines): Socket.io handlers, real-time events
- tests/ (475 lines): Testing patterns and structure

Each CLAUDE.md includes:
- Purpose & architecture overview
- Key components with detailed explanations
- Patterns & conventions
- Integration points
- Common tasks (step-by-step guides)
- Troubleshooting with solutions
- Working code examples
- Testing guidance

Total changes: +9,294 lines / -24 lines
Tests: All passing (62/62 model tests, 7/7 ManualOutcomeSubmission tests)
2025-10-31 16:03:54 -05:00
Cal Corum
e2f1d6079f CLAUDE: Implement Week 7 Task 6 - PlayResolver Integration with RunnerAdvancement
Major Refactor: Outcome-First Architecture
- PlayResolver now accepts league_id and auto_mode in constructor
- Added core resolve_outcome() method - all resolution logic in one place
- Added resolve_manual_play() wrapper for manual submissions (primary)
- Added resolve_auto_play() wrapper for PD auto mode (rare)
- Removed SimplifiedResultChart (obsolete with new architecture)
- Removed play_resolver singleton

RunnerAdvancement Integration:
- All groundball outcomes (GROUNDBALL_A/B/C) now use RunnerAdvancement
- Proper DP probability calculation with positioning modifiers
- Hit location tracked for all relevant outcomes
- 13 result types fully integrated from advancement charts

Game State Updates:
- Added auto_mode field to GameState (stored per-game)
- Updated state_manager.create_game() to accept auto_mode parameter
- GameEngine now uses state.auto_mode to create appropriate resolver

League Configuration:
- Added supports_auto_mode() to BaseGameConfig
- SbaConfig: returns False (no digitized cards)
- PdConfig: returns True (has digitized ratings)
- PlayResolver validates auto mode support and raises error for SBA

Play Results:
- Added hit_location field to PlayResult
- Groundballs include location from RunnerAdvancement
- Flyouts track hit_location for tag-up logic (future)
- Other outcomes have hit_location=None

Testing:
- Completely rewrote test_play_resolver.py for new architecture
- 9 new tests covering initialization, strikeouts, walks, groundballs, home runs
- All 9 tests passing
- All 180 core tests still passing (1 pre-existing failure unrelated)

Terminal Client:
- No changes needed - defaults to manual mode (auto_mode=False)
- Perfect for human testing of manual submissions

This completes Week 7 Task 6 - the final task of Week 7!
Week 7 is now 100% complete with all 8 tasks done.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 08:20:52 -05:00
Cal Corum
102cbb6081 CLAUDE: Implement Week 7 Tasks 4 & 5 - Runner advancement logic and double play mechanics
- Created runner_advancement.py with complete groundball advancement system
- Implemented GroundballResultType IntEnum with 13 rulebook-aligned results
- Built RunnerAdvancement class with chart lookup logic (Infield Back/In)
- Implemented all 13 result handlers (gb_result_1 through gb_result_13)
- Added DECIDE mechanic support for interactive runner advancement decisions
- Implemented double play probability calculation with positioning modifiers
- Created 30 comprehensive unit tests covering all scenarios (100% passing)

Key Features:
- Supports Infield Back and Infield In defensive positioning
- Handles Corners In hybrid positioning (applies In rules to corner fielders)
- Conditional results based on hit location (middle IF, right side, corners)
- Force play detection and advancement logic
- Double play mechanics with probability-based success (45% base rate)
- Result types match official rulebook exactly (1-13)

Architecture:
- IntEnum for result types (type-safe, self-documenting)
- Comprehensive hit location tracking (1B, 2B, SS, 3B, P, C, LF, CF, RF)
- Dataclasses for movements (RunnerMovement, AdvancementResult)
- Probability modifiers: Infield In (-15%), hit location (±10%)

Testing:
- 30 unit tests covering chart lookup, all result types, and edge cases
- Double play probability validation
- All on-base codes (0-7) tested
- All groundball types (A, B, C) verified

Status: Week 7 Tasks 4 & 5 complete (~87% of Week 7 finished)
Next: Task 6 (PlayResolver Integration)

Related: #task4 #task5 #runner-advancement #double-play #week7
2025-10-30 23:32:44 -05:00
Cal Corum
9cae63ac43 CLAUDE: Implement Week 7 Task 7 - WebSocket manual outcome handlers
Complete manual outcome workflow for SBA and PD manual mode gameplay:

**WebSocket Event Handlers** (app/websocket/handlers.py):
- roll_dice: Server rolls dice, stores in state, broadcasts to players
- submit_manual_outcome: Validates and processes player submissions
- Events: dice_rolled, outcome_accepted, outcome_rejected, play_resolved

**Game Engine Integration** (app/core/game_engine.py):
- resolve_manual_play(): Processes manual outcomes with server dice
- Uses ab_roll for audit trail, player outcome for resolution
- Same orchestration as resolve_play() (save, update, advance inning)

**Data Model** (app/models/game_models.py):
- pending_manual_roll: Stores server dice between roll and submission

**Terminal Client** (terminal_client/):
- roll_dice command: Roll dice and display results
- manual_outcome command: Submit outcomes from physical cards
- Both integrated into REPL for testing

**Tests** (tests/unit/websocket/test_manual_outcome_handlers.py):
- 12 comprehensive tests covering all validation paths
- All tests passing (roll_dice: 4, submit_manual_outcome: 8)

**Key Decisions**:
- Server rolls dice for fairness (not players!)
- One-time roll usage (cleared after submission)
- Early validation (check pending roll before accepting)
- Field-level error messages for clear feedback

**Impact**:
- Complete manual mode workflow ready
- Frontend WebSocket integration supported
- Terminal testing commands available
- Audit trail with server-rolled dice maintained

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 22:51:31 -05:00
Cal Corum
9b03fb555b CLAUDE: Implement play rollback functionality for error recovery
Add ability to roll back the last N plays, useful for correcting mistakes
or recovering from corrupted plays. Deletes plays from database and
reconstructs game state by replaying remaining plays.

Database Operations (app/database/operations.py):
- delete_plays_after(): Delete plays with play_number > target
- delete_substitutions_after(): Delete lineup entries with after_play >= target
- delete_rolls_after(): Delete dice rolls (kept for reference, not used)

Game Engine (app/core/game_engine.py):
- rollback_plays(): Main rollback orchestration
  - Validates: num_plays > 0, enough plays exist, game not completed
  - Deletes plays and substitutions from database
  - Clears in-memory roll tracking
  - Calls state_manager.recover_game() to rebuild state
  - Returns updated GameState

Terminal Client (terminal_client/commands.py, terminal_client/repl.py):
- rollback_plays(): Command wrapper with user-friendly output
- do_rollback(): REPL command with argument parsing

Usage:
   > rollback 3

Validations:
- Cannot roll back more plays than exist
- Cannot roll back completed games
- Rolling back across innings is allowed
- Substitutions after rolled-back plays are undone

Testing:
-  Successfully rolls back 2 plays from 5-play game
-  Correctly validates rollback of 10 plays when only 2 exist
-  Game state properly reconstructed via replay

Note: Dice rolls kept in database for auditing (don't affect state).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 16:02:51 -05:00
Cal Corum
8ecce0f5ad CLAUDE: Implement forced outcome feature for terminal client testing
Add ability to force specific play outcomes instead of random dice rolls,
enabling targeted testing of specific game scenarios.

Changes:
- play_resolver.resolve_play(): Add forced_outcome parameter, bypass dice
  rolls when provided, create dummy AbRoll with placeholder values
- game_engine.resolve_play(): Accept and pass through forced_outcome param
- terminal_client/commands.py: Pass forced_outcome to game engine

Testing:
- Verified TRIPLE, HOMERUN, and STRIKEOUT outcomes work correctly
- Dummy AbRoll properly constructed with all required fields
- Game state updates correctly with forced outcomes

Example usage in REPL:
  resolve_with triple
  resolve_with homerun

Fixes terminal client testing workflow to allow controlled scenarios.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 15:39:35 -05:00
Cal Corum
ee94fcfa96 CLAUDE: Fix terminal client import error in resolve_play command
Remove unused PlayResult creation code that had incorrect import path
and missing required fields. The forced outcome feature is experimental
and not yet implemented - the code was just showing warnings anyway.

Fixes ImportError when running 'resolve_with <outcome>' command.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 15:29:51 -05:00
Cal Corum
b40465ca8a CLAUDE: Add terminal client commands for manual outcome testing
New Commands:
- manual_outcome <outcome> [location] - Validates ManualOutcomeSubmission
  - Tests outcome and location validation
  - Shows which outcomes require hit location
  - Displays clear validation errors

- test_location <outcome> [handedness] [count] - Tests hit location distribution
  - Generates sample hit locations for an outcome
  - Shows distribution table with percentages
  - Validates pull rates (45% pull, 35% center, 20% opposite)
  - Supports both LHB and RHB

Implementation:
- Added validate_manual_outcome() to GameCommands class
- Added test_hit_location() to GameCommands class
- Added do_manual_outcome() to REPL
- Added do_test_location() to REPL
- Uses ManualOutcomeSubmission model from Task 3
- Uses calculate_hit_location() helper from Task 3

Testing:
- Tested manual_outcome with valid outcomes (groundball_c SS, strikeout)
- Tested manual_outcome with invalid outcome (proper error display)
- Tested test_location with groundball_c for RHB (shows distribution)
- All validation and display working correctly

Note: Full play resolution integration deferred to Week 7 Task 6 (WebSocket handlers).
      These commands validate and test the new models but don't resolve plays yet.

Files Modified:
- terminal_client/commands.py (+117 lines)
- terminal_client/repl.py (+65 lines)
2025-10-30 15:25:30 -05:00
Cal Corum
9245b4e008 CLAUDE: Implement Week 7 Task 3 - Result chart abstraction and PD auto mode
Core Implementation:
- Added ResultChart abstract base class with get_outcome() method
- Implemented calculate_hit_location() helper for hit distribution
  - 45% pull, 35% center, 20% opposite field
  - RHB pulls left, LHB pulls right
  - Groundballs → infield positions, flyouts → outfield positions
- Added PlayOutcome.requires_hit_location() helper method
  - Returns True for groundballs and flyouts only

Manual Mode Support:
- Added ManualResultChart (passthrough for interface completeness)
- Manual mode doesn't use result charts - players submit directly
- Added ManualOutcomeSubmission model for WebSocket submissions
  - Validates PlayOutcome enum values
  - Validates hit location positions (1B, 2B, SS, 3B, LF, CF, RF, P, C)

PD Auto Mode Implementation:
- Implemented PdAutoResultChart for automated outcome generation
  - Coin flip (50/50) to choose batting or pitching card
  - Gets rating for correct handedness matchup
  - Builds cumulative distribution from rating percentages
  - Rolls 1d100 to select outcome
  - Calculates hit location using handedness and pull rates
- Maps rating fields to PlayOutcome enum:
  - Common: homerun, triple, doubles, singles, walks, strikeouts
  - Batting-specific: lineouts, popouts, flyout variants, groundout variants
  - Pitching-specific: uncapped singles/doubles, flyouts by location
- Proper error handling when card data missing

Testing:
- Created 21 comprehensive unit tests (all passing)
- Helper function tests (calculate_hit_location)
- PlayOutcome helper tests (requires_hit_location)
- ManualResultChart tests (NotImplementedError)
- PdAutoResultChart tests:
  - Coin flip distribution (~50/50)
  - Handedness matchup selection
  - Cumulative distribution building
  - Outcome selection from probabilities
  - Hit location calculation
  - Error handling for missing cards
  - Statistical distribution verification (1000 trials)
- ManualOutcomeSubmission validation tests
  - Valid/invalid outcomes
  - Valid/invalid hit locations
  - Optional location handling

Deferred to Future Tasks:
- PlayResolver integration (Phase 6 - Week 7 Task 3B)
- Terminal client manual outcome command (Phase 8)
- WebSocket handlers for manual submissions (Week 7 Task 6)
- Runner advancement logic using hit locations (Week 7 Task 4)

Files Modified:
- app/config/result_charts.py: Added base class, auto mode, and helpers
- app/models/game_models.py: Added ManualOutcomeSubmission model
- tests/unit/config/test_result_charts.py: 21 comprehensive tests

All tests passing, no regressions.
2025-10-30 12:42:41 -05:00
Cal Corum
c0051d2a65 CLAUDE: Fix defensive decision validation for corners_in/infield_in depths
- Updated validators.py to use is_runner_on_third() helper method instead of hardcoded on_base_code values
- Fixed DefensiveDecision Pydantic model: infield depths now ['infield_in', 'normal', 'corners_in']
- Fixed DefensiveDecision Pydantic model: outfield depths now ['in', 'normal'] (removed 'back')
- Removed invalid double_play depth tests (depth doesn't exist)
- Added proper tests for corners_in and infield_in validation (requires runner on third)
- All 54 validator tests now passing

Changes maintain consistency between Pydantic validation and GameValidator logic.
2025-10-30 10:25:01 -05:00
Cal Corum
121a9082f1 CLAUDE: Implement Week 7 Task 2 - Decision Validators
- Enhanced validate_defensive_decision() with comprehensive validation:
  - Validate all alignments (normal, shifted_left, shifted_right, extreme_shift)
  - Validate all infield depths (in, normal, back, double_play)
  - Validate all outfield depths (in, normal, back)
  - Validate hold_runners require actual runners on specified bases
  - Validate hold_runners only on bases 1, 2, or 3
  - Validate double_play depth requires runner on first
  - Validate double_play depth not allowed with 2 outs

- Enhanced validate_offensive_decision() with comprehensive validation:
  - Validate all approaches (normal, contact, power, patient)
  - Validate steal_attempts only to bases 2, 3, or 4
  - Validate steal_attempts require runner on base-1
  - Validate bunt_attempt not allowed with 2 outs
  - Validate bunt_attempt and hit_and_run cannot be simultaneous
  - Validate hit_and_run requires at least one runner on base

- Added 24+ comprehensive test cases covering all edge cases:
  - 13 new defensive decision validation tests
  - 16 new offensive decision validation tests
  - All tests pass (54/54 passing)

Clear error messages for all validation failures.
Follows 'Raise or Return' pattern with ValidationError exceptions.
2025-10-30 06:38:34 -05:00
Cal Corum
95d8703f56 CLAUDE: Implement Week 7 Task 1 - Strategic Decision Integration
Enhanced game engine with async decision workflow and AI opponent integration:

GameState Model Enhancements:
- Added pending_defensive_decision and pending_offensive_decision fields
- Added decision_phase tracking (idle, awaiting_defensive, awaiting_offensive, resolving, completed)
- Added decision_deadline field for timeout handling
- Added is_batting_team_ai() and is_fielding_team_ai() helper methods
- Added validator for decision_phase

StateManager Enhancements:
- Added _pending_decisions dict for asyncio.Future-based decision queue
- Added set_pending_decision() to create decision futures
- Added await_decision() to wait for decision submission
- Added submit_decision() to resolve pending futures
- Added cancel_pending_decision() for cleanup

GameEngine Enhancements:
- Added await_defensive_decision() with AI/human branching and timeout
- Added await_offensive_decision() with AI/human branching and timeout
- Enhanced submit_defensive_decision() to resolve pending futures
- Enhanced submit_offensive_decision() to resolve pending futures
- Added DECISION_TIMEOUT constant (30 seconds)

AI Opponent (Stub):
- Created ai_opponent.py with stub implementations
- generate_defensive_decision() returns default "normal" positioning
- generate_offensive_decision() returns default "normal" approach
- TODO markers for Week 9 full AI logic implementation

Integration:
- Backward compatible with existing terminal client workflow
- New async methods ready for WebSocket integration (Week 7 Task 4)
- AI teams get instant decisions, human teams wait with timeout
- Default decisions applied on timeout (no game blocking)

Testing:
- Config tests: 58/58 passing 
- Terminal client: Working perfectly 
- Existing workflows: Fully compatible 

Week 7 Task 1: Complete
Next: Task 2 - Decision Validators

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 21:38:11 -05:00
Cal Corum
d7caa75310 CLAUDE: Add manual outcome testing to terminal client and Phase 3 planning
Terminal Client Enhancements:
- Added list_outcomes command to display all PlayOutcome values
- Added resolve_with <outcome> command for testing specific scenarios
- TAB completion for all outcome names
- Full help documentation and examples
- Infrastructure ready for Week 7 integration

Files Modified:
- terminal_client/commands.py - list_outcomes() and forced outcome support
- terminal_client/repl.py - do_list_outcomes() and do_resolve_with() commands
- terminal_client/completions.py - VALID_OUTCOMES and complete_resolve_with()
- terminal_client/help_text.py - Help entries for new commands

Phase 3 Planning:
- Created comprehensive Week 7 implementation plan (25 pages)
- 6 major tasks covering strategic decisions and result charts
- Updated 00-index.md to mark Week 6 as 100% complete
- Documented manual outcome testing feature

Week 6: 100% Complete 
Phase 3 Week 7: Ready to begin

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 20:53:47 -05:00
Cal Corum
6880b6d5ad CLAUDE: Complete Week 6 - granular PlayOutcome integration and metadata support
- Renamed check_d20 → chaos_d20 throughout dice system
- Expanded PlayOutcome enum with granular variants (SINGLE_1/2, DOUBLE_2/3, GROUNDBALL_A/B/C, etc.)
- Integrated PlayOutcome from app.config into PlayResolver
- Added play_metadata support for uncapped hit tracking
- Updated all tests (139/140 passing)

Week 6: 100% Complete - Ready for Phase 3

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 20:29:06 -05:00
Cal Corum
5d5c13f2b8 CLAUDE: Implement Week 6 league configuration and play outcome systems
Week 6 Progress: 75% Complete

## Components Implemented

### 1. League Configuration System 
- Created BaseGameConfig abstract class for league-agnostic rules
- Implemented SbaConfig and PdConfig with league-specific settings
- Immutable configs (frozen=True) with singleton registry
- 28 unit tests, all passing

Files:
- backend/app/config/base_config.py
- backend/app/config/league_configs.py
- backend/tests/unit/config/test_league_configs.py

### 2. PlayOutcome Enum 
- Universal enum for all play outcomes (both SBA and PD)
- Helper methods: is_hit(), is_out(), is_uncapped(), is_interrupt()
- Supports standard hits, uncapped hits, interrupt plays, ballpark power
- 30 unit tests, all passing

Files:
- backend/app/config/result_charts.py
- backend/tests/unit/config/test_play_outcome.py

### 3. Player Model Refinements 
- Fixed PdPlayer.id field mapping (player_id → id)
- Improved field docstrings for image types
- Fixed position checking logic in SBA helper methods
- Added safety checks for missing image data

Files:
- backend/app/models/player_models.py (updated)

### 4. Documentation 
- Updated backend/CLAUDE.md with Week 6 section
- Documented card-based resolution mechanics
- Detailed config system and PlayOutcome usage

## Architecture Decisions

1. **Card-Based Resolution**: Both SBA and PD use same mechanics
   - 1d6 (column) + 2d6 (row) + 1d20 (split resolution)
   - PD: Digitized cards with auto-resolution
   - SBA: Manual entry from physical cards

2. **Immutable Configs**: Prevent accidental modification using Pydantic frozen

3. **Universal PlayOutcome**: Single enum for both leagues reduces duplication

## Testing
- Total: 58 tests, all passing
- Config tests: 28
- PlayOutcome tests: 30

## Remaining Work (25%)
- Update dice system (check_d20 → chaos_d20)
- Integrate PlayOutcome into PlayResolver
- Add Play.metadata support for uncapped hits

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 22:46:12 -05:00
Cal Corum
a0146223c8 CLAUDE: Update documentation with session improvements
Comprehensive documentation update covering all changes from 2025-10-28:

## Documentation Additions

**Performance Optimizations Section:**
- Added conditional game state updates (4th optimization)
- Updated performance impact metrics (70% query reduction in low-scoring innings)
- Clarified combined effect of all optimizations

**Game Models Refactor Section:**
- Documented RunnerState removal rationale
- Explained direct base reference approach
- Listed benefits and updated methods
- Included before/after code comparison

**Terminal Client Modularization Section:**
- Documented problem (code duplication)
- Explained modular solution with 4 new modules
- Listed benefits of DRY architecture
- Included file structure diagram
- Referenced test coverage

**Summary Section:**
- Complete overview of all 2025-10-28 updates
- Statistics: 36 files, +9,034 lines, 2 commits
- 5 major improvement categories
- Test status across all changes
- Documentation deliverables
- Next priorities for Week 6

## Changes Made

- Added conditional UPDATE optimization details
- Documented model simplification (RunnerState removal)
- Documented terminal client modularization
- Added comprehensive session summary
- All sections cross-referenced with code locations

**Total Documentation**: ~150 lines added covering:
- Performance optimizations (complete)
- Bug fixes (complete)
- Model refactoring
- Terminal client improvements
- Session summary with metrics

Makes it easy for future developers to understand today's architectural
decisions and performance improvements.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 14:40:37 -05:00
Cal Corum
1c32787195 CLAUDE: Refactor game models and modularize terminal client
This commit includes cleanup from model refactoring and terminal client
modularization for better code organization and maintainability.

## Game Models Refactor

**Removed RunnerState class:**
- Eliminated separate RunnerState model (was redundant)
- Replaced runners: List[RunnerState] with direct base references:
  - on_first: Optional[LineupPlayerState]
  - on_second: Optional[LineupPlayerState]
  - on_third: Optional[LineupPlayerState]
- Updated helper methods:
  - get_runner_at_base() now returns LineupPlayerState directly
  - get_all_runners() returns List[Tuple[int, LineupPlayerState]]
  - is_runner_on_X() simplified to direct None checks

**Benefits:**
- Matches database structure (plays table has on_first_id, etc.)
- Simpler state management (direct references vs list management)
- Better type safety (LineupPlayerState vs generic runner)
- Easier to work with in game engine logic

**Updated files:**
- app/models/game_models.py - Removed RunnerState, updated GameState
- app/core/play_resolver.py - Use get_all_runners() instead of state.runners
- app/core/validators.py - Updated runner access patterns
- tests/unit/models/test_game_models.py - Updated test assertions
- tests/unit/core/test_play_resolver.py - Updated test data
- tests/unit/core/test_validators.py - Updated test data

## Terminal Client Refactor

**Modularization (DRY principle):**
Created separate modules for better code organization:

1. **terminal_client/commands.py** (10,243 bytes)
   - Shared command functions for game operations
   - Used by both CLI (main.py) and REPL (repl.py)
   - Functions: submit_defensive_decision, submit_offensive_decision,
     resolve_play, quick_play_sequence
   - Single source of truth for command logic

2. **terminal_client/arg_parser.py** (7,280 bytes)
   - Centralized argument parsing and validation
   - Handles defensive/offensive decision arguments
   - Validates formats (alignment, depths, hold runners, steal attempts)

3. **terminal_client/completions.py** (10,357 bytes)
   - TAB completion support for REPL mode
   - Command completions, option completions, dynamic completions
   - Game ID completions, defensive/offensive option suggestions

4. **terminal_client/help_text.py** (10,839 bytes)
   - Centralized help text and command documentation
   - Detailed command descriptions
   - Usage examples for all commands

**Updated main modules:**
- terminal_client/main.py - Simplified by using shared commands module
- terminal_client/repl.py - Cleaner with shared functions and completions

**Benefits:**
- DRY: Behavior consistent between CLI and REPL modes
- Maintainability: Changes in one place affect both interfaces
- Testability: Can test commands module independently
- Organization: Clear separation of concerns

## Documentation

**New files:**
- app/models/visual_model_relationships.md
  - Visual documentation of model relationships
  - Helps understand data flow between models
- terminal_client/update_docs/ (6 phase documentation files)
  - Phased documentation for terminal client evolution
  - Historical context for implementation decisions

## Tests

**New test files:**
- tests/unit/terminal_client/__init__.py
- tests/unit/terminal_client/test_arg_parser.py
- tests/unit/terminal_client/test_commands.py
- tests/unit/terminal_client/test_completions.py
- tests/unit/terminal_client/test_help_text.py

**Updated tests:**
- Integration tests updated for new runner model
- Unit tests updated for model changes
- All tests passing with new structure

## Summary

-  Simplified game state model (removed RunnerState)
-  Better alignment with database structure
-  Modularized terminal client (DRY principle)
-  Shared command logic between CLI and REPL
-  Comprehensive test coverage
-  Improved documentation

Total changes: 26 files modified/created

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 14:16:38 -05:00
Cal Corum
aabb90feb5 CLAUDE: Implement player models and optimize database queries
This commit includes Week 6 player models implementation and critical
performance optimizations discovered during testing.

## Player Models (Week 6 - 50% Complete)

**New Files:**
- app/models/player_models.py (516 lines)
  - BasePlayer abstract class with polymorphic interface
  - SbaPlayer with API parsing factory method
  - PdPlayer with batting/pitching scouting data support
  - Supporting models: PdCardset, PdRarity, PdBattingCard, PdPitchingCard
- tests/unit/models/test_player_models.py (692 lines)
  - 32 comprehensive unit tests, all passing
  - Tests for BasePlayer, SbaPlayer, PdPlayer, polymorphism

**Architecture:**
- Simplified single-layer approach vs planned two-layer
- Factory methods handle API → Game transformation directly
- SbaPlayer.from_api_response(data) - parses SBA API inline
- PdPlayer.from_api_response(player_data, batting_data, pitching_data)
- Full Pydantic validation, type safety, and polymorphism

## Performance Optimizations

**Database Query Reduction (60% fewer queries per play):**
- Before: 5 queries per play (INSERT play, SELECT play with JOINs,
  SELECT games, 2x SELECT lineups)
- After: 2 queries per play (INSERT play, UPDATE games conditionally)

Changes:
1. Lineup caching (game_engine.py:384-425)
   - Check state_manager.get_lineup() cache before DB fetch
   - Eliminates 2 SELECT queries per play
2. Remove unnecessary refresh (operations.py:281-302)
   - Removed session.refresh(play) after INSERT
   - Eliminates 1 SELECT with 3 expensive LEFT JOINs
3. Direct UPDATE statement (operations.py:109-165)
   - Changed update_game_state() to use direct UPDATE
   - No longer does SELECT + modify + commit
4. Conditional game state updates (game_engine.py:200-217)
   - Only UPDATE games table when score/inning/status changes
   - Captures state before/after and compares
   - ~40-60% fewer updates (many plays don't score)

## Bug Fixes

1. Fixed outs_before tracking (game_engine.py:551)
   - Was incorrectly calculating: state.outs - result.outs_recorded
   - Now correctly captures: state.outs (before applying result)
   - All play records now have accurate out counts

2. Fixed game recovery (state_manager.py:312-314)
   - AttributeError when recovering: 'GameState' has no attribute 'runners'
   - Changed to use state.get_all_runners() method
   - Games can now be properly recovered from database

## Enhanced Terminal Client

**Status Display Improvements (terminal_client/display.py:75-97):**
- Added "⚠️ WAITING FOR ACTION" section when play is pending
- Shows specific guidance:
  - "The defense needs to submit their decision" → Run defensive [OPTIONS]
  - "The offense needs to submit their decision" → Run offensive [OPTIONS]
  - "Ready to resolve play" → Run resolve
- Color-coded command hints for better UX

## Documentation Updates

**backend/CLAUDE.md:**
- Added comprehensive Player Models section (204 lines)
- Updated Current Phase status to Week 6 (~50% complete)
- Documented all optimizations and bug fixes
- Added integration examples and usage patterns

**New Files:**
- .claude/implementation/week6-status-assessment.md
  - Comprehensive Week 6 progress review
  - Architecture decision rationale (single-layer vs two-layer)
  - Completion status and next priorities
  - Updated roadmap for remaining Week 6 work

## Test Results

- Player models: 32/32 tests passing
- All existing tests continue to pass
- Performance improvements verified with terminal client

## Next Steps (Week 6 Remaining)

1. Configuration system (BaseConfig, SbaConfig, PdConfig)
2. Result charts & PD play resolution with ratings
3. API client for live roster data (deferred)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 14:08:56 -05:00
Cal Corum
05fc037f2b CLAUDE: Fix game recovery and add required field validation for plays
Fixed critical bugs in game recovery and play persistence:

1. Terminal REPL Auto-Recovery:
   - Added _ensure_game_loaded() helper to auto-recover games from database
   - Calls state_manager.recover_game() when game not in memory
   - Calls _prepare_next_play() after recovery to populate snapshot fields
   - Enables seamless continuation of games across REPL sessions

2. Play Validation:
   - Added verification in _save_play_to_db() for required fields
   - Ensures batter_id, pitcher_id, catcher_id are never NULL
   - Raises ValueError with clear error message if fields missing
   - Prevents database constraint violations

3. Updated Commands:
   - All REPL commands now call _ensure_game_loaded()
   - Commands: defensive, offensive, resolve, status, quick_play, box_score
   - Fixes "Game state not found" errors on recovered games

Root Cause:
- state_manager.recover_game() rebuilds GameState from database
- But didn't populate snapshot fields (current_batter_lineup_id, etc.)
- _save_play_to_db() requires these fields to save plays
- Solution: Call _prepare_next_play() after recovery

Files Modified:
- app/core/game_engine.py - Added verification in _save_play_to_db()
- terminal_client/repl.py - Added _ensure_game_loaded() and integrated

Testing: Successfully recovered game, submitted decisions, and resolved plays

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 13:14:12 -05:00
Cal Corum
918beadf24 CLAUDE: Add interactive terminal client for game engine testing
Created comprehensive terminal testing tool with two modes:
1. Interactive REPL (recommended) - Persistent in-memory state
2. Standalone CLI commands - Config file persistence

Features:
- Interactive REPL using Python cmd module
- Persistent event loop prevents DB connection issues
- 11 commands for full game control (new_game, defensive, offensive, resolve, etc.)
- Beautiful Rich formatting with colors and panels
- Auto-generated test lineups for rapid testing
- Direct GameEngine access (no WebSocket overhead)
- Config file (~/.terminal_client_config.json) for state persistence

Files added:
- terminal_client/repl.py (525 lines) - Interactive REPL
- terminal_client/main.py (516 lines) - Click standalone commands
- terminal_client/display.py (218 lines) - Rich formatting
- terminal_client/config.py (89 lines) - Persistent config
- terminal_client/__main__.py - Dual mode entry point
- terminal_client/CLAUDE.md (725 lines) - Full documentation

Updated:
- backend/CLAUDE.md - Added terminal client to testing section
- requirements.txt - Added rich==13.9.4

Perfect for rapid iteration on game engine without building frontend!

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 12:51:01 -05:00
Cal Corum
f9aa653c37 CLAUDE: Reorganize Week 6 documentation and separate player model specifications
Split player model architecture into dedicated documentation files for clarity
and maintainability. Added Phase 1 status tracking and comprehensive player
model specs covering API models, game models, mappers, and testing strategy.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 23:48:57 -05:00
Cal Corum
f3238c4e6d CLAUDE: Complete Week 5 testing and update documentation
Add comprehensive unit and integration tests for Week 5 deliverables:
- test_play_resolver.py: 18 tests covering outcome resolution and runner advancement
- test_validators.py: 36 tests covering game state, decisions, lineups, and flow
- test_game_engine.py: 7 test classes for complete game flow integration

Update implementation documentation to reflect completed status:
- 00-index.md: Mark Phase 2 Weeks 4-5 complete with test coverage
- 02-week5-game-logic.md: Comprehensive test details and completion status
- 02-game-engine.md: Forward-looking snapshot pattern documentation

Week 5 now fully complete with 54 unit tests + 7 integration test classes passing.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 22:57:23 -05:00
Cal Corum
13e924a87c CLAUDE: Refactor GameEngine to forward-looking play tracking pattern
Replaced awkward "lookback" pattern with clean "prepare → execute → save"
orchestration that captures state snapshots BEFORE each play.

Key improvements:
- Added per-team batter indices (away_team_batter_idx, home_team_batter_idx)
- Added play snapshot fields (current_batter/pitcher/catcher_lineup_id)
- Added on_base_code bit field for efficient base situation queries
- Created _prepare_next_play() method for snapshot preparation
- Refactored start_game() with hard lineup validation requirement
- Refactored resolve_play() with explicit 6-step orchestration
- Updated _save_play_to_db() to use snapshots (no DB lookbacks)
- Enhanced state recovery to rebuild from last play (single query)
- Added defensive lineup position validator

Benefits:
- No special cases for first play
- Single source of truth in GameState
- Saves 18+ database queries per game
- Fast state recovery without replay
- Complete runner tracking (before/after positions)
- Explicit orchestration (easy to debug)

Testing:
- Added 3 new test functions (lineup validation, snapshot tracking, batting order)
- All 5 test suites passing (100%)
- Type checking cleaned up with targeted suppressions for SQLAlchemy

Documentation:
- Added comprehensive "Type Checking & Common False Positives" section to CLAUDE.md
- Created type-checking-guide.md and type-checking-summary.md
- Added mypy.ini configuration for SQLAlchemy/Pydantic

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 22:18:15 -05:00
Cal Corum
0542723d6b CLAUDE: Fix GameEngine lineup integration and add test script
Fixes:
 Updated GameEngine._save_play_to_db() to fetch real lineup IDs
   - Gets active batting/fielding lineups from database
   - Extracts batter, pitcher, catcher IDs by position
   - No more hardcoded placeholder IDs

 Shortened AbRoll.__str__() to fit VARCHAR(50)
   - "WP 1/10" instead of "AB Roll: Wild Pitch Check..."
   - "AB 6,9(4+5) d20=12/10" for normal rolls
   - Prevents database truncation errors

 Created comprehensive test script (scripts/test_game_flow.py)
   - Tests single at-bat flow
   - Tests full half-inning (50+ plays)
   - Creates dummy lineups for both teams
   - Verifies complete game lifecycle

Test Results:
 Successfully ran 50 at-bats across 6 innings
 Score tracking: Away 5 - Home 2
 Inning advancement working
 Play persistence to database
 Roll batch saving at inning boundaries
 State synchronization (memory + DB)

GameEngine Verified Working:
   Game lifecycle management (create → start → play → complete)
   Decision submission (defensive + offensive)
   Play resolution with AbRoll system
   State management and persistence
   Inning advancement logic
   Score tracking
   Lineup integration
   Database persistence

Ready for:
- WebSocket integration
- Frontend connectivity
- Full game simulations
- AI opponent integration

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 15:04:41 -05:00
Cal Corum
0d7ddbe408 CLAUDE: Implement GameEngine, PlayResolver, and GameValidator
Core Components:
 GameValidator (validators.py)
   - Validates game state and decisions
   - Rule enforcement for baseball gameplay
   - Game-over and inning continuation logic

 PlayResolver (play_resolver.py)
   - Resolves play outcomes using AbRoll system
   - Simplified result charts for MVP
   - Handles wild pitch/passed ball checks
   - Runner advancement logic for all hit types
   - PlayOutcome enum with 12 outcome types

 GameEngine (game_engine.py)
   - Orchestrates complete game flow
   - Start game, submit decisions, resolve plays
   - Integrates DiceSystem with roll context
   - Batch saves rolls at end of each half-inning
   - Persists plays and game state to database
   - Manages inning advancement and game completion

Integration Features:
- Uses advanced AbRoll system (not simplified d20)
- Roll context tracking per inning
- Batch persistence at inning boundaries
- Full audit trail with roll history
- State synchronization between memory and database

Architecture:
  GameEngine → PlayResolver → DiceSystem
       ↓             ↓
  GameValidator  StateManager
       ↓             ↓
   Database      In-Memory Cache

Ready For:
 End-to-end at-bat testing
 WebSocket integration
 Result chart configuration
 Advanced decision logic (Phase 3)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 10:00:21 -05:00
Cal Corum
57b8a90818 CLAUDE: Attempted NullPool fix for async test fixtures (unsuccessful)
Attempted Fix:
- Created test-specific engine with NullPool
- Monkeypatched DatabaseOperations to use test engine
- Reference: https://github.com/MagicStack/asyncpg/issues/863

Result:
 NullPool did NOT resolve the issue
- Tests still fail after #4 with "another operation is in progress"
- Error occurs during fixture setup, not in test bodies
- Timestamps show pytest setting up multiple fixtures concurrently

Root Cause Analysis:
The issue isn't connection pooling - it's async fixture dependency chains.
When pytest-asyncio sets up `sample_game` fixture (which uses `db_ops`),
it creates overlapping async contexts that asyncpg can't handle.

Evidence:
- Individual tests:  PASS
- First 4 tests together:  PASS
- Tests 5-16:  FAIL with concurrent operation errors
- Unit tests:  87/88 PASS (core logic proven correct)

Conclusion:
This is a complex pytest-asyncio + SQLAlchemy + asyncpg interaction
requiring architectural test changes (separate test DB, sync fixtures, etc).
Not worth solving pre-MVP given tests work individually and code is proven.

Workaround:
Run test classes separately - each class passes fine:
  pytest tests/integration/database/test_roll_persistence.py::TestRollPersistenceBatch -v
  pytest tests/integration/database/test_roll_persistence.py::TestRollRetrieval -v
  pytest tests/integration/database/test_roll_persistence.py::TestRollDataIntegrity -v
  pytest tests/integration/database/test_roll_persistence.py::TestRollEdgeCases -v

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 08:44:44 -05:00
Cal Corum
56c042c85e CLAUDE: Add async fixture management and document integration test limitation
Changes:
- Created tests/integration/conftest.py with shared fixtures
- Added README.md documenting asyncpg connection pool issue
- Fixed uuid4 import in test_roll_persistence.py

Issue Analysis:
- Integration tests work individually but fail when run together (12+ tests)
- AsyncPG error: "cannot perform operation: another operation is in progress"
- Root cause: pytest-asyncio + asyncpg connection reuse across rapid fixtures
- Tests #1-4 pass, then connection pool enters bad state

Test Status:
 87/88 unit tests pass (1 pre-existing timing issue)
 Integration tests PASS individually
⚠️  Integration tests FAIL when run together (fixture issue, not code bug)

Workarounds:
- Run test classes separately
- Run individual tests
- Use pytest-xdist for isolation

The tests themselves are well-designed and use production code paths.
This is purely a test infrastructure limitation to be resolved post-MVP.

Core dice and roll persistence logic is proven correct by unit tests.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 08:41:03 -05:00
Cal Corum
874e24dc75 CLAUDE: Implement comprehensive dice roll system with persistence
Core Implementation:
- Created roll_types.py with AbRoll, JumpRoll, FieldingRoll, D20Roll dataclasses
- Implemented DiceSystem singleton with cryptographically secure random generation
- Added Roll model to db_models.py with JSONB storage for roll history
- Implemented save_rolls_batch() and get_rolls_for_game() in database operations

Testing:
- 27 unit tests for roll type dataclasses (100% passing)
- 35 unit tests for dice system (34/35 passing, 1 timing issue)
- 16 integration tests for database persistence (uses production DiceSystem)

Features:
- Unique roll IDs using secrets.token_hex()
- League-specific logic (SBA d100 rare plays, PD error-based rare plays)
- Automatic derived value calculation (d6_two_total, jump_total, error_total)
- Full audit trail with context metadata
- Support for batch saving rolls per inning

Technical Details:
- Fixed dataclass inheritance with kw_only=True for Python 3.13
- Roll data stored as JSONB for flexible querying
- Indexed on game_id, roll_type, league_id, team_id for efficient retrieval
- Supports filtering by roll type, team, and timestamp ordering

Note: Integration tests have async connection pool issue when run together
(tests work individually, fixture cleanup needed in follow-up branch)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 08:29:02 -05:00
Cal Corum
04a5538447 Add scripts to test models in dev database 2025-10-23 09:10:55 -05:00
Cal Corum
9284162682 Clean up false positive Pylance errors 2025-10-23 09:10:41 -05:00