Live-surface integrity on the repaired champion; fix the label my own
repair falsified
PHASE 0 — four checks PASS, one defect found and fixed.
PASS gradeBands is required by NO serving code -- built across several
orders, never wired. No stale band derived from the retired
ten-game champion can reach a user, because none reaches a user
at all.
PASS CALIBRATION_DEPLOYED is [] and the calibrate loop iterates it, so
calibrate() is never called and p_win_calibrated is never set. The
only assignment site sits inside that empty loop. No withdrawn map
can leak.
PASS projectionFor reads l20_avg, which mlbGameLogFeatures now builds
from fullLog -- so refusals are computed on the repaired
full-window reference, not the retired ten-game one.
PASS factors still fire with correct sign across the repaired base
range (0.35/0.50/0.65/0.80): defense lowers, pitcher-contact
raises, platoon raises at every point. Mechanical firing check
only -- NOT a lift re-measurement, which waits for accrual.
DEFECT FIXED — my own repair falsified a user-facing sentence. The grade
card rendered "Last 20 games average: X" from l20_avg, and l20_avg is now
a FULL SEASON average. The number changed and the label did not, so the
surface was stating something the data no longer supported. Copy now reads
"Season average"; trapDetection's L20 explanations likewise. The field
name is kept -- it is read in many places -- but no rendered sentence
claims a window that isn't there.
That is the same class as everything else tonight, one layer out: a
correct-looking string describing data that moved underneath it.
Serving change; frozen model modules unchanged; p_win never mutated; no
Bonferroni slot.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1sivYNqY2TS5ftykmHBU9
This commit is contained in:
@@ -114,7 +114,11 @@ function buildConcreteReasoning(features = {}, engine1Result = {}, meta = {}, pr
|
||||
lines.push(`${prop.player || 'Player'} is averaging ${features.l5_avg.toFixed(1)} ${prop.stat_type || ''} over his last 5 games.`);
|
||||
}
|
||||
if (Number.isFinite(features.l20_avg)) {
|
||||
lines.push(`Last 20 games average: ${features.l20_avg.toFixed(1)}.`);
|
||||
// LABEL FIXED WITH THE DATA. `l20_avg` is now built from the full season
|
||||
// log rather than a ten-game slice, so "Last 20 games" was a sentence the
|
||||
// number no longer supported. The field name is kept (it is read in many
|
||||
// places) but the copy states what is actually being shown.
|
||||
lines.push(`Season average: ${features.l20_avg.toFixed(1)}.`);
|
||||
}
|
||||
|
||||
// Trend direction relative to the line.
|
||||
|
||||
@@ -141,11 +141,11 @@ function signalRecencyInflation(input) {
|
||||
return inactive('l5_avg or l20_avg missing');
|
||||
}
|
||||
const ratio = (l5 - l20) / l20;
|
||||
if (ratio <= 0) return { score: 0, active: true, explanation: 'L5 not hotter than L20' };
|
||||
if (ratio <= 0) return { score: 0, active: true, explanation: 'L5 not hotter than season' };
|
||||
return {
|
||||
score: Math.min(1.0, ratio),
|
||||
active: true,
|
||||
explanation: `L5 (${l5.toFixed(1)}) ${(ratio * 100).toFixed(0)}% above L20 (${l20.toFixed(1)})`,
|
||||
explanation: `L5 (${l5.toFixed(1)}) ${(ratio * 100).toFixed(0)}% above season (${l20.toFixed(1)})`,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user