Files
vyndr/specs/rbi-resolution-anomaly.md
T
builtbykev 65ca6493db Decompose the rbi anomaly: it is lineup ROLE, and the counter is
out-resolved by a frequency table on three of four stats

PHASE 0 — the 14.51% is REAL. Re-derived with a paged pull asserted
against an exact count (rbi 7,930 == 7,930; hits 11,690; TB 12,086; runs
6,440), since this harness produced a false null three times tonight. rbi
resolution 0.03268 reproduces, deciles are monotone through the middle,
and 20 raw rows are in the artifact for hand audit.

CAVEAT GOVERNING EVERYTHING BELOW: the naive forecasts are leave-one-out
ON THE EVALUATION WINDOW, so they see the rows they are scored on while
the model is strictly point-in-time. They are upper bounds on available
resolution, not fair competitors, and every comparison is read that way.

PHASE 1 — the split:

  stat  MODEL    (a)player-base  (b)lineup-slot  (c)within-stratum
  rbi   0.03268     0.01167         0.03608          0.01908
  hits  0.00252     0.00446         0.00100          0.00473
  TB    0.00442     0.01331         0.03448          0.00607
  runs  0.00130     0.00262         0.01156          0.01170

FINDING 1 — rbi's resolution is LINEUP ROLE almost exactly. Batting-order
slot alone resolves 0.03608 against the model's 0.03268. A single integer
accounts for the whole anomaly and slightly more. That is opportunity, not
skill -- the cleanup hitter bats with runners on. 36% is matched by player
identity alone. Within similar-base-rate strata the model still resolves
0.01908, 58% of its total and higher than any other stat's ENTIRE model
resolution, so genuine within-role discrimination exists on top.

FINDING 2 — on three of four stats the model is beaten by "he's a .270
hitter". Base-rate-only out-resolves the model 1.8x on hits, 3.0x on TB,
2.0x on runs. Even allowing for the window-peeking advantage, a 1.8-3.0x
gap is not explained by that alone: the served counter appears to DESTROY
discrimination relative to the player's own rate. rbi is the one stat
where the model beats the naive baseline.

FINDING 3 — lineup slot out-resolves the MODEL on three stats: TB 7.8x,
runs 8.9x, rbi 1.1x. Hits is the only stat where batting order carries
less, which is mechanically right -- a hit is a hit wherever you bat, but
runs, RBI and total bases all scale with opportunity.

PHASE 2 — all three worlds are partly true, in measured proportions.
World A ~90% true (slot covers rbi's entire resolution). World B ~36% true
for rbi, but the WHOLE story for hits/TB/runs where base rate alone wins.
World C true with a low ceiling: hits' total available spread resolution
is 0.00446, i.e. 1.8% of variance from a forecast that has seen the
answers.

PHASE 3 — the next arc is NOT "strengthen hits factors". Hits has the
lowest available resolution on the board and last order's wiring already
took it to 1.39% of a ~1.8% ceiling. Named first factor order for next
session: LINEUP SLOT / RISP OPPORTUNITY on rbi through the two-part gate --
input already ingested and prod-verified (S89), resolution measured not
hypothesised, causally-correct unit is plate appearances with runners on.
Measured availability is not a pass; it still faces the gate.

And higher-value than either: the counter being out-resolved by a
frequency table on three of four stats is a defect in the CHAMPION, not a
factor problem, and it costs nothing to test -- the recency blend and the
+/-0.03 / +/-0.015 nudges are three lines in probabilityEstimator.

The hits transmission win from 43f65d3 stands: the conduit is real and
permanent. This order changes only which stat has the most worth flowing
through it.

Diagnostic only -- no factor wired, no serving path changed, p_win
untouched, all frozen modules byte-identical. No Bonferroni slot.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1sivYNqY2TS5ftykmHBU9
2026-08-07 03:09:44 -04:00

142 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# The rbi anomaly, decomposed — the model is out-resolved by a batting-order integer
## PHASE 0 — the 14.51% is REAL
The figure came from the harness that produced a false null three times tonight,
so it was re-derived with a paged pull **asserted against an exact count**:
| stat | exact rows | paged rows | scorable | resolution | share |
|---|---|---|---|---|---|
| rbi | 7,930 | 7,930 ✓ | 630 | **0.03268** | **14.51%** |
| hits | 11,690 | 11,690 ✓ | 1,140 | 0.00252 | 1.03% |
| total_bases | 12,086 | 12,086 ✓ | 1,050 | 0.00442 | 1.82% |
| runs | 6,440 | 6,440 ✓ | 597 | 0.00130 | 0.56% |
**Reproduces exactly.** rbi deciles are monotone through the middle (0.552→0.577,
0.646→0.691, 0.746→0.784) with a genuinely low bin at 0.13→0.122, and 20 raw
rows are printed in the artifact for hand audit.
---
## The caveat that governs every number below
The naive forecasts are **leave-one-out on the evaluation window itself** — they
see that player's performance in the very rows being scored, while the model is
strictly point-in-time. They are therefore **upper bounds on available
resolution, not fair competitors.** Every comparison is read that way.
---
## PHASE 1 — the three-way split
| stat | MODEL | (a) player base rate | (b) lineup slot | (c) within-stratum |
|---|---|---|---|---|
| **rbi** | **0.03268** | 0.01167 | **0.03608** | 0.01908 |
| hits | 0.00252 | **0.00446** | 0.00100 | 0.00473 |
| total_bases | 0.00442 | **0.01331** | **0.03448** | 0.00607 |
| runs | 0.00130 | **0.00262** | **0.01156** | 0.01170 |
### Finding 1 — rbi's resolution is LINEUP ROLE, almost exactly
**Batting-order slot alone resolves 0.03608 against the model's 0.03268.** A
single integer — where he hits in the order — accounts for the entire anomaly and
slightly more. That is real predictive signal and it is **opportunity, not
skill**: the cleanup hitter bats with runners on, the 8-hole hitter does not.
Player base rate alone gives 0.01167, so ~36% of the model's rbi resolution is
matched by knowing only *who* is batting.
Within strata of similar-base-rate players the model still resolves **0.01908**
58% of its total, and **higher than any other stat's entire model resolution.**
So rbi does carry genuine within-role discrimination on top of the role effect.
### Finding 2 — on three of four stats the model is beaten by "he's a .270 hitter"
| stat | model | player base rate alone | |
|---|---|---|---|
| hits | 0.00252 | **0.00446** | base-rate-only resolves **1.8×** the model |
| total_bases | 0.00442 | **0.01331** | **3.0×** |
| runs | 0.00130 | **0.00262** | **2.0×** |
| rbi | **0.03268** | 0.01167 | model wins, 2.8× |
Even allowing that the naive forecast peeks at the window, a **1.83.0× gap is
not explained by that advantage alone.** The served counter — a frequency over
the line, blended with the last five games, nudged by opponent rank and home/away
— appears to **destroy discrimination relative to the player's own rate.** The
recency blend and the ±0.03/±0.015 nudges move predictions in ways that do not
track outcomes.
**rbi is the one stat where the model beats the naive baseline.**
### Finding 3 — lineup slot out-resolves the model on THREE stats
| stat | model | slot alone |
|---|---|---|
| total_bases | 0.00442 | **0.03448** (7.8×) |
| runs | 0.00130 | **0.01156** (8.9×) |
| rbi | 0.03268 | **0.03608** (1.1×) |
| hits | 0.00252 | 0.00100 (model wins) |
**Hits is the only stat where batting order carries less than the model** — which
makes sense: a hit is a hit whether you bat first or ninth, but runs, RBI and
total bases all scale with opportunity.
---
## PHASE 2 — which world
**All three are partly true, in measured proportions:**
- **WORLD A — rbi resolution is real and role-driven: ~90% TRUE.** Slot alone
(0.03608) covers the model's entire rbi resolution. It is real, it is
contextual rather than skill-based, and 58% survives within similar-player
strata as genuine discrimination.
- **WORLD B — base-rate-spread artefact: ~36% TRUE for rbi.** Player identity
alone accounts for about a third. Not the main story for rbi — but for
**hits, TB and runs it is the whole story and then some**, since base rate
alone out-resolves the model on all three.
- **WORLD C — hits is intrinsically compressed: TRUE, and the ceiling is low.**
Total available spread resolution for hits is 0.00446 — **1.8% of variance even
from a forecast that has seen the answers.** Perfect factors cannot make hits a
high-resolution grade.
---
## PHASE 3 — the roadmap-deciding log
**The next arc is not "strengthen hits factors."** Hits has the lowest available
resolution on the board (1.8% ceiling from an oracle-ish baseline) and last
order's wiring already lifted it to 1.39% of a 1.8% ceiling. There is very little
left there.
**Named first factor order for next session: LINEUP SLOT / RISP OPPORTUNITY on
rbi**, through the two-part gate.
- The input is **already ingested and prod-verified** (`lineup_context` batting
order, `hitter_opportunity` RISP share, S89).
- Its resolution is **measured, not hypothesised**: 0.03608 slot-only on rbi,
0.03448 on TB, 0.01156 on runs.
- The causally-correct unit is **plate appearances with runners on**, which is
what RISP share measures directly — the crude version is the slot integer.
- It must clear the two-part gate like anything else. Measured availability is
not a pass.
**Second, and higher-value than either:** the counter is out-resolved by a player
frequency table on three of four stats. That is not a factor problem — it is a
defect in the champion. **Diagnosing whether the recency blend and the
±0.03/±0.015 nudges are destroying discrimination is the biggest single lever
this decomposition found**, and it costs nothing to test: they are three lines in
`probabilityEstimator`.
**The hits transmission win stands.** The conduit is real and permanent —
sign-verified, 75% coverage. This order changes only *which stat* has the most
worth flowing through it.
---
## Invariants
Diagnostic only. No factor wired, no serving path changed, no calibration refit,
`p_win` untouched, all frozen modules byte-identical including the hits path from
`43f65d3`. No Bonferroni slot — this is resolution accounting, not a causal claim.