fix: auto-initialize RefractorCardState in evaluate-game #178

Merged
cal merged 1 commits from fix/refractor-auto-init-missing-states into main 2026-03-31 06:25:42 +00:00
Owner

Summary

  • Cards created before the refractor system was deployed have no RefractorCardState row. Previously evaluate-game silently skipped these players.
  • Now calls initialize_card_refractor on-the-fly when a state is missing, so any card used in a game gets refractor tracking regardless of when it was created.
  • Critical for season rollover: existing cards in team lineups must support refractor from day one.

Changes

  • app/routers_v2/refractor.py: Replace if state is None: continue with auto-init via initialize_card_refractor (idempotent, failure-safe)
  • Top-level import of initialize_card_refractor and _determine_card_type from refractor_init
  • Updated docstring to reflect new behavior

Test plan

  • Deploy to dev, wipe refractor state for a team, trigger evaluate-game — states should be auto-created
  • Verify idempotency: re-run evaluate-game on same game, no errors or duplicates
  • Verify existing cards with states still evaluate normally (no regression)

🤖 Generated with Claude Code

## Summary - Cards created before the refractor system was deployed have no `RefractorCardState` row. Previously `evaluate-game` silently skipped these players. - Now calls `initialize_card_refractor` on-the-fly when a state is missing, so any card used in a game gets refractor tracking regardless of when it was created. - Critical for season rollover: existing cards in team lineups must support refractor from day one. ## Changes - `app/routers_v2/refractor.py`: Replace `if state is None: continue` with auto-init via `initialize_card_refractor` (idempotent, failure-safe) - Top-level import of `initialize_card_refractor` and `_determine_card_type` from `refractor_init` - Updated docstring to reflect new behavior ## Test plan - [ ] Deploy to dev, wipe refractor state for a team, trigger `evaluate-game` — states should be auto-created - [ ] Verify idempotency: re-run `evaluate-game` on same game, no errors or duplicates - [ ] Verify existing cards with states still evaluate normally (no regression) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
cal added 1 commit 2026-03-31 06:23:09 +00:00
Cards created before the refractor system was deployed have no
RefractorCardState row. Previously evaluate-game silently skipped these
players. Now it calls initialize_card_refractor on-the-fly so any card
used in a game gets refractor tracking regardless of when it was created.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
cal reviewed 2026-03-31 06:25:04 +00:00
cal left a comment
Author
Owner

AI Code Review

Files Reviewed

  • app/routers_v2/refractor.py (modified)
  • app/services/refractor_init.py (read for context — unchanged)

Findings

Correctness

  • The replacement of continue with an auto-init block is logically correct. When state is None, the code fetches the player, determines card type, and calls initialize_card_refractor — which is idempotent via get_or_create.
  • The inner if state is None: continue guard after the except block correctly handles the case where initialize_card_refractor returns None (missing track, DB error, etc.) — no NPE can proceed downstream.
  • Player.get_by_id failure is caught by the broad except Exception, leaving state = None, which then triggers continue. Correct.
  • Existing cards with states are unaffected — the new block is only entered when state is None.

Security

  • No new attack surface. Auth check is unchanged. No user input reaches the new code path.

Style & Conventions

  • Top-level import of initialize_card_refractor and _determine_card_type is correct — CLAUDE.md explicitly notes lazy imports should not be added to the middle of files. The _determine_card_type underscore prefix is intentional: refractor_init.py's module docstring explicitly lists it as exported for use by routers and tests.
  • Error handling pattern (broad except Exception + logger.warning) matches the existing style throughout evaluate_game.
  • Docstring updated accurately to reflect new behavior.

Suggestions

  • No blocking suggestions. A follow-up integration test covering the auto-init path would be a good addition but is not required to merge this fix.

Verdict: APPROVED

Clean, targeted fix. The implementation is correct, idempotent, failure-safe, and follows existing conventions. Critical for season rollover — any card that appears in a game will now get a refractor state initialized on-the-fly rather than being silently skipped.


Automated review by Claude PR Reviewer

## AI Code Review ### Files Reviewed - `app/routers_v2/refractor.py` (modified) - `app/services/refractor_init.py` (read for context — unchanged) ### Findings #### Correctness - The replacement of `continue` with an auto-init block is logically correct. When `state is None`, the code fetches the player, determines card type, and calls `initialize_card_refractor` — which is idempotent via `get_or_create`. - The inner `if state is None: continue` guard after the except block correctly handles the case where `initialize_card_refractor` returns `None` (missing track, DB error, etc.) — no NPE can proceed downstream. - `Player.get_by_id` failure is caught by the broad `except Exception`, leaving `state = None`, which then triggers `continue`. Correct. - Existing cards with states are unaffected — the new block is only entered when `state is None`. #### Security - No new attack surface. Auth check is unchanged. No user input reaches the new code path. #### Style & Conventions - Top-level import of `initialize_card_refractor` and `_determine_card_type` is correct — CLAUDE.md explicitly notes lazy imports should not be added to the middle of files. The `_determine_card_type` underscore prefix is intentional: `refractor_init.py`'s module docstring explicitly lists it as exported for use by routers and tests. - Error handling pattern (broad `except Exception` + `logger.warning`) matches the existing style throughout `evaluate_game`. - Docstring updated accurately to reflect new behavior. #### Suggestions - No blocking suggestions. A follow-up integration test covering the auto-init path would be a good addition but is not required to merge this fix. ### Verdict: APPROVED Clean, targeted fix. The implementation is correct, idempotent, failure-safe, and follows existing conventions. Critical for season rollover — any card that appears in a game will now get a refractor state initialized on-the-fly rather than being silently skipped. --- *Automated review by Claude PR Reviewer*
Claude approved these changes 2026-03-31 06:25:16 +00:00
Claude left a comment
Collaborator

Approved via pd-pr

Approved via pd-pr
cal merged commit ffe07ec54c into main 2026-03-31 06:25:42 +00:00
cal deleted branch fix/refractor-auto-init-missing-states 2026-03-31 06:25:42 +00:00
Sign in to join this conversation.
No description provided.