🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
30 KiB
Next Session Plan - Phase 3 Week 7 in Progress
Current Status: Phase 3 - Week 7 (~62% Complete)
Last Commit: 9cae63a - "CLAUDE: Implement Week 7 Task 7 - WebSocket manual outcome handlers"
Date: 2025-10-30
Remaining Work: 38% (3 of 8 tasks remaining, Task 7 complete!)
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 4: Runner Advancement Logic (next logical step)
- Run tests after each change:
export PYTHONPATH=. && pytest tests/unit/config/ -v
📍 Current Context
Week 7 Tasks 1-3 and 7 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 7: WebSocket manual outcome handlers with 12 tests passing ✅
Next up: Implement runner advancement logic (Task 4)! This is the CRITICAL component that uses hit locations from Task 3 to determine where runners go based on outcome + game situation (Infield In/Back charts, tag-ups, force plays, etc.). This is where the advancement charts from the user images come into play.
Note: Task 7 completed out of order because Task 4 requires advancement chart images 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
- ResultChart abstract base class: Defines
-
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
- PdAutoResultChart: Full auto-generation for PD games
-
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 resultsmanual_outcome <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)
- roll_dice tests (4):
-
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
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. Legacy Bot Code Review Timing
Question: When should we review ../paper-dynasty/discord-app/in_game/ for advancement logic?
Context: User mentioned legacy bot has dozens of advancement scenarios coded. We should NOT reuse the code (not optimized) but the LOGIC is valuable.
Recommendation: Review before starting Task 4 to understand all edge cases (TOOTBLAN, FARTSLAM, DECIDE mechanics from user's images).
2. WebSocket Event Names for Manual Submissions
Question: What events should manual mode use?
Context: Need events for:
- Rolling dice and presenting to players
- Players submitting ManualOutcomeSubmission
- Validating submission
- Broadcasting result
Proposed Names:
roll_dice- Server rolls dice and broadcasts to playerssubmit_manual_outcome- Player sends ManualOutcomeSubmissionoutcome_accepted- Server confirms valid outcomeoutcome_rejected- Server rejects invalid outcome (validation error)
Recommendation: Define in Task 6 (WebSocket Handlers).
3. Terminal Client Testing Without Frontend
Question: How to test manual outcome submission flow without WebSocket?
Context: Terminal client currently uses game engine directly. Manual mode flow goes through WebSocket.
Options:
- A) Add
manual_outcomecommand that simulates WebSocket submission - B) Skip terminal client manual mode testing until WebSocket handlers done
- C) Add test-only bypass in game engine for manual outcomes
Recommendation: Option A - add manual_outcome command in Task 8 (Terminal Client Enhancement).
Tasks for Next Session
Task 4: Runner Advancement Logic (6-8 hours) - HIGH PRIORITY
Files:
app/core/runner_advancement.py(NEW)app/core/play_resolver.py(integrate)tests/unit/core/test_runner_advancement.py(NEW)
Goal: Implement complete runner advancement logic using hit locations and game situation
Changes:
-
Create
RunnerAdvancementclass:advance_runners(outcome, hit_location, state, defensive_decision) -> dict- Returns movements:
{runner_id: {from_base: int, to_base: int, is_out: bool}}
-
Implement Infield Back advancement (user's first image):
- Normal advancement for standard plays
- Special rules for GROUNDBALL_C based on base situation
-
Implement Infield In advancement (user's second image):
- Runner on 3rd scores on contact (GROUNDBALL_C)
- Lead runner advancement based on hit location
- TOOTBLAN mechanic (pick-off at third attempt)
- FARTSLAM mechanic (runner tries to score on grounder)
- DECIDE mechanic (lead runner can attempt advance)
-
Implement tag-up logic for flyouts:
- Shallow flies: no advancement
- Medium flies: R3 can tag
- Deep flies: R3 tags, R2 can advance
-
Force play detection:
- Runner must advance if forced
- Used in advancement calculations
Files to Update:
app/core/runner_advancement.py- NEW file with RunnerAdvancement classapp/core/play_resolver.py- Integration point (call RunnerAdvancement)tests/unit/core/test_runner_advancement.py- NEW, ~30 test cases
Test Command:
export PYTHONPATH=. && pytest tests/unit/core/test_runner_advancement.py -v
Acceptance Criteria:
- RunnerAdvancement.advance_runners() returns correct movements dict
- Infield Back chart implemented (all 9 base situations from user image)
- Infield In chart implemented (all variations from user image)
- TOOTBLAN mechanic implemented (d20 roll for pick-off attempt)
- FARTSLAM mechanic implemented (d20 roll for safe range)
- DECIDE mechanic implemented (offense chooses advancement)
- Tag-up logic for flyouts (R3 on deep fly, etc.)
- Force play detection works correctly
- Hit location affects advancement (1B/3B/P/C for corners_in)
- 30+ test cases covering all scenarios
- Integration with play_resolver works
IMPORTANT: Review ../paper-dynasty/discord-app/in_game/ before starting to understand all edge cases!
Task 5: Double Play Mechanics (2-3 hours)
Files:
app/core/play_resolver.py(enhance)tests/unit/core/test_play_resolver.py(add tests)
Goal: Implement double play resolution for GROUNDBALL_A outcomes
Changes:
- Add
_resolve_double_play_attempt()method - Calculate DP probability based on:
- Base probability: 45%
- Positioning modifiers (DP depth +20%, infield in -15%)
- Hit location modifiers (up middle +10%, corners -10%)
- Runner speed modifiers (fast -15%, slow +10%)
- Return (outs_recorded, [runner_ids_out])
- Integrate with
_resolve_outcome()for GROUNDBALL_A
Files to Update:
app/core/play_resolver.py- Add DP resolutiontests/unit/core/test_play_resolver.py- Add ~10 DP tests
Test Command:
export PYTHONPATH=. && pytest tests/unit/core/test_play_resolver.py::test_double_play -v
Acceptance Criteria:
- Base DP probability: 45%
- Positioning modifiers work correctly
- Hit location modifiers work correctly
- Runner speed considered (need player speed data)
- Returns correct outs_recorded
- Returns correct runner_ids_out list
- Terminal client shows "DP" in description
- 10+ test cases for various scenarios
Task 6: PlayResolver Integration (3-4 hours)
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:
- Add
league_idandauto_modeparams to PlayResolver.init() - Create PdAutoResultChart for PD auto mode
- Update resolve_play() to use result chart when in auto mode
- Integrate RunnerAdvancement for all plays
- Store hit_location in play results
- Update all callers (game_engine, terminal_client)
Files to Update:
app/core/play_resolver.py- Major refactorapp/core/game_engine.py- Update resolve_play callstests/unit/core/test_play_resolver.py- Update existing teststerminal_client/commands.py- Update for auto mode support
Test Command:
export PYTHONPATH=. && pytest tests/unit/core/test_play_resolver.py -v
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 outcomes
- Hit location stored in play results
- All existing tests pass (no regressions)
- Terminal client works with both modes
Task 7: WebSocket Handlers for Manual Submissions (3-4 hours)
Files:
app/websocket/handlers.py(add handlers)tests/unit/websocket/test_manual_outcome_handlers.py(NEW)
Goal: Create WebSocket event handlers for manual outcome submission
Changes:
- Add
roll_diceevent handler - Server rolls and broadcasts dice - Add
submit_manual_outcomeevent handler - Validates ManualOutcomeSubmission - Validate outcome is valid PlayOutcome
- Validate location provided when required
- Call play_resolver with manual outcome
- Broadcast result to game room
Files to Update:
app/websocket/handlers.py- Add manual outcome handlersapp/websocket/events.py- Define event names (if doesn't exist)tests/unit/websocket/test_manual_outcome_handlers.py- NEW, ~15 tests
Test Command:
export PYTHONPATH=. && pytest tests/unit/websocket/test_manual_outcome_handlers.py -v
Acceptance Criteria:
roll_dicehandler rolls dice and broadcasts to playerssubmit_manual_outcomevalidates ManualOutcomeSubmission- Validates outcome is valid PlayOutcome enum value
- Validates location provided for groundballs/flyouts
- Rejects invalid outcomes with clear error
- Calls play_resolver with manual outcome
- Broadcasts result to game room
- 15+ test cases for all scenarios
- Error handling with clear messages
Task 8: Terminal Client Enhancement (2-3 hours)
Files:
terminal_client/commands.py(add command)terminal_client/help_text.py(update docs)terminal_client/completions.py(add completions)
Goal: Add manual_outcome command for testing manual submission flow
Changes:
- Add
manual_outcome <outcome> [location]command - Validates outcome is valid PlayOutcome
- Validates location if required
- Simulates manual submission (bypasses WebSocket for testing)
- Add TAB completion for outcome names
- Update help text with examples
Files to Update:
terminal_client/commands.py- Add manual_outcome commandterminal_client/help_text.py- Update documentationterminal_client/completions.py- Add TAB completions
Test Command:
python -m terminal_client
> help manual_outcome
> new_game --league sba
> roll_dice
> manual_outcome groundball_c SS
> status
Acceptance Criteria:
manual_outcomecommand accepts outcome + optional location- Validates outcome is valid PlayOutcome
- Validates location if required (groundballs/flyouts)
- Simulates manual submission flow
- TAB completion for outcome names works
- Help text shows examples
- Manual testing passes
- Works alongside auto resolution mode
Files to Review Before Starting
For Task 4 (Runner Advancement):
../paper-dynasty/discord-app/in_game/- Legacy bot advancement logic (DO NOT copy code, study LOGIC)- User's advancement chart images (already provided - see session context)
app/config/result_charts.py:203-278- calculate_hit_location() for understanding locationsapp/models/game_models.py:247-450- GameState model for base runner accessapp/core/play_resolver.py- Current resolution logic to integrate with
For Task 5 (Double Play):
app/core/play_resolver.py- SimplifiedResultChart.get_outcome() for integration pointapp/models/game_models.py- GameState for runner accesstests/unit/core/test_play_resolver.py- Existing test patterns
For Task 6 (Integration):
app/core/play_resolver.py- Entire file needs refactorapp/core/game_engine.py:300-400- resolve_play callsapp/config/result_charts.py- ResultChart interfacetests/unit/core/test_play_resolver.py- Update all tests
For Task 7 (WebSocket):
app/websocket/handlers.py- Existing handler patternsapp/websocket/connection_manager.py- Broadcasting methodsapp/models/game_models.py:192-240- ManualOutcomeSubmission model
Verification Steps
After each task:
-
Run unit tests:
# After Task 4 export PYTHONPATH=. && pytest tests/unit/core/test_runner_advancement.py -v # After Task 5 export PYTHONPATH=. && pytest tests/unit/core/test_play_resolver.py -v # After Task 6 export PYTHONPATH=. && pytest tests/unit/core/ -v # After Task 7 export PYTHONPATH=. && pytest tests/unit/websocket/ -v # After Task 8 python -m terminal_client # Manual testing -
Run all tests (check for regressions):
export PYTHONPATH=. && pytest tests/unit/ -v -
Terminal client testing:
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 -
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 (DONE - 54 tests passing)
- ✅ Task 3: Result Charts + PD Auto Mode (DONE - 21 tests passing)
- Task 4: Runner Advancement Logic (~30 tests passing) - BLOCKED: Awaiting advancement chart images from user
- Task 5: Double Play Mechanics (~10 tests passing)
- Task 6: PlayResolver Integration (all existing tests still pass)
- ✅ Task 7: WebSocket Manual Outcome Handlers (DONE - 12 tests passing)
- ✅ Task 8: Terminal Client Enhancement (DONE - manual commands working)
- All 130+ new tests passing (currently 87/130 done - 67%)
- ✅ Terminal client demonstrates both auto and manual modes
- ✅ 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: ~489 tests passing
- Config tests: 79/79 ✅ (58 + 21 new from Task 3)
- Validators: 54/54 ✅
- 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+ ✅
Target Test Count After Week 7: ~550+ tests Current Progress: 489/550 (89%)
Last Test Run: All passing except 1 pre-existing (2025-10-30)
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 Remaining Tasks:
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
Recent Commit History (Last 10):
9245b4e - CLAUDE: Implement Week 7 Task 3 - Result chart abstraction and PD auto mode (53 seconds ago)
c0051d2 - CLAUDE: Fix defensive decision validation for corners_in/infield_in depths (2 hours ago)
f07d8ca - CLAUDE: Update NEXT_SESSION.md - Task 2 complete (6 hours ago)
121a908 - CLAUDE: Implement Week 7 Task 2 - Decision Validators (6 hours ago)
0a21eda - CLAUDE: Update project plan for Week 7 continuation (11 hours ago)
95d8703 - CLAUDE: Implement Week 7 Task 1 - Strategic Decision Integration (15 hours ago)
d7caa75 - CLAUDE: Add manual outcome testing to terminal client and Phase 3 planning (16 hours ago)
6880b6d - CLAUDE: Complete Week 6 - granular PlayOutcome integration and metadata support (16 hours ago)
64aa800 - CLAUDE: Update implementation plans for next session (2 days ago)
5d5c13f - CLAUDE: Implement Week 6 league configuration and play outcome systems (2 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 4-8):
app/core/runner_advancement.py- CREATE for Task 4 (runner advancement logic)app/core/play_resolver.py- UPDATE for Tasks 5-6 (DP mechanics + integration)app/websocket/handlers.py- UPDATE for Task 7 (manual outcome handlers)terminal_client/commands.py- UPDATE for Task 8 (manual outcome command)app/config/result_charts.py- REFERENCE for hit location logicapp/core/game_engine.py- REFERENCE for integration pointsapp/core/state_manager.py- REFERENCE for decision workflowapp/core/ai_opponent.py- REFERENCE for AI decision generation
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
- ❌ 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:
# 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:
# 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)
Estimated Time for Next Session: 16-22 hours (Tasks 4-8) Priority: High (Task 4 is critical - all advancement logic) Blocking Other Work: Yes (frontend needs WebSocket handlers from Task 7) Next Milestone After This: Week 8 - Substitutions + Frontend UI