Snapcount · the deck · 18 slides · spring 2026 archive — current numbers live at /proof.html

The multi-agent engine
for NFL prediction.

Greenfield from PRD intent. Walk-forward verified. 2025 quarantined. Built by four AI agents and one human in twenty-four hours of working time.

Press SPACE to advance · ESC for overview
01 · The claim

We don't predict
football. We orchestrate it.

A prediction is not a single number from a single model. It's the output of four cooperating systems running on 484,254 plays of NFL data, gated by anti-leakage tests, audited by an independent LLM, and bound to a freshness contract before it reaches production.

02 · The problem

Most NFL models are quietly broken.

  • Walk-forward CV is rare. Random k-fold leaks future games into training folds and inflates accuracy.
  • Participation columns (was_pressure, route, defense_coverage_type) are FTN end-of-season backfill — never available live, but routinely used as features.
  • "Quarantined holdout" usually means "we showed the model the holdout while tuning."
  • TD predictions go negative under squared-error regression and nobody notices because MAE is small.
  • The validation harness self-approves. There's no independent reviewer.

Snapcount fixes all five at the data layer, not the model layer.

03 · Snapcount in one sentence

Snapcount turns nflverse data into per-player projections, calibrated correlations, and explanations you can read in plain English.

27
nflverse sources
2016 → 2025
484K
plays analyzed
372 cols deep
8
player targets
baselined
81/81
tests
passing
9
codex audit rounds
passed
04 · Product surface · Four agents, one stack

Four products. One feedback loop.

01 / SNAPSCORE

SnapScore

XGBoost on a walk-forward harness. Per-player projections for 8 fantasy targets. Holdout 2025 quarantined.

02 / SNAPFORM

SnapForm

Closed-form formulas for live signals. Injury decay, weather penalties, snap-share trajectories. Adam-owned.

03 / SNAPPRO

SnapPro

API + correlation matrix. Underwrites parlays, lineups, prop combos. TB12-owned.

04 / SNAPCALL

SnapCall

Domain LLM. /explain, /reason, /simulate. Trained on SnapScore SHAP traces.

SnapScore learns from history. SnapForm adjusts for the present. SnapPro turns predictions into decisions. SnapCall explains why.

05 · The pipeline · Six stages, idempotent

Ingest → Validate → Freeze → Features → Harness → Models

01 / INGEST

nflreadpy

Pull 27 sources for 2016 → current season. Auto-derives season range from today.

02 / VALIDATE

3-layer

Schema drift, coverage invariants, in-season currency. Hard-fails on regression.

03 / FREEZE

Two-tier slice

Predicate filtering carves validation (2024 wks 9+) and holdout (2025).

04 / FEATURES

Layer 0 + 1

Id-keys + lagged player-game features. M3 adds Layers 2/3/4.

05 / HARNESS

Walk-forward CV

Predict (S, W) from (season < S OR week < W). 17 boundary tests.

06 / MODELS

Ridge → XGB

Same harness, plug-in models. Target-aware loss.

Every stage idempotent. Every stage refuses to start if upstream stage failed.

06 · Source taxonomy

Four schema kinds. One filter rule each.

KindDefining traitFilter rule
A · Season + Weekseason + week, no game_idseason == X AND (week ≥ min_week OR week IS NULL)
B · Season onlyseason, no week (annual snapshot)season == X
C · Game-keyednflverse_game_id is authoritativenflverse_game_id IN slice.game_ids
D · Timestamp-keyeddt ISO8601 (2025+ depth charts)dt ∈ [Aug 1 of X, Mar 1 of X+1)
Z · All-timeno season key (reference tables)read whole; not slice-able

The fix that took 5 codex rounds: the original code built a (season, week) pair set from PBP and inner-joined every Kind A source. PBP 2025 stops at week 22, but NGS has week 0 (preseason) + week 23 (post-SB). Those rows escaped the filter and risked leaking. Predicate-based filtering catches them.

07 · Two-tier eval

Validation drives the loop. Holdout opens the gate.

Validation · loop reads every iteration

2024 weeks 9+

Drives the AutoResearch loop's keep-or-revert decision. 14 walk-forward folds across wks 9-22. Per fold the model trains on everything strictly earlier.

data/validation_2024_w9plus/ · 162 games · 28,198 PBP rows

Holdout · ship-gate ONLY · NEVER in loop

2025 entire season

The sacred ship-gate. Belt + suspenders: run_baseline.py drops 2025 BEFORE the harness; walk_forward_splits filters again; holdout_seasons enforced by both split flavors.

data/holdout_2025/ · 285 games · 48,771 PBP rows · 517,851 depth-chart events

08 · Walk-forward harness

The contract: predict at (S, W) reads only data from before (S, W).

Every row in the train fold satisfies (season < S) OR (season == S AND week < W). Imputer + scaler fit per fold; no global statistics leak across folds. 17 boundary tests pin this contract via synthetic frames.

  • train never contains target week · pinned
  • train never contains future seasons · pinned
  • train never contains future weeks of same season · pinned
  • holdout_seasons excluded from train AND predict · pinned
  • leakage gate fires at split-time before any fit · pinned
  • train sizes monotonically grow fold-over-fold · pinned
09 · Live vs training surface

Some columns are training-only. The validator enforces it.

ALLOWED LIVE

Released ≤ 24h post-game or known pre-kickoff

avg_time_to_throw
aggressiveness
CPOE
avg_separation
RYOE
avg_yac_above_expectation
pfr_advstats_week_*
schedules + Vegas
pbp pre-kickoff
player_stats lagged
snap_counts lagged
rosters_weekly
FORBIDDEN LIVE · participation backfill

Three block-list surfaces

was_pressure
route
defense_coverage_type
defense_man_zone_type
ngs_air_yards
time_to_throw (per-play)
n_pass_rushers
n_offense / n_defense
defenders_in_box
offense_personnel
defense_personnel
offense_formation
epa / wpa / qb_epa
yards_gained / play_type
complete_pass / fumble
temp / wind
head_official
series_result
fixed_drive_result

@realfrankbrank 2025-09-02: "we will backfill each year at the end of the regular season." 2025 lands ~Feb 2026 post-Super-Bowl.

10 · M4 baseline · honest unfiltered cohort

Numbers, not narratives.

Position × TargetnM1 Ridge
(lagged)
M3 XGB
(+EPA/NGS)
M4 XGBM1→M4 Δ
QB × passing_yards39567.0551.7551.35−23.4%
QB × passing_tds3950.860.780.78−9.3%
RB × rushing_yards90619.7915.0314.99−24.3%
RB × rushing_tds9060.340.310.31−9.7%
WR × receiving_yards1,45720.9217.1317.10−18.3%
WR × receiving_tds1,4570.320.310.31−5.0%
TE × receiving_yards73415.3912.3912.49−18.8%
TE × receiving_tds7340.270.260.25−6.7%

14 walk-forward folds across 2024 wks 9-22. XGB target-aware: reg:squarederror for yards, count:poisson for TDs. M4 = M3 + Layer 5 player attrs.

11 · The lesson
Both models were squeezing the same juice. With 19 features (lagged versions of six source columns), there was almost no non-linear interaction for trees to exploit. The bottleneck wasn't model class. It was feature surface.— Internal post-M2 review

M3 adds opponent quality (defensive EPA allowed), Vegas implied team totals, NGS weekly aggregates (separation, RYOE, CPOE, avg_time_to_throw), and Adam's live injury feed. Then XGB pulls ahead substantially.

12 · Roadmap · Tagged in git, dated to the day

Greenfield to baseline in 24 hours.

M0
Data layer
27 sources · 3-layer validator · two-tier eval.
M1
Eval harness
Walk-forward CV · anti-leakage · Ridge baseline.
M2
XGBoost
Same harness · target-aware loss · tiny gain vs Ridge.
M3
EPA+NGS+opp
Layer 2/3/4 features · XGB pulls ahead 17-25%.
M4
Player attrs
+ SnapForm v1
Static player feats + injury/weather/form formulas.
M5
Ensembles +
embeddings
Linear+tree ensemble · QB/team/coach embeddings.
M_serve
Live snapshot
Point-in-time API · max-staleness per source.
M_inf
Spatiotemporal
Big Data Bowl tracking · GNN/RNN · keep iff harness improves.
13 · Engineering principles

The boring stuff that makes the predictions trustworthy.

  • Anti-leakage at split-time. Validator runs before any fit. 16 tests pin the block list against the actual participation.parquet schema.
  • Schema-drift validator. Every ingest diffs against a committed baseline. Bad nflverse releases can't slip through to modeling.
  • Walk-forward correctness. Fresh imputer + scaler per fold. No global statistics leak. 17 boundary tests.
  • Independent codex audits. Every milestone reviewed by a different LLM with adversarial intent. CRITICAL/HIGH closed before tag.
  • Tagged commits. m0-complete · m1-codex-pass · m2-xgboost · m3-codex-pass · m4-features. Reproducible from any tag.
  • The modeling lane doesn't self-approve. Ever.
14 · Live snapshot contract · M_serve scope

Per-source max-staleness, enforced at predict time.

Pre-kickoff inputs (current injuries, depth charts, Vegas lines, weather forecast, inactives) are moving targets. Every prediction binds to a single (target_game_id, as_of_ts) tuple.

SourceProvidermax_staleness
injuriesAdam's ESPN/PFR scrape4h
depth_chartsnflverse depth_charts_timestamped24h
vegas_linesSportsbook API1h
weather_forecastNWS / Tomorrow.io6h
inactivesNFL inactives feed (T-90min)1.5h
pbp_lagged / ngs_laggednflverse48h

A snapshot is valid iff every source's actual_staleness ≤ max_staleness. Otherwise POST /api/snapscore/predict returns 503.

15 · Independent review · Codex audit rounds

Nine rounds. Thirty-plus findings. Zero shipped without resolution.

M0 · 5 rounds

Data layer

CRITICAL: pair-set leak (NGS wk 0/23 + officials wk 23). HIGH: stale manifest, missing schema validator. All closed.

M1 · 1 round

Eval harness

CRITICAL: leakage block-list excluded play_id + nflverse_game_id. HIGH: label-based selection bias. Closed.

M2 · 1 round (PASS)

XGBoost

Verified: target dispatch, fold isolation, Poisson non-negativity, no silent train-mean. PASS gate.

M3 · 2 rounds (PASS)

Features

CRITICAL: NGS wk=0 same-season aggregate leak (caught a 24% MAE inflation). All closed. Layer tests added.

The modeling lane doesn't self-approve. Every milestone gets reviewed by a different LLM (OpenAI codex) with adversarial intent. Every CRITICAL/HIGH finding closes before tag. Process is the moat.

16 · One number
24h
Greenfield → tagged baseline · M0 + M1 + M2

Three milestones. Five codex review rounds. A working harness that recorded the first projection_error on all 8 player-level targets. Independent audits at every tag.

Multi-agent orchestration at full velocity, with no broken windows.

17 · What's next

Snapcount is shipping.

M3 unlocks the feature surface. M_serve formalizes the live-snapshot contract. M_inf adds spatiotemporal once Big Data Bowl lands. Production prediction is the back half of 2026.

snapcount.ai · multi-agent NFL prediction · greenfield 2026 · m4-features · 81/81 tests · 9 codex rounds