Review follow-up: the @app_commands.describe string still referenced
"batting or pitching card ID" after the switch to the unified cards
endpoint. Update to clarify that card_id is now a card-instance ID.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous two-step battingcards→pitchingcards fallback caused card
ID collisions — e.g. card 494 resolving to Cameron Maybin (batting)
instead of the intended pitcher Grayson Rodriguez. The unified cards
endpoint is keyed on globally-unique card instance IDs and carries
player, team, and variant in a single response.
- Single db_get("cards", object_id=card_id) lookup
- Card type derived from player.pos_1 (SP→sp, RP/CP→rp, else→batter)
- team_id sourced from card["team"]["id"] (no get_team_by_owner fallback)
- TestRefractorTestSetup rewritten for the single-endpoint contract
Spec: docs/superpowers/specs/2026-04-11-refractor-test-unified-cards-lookup-design.md
Remove unused `player_name` param from `_execute_refractor_test` and
unused `final` param from `update_embed` closure.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Closes#147
Adds a "Refractor Progress" field to the game summary embed showing:
- Cards that tiered up during this game (⬆ Name → Tier Name)
- Cards currently ≥80% toward their next tier on either team (◈ Name (pct%))
The field is omitted entirely when there is nothing to show.
Implementation:
- _run_post_game_refractor_hook() now returns evo_result (or None on failure)
- New _build_refractor_progress_text() fetches close-to-tier cards from both
teams via refractor/cards?progress=close and formats the combined output
- complete_game() adds the field between Rewards and Highlights sections
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#144
- build_tier_up_embed() accepts optional image_url and calls set_image() when provided
- notify_tier_completion() accepts optional image_url and passes it through
- _trigger_variant_renders() now captures the render response image_url per player and returns a player_id->image_url dict
- _run_post_game_refractor_hook() triggers renders first (to obtain image URLs), then sends notifications with card art included
- Updated test_post_game_refractor_hook.py to reflect new render-before-notify ordering and image_url kwarg in notify calls
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extract _run_post_game_refractor_hook() from complete_game() so the hook
logic can be tested directly without a live game session. Add 13 tests
covering endpoint ordering, tier-up notification dispatch, variant render
triggers, and non-fatal error handling.
Closes#148
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#98
Replace sequential await-in-list-comprehension with asyncio.gather() so
all card embed fetches run concurrently. Cuts 50 sequential DB round-trips
(5 packs × 5 cards × 2 calls each) down to ~2 concurrent batches.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#101
Replace sequential for-loop with asyncio.gather() so all scout
opportunities are created concurrently. Remove asyncio.sleep(2) that
added ~8s of post-display delay for multi-pack opens. create_scout_opportunity()
already guards against empty pack_cards with an early return.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces bare `except Exception: pass` with `logging.debug(..., exc_info=True)`
so badge lookup failures are traceable in logs without affecting card display.
Closes#150
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix incorrect command names (/card→/player, /roster→/team, /buy→/buy card-by-name,
/openpack→/open-packs, /scout→/scout-tokens). Update execution checklist with full
Playwright test session results — API tests, filter tests, pagination, edge cases
all passing. Note badge propagation design gap and REF-22 fix (discord#141).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adminer is exposed on host port 8080, shadowing the bot health endpoint.
Change health server default to 8081 to avoid the conflict.
Closes#130
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When page exceeds total pages, API returns empty items but non-zero
count. Now detects this case and re-fetches the last valid page.
Closes#141
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#138
The test suite passes `team` to _build_refractor_response but the
function signature did not accept it. Adds `team: dict = None` so
tests for the refractor card image collection view pass without
changing any existing behavior.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use `variant is None` instead of `not variant` to avoid skipping
variant 0 tier-ups (0 is falsy in Python)
- Remove unused `team` parameter from _build_refractor_response
- Update tests to match
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds optional refractor_tier parameter to the /player slash command.
When provided: looks up the user's team refractor data, shows the
evolved card image if available, triggers on-demand render if image
not yet generated, or shows top 5 refractor cards as fallback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
After refractor tier-ups, the bot hits the card render URL for each
variant card to trigger Playwright render + S3 upload as a side
effect. Fire-and-forget — failures are logged but never raised.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tier boosts shipped in Phase 2 — the teaser field in the T4 tier-up
embed was outdated. Remove it and update tests + test plan to match.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>