- Fix falsy-zero bug: `(loss_max or 99)` → `loss_max is not None and losses > loss_max`
so a player finishing 10-1 sees ❌ on the perfect-run bonus instead of ⬜
- Tighten test assertion: assert "❌" in bonus_line (was: assert "✅" not in bonus_line)
- Revert in_game/gameplay_queries.py to main — formatting/NoResultFound changes
belong in PR #163, not here
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>