{
  "source_count": 7,
  "ready_for_live_count": 7,
  "all_ready_for_live": true,
  "sources": [
    {
      "source_key": "schedule",
      "source_label": "Game Metadata",
      "live_adapter_count": 1,
      "fixture_adapter_count": 1,
      "live_adapter_names": [
        "nflreadpy_schedule"
      ],
      "live_provider_ids": [
        "nflverse_nflreadpy"
      ],
      "fixture_adapter_names": [
        "fixture_slate"
      ],
      "normalizer_available": true,
      "provider_sample_ready": true,
      "provider_sample_files": [
        "nflverse_schedule_sample.json"
      ],
      "provider_sample_record_count": 1,
      "ready_for_live": true,
      "notes": "Live V1 adapter boundary is provider-specific but no-call until approvals, config, and quota gates pass."
    },
    {
      "source_key": "odds",
      "source_label": "Market Lines",
      "live_adapter_count": 1,
      "fixture_adapter_count": 0,
      "live_adapter_names": [
        "the_odds_api_nfl"
      ],
      "live_provider_ids": [
        "the_odds_api"
      ],
      "fixture_adapter_names": [],
      "normalizer_available": true,
      "provider_sample_ready": true,
      "provider_sample_files": [
        "the_odds_api_nfl_sample.json"
      ],
      "provider_sample_record_count": 2,
      "ready_for_live": true,
      "notes": "Live V1 adapter boundary is provider-specific but no-call until approvals, config, and quota gates pass."
    },
    {
      "source_key": "usage",
      "source_label": "Usage and Role",
      "live_adapter_count": 1,
      "fixture_adapter_count": 0,
      "live_adapter_names": [
        "nflreadpy_usage"
      ],
      "live_provider_ids": [
        "nflverse_nflreadpy"
      ],
      "fixture_adapter_names": [],
      "normalizer_available": true,
      "provider_sample_ready": true,
      "provider_sample_files": [
        "nflverse_usage_sample.json"
      ],
      "provider_sample_record_count": 1,
      "ready_for_live": true,
      "notes": "Live V1 adapter boundary is provider-specific but no-call until approvals, config, and quota gates pass."
    },
    {
      "source_key": "injuries",
      "source_label": "Injuries and Inactives",
      "live_adapter_count": 1,
      "fixture_adapter_count": 0,
      "live_adapter_names": [
        "manual_csv_injury_inactives"
      ],
      "live_provider_ids": [
        "manual_csv_overrides"
      ],
      "fixture_adapter_names": [],
      "normalizer_available": true,
      "provider_sample_ready": true,
      "provider_sample_files": [
        "manual_csv_injuries_sample.json"
      ],
      "provider_sample_record_count": 1,
      "ready_for_live": true,
      "notes": "Live V1 adapter boundary is provider-specific but no-call until approvals, config, and quota gates pass."
    },
    {
      "source_key": "team_context",
      "source_label": "Team Context",
      "live_adapter_count": 1,
      "fixture_adapter_count": 0,
      "live_adapter_names": [
        "derived_team_context"
      ],
      "live_provider_ids": [
        "derived_nflverse_odds"
      ],
      "fixture_adapter_names": [],
      "normalizer_available": true,
      "provider_sample_ready": true,
      "provider_sample_files": [
        "derived_team_context_sample.json"
      ],
      "provider_sample_record_count": 1,
      "ready_for_live": true,
      "notes": "Live V1 adapter boundary is provider-specific but no-call until approvals, config, and quota gates pass."
    },
    {
      "source_key": "matchup",
      "source_label": "Defensive Matchup",
      "live_adapter_count": 1,
      "fixture_adapter_count": 0,
      "live_adapter_names": [
        "nflreadpy_matchup"
      ],
      "live_provider_ids": [
        "nflverse_nflreadpy"
      ],
      "fixture_adapter_names": [],
      "normalizer_available": true,
      "provider_sample_ready": true,
      "provider_sample_files": [
        "nflverse_matchup_sample.json"
      ],
      "provider_sample_record_count": 1,
      "ready_for_live": true,
      "notes": "Live V1 adapter boundary is provider-specific but no-call until approvals, config, and quota gates pass."
    },
    {
      "source_key": "weather",
      "source_label": "Weather",
      "live_adapter_count": 1,
      "fixture_adapter_count": 0,
      "live_adapter_names": [
        "open_meteo_weather"
      ],
      "live_provider_ids": [
        "open_meteo"
      ],
      "fixture_adapter_names": [],
      "normalizer_available": true,
      "provider_sample_ready": true,
      "provider_sample_files": [
        "open_meteo_weather_sample.json"
      ],
      "provider_sample_record_count": 1,
      "ready_for_live": true,
      "notes": "Live V1 adapter boundary is provider-specific but no-call until approvals, config, and quota gates pass."
    }
  ]
}