results.ats_correct / ou_correct (our side fixed pre-kickoff, closing line, pushes excluded); Record page "Against the spread and the total" with the 52.4% break-even line and a by-week table. Picks table shows our spread and total.lab.ga4_id in config (empty = off); shared header carries the tag.python -m niftilab.web submissions on the server); Local section "coming soon" (police-log card removed); /sitemap.xml, /sitemap-index.xml, /robots.txt; Contact in the header and footers.summarise → summarize._labhead.html) owned by niftiLab and copied in by scripts/sync_header.py; lab: in config.yml holds the links./sports/ and /local/, an /about page, hover on cards, same header.lab.niftiiq.com/sports/nfl): ProxyFix reads X-Forwarded-Prefix, so every link is prefixed automatically; the tunnel on 127.0.0.1:8400 still works at the root. Verified through a real nginx with the shipped site file.lab: — name, tabs, which tab this app is)./api/summary: one-card JSON (record, picks stored, next week) for the Lab landing page.niftiLab (separate folder /opt/niftiLab, port 8500) — landing page, nginx site with one location per project, scripts/install.sh. D-017.news_items (RSS: PFT, CBS, ESPN), game_weather (NWS at kickoff, outdoor stadiums), claims (typed, confidence, signed points, source link, graded). One language-model call per game only when there is new news; strict schema; "already counted" list keeps it from double-counting injuries and named QBs.home_win_prob_model (untouched) and analyst_adj; the adjusted probability is the pick of record; results store model_pick_correct beside pick_correct.news, analyst [--test|--force|--notes FILE --game ID], claims [--week]; weekly = fetch → grade → news → analyst → predict → markets → ratings → project.analyst: block (mode api|manual|off, key_file, model auto, caps, feeds).odds_snapshots table; every run stores one row per game per source for games in the next 8 days — nflverse line (benchmark of record), Polymarket moneyline price + best-liquidity spread (public Gamma API, slug nfl-{away}-{home}-{utc date} with search fallback), ESPN scoreboard line (cdn.espn.com, provider as named). All free, no keys. Every fetch is isolated; a dead source is logged, never fatal.python -m niftinfl markets (manual snapshot); weekly now runs fetch → grade → predict → markets → ratings → project.scripts/probe_sources.py / probe_sources2.py (what answered from the VPS: Polymarket, ESPN cdn scoreboard, NWS weather, ESPN/PFT/CBS RSS; blocked: ESPN site.api, DraftKings; dead: NBC edge RSS, NFL.com feed).injuries and starters tables loaded from nflverse injury reports and depth charts (weekly format ≤2024, dated snapshots 2025+), refreshed every run. New feature d_missing = position-weighted listed starters Out/Doubtful, away minus home (QB excluded — it has its own feature). Factor group "Injuries" in the why-line: "BAL missing 2 starters (+2)".fetch and seed now also pull injuries + depth charts; status shows their row counts.games, team_game, qb_game (idempotent upserts; seed for history, fetch for routine refresh).data/backtest_latest.json for the dashboard. Leak audit PASS.scripts/install_step1.sh, install_step2.sh, systemd niftinfl-web, niftinfl-weekly (+timer), nginx template (opt-in).