{
  "schema_version": 13,
  "season": "2025-26",
  "generated_at": "2026-10-15T00:27:30.444250+00:00",
  "config_versions": {
    "players": "4.6",
    "teams": "2.3",
    "season": "3.0",
    "recaps": "1.1",
    "method_examples": "2.0"
  },
  "classifiers": {
    "sentiment": {
      "model": "claude-haiku-4-5-20251001",
      "prompt_version": "v2-production+s-hint",
      "prompt": "Classify sentiment toward NBA players.\nSlang: nasty/sick/filthy=positive, washed/brick/fraud/cooked=negative, GOAT=positive.\nA trailing \"/s\" tags the comment as sarcasm.\n\nComment: {comment_body}\n\nRespond ONLY with JSON: {{\"s\":\"pos|neg|neu\",\"c\":0.0-1.0,\"p\":\"Player Name\"|null}}",
      "max_tokens": 75,
      "sampling_params": {
        "temperature": 0.0
      }
    },
    "target": {
      "model": "claude-sonnet-5",
      "prompt_version": "v1",
      "prompt": "This r/NBA comment was labeled {sentiment_word}. Is that {sentiment_word} sentiment aimed at an NBA player, or at a team, front office, coach, referees, a decision, or a play? If at a player, name them; otherwise answer null.\nThe target is the player being praised or criticized - not a player who is merely mentioned, sympathized with, or the subject of someone else's decision.\nNever name a player who does not appear in the comment.\n\nComment: {comment_body}\n\nRespond ONLY with JSON: {{\"t\":\"Player Name\"|null,\"c\":0.0-1.0}}",
      "max_tokens": 75,
      "sampling_params": {
        "thinking": {
          "type": "disabled"
        }
      }
    }
  },
  "snapshots": {
    "games_fetched_at": "2026-09-12",
    "posts_processed_at": "2026-10-08",
    "download_daily_processed_at": "2026-10-11"
  },
  "rules": {
    "qualified_threshold": 5000,
    "samples": {
      "top_n": 10,
      "min_confidence": 0.9,
      "max_body_chars": 500,
      "requires_target": false,
      "pool_k": 50,
      "admission": "verified"
    },
    "receipts": {
      "verified": true,
      "coverage": 0.9992572586090479,
      "precision": 0.777461876453864,
      "attribution_toward_share": 0.74
    },
    "accuracy": {
      "labeled": true,
      "drawn": 1000,
      "scored": 509,
      "rejected": 21,
      "seed": 11,
      "drawn_at": "2026-09-24",
      "rubric": "v1",
      "groups": {
        "first": {
          "size": 350,
          "weight": 0.35,
          "labeled": 350,
          "rejected": 14,
          "scored": 336,
          "sentiment_agreement": 0.8072,
          "target_agreement": 0.9848,
          "joint_agreement": 0.7917
        },
        "ordered": {
          "size": 629,
          "weight": 0.65,
          "labeled": 180,
          "rejected": 7,
          "scored": 173,
          "sentiment_agreement": 0.6182,
          "target_agreement": 0.932,
          "joint_agreement": 0.5896
        },
        "held_out": {
          "size": 21,
          "weight": 0.0,
          "labeled": 20,
          "rejected": 1,
          "scored": 19,
          "sentiment_agreement": 0.4737,
          "target_agreement": 1.0,
          "joint_agreement": 0.4737
        }
      },
      "sentiment_agreement": 0.6859,
      "sentiment_margin": 0.0502,
      "target_agreement": 0.954,
      "target_margin": 0.0291,
      "joint_agreement": 0.6603,
      "joint_margin": 0.0503,
      "by_class": {
        "neg": {
          "predicted": 194,
          "labeled": 188,
          "precision": 0.7088,
          "recall": 0.7818,
          "toward_precision": 0.7057
        },
        "neu": {
          "predicted": 164,
          "labeled": 142,
          "precision": 0.6128,
          "recall": 0.6651,
          "toward_precision": 0.6128
        },
        "pos": {
          "predicted": 151,
          "labeled": 179,
          "precision": 0.7549,
          "recall": 0.6182,
          "toward_precision": 0.7511
        }
      },
      "class_mix": {
        "neg": {
          "classifier": 0.3487,
          "manual": 0.3126,
          "gap": 0.0361,
          "gap_margin": 0.0464
        },
        "neu": {
          "classifier": 0.3691,
          "manual": 0.338,
          "gap": 0.0311,
          "gap_margin": 0.0563
        },
        "pos": {
          "classifier": 0.2822,
          "manual": 0.3494,
          "gap": -0.0672,
          "gap_margin": 0.051
        }
      },
      "context_share": 0.0707,
      "unsure_share": 0.0453,
      "reject_share": 0.0393
    },
    "floors": {
      "fanbase_min_n": 200,
      "week_min_n": 30,
      "belt_min_n": 300,
      "game_min_n": 20,
      "race_entry_min_n": 500,
      "room_min_n": 200
    },
    "recaps": {
      "room_bucket_seconds": 120,
      "room_bodies_per_bucket": 2,
      "anchor_window_seconds": 480,
      "anchor_min_reactions": 3,
      "anchor_vocabulary": {
        "block": "\\b(?:block|swat|reject|denied|erased|volleyball)",
        "steal": "\\b(?:steal|stole|swipe|pickpocket|pick(?:ed|s)? (?:his )?pocket|strip(?:ped|s)?\\b|jumped the (?:lane|pass))",
        "dunk": "\\b(?:dunk|slam|poster|flush|hammer|jam(?:med|s)?\\b|yam(?:med|s)?\\b|throw(?:s|n)? (?:it )?down)"
      },
      "reaction_lag": {
        "candidates": 29276,
        "anchors": 128,
        "games": 58,
        "median_offset_seconds": 64,
        "p25_offset_seconds": 44,
        "p75_offset_seconds": 88
      }
    },
    "metrics": {
      "neg_rate": "neg_count / comment_count",
      "pos_rate": "pos_count / comment_count",
      "net_sentiment": "(pos_count - neg_count) / comment_count",
      "polarization": "(pos_count + neg_count) / comment_count"
    }
  },
  "calendar": {
    "opening_night": "2025-10-21",
    "nba_cup_final": "2025-12-16",
    "christmas": "2025-12-25",
    "trade_deadline": "2026-02-05",
    "all_star_weekend": "2026-02-13",
    "all_star": "2026-02-15",
    "play_in_start": "2026-04-14",
    "play_in_end": "2026-04-17",
    "playoffs_start": "2026-04-18",
    "finals_start": "2026-06-03",
    "finals_end": "2026-06-13",
    "draft": "2026-06-23"
  },
  "corpus": {
    "raw_comments": 7283478,
    "population_submitted": 2110485,
    "classified": 2110479,
    "usable": 2059495,
    "attributed": 1787520
  },
  "populations": {
    "raw_comments": "every r/NBA comment downloaded for the season window",
    "population_submitted": "raw comments that mention a tracked player, as submitted to the sentiment classifier",
    "classified": "submitted comments with a classifier response: the rows of sentiment.parquet",
    "usable": "classified comments minus classifier errors",
    "attributed": "usable comments resolved to one tracked player",
    "flaired": "usable comments whose author carries a team flair, attributed or not",
    "attributed_flaired": "attributed comments whose author carries a team flair",
    "in_thread": "attributed comments posted in a game or post-game thread",
    "bridged": "attributed comments whose post the bridge holds",
    "live_thread": "usable comments posted in a game's live game threads, primary and split"
  },
  "tables": {
    "player_overall": {
      "file": "player_overall.parquet",
      "rows": 223,
      "population": "attributed"
    },
    "player_temporal": {
      "file": "player_temporal.parquet",
      "rows": 8711,
      "population": "attributed"
    },
    "player_fan_team": {
      "file": "player_fan_team.parquet",
      "rows": 6497,
      "population": "attributed_flaired"
    },
    "fan_team_overall": {
      "file": "fan_team_overall.parquet",
      "rows": 30,
      "population": "flaired"
    },
    "game_sentiment": {
      "file": "game_sentiment.parquet",
      "rows": 28516,
      "population": "in_thread"
    },
    "player_room": {
      "file": "player_room.parquet",
      "rows": 1885,
      "population": "bridged"
    },
    "room_temporal": {
      "file": "room_temporal.parquet",
      "rows": 347,
      "population": "bridged"
    },
    "players": {
      "file": "players.parquet",
      "rows": 223,
      "population": null
    },
    "teams": {
      "file": "teams.parquet",
      "rows": 30,
      "population": null
    },
    "games": {
      "file": "games.parquet",
      "rows": 1387,
      "population": null
    },
    "player_games": {
      "file": "player_games.parquet",
      "rows": 14657,
      "population": null
    },
    "posts": {
      "file": "posts.parquet",
      "rows": 6549,
      "population": null
    },
    "comment_samples": {
      "file": "comment_samples.parquet",
      "rows": 5964,
      "population": "attributed"
    },
    "corpus_daily": {
      "file": "corpus_daily.parquet",
      "rows": 273,
      "population": "attributed"
    },
    "method_examples": {
      "file": "method_examples.parquet",
      "rows": 17,
      "population": null
    }
  },
  "recaps": {
    "0042500404-de-aaron-fox": {
      "file": "recaps/0042500404-de-aaron-fox.json",
      "rows": 14846,
      "game_id": "0042500404",
      "attributed_player": "De'Aaron Fox",
      "player_id": 1628368,
      "slug": "de-aaron-fox",
      "live_n": 1786,
      "room_n": 65137,
      "by_period": {
        "1": {
          "neg": 35,
          "pos": 11,
          "neu": 22
        },
        "2": {
          "neg": 35,
          "pos": 48,
          "neu": 20
        },
        "3": {
          "neg": 307,
          "pos": 32,
          "neu": 65
        },
        "4": {
          "neg": 963,
          "pos": 61,
          "neu": 186
        }
      },
      "swing": 0.28116188624210015,
      "minutes_diff": 0,
      "population": "live_thread"
    },
    "0042500317-chet-holmgren": {
      "file": "recaps/0042500317-chet-holmgren.json",
      "rows": 15473,
      "game_id": "0042500317",
      "attributed_player": "Chet Holmgren",
      "player_id": 1631096,
      "slug": "chet-holmgren",
      "live_n": 2166,
      "room_n": 47934,
      "by_period": {
        "1": {
          "neg": 92,
          "pos": 7,
          "neu": 12
        },
        "2": {
          "neg": 151,
          "pos": 18,
          "neu": 58
        },
        "3": {
          "neg": 152,
          "pos": 15,
          "neu": 27
        },
        "4": {
          "neg": 1070,
          "pos": 120,
          "neu": 264
        }
      },
      "swing": -0.09292786596775593,
      "minutes_diff": 0,
      "population": "live_thread"
    },
    "0042500405-victor-wembanyama": {
      "file": "recaps/0042500405-victor-wembanyama.json",
      "rows": 17294,
      "game_id": "0042500405",
      "attributed_player": "Victor Wembanyama",
      "player_id": 1641705,
      "slug": "victor-wembanyama",
      "live_n": 4539,
      "room_n": 49230,
      "by_period": {
        "1": {
          "neg": 78,
          "pos": 104,
          "neu": 91
        },
        "2": {
          "neg": 217,
          "pos": 156,
          "neu": 262
        },
        "3": {
          "neg": 907,
          "pos": 278,
          "neu": 614
        },
        "4": {
          "neg": 985,
          "pos": 194,
          "neu": 460
        }
      },
      "swing": 0.3152619192887649,
      "minutes_diff": 0,
      "population": "live_thread"
    },
    "0042500402-karl-anthony-towns": {
      "file": "recaps/0042500402-karl-anthony-towns.json",
      "rows": 14671,
      "game_id": "0042500402",
      "attributed_player": "Karl-Anthony Towns",
      "player_id": 1626157,
      "slug": "karl-anthony-towns",
      "live_n": 2124,
      "room_n": 49282,
      "by_period": {
        "1": {
          "neg": 42,
          "pos": 26,
          "neu": 41
        },
        "2": {
          "neg": 146,
          "pos": 720,
          "neu": 125
        },
        "3": {
          "neg": 355,
          "pos": 160,
          "neu": 181
        },
        "4": {
          "neg": 81,
          "pos": 80,
          "neu": 81
        }
      },
      "swing": -0.050610357115778326,
      "minutes_diff": 0,
      "population": "live_thread"
    },
    "0042500312-stephon-castle": {
      "file": "recaps/0042500312-stephon-castle.json",
      "rows": 11232,
      "game_id": "0042500312",
      "attributed_player": "Stephon Castle",
      "player_id": 1642264,
      "slug": "stephon-castle",
      "live_n": 1606,
      "room_n": 32187,
      "by_period": {
        "1": {
          "neg": 14,
          "pos": 116,
          "neu": 38
        },
        "2": {
          "neg": 183,
          "pos": 206,
          "neu": 142
        },
        "3": {
          "neg": 112,
          "pos": 16,
          "neu": 40
        },
        "4": {
          "neg": 447,
          "pos": 77,
          "neu": 205
        }
      },
      "swing": 0.529835390946502,
      "minutes_diff": 0,
      "population": "live_thread"
    },
    "0042500311-dylan-harper": {
      "file": "recaps/0042500311-dylan-harper.json",
      "rows": 17334,
      "game_id": "0042500311",
      "attributed_player": "Dylan Harper",
      "player_id": 1642844,
      "slug": "dylan-harper",
      "live_n": 840,
      "room_n": 48213,
      "by_period": {
        "1": {
          "neg": 5,
          "pos": 25,
          "neu": 19
        },
        "2": {
          "neg": 9,
          "pos": 22,
          "neu": 16
        },
        "3": {
          "neg": 9,
          "pos": 118,
          "neu": 28
        },
        "4": {
          "neg": 51,
          "pos": 231,
          "neu": 82
        },
        "5": {
          "neg": 14,
          "pos": 1,
          "neu": 13
        },
        "6": {
          "neg": 49,
          "pos": 82,
          "neu": 40
        }
      },
      "swing": 0.18450889127580855,
      "minutes_diff": 0,
      "population": "live_thread"
    },
    "0042500301-jalen-brunson": {
      "file": "recaps/0042500301-jalen-brunson.json",
      "rows": 5036,
      "game_id": "0042500301",
      "attributed_player": "Jalen Brunson",
      "player_id": 1628973,
      "slug": "jalen-brunson",
      "live_n": 696,
      "room_n": 17029,
      "by_period": {
        "1": {
          "neg": 13,
          "pos": 10,
          "neu": 15
        },
        "2": {
          "neg": 11,
          "pos": 5,
          "neu": 17
        },
        "3": {
          "neg": 130,
          "pos": 11,
          "neu": 37
        },
        "4": {
          "neg": 52,
          "pos": 140,
          "neu": 43
        },
        "5": {
          "neg": 22,
          "pos": 68,
          "neu": 24
        }
      },
      "swing": -0.14912280701754388,
      "minutes_diff": 0,
      "population": "live_thread"
    },
    "0042500173-lebron-james": {
      "file": "recaps/0042500173-lebron-james.json",
      "rows": 3781,
      "game_id": "0042500173",
      "attributed_player": "LeBron James",
      "player_id": 2544,
      "slug": "lebron-james",
      "live_n": 1174,
      "room_n": 10632,
      "by_period": {
        "1": {
          "neg": 15,
          "pos": 8,
          "neu": 7
        },
        "2": {
          "neg": 42,
          "pos": 91,
          "neu": 30
        },
        "3": {
          "neg": 20,
          "pos": 15,
          "neu": 11
        },
        "4": {
          "neg": 227,
          "pos": 235,
          "neu": 116
        },
        "5": {
          "neg": 85,
          "pos": 145,
          "neu": 65
        }
      },
      "swing": -0.211864406779661,
      "minutes_diff": 0,
      "population": "live_thread"
    },
    "0042500164-nikola-jokic": {
      "file": "recaps/0042500164-nikola-jokic.json",
      "rows": 3741,
      "game_id": "0042500164",
      "attributed_player": "Nikola Jokic",
      "player_id": 203999,
      "slug": "nikola-jokic",
      "live_n": 1424,
      "room_n": 12661,
      "by_period": {
        "1": {
          "neg": 21,
          "pos": 22,
          "neu": 14
        },
        "2": {
          "neg": 41,
          "pos": 20,
          "neu": 26
        },
        "3": {
          "neg": 146,
          "pos": 7,
          "neu": 39
        },
        "4": {
          "neg": 713,
          "pos": 64,
          "neu": 136
        }
      },
      "swing": 0.4125208969850695,
      "minutes_diff": 0,
      "population": "live_thread"
    },
    "0022500001-kevin-durant": {
      "file": "recaps/0022500001-kevin-durant.json",
      "rows": 6580,
      "game_id": "0022500001",
      "attributed_player": "Kevin Durant",
      "player_id": 201142,
      "slug": "kevin-durant",
      "live_n": 1323,
      "room_n": 18482,
      "by_period": {
        "1": {
          "neg": 38,
          "pos": 34,
          "neu": 36
        },
        "2": {
          "neg": 25,
          "pos": 80,
          "neu": 29
        },
        "3": {
          "neg": 21,
          "pos": 15,
          "neu": 19
        },
        "4": {
          "neg": 80,
          "pos": 52,
          "neu": 61
        },
        "5": {
          "neg": 199,
          "pos": 36,
          "neu": 96
        },
        "6": {
          "neg": 188,
          "pos": 75,
          "neu": 103
        }
      },
      "swing": 0.1618093503339405,
      "minutes_diff": 0,
      "population": "live_thread"
    }
  }
}
