strat-gameplay-webapp/.claude/implementation/NEXT_SESSION.md
Cal Corum 0a21edad5c CLAUDE: Update project plan for Week 7 continuation
Project Plan Updates:
- Updated NEXT_SESSION.md with comprehensive Week 7 status
- Current status: Phase 3 Week 7 at 17% complete (1 of 6 tasks done)
- Documented Task 1 completion (Strategic Decision Integration)
- Created detailed task breakdown for Tasks 2-7
- Added architectural decision documentation
- Included outstanding questions and verification steps

Session Accomplishments:
- Task 1: Strategic Decision Integration (100% complete)
  - GameState: Added decision phase tracking and AI helper methods
  - StateManager: Implemented asyncio.Future decision queue
  - GameEngine: Added await_defensive/offensive_decision methods
  - AI Opponent: Created stub with default decisions
- Bonus: Manual outcome testing feature for terminal client
- Planning: Complete Week 7 plan document (25 pages)

Next Session Tasks:
1. Task 2: Decision Validators (3-4h)
2. Task 3: Result Charts Part A (4-5h)
3. Task 4: Result Charts Part B (4-5h)
4. Task 5: Double Play Mechanics (2-3h)
5. Task 6: WebSocket Handlers (3-4h)
6. Task 7: Terminal Client Enhancement (2-3h)

Slash Commands:
- Added save-project-plan.md command definition

Test Status: 200/201 passing
Target: 285+ after Week 7 complete

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 01:24:51 -05:00

22 KiB

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 <outcome> 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:

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:

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:

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:

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:

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:

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:

    # 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:

    python -m terminal_client
    > new_game
    > defensive shifted_left double_play normal
    > offensive power --steal 2
    > resolve
    > status
    
  3. Integration test:

    pytest tests/integration/test_strategic_gameplay.py -v
    
  4. Commit after each task:

    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:

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:

# 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