From 119f1694749200c9883f25978e9824c26e4b6966 Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Fri, 31 Oct 2025 08:37:59 -0500 Subject: [PATCH] CLAUDE: Prepare NEXT_SESSION.md for Week 8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comprehensive update for next session: Week 7 Summary (100% Complete): - All 8 tasks completed with full descriptions - 126 new tests (all passing) - 180/181 core tests passing - Manual testing verified (8/8 scenarios) Week 8 Preview: - Task 1: Substitution system (pinch hitters, runners, defensive) - Task 2: Pitching changes (relief, fatigue, bullpen) - Task 3: Advanced rules (steals, pickoffs, balks) - Task 4: Game state persistence (save/load/replay) - Task 5: Enhanced terminal client Quick Start Guide: - Clear entry point for next agent - Key files and architecture diagrams - Testing strategy - Important patterns and conventions Architectural Reference: - Outcome-first PlayResolver design - Auto mode configuration - Hit location tracking - Manual vs auto mode flows Ready for Week 8 implementation! ๐ŸŽฏ Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .claude/implementation/NEXT_SESSION.md | 910 ++++++++----------------- 1 file changed, 282 insertions(+), 628 deletions(-) diff --git a/.claude/implementation/NEXT_SESSION.md b/.claude/implementation/NEXT_SESSION.md index eed7c94..9b7e99e 100644 --- a/.claude/implementation/NEXT_SESSION.md +++ b/.claude/implementation/NEXT_SESSION.md @@ -1,670 +1,324 @@ -# Next Session Plan - Phase 3 Week 7 COMPLETE! +# Next Session Plan - Week 8: Substitutions & Advanced Gameplay -**Current Status**: Phase 3 - Week 7 (100% Complete) โœ… -**Last Commit**: `e2f1d60` - "CLAUDE: Implement Week 7 Task 6 - PlayResolver Integration with RunnerAdvancement" +**Current Status**: Phase 3 - Week 7 Complete (100%) โœ… โ†’ Starting Week 8 +**Last Commit**: `4cf349a` - "CLAUDE: Update NEXT_SESSION.md - Week 7 complete at 100%" **Date**: 2025-10-31 -**Remaining Work**: 0% - ALL 8 TASKS COMPLETE! +**Next Priority**: Week 8 - Player substitutions, pitching changes, and game management features + +--- + +## ๐ŸŽ‰ Week 7 Summary - COMPLETE! + +**All 8 tasks completed successfully:** + +### Task 1: Strategic Decision Integration โœ… +- Async decision workflow with `asyncio.Future` +- Defensive decision queue: alignment, infield/outfield depth, hold runners +- Offensive decision queue: approach, steal attempts, bunting +- Full integration with GameEngine + +### Task 2: Decision Validators โœ… (54 tests) +- DefensiveDecision validation: positioning rules, depth requirements +- OffensiveDecision validation: steal/bunt prerequisites +- Lineup validation: complete defensive positioning +- Game flow validation: inning/out state checks + +### Task 3: Result Charts + PD Auto Mode โœ… (21 tests) +- `ResultChart` abstract base class +- `PdAutoResultChart` for auto-generated outcomes +- `ManualResultChart` for player submissions +- `calculate_hit_location()` helper (pull rates, handedness) +- `ManualOutcomeSubmission` validation model + +### Task 4: Runner Advancement Logic โœ… (30 tests) +- `RunnerAdvancement` class with 13 result types +- Infield Back chart (default positioning) +- Infield In chart (runner on 3rd) +- Corners In positioning (hybrid approach) +- Full groundball outcome resolution + +### Task 5: Double Play Mechanics โœ… +- Integrated into Task 4 `RunnerAdvancement` +- Base probability: 45% with modifiers +- Positioning: Infield In (-15%), Normal (0%) +- Hit location: Middle infield (+10%), Corners (-10%) +- Probabilistic execution (not deterministic) + +### Task 6: PlayResolver Integration โœ… (9 tests) +- **Outcome-first architecture** - Manual mode is primary +- `resolve_outcome()` core method - all game logic +- `resolve_manual_play()` wrapper for player submissions +- `resolve_auto_play()` wrapper for PD auto mode +- RunnerAdvancement integrated for all groundballs +- `hit_location` tracked in `PlayResult` +- Removed obsolete `SimplifiedResultChart` and singleton + +### Task 7: WebSocket Manual Outcome Handlers โœ… (12 tests) +- `roll_dice` event: Server rolls, broadcasts to players +- `submit_manual_outcome` event: Players submit after reading cards +- `GameEngine.resolve_manual_play()` orchestration +- Terminal client commands: `roll_dice`, `manual_outcome` + +### Task 8: Terminal Client Enhancement โœ… +- Manual outcome submission commands +- Full REPL integration +- Testing without frontend + +### Testing Summary +- **180/181 core tests passing** (1 pre-existing failure in dice history) +- **126 new tests for Week 7** - all passing +- **Manual testing**: 8/8 scenarios verified โœ… + +--- + +## ๐Ÿš€ Week 8: Substitutions & Advanced Gameplay + +**Focus**: Player substitutions, pitching management, and advanced game features + +### Planned Tasks + +#### Task 1: Substitution System +- **Pinch hitters** - Replace batter mid-at-bat or in lineup +- **Pinch runners** - Replace runner on base +- **Defensive replacements** - Swap fielders +- **Database tracking**: `replacing_id`, `after_play`, `entered_inning` +- **Validation**: DH rules, position eligibility, one-way substitutions + +#### Task 2: Pitching Changes +- **Relief pitcher** - Bring in from bullpen +- **Pitching fatigue** - Track pitch count and `is_fatigued` flag +- **Bullpen management** - Available relievers, warmup status +- **Closer/setup roles** - Strategic substitution timing + +#### Task 3: Advanced Game Rules +- **Steal attempts** - Use OffensiveDecision.steal_attempts +- **Caught stealing resolution** - JumpRoll mechanics +- **Pick-off attempts** - Pitcher vs runner +- **Balk detection** - Using chaos_d20 rolls + +#### Task 4: Game State Persistence +- **Save/load functionality** - Store/restore game mid-play +- **Replay system** - Rebuild state from play history +- **Recovery on crash** - Automatic state reconstruction + +#### Task 5: Enhanced Terminal Client +- **Substitution commands** - `pinch_hit`, `pinch_run`, `defensive_sub` +- **Pitching commands** - `change_pitcher`, `bullpen_status` +- **Better status display** - Show fatigue, available subs --- ## Quick Start for Next AI Agent -### ๐ŸŽฏ Where to Begin -1. Read this entire document first -2. Review `@.claude/implementation/WEEK_7_PLAN.md` for comprehensive task details -3. Start with **Task 6: PlayResolver Integration** (final task!) -4. Run tests after each change: `export PYTHONPATH=. && pytest tests/unit/core/ -v` - -### ๐Ÿ“ Current Context -**Week 7 Tasks 1-5, 7-8 are complete!** -- **Task 1**: Async decision workflow with asyncio Futures โœ… -- **Task 2**: Defensive/offensive decision validators with 54 tests passing โœ… -- **Task 3**: Result chart abstraction + PD auto mode with 21 tests passing โœ… -- **Task 4**: Runner advancement logic with 30 tests passing โœ… -- **Task 5**: Double play mechanics (integrated into Task 4) โœ… -- **Task 7**: WebSocket manual outcome handlers with 12 tests passing โœ… -- **Task 8**: Terminal client enhancement (manual commands) โœ… - -**Next up**: Task 6 - PlayResolver Integration! This is the final task. Integrate the RunnerAdvancement class into play_resolver.py so all groundball outcomes use the new advancement logic. Update existing tests and ensure no regressions. - -**Note**: Tasks 7-8 completed out of order while waiting for advancement chart clarification from user. - -**IMPORTANT CONTEXT**: In this session, we clarified major architectural points: -- **Manual Mode (SBA + PD manual)**: - - Server rolls dice for fairness and auditing (NOT players!) - - Players read PHYSICAL cards based on server dice - - Players submit outcomes via WebSocket - - System validates and processes with server-rolled dice -- **PD Auto Mode**: System uses digitized ratings to auto-generate outcomes for faster/AI play. This is NEW functionality enabling AI vs AI games. -- **Decision Modifiers**: Do NOT change the base outcome (GROUNDBALL_C stays GROUNDBALL_C). They affect RUNNER ADVANCEMENT based on hit location and defensive positioning. - ---- - -## What We Just Completed โœ… - -### 1. Validator Bug Fixes (Commit `c0051d2`) - - **File**: `app/core/validators.py` - - **Issue**: Validator checking wrong on_base_codes for "runner on third" - - **Fix**: Updated to use `state.is_runner_on_third()` helper method - - **Changes**: - - Fixed infield depth validation (corners_in/infield_in require runner on third) - - Updated DefensiveDecision Pydantic model: infield depths `['infield_in', 'normal', 'corners_in']` - - Updated DefensiveDecision Pydantic model: outfield depths `['in', 'normal']` (removed 'back') - - Removed 4 invalid double_play depth tests (depth doesn't exist) - - Added 4 proper corners_in/infield_in tests - - **Testing**: All 54 validator tests passing โœ… - - **Impact**: Validators now correctly check game state using helper methods - -### 2. Result Chart Abstraction & PD Auto Mode (Commit `9245b4e`) - Week 7 Task 3 - - **Files**: - - `app/config/result_charts.py` (+400 lines) - - `app/models/game_models.py` (+55 lines) - - `tests/unit/config/test_result_charts.py` (+492 lines, NEW) - - - **Core Implementation**: - - **ResultChart abstract base class**: Defines `get_outcome(roll, state, batter, pitcher) -> tuple[outcome, location]` - - **calculate_hit_location() helper**: - - 45% pull, 35% center, 20% opposite field distribution - - RHB pulls left (3B, SS, LF), LHB pulls right (1B, 2B, RF) - - Groundballs โ†’ infield positions (1B, 2B, SS, 3B, P, C) - - Flyouts โ†’ outfield positions (LF, CF, RF) - - **PlayOutcome.requires_hit_location()**: Returns True for groundballs and flyouts only - - - **Manual Mode Support**: - - **ManualResultChart**: Passthrough class (raises NotImplementedError) - - Manual mode doesn't use result charts - players submit via WebSocket - - **ManualOutcomeSubmission model**: Validates PlayOutcome enum + hit location - - Validates outcome is valid PlayOutcome value - - Validates hit location in ['1B', '2B', 'SS', '3B', 'LF', 'CF', 'RF', 'P', 'C'] - - Location is optional (only needed for certain outcomes) - - - **PD Auto Mode Implementation**: - - **PdAutoResultChart**: Full auto-generation for PD games - - `_select_card()`: Coin flip (50/50) to choose batting or pitching card - - `_build_distribution()`: Creates cumulative distribution from rating percentages - - `_select_outcome()`: Rolls 1d100 to select outcome from distribution - - 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 (SINGLE_UNCAPPED, DOUBLE_UNCAPPED) - - Calculates hit location using handedness and pull rates - - Proper error handling when card data missing - - - **Testing**: 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 over 1000 trials) - - Handedness matchup selection - - Cumulative distribution building - - Outcome selection from probabilities - - Hit location calculation for groundballs - - Error handling for missing cards - - Statistical distribution verification - - ManualOutcomeSubmission validation tests - - - **Impact**: - - โœ… Foundation for both manual and auto play modes - - โœ… Hit locations ready for Task 4 runner advancement - - โœ… PD auto mode enables AI vs AI games - - โณ Integration with PlayResolver deferred (Phase 6) - - โณ Terminal client manual outcome command deferred (Phase 8) - -### 3. WebSocket Manual Outcome Handlers (Current Session) - Week 7 Task 7 - - **Files**: - - `app/websocket/handlers.py` (+240 lines - 2 new event handlers) - - `app/core/game_engine.py` (+147 lines - resolve_manual_play method) - - `app/models/game_models.py` (+1 line - pending_manual_roll field) - - `terminal_client/commands.py` (+128 lines - roll_manual_dice, submit_manual_outcome) - - `terminal_client/repl.py` (updated do_roll_dice, do_manual_outcome) - - `tests/unit/websocket/test_manual_outcome_handlers.py` (+432 lines, NEW) - - - **Core Implementation**: - - **roll_dice WebSocket Handler**: - - Server rolls dice using dice_system.roll_ab() - - Stores ab_roll in state.pending_manual_roll - - Broadcasts dice results to all players in game room - - Events: `dice_rolled` (broadcast), `error` (validation failures) - - - **submit_manual_outcome WebSocket Handler**: - - Validates ManualOutcomeSubmission model (outcome + optional location) - - Checks for pending_manual_roll (prevents submission without roll) - - Validates hit_location required for groundballs/flyouts - - Calls game_engine.resolve_manual_play() to process - - Events: `outcome_accepted`, `outcome_rejected`, `play_resolved`, `error` - - - **GameEngine.resolve_manual_play()**: - - Accepts server-rolled ab_roll for audit trail - - Uses player-submitted outcome for resolution - - Validates hit_location when required - - Same orchestration as resolve_play() (save, update, advance inning) - - Tracks rolls for batch saving at inning boundaries - - - **Terminal Client Commands**: - - `roll_dice` - Roll dice and display results - - `manual_outcome [location]` - Submit manual outcome - - Both integrated into REPL for testing - - - **Testing**: 12 comprehensive unit tests (all passing โœ…) - - roll_dice tests (4): - - Successful roll and broadcast - - Missing game_id validation - - Invalid game_id format validation - - Game not found error handling - - submit_manual_outcome tests (8): - - Successful submission and play resolution - - Missing game_id validation - - Missing outcome validation - - Invalid outcome value validation - - Invalid hit_location validation - - Missing required hit_location validation - - No pending roll error handling - - Walk without location (valid case) - - - **Key Architectural Decisions**: - - **Server rolls dice for fairness**: Clarified with user - server generates dice, stores for audit, players read cards - - **One-time roll usage**: pending_manual_roll cleared after submission to prevent reuse - - **Early validation**: Check for pending roll BEFORE emitting outcome_accepted - - **Comprehensive error handling**: Field-level error messages for clear user feedback - - - **Impact**: - - โœ… Complete manual outcome workflow implemented - - โœ… WebSocket handlers ready for frontend integration - - โœ… Terminal client testing commands available - - โœ… Audit trail maintained with server-rolled dice - - โœ… Foundation for SBA and PD manual mode gameplay - -### 4. Runner Advancement Logic (Current Session) - Week 7 Tasks 4 & 5 - - **Files**: - - `app/core/runner_advancement.py` (+1230 lines, NEW) - - `tests/unit/core/test_runner_advancement.py` (+705 lines, NEW) - - - **Core Implementation**: - - **GroundballResultType IntEnum**: 13 result constants matching rulebook exactly - - BATTER_OUT_RUNNERS_HOLD (1) - - DOUBLE_PLAY_AT_SECOND (2) - - BATTER_OUT_RUNNERS_ADVANCE (3) - - BATTER_SAFE_FORCE_OUT_AT_SECOND (4) - - CONDITIONAL_ON_MIDDLE_INFIELD (5) - - CONDITIONAL_ON_RIGHT_SIDE (6) - - BATTER_OUT_FORCED_ONLY (7/8) - - LEAD_HOLDS_TRAIL_ADVANCES (9) - - DOUBLE_PLAY_HOME_TO_FIRST (10) - - BATTER_SAFE_LEAD_OUT (11) - - DECIDE_OPPORTUNITY (12) - - CONDITIONAL_DOUBLE_PLAY (13) - - - **RunnerAdvancement class**: - - `advance_runners()` - Main entry point for advancement calculation - - `_determine_groundball_result()` - Chart lookup logic (Infield Back vs Infield In) - - `_execute_result()` - Dispatches to result-specific handlers - - `_calculate_double_play_probability()` - DP success calculation with modifiers - - - **Infield Back Chart** (default defensive positioning): - - Empty bases: Result 1 (batter out, runners hold) - - Runner on 1st: Result 2/4 (DP attempt or force out) - - Runner on 2nd: Result 6 (conditional on right side hit) - - Runner on 3rd: Result 5 (conditional on middle infield hit) - - Multiple runners: Various forced advancement scenarios - - - **Infield In Chart** (runner on 3rd, defense playing in): - - 3rd only: Result 7/1/8 based on groundball type - - 1st & 3rd: Result 7/9/12 with DECIDE opportunities - - 2nd & 3rd: Result 7/1/8 - - Bases loaded: Result 10/11 (DP attempts at home) - - - **Corners In Positioning** (hybrid approach): - - Uses Infield In rules when ball hit to corners (1B/3B/P/C) - - Uses Infield Back rules when ball hit to middle infield (2B/SS) - - Automatic detection based on hit_location parameter - - - **Double Play Mechanics** (Task 5): - - Base probability: 45% - - Positioning modifiers: - - Infield In: -15% (prioritizing out at plate) - - Normal: 0% (base rate) - - Hit location modifiers: - - Middle infield (2B/SS): +10% - - Corners (1B/3B/P/C): -10% - - TODO: Runner speed modifiers when player ratings available - - Probability clamped between 0% and 100% - - - **DECIDE Mechanic** (Result 12): - - Placeholder for interactive runner advancement decisions - - Offense chooses whether lead runner attempts to advance - - Defense chooses to take sure out OR throw for lead runner - - Safe range calculation: runner_speed - 4 + fielder_rating - - Conservative default (runners hold) until interactive flow implemented - - - **All 13 Result Handlers**: - - `_gb_result_1()` through `_gb_result_13()` - - Each returns AdvancementResult with movements, outs, runs - - Handles force plays, runner advancement, scoring logic - - Conditional results based on hit location - - - **Testing**: 30 comprehensive unit tests (all passing โœ…) - - Chart lookup tests (7): - - Empty bases โ†’ Result 1 - - 2 outs โ†’ Result 1 (always) - - Runner on 1st + GBA + Infield Back โ†’ Result 2 (DP) - - Runner on 3rd + Infield In โ†’ Result 7 (forced only) - - Bases loaded + Infield In โ†’ Result 10 (DP home to first) - - Corners In hit to corner โ†’ Infield In rules - - Corners In hit to middle โ†’ Infield Back rules - - - Result handler tests (11): - - Result 1: Batter out, runners hold - - Result 2: Double play (successful and failed) - - Result 3: Batter out, runners advance - - Result 5: Conditional on middle infield - - Result 7: Forced advancement only - - Result 10: DP home to first - - Result 12: DECIDE opportunities - - - Double play probability tests (5): - - Base probability (45% + location bonus) - - Corner penalty (-10%) - - Infield in penalty (-15%) - - Probability bounds (0-1 clamping) - - - Edge case tests (7): - - Invalid outcome raises ValueError - - All groundball types supported (A, B, C) - - All hit locations supported (1B, 2B, SS, 3B, P, C) - - All on-base codes supported (0-7) - - - **Key Architectural Decisions**: - - **IntEnum approach**: Balances rulebook traceability with code clarity - - **Probability-based DPs**: More realistic than deterministic outcomes - - **TOOTBLAN/FARTSLAM deprecated**: User clarified these are no longer in ruleset - - **DECIDE placeholder**: Foundation laid, interactive flow deferred to game engine layer - - **Hit location critical**: Determines which chart row and conditional logic applies - - - **Impact**: - - โœ… Complete groundball advancement system implemented - - โœ… Both Infield Back and Infield In charts working - - โœ… Double play mechanics with realistic probability - - โœ… Foundation for interactive DECIDE mechanic - - โœ… 30 tests ensuring correctness across all scenarios - - โณ Integration with PlayResolver pending (Task 6) - ---- - -## Key Architecture Decisions Made - -### 1. **Manual vs Auto Mode Clarification** -**Decision**: Manual mode doesn't use result charts at all - humans submit outcomes directly - -**Rationale**: -- SBA and PD manual games use physical cards that aren't digitized (SBA) or optional digitization (PD) -- Players roll dice, read their card, and tell system the outcome + location via WebSocket -- Result charts only used for PD auto mode where we need to generate outcomes - -**Impact**: -- Simpler architecture - no "manual result chart" logic needed -- ManualResultChart exists only for interface completeness (raises NotImplementedError) -- WebSocket handlers will receive ManualOutcomeSubmission objects -- PdAutoResultChart is truly optional - only for auto mode - -### 2. **Decision Modifiers Affect Advancement, Not Outcomes** -**Decision**: Defensive decisions don't change the PlayOutcome - they change runner advancement - -**Rationale**: -- User provided advancement charts showing different runner movements for same outcome -- GROUNDBALL_C stays GROUNDBALL_C whether infield is "in", "back", or "normal" -- The HIT LOCATION + DEFENSIVE POSITIONING determine advancement (Infield In/Back charts) -- Example: GROUNDBALL_C to SS with "corners_in" = different advancement than "normal" depth - -**Impact**: -- Task 3 (this session) focused on outcome selection + hit location calculation -- Task 4 (next) implements advancement logic using hit locations from Task 3 -- SimplifiedResultChart in play_resolver.py remains untouched (no breaking changes) -- Original Week 7 plan overestimated decision modifier complexity - -### 3. **Hit Location is Critical, Not Just Informational** -**Decision**: Track precise hit location (1B, 2B, SS, 3B, LF, CF, RF, P, C) for every groundball/flyout - -**Rationale**: -- User's advancement charts show different rules for different fielders -- "Corners in" only affects plays hit to 1B, 3B, P, or C (not 2B/SS) -- Hit location determines which advancement chart row to use -- Tag-up logic for flyouts depends on location (deep fly vs shallow) - -**Impact**: -- calculate_hit_location() must be accurate with proper pull rates -- ManualOutcomeSubmission requires location for groundballs/flyouts -- Task 4 will use location extensively in advancement logic -- Future: Could add fielder ratings affecting outcomes - -### 4. **On-Base Code is Enumeration, Not Bit Field** -**Decision**: current_on_base_code is 0-7 enumeration, not bit-field addition - -**Clarification** (from user): -- 0: empty -- 1: on first -- 2: on second -- 3: on third -- 4: first and second -- 5: first and third -- 6: second and third -- 7: bases loaded - -**Impact**: -- Fixed validator bug checking wrong codes for "runner on third" -- Code should use helper methods (`is_runner_on_first()`) instead of hardcoding -- Documentation updated with correct enumeration values - ---- - -## Blockers Encountered ๐Ÿšง - -### 1. **PYTHONPATH Required for Tests** -**Issue**: Tests fail with `ModuleNotFoundError: No module named 'app'` without PYTHONPATH set - -**Workaround**: Run tests with `export PYTHONPATH=. && pytest ...` - -**Status**: โš ๏ธ Need to investigate why PYTHONPATH isn't set automatically by pytest.ini - -**TODO**: Add PYTHONPATH configuration to pytest.ini or add __init__.py files to fix imports - ---- - -## Outstanding Questions โ“ - -### 1. **DECIDE Mechanic Interactive Flow** โœ… RESOLVED -**Question**: How should DECIDE mechanic interactive flow work? - -**Context**: Result 12 creates DECIDE opportunities where offense chooses if lead runner attempts to advance, then defense responds. - -**Resolution**: Foundation implemented in RunnerAdvancement with conservative default (runners hold). Full interactive flow will be handled by game engine layer with WebSocket events for offense/defense decisions. Safe range calculation: runner_speed - 4 + fielder_rating (max 1-19). - -### 2. **TOOTBLAN/FARTSLAM Mechanics** โœ… RESOLVED -**Question**: Should we implement TOOTBLAN and FARTSLAM mechanics from images? - -**Context**: Images show these as special d20 roll mechanics for runner advancement. - -**Resolution**: User clarified these are deprecated from the ruleset. We do NOT implement them. - -### 3. **WebSocket Event Names for Manual Submissions** โœ… RESOLVED -**Question**: What events should manual mode use? - -**Context**: Need events for rolling dice, submitting outcomes, validation, and broadcasting results. - -**Resolution**: Implemented in Task 7 with these events: -- `roll_dice` - Server rolls dice and broadcasts to players -- `submit_manual_outcome` - Player sends ManualOutcomeSubmission -- `outcome_accepted` - Server confirms valid outcome -- `outcome_rejected` - Server rejects invalid outcome (validation error) -- `dice_rolled` - Broadcast event with dice results -- `play_resolved` - Broadcast event with play result - -### 4. **Terminal Client Testing Without Frontend** โœ… RESOLVED -**Question**: How to test manual outcome submission flow without WebSocket? - -**Resolution**: Implemented in Task 8 with `roll_dice` and `manual_outcome` commands that call WebSocket handlers directly, allowing full manual mode testing in terminal client without needing a frontend. - ---- - -## Tasks for Next Session - -### Task 6: PlayResolver Integration (3-4 hours) - **FINAL TASK** - -**Files**: -- `app/core/play_resolver.py` (major refactor) -- `app/core/game_engine.py` (update calls) - -**Goal**: Integrate result charts and runner advancement into play resolution - -**Changes**: -1. Add `league_id` and `auto_mode` params to PlayResolver.__init__() -2. Create PdAutoResultChart for PD auto mode -3. Update resolve_play() to use result chart when in auto mode -4. Integrate RunnerAdvancement for all plays -5. Store hit_location in play results -6. Update all callers (game_engine, terminal_client) - -**Files to Update**: -- `app/core/play_resolver.py` - Major refactor -- `app/core/game_engine.py` - Update resolve_play calls -- `tests/unit/core/test_play_resolver.py` - Update existing tests -- `terminal_client/commands.py` - Update for auto mode support - -**Test Command**: -```bash -export PYTHONPATH=. && pytest tests/unit/core/test_play_resolver.py -v +### ๐ŸŽฏ Where to Begin (Week 8) + +1. **Read Week 8 plan** (to be created): `@.claude/implementation/WEEK_8_PLAN.md` +2. **Review database models**: `@app/models/db_models.py` + - Check `Lineup` model: `replacing_id`, `after_play`, `is_fatigued` fields + - These are already in place from Phase 1! +3. **Start with Task 1**: Substitution system + - Create `SubstitutionManager` class + - Implement pinch hitter logic first (simplest case) + - Add validation rules + +### ๐Ÿ“ Current Architecture (Week 7 Complete) + +**Game Engine Flow**: +```python +# Manual mode (SBA + PD manual) +GameEngine.resolve_manual_play( + game_id, ab_roll, outcome, hit_location +) โ†’ PlayResult + +# Auto mode (PD only) +GameEngine.resolve_play(game_id) โ†’ PlayResult ``` -**Acceptance Criteria**: -- [ ] PlayResolver accepts league_id and auto_mode params -- [ ] PD auto mode uses PdAutoResultChart -- [ ] Manual mode bypasses result charts (expects ManualOutcomeSubmission) -- [ ] RunnerAdvancement called for all groundball outcomes -- [ ] Hit location stored in play results -- [ ] All existing tests pass (no regressions) -- [ ] Terminal client works with both modes -- [ ] Integration tests verify end-to-end groundball advancement +**Play Resolution**: +```python +PlayResolver(league_id, auto_mode) + โ”œโ”€โ”€ resolve_manual_play(submission, state, ...) โ†’ PlayResult + โ”œโ”€โ”€ resolve_auto_play(state, batter, pitcher, ...) โ†’ PlayResult + โ””โ”€โ”€ resolve_outcome(outcome, hit_location, state, ...) โ†’ PlayResult (core) +``` + +**Runner Advancement**: +```python +RunnerAdvancement.advance_runners( + outcome, hit_location, state, defensive_decision +) โ†’ AdvancementResult +``` + +### ๐Ÿ”‘ Key Files for Week 8 + +**Substitution System**: +- `app/models/db_models.py` - Lineup model (already has substitution fields!) +- `app/core/substitution_manager.py` (NEW) - Handle substitution logic +- `app/core/validators.py` - Add substitution validation +- `tests/unit/core/test_substitution_manager.py` (NEW) + +**Pitching Changes**: +- `app/core/game_engine.py` - Add `change_pitcher()` method +- `app/models/game_models.py` - Add pitching state tracking +- `app/core/validators.py` - Validate pitcher eligibility + +**Terminal Client**: +- `terminal_client/commands.py` - Add sub commands +- `terminal_client/repl.py` - Add REPL integration + +### ๐Ÿงช Testing Strategy + +```bash +# Run substitution tests +export PYTHONPATH=. && pytest tests/unit/core/test_substitution_manager.py -v + +# Run all core tests (should still pass) +export PYTHONPATH=. && pytest tests/unit/core/ -v + +# Manual testing in terminal client +python -m terminal_client +> new_game +> start_game +> pinch_hit 5 101 # Pinch hit for batting order 5 with lineup_id 101 +> status +``` --- -## Files to Review Before Starting +## Week 7 Architectural Decisions (Reference) -### For Task 6 (PlayResolver Integration): -1. `app/core/runner_advancement.py` - NEW RunnerAdvancement class to integrate -2. `app/core/play_resolver.py` - Entire file needs refactor -3. `app/core/game_engine.py` - resolve_play calls that need updating -4. `app/config/result_charts.py` - ResultChart interface and hit location helpers -5. `tests/unit/core/test_play_resolver.py` - Update all existing tests -6. `tests/unit/core/test_runner_advancement.py` - Reference for advancement behavior +### 1. **Outcome-First PlayResolver Architecture** +- **Manual mode is primary** - Most games use this (all SBA + half of PD) +- **Core `resolve_outcome()` method** - All game logic in one place +- **Thin wrappers** - `resolve_manual_play()` and `resolve_auto_play()` +- **No hard-coded exceptions** - Multi-step plays handled generically by GameEngine + +### 2. **Auto Mode Configuration** +- **Stored per-game** - `GameState.auto_mode` field +- **League validation** - `supports_auto_mode()` in config + - SBA: `False` (raises error if attempted) + - PD: `True` (has digitized ratings) + +### 3. **Hit Location Tracking** +- **Critical for advancement** - Determines chart row and conditionals +- **Groundballs** - Must specify location (1B, 2B, 3B, SS, P, C) +- **Flyouts** - Track for future tag-up logic (LF, CF, RF) +- **Other outcomes** - `None` (walks, strikeouts, etc.) + +### 4. **Manual vs Auto Mode** +**Manual Mode** (primary): +```python +1. Server rolls dice โ†’ AbRoll +2. Broadcasts dice to players via WebSocket +3. Players read physical cards +4. Players submit outcome + location +5. Server validates ManualOutcomeSubmission +6. Server resolves with RunnerAdvancement +7. Broadcasts result +``` + +**Auto Mode** (PD only, rare): +```python +1. Server rolls dice โ†’ AbRoll +2. PdAutoResultChart.get_outcome(roll, batter, pitcher) โ†’ outcome + location +3. Server resolves with RunnerAdvancement +4. Broadcasts result +``` --- -## Verification Steps +## Important Patterns & Conventions -After Task 6: +### Testing +- **Always use venv**: `source venv/bin/activate` +- **Set PYTHONPATH**: `export PYTHONPATH=.` +- **Run tests after each change**: `pytest tests/unit/core/ -v` -1. **Run unit tests**: - ```bash - # Runner advancement tests - export PYTHONPATH=. && pytest tests/unit/core/test_runner_advancement.py -v +### Git Commits +- **Prefix with "CLAUDE: "**: All commits must start with this +- **Descriptive messages**: Include what changed and why +- **Reference tasks**: "Implement Week 8 Task 1 - Substitution System" - # Play resolver tests - export PYTHONPATH=. && pytest tests/unit/core/test_play_resolver.py -v +### Code Style +- **Pydantic dataclasses** - For models and validation +- **Async/await** - All database operations +- **Frozen configs** - Immutable league configurations +- **"Raise or Return"** - No Optional unless required +- **Pendulum for dates** - Never use Python's datetime - # All core tests - export PYTHONPATH=. && pytest tests/unit/core/ -v - ``` - -2. **Run all tests** (check for regressions): - ```bash - export PYTHONPATH=. && pytest tests/unit/ -v - ``` - -3. **Terminal client testing**: - ```bash - python -m terminal_client - > new_game --league pd --auto - > defensive normal normal normal - > offensive normal - > resolve # Auto mode - - > new_game --league sba - > roll_dice - > manual_outcome groundball_c SS # Manual mode - > status - ``` - -4. **Commit after each task**: - ```bash - git add [modified files] - git commit -m "CLAUDE: Implement Week 7 Task [N] - [Task Name]" - ``` +### Documentation +- **Update NEXT_SESSION.md** - After completing tasks +- **Add TODO comments** - For future work +- **Docstrings** - Google style for classes and public methods --- -## Success Criteria +## Current Test Status -**Week 7** will be **100% complete** when: - -- โœ… Task 1: Strategic Decision Integration (DONE) -- โœ… Task 2: Decision Validators (DONE - 54 tests passing) -- โœ… Task 3: Result Charts + PD Auto Mode (DONE - 21 tests passing) -- โœ… Task 4: Runner Advancement Logic (DONE - 30 tests passing) -- โœ… Task 5: Double Play Mechanics (DONE - integrated into Task 4) -- โœ… Task 6: PlayResolver Integration (DONE - 9 new tests, 180/181 core tests passing) -- โœ… Task 7: WebSocket Manual Outcome Handlers (DONE - 12 tests passing) -- โœ… Task 8: Terminal Client Enhancement (DONE - manual commands working) -- โœ… All 126 new tests passing (100%) -- โœ… Terminal client works in manual mode (auto mode configurable) -- โœ… Documentation updated -- โœ… Git commits for each task - -**Week 8** will begin with: -- Substitution system (pinch hitters, defensive replacements) -- Pitching changes (bullpen management) -- Frontend game interface (mobile-first) - ---- - -## Quick Reference - -**Current Test Count**: ~519 tests passing -- Config tests: 79/79 โœ… (58 + 21 new from Task 3) +**Total Tests**: ~519 tests +- Config: 79/79 โœ… (58 base + 21 result charts) - Validators: 54/54 โœ… -- Runner advancement: 30/30 โœ… (NEW from Tasks 4 & 5) -- WebSocket handlers: 12/12 โœ… (NEW from Task 7) -- Play resolver tests: 19/19 โœ… -- Dice tests: 34/35 (1 pre-existing failure) -- Roll types tests: 27/27 โœ… -- Player models: 32/32 โœ… -- Game models: ~150+ โœ… -- State manager: ~80+ โœ… +- Runner Advancement: 30/30 โœ… +- PlayResolver: 9/9 โœ… (rewritten for new architecture) +- WebSocket Handlers: 12/12 โœ… +- Dice: 34/35 (1 pre-existing failure in get_rolls_since) +- Roll Types: 27/27 โœ… +- Player Models: 32/32 โœ… +- Game Models: ~150+ โœ… +- State Manager: ~80+ โœ… -**Target Test Count After Week 7**: ~550+ tests -**Current Progress**: 519/550 (94%) +**Week 8 Target**: Add ~50 new tests for substitutions and pitching -**Last Test Run**: All passing except 1 pre-existing (2025-10-30) -**Branch**: `implement-phase-2` +--- + +## Database & Environment + +**Database**: PostgreSQL @ 10.10.0.42:5432 (paperdynasty_dev) **Python**: 3.13.3 **Virtual Env**: `backend/venv/` -**Database**: PostgreSQL @ 10.10.0.42:5432 (paperdynasty_dev) +**Branch**: `implement-phase-2` -**Key Imports for Week 7 Remaining Tasks**: -```python -from app.config import get_league_config, PlayOutcome -from app.config.result_charts import calculate_hit_location, PdAutoResultChart, ManualOutcomeSubmission -from app.core.dice import AbRoll -from app.core.validators import game_validator, ValidationError -from app.core.state_manager import state_manager -from app.core.ai_opponent import ai_opponent -from app.models.game_models import DefensiveDecision, OffensiveDecision, GameState, ManualOutcomeSubmission -``` +**Key Commands**: +```bash +# Activate venv +cd backend && source venv/bin/activate -**Recent Commit History** (Last 10): -``` -102cbb6 - CLAUDE: Implement Week 7 Tasks 4 & 5 - Runner advancement logic and double play mechanics -9cae63a - CLAUDE: Implement Week 7 Task 7 - WebSocket manual outcome handlers -9b03fb5 - CLAUDE: Implement play rollback functionality for error recovery -8ecce0f - CLAUDE: Implement forced outcome feature for terminal client testing -16ba30b - CLAUDE: Update NEXT_SESSION.md with Week 7 Task 3 completion status -9245b4e - CLAUDE: Implement Week 7 Task 3 - Result chart abstraction and PD auto mode -c0051d2 - CLAUDE: Fix defensive decision validation for corners_in/infield_in depths -f07d8ca - CLAUDE: Update NEXT_SESSION.md - Task 2 complete -121a908 - CLAUDE: Implement Week 7 Task 2 - Decision Validators -0a21eda - CLAUDE: Update project plan for Week 7 continuation +# Run tests +export PYTHONPATH=. && pytest tests/unit/core/ -v + +# Terminal client +python -m terminal_client + +# Check git status +git status ``` --- -## Context for AI Agent Resume +## What NOT to Do -**If the next agent needs to understand the bigger picture**: -- **Overall project**: See `@prd-web-scorecard-1.1.md` and `@CLAUDE.md` -- **Architecture**: See `@.claude/implementation/00-index.md` -- **Backend guide**: See `@backend/CLAUDE.md` -- **Current phase details**: See `@.claude/implementation/03-gameplay-features.md` -- **Week 7 detailed plan**: See `@.claude/implementation/WEEK_7_PLAN.md` - -**Critical files for current work (Week 7 Task 6)**: -1. `app/core/runner_advancement.py` - โœ… COMPLETE - Runner advancement logic with 13 result types -2. `app/core/play_resolver.py` - UPDATE for Task 6 (integrate RunnerAdvancement) -3. `app/core/game_engine.py` - UPDATE for Task 6 (update resolve_play calls) -4. `app/config/result_charts.py` - REFERENCE for hit location logic -5. `tests/unit/core/test_runner_advancement.py` - REFERENCE for advancement behavior -6. `tests/unit/core/test_play_resolver.py` - UPDATE with integration tests - -**What NOT to do**: -- โŒ Don't modify database schema without migration -- โŒ Don't use Python's datetime module (use Pendulum) -- โŒ Don't return Optional unless required (Raise or Return pattern) -- โŒ Don't disable type checking globally (use targeted # type: ignore) -- โŒ Don't skip validation - all decisions must be validated -- โŒ Don't implement full AI logic yet (Week 9 task) +- โŒ Don't modify database schema without migrations +- โŒ Don't use Python's `datetime` (use Pendulum) +- โŒ Don't return `Optional` unless required +- โŒ Don't disable type checking globally +- โŒ Don't skip validation - โŒ Don't commit without "CLAUDE: " prefix - โŒ Don't forget `export PYTHONPATH=.` when running tests -- โŒ Don't try to change PlayOutcome with decision modifiers (affects advancement, not outcome) - -**Patterns we're using**: -- โœ… Pydantic dataclasses for models -- โœ… Async/await for all database operations -- โœ… Frozen configs for immutability -- โœ… asyncio.Future for decision queue -- โœ… Validator pattern with clear error messages -- โœ… Result chart abstraction for league-specific resolution -- โœ… Manual vs auto mode separation (manual = WebSocket, auto = result charts) -- โœ… Hit location tracking for advancement logic -- โœ… TODO comments for future work (Week 9 AI, Week 8 substitutions) - -**Manual Mode Flow**: -```python -# 1. Player requests action -> resolve - -# 2. Server rolls dice -dice = dice_system.roll_ab(game_id) - -# 3. Server broadcasts dice to players via WebSocket -emit('dice_rolled', {column_d6, row_2d6, chaos_d20}) - -# 4. Players read physical cards -[Human player looks at card] - -# 5. Player submits outcome via WebSocket -emit('submit_manual_outcome', { - outcome: 'groundball_c', - hit_location: 'SS' -}) - -# 6. Server validates ManualOutcomeSubmission -submission = ManualOutcomeSubmission(**data) - -# 7. Server resolves play with manual outcome -result = play_resolver.resolve_with_manual_outcome(submission, state) - -# 8. Server broadcasts result -emit('play_resolved', result) -``` - -**Auto Mode Flow**: -```python -# 1. Player requests action -> resolve - -# 2. Server generates outcome automatically -outcome, location = result_chart.get_outcome(roll, state, batter, pitcher) - -# 3. Server resolves play with auto outcome -result = play_resolver.resolve_play(outcome, location, state) - -# 4. Server broadcasts result -emit('play_resolved', result) -``` +- โŒ Don't hard-code multi-step play logic (keep it generic) --- -**Estimated Time for Next Session**: 3-4 hours (Task 6 only - final task!) -**Priority**: High (completes Week 7) -**Blocking Other Work**: No (WebSocket handlers and terminal client already complete) -**Next Milestone After This**: Week 8 - Substitutions + Frontend UI +## References -**Status**: Week 7 is 87% complete, only PlayResolver integration remaining! +- **Implementation Guide**: `@.claude/implementation/01-infrastructure.md` +- **Backend Architecture**: `@.claude/implementation/backend-architecture.md` +- **Week 7 Plan**: `@.claude/implementation/WEEK_7_PLAN.md` +- **Database Design**: `@.claude/implementation/database-design.md` +- **Full PRD**: `@prd-web-scorecard-1.1.md` + +--- + +**Status**: โœ… Week 7 Complete - Ready for Week 8! +**Priority**: High - Substitutions are core gameplay feature +**Estimated Time**: Week 8 should take 3-5 sessions +**Next Milestone**: Complete substitution system and pitching management