Complete OAuth-based authentication with JWT session management:
Core Services:
- JWT service for access/refresh token creation and verification
- Token store with Redis-backed refresh token revocation
- User service for CRUD operations and OAuth-based creation
- Google and Discord OAuth services with full flow support
API Endpoints:
- GET /api/auth/{google,discord} - Start OAuth flows
- GET /api/auth/{google,discord}/callback - Handle OAuth callbacks
- POST /api/auth/refresh - Exchange refresh token for new access token
- POST /api/auth/logout - Revoke single refresh token
- POST /api/auth/logout-all - Revoke all user sessions
- GET/PATCH /api/users/me - User profile management
- GET /api/users/me/linked-accounts - List OAuth providers
- GET /api/users/me/sessions - Count active sessions
Infrastructure:
- Pydantic schemas for auth/user request/response models
- FastAPI dependencies (get_current_user, get_current_premium_user)
- OAuthLinkedAccount model for multi-provider support
- Alembic migration for oauth_linked_accounts table
Dependencies added: email-validator, fakeredis (dev), respx (dev)
84 new tests, 1058 total passing
722 lines
37 KiB
JSON
722 lines
37 KiB
JSON
{
|
|
"meta": {
|
|
"version": "1.0.0",
|
|
"created": "2026-01-24",
|
|
"lastUpdated": "2026-01-26",
|
|
"planType": "feature",
|
|
"projectName": "Mantimon TCG - Backend Game Engine",
|
|
"description": "Core game engine scaffolding for a highly configurable Pokemon TCG-inspired card game. The engine must support campaign mode with fixed rules and free play mode with user-configurable rules.",
|
|
"totalEstimatedHours": 48,
|
|
"totalTasks": 32,
|
|
"completedTasks": 32
|
|
},
|
|
"categories": {
|
|
"critical": "Foundation components that block all other work",
|
|
"high": "Core engine functionality required for basic gameplay",
|
|
"medium": "Important features for complete gameplay experience",
|
|
"low": "Polish, optimization, and nice-to-have features",
|
|
"feature": "New capabilities beyond MVP"
|
|
},
|
|
"architectureDecisions": {
|
|
"configurability": "All game rules driven by RulesConfig - defaults for campaign, user-adjustable for free play",
|
|
"rngHandling": "RandomProvider protocol with SeededRandom (tests/replays) and SecureRandom (production PvP)",
|
|
"cardRegistry": "Hybrid - definitions loaded from DB via CardService, embedded in GameState at game creation for self-contained gameplay",
|
|
"cardModels": "Separate CardDefinition (immutable template) from CardInstance (mutable in-game state)",
|
|
"actionModeling": "Union types for type safety",
|
|
"asyncSupport": "Async throughout for WebSocket compatibility",
|
|
"enumsLocation": "Enums in app/core/enums.py (foundational module with zero dependencies) - breaks circular imports and enables clean re-exports"
|
|
},
|
|
"directoryStructure": {
|
|
"core": "backend/app/core/",
|
|
"enums": "backend/app/core/enums.py",
|
|
"models": "backend/app/core/models/",
|
|
"effects": "backend/app/core/effects/",
|
|
"tests": "backend/tests/core/"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "CRIT-001",
|
|
"name": "Create core module structure",
|
|
"description": "Set up the directory structure and __init__.py files for the core game engine module hierarchy",
|
|
"category": "critical",
|
|
"priority": 1,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": [],
|
|
"files": [
|
|
{"path": "app/core/__init__.py", "status": "created"},
|
|
{"path": "app/core/models/__init__.py", "status": "created"},
|
|
{"path": "app/core/effects/__init__.py", "status": "created"},
|
|
{"path": "tests/core/__init__.py", "status": "created"},
|
|
{"path": "tests/core/test_models/__init__.py", "status": "created"},
|
|
{"path": "tests/core/test_effects/__init__.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Create all directories and empty __init__.py files with appropriate module docstrings",
|
|
"estimatedHours": 0.5,
|
|
"notes": "Foundation task - must be completed first",
|
|
"completedDate": "2026-01-24"
|
|
},
|
|
{
|
|
"id": "CRIT-002",
|
|
"name": "Create enums module",
|
|
"description": "Define all enumeration types used throughout the game engine: CardType, EnergyType, PokemonStage, PokemonVariant, TurnPhase, StatusCondition, TrainerType, ActionType, GameEndReason",
|
|
"category": "critical",
|
|
"priority": 2,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["CRIT-001"],
|
|
"files": [
|
|
{"path": "app/core/models/enums.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Create StrEnum classes for each enumeration type. Use StrEnum for JSON serialization compatibility.",
|
|
"estimatedHours": 1,
|
|
"notes": "PokemonStage (BASIC, STAGE_1, STAGE_2) separated from PokemonVariant (NORMAL, EX, GX, V, VMAX, VSTAR). Stage determines evolution mechanics, variant determines knockout points.",
|
|
"completedDate": "2026-01-24"
|
|
},
|
|
{
|
|
"id": "TEST-001",
|
|
"name": "Create enums tests",
|
|
"description": "Test that all enums serialize correctly to JSON, have expected values, and can be used in Pydantic models",
|
|
"category": "high",
|
|
"priority": 3,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["CRIT-002"],
|
|
"files": [
|
|
{"path": "tests/core/test_models/test_enums.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Test each enum: value consistency, JSON round-trip, membership checks",
|
|
"estimatedHours": 0.5,
|
|
"notes": "28 tests covering all enums including PokemonStage/PokemonVariant separation",
|
|
"completedDate": "2026-01-24"
|
|
},
|
|
{
|
|
"id": "CRIT-003",
|
|
"name": "Create RulesConfig module",
|
|
"description": "Define the master configuration system for all game rules with sensible defaults. Includes: DeckConfig, BenchConfig, EnergyConfig, PrizeConfig, FirstTurnConfig, WinConditionsConfig, StatusConfig, TrainerConfig, EvolutionConfig, RetreatConfig",
|
|
"category": "critical",
|
|
"priority": 4,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["CRIT-002"],
|
|
"files": [
|
|
{"path": "app/core/config.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Create nested Pydantic BaseModel classes with Field defaults. Use Field(default_factory=...) for mutable defaults.",
|
|
"estimatedHours": 2,
|
|
"notes": "Defaults based on Mantimon TCG house rules (40-card deck, 20-card energy deck, 4 points to win). Includes standard_pokemon_tcg() class method for official rules preset. PrizeConfig uses PokemonVariant for knockout points.",
|
|
"completedDate": "2026-01-24"
|
|
},
|
|
{
|
|
"id": "TEST-002",
|
|
"name": "Create RulesConfig tests",
|
|
"description": "Test that RulesConfig has sensible defaults, custom values override correctly, and serialization round-trips work",
|
|
"category": "high",
|
|
"priority": 5,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["CRIT-003"],
|
|
"files": [
|
|
{"path": "tests/core/test_config.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Test: default instantiation, partial overrides, full JSON round-trip, validation of invalid values",
|
|
"estimatedHours": 1,
|
|
"notes": "31 tests covering all config classes, defaults, customization, and JSON serialization",
|
|
"completedDate": "2026-01-24"
|
|
},
|
|
{
|
|
"id": "CRIT-004",
|
|
"name": "Create RandomProvider module",
|
|
"description": "Implement the RandomProvider protocol with SeededRandom (for testing/replays) and SecureRandom (for production PvP) implementations",
|
|
"category": "critical",
|
|
"priority": 6,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["CRIT-001"],
|
|
"files": [
|
|
{"path": "app/core/rng.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Create Protocol class with random(), randint(), choice(), shuffle() methods. Implement SeededRandom using random.Random with seed, SecureRandom using secrets module.",
|
|
"estimatedHours": 1.5,
|
|
"notes": "Includes coin_flip() and sample() methods. create_rng() factory function for easy instantiation.",
|
|
"completedDate": "2026-01-24"
|
|
},
|
|
{
|
|
"id": "TEST-003",
|
|
"name": "Create RandomProvider tests",
|
|
"description": "Test that SeededRandom produces deterministic results and SecureRandom produces varied results",
|
|
"category": "high",
|
|
"priority": 7,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["CRIT-004"],
|
|
"files": [
|
|
{"path": "tests/core/test_rng.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Test: SeededRandom with same seed produces identical sequences, SecureRandom produces different values across calls (statistical test)",
|
|
"estimatedHours": 1,
|
|
"notes": "42 tests including protocol compliance, game use cases (deck shuffle, coin flip, prize selection)",
|
|
"completedDate": "2026-01-24"
|
|
},
|
|
{
|
|
"id": "HIGH-001",
|
|
"name": "Create CardDefinition and CardInstance models",
|
|
"description": "Define the card template (CardDefinition) and in-game card state (CardInstance) models. Includes Attack, Ability, WeaknessResistance sub-models.",
|
|
"category": "high",
|
|
"priority": 8,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["CRIT-002"],
|
|
"files": [
|
|
{"path": "app/core/models/card.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "CardDefinition: immutable template with id, name, card_type, stage, variant, hp, attacks, abilities, weakness, resistance, retreat_cost. CardInstance: mutable state with instance_id, definition_id, damage, attached_energy, status_conditions, turn_played.",
|
|
"estimatedHours": 2,
|
|
"notes": "CardDefinition has separate stage (evolution) and variant (knockout points) fields. Includes helper methods: is_basic_pokemon(), is_evolution(), requires_evolution_from_variant(), knockout_points(). CardInstance has status condition management with override rules. Added stat modifiers: hp_modifier, retreat_cost_modifier, damage_modifier, attack_cost_overrides for effect support. Ability.uses_per_turn (int|None) replaces once_per_turn boolean for configurable limits.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "TEST-004",
|
|
"name": "Create card model tests",
|
|
"description": "Test CardDefinition and CardInstance creation, validation, and serialization",
|
|
"category": "high",
|
|
"priority": 9,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-001"],
|
|
"files": [
|
|
{"path": "tests/core/test_models/test_card.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Test: Pokemon card creation with attacks, Trainer card creation, Energy card creation, CardInstance damage tracking, energy attachment, status conditions",
|
|
"estimatedHours": 1.5,
|
|
"notes": "77 tests covering all card types, stage/variant combinations (Basic EX, Stage 2 GX, etc.), status condition override rules, evolution timing, energy attachment/detachment, stat modifiers (HP, retreat cost, damage), attack cost overrides, ability usage limits (once/multiple/unlimited per turn).",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "HIGH-002",
|
|
"name": "Create Action union types",
|
|
"description": "Define all player action types as Pydantic models with Literal type discriminators: PlayPokemonAction, EvolvePokemonAction, AttachEnergyAction, PlayTrainerAction, UseAbilityAction, AttackAction, RetreatAction, PassAction, SelectPrizeAction, SelectActiveAction, ResignAction",
|
|
"category": "high",
|
|
"priority": 10,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["CRIT-002"],
|
|
"files": [
|
|
{"path": "app/core/models/actions.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Each action model has a 'type' field with Literal value for discrimination. Create Action = Union[...] type alias for all actions.",
|
|
"estimatedHours": 1.5,
|
|
"notes": "11 action types implemented. Includes parse_action() for JSON deserialization and VALID_PHASES_FOR_ACTION mapping for phase validation.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "TEST-005",
|
|
"name": "Create action model tests",
|
|
"description": "Test that action union types discriminate correctly and serialize/deserialize properly",
|
|
"category": "high",
|
|
"priority": 11,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-002"],
|
|
"files": [
|
|
{"path": "tests/core/test_models/test_actions.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Test: each action type creates correctly, JSON round-trip works, discriminated union parses correct type",
|
|
"estimatedHours": 1,
|
|
"notes": "48 tests covering all 11 action types, parse_action discrimination, error handling, valid phases for each action type",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "HIGH-003",
|
|
"name": "Create GameState, PlayerState, and Zone models",
|
|
"description": "Define the complete game state model hierarchy: Zone (card collection with operations), PlayerState (all player zones and turn state), GameState (full game including card_registry, rules, players, turn tracking)",
|
|
"category": "high",
|
|
"priority": 12,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["CRIT-003", "HIGH-001"],
|
|
"files": [
|
|
{"path": "app/core/models/game_state.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Zone: list of CardInstance with add/remove/shuffle/draw methods. PlayerState: deck, hand, active, bench, prizes, discard zones plus turn state flags. GameState: game_id, rules, card_registry, players dict, turn tracking, winner.",
|
|
"estimatedHours": 3,
|
|
"notes": "GameState.card_registry holds all CardDefinitions used in this game. Zone operations need RandomProvider for shuffle. PlayerState uses integer counters (not booleans) for per-turn actions to support configurable RulesConfig limits.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "TEST-006",
|
|
"name": "Create game state model tests",
|
|
"description": "Test Zone operations, PlayerState initialization and turn resets, GameState properties and player access",
|
|
"category": "high",
|
|
"priority": 13,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-003"],
|
|
"files": [
|
|
{"path": "tests/core/test_models/test_game_state.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Test: Zone add/remove/shuffle/draw, PlayerState turn state resets, GameState current_player property, GameState is_first_turn logic",
|
|
"estimatedHours": 2,
|
|
"notes": "62 tests covering Zone operations, PlayerState counters with configurable rules (energy, supporters, items, stadiums, retreats), and GameState turn management. Uses SeededRandom for deterministic shuffle tests.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "HIGH-004",
|
|
"name": "Create test fixtures (conftest.py)",
|
|
"description": "Create shared pytest fixtures for sample cards, game states, and seeded RNG instances",
|
|
"category": "high",
|
|
"priority": 14,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-001", "HIGH-003", "CRIT-004"],
|
|
"files": [
|
|
{"path": "tests/core/conftest.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Create fixtures: sample_pokemon_card, sample_trainer_card, sample_energy_card, sample_deck, empty_game_state, mid_game_state, seeded_rng",
|
|
"estimatedHours": 1.5,
|
|
"notes": "Fixtures include sample cards (Pikachu, Raichu, Charmander), factory functions for CardInstance/GameState creation, and SeededRandom fixtures for deterministic tests.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "MED-001",
|
|
"name": "Create EffectContext and base types",
|
|
"description": "Define the context object passed to effect handlers and the EffectResult return type",
|
|
"category": "medium",
|
|
"priority": 15,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-003"],
|
|
"files": [
|
|
{"path": "app/core/effects/base.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "EffectContext: game state, source player/card, target player/card, params dict, rng provider. EffectResult: success bool, message, state changes list for logging.",
|
|
"estimatedHours": 1,
|
|
"notes": "EffectContext provides helper methods for player/card access, parameter parsing, coin flips, and rules access. EffectResult includes success, message, effect_type, and details. EffectType enum categorizes effects (damage, heal, draw, etc.). 30 tests in test_base.py.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "MED-002",
|
|
"name": "Create effect handler registry",
|
|
"description": "Implement the effect handler registry with decorator for registering handlers and lookup function for resolving effects",
|
|
"category": "medium",
|
|
"priority": 16,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["MED-001"],
|
|
"files": [
|
|
{"path": "app/core/effects/registry.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Global EFFECT_REGISTRY dict. @effect_handler(name) decorator adds function to registry. resolve_effect(effect_id, context) looks up and calls handler.",
|
|
"estimatedHours": 1,
|
|
"notes": "@effect_handler decorator with validation for handler signatures. resolve_effect() handles sync/async handlers. list_effects() and get_effect_info() for introspection. 21 tests in test_registry.py.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "TEST-007",
|
|
"name": "Create effect registry tests",
|
|
"description": "Test that effect handlers register correctly and resolve_effect calls the right handler",
|
|
"category": "medium",
|
|
"priority": 17,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["MED-002"],
|
|
"files": [
|
|
{"path": "tests/core/test_effects/test_registry.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Test: decorator registers handler, resolve_effect calls correct handler, unknown effect_id handled gracefully",
|
|
"estimatedHours": 1,
|
|
"notes": "21 tests covering registration, resolution, async handlers, error handling, introspection APIs.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "MED-003",
|
|
"name": "Create built-in effect handlers",
|
|
"description": "Implement common effect handlers: deal_damage, heal, draw_cards, discard_cards, apply_status, remove_status, coin_flip, discard_energy, search_deck",
|
|
"category": "medium",
|
|
"priority": 18,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["MED-002"],
|
|
"files": [
|
|
{"path": "app/core/effects/handlers.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Each handler is an async function decorated with @effect_handler. Use context.params for effect-specific parameters. Return EffectResult with success/failure.",
|
|
"estimatedHours": 3,
|
|
"notes": "12 built-in handlers: deal_damage, heal, draw_cards, discard_from_hand, apply_status, remove_status, coin_flip_damage, discard_energy, modify_hp, modify_retreat_cost, shuffle_deck, bench_damage. All handlers use context.rng for testability.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "TEST-008",
|
|
"name": "Create effect handler tests",
|
|
"description": "Test each built-in effect handler with various scenarios",
|
|
"category": "medium",
|
|
"priority": 19,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["MED-003", "HIGH-004"],
|
|
"files": [
|
|
{"path": "tests/core/test_effects/test_handlers.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Test: deal_damage reduces HP, heal restores HP up to max, draw_cards moves from deck to hand, apply_status adds condition, coin_flip with seeded RNG",
|
|
"estimatedHours": 2,
|
|
"notes": "33 tests covering all 12 handlers with various scenarios including edge cases. Uses SeededRandom for deterministic coin flip tests.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "HIGH-005",
|
|
"name": "Create rules validator",
|
|
"description": "Implement config-driven action validation: check turn, phase, card ownership, action legality based on RulesConfig",
|
|
"category": "high",
|
|
"priority": 20,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-002", "HIGH-003", "CRIT-003"],
|
|
"files": [
|
|
{"path": "app/core/rules_validator.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "ValidationResult model with valid bool and reason string. validate_action(game, player_id, action) checks: is it player's turn, is phase correct, does player have the card, is action legal per rules. Separate validator functions per action type.",
|
|
"estimatedHours": 4,
|
|
"notes": "Validates all 11 action types. Includes energy cost matching, forced action handling, first-turn restrictions, per-turn limits. Also added ForcedAction model to GameState, starting_hand_size to DeckConfig, renamed from_energy_deck to from_energy_zone.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "TEST-009",
|
|
"name": "Create rules validator tests",
|
|
"description": "Test action validation for each action type with valid and invalid scenarios",
|
|
"category": "high",
|
|
"priority": 21,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-005", "HIGH-004"],
|
|
"files": [
|
|
{"path": "tests/core/test_rules_validator.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Test per action type: valid action passes, wrong turn fails, wrong phase fails, card not owned fails, rule limit exceeded fails. Test with custom RulesConfig to verify config-driven behavior.",
|
|
"estimatedHours": 3,
|
|
"notes": "95 tests covering universal validation, forced actions, and all 11 action types. Includes tests for energy cost matching, status condition blocking, evolution timing, trainer subtype limits, and first-turn restrictions.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "HIGH-006",
|
|
"name": "Create win conditions checker",
|
|
"description": "Implement config-driven win condition checking: all prizes taken, no Pokemon in play, cannot draw",
|
|
"category": "high",
|
|
"priority": 22,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-003", "CRIT-003"],
|
|
"files": [
|
|
{"path": "app/core/win_conditions.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "WinResult model with winner player_id and reason string. check_win_conditions(game) checks each enabled condition from rules config and returns WinResult if any are met.",
|
|
"estimatedHours": 1.5,
|
|
"notes": "Includes check_prizes_taken, check_no_pokemon_in_play, check_cannot_draw, check_turn_limit, check_resignation, check_timeout, and apply_win_result. Each condition independently enabled/disabled via RulesConfig.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "TEST-010",
|
|
"name": "Create win conditions tests",
|
|
"description": "Test each win condition triggers correctly and respects config flags",
|
|
"category": "high",
|
|
"priority": 23,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-006", "HIGH-004"],
|
|
"files": [
|
|
{"path": "tests/core/test_win_conditions.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Test: all prizes taken triggers win, last Pokemon knocked out triggers win, empty deck triggers win, disabled conditions don't trigger, custom prize count works",
|
|
"estimatedHours": 1.5,
|
|
"notes": "53 tests covering WinResult model, all win condition types, turn limit with draws, resignation/timeout helpers, edge cases, and config-driven enable/disable of conditions.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "HIGH-007",
|
|
"name": "Create turn manager",
|
|
"description": "Implement the turn/phase state machine with valid transitions and turn start/end handling",
|
|
"category": "high",
|
|
"priority": 24,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-003", "CRIT-002"],
|
|
"files": [
|
|
{"path": "app/core/turn_manager.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "TurnManager class with advance_phase(), end_turn(), start_turn() methods. Enforce valid transitions (DRAW->MAIN->ATTACK->END). Handle between-turn effects (poison/burn damage). Reset per-turn flags on turn start.",
|
|
"estimatedHours": 2.5,
|
|
"notes": "TurnManager implements full phase state machine, between-turn status effects (poison/burn damage, sleep/burn recovery flips, paralysis removal), turn start processing (draw, energy flip, counter resets), and knockout processing with win condition integration.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "TEST-011",
|
|
"name": "Create turn manager tests",
|
|
"description": "Test phase transitions, turn switching, and per-turn state resets",
|
|
"category": "high",
|
|
"priority": 25,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-007", "HIGH-004"],
|
|
"files": [
|
|
{"path": "tests/core/test_turn_manager.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Test: valid transitions work, invalid transitions rejected, turn switch alternates players, per-turn flags reset, between-turn effects applied",
|
|
"estimatedHours": 2,
|
|
"notes": "60 tests covering phase transitions, turn start/end, between-turn effects (poison, burn, sleep, paralysis), knockout processing, and turn limit checking. Uses SeededRandom for deterministic coin flip tests.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "HIGH-008",
|
|
"name": "Create visibility filter",
|
|
"description": "Implement hidden information filtering to create client-safe game state views",
|
|
"category": "high",
|
|
"priority": 26,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-003"],
|
|
"files": [
|
|
{"path": "app/core/visibility.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "VisibleGameState model with filtered data. get_visible_state(game, player_id) returns: full own hand, own prize count, opponent hand COUNT only, opponent deck COUNT only, public battlefield/discard. Never expose deck order or opponent hand contents.",
|
|
"estimatedHours": 2,
|
|
"notes": "VisibleGameState, VisiblePlayerState, VisibleZone models. get_visible_state() filters for player view, get_spectator_state() for spectators. Hidden: hand contents, deck order/contents, prize contents, energy deck order. Public: battlefield, discard, energy zone, scores, stadium.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "TEST-012",
|
|
"name": "Create visibility filter tests",
|
|
"description": "Test that hidden information is never leaked and public information is preserved",
|
|
"category": "high",
|
|
"priority": 27,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-008", "HIGH-004"],
|
|
"files": [
|
|
{"path": "tests/core/test_visibility.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Test: opponent hand contents not visible, opponent deck order not visible, own hand fully visible, battlefield fully visible, prize counts visible but not contents",
|
|
"estimatedHours": 1.5,
|
|
"notes": "44 security-critical tests covering own info visibility, opponent info hiding, public info, spectator mode, edge cases, and JSON serialization. Tests verify card IDs don't leak in serialized output.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "HIGH-009",
|
|
"name": "Create main GameEngine orchestrator",
|
|
"description": "Implement the main GameEngine class that orchestrates all components: game creation, action validation, action execution, win condition checking",
|
|
"category": "high",
|
|
"priority": 28,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-005", "HIGH-006", "HIGH-007", "HIGH-008", "MED-002"],
|
|
"files": [
|
|
{"path": "app/core/engine.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "GameEngine class with: __init__(rules, rng_provider), create_game(player_ids, decks, card_registry), validate_action(game, player_id, action), execute_action(game, player_id, action), check_win_conditions(game), get_visible_state(game, player_id). All methods async.",
|
|
"estimatedHours": 4,
|
|
"notes": "Main public API. create_game() validates decks, shuffles, deals hands. execute_action() validates and executes all 11 action types. Integrates turn_manager, rules_validator, win_conditions, and visibility filter.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "TEST-013",
|
|
"name": "Create GameEngine integration tests",
|
|
"description": "Test full game flow from creation through actions to win condition",
|
|
"category": "high",
|
|
"priority": 29,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-009", "HIGH-004"],
|
|
"files": [
|
|
{"path": "tests/core/test_engine.py", "status": "created"}
|
|
],
|
|
"suggestedFix": "Test: create game with two players, execute valid actions, reject invalid actions, detect win condition, full sample game playthrough",
|
|
"estimatedHours": 3,
|
|
"notes": "22 integration tests covering game creation, deck validation, turn management, action execution (retreat, attach energy, attack, pass, resign), visibility filtering, timeout handling, and error cases.",
|
|
"completedDate": "2026-01-25"
|
|
},
|
|
{
|
|
"id": "MED-004",
|
|
"name": "Create core module exports",
|
|
"description": "Set up clean public API exports in __init__.py files",
|
|
"category": "medium",
|
|
"priority": 30,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-009"],
|
|
"files": [
|
|
{"path": "app/core/__init__.py", "status": "updated"},
|
|
{"path": "app/core/models/__init__.py", "status": "updated"},
|
|
{"path": "app/core/effects/__init__.py", "status": "updated"}
|
|
],
|
|
"suggestedFix": "Export key classes: GameEngine, RulesConfig, GameState, CardDefinition, CardInstance, Action types, effect_handler decorator",
|
|
"estimatedHours": 0.5,
|
|
"notes": "Clean API surface for consumers of the core module. Exports: 34 items from core, 29 from models, 12 from effects. 14 effect handlers auto-registered.",
|
|
"completedDate": "2026-01-26"
|
|
},
|
|
{
|
|
"id": "DOCS-001",
|
|
"name": "Create core module AGENTS.md",
|
|
"description": "Document the game engine architecture, patterns, and usage guidelines for AI agents",
|
|
"category": "low",
|
|
"priority": 31,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-009"],
|
|
"files": [
|
|
{"path": "app/core/AGENTS.md", "status": "created"}
|
|
],
|
|
"suggestedFix": "Document: module structure, key classes, effect handler pattern, configuration system, testing approach, security considerations (hidden info)",
|
|
"estimatedHours": 1,
|
|
"notes": "Comprehensive documentation covering architecture, import patterns, core patterns (game creation, action execution, effects, config, visibility), key classes, testing patterns, security rules, module independence, and quick commands.",
|
|
"completedDate": "2026-01-26"
|
|
},
|
|
{
|
|
"id": "LOW-001",
|
|
"name": "Add comprehensive docstrings",
|
|
"description": "Ensure all public classes and methods have detailed docstrings with examples",
|
|
"category": "low",
|
|
"priority": 32,
|
|
"completed": true,
|
|
"tested": true,
|
|
"dependencies": ["HIGH-009"],
|
|
"files": [
|
|
{"path": "app/core/enums.py", "status": "verified"},
|
|
{"path": "app/core/config.py", "status": "verified"},
|
|
{"path": "app/core/rng.py", "status": "verified"},
|
|
{"path": "app/core/models/card.py", "status": "verified"},
|
|
{"path": "app/core/models/actions.py", "status": "verified"},
|
|
{"path": "app/core/models/game_state.py", "status": "verified"},
|
|
{"path": "app/core/effects/base.py", "status": "verified"},
|
|
{"path": "app/core/effects/registry.py", "status": "verified"},
|
|
{"path": "app/core/effects/handlers.py", "status": "verified"},
|
|
{"path": "app/core/rules_validator.py", "status": "verified"},
|
|
{"path": "app/core/turn_manager.py", "status": "verified"},
|
|
{"path": "app/core/win_conditions.py", "status": "verified"},
|
|
{"path": "app/core/visibility.py", "status": "verified"},
|
|
{"path": "app/core/engine.py", "status": "verified"}
|
|
],
|
|
"suggestedFix": "Add Google-style docstrings with Args, Returns, Raises, and Example sections",
|
|
"estimatedHours": 2,
|
|
"notes": "Audit complete: All 14 core module files already have comprehensive Google-style docstrings with module docstrings, class docstrings (with Attributes), method/function docstrings (with Args, Returns, Raises, Examples). No additional documentation needed.",
|
|
"completedDate": "2026-01-26"
|
|
}
|
|
],
|
|
"quickWins": [
|
|
{
|
|
"taskId": "CRIT-001",
|
|
"estimatedMinutes": 30,
|
|
"impact": "Unblocks all other development"
|
|
},
|
|
{
|
|
"taskId": "CRIT-002",
|
|
"estimatedMinutes": 60,
|
|
"impact": "Foundation for all models"
|
|
},
|
|
{
|
|
"taskId": "MED-004",
|
|
"estimatedMinutes": 30,
|
|
"impact": "Clean public API"
|
|
}
|
|
],
|
|
"productionBlockers": [
|
|
{
|
|
"taskId": "HIGH-005",
|
|
"reason": "Cannot trust client actions without server-side validation"
|
|
},
|
|
{
|
|
"taskId": "HIGH-008",
|
|
"reason": "Hidden information must never leak to clients"
|
|
},
|
|
{
|
|
"taskId": "HIGH-009",
|
|
"reason": "No gameplay possible without engine orchestrator"
|
|
}
|
|
],
|
|
"weeklyRoadmap": {
|
|
"week1": {
|
|
"theme": "Foundation & Models",
|
|
"tasks": ["CRIT-001", "CRIT-002", "TEST-001", "CRIT-003", "TEST-002", "CRIT-004", "TEST-003"],
|
|
"estimatedHours": 8,
|
|
"goals": ["Module structure complete", "Enums, config, and RNG working with tests"],
|
|
"status": "COMPLETED",
|
|
"completedDate": "2026-01-24"
|
|
},
|
|
"week2": {
|
|
"theme": "Core Models",
|
|
"tasks": ["HIGH-001", "TEST-004", "HIGH-002", "TEST-005", "HIGH-003", "TEST-006", "HIGH-004"],
|
|
"estimatedHours": 12,
|
|
"goals": ["All data models complete", "Test fixtures established"],
|
|
"status": "COMPLETED",
|
|
"completedDate": "2026-01-25",
|
|
"progress": "All 7 tasks complete. CardInstance includes stat modifiers (hp_modifier, retreat_cost_modifier, damage_modifier, attack_cost_overrides) for effect support. PlayerState uses integer counters for configurable per-turn action limits. 289 tests passing."
|
|
},
|
|
"week3": {
|
|
"theme": "Effects System",
|
|
"tasks": ["MED-001", "MED-002", "TEST-007", "MED-003", "TEST-008"],
|
|
"estimatedHours": 8,
|
|
"goals": ["Effect handler system working", "Built-in effects implemented"],
|
|
"status": "COMPLETED",
|
|
"completedDate": "2026-01-25",
|
|
"progress": "All 5 tasks complete. EffectContext/EffectResult base types, @effect_handler decorator registry with resolve_effect(), and 12 built-in handlers (deal_damage, heal, draw_cards, discard_from_hand, apply_status, remove_status, coin_flip_damage, discard_energy, modify_hp, modify_retreat_cost, shuffle_deck, bench_damage). 84 tests in test_effects/ directory."
|
|
},
|
|
"week4": {
|
|
"theme": "Game Logic",
|
|
"tasks": ["HIGH-005", "TEST-009", "HIGH-006", "TEST-010", "HIGH-007", "TEST-011"],
|
|
"estimatedHours": 14,
|
|
"goals": ["Validation working", "Win conditions working", "Turn management working"],
|
|
"status": "COMPLETED",
|
|
"completedDate": "2026-01-25",
|
|
"progress": "All 6 tasks complete. Rules validator validates all 11 action types. Win conditions checker handles points/prizes, knockouts, deck-out, turn limits. Turn manager implements phase state machine, between-turn effects (poison/burn/sleep/paralysis), and knockout processing. 644 total core tests passing at 97% coverage."
|
|
},
|
|
"week5": {
|
|
"theme": "Engine & Polish",
|
|
"tasks": ["HIGH-008", "TEST-012", "HIGH-009", "TEST-013", "MED-004", "DOCS-001", "LOW-001"],
|
|
"estimatedHours": 14,
|
|
"goals": ["GameEngine complete", "Full integration tested", "Documentation complete"],
|
|
"status": "COMPLETED",
|
|
"completedDate": "2026-01-26",
|
|
"progress": "All 7 tasks complete. Docstring audit revealed all 14 core module files already have comprehensive Google-style documentation - module docstrings, class docstrings with Attributes, method/function docstrings with Args/Returns/Raises. 826 tests passing at 97% coverage. Core game engine scaffolding complete!"
|
|
}
|
|
},
|
|
"testingStrategy": {
|
|
"unitTests": "Each module has corresponding test file",
|
|
"integrationTests": "test_engine.py covers full game flow",
|
|
"fixtures": "conftest.py provides reusable sample data",
|
|
"determinism": "SeededRandom enables reproducible random tests",
|
|
"coverage": "Target 90%+ coverage on core module (currently at 97%)"
|
|
},
|
|
"securityChecklist": [
|
|
{
|
|
"item": "Deck order never sent to client",
|
|
"module": "visibility.py",
|
|
"verified": true,
|
|
"verifiedDate": "2026-01-25",
|
|
"notes": "test_own_deck_contents_also_hidden and test_opponent_deck_cards_not_leaked verify deck cards never appear in visible state JSON."
|
|
},
|
|
{
|
|
"item": "Opponent hand contents never sent",
|
|
"module": "visibility.py",
|
|
"verified": true,
|
|
"verifiedDate": "2026-01-25",
|
|
"notes": "test_opponent_hand_contents_hidden and test_opponent_hand_card_ids_not_leaked verify hand contents are empty for opponent and card IDs don't appear in JSON."
|
|
},
|
|
{
|
|
"item": "Prize card contents hidden until taken",
|
|
"module": "visibility.py",
|
|
"verified": true,
|
|
"verifiedDate": "2026-01-25",
|
|
"notes": "test_opponent_prizes_hidden, test_opponent_prize_cards_not_leaked, test_own_prize_contents_hidden verify prize cards hidden for both players."
|
|
},
|
|
{
|
|
"item": "All actions validated server-side",
|
|
"module": "rules_validator.py",
|
|
"verified": true,
|
|
"verifiedDate": "2026-01-25",
|
|
"notes": "95 tests verify validation of all 11 action types including turn ownership, phase validity, card ownership, per-turn limits, status conditions, and first-turn restrictions."
|
|
},
|
|
{
|
|
"item": "RNG unpredictable in production",
|
|
"module": "rng.py",
|
|
"verified": false
|
|
}
|
|
]
|
|
}
|