paper-dynasty-database/tests
Cal Corum ab15228c44 fix(refractor): mask variant hash to 31 bits to fit Postgres INTEGER
compute_variant_hash took the first 8 hex chars of a SHA-256 digest and
cast to int, producing values up to 2^32 - 1. The variant columns on
Card, BattingCard, PitchingCard, and RefractorCardState are Peewee
IntegerField → Postgres INTEGER, which is signed 32-bit (max 2^31 - 1).
Roughly half of all players (~50%) would hash into the range [2^31,
2^32 - 1] and crash tier-up writes with:

  peewee.DataError: integer out of range

Surfaced via /dev refractor-test card_id:64460 (Charles Nagy,
player_id=10795), whose tier-1 hash was 2874960417. The outer
exception handler in refractor.evaluate_game caught the error and
logged a warning, so the tier-up was silently dropped — the test
harness reported "No tier-up detected (evaluated 2 cards)" while
apply_tier_boost was actually failing mid-write.

Fix: mask the hash with & 0x7FFFFFFF, dropping one bit of entropy.
~2.1B distinct values remain — still astronomically collision-safe.

Backwards-compatible: all 9 existing refractor_boost_audit rows and
9 persisted non-zero variants have hashes where the high bit was
already 0 (those tier-ups happened to land in the safe half). Masking
leaves those values unchanged.

Added regression test test_fits_postgres_int32 covering 10,000 player
IDs × 5 tiers = 50,000 combinations, all asserted ≤ 2,147,483,647.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 13:11:40 -05:00
..
__init__.py feat: evolution track seed data and tests (WP-03) (#68) 2026-03-12 17:35:12 -05:00
conftest.py chore: remove unused RefractorTierBoost and RefractorCosmetic tables 2026-04-05 22:27:26 -05:00
test_card_storage.py fix: address review feedback (#187) 2026-04-06 20:03:02 -05:00
test_formula_engine.py test: add Tier 1 and Tier 2 refractor system test cases 2026-03-24 09:02:30 -05:00
test_players_card_render.py fix(render): schedule image_url backfill on cache hits 2026-04-11 10:12:23 -05:00
test_postgame_refractor.py chore: remove unused RefractorTierBoost and RefractorCosmetic tables 2026-04-05 22:27:26 -05:00
test_refractor_boost_integration.py chore: remove unused RefractorTierBoost and RefractorCosmetic tables 2026-04-05 22:27:26 -05:00
test_refractor_boost.py fix(refractor): mask variant hash to 31 bits to fit Postgres INTEGER 2026-04-11 13:11:40 -05:00
test_refractor_evaluator.py feat: Refractor Phase 2 integration — wire boost into evaluate-game 2026-03-30 13:04:52 -05:00
test_refractor_image_url.py feat: include image_url in refractor cards API response 2026-04-06 22:36:20 +00:00
test_refractor_init.py test: add Tier 1 and Tier 2 refractor system test cases 2026-03-24 09:02:30 -05:00
test_refractor_models.py chore: remove unused RefractorTierBoost and RefractorCosmetic tables 2026-04-05 22:27:26 -05:00
test_refractor_seed.py test: add Tier 1 and Tier 2 refractor system test cases 2026-03-24 09:02:30 -05:00
test_refractor_state_api.py chore: remove unused RefractorTierBoost and RefractorCosmetic tables 2026-04-05 22:27:26 -05:00
test_refractor_track_api.py chore: remove unused RefractorTierBoost and RefractorCosmetic tables 2026-04-05 22:27:26 -05:00
test_season_stats_model.py refactor: deduplicate pitcher formula and test constants 2026-03-17 09:49:33 -05:00
test_season_stats_update.py fix: stale docstring + add decision-only pitcher test 2026-03-19 10:31:16 -05:00