feat(compare): /compare command — side-by-side card stat embed (Roadmap 2.5b) #165

Open
cal wants to merge 4 commits from autonomous/feat-compare-command into main

4 Commits

Author SHA1 Message Date
Cal Corum
cc72827dad fix(gauntlet): fix loss_max=0 falsy-zero trap in recap marker logic
All checks were successful
Ruff Lint / lint (pull_request) Successful in 19s
`(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>
2026-04-10 12:32:10 -05:00
Cal Corum
0b8beda8b5 feat(compare): add /compare slash command for side-by-side card comparison
All checks were successful
Ruff Lint / lint (pull_request) Successful in 13s
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>
2026-04-10 10:35:17 -05:00
Cal Corum
9228d2e66c feat(gauntlet): post completion recap embed on 10-win gauntlet finish
All checks were successful
Ruff Lint / lint (pull_request) Successful in 13s
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>
2026-04-10 10:31:57 -05:00
Cal Corum
f62e08889f fix(gameplay): replace bare except with NoResultFound in cache-miss paths
All checks were successful
Ruff Lint / lint (pull_request) Successful in 27s
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>
2026-04-10 10:28:40 -05:00