# Next Session Plan - Phase 3 Week 7 in Progress **Current Status**: Phase 3 - Week 7 (~17% Complete) **Last Commit**: `95d8703` - "CLAUDE: Implement Week 7 Task 1 - Strategic Decision Integration" **Date**: 2025-10-29 **Remaining Work**: 83% (5 of 6 tasks remaining) --- ## 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 2: Decision Validators** (next logical step) 4. Run tests after each change: `pytest tests/unit/core/test_validators.py -v` ### 📍 Current Context **Week 7 Task 1 is complete!** We've implemented the async decision workflow infrastructure that integrates AI and human decision-making. The GameEngine now has `await_defensive_decision()` and `await_offensive_decision()` methods that use asyncio Futures for WebSocket communication. AI teams get instant decisions, human teams wait with timeout. **Next up**: Validate those decisions! Task 2 adds `validate_defensive_decision()` and `validate_offensive_decision()` to the validators module to ensure decisions are legal for the current game state. --- ## What We Just Completed ✅ ### 1. Strategic Decision Integration (Week 7 Task 1) - 100% - **GameState Model** (`app/models/game_models.py`) - Added `pending_defensive_decision` and `pending_offensive_decision` fields - Added `decision_phase` tracking (idle, awaiting_defensive, awaiting_offensive, resolving, completed) - Added `decision_deadline` field (ISO8601 timestamp) for timeout handling - Added `is_batting_team_ai()` and `is_fielding_team_ai()` helper methods - Added validator for `decision_phase` field - **Impact**: State can now track the full decision workflow lifecycle - **StateManager** (`app/core/state_manager.py`) - Added `_pending_decisions` dict for asyncio.Future-based decision queue - Implemented `set_pending_decision()` - Creates futures for pending decisions - Implemented `await_decision()` - Waits for decision submission (blocks until resolved) - Implemented `submit_decision()` - Resolves pending futures when decisions submitted - Implemented `cancel_pending_decision()` - Cleanup on timeout/abort - **Impact**: Enables async decision workflow with WebSocket integration ready - **GameEngine** (`app/core/game_engine.py`) - Added `DECISION_TIMEOUT` constant (30 seconds) - Implemented `await_defensive_decision()` with AI/human branching and timeout - Implemented `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 - **Impact**: Fully async decision workflow, backward compatible with terminal client - **AI Opponent Stub** (`app/core/ai_opponent.py`) - Created new module with `AIOpponent` class - `generate_defensive_decision()` - Returns default "normal" positioning (stub) - `generate_offensive_decision()` - Returns default "normal" approach (stub) - TODO markers for Week 9 full AI implementation - **Impact**: AI teams can play immediately, full logic deferred to Week 9 - **Testing**: Config tests 58/58 passing ✅, Terminal client works perfectly ✅ ### 2. Manual Outcome Testing Feature (Bonus) - **Terminal Client Commands** (`terminal_client/commands.py`, `terminal_client/repl.py`) - Added `list_outcomes` command - Displays categorized table of all 30+ PlayOutcome values - Added `resolve_with ` command - Force specific outcome for testing - TAB completion for all outcome names - Full help documentation with examples - **Impact**: Can test specific scenarios without random dice rolls - **Documentation** (`.claude/implementation/MANUAL_OUTCOME_TESTING.md`) - Complete usage guide - Testing use cases (runner advancement, DP mechanics, scoring) - Implementation details - Future enhancement plan for Week 7 integration ### 3. Phase 3 Planning Complete - **Week 7 Plan** (`.claude/implementation/WEEK_7_PLAN.md`) - 25-page comprehensive plan with 6 major tasks - Code examples and acceptance criteria for each task - Testing strategy (85+ new tests planned) - **Impact**: Clear roadmap for entire Week 7 - **Implementation Index Updated** (`.claude/implementation/00-index.md`) - Marked Week 6 as 100% complete - Updated status table with granular completion tracking - Set current phase to "Phase 3 - Complete Game Features (Planning → In Progress)" --- ## Key Architecture Decisions Made ### 1. **Async Decision Workflow with Futures** **Decision**: Use `asyncio.Future` for decision queue instead of simple flag polling **Rationale**: - True async/await pattern - GameEngine blocks until decision arrives - Timeout naturally handled with `asyncio.wait_for()` - Clean separation between decision request and resolution - Works seamlessly with WebSocket event handlers **Impact**: - GameEngine can await human decisions without polling - WebSocket handlers simply call `state_manager.submit_decision()` - Timeout automatically applies default decision (no game blocking) - Fully backward compatible with terminal client ### 2. **AI/Human Decision Branching** **Decision**: Check AI status in `await_*_decision()` methods, not in submit handlers **Rationale**: - AI teams get instant decisions (no waiting) - Human teams use WebSocket workflow - Same code path for both after decision obtained - AI logic centralized in `ai_opponent` module **Impact**: - AI games play at full speed - Human games have proper timeout handling - Easy to swap AI difficulty levels - Clear separation of concerns ### 3. **Decision Phase State Machine** **Decision**: Add explicit `decision_phase` field to GameState **Rationale**: - Frontend needs to know what's expected (awaiting defensive, awaiting offensive, resolving) - Can display appropriate UI based on phase - Easy to debug decision workflow - Timestamp deadline for timeout UI **Impact**: - Frontend can show countdown timers - Clear state transitions for WebSocket events - Better user experience (know what's happening) - Easier to implement async game mode ### 4. **Stub AI for Week 7, Full AI for Week 9** **Decision**: Return sensible defaults now, defer complex AI logic **Rationale**: - Week 7 focus is decision infrastructure, not AI strategy - Default decisions allow testing without blocking - AI logic is complex enough to deserve dedicated time - Can test human vs human immediately **Impact**: - Week 7 can proceed without AI complexity - AI vs AI games work (just use defaults) - Clear TODO markers for Week 9 work - Testing not blocked on AI implementation --- ## Blockers Encountered 🚧 **None** - Development proceeded smoothly. All planned tasks completed successfully. --- ## Outstanding Questions ❓ ### 1. **Default Decision on Timeout** **Question**: Should default decision be logged/notified to user? **Context**: When human player times out, we apply default decision (all "normal" values). Should we: - A) Silently apply defaults (current implementation) - B) Log and broadcast to game room that default was used - C) Show warning message to timed-out player **Recommendation**: Option B - broadcast to game room for transparency, but don't block game flow. ### 2. **WebSocket Event Names** **Question**: What should we call the decision notification events? **Context**: Need event names for: - Requesting decision from player - Decision submitted successfully - Decision timeout/default applied **Proposed Names**: - `decision_required` - Notify player their decision is needed - `decision_accepted` - Confirm decision received - `decision_submitted` - Broadcast to room that decision was made - `decision_timeout` - Notify room that default was applied **Recommendation**: Use proposed names, add to `websocket/events.py` in Task 4. ### 3. **Validation Order** **Question**: Validate decisions before or after storing in state? **Context**: Current flow stores decision in state, then validates. Alternative is validate first, then store. **Recommendation**: Keep current order (store then validate) for debugging - can see what invalid decisions were attempted. --- ## Tasks for Next Session ### Task 2: Decision Validators (3-4 hours) **File**: `backend/app/core/validators.py` **Goal**: Add strategic decision validation to ensure decisions are legal for current game state **Changes**: 1. Add `validate_defensive_decision(state, decision)` method 2. Add `validate_offensive_decision(state, decision)` method 3. Validate hold runners exist on bases 4. Validate steal attempts have runners 5. Validate bunt/hit-and-run situational requirements 6. Clear error messages for each validation failure **Files to Update**: - `app/core/validators.py` - Add two new validation methods - `tests/unit/core/test_validators.py` - Add ~20 test cases **Test Command**: ```bash pytest tests/unit/core/test_validators.py -v ``` **Acceptance Criteria**: - [ ] `validate_defensive_decision()` checks all hold runner validations - [ ] `validate_defensive_decision()` checks infield depth vs outs (DP with 2 outs = error) - [ ] `validate_offensive_decision()` checks steal attempts have runners on base - [ ] `validate_offensive_decision()` checks bunt not attempted with 2 outs - [ ] `validate_offensive_decision()` checks hit-and-run has at least one runner - [ ] All validators raise `ValidationError` with clear messages - [ ] 20+ test cases covering all edge cases - [ ] GameEngine integration works (validators called before resolution) --- ### Task 3: Complete Result Charts - Part A (4-5 hours) **File**: `backend/app/config/result_charts.py` **Goal**: Implement `StandardResultChart` with defensive/offensive decision modifiers **Changes**: 1. Create abstract `ResultChart` base class 2. Implement `StandardResultChart.get_outcome()` with decision modifiers 3. Implement hit location logic (pull/center/opposite distribution) 4. Add defensive modifier methods (shifts, depths affect outcomes) 5. Add offensive modifier methods (approaches affect outcomes) **Files to Update**: - `app/config/result_charts.py` - Replace `SimplifiedResultChart` - `tests/unit/config/test_result_charts.py` - Add ~25 test cases **Test Command**: ```bash pytest tests/unit/config/test_result_charts.py -v ``` **Acceptance Criteria**: - [ ] `ResultChart` abstract base class with `get_outcome()` method - [ ] `StandardResultChart` uses defensive decision to modify outcomes - [ ] Infield in: GROUNDBALL_B → better chance to get lead runner - [ ] Infield back: GROUNDBALL_A → sacrifice DP opportunity - [ ] Shift: Affects hit location distribution - [ ] Contact approach: Fewer strikeouts, more weak contact - [ ] Power approach: More strikeouts, more extra-base hits - [ ] Bunt: Converts to bunt outcomes - [ ] 25+ test cases for all modifiers - [ ] Hit location logic with handedness (RHB pulls left, LHB pulls right) --- ### Task 4: Complete Result Charts - Part B (4-5 hours) **File**: `backend/app/config/result_charts.py` **Goal**: Implement runner advancement logic and `PdResultChart` **Changes**: 1. Create `RunnerAdvancer` class for runner movement calculation 2. Implement `calculate_destination()` for each outcome type 3. Implement tag-up rules for flyouts 4. Implement force play detection 5. Create `PdResultChart` using player card ratings **Files to Update**: - `app/config/result_charts.py` - Add `RunnerAdvancer` and `PdResultChart` - `tests/unit/config/test_runner_advancement.py` - Add ~20 test cases **Test Command**: ```bash pytest tests/unit/config/test_runner_advancement.py -v ``` **Acceptance Criteria**: - [ ] `RunnerAdvancer.advance_runners()` returns list of movements - [ ] Singles: R3 scores, R2 to 3rd, R1 to 2nd - [ ] Doubles: R2+ score, R1 to 3rd - [ ] Flyouts: Tag-up logic (R3 tags on medium/deep fly) - [ ] Groundouts: Score on contact logic (R3 with <2 outs) - [ ] Force plays detected correctly - [ ] `PdResultChart` uses batting/pitching rating probabilities - [ ] Cumulative distribution selects outcome from ratings - [ ] 20+ test cases for all advancement scenarios --- ### Task 5: Double Play Mechanics (2-3 hours) **File**: `backend/app/core/play_resolver.py` **Goal**: Implement double play resolution for GROUNDBALL_A outcomes **Changes**: 1. Add `_resolve_double_play_attempt()` method 2. Calculate DP probability based on positioning, hit location, speed 3. Return (outs_recorded, [runner_ids_out]) 4. Integrate with `_resolve_outcome()` for GROUNDBALL_A **Files to Update**: - `app/core/play_resolver.py` - Add DP resolution logic - `tests/unit/core/test_play_resolver.py` - Add ~10 DP test cases **Test Command**: ```bash pytest tests/unit/core/test_play_resolver.py::test_double_play -v ``` **Acceptance Criteria**: - [ ] Base DP probability: 45% - [ ] DP depth: +20% probability - [ ] Back depth: -15% probability - [ ] Up the middle (4, 6 positions): +10% - [ ] Corners (3, 5 positions): -10% - [ ] Fast runner: -15% - [ ] Slow runner: +10% - [ ] Returns correct outs and runner IDs - [ ] 10+ test cases for various scenarios - [ ] Terminal client shows "DP" in play description --- ### Task 6: WebSocket Handlers (3-4 hours) **File**: `backend/app/websocket/handlers.py` **Goal**: Create WebSocket event handlers for decision submission **Changes**: 1. Add `submit_defensive_decision` event handler 2. Add `submit_offensive_decision` event handler 3. Validate team_id matches current turn 4. Call `state_manager.submit_decision()` to resolve futures 5. Broadcast decision submission to game room 6. Emit `decision_required` events (for frontend) **Files to Update**: - `app/websocket/handlers.py` - Add decision handlers - `tests/unit/websocket/test_decision_handlers.py` - Add ~15 test cases **Test Command**: ```bash pytest tests/unit/websocket/test_decision_handlers.py -v ``` **Acceptance Criteria**: - [ ] `submit_defensive_decision` validates team_id - [ ] `submit_defensive_decision` calls validators - [ ] `submit_defensive_decision` resolves pending future - [ ] `submit_offensive_decision` same validations - [ ] Error handling with clear messages - [ ] Broadcast `decision_submitted` to game room - [ ] Emit `decision_required` when awaiting decisions - [ ] 15+ test cases for all scenarios --- ### Task 7: Terminal Client Enhancement (2-3 hours) **File**: `backend/terminal_client/commands.py` **Goal**: Add support for all decision options in terminal client **Changes**: 1. Enhance `defensive` command with all options 2. Enhance `offensive` command with all options 3. Update help text with examples 4. Add validation error display **Files to Update**: - `terminal_client/commands.py` - Enhanced option parsing - `terminal_client/help_text.py` - Updated documentation - `terminal_client/completions.py` - TAB completion for all options **Test Command**: ```bash python -m terminal_client > help defensive > help offensive > defensive shifted_left double_play normal --hold 1,3 > offensive power --steal 2 ``` **Acceptance Criteria**: - [ ] All defensive options work (alignment, depths, hold runners) - [ ] All offensive options work (approach, steals, hit-run, bunt) - [ ] TAB completion for all option values - [ ] Help text shows all examples - [ ] Validation errors display clearly - [ ] Manual testing shows all features work --- ## Files to Review Before Starting 1. `app/core/validators.py` - Existing validation patterns to follow 2. `app/config/result_charts.py` - SimplifiedResultChart to enhance 3. `app/core/play_resolver.py` - Integration point for new result charts 4. `app/websocket/handlers.py` - Existing handler patterns 5. `.claude/implementation/WEEK_7_PLAN.md:120-600` - Detailed code examples for all tasks 6. `tests/unit/core/test_validators.py` - Test patterns to follow --- ## Verification Steps After each task: 1. **Run unit tests**: ```bash # After Task 2 pytest tests/unit/core/test_validators.py -v # After Task 3 pytest tests/unit/config/test_result_charts.py -v # After Task 4 pytest tests/unit/config/test_runner_advancement.py -v # After Task 5 pytest tests/unit/core/test_play_resolver.py -v # After Task 6 pytest tests/unit/websocket/test_decision_handlers.py -v ``` 2. **Terminal client testing**: ```bash python -m terminal_client > new_game > defensive shifted_left double_play normal > offensive power --steal 2 > resolve > status ``` 3. **Integration test**: ```bash pytest tests/integration/test_strategic_gameplay.py -v ``` 4. **Commit after each task**: ```bash git add [modified files] git commit -m "CLAUDE: Implement Week 7 Task [N] - [Task Name]" ``` --- ## Success Criteria **Week 7** will be **100% complete** when: - ✅ Task 1: Strategic Decision Integration (DONE) - [ ] Task 2: Decision Validators (~20 tests passing) - [ ] Task 3: Result Charts Part A (~25 tests passing) - [ ] Task 4: Result Charts Part B (~20 tests passing) - [ ] Task 5: Double Play Mechanics (~10 tests passing) - [ ] Task 6: WebSocket Handlers (~15 tests passing) - [ ] Task 7: Terminal Client Enhancement (manual testing passes) - [ ] All 85+ new tests passing - [ ] Terminal client demonstrates all features - [ ] 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**: 200/201 tests passing (58 config + core/state/dice tests) - Config tests: 58/58 ✅ - Play resolver tests: 19/19 ✅ - Dice tests: 34/35 (1 pre-existing) - Roll types tests: 27/27 ✅ - Validators: To be added (Task 2) **Target Test Count After Week 7**: 285+ tests (85+ new tests) **Last Test Run**: All passing (2025-10-29) **Branch**: `implement-phase-2` **Python**: 3.13.3 **Virtual Env**: `backend/venv/` **Database**: PostgreSQL @ 10.10.0.42:5432 (paperdynasty_dev) **Key Imports for Week 7**: ```python from app.config import get_league_config, PlayOutcome 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 ``` **Recent Commit History** (Last 10): ``` 95d8703 - CLAUDE: Implement Week 7 Task 1 - Strategic Decision Integration (63 seconds ago) d7caa75 - CLAUDE: Add manual outcome testing to terminal client and Phase 3 planning (45 minutes ago) 6880b6d - CLAUDE: Complete Week 6 - granular PlayOutcome integration and metadata support (70 minutes ago) 64aa800 - CLAUDE: Update implementation plans for next session (23 hours ago) 5d5c13f - CLAUDE: Implement Week 6 league configuration and play outcome systems (23 hours ago) a014622 - CLAUDE: Update documentation with session improvements (31 hours ago) 1c32787 - CLAUDE: Refactor game models and modularize terminal client (31 hours ago) aabb90f - CLAUDE: Implement player models and optimize database queries (32 hours ago) 05fc037 - CLAUDE: Fix game recovery and add required field validation for plays (3 days ago) 918bead - CLAUDE: Add interactive terminal client for game engine testing (3 days ago) ``` --- ## Context for AI Agent Resume **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 Tasks 2-7)**: 1. `app/core/validators.py` - Add decision validators (Task 2) 2. `app/config/result_charts.py` - Enhance result charts (Tasks 3-4) 3. `app/core/play_resolver.py` - Add DP mechanics (Task 5) 4. `app/websocket/handlers.py` - Add decision handlers (Task 6) 5. `terminal_client/commands.py` - Enhance client (Task 7) 6. `app/core/game_engine.py` - Already enhanced with decision workflow 7. `app/core/state_manager.py` - Already enhanced with decision queue 8. `app/core/ai_opponent.py` - Stub AI (enhance in Week 9) **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 commit without "CLAUDE: " prefix **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 - ✅ TODO comments for future work (Week 9 AI, Week 8 substitutions) **Decision Workflow Pattern**: ```python # 1. GameEngine requests decision decision = await game_engine.await_defensive_decision(state) # 2a. AI team: ai_opponent generates immediately # 2b. Human team: state_manager waits for WebSocket submission # 3. WebSocket handler receives and submits state_manager.submit_decision(game_id, team_id, decision) # 4. Future resolves, GameEngine continues # 5. Validator checks decision legality # 6. Resolution uses decision to modify outcomes ``` --- **Estimated Time for Next Session**: 18-22 hours (Tasks 2-7) **Priority**: High (core Phase 3 functionality) **Blocking Other Work**: Yes (frontend needs WebSocket handlers from Task 6) **Next Milestone After This**: Week 8 - Substitutions + Frontend UI