# 14. Risk Register and Open Questions

[< Back to Index](README.md)

---

## Risk Register

| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Milestone queries become slow at scale | Low | Medium | Queries go through `player_season_stats` materialized view keyed on `(team_id, player_id)`, not raw stratplay scans. Ensure appropriate indexes on the materialized view. |
| Milestone thresholds too easy, Full Evolution trivial | Medium | Medium | Admin-tunable thresholds; monitor completion rate and adjust; launch conservatively |
| Milestone thresholds too hard, players don't notice evolution is happening | Medium | Medium | Lower thresholds; T1 should complete for any card played in ~2 weeks of casual play |
| Retroactive backfill gives some cards immediate T4 on launch | Low | Medium | Evaluate whether progress_since should be launch date rather than card.created_at; see Open Question 2 |
| Cosmetic pricing too low, not a meaningful sink | Low | Low | Monitor purchase rates; adjust cosmetic catalog pricing post-launch |
| Cosmetic pricing too high, nobody buys them | Medium | Medium | Start at lower price points; increase for new cosmetics based on demand data |
| Rating boosts break 108-sum column invariant | Low | High | Unit test suite for `apply_evolution_boosts()`; validation on every boost application |
| Variant rows conflict with existing `UNIQUE(player_id, variant)` constraint | Low | High | Validate constraint behavior in dev before migration; existing data has variant=0 only |
| API variant resolution adds latency to card embed | Low | Low | Single additional DB lookup; index on card_state by card_id |
| Trade cosmetic-stripping creates player frustration | Low | Low | Clear in-game warning before trade completes; cosmetics are team purchases, not card upgrades |
| Player collusion to farm milestones via exhibition | Low | Low | Future safeguard: mode restrictions via game_mode field; low priority since exhibition outcomes are real D20 games |
| APNG file sizes too large for mobile Discord clients | Medium | Medium | pngquant compression, frame count reduction, file size budget enforcement (see [08-display.md § 8.6.8](08-display.md#868-file-size-budget)) |
| Animated render pipeline too slow for batch operations | Low | Low | Animated variants are rare (premium purchases only); batch re-renders can run in background |
| APNG not supported on older Discord mobile clients | Low | Low | Graceful degradation: first frame renders as static PNG; bot can check URL extension to warn user |

---

## Open Questions

1. **Progress start date — all-time vs acquisition date vs launch date:** Currently specified as
   `card.created_at`. Three options exist: (a) all-time for that player_id on that team (most
   rewarding, may cause immediate tier completions on launch), (b) card acquisition date (natural,
   but retroactive depth varies by card age), (c) system launch date (clean cold start, no
   retroactive credit). Which is preferred for the launch experience?

2. **Immediate Full Evolution on backfill:** Some veteran players may have cards where enough
   historical games exist to hit T4 immediately on launch day. Is this a good thing (reward
   loyal players) or a bad thing (deflates the progression experience)? One mitigation: cap
   retroactive credit at T2 on launch, let players play their way to T3-T4.

3. ~~**Boost allocation player choice (Phase 4):**~~ **RESOLVED — CUT.** Boost direction override
   was removed entirely. Auto-detected profile determines distribution; no player customization.
   Cosmetics are the sole currency sink.

4. **Maximum evolved card count visibility:** With all cards evolving simultaneously, the
   `!evo status` embed could become overwhelming for large rosters. Should it default to showing
   only cards close to a tier milestone (within 20% of threshold)? Or only T3+ cards?

5. **Season-specific evolution tracks:** Time-limited evolution tracks tied to current season
   events are a strong engagement feature. Should these be a separate PRD, or designed into
   the track schema from the start?

6. ~~**HoF cards on Legend track:**~~ **RESOLVED in v4.0.** Tracks are now universal (not
   rarity-gated). HoF cards follow the same track as all other cards, receive the same flat rating
   boosts, and get the full visual rework at T4. They do not receive a rarity upgrade (already
   at ceiling). The flat delta naturally provides diminishing returns for elite cards.

7. **Quality start definition:** The D20 system does not natively track innings pitched per
   appearance. "6+ innings, 3 or fewer ER" requires a proxy calculation based on the outcome
   simulation. How is this currently exposed from the game engine, if at all? If not available,
   this milestone type may need to be replaced with a simpler proxy (e.g., "pitcher records a win
   with fewer than N walks allowed").

8. **Cosmetic catalog scope:** The cosmetics listed in [08-display.md](08-display.md) are
   illustrative. Should cosmetics be designed in detail before Phase 3 begins, or is it
   acceptable to ship with one or two cosmetics and expand the catalog over time?

9. **Cosmetic CSS implementation detail:** The card HTML template currently uses hardcoded inline
   styles for backgrounds (`#ACE6FF`, `#EAA49C`) and gradients (`blue-gradient`, `red-gradient`).
   Cosmetics need to override these. Options: (a) pass cosmetic flags as Jinja2 template variables
   and use conditionals in the template, (b) inject a cosmetic CSS override block after `style.html`,
   (c) build a cosmetic theme system with named CSS classes. Which approach best balances flexibility
   with maintainability?

10. ~~**Variant hash collision handling:**~~ **RESOLVED.** The `UNIQUE(player_id, variant)`
    constraint catches collisions at the DB level. No application-level check needed. With 32-bit
    hashes (~4 billion values) and realistic catalog sizes, collision probability is negligible.

11. ~~**APNG render determinism:**~~ **RESOLVED in v4.0.** The render pipeline uses the
    `--anim-progress` CSS custom property for deterministic per-frame control. CSS `@keyframes`
    are not used for animated cosmetics. See [08-display.md § 8.6.4](08-display.md#864-deterministic-frame-control).

---

*End of PRD: Card Evolution System v4.1*
*Status: Full review with Cal complete (2026-03-11). Next step: Confirm Phase 1 scope, create Gitea milestone and issue breakdown.*
