STATE: Session 73 — park factors derived + composable; pipeline gap documented
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCNgGSt5qvcLxaeQqa7Zpj
This commit is contained in:
+75
-1
@@ -1,5 +1,5 @@
|
||||
# VYNDR — STATE OF THE WORLD
|
||||
### As of `927e867` (main, DEPLOYED), 2026-07-21. This file opens every future session. **Start with the CURRENT STATUS + OPEN ITEMS block below.**
|
||||
### As of `3ac91c3` (main, DEPLOYED), 2026-07-21. This file opens every future session. **Start with the CURRENT STATUS + OPEN ITEMS block below.**
|
||||
|
||||
---
|
||||
|
||||
@@ -131,6 +131,80 @@ exist locally; harmless, the data restores completely.
|
||||
`specs/snapshot-retention.md` (Phase 2 report + schema) ·
|
||||
`specs/audit-data/grade-collapse.md` · `specs/audit-data/gate-simulation.md`.
|
||||
|
||||
---
|
||||
|
||||
# 🟡 SESSION 73 — PARK FACTORS (derived, composable) (2026-07-21)
|
||||
**Derivation + composition BUILT and proven. PIPELINE WIRING INCOMPLETE — see
|
||||
the gap.** Layer 3 Step 4.
|
||||
|
||||
## 🔴 PHASE 0 — A STATIC PARK TABLE ALREADY EXISTED (nearly built a duplicate)
|
||||
`src/data/parkFactors.js` — **static FanGraphs table, Session 15**, consumed by
|
||||
`computeFeatures.js:374`. I almost created a second source of truth.
|
||||
- **NEW derived service = `src/services/parkFactors.js`** (distinct path).
|
||||
- **Checked:** the static table reaches `computeFeatures` but **NOT
|
||||
`probabilityEstimator`** → it does **not** currently touch `p_win`.
|
||||
- **This reframes the order:** if the champion ever does see park, adding it to
|
||||
the challenger is DOUBLE-COUNTING — precisely what the S72 harness catches.
|
||||
Park therefore ships as a **nominated challenger to be TESTED**, not an
|
||||
assumed win.
|
||||
|
||||
## Derivation (ours, from real games)
|
||||
statsapi `schedule?hydrate=linescore,venue,scoringplays` — **one call per date
|
||||
range**. Every HR scores ≥ the batter, so **HR totals are fully recoverable from
|
||||
scoringPlays**. Derived from **5,055 real games, 2022–2025**:
|
||||
|
||||
| Park | HR base | RUN base |
|
||||
|---|---|---|
|
||||
| Dodger Stadium | **1.106** | 1.023 |
|
||||
| Coors Field | 1.029 | **1.099** |
|
||||
| Oracle Park | **0.923** | 0.969 |
|
||||
| PNC Park | **0.917** | 0.994 |
|
||||
|
||||
**18 parks present · 18 honestly absent** (below the 150-game regime floor).
|
||||
*(Sample was a partial pull — month-chunked with `-31` end dates drops days — so
|
||||
absences are inflated. Re-derive with proper date ranges before trusting counts.)*
|
||||
|
||||
## COMPOSABLE — the architectural point
|
||||
Emits a **multiplier ~1.0**, never an additive nudge, because weather must
|
||||
modulate it next: `effective = park_base × weather_mod × …`. Additive terms
|
||||
don't compose (5% park + 8% wind = 1.05×1.08, **not** +13%). The challenger
|
||||
converts via `Math.log(env)` into the same log-odds space the archetype nudges
|
||||
use. A test multiplies a placeholder weather term on to prove the shape composes
|
||||
**with no rearchitecting**.
|
||||
|
||||
## Honest states (three, distinct)
|
||||
`absent` (thin → adjust nothing) · `present` (adjust) · **`weather_na`** (dome —
|
||||
**the park factor STILL APPLIES**; the flag exists so next order's weather does
|
||||
nothing there). **N/A ≠ absent** — conflating them either drops a valid park
|
||||
factor or applies wind indoors.
|
||||
|
||||
## Directional by prop-owner
|
||||
`home_runs` and `home_runs_allowed` both key off `hr_base` **in the same
|
||||
direction** — the sign lives in the STAT, not the park.
|
||||
|
||||
## Structural breaks + shrinkage
|
||||
A deviating season starts a new regime **only if the NEXT season confirms** (one
|
||||
odd year = noise). Only post-break seasons used. Factors **regress toward
|
||||
neutral by sample size**; fine conditioning (park×hand, park×batted-ball) stays
|
||||
**unavailable** until its own larger floor (400 games).
|
||||
|
||||
## 🔴 THE GAP — park is NOT yet reaching live props
|
||||
`adjust()` accepts `environment`, and `parkMultiplier` produces it — but
|
||||
**nothing in `snapshotService` looks up a venue per prop and passes it**. Props
|
||||
carry `game_time` (via gameBinder) but **no venue**. Remaining wire-up:
|
||||
1. Attach venue to each prop (statsapi schedule already returns it).
|
||||
2. Persist derived factors (a table or cached blob) + a refresh job.
|
||||
3. Pass `environment` into `attachChallenger`.
|
||||
**Until then park adjusts nothing live** — the derivation and composition are
|
||||
proven, the plumbing is not.
|
||||
|
||||
## Next
|
||||
1. Wire venue → prop → park lookup (the gap above).
|
||||
2. **Weather modulation** — composes by multiplying `park_base`; domes already
|
||||
flagged `weather_na`.
|
||||
3. Still blocking all measurement: **no settled row carries `p_win` yet**.
|
||||
|
||||
|
||||
---
|
||||
|
||||
# 🟢 SESSION 72 — TIER-1 MAPPINGS LIVE + TIER-2 HARNESS (2026-07-21)
|
||||
|
||||
Reference in New Issue
Block a user