Easy Money

ET --:-- -- · CST --:-- --
← Back to game
Odds Graph Debug — 0042500214
NYK @ PHI  ·  2026-05-10T19:30:00Z  ·  price-history JSON ↗  ·  alignment-debug JSON ↗
Summary
game_row_found True
playoff_row_found True
game_time_utc 2026-05-10T19:30:00Z
game_status_id 3
game_has_final_score True
final_signal scores_past_date
game_start_ms 1778441400000 2026-05-10T19:30:00Z
window_start_ms 1778437800000 2026-05-10T18:30:00Z
basketball_final_ms 1778448883000 2026-05-10T21:34:43Z
window_end_ms 1778449783000 2026-05-10T21:49:43Z
window_duration_min 200
pg_final_ms_fallback used False
odds_start_fallback used False
game_time_utc Refetch Execution
gtu_refetch_attempted False ← refetch was NOT triggered on this request
gtu_refetch_trigger_reason game_time_utc already set
game_time_utc_before
game_date (used for ScoreboardV3 call) NULL
source_1_scoreboard_attempted
source_1_scoreboard_found_game
source_1_scoreboard_gameTimeUTC null
source_2_boxscore_attempted
source_2_boxscore_gameTimeUTC null
gtu_refetch_source_used none
gtu_refetch_value null
db_path
rows_affected (SQL UPDATE)
gtu_refetch_update_applied
game_time_utc_after (re-read same conn) null
Source Rows
A. games table
game_id 0042500214
game_status_id 3
game_time_utc 2026-05-10T19:30:00Z
home_abbr PHI
visitor_abbr NYK
home_pts 114
visitor_pts 144
B. playoff_games table
game_start_ms 1778441400000
scheduled_start_ms 1778441400000
basketball_final_ms 1778447848000
basketball_final_source espn_pbp_last_valid_event
basketball_final_event_text Miles McBride makes 25-foot three pointer (Mikal Bridges assists)
basketball_final_period 3
basketball_final_clock 5:45
basketball_final_raw_timestamp 2026-05-10T21:17:28Z
home_team_abbr PHI
away_team_abbr NYK
home_score 75
away_score 105
status in_progress
C. playoff_game_pbp_events diagnostics
row count 289
Show last 5 PBP events ↓
[
  {
    "id": 418362,
    "game_id": "0042500214",
    "source": "espn",
    "event_id": "401871162426",
    "sequence": 426,
    "timestamp_ms": 1778447848000,
    "raw_timestamp": "2026-05-10T21:17:28Z",
    "period": 3,
    "clock": "5:45",
    "event_type": "131",
    "event_text": "Miles McBride makes 25-foot three pointer (Mikal Bridges assists)",
    "team_id": "18",
    "player_id": "4431823",
    "is_valid_in_game_event": 1,
    "raw_json": "{\"seq\": 426, \"period\": 3, \"clock\": \"5:45\", \"text\": \"Miles McBride makes 25-foot three pointer (Mikal Bridges assists)\", \"homeScore\": 75, \"awayScore\": 105}",
    "created_at": "2026-05-10T21:18:07Z",
    "updated_at": "2026-05-10T21:18:07Z",
    "home_score": 75,
    "away_score": 105
  },
  {
    "id": 418361,
    "game_id": "0042500214",
    "source": "espn",
    "event_id": "401871162424",
    "sequence": 424,
    "timestamp_ms": 1778447826000,
    "raw_timestamp": "2026-05-10T21:17:06Z",
    "period": 3,
    "clock": "6:07",
    "event_type": "110",
    "event_text": "VJ Edgecombe makes driving layup (Joel Embiid assists)",
    "team_id": "20",
    "player_id": "5124612",
    "is_valid_in_game_event": 1,
    "raw_json": "{\"seq\": 424, \"period\": 3, \"clock\": \"6:07\", \"text\": \"VJ Edgecombe makes driving layup (Joel Embiid assists)\", \"homeScore\": 75, \"awayScore\": 102}",
    "created_at": "2026-05-10T21:18:07Z",
    "updated_at": "2026-05-10T21:18:07Z",
    "home_score": 75,
    "away_score": 102
  },
  {
    "id": 418360,
    "game_id": "0042500214",
    "source": "espn",
    "event_id": "401871162422",
    "sequence": 422,
    "timestamp_ms": 1778447801000,
    "raw_timestamp": "2026-05-10T21:16:41Z",
    "period": 3,
    "clock": "6:31",
    "event_type": "92",
    "event_text": "Josh Hart makes 23-foot three point jumper (Mikal Bridges assists)",
    "team_id": "18",
    "player_id": "3062679",
    "is_valid_in_game_event": 1,
    "raw_json": "{\"seq\": 422, \"period\": 3, \"clock\": \"6:31\", \"text\": \"Josh Hart makes 23-foot three point jumper (Mikal Bridges assists)\", \"homeScore\": 73, \"awayScore\": 102}",
    "created_at": "2026-05-10T21:18:07Z",
    "updated_at": "2026-05-10T21:18:07Z",
    "home_score": 73,
    "away_score": 102
  },
  {
    "id": 418359,
    "game_id": "0042500214",
    "source": "espn",
    "event_id": "401871162421",
    "sequence": 421,
    "timestamp_ms": 1778447785000,
    "raw_timestamp": "2026-05-10T21:16:25Z",
    "period": 3,
    "clock": "6:44",
    "event_type": "97",
    "event_text": "Dominick Barlow makes free throw 1 of 1",
    "team_id": "20",
    "player_id": "4870562",
    "is_valid_in_game_event": 1,
    "raw_json": "{\"seq\": 421, \"period\": 3, \"clock\": \"6:44\", \"text\": \"Dominick Barlow makes free throw 1 of 1\", \"homeScore\": 73, \"awayScore\": 99}",
    "created_at": "2026-05-10T21:18:07Z",
    "updated_at": "2026-05-10T21:18:07Z",
    "home_score": 73,
    "away_score": 99
  },
  {
    "id": 418358,
    "game_id": "0042500214",
    "source": "espn",
    "event_id": "401871162419",
    "sequence": 419,
    "timestamp_ms": 1778447764000,
    "raw_timestamp": "2026-05-10T21:16:04Z",
    "period": 3,
    "clock": "6:44",
    "event_type": "44",
    "event_text": "Mikal Bridges shooting foul",
    "team_id": "18",
    "player_id": "3147657",
    "is_valid_in_game_event": 1,
    "raw_json": "{\"seq\": 419, \"period\": 3, \"clock\": \"6:44\", \"text\": \"Mikal Bridges shooting foul\", \"homeScore\": 72, \"awayScore\": 99}",
    "created_at": "2026-05-10T21:18:07Z",
    "updated_at": "2026-05-10T21:18:07Z",
    "home_score": 72,
    "away_score": 99
  }
]
Games Row Provenance
Most Likely Write Source
confidence: High   fetch_and_store_games
game_time_utc is populated. This field is ONLY written by fetch_and_store_games() (ScoreboardV3). All other write paths omit it from their INSERT/UPDATE.
this path writes game_time_utc True
games.updated_at
games.game_time_utc (current) 2026-05-10T19:30:00Z
games.game_status_id (current) 3
games.home_pts / visitor_pts 114 / 144
Field-Level Write Coverage
Field Written by NOT written by Strategy / Risk
game_time_utc fetch_and_store_games sync_playoff_games, fetch_and_store_historical_game, copy_game_to_nba_db, boxscores_live_update, playoff_resolve_update COALESCE — set once on first non-null insert; never overwritten after that
Risk: High: only fetch_and_store_games writes it, and it only runs for today/yesterday
game_status_id fetch_and_store_games, sync_playoff_games, fetch_and_store_historical_game, copy_game_to_nba_db, boxscores_live_update playoff_resolve_update MAX(existing, new) in fetch_and_store_games; direct set in sync/historical/live
Risk: Low: all major paths write it
home_pts / visitor_pts fetch_and_store_games, sync_playoff_games, fetch_and_store_historical_game, copy_game_to_nba_db, boxscores_live_update playoff_resolve_update Varies: MAX for final (sync), COALESCE for live, direct for historical
Risk: Low: most paths populate scores
game_date fetch_and_store_games, sync_playoff_games, fetch_and_store_historical_game, copy_game_to_nba_db boxscores_live_update, playoff_resolve_update Set on INSERT; ON CONFLICT generally does not update it
Risk: Low: all INSERT paths include game_date
All Candidate Write Paths
Function File game_time_utc can null gtu old games When / Note
fetch_and_store_games(game_date) likely app/services/games.py YES Only if ScoreboardV3 returns gameTimeUTC=null (rare) False
Homepage load (today/yesterday), scheduler daily, startup warmup_games_db()
Warmup covers today+yesterday only. Games ≥2 days old are never re-fetched by this path.
sync_playoff_games(season) app/services/games.py NO True True
Rate-limited: called by playoff_analytics._sync_playoff_games_if_due() on bracket page fetch
LeagueGameFinder has no gameTimeUTC field. Creates complete rows (date, teams, final score) but leaves game_time_utc=NULL.
fetch_and_store_historical_game(game_id) app/services/historical.py NO True True
On-demand: /games/{game_id} visited and game not yet in DB
Bypassed if game already exists (sync_playoff_games may have created it). Does not populate game_time_utc.
copy_game_to_nba_db(game_id) app/services/playoff_history_db.py NO True True
Called first inside fetch_and_store_historical_game
Short-circuits the nba_api call if game is in the local history DB.
fetch_and_store_live_boxscore() / store_live_period_scores() app/services/boxscores.py NO False False
During live game polling (~every 5 s while game is live)
Never creates rows. Cannot set game_time_utc to NULL.
_resolve_playoff_placeholders() app/main.py NO False False
Homepage load when visitor/home team is still TBD
Only sets team identification fields. Cannot affect game_time_utc.
Execution Trace
# Step Branch / Path Output Inputs & Fields
1 Load games table row found found=True
game_id 0042500214
game_time_utc 2026-05-10T19:30:00Z
game_status_id 3
home_pts 114
visitor_pts 144
2 Load playoff_games row found found=True
game_id 0042500214
status in_progress
game_start_ms 1778441400000
scheduled_start_ms 1778441400000
basketball_final_ms 1778447848000
3 Load odds aggregate (playoff_game_odds_history) no_data cnt=0 min_ts=None max_ts=None
game_id 0042500214
4 Derive scheduled_start_ms games.game_time_utc 1778441400000 (2026-05-10T19:30:00Z)
games.game_time_utc 2026-05-10T19:30:00Z
playoff_games.scheduled_start_ms 1778441400000
playoff_games.game_start_ms 1778441400000
5 Derive game_start_ms playoff_games.game_start_ms (actual) 1778441400000 (2026-05-10T19:30:00Z)
actual_start_ms (pg.game_start_ms) 1778441400000
scheduled_start_ms 1778441400000
5b Midnight-ET placeholder detection & start correction not_midnight_et uncorrected → 1778441400000 (2026-05-10T19:30:00Z)
not midnight-ET
game_start_ms_raw 1778441400000
bfr_ms 1778447848000
basketball_final_raw_ts 2026-05-10T21:17:28Z
basketball_final_period 3
midnight_et_detected False
corrected_game_start_ms null
bfr_ms 1778447848000
6 Detect game_has_final_score scores_past_date game_has_final_score=True final_signal=scores_past_date
home_pts 114
visitor_pts 144
game_time_utc 2026-05-10T19:30:00Z
game_status_id 3
pg.status in_progress
pg.basketball_final_ms 1778447848000
scores_present True
game_time_utc_present True
past_date_in_et True
status_id_is_3 True
pg_status_is_final False
pg_status_is_in_progress True
pg_has_basketball_final_ms True
pg_bfm_suppressed_in_progress True
scores_past_date_fired True
scores_status3_sameday_fired False
scores_status3_no_tip_fired False
playoff_games_status_final_fired False
playoff_games_has_final_ms_fired False
midnight_et_start_detected False
midnight_et_start_corrected False
7 Derive basketball_final_ms get_basketball_final_point → value 1778448883000 (2026-05-10T21:34:43Z)
game_has_final_score True
bfp_called True
bfp_returned_ms 1778448883000
bfp_error null
pg.basketball_final_ms 1778447848000
pg.basketball_final_raw_ts 2026-05-10T21:17:28Z
bfr_ms 1778447848000
bfp_vs_bfr_delta_h 0.2875
used_pg_final_ms_fallback False
bfr_ms 1778447848000
bfp_vs_bfr_delta_h 0.2875
bfr_overrode_bfp False
8 Derive window_start_ms (game_start − 1 h) game_start_minus_1h 1778437800000 (2026-05-10T18:30:00Z)
game_start_ms 1778441400000
ph_agg.min_ts null
odds_start_fallback_used False
9 Derive window_end_ms (basketball_final + 15 min) final_plus_15min 1778449783000 (2026-05-10T21:49:43Z)
basketball_final_ms 1778448883000
grace_ms 900000
Branch Decisions
scores_present True
game_time_utc_present True
past_date_in_et True
status_id_is_3 True
pg_status_is_final False
pg_status_is_in_progress True
pg_has_basketball_final_ms True
pg_bfm_suppressed_in_progress True
scores_past_date_fired True
scores_status3_sameday_fired False
scores_status3_no_tip_fired False
playoff_games_status_final_fired False
playoff_games_has_final_ms_fired False
midnight_et_start_detected False
midnight_et_start_corrected False
bfp_called True
pg_final_ms_fallback_used False
odds_start_fallback_used False
Odds Filtering Breakdown
odds source postgres_listener
raw rows total 2235
rows before window_start_ms 1
rows in window (start → end) 1591
rows after window_end_ms 643
earliest timestamp (epoch s) 1778437798 2026-05-10T18:29:58Z
latest timestamp (epoch s) 1778453121 2026-05-10T22:45:21Z
local odds history rows 0
window_start_ms applied 1778437800000 2026-05-10T18:30:00Z
window_end_ms applied 1778449783000 2026-05-10T21:49:43Z
Enrichment Trace
A. Referees
query game_referee_assignments JOIN referees
game_referee_assignments rows 4
referees after JOIN 4
referee list #4 Sean Wright (Crew Chief)
#10 John Goble (Referee)
#3 Nick Buchert (Umpire)
#83 Andy Nagy (Alternate)
B. Lineup Marker
query lineup_state WHERE game_id = ?
lineup_state row found True
is_confirmed 1
telegram_first_detected_at NULL
first_confirmed_at 2026-05-10T19:36:34Z
chosen timestamp field first_confirmed_at
final lineup_marker_ts 2026-05-10T19:36:34Z 2026-05-10T19:36:34Z
lineup_confirmed True
Raw Debug JSON (machine-readable)
Show full debug payload ↓
{
  "game_id": "0042500214",
  "gtu_refetched": false,
  "gtu_refetch_trace": {
    "attempted": false,
    "trigger_reason": "game_time_utc already set"
  },
  "games_raw": {
    "game_id": "0042500214",
    "game_status_id": 3,
    "game_time_utc": "2026-05-10T19:30:00Z",
    "home_abbr": "PHI",
    "visitor_abbr": "NYK",
    "home_pts": 114,
    "visitor_pts": 144
  },
  "playoff_games_raw": {
    "game_start_ms": 1778441400000,
    "scheduled_start_ms": 1778441400000,
    "basketball_final_ms": 1778447848000,
    "basketball_final_source": "espn_pbp_last_valid_event",
    "basketball_final_event_text": "Miles McBride makes 25-foot three pointer (Mikal Bridges assists)",
    "basketball_final_period": 3,
    "basketball_final_clock": "5:45",
    "basketball_final_raw_timestamp": "2026-05-10T21:17:28Z",
    "home_team_abbr": "PHI",
    "away_team_abbr": "NYK",
    "home_score": 75,
    "away_score": 105,
    "status": "in_progress"
  },
  "ph_agg": {
    "cnt": 0,
    "min_ts": null,
    "max_ts": null
  },
  "bfp": {
    "final_ms": 1778448883000,
    "source": "stored_pbp_extrapolated_to_game_end",
    "event_text": "Miles McBride makes 25-foot three pointer (Mikal Bridges assists)",
    "period": 3,
    "clock": "0:00",
    "raw_timestamp": null,
    "warning": "extrapolated 345s remaining game-clock to end (3\u00d7 stretch)"
  },
  "bfp_called": true,
  "bfp_error": null,
  "final_branches": {
    "scores_present": true,
    "game_time_utc_present": true,
    "past_date_in_et": true,
    "status_id_is_3": true,
    "pg_status_is_final": false,
    "pg_status_is_in_progress": true,
    "pg_has_basketball_final_ms": true,
    "pg_bfm_suppressed_in_progress": true,
    "scores_past_date_fired": true,
    "scores_status3_sameday_fired": false,
    "scores_status3_no_tip_fired": false,
    "playoff_games_status_final_fired": false,
    "playoff_games_has_final_ms_fired": false,
    "midnight_et_start_detected": false,
    "midnight_et_start_corrected": false
  },
  "window": {
    "game_start_ms": 1778441400000,
    "window_start_ms": 1778437800000,
    "window_end_ms": 1778449783000,
    "basketball_final_ms": 1778448883000,
    "window_duration_min": 200
  },
  "odds_filter": {
    "raw_count": 2235,
    "before_window": 1,
    "in_window": 1591,
    "after_window": 643,
    "uncategorized": 0
  },
  "referee_trace": {
    "query": "game_referee_assignments JOIN referees",
    "assignments_found": 4,
    "referees_found": 4,
    "error": null
  },
  "lineup_trace": {
    "query": "lineup_state WHERE game_id = ?",
    "row_found": true,
    "is_confirmed": 1,
    "telegram_first_detected_at": null,
    "first_confirmed_at": "2026-05-10T19:36:34Z",
    "chosen_field": "first_confirmed_at",
    "error": null
  },
  "pbp_row_count": 289,
  "pbp_last_events": [
    {
      "id": 418362,
      "game_id": "0042500214",
      "source": "espn",
      "event_id": "401871162426",
      "sequence": 426,
      "timestamp_ms": 1778447848000,
      "raw_timestamp": "2026-05-10T21:17:28Z",
      "period": 3,
      "clock": "5:45",
      "event_type": "131",
      "event_text": "Miles McBride makes 25-foot three pointer (Mikal Bridges assists)",
      "team_id": "18",
      "player_id": "4431823",
      "is_valid_in_game_event": 1,
      "raw_json": "{\"seq\": 426, \"period\": 3, \"clock\": \"5:45\", \"text\": \"Miles McBride makes 25-foot three pointer (Mikal Bridges assists)\", \"homeScore\": 75, \"awayScore\": 105}",
      "created_at": "2026-05-10T21:18:07Z",
      "updated_at": "2026-05-10T21:18:07Z",
      "home_score": 75,
      "away_score": 105
    },
    {
      "id": 418361,
      "game_id": "0042500214",
      "source": "espn",
      "event_id": "401871162424",
      "sequence": 424,
      "timestamp_ms": 1778447826000,
      "raw_timestamp": "2026-05-10T21:17:06Z",
      "period": 3,
      "clock": "6:07",
      "event_type": "110",
      "event_text": "VJ Edgecombe makes driving layup (Joel Embiid assists)",
      "team_id": "20",
      "player_id": "5124612",
      "is_valid_in_game_event": 1,
      "raw_json": "{\"seq\": 424, \"period\": 3, \"clock\": \"6:07\", \"text\": \"VJ Edgecombe makes driving layup (Joel Embiid assists)\", \"homeScore\": 75, \"awayScore\": 102}",
      "created_at": "2026-05-10T21:18:07Z",
      "updated_at": "2026-05-10T21:18:07Z",
      "home_score": 75,
      "away_score": 102
    },
    {
      "id": 418360,
      "game_id": "0042500214",
      "source": "espn",
      "event_id": "401871162422",
      "sequence": 422,
      "timestamp_ms": 1778447801000,
      "raw_timestamp": "2026-05-10T21:16:41Z",
      "period": 3,
      "clock": "6:31",
      "event_type": "92",
      "event_text": "Josh Hart makes 23-foot three point jumper (Mikal Bridges assists)",
      "team_id": "18",
      "player_id": "3062679",
      "is_valid_in_game_event": 1,
      "raw_json": "{\"seq\": 422, \"period\": 3, \"clock\": \"6:31\", \"text\": \"Josh Hart makes 23-foot three point jumper (Mikal Bridges assists)\", \"homeScore\": 73, \"awayScore\": 102}",
      "created_at": "2026-05-10T21:18:07Z",
      "updated_at": "2026-05-10T21:18:07Z",
      "home_score": 73,
      "away_score": 102
    },
    {
      "id": 418359,
      "game_id": "0042500214",
      "source": "espn",
      "event_id": "401871162421",
      "sequence": 421,
      "timestamp_ms": 1778447785000,
      "raw_timestamp": "2026-05-10T21:16:25Z",
      "period": 3,
      "clock": "6:44",
      "event_type": "97",
      "event_text": "Dominick Barlow makes free throw 1 of 1",
      "team_id": "20",
      "player_id": "4870562",
      "is_valid_in_game_event": 1,
      "raw_json": "{\"seq\": 421, \"period\": 3, \"clock\": \"6:44\", \"text\": \"Dominick Barlow makes free throw 1 of 1\", \"homeScore\": 73, \"awayScore\": 99}",
      "created_at": "2026-05-10T21:18:07Z",
      "updated_at": "2026-05-10T21:18:07Z",
      "home_score": 73,
      "away_score": 99
    },
    {
      "id": 418358,
      "game_id": "0042500214",
      "source": "espn",
      "event_id": "401871162419",
      "sequence": 419,
      "timestamp_ms": 1778447764000,
      "raw_timestamp": "2026-05-10T21:16:04Z",
      "period": 3,
      "clock": "6:44",
      "event_type": "44",
      "event_text": "Mikal Bridges shooting foul",
      "team_id": "18",
      "player_id": "3147657",
      "is_valid_in_game_event": 1,
      "raw_json": "{\"seq\": 419, \"period\": 3, \"clock\": \"6:44\", \"text\": \"Mikal Bridges shooting foul\", \"homeScore\": 72, \"awayScore\": 99}",
      "created_at": "2026-05-10T21:18:07Z",
      "updated_at": "2026-05-10T21:18:07Z",
      "home_score": 72,
      "away_score": 99
    }
  ],
  "games_write_paths": [
    {
      "id": "fetch_and_store_games",
      "file": "app/services/games.py",
      "function": "fetch_and_store_games(game_date)",
      "when": "Homepage load (today/yesterday), scheduler daily, startup warmup_games_db()",
      "source_api": "ScoreboardV3 (nba_api)",
      "writes_game_time_utc": true,
      "game_time_utc_strategy": "COALESCE(existing, new) \u2014 fills if null, never overwrites non-null",
      "can_create_null_gtu": "Only if ScoreboardV3 returns gameTimeUTC=null (rare)",
      "covers_old_games": false,
      "note": "Warmup covers today+yesterday only. Games \u22652 days old are never re-fetched by this path."
    },
    {
      "id": "sync_playoff_games",
      "file": "app/services/games.py",
      "function": "sync_playoff_games(season)",
      "when": "Rate-limited: called by playoff_analytics._sync_playoff_games_if_due() on bracket page fetch",
      "source_api": "LeagueGameFinder (nba_api)",
      "writes_game_time_utc": false,
      "game_time_utc_strategy": "NOT in INSERT column list; NOT in ON CONFLICT SET \u2014 always NULL for new rows",
      "can_create_null_gtu": true,
      "covers_old_games": true,
      "note": "LeagueGameFinder has no gameTimeUTC field. Creates complete rows (date, teams, final score) but leaves game_time_utc=NULL."
    },
    {
      "id": "fetch_and_store_historical_game",
      "file": "app/services/historical.py",
      "function": "fetch_and_store_historical_game(game_id)",
      "when": "On-demand: /games/{game_id} visited and game not yet in DB",
      "source_api": "BoxScoreSummaryV3 (nba_api) / playoff_history_db",
      "writes_game_time_utc": false,
      "game_time_utc_strategy": "NOT in INSERT column list; NOT in ON CONFLICT SET",
      "can_create_null_gtu": true,
      "covers_old_games": true,
      "note": "Bypassed if game already exists (sync_playoff_games may have created it). Does not populate game_time_utc."
    },
    {
      "id": "copy_game_to_nba_db",
      "file": "app/services/playoff_history_db.py",
      "function": "copy_game_to_nba_db(game_id)",
      "when": "Called first inside fetch_and_store_historical_game",
      "source_api": "Local playoff_history.db SQLite file",
      "writes_game_time_utc": false,
      "game_time_utc_strategy": "NOT in INSERT column list; NOT in ON CONFLICT SET",
      "can_create_null_gtu": true,
      "covers_old_games": true,
      "note": "Short-circuits the nba_api call if game is in the local history DB."
    },
    {
      "id": "boxscores_live_update",
      "file": "app/services/boxscores.py",
      "function": "fetch_and_store_live_boxscore() / store_live_period_scores()",
      "when": "During live game polling (~every 5 s while game is live)",
      "source_api": "data.nba.com live BoxScore",
      "writes_game_time_utc": false,
      "game_time_utc_strategy": "UPDATE only: game_status_id, status_text, home_pts, visitor_pts",
      "can_create_null_gtu": false,
      "covers_old_games": false,
      "note": "Never creates rows. Cannot set game_time_utc to NULL."
    },
    {
      "id": "playoff_resolve_update",
      "file": "app/main.py",
      "function": "_resolve_playoff_placeholders()",
      "when": "Homepage load when visitor/home team is still TBD",
      "source_api": "postseason_state / standings (DB-only)",
      "writes_game_time_utc": false,
      "game_time_utc_strategy": "UPDATE only: visitor/home team abbr, name, team_id",
      "can_create_null_gtu": false,
      "covers_old_games": false,
      "note": "Only sets team identification fields. Cannot affect game_time_utc."
    }
  ],
  "likely_games_write_source": {
    "source": "fetch_and_store_games",
    "reason": "game_time_utc is populated. This field is ONLY written by fetch_and_store_games() (ScoreboardV3). All other write paths omit it from their INSERT/UPDATE.",
    "confidence": "High",
    "writes_game_time_utc": true
  },
  "field_write_coverage": {
    "game_time_utc": {
      "written_by": [
        "fetch_and_store_games"
      ],
      "not_written_by": [
        "sync_playoff_games",
        "fetch_and_store_historical_game",
        "copy_game_to_nba_db",
        "boxscores_live_update",
        "playoff_resolve_update"
      ],
      "strategy": "COALESCE \u2014 set once on first non-null insert; never overwritten after that",
      "null_risk": "High: only fetch_and_store_games writes it, and it only runs for today/yesterday"
    },
    "game_status_id": {
      "written_by": [
        "fetch_and_store_games",
        "sync_playoff_games",
        "fetch_and_store_historical_game",
        "copy_game_to_nba_db",
        "boxscores_live_update"
      ],
      "not_written_by": [
        "playoff_resolve_update"
      ],
      "strategy": "MAX(existing, new) in fetch_and_store_games; direct set in sync/historical/live",
      "null_risk": "Low: all major paths write it"
    },
    "home_pts / visitor_pts": {
      "written_by": [
        "fetch_and_store_games",
        "sync_playoff_games",
        "fetch_and_store_historical_game",
        "copy_game_to_nba_db",
        "boxscores_live_update"
      ],
      "not_written_by": [
        "playoff_resolve_update"
      ],
      "strategy": "Varies: MAX for final (sync), COALESCE for live, direct for historical",
      "null_risk": "Low: most paths populate scores"
    },
    "game_date": {
      "written_by": [
        "fetch_and_store_games",
        "sync_playoff_games",
        "fetch_and_store_historical_game",
        "copy_game_to_nba_db"
      ],
      "not_written_by": [
        "boxscores_live_update",
        "playoff_resolve_update"
      ],
      "strategy": "Set on INSERT; ON CONFLICT generally does not update it",
      "null_risk": "Low: all INSERT paths include game_date"
    }
  }
}