From 2eea7a7f587be2df113449dfdf99ee122be9f5dd Mon Sep 17 00:00:00 2001 From: ChuckBuilds Date: Sat, 1 Aug 2026 15:19:45 -0400 Subject: [PATCH] fix(baseball): don't drop favourite MiLB games on the diagnostic path The competition-level status fallback fixed the inning lookup, but the favourite-team debug block a few lines above still read the event top-level game_event["status"]. MiLB events (synthesized from the MLB Stats API into an ESPN-like shape) populate only the competition-level status, so the identical event that extracted fine for a non-favourite raised KeyError and returned None once the team was a favourite. Worst possible shape for the bug: it only hit the games the user cared most about, and only on the path meant to help diagnose them. The existing regression test missed it because it never passes favourites, so is_favorite_game was False and the block never ran. Uses the validated competition-level `status`, which _extract_game_details_common guarantees is present by that point. Adds a favourites-passing companion test; confirmed it reproduces the KeyError without the fix. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01KEZK1P1Q1fu5pcuVrkrCFZ --- src/base_classes/baseball.py | 7 ++++++- test/test_sports_base_characterization.py | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/base_classes/baseball.py b/src/base_classes/baseball.py index 83b90a24..ac84bfb7 100644 --- a/src/base_classes/baseball.py +++ b/src/base_classes/baseball.py @@ -151,7 +151,12 @@ class Baseball(SportsCore): # Only log detailed information for favorite teams if is_favorite_game: - self.logger.debug(f"Full status data: {game_event['status']}") + # Use the validated competition-level `status` here too. MiLB + # events carry no event-level one, so this debug line raised a + # KeyError and dropped the very games it was meant to help + # diagnose -- and only for favourites, which is the worst way + # for it to fail. + self.logger.debug(f"Full status data: {status}") self.logger.debug(f"Status type: {game_status}, State: {status_state}") self.logger.debug(f"Status detail: {status['type'].get('detail', '')}") self.logger.debug( diff --git a/test/test_sports_base_characterization.py b/test/test_sports_base_characterization.py index 980446f7..42c7f427 100644 --- a/test/test_sports_base_characterization.py +++ b/test/test_sports_base_characterization.py @@ -363,6 +363,20 @@ class TestExtractGameDetailsContract: assert details is not None assert details["inning"] == 7 + def test_baseball_live_without_top_level_status_extracts_for_favorites(self): + # The favourite-team branch logs the status payload for diagnostics and + # read the same event top-level key the test above proves can be + # absent. So the identical MiLB event that extracts fine for a + # non-favourite raised KeyError and was dropped once the team WAS a + # favourite -- the worst shape for the bug, since it only hit the games + # the user cared most about, and only on the diagnostic path that was + # supposed to help debug them. + event = make_event("413", "in", "2026-07-16T23:05:00Z", period=7) + del event["status"] + details = extract(Baseball, event, favorites=["TB"]) + assert details is not None + assert details["inning"] == 7 + # --------------------------------------------------------------------------- # 2. update() flow on concrete subclasses (offline, cache-fed)