claude/clever-archimedes-dvye42 #110

Merged
chrisp merged 4 commits from claude/clever-archimedes-dvye42 into main 2026-06-26 05:16:54 +00:00
Owner
No description provided.
chrisp added 4 commits 2026-06-26 05:16:44 +00:00
Make the futures-vs-Elo relationship an explicit, configurable rule and fix
futures odds failing to override stored Elo.

Root causes addressed:
- resolveSourceElos/resolveRatings used a hardcoded precedence (direct Elo ->
  projectedWins -> projectedTablePoints -> odds). The prior fix nulled sourceElo
  on futures entry but not projections, which still outranked odds.
- The override relied on a destructive null-on-save hack that also wiped
  manually entered Elo.
- Blended simulators buried their Elo/odds weight in module constants.
- Futures odds were not surfaced on the /admin/simulators inventory.

Changes:
- Add a configurable source policy: sourceEloPriority (ordered) and oddsWeight,
  parsed/clamped in getSimulatorInputPolicy. resolveSourceElos/resolveRatings now
  resolve each participant by the configured priority instead of a fixed order.
  Futures-centric simulators (ncaam, ncaaw, world_cup, ncaa_football,
  college_hockey) default to a futures-override priority.
- Drop the destructive nulling in batchSaveFuturesOddsForSimulator and
  batchSaveSourceOdds; override is now governed by policy, preserving stored Elo.
- Thread an optional SimulationContext (oddsWeight) through the Simulator
  interface so blended sims (UCL, World Cup, NCAA FB, MLB) read the blend weight
  from the season policy; defaults preserve prior calibration when no context is
  passed.
- Add a "Futures vs. Elo" strategy control and Odds Blend Weight input to the
  Simulator Setup input-policy card, persisted via save-input-policy.
- Surface futures on /admin/simulators: a source badge and a Futures Odds quick
  link; extend listSportsSeasonSimulatorSummaries with odds source info.
- Tests: configurable priority override (Elo/projections/rating), oddsWeight
  parsing/clamping, prefersFuturesOdds, manifest defaults, an NCAA Football
  context-blend behavioral test, and an updated non-destructive save test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QhNeB7gN6VKene7sdbBVQT
Replace the two parallel odds/Elo mechanisms with one model: every strength
source (raw Elo, projected wins, projected table points, futures odds) converts
to an Elo, those blend by weight into a single Elo, and that one Elo feeds every
simulator. This supersedes the earlier source-priority + per-match probability
blend approach.

Resolution (app/services/simulations/input-policy.ts):
- SimulatorInputPolicy gains baseEloPriority (order among the substitutable base
  sources: raw Elo / projected wins / projected table points) and oddsWeight
  (0–1). resolveSourceElos/resolveRatings now compute baseElo, derive an
  odds Elo via convertFuturesToElo, and blend: 0 = base only, 1 = futures
  override, between = weighted blend (method "blend").
- Drops the odds-inclusive sourceEloPriority and the prefersFuturesOdds helper.

Simulators consume the single resolved Elo:
- UCL, World Cup, NCAA Football, MLB drop their separate normalized-odds signal,
  convertFuturesToElo calls, and per-match probability blend; they read the
  resolved sourceElo (preserving each sim's hardcoded fallback Elo table). The
  optional SimulationContext oddsWeight plumbing (types.ts/runner.ts) is removed.
- UCL is routed through the central blend (requiredInputs sourceElo, derivable
  from sourceOdds) so any entered Elo and futures blend uniformly.
- College hockey already blends odds into Elo internally (and uses NPI rank the
  central resolver can't), so its central oddsWeight is set to 0 to avoid
  double-counting; the simulator is unchanged.

Manifest: per-profile oddsWeight defaults (World Cup/UCL/MLB 0.3, NCAA FB 0.4,
college hockey 0; global default 0.3).

UI: the Input Policy card exposes one "Futures vs. Elo — Odds Blend Weight"
control; the /admin/simulators inventory badge shows the effective blend
("Elo only" / "NN% blend" / "overrides Elo") with the odds participant count.

Tests: input-policy blend math (0/0.5/1) for Elo and ratings, baseEloPriority
and oddsWeight parsing/clamping, manifest per-profile weights; obsolete
source-priority and oddsWeight-context tests removed/replaced.

Note: this intentionally shifts the calibrated EV outputs of the four sims that
previously blended at the probability level (accepted in design discussion).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QhNeB7gN6VKene7sdbBVQT
Code review caught a regression in the single-Elo blend: resolveSourceElos /
resolveRatings clamped every resolved value to [eloMin, eloMax] /
[ratingMin, ratingMax], including a directly entered base Elo. The original
resolver only clamped derived values (projections, odds, fallbacks) and passed
direct inputs through untouched. With the default 1900 Elo ceiling this
truncated manual Elos for sports that enter higher ratings (e.g. snooker ~2450),
collapsing their spread.

Clamp only odds-derived / blended / fallback values now; direct Elo and rating
inputs pass through as entered. Adds a regression test, and fixes two comments
that still referenced the removed `sourceEloPriority` field (now `oddsWeight`).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QhNeB7gN6VKene7sdbBVQT
Cleanup: dedupe blend logic, single-home oddsWeight
Some checks failed
🚀 Deploy / 🐳 Build (pull_request) Has been skipped
🚀 Deploy / 🚀 Deploy (pull_request) Has been skipped
🚀 Deploy / 🧪 Test (pull_request) Successful in 3m20s
🚀 Deploy / ʦ🔍 Typecheck & Lint (pull_request) Failing after 51s
a77485d5a5
Address code-review cleanup notes:
- Extract the base/odds blend ladder (duplicated between resolveSourceElos and
  resolveRatings) into one generic `blendBaseAndOdds` helper.
- Move the futures blend weight to a single home: oddsWeight now lives only under
  inputPolicy. Manifest per-profile defaults moved from top-level config into
  inputPolicy.oddsWeight, and getSimulatorInputPolicy no longer reads a legacy
  top-level config.oddsWeight. Drops the now-dead mlb rDiffWeight config knob.
- Clarify the college_hockey oddsWeight 0 rationale (it disables the central
  blend so its internal odds blend isn't double-counted, while still letting odds
  resolve an Elo when they're the only source — a separate centralBlend flag
  would wrongly drop that sole-source path and break readiness).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QhNeB7gN6VKene7sdbBVQT
chrisp merged commit ee099c64cd into main 2026-06-26 05:16:54 +00:00
chrisp deleted branch claude/clever-archimedes-dvye42 2026-06-26 05:16:55 +00:00
chrisp referenced this pull request from a commit 2026-06-26 05:16:56 +00:00
Sign in to join this conversation.
No description provided.