Reality assessment: the forward model exists, wired to the wrong side of the pipe
READ-ONLY. src/ and web/ untouched. Inventoried every forward-model component against the real objective -- a forward matchup projection, not an edge number. The finding is that all of it already exists and is already loaded in production, and 100% of it sits DOWNSTREAM of the grade in challenger columns nothing serves. The served p_win reads three features and a game log; it has never seen a pitcher. Inputs are HAVE, not missing: statcast_aggregates carries 1,354 rows (750 pitchers, 604 batters) with exit velo, launch angle, barrel, hard-hit, whiff, chase, pitch mix, GB/FB, arm angle, and handedness complete on every row. Real gaps are team defense and catcher/umpire. So Stage A is a plumbing-and- modelling job, not a data-acquisition job. Found along the way: the Statcast nightly refresh is unreachable code. tick() returns for any hour not in HOURS_UTC (14,19,22,1,3) and the refresh block then tests h === 11, which that guard can never admit. The mechanism data has been frozen at its 2026-07-21 backfill for 13 days, and the block's own failure alert sits in the same dead branch -- the identical silently-guarded- out shape as the settlement outage. Design shows the counter: every factor label the SIGNAL BREAKDOWN renders is a restatement of recent frequency (l5_hot_vs_line, l20_over_line, back_to_back, home_game) plus several structurally-NBA labels (referees, coach pace, starters out) inside a baseball product. Not one names a pitcher, pitch type, handedness or park. The card's forward-read slots already exist and go unfilled -- the surface needs feeding, not redesigning. On what changes: the prior measurements were outcome-accuracy, not edge, so the metric was right and the question was narrow. proj-v1.1 and hits-v1 stay correctly refuted as DISTRIBUTION swaps on thin inputs -- neither tested a matchup-fed projection. arch-v1 is a market-relative nudge by construction and is the one component genuinely measured on the wrong axis. AT CEILING is provisional: measured only against features the champion already reads. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W1sivYNqY2TS5ftykmHBU9
This commit is contained in:
@@ -1224,6 +1224,44 @@ phased plan in the Session-57 conversation / BUILD-STATE Next section).
|
||||
built for exactly this kind of replay was never settled, so ablations must join
|
||||
outcomes from `ledger_entries` on (player_key, stat, line, side, game_date).
|
||||
|
||||
## Forward-model reality check (Session 79 — non-obvious)
|
||||
- **`specs/forward-model-reality-assessment.md`.** THE OBJECTIVE is a FORWARD
|
||||
matchup projection (hitter profile × pitcher stuff × park/conditions, read
|
||||
through archetype), not a market-edge number. Every component that needs
|
||||
exists AND is loaded in prod — and ALL of it sits DOWNSTREAM of the grade.
|
||||
- **The served grade sees NONE of it.** `probabilityEstimator` reads exactly
|
||||
three features (`opp_rank_stat`, `home_away`, `l10_stddev`/`l20_avg`) plus the
|
||||
game log. statcast rows, arsenal, park, weather, platoon and archetype are all
|
||||
loaded in `snapshotService` AFTER grading and written to CHALLENGER columns.
|
||||
`mlbContext` (platoon/handedness) has ZERO consumers — dead code.
|
||||
- **STATCAST NIGHTLY REFRESH IS UNREACHABLE CODE.** `snapshotScheduler.tick()`
|
||||
returns at `if (!HOURS_UTC.includes(h)) return` (14,19,22,1,3); the statcast
|
||||
block then tests `h === STATCAST_HOUR_UTC` (default **11**), which that guard
|
||||
can never admit. Data frozen at its 2026-07-21 backfill; its failure alert is
|
||||
inside the same dead branch so it can't warn. Same shape as the settlement
|
||||
outage — guarded-out code that reports nothing. Set STATCAST_HOUR_UTC to one of
|
||||
HOURS_UTC or move the block above the guard.
|
||||
- **Inputs are HAVE, not missing** — `statcast_aggregates` 1,354 rows (750
|
||||
pitchers / 604 batters): exit velo, launch, barrel, hard-hit, whiff, chase,
|
||||
pitch_mix, GB/FB, arm angle, and **bats/throws complete on all 1,354**. Gaps
|
||||
are team DEFENSE (only a coarse `opp_rank_stat`) and catcher framing/umpire.
|
||||
PARTIAL: batter GB/FB land in the `metrics` JSONB not the typed columns;
|
||||
lineup-slot tables (`player_role_profiles`, `lineup_role_profiles`) are 0 rows.
|
||||
- **The card is designed for the forward read; the engine never fills it.** The
|
||||
factor vocabulary the "SIGNAL BREAKDOWN" renders is entirely counter-restating
|
||||
(`l5_hot_vs_line`, `l20_over_line`, `back_to_back`, `home_game`) with several
|
||||
structurally-NBA labels (`ref_foul_high`, `coach_pace_delta`,
|
||||
`opp_3plus_starters_out`). No signal names a pitcher, pitch type, handedness or
|
||||
park. Surface needs FEEDING, not redesigning.
|
||||
- **What the prior verdicts do and don't say.** Resolution = corr(forecast,
|
||||
outcome) was never a market/edge test — the metric was right, the QUESTION was
|
||||
narrow ("does challenger out-rank champion?"). proj-v1.1 and hits-v1 remain
|
||||
correctly refuted AS DISTRIBUTION SWAPS on thin inputs; neither tested a
|
||||
matchup-fed projection. arch-v1 IS market-relative by construction and is the
|
||||
one component genuinely measured on the wrong axis — re-test its axes as
|
||||
forward inputs. "AT CEILING" (runs/walks) is provisional: measured only against
|
||||
features the champion already reads.
|
||||
|
||||
## Active Skills
|
||||
- vyndr-voice (all user-facing output)
|
||||
- prop-analysis (grading methodology)
|
||||
|
||||
Reference in New Issue
Block a user