# Exports

This directory contains generated research and model outputs that are useful
for review or downstream consumption.

| Artifact | Producer |
| --- | --- |
| `sample_week_predictions.json` | `uv run python -m cfb_model_lab.export` |
| `sp_plus_vs_epa_2026.png` | `uv run python analysis/plot_sp_vs_epa.py` |
| `season_previews_2026/` | `./scripts/build_season_previews.sh` |
| `epa_prior_20260914/` | `uv run python -m analysis.evaluate_epa_prior` and `uv run python -m analysis.build_epa_prior_shadow` |
| `sp_plus_card_audit_20260908.csv` and `.json` | `python3 analysis/sp_plus_card_audit.py [predictive-table.tsv]` |

## Picks ledger

### Current card audit

The reproducible runtime payload is `picks_latest.json`. Audit it without
refreshing data or overwriting the payload:

```bash
uv run python analysis/audit_picks.py exports/picks_latest.json \
  --output exports/picks_audit_20260909
```

The September 9 payload is a 2026 Week 2 `preseason_sp_plus` run. It contains
49 projected games, 26 picks at the 3.0-point edge threshold, and 23 games
below the threshold. The count is therefore a threshold result, not a target
of 25. Its 2025 bucket table is a cover backtest, not a win-probability
calibration; the 7-14 bucket attached to several picks has a 43.56% historical
hit rate. The audit passes the edge arithmetic and preserves the payload hash.

The separate `sp_plus_card_audit_20260908` artifact is a 25-game, user-supplied
card comparison. It is not the runtime pick payload and cannot establish that
the runtime generated 25 picks.

### Branch disposition (September 9, 2026)

The exact local and `origin` refs are captured in
`research_branch_inventory_20260909.json`; regenerate it with:

```bash
uv run python analysis/research_branch_inventory.py \
  --output exports/research_branch_inventory_20260909.json
```

`master` includes the direct external forecast research and pick audit from
`codex/external-prediction-sources`. `codex/sp-plus-card-research` is already
merged into master and its CSV audits remain comparison artifacts. The
`codex/current-team-rankings` work is merged into master. The
`codex/merge-outstanding-branches` pointer contains the same merged history,
including the scoreboard evidence fixture. The remote refresh, publish, and
week-one branches contain operational or dashboard updates already represented
in the merged history; they do not independently validate the pick model.
The `cursor/*`, `hermes/*`, `fix/*`, and `scoreboard/*` branches remain
reviewable source history. All local and fetched remote branch tips are
ancestors of the merged `master`. Uncommitted worktree edits remain separate,
and no branch was deleted. External ratings and SP+ comparisons stay research inputs until a
chronological evaluation clears the promotion gate documented in README.

`picks_ledger.csv` is generated operational data, kept separate from code
changes. The first tracked snapshot preserves an existing local file with
10 records for 2026 Week 1, all carrying the settlement timestamp
`2026-09-08T17:09:16.459276+00:00`. It was not regenerated when committed.
The exact source captures and command that produced those entries have not
been verified; tracking the file does not certify its results.

The supported settlement command is
`uv run python -m cfb_model_lab.picks settle <season> <week>`.
Preserve the original week's picks before running it. See
[`docs/operations/college-football-refresh.md`](../docs/operations/college-football-refresh.md).

## September 8 SP+ card comparison

The [25-game comparison](sp_plus_card_audit_20260908.csv) uses the user's
original rounded spread card and the predictive SP+ table they supplied on
September 8. The [metadata](sp_plus_card_audit_20260908.json) records source,
input hash, formula, and limitations. With 2.5 points of home field, 14 picks
retain positive rating-based edges and 11 reverse direction. These are
research comparisons, not official Connelly game picks, cover probabilities,
or confirmed professional wagers.

The calculation is `home_rating - away_rating + 2.5` for expected Home Margin.
For the original picked team, estimated margin plus its quoted spread is the
new edge. Positive values favor that original pick. Each CSV row retains
the two ratings and original line, so its arithmetic can be checked without
the raw ESPN table. Rebuilding from the source requires the locally retained
paste or supplying its path explicitly; it needs only Python's standard library.

The largest disagreements with the quoted lines favor Buffalo, Jacksonville
State, and UTSA at +9.7 points each, followed by UNLV at +9.5. The largest
reversals are Auburn -9.1, Clemson -7.0, ECU -5.9, and Ole Miss -5.7.
These differences warrant checking source freshness, canonical team mapping,
and actual available prices. They are not evidence that those gaps can be bet.

The original card's decimal spreads may be median book quotes rounded for
display. The engine computes median provider spreads; a median need not be
an executable sportsbook price. The original card's exact source snapshot
has not been matched, so the audit preserves its displayed numbers.

The pick engine's early-season SP+ fallback attaches historical bucket rates
from its 2025 in-season EPA margin backtest. Those rates are not calibrated
probabilities for this SP+ comparison. Comparing refreshed SP+ ratings with
picks already based on SP+ is also not independent model confirmation.

The existing [line-drift study](../analysis/output/line_drift_study.md) found
1,669 wins in 3,306 graded bets following drift at the archived final number,
or 50.48%. It used retrospective captures and is not a prospective execution
test. Its opening-price diagnostic uses future movement and must not be
presented as an executable strategy. This audit does not promote any model,
change the ledger, refresh odds, or deploy dashboard data.

## September 8 external forecasts and market quotes

Run `python3 analysis/tracker_card_comparison.py` to reproduce the
[Tracker comparison](tracker_card_comparison_20260908.csv). It retains manually
transcribed system average and median home-margin forecasts from
[The Prediction Tracker](https://www.thepredictiontracker.com/predncaa.html),
whose displayed update was September 8, 2026, 12:11 PM (timezone unspecified).
The downloadable CSV returned HTTP 403; this is a bounded transcription of
25 matchups, not an automated feed. Positive home margins mean home favorites.

At the original displayed spreads, nine picks have positive edges under SP+,
Tracker average, and Tracker median; five have negative edges under all three;
eleven are mixed. Positive: Buffalo, Ohio State, Hawaii, Bowling Green,
Vanderbilt, Louisiana Tech, Rutgers, Minnesota, UTSA. Negative: Marshall,
Fresno State, Auburn, Ole Miss, Missouri. Average and median summarize overlapping
systems, so these are not three independent votes or calibrated probabilities.

Run `python3 analysis/card_market_audit.py` to reproduce the
[50 provider quotes for all 25 games](card_market_audit_20260908.csv) using the
[retained CFBD response](../data/external/cfbd_20260908_research/lines_week2.json)
and [capture metadata](../data/external/cfbd_20260908_research/metadata.json).
The authenticated request returned 86 Week 2 games. Rows retain game IDs,
start times, providers, opening and captured spreads, and recalculated forecast
edges at each provider's number. These are CFBD-reported quotes; the response
has no spread juice or provider quote timestamp to verify execution.

`movement_toward_pick = opening_pick_spread - captured_pick_spread`: positive
means the picked team became more favored. UNLV moved from -6.5 to -3.5 at
DraftKings, against the original pick; Tracker also opposes UNLV while SP+
supports it. Auburn moved from -29.5 to -33.5, toward the original pick, but
all three forecasts oppose Auburn at the captured price. Buffalo's quotes
were unchanged and all three forecasts support it. Movement and value at the
new price answer different questions. Neither establishes who placed bets.

## September 9 Week 2 refresh

`picks_refresh_audit_20260909/` preserves the September 9, 20:26 UTC
payload and its arithmetic and selection audit: 49 games, 26 picks, and
no audit errors. Reproduce with `python -m analysis.audit_picks
exports/picks_latest.json --output exports/picks_refresh_audit_20260909`.
The projection basis remains `preseason_sp_plus`; historical EPA bucket
rates are not calibrated probabilities for this early-season model.

The local `external_predictions_refresh_20260909/` and
`external_predictions_direct_refresh_20260909/` directories contain fresh
Tracker and direct-provider comparisons against that saved pick payload.
Tracker supplied 1,916 forecasts across 49 matched games. The direct import
retained 2,020 team-rating rows and produced 2,187 combined forecasts across
the 86-game provider schedule. Coverage varies by system.

Immutable captures are under
`data/external/prediction_tracker/20260909T202722841822Z` and
`data/external/direct_ratings/20260909T202744022757Z`. Each output directory
retains provenance and exact schedule and model inputs for the README's
offline replay commands. These ignored local captures remain research inputs;
production model weights and historical evaluations are unchanged.

## Season previews

`season_previews_2026/<team_slug>/` holds a three-artifact set per FBS team: the
payload JSON (every figure in the report), the rendered HTML, and a 5-page
Letter PDF. `season_previews_2026/manifest.json` is the run record — it lists
per-team status, expected wins, warnings, and any failure reason.
`season_previews_2026/index.html` plus one page per conference make the run
browsable; those pages are built from the manifest and payloads, so they cannot
link to a report that does not exist.

The pipeline is deterministic and reads only committed snapshots
(`data/external/cfbd_2026/`, `data/external/connelly_*_2026/`), so it needs no
live API call and no model reasoning. Data assembly
(`analysis/season_preview_data.py`) is separated from rendering
(`analysis/season_preview_report.py`) so a figure on the page always traces back
to the stored payload.

Regenerate everything with `./scripts/build_season_previews.sh`, a subset with
`./scripts/build_season_previews.sh "Michigan State" "Louisville"`, or skip PDF
rendering with `FAST=1`. A weekly `no_agent` cron job runs the same script and
reports only teams whose projection moved.

Keep reproducible outputs here rather than in the repository root. When the
generating command is unknown, preserve the artifact in a descriptive
subdirectory and add a short provenance note instead of guessing.

`public/` is a separate lane: it contains the deploy-ready static dashboard
snapshot generated by `uv run python scripts/build_static.py`.
