836b8c73d5
A cache entry answers "what is the market for THIS SLATE". For MLB the slate is
a BASEBALL DATE in America/New_York -- the same date gameBinder,
retentionService, ledgerService and read_natural_key all use. The key was built
from the UTC calendar date, so between 00:00Z and Eastern midnight the key
advanced while the slate did not:
2026-08-29T01:03Z = 2026-08-28 21:03 ET
slate date 2026-08-28, key looked up odds:mlb:2026-08-29
A value written earlier that evening under odds:mlb:2026-08-28 was then
unreachable -- not expired, ADDRESSED WRONG.
CAUSAL HONESTY: this is NOT retroactively the cause of the failed 01:03Z canary.
That run also used an 84-minute-old observation whose cache had passed its 1h
TTL. Two independent reasons; the date defect is real but not proven
counterfactual.
MLB ONLY. Every other sport keeps the UTC basis -- their date semantics are
unproven here and rekeying a cache they already write and read consistently
would invalidate live entries for no demonstrated defect.
Symmetry is structural, not conventional: the three readers that built the key
inline now ask `oddsService.getCacheKey(sport)`, so writer and readers cannot
diverge. The ET date comes from `scheduleService.gameDateET` -- the repository's
own Intl/America\/New_York primitive, now exported -- so DST is the zone
database's business and never offset arithmetic. An unresolvable clock REFUSES
rather than falling back to the other basis.
TTL truth is kept separate: a correctly addressed but expired entry still
misses, and CACHE_TTL is unchanged at 3600.
Provider priority, quota policy, retries, EARLY_RETURN_ODDS_ERROR semantics,
lineage lookup, game-date repair, canonical participant and intraday belief
integrity are all untouched.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CQJeAG8vcDoL5zkiaJyVb8