Commit Graph
3 Commits
Author SHA1 Message Date
Claude 98a7c769ec fix(sports): harden the live game-over check and font/log init
Follow-up review findings on the promoted base-class methods.

_is_game_really_over:
- `period` present-but-None raised TypeError on `None >= FINAL_PERIOD`,
  taking down the whole live-update pass (_detect_stale_games has no
  try/except). Same failure shape as the null `period_text` already fixed.
- An expired clock spelled "00:00" normalizes to "0000", which matched
  none of the hand-listed literals, so a finished game with a two-digit
  minute clock stayed on the scoreboard forever. Compare numerically.

SportsCore:
- _load_fonts kept the cwd-relative "assets/fonts/..." literals the
  _font_root() seam exists to remove, so every scoreboard font degraded
  to PIL's default face outside the install root.
- _should_log read self._last_warning_time unguarded while only an
  unrelated method initialized it lazily; the first warning of a run
  raised AttributeError. Initialize it in __init__.

Also documents that game_update_timestamps is written by subclasses, not
by the base class, so the staleness branch is inert until B5 adoption.

14 new tests. Gates: 463 core unit, 60 plugin safety.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FgbA8SMutQQpXkMG8LMmC4
2026-08-01 16:45:04 +00:00
Claude 2486bdb249 fix(sports): stop dropping hockey and baseball events on optional feed keys
Both bugs were pinned AS-IS by the B0 characterization suite so this
phase could change them knowingly. Both fixes are adoptions of code the
corresponding plugins already ship, not new inventions.

Hockey: the extractor read competitor["statistics"] unguarded, so a
competitor arriving without that array raised KeyError inside the
generator and the WHOLE event was discarded -- valid scores and status
included. Shot/save counts now default to 0, which is already what the
suite expects for an empty statistics array.

Baseball: for live games the extractor read game_event["status"], the
event TOP-LEVEL status, to get the inning. Real ESPN events duplicate
status there, but MiLB events (synthesized from the MLB Stats API into
an ESPN-like shape) populate only the competition-level one, so the
lookup raised a bare KeyError and dropped the event. It now reads the
competition-level status that _extract_game_details_common has already
validated, so it cannot be missing at that point.

The two characterization tests that pinned the old behaviour are
rewritten to assert the fix rather than deleted, so the suite still
documents the edge case -- and still totals 94.

CHANGELOG records these plus the live-clock change from aaabc61 under
Changed/Fixed, since all three are user-visible. The two new promotion
suites join the CI unit job (449 tests).

Verified: unit job 449 passed, plugin-safety job 60 passed, and the
hockey (16) and baseball (24) plugin harnesses render clean at every
panel size.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FgbA8SMutQQpXkMG8LMmC4
2026-08-01 16:25:32 +00:00
Claude 3f4e915af7 docs: seed CHANGELOG.md with the module-availability release discipline
The plugins monorepo's sunset rule ('delete a bundled fallback copy only
when the manifest floors on the first core release shipping the module')
needs core module additions recorded against version numbers. Seeds the
changelog at 3.1.0 and documents the discipline.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FgbA8SMutQQpXkMG8LMmC4
2026-08-01 14:08:18 +00:00