claude-home/paper-dynasty/card-evolution-prd/13-implementation.md
Cal Corum aafe527d51
All checks were successful
Reindex Knowledge Base / reindex (push) Successful in 5s
docs: add Major Domo and Paper Dynasty release notes and card evolution PRD
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 22:29:18 -05:00

17 KiB

13. Implementation Phases and Checklists

< Back to Index | Next: Risks and Open Questions >


Phase 0 — Render Pipeline Optimization (Week 0, Pre-Requisite)

Focus: Persistent browser, self-hosted fonts, concurrent upload pipeline. This phase is independent of evolution and benefits all existing card generation workflows immediately. Should be implemented before any evolution work begins.

Deliverables:

  • Persistent Chromium browser instance in API server (replaces per-request browser launch)
  • FastAPI lifespan hooks for browser startup/shutdown with auto-reconnect
  • Self-hosted fonts: download Source Sans 3 + Open Sans WOFF2 files, base64-embed in template
  • Remove Google Fonts CDN @import from style.html
  • Concurrent upload pipeline in pd_cards/core/upload.py using asyncio.Semaphore(8) + asyncio.gather
  • Increase fetch_card_image timeout from 6s to 10s to account for render queue contention
  • Benchmark: measure per-card render time before/after, total run time for full cardset

Implementation details: See 02-architecture.md § Card Render Pipeline Optimization

Success Criteria: Per-card render time drops from ~3s to ~0.6-1.0s. Full 800-card upload run completes in under 5 minutes (down from ~40 minutes). No external font CDN dependency.

Files changed:

File Change
database/app/routers_v2/players.py Persistent browser, page-per-request pattern
database/app/main.py FastAPI lifespan hooks
database/storage/templates/style.html @font-face with base64 WOFF2
database/storage/fonts/ Font files (new directory)
pd_cards/core/upload.py asyncio.gather with semaphore
check_cards_and_upload.py Same concurrency pattern (legacy script)

13.1 Phase 1 — Foundation (Weeks 1-3)

Focus: Database schema, lazy evaluation engine, tier badge display, basic Discord commands.

Deliverables:

  • player_season_stats materialized aggregate table created (reference Major Domo implementation)
  • Incremental update logic in post-game callback for player_season_stats
  • Backfill script to populate player_season_stats from existing stratplay/decision data
  • All evolution database tables created with migrations
  • evolution_card_state initialization on card acquisition (pack opening hook): create if no (player_id, team_id) state exists, otherwise inherit existing state
  • API endpoints: track catalog, card state GET, evaluate POST
  • Post-game callback integration: evaluate participating cards after each game
  • Milestone evaluation engine for all stratplay/decision/stratgame milestone types
  • Bot command: !evo status (roster-wide view and per-card view)
  • Basic Discord embed: tier badge on card name
  • No rating boosts yet — tier advances are tracked but boosts deferred to Phase 2
  • Three universal evolution tracks seeded in database (Batter, Starting Pitcher, Relief Pitcher)
  • Backfill job: initialize evolution_card_state for all unique (player_id, team_id) pairs with progress_since = earliest card.created_at

Success Criteria: All cards have evolution state. Players can see tier progress. Milestones complete automatically after games.

13.2 Phase 2 — Rating Boosts (Weeks 4-6)

Focus: Apply rating boosts on tier completion, variant card API.

Deliverables:

  • apply_evolution_boosts() function in card-creation repo
  • Batter and pitcher player profile detection from existing ratings
  • Tier boost application on tier completion: writes new variant rows to battingcardratings/pitchingcardratings
  • evolution_tier_boost audit table populated
  • Updated card API: card_id param for variant resolution
  • Discord notification on milestone and tier completion (with boost summary)
  • T4 rarity upgrade (universal, capped at HoF)
  • Evolved card display name ([Team]'s Evolved [Player])

Success Criteria: Tier completion triggers rating boost. Evolved cards show higher ratings in card embed.

13.3 Phase 3 — Static Cosmetics (Weeks 7-10)

Focus: Premium static cosmetics, visual differentiation, economy tuning.

Deliverables:

  • Cosmetics catalog seeded in database (static cosmetics only: frames, themes, badges)
  • Cosmetics purchase and display endpoints
  • Cosmetic CSS injection in card HTML template (frame overlays, background colors, badges)
  • Variant render pipeline: Playwright renders cards with cosmetic CSS, uploads to S3
  • battingcard.image_url column populated for variant rows
  • Bot image resolution updated: variant → battingcard.image_url fallback to player.image
  • Verify all three tracks work correctly across all rarity levels (Rep through HoF)
  • Discord embed accent colors per tier (T2 gold, T3 purple, T4 teal)
  • Analytics query for admin: evolution completion rates, milestone drop-off, cosmetic revenue
  • Economy review: check cosmetics pricing against actual currency circulation data

Success Criteria: Static cosmetics purchasable and visually distinct. Full T0-T4 evolution journey works end to end including cosmetics.

13.4 Phase 4 — Animated Cosmetics (Weeks 11-13)

Focus: APNG render pipeline, animated cosmetic effects.

Prerequisite: Phase 0 (persistent browser) must be complete. The APNG pipeline depends on the persistent browser for efficient multi-frame capture.

Deliverables:

  • Deterministic multi-frame capture using --anim-progress CSS custom property
  • capture_animated_frames() function using persistent browser page pool
  • APNG assembly from frame buffers using apng Python library (pip install apng)
  • CSS custom property-driven animations in card HTML template (no @keyframes for animated cosmetics)
  • Animated cosmetics added to catalog: Holographic Frame, Rarity Glow (Subtle/Strong), T4 Badge Sparkle
  • S3 upload with .apng extension and image/apng content type and CacheControl: public, max-age=31536000
  • File size validation (target <4 MB per animated card)
  • Bot display verified: APNG auto-plays in Discord embeds (desktop + mobile)
  • Performance benchmarking: target ~4.5s for 8-frame, ~6s for 12-frame animated variant
  • pngquant integration for frame compression if file sizes exceed budget

Success Criteria: Animated cosmetics render correctly as APNG, auto-play in Discord embeds, file sizes within budget, render time <8 seconds per animated variant.


13.5 Render Pipeline Optimization Checklist (Phase 0)

  • Download Source Sans 3 (400, 700) and Open Sans (300, 400, 700) WOFF2 files
  • Base64-encode font files and create @font-face declarations
  • Replace @import url('fonts.googleapis.com/...') in style.html with local @font-face — PR #96 (next-release)
  • Verify card renders identically with self-hosted fonts (visual diff)
  • Create get_browser() / shutdown_browser() functions in players.py — merged 2026.3.17
  • Add FastAPI lifespan hooks for browser startup/shutdown — merged 2026.3.17
  • Replace async with async_playwright() block with persistent browser + page-per-request — merged 2026.3.17
  • Add is_connected() check with automatic browser reconnect — implemented via asyncio.Lock, merged 2026.3.17
  • Test: render 10 cards sequentially, verify no browser leaks (page count stays at 0 between renders)
  • Test: concurrent renders (4 simultaneous requests) complete without errors
  • Benchmark: measure per-card render time (target: <1.0s, down from ~3.0s) — script in PR #95 (next-release)
  • Refactor pd_cards/core/upload.py loop to use asyncio.Semaphore(8) + asyncio.gather
  • Add error handling: individual card failures don't abort the batch
  • Add progress reporting: log every N completions (not every 20 starts)
  • Increase fetch_card_image timeout from 6s to 10s
  • Benchmark: full 800-card upload run (target: <5 minutes)
  • Update check_cards_and_upload.py legacy script with same concurrency pattern
  • Deploy to dev, run full cardset upload, verify all cards render correctly
  • Deploy to production — persistent browser deployed 2026.3.17

13.6 Database Checklist

  • Write Peewee model for evolution_track — pending PR #84 (card-evolution)
  • Write Peewee model for evolution_milestone — pending PR #84 (card-evolution)
  • Write Peewee model for evolution_card_state — pending PR #84 (card-evolution)
  • Write Peewee model for evolution_progress
  • Write Peewee model for evolution_tier_boost — stub schema in PR #84
  • Write Peewee model for evolution_cosmetic — stub schema in PR #84
  • Write migration scripts for all new tables (idempotent) — pending PR #84 (card-evolution)
  • Write Peewee model for player_season_stats — split into BattingSeasonStats + PitchingSeasonStats in app/models/season_stats.py, merged 2026.3.17
  • Implement incremental update in post-game callback (delta-based, not full recompute)
  • Add last_game_id check to prevent double-counting on callback retries
  • Write backfill script to populate from existing stratplay/decision rows
  • Verify backfill totals match on-demand GROUP BY queries for a sample of players
  • Reference Major Domo implementation for patterns and edge cases
  • Seed three universal evolution tracks (Batter, SP, RP) — seed data + JSON in app/seed/evolution_tracks.py, merged 2026.3.17; runnable once migration (PR #84) lands
  • Add image_url nullable column to battingcard and pitchingcard — in PR #84 migration
  • Add variant column to card table (integer, default 0) — in PR #84 migration
  • Verify battingcard.variant UNIQUE constraint behavior with hash-based integers
  • Index all FK columns and query-hot columns on new tables — indexes in PR #84 migration
  • Ensure player_season_stats has appropriate indexes for (team_id, player_id) lookups — indexes in PR #84 migration
  • Test schema in dev environment before production migration
  • Write and test backfill script: create evolution_card_state for each unique (player_id, team_id) pair, propagate variant to all matching card instances

13.7 Card Creation System Checklist

  • Implement apply_evolution_boosts(card_ratings_df, boost_tier, player_profile) in creation_helpers.py or batters/calcs_batter.py
  • Implement batter player profile detection (power, contact, patient) from existing ratings
  • Implement pitcher player profile detection (SP power, SP control, RP) from existing ratings
  • Write unit tests for boost distribution: verify column sums remain valid post-boost
  • Write unit tests for rating cap enforcement: verify boosts truncate at caps (e.g., hold at -5)
  • Write unit tests for cap truncation: verify excess budget is discarded (not redistributed) when a stat hits its cap
  • Write unit test for rarity upgrade eligibility check (HoF ceiling)
  • Integrate apply_evolution_boosts() with API endpoint trigger (or standalone script callable by API service)
  • Implement compute_variant_hash() function for deterministic variant numbering
  • Handle variant field correctly: check for existing variant row before creating new one
  • Implement cosmetic CSS injection in card HTML template (frames, backgrounds, badges)
  • Implement CSS --anim-progress custom property animations for animated cosmetics (holographic, glow pulse, sparkle)
  • Implement multi-frame Playwright capture for animated variants
  • Implement APNG assembly from frame buffers
  • Add file size validation for animated output
  • Add CLI command: pd-cards evolution apply-boost --card-id <id> --tier <n> for admin use
  • Add CLI command: pd-cards evolution render-variant --player-id <id> --variant <hash> for manual re-renders

13.8 API Development Checklist

  • Implement track catalog endpoints (GET list, GET single) — GET /api/v2/evolution/tracks and /tracks/{id} in app/routers_v2/evolution.py, merged 2026.3.17; returns 500 until PR #84 (EvolutionTrack model) lands
  • Implement track milestones endpoint (GET milestones for track)
  • Implement season stats CRUD — full REST endpoints in app/routers_v2/season_stats.py, merged 2026.3.17
  • Formula engine — app/services/formula_engine.py, batter OPS + pitcher ERA/WHIP/K formulas, merged 2026.3.17
  • Implement card state endpoints (GET by team, GET by card)
  • Implement POST evaluate endpoint — in PR #98 (card-evolution); POST /api/v2/evolution/cards/{card_id}/evaluate with evaluator service
  • Implement cosmetics endpoints (GET catalog, GET card cosmetics, POST purchase, DELETE deactivate)
  • Modify battingcard/pitchingcard endpoints to accept optional card_id param
  • Implement variant resolution logic in card endpoints using evolution_card_state
  • Implement admin endpoints for track/milestone management and manual boost application
  • Implement idempotent milestone evaluator (recalculate from source, not increment)
  • Render endpoint: detect animated vs static cosmetics, route to correct pipeline
  • Write API integration tests for full T0-T4 evolution lifecycle
  • Write API integration tests for cosmetics purchase flow (static + animated)
  • Document all new endpoints in API reference

13.9 Bot Integration Checklist

  • Add !evo status command with roster-wide formatted embed
  • Add !evo card <card_id> command for detailed single-card milestone breakdown
  • Add !evo cosmetics <card_id> command for premium cosmetics browsing
  • Integrate post-game evolution evaluator in post-game processing pipeline
  • Verify evaluator fires after game resolution in all modes (campaign, gauntlet, exhibition, unlimited)
  • Add milestone completion notification to team channel
  • Add tier completion notification with rating boost summary
  • Add Full Evolution notification with rarity upgrade announcement
  • Update card display embed to show tier badge from evolution_card_state.current_tier
  • Update card display embed to show evolved name for fully evolved cards
  • Update card display embed to apply active cosmetic styling
  • Verify APNG auto-plays correctly in Discord embeds across desktop and mobile
  • Update trade processing: set traded card's variant to 0, check for existing state on new team's (player_id, team_id), create fresh state if none exists

13.10 Testing Checklist

  • Unit tests: apply_evolution_boosts() for all player profiles and tiers
  • Unit tests: milestone evaluation logic for all challenge types
  • Unit tests: variant resolution in card endpoint
  • Unit tests: idempotent evaluator (calling twice yields same result)
  • Unit tests: APNG assembly produces valid APNG output
  • Integration tests: game -> post-game callback -> milestone completion -> tier boost full flow
  • Integration tests: T4 rarity upgrade across all rarity levels (Rep→Res, Sta→All, MVP→HoF, HoF stays HoF)
  • Integration tests: evolved card state and name update correctly after trade
  • Integration tests: cosmetics remain on selling team's (player_id, team_id) state after trade
  • Integration tests: animated cosmetic purchase triggers APNG render pipeline
  • Load test: milestone query latency against player_season_stats with large dataset
  • Regression test: base card ratings unaffected by evolution variant writes
  • Regression test: scouting report generation ignores variant rows
  • Visual test: animated APNG renders correctly in Discord (desktop + mobile)
  • Visual test: APNG graceful degradation (first frame displays if client doesn't support animation)

13.11 Security and Balance Checklist

  • Verify cosmetic purchase currency deducted atomically (wallet check + deduction in single transaction)
  • Verify card ownership validated before cosmetic purchase (card.team_id == requesting team_id)
  • Verify cosmetics are non-transferable on trade (team_id check in display layer)
  • Review milestone thresholds against expected games-per-week before launch
  • Verify rarity cap enforcement (no evolution beyond HoF)
  • Verify individual stat column caps enforced during boost application (e.g., hold ≥ -5)
  • Verify evolved card stats cannot exceed designed boost budget (4.0 chances/108 total) via any combination of track + boost

13.12 Deployment Checklist

  • Run schema migration in dev, verify all tables and indexes created correctly — blocked on PR #84
  • Seed evolution tracks and milestones in dev — seed script ready, blocked on schema
  • Run backfill job on dev copy of card inventory, verify all cards get state records
  • Run full Phase 1 test suite in dev environment
  • Deploy API changes to dev, smoke test all new endpoints — season stats + formula engine deployed to prod 2026.3.17; track catalog deployed but non-functional (missing model)
  • Deploy bot changes to dev instance, run a game to verify post-game evaluator fires
  • Demo full T0 -> T1 progression flow in dev
  • Cal approves dev demo
  • Run schema migration in production during low-traffic window
  • Run backfill job in production for existing card inventory
  • Deploy API changes to production
  • Deploy bot changes to production
  • Monitor milestone query latency for first 48 hours
  • Monitor tier completion rate and cosmetic purchase rate after first week
  • Schedule economy review at Day 30