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>
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
- Read this entire document first
- Review
@.claude/implementation/WEEK_7_PLAN.mdfor comprehensive task details - Start with Task 2: Decision Validators (next logical step)
- 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_decisionandpending_offensive_decisionfields - Added
decision_phasetracking (idle, awaiting_defensive, awaiting_offensive, resolving, completed) - Added
decision_deadlinefield (ISO8601 timestamp) for timeout handling - Added
is_batting_team_ai()andis_fielding_team_ai()helper methods - Added validator for
decision_phasefield - Impact: State can now track the full decision workflow lifecycle
- Added
-
StateManager (
app/core/state_manager.py)- Added
_pending_decisionsdict 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
- Added
-
GameEngine (
app/core/game_engine.py)- Added
DECISION_TIMEOUTconstant (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
- Added
-
AI Opponent Stub (
app/core/ai_opponent.py)- Created new module with
AIOpponentclass 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
- Created new module with
-
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_outcomescommand - 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
- Added
-
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_opponentmodule
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 neededdecision_accepted- Confirm decision receiveddecision_submitted- Broadcast to room that decision was madedecision_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:
- Add
validate_defensive_decision(state, decision)method - Add
validate_offensive_decision(state, decision)method - Validate hold runners exist on bases
- Validate steal attempts have runners
- Validate bunt/hit-and-run situational requirements
- Clear error messages for each validation failure
Files to Update:
app/core/validators.py- Add two new validation methodstests/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 validationsvalidate_defensive_decision()checks infield depth vs outs (DP with 2 outs = error)validate_offensive_decision()checks steal attempts have runners on basevalidate_offensive_decision()checks bunt not attempted with 2 outsvalidate_offensive_decision()checks hit-and-run has at least one runner- All validators raise
ValidationErrorwith 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:
- Create abstract
ResultChartbase class - Implement
StandardResultChart.get_outcome()with decision modifiers - Implement hit location logic (pull/center/opposite distribution)
- Add defensive modifier methods (shifts, depths affect outcomes)
- Add offensive modifier methods (approaches affect outcomes)
Files to Update:
app/config/result_charts.py- ReplaceSimplifiedResultCharttests/unit/config/test_result_charts.py- Add ~25 test cases
Test Command:
pytest tests/unit/config/test_result_charts.py -v
Acceptance Criteria:
ResultChartabstract base class withget_outcome()methodStandardResultChartuses 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:
- Create
RunnerAdvancerclass for runner movement calculation - Implement
calculate_destination()for each outcome type - Implement tag-up rules for flyouts
- Implement force play detection
- Create
PdResultChartusing player card ratings
Files to Update:
app/config/result_charts.py- AddRunnerAdvancerandPdResultCharttests/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
PdResultChartuses 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:
- Add
_resolve_double_play_attempt()method - Calculate DP probability based on positioning, hit location, speed
- Return (outs_recorded, [runner_ids_out])
- Integrate with
_resolve_outcome()for GROUNDBALL_A
Files to Update:
app/core/play_resolver.py- Add DP resolution logictests/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:
- Add
submit_defensive_decisionevent handler - Add
submit_offensive_decisionevent handler - Validate team_id matches current turn
- Call
state_manager.submit_decision()to resolve futures - Broadcast decision submission to game room
- Emit
decision_requiredevents (for frontend)
Files to Update:
app/websocket/handlers.py- Add decision handlerstests/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_decisionvalidates team_idsubmit_defensive_decisioncalls validatorssubmit_defensive_decisionresolves pending futuresubmit_offensive_decisionsame validations- Error handling with clear messages
- Broadcast
decision_submittedto game room - Emit
decision_requiredwhen 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:
- Enhance
defensivecommand with all options - Enhance
offensivecommand with all options - Update help text with examples
- Add validation error display
Files to Update:
terminal_client/commands.py- Enhanced option parsingterminal_client/help_text.py- Updated documentationterminal_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
app/core/validators.py- Existing validation patterns to followapp/config/result_charts.py- SimplifiedResultChart to enhanceapp/core/play_resolver.py- Integration point for new result chartsapp/websocket/handlers.py- Existing handler patterns.claude/implementation/WEEK_7_PLAN.md:120-600- Detailed code examples for all taskstests/unit/core/test_validators.py- Test patterns to follow
Verification Steps
After each task:
-
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 -
Terminal client testing:
python -m terminal_client > new_game > defensive shifted_left double_play normal > offensive power --steal 2 > resolve > status -
Integration test:
pytest tests/integration/test_strategic_gameplay.py -v -
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.mdand@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):
app/core/validators.py- Add decision validators (Task 2)app/config/result_charts.py- Enhance result charts (Tasks 3-4)app/core/play_resolver.py- Add DP mechanics (Task 5)app/websocket/handlers.py- Add decision handlers (Task 6)terminal_client/commands.py- Enhance client (Task 7)app/core/game_engine.py- Already enhanced with decision workflowapp/core/state_manager.py- Already enhanced with decision queueapp/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