`(loss_max or 99)` treats `loss_max=0` as 99, so 10-1 runs showed ⬜
instead of ❌ for perfect-run rewards. Fix uses explicit None check.
Tighten test to assert ❌ presence rather than just absence of ✅.
Addresses review feedback on PR #165.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements Roadmap 2.5b: new /compare command lets players compare two
cards of the same type (batter vs batter or pitcher vs pitcher) in a
side-by-side embed with directional delta arrows (▲▼═).
- cogs/compare.py: new CompareCog with /compare slash command and
player_autocomplete on both params; fetches battingcard/pitchingcard
data from API; validates type compatibility; sends public embed
- tests/test_compare_command.py: 30 unit tests covering _delta_arrow,
_is_pitcher, batter/pitcher embed builders, type mismatch error, and
edge cases (None stats, tied values)
- paperdynasty.py: registers cogs.compare in COGS list
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds build_gauntlet_recap_embed (sync builder) and post_gauntlet_recap
(async sender) to gauntlets.py. Called from post_result when wins == 10.
Embed shows champion name + user mention, final record, win-progression
ladder, and full prize-distribution table with earned/unearned markers.
Gracefully skips if channel is None or any step raises.
Roadmap 2.4a — closes growth-sweep finding 2026-04-10-003.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
In gameplay_queries.py, 10 try/except blocks used `except Exception:` to
detect SQLModel row-not-found cache misses (.one() returning no result).
This silently swallowed connection failures, attribute errors, and
programming bugs on the gameplay hot path.
Narrowed each handler to `except NoResultFound:` (sqlalchemy.exc).
Real errors now propagate instead of being misinterpreted as cache misses.
Refs: autonomous-pipeline finding analyst-2026-04-10-003
Category: stability / error_handling
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>