55b210cb95
PHASE 0 — audit. espnStatsAdapter's slice(0,20) was already fixed at494c83c, so the ESPN branch of getStatRows inherits a full log and is CORRECT. MLB's l20_avg is a real seasonTotal/games aggregate, verified, also CORRECT. TWO basketball defects remained: DEFECTIVE nbaGameLogFeatures m20 = avg(vals.slice(0, 20)) -- l20_avg is the season reference projectionFor reads, and slicing to 20 made it a twenty-game average wearing a season label. The MLB l20 bug, unfixed for basketball. DEFECTIVE getStatRows python getGameLogs(playerName, sp, 20) PHASE 1 — both fixed via a named SEASON_LOG_DEPTH = 100, past an 82-game season so a request can never truncate one. API COST: ZERO. The count is a request parameter, so asking for a season is the same single call. No extra request, no extra quota. MEASUREMENT DEFERRED, EXPLICITLY: basketball is offline, there are no settled basketball rows, and resolution before/after CANNOT be measured now. This is a code fix, not a measured improvement -- exactly like the deferred MLB sibling paths. PHASE 2 — the window guard asserts the property on source: no fixed N may stand in for a season. It immediately caught TWO MORE instances I had missed in Phase 1 -- a hardcoded 20 at featureCache:377 and gameLogService's own `count = 20` DEFAULT, which would have handed a twenty-game window to any caller that omitted the argument. That is a seventh path, found by the guard rather than by me. Retro-confirmed: run unchanged against981a05cit goes 3 failed / 6 passed, flagging the basketball slice, the game-log request and the season-reference check. The class in full, now six paths across two sports, every one of which looked like ordinary code. `slice(0, 20)` is unremarkable; what made it a defect was the QUESTION it answered -- "what is this player's season rate?" -- and no test could see that mismatch because the value produced was always a plausible number. PHASE 3 — THIS CLOSES THE NON-ACCRUAL ARC. Everything buildable without settled rows is built: push unblocked (it was the wrong remote, not the firewall), grade surface honest and rendering, reachability guarded, champion repaired across every path including dormant basketball, and the window class guarded so it cannot return. The program is now correctly IDLE on modeling. Today's count: 0 eligible dates, all four re-audit items WAITING. FIRST TRIGGER: 10 eligible calibration dates on the repaired champion, at which point the resumption order is calibration re-fit, hits factor lift, prior verdict re-audit, rbi lineup-slot gate. No basketball measurement claimed. No NBA chain/archetype build. MLB serving verified byte-identical. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W1sivYNqY2TS5ftykmHBU9