feat: add season-level player catalog - #50
Merged
Merged
Conversation
Discovery and the persisted catalog read returned two different orders for the same players, and neither was name order. Discovery sorted on casefold, which does not fold accents; the repository sorted in SQL, where SQLite's default collation compares raw bytes and puts every lowercase name after every uppercase one. A stored directory read back as Bo Bichette, Zack Wheeler, aaron Judge, Ángel Martínez. Move the rule onto PlayerIdentity.name_sort_key, which folds case and strips combining marks, and apply it in both the discovery service and list_player_catalog. Accented names now sort under their base letter, and a discovered directory compares equal to a catalog read of the same players. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the season-level Player catalog that closes out the Player discovery foundation for M6.
The application can now discover MLB players for a season with one bulk
Mlb.get_people(sport_id=1, season=...)request, persist stable player identity separately from season membership, and support future DB-only Player search/selection without requiring users to know MLB player IDs.No Player UI, charts, game logs, pitching ingestion, team-stint model, or mass per-player stats ingestion is added here.
Why
PR #49 established the first Player data slice, but explicit player-season ingestion still required a known MLB player ID.
Before Player analytics can have a usable selector, the local database needs to answer a simpler question:
A live audit confirmed that
get_people(sport_id=1, season=YEAR)behaves as a season-scoped Player directory and returns one bulk population rather than requiring one request per player. The audit also showed that historical responses expose current biographical identity fields, so season membership must remain separate from global Player identity.What
player_seasonspersistence keyed by(player_id, season)playersas the single source of current normalized Player identityplayer_season_hittingindependent from catalog membershipPlayerSeasonCatalogEntryand typed catalog-ingestion resultsMlb.get_people(...)requestMlb()client when the caller does not supply onescripts/import_player_catalog.py --season <year>as a thin CLI adapterTests
Live discovery audit documented in
docs/player-season-catalog.mdcovered multiple seasons and confirmed unique Player IDs with no missing required names or primary positions in the audited populations.Risk and impact
Normal
This adds a new persistence concept and a bulk ingestion path, but keeps the existing architecture deliberately conservative:
Future Player UI can query this catalog locally and join to available stat tables without calling MLB from a browser request.