-- Migration 034: model_snapshots.factor_inputs — FREEZE THE FACTOR INPUTS (Fix A5). -- -- A re-audit that joins context tables to a past grade RECONSTRUCTS what the -- context probably was. This column carries what the grader ACTUALLY read, so a -- row becomes independently checkable. -- -- INPUTS, NOT OUTPUTS. It stores the raw values (spray shares, positional OAA, -- pitcher hard-hit rate, platoon split counts, handedness) and NOT the resulting -- multiplier. A stored multiplier can only be compared to itself; stored inputs -- can be re-run through hitsFactors and checked. -- -- A SEPARATE COLUMN, not extra keys inside `features`: champion-ablation.js -- iterates every key of `features` for its residual scan, so widening it would -- silently enlarge that multiple-comparisons denominator. -- -- NULLABLE and populated only on `hits` rows with a factor context, so the -- storage cost is bounded. Adding a nullable column is metadata-only in -- Postgres — no table rewrite — which matters while this database sits over its -- free-tier size cap. ALTER TABLE model_snapshots ADD COLUMN IF NOT EXISTS factor_inputs jsonb; COMMENT ON COLUMN model_snapshots.factor_inputs IS 'Fix A5: raw inputs the hits factors read at grade time (never the multiplier). Recompute via factorFreeze.recompute().';