diff --git a/specs/wiring-data-train.md b/specs/wiring-data-train.md
index ed9ece9..52b68a2 100644
--- a/specs/wiring-data-train.md
+++ b/specs/wiring-data-train.md
@@ -106,6 +106,18 @@ Weave in essentially everything from the mockup across all surfaces (see referen
---
+## WAVE 2 BUILD PLAN (LOCKED — de-risk findings)
+The `(league,id)`→URL resolver (`web/src/lib/playerHeadshot.ts` `getHeadshotUrl`) + `PlayerAvatar` (headshot-or-monogram via `
`) **already exist and are correct**. PropLine props carry NO id → the id can ONLY come from the **stats resolve the snapshot already runs per player** (`snapshotService.js:311`) = Addition 1's intent exactly. **Store `playerId`+`espnId` on the `enriched` grade objects at `snapshotService.js:331-336`** (beside `archetype`/`team`) → flows free to `grades:{sport}` → `buildPlayerStripsFromProps` → `StatStrip` `playerId`. Zero new Redis key, zero new I/O.
+
+| League | Verdict | Wiring |
+|---|---|---|
+| MLB | ✅ now | MLBAM `res.id` already captured (into rosterlogs only) — add to `enriched`; thread to strip/scan/hotlist |
+| NBA/WNBA | 🔧 free now | `espnStatsAdapter.getSeasonAverages` **resolves the ESPN athlete id at `:89` and discards it** — return it as `espnId`; surface via `resolvePlayerStats` nba/wnba branch; thread `espnId`→`getHeadshotUrl`; runtime-verify ESPN coverage |
+| NFL/NHL | dormant | not in `ACTIVE_SPORTS` (+ off-season); add `nfl`/`nhl` to `ESPN_SPORT_PATH` (`playerHeadshot.ts:39`); inherits ESPN id when ingested |
+| Soccer | ⛔ blocked | no live resolve branch; API-Football has `player.id` + `media.api-sports.io` CDN but is key-gated (`API_FOOTBALL_KEY`) + unwired → **honest monogram** until a soccer resolve branch + key land. **This is the one league to report as no-free-id-today.** |
+
+**404-status (Addition 1):** id resolve is free; a true resolved-or-404 status needs an image HEAD probe (extra I/O). `
` already degrades per-render + the browser CDN-caches → **ship id-only first**; add a bounded HEAD probe in the `mapLimit` loop only if the one-frame monogram→photo flash is objectionable. Book SVGs (D3) + ledger `BookWordmark` import ride this wave too.
+
## WAVE SEQUENCE (ship on green, per step; toward the mockup)
1. **Wave 1 — Step 1 trust bugs** (billing renewal date + Wood nameKey-collision + streaks join-invariant test) + the quick DeskShowcase "A $1M terminal" → on-voice deadpan copy fix. Quick, independent, no mockup dep.
2. **Wave 2 — Step 2 entity layer, SPORT-AGNOSTIC (the eyeball gate).** (a) ingestion-time athlete-id capture per league (ESPN cross-sport id + MLB MLBAM) with resolved-or-404 status stored (Addition 1); (b) ONE `(league,id)`→headshot resolver; (c) thread id → grade → strip → every surface (slate strips, scan search, hot list, grade cards); (d) ledger book wordmarks — import `BookWordmark` + add missing keys + **bundle the ~8 real book SVGs**; (e) team-logo coverage gaps. **STOP + REPORT for founder eyeball of real logos/headshots across ALL sports before the rest builds on it.** Report any league with no free id source.