CI check.yml has failed 20 consecutive runs since 6ea03029 (Apr 11 06:30)
because features/engine.py and hf-space/features/engine.py diverged after
a partial auto-sync touched only the hf-space copy.
Per CLAUDE.md Rule 2, /home/termius/mon-ipad/features/engine.py is the
canonical source. This commit sets BOTH nomos-nba-agent copies to an exact
byte-for-byte copy of the mon-ipad canonical (sha256 13ef12d9..., v3.1-65cat,
8012 LOC). Previously nomos-nba-agent was pinned to v3.1-59cat and missing
Cat 60-65 (score margin distribution, pace-adjusted net rating, clutch
performance, Pythagorean luck, opponent-Elo-weighted perf, style matchup).
Verified locally:
- Parity check: PASS (sha256 match)
- Import smoke test: PASS (ENGINE_VERSION=v3.1-65cat, NBAFeatureEngine present)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Brain cycle 83: Cat59 opponent graph features (arXiv 2303.16741 GATv2-TCN)
Claude
c588104
12 new features: 2nd-order SOS, common-opp advantage, transitive wins,
schedule difficulty trend, opponent form at time of matchup.
Engine: v3.1-59cat (6350+ feature candidates)
https://claude.ai/code/session_01KtBfaHJZ3YzfFqzerNp23f
Brain cycle 83: Cat56-58 + engine v3.1-58cat (3 new SOTA 2026 categories)
Claude
0e6ea15
Cat56: Directional Circadian Advantage (10 features)
- Chronobiology Int'l 2022 + ScienceDaily 2024: 25,016-game study
- Westbound home teams win 63.5% vs 55.0% eastbound → net +8.5pp effect
- SIGNED timezone delta (vs abs() in Cat39) captures direction, not just magnitude
- Sigmoid-encoded probability boost; double advantage if home→west AND away→east
Cat57: Sequential Exponential Form (12 features)
- arXiv 2512.08591: LSTM 8-season paper, sequential dependencies > rolling avg
- α=0.4 exp-weighted form: recency-preserved, covers 5-10 game horizon
- Hot hand (3+ consecutive wins), form variance (consistency), momentum
Cat58: Model Confidence & Calibration Anchors (10 features)
- arXiv 2303.06021: Brier-calibrated model selection beats accuracy by 5-7% ROI
- Spread confidence, B2B uncertainty, H2H consistency, home reliability signal
- Compound confidence; matchup × market signal compound
ENGINE_VERSION: v3.1-55cat → v3.1-58cat (6338+ feature candidates)
Both features/engine.py and h…
polymarket_home_prob and prediction_market_consensus defaulted to constant
0.5 for all historical games — polymarket data is never available during
training, making both features zero-variance (filtered out by app.py).
Now falls back to odds_data[(gd,home,away)].implied_home_prob and
fair_home_prob respectively, using the same lookup pattern as Cat46.
This gives 2 of 8 Cat15 features real variance from book consensus odds,
allowing them to survive the zero-variance filter and contribute signal.
Feature names unchanged; fallback remains 0.5 when odds_data has no entry.
Estimated Brier impact: -0.0003.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
shot_contest_rate was hardcoded 0.6 and rim_protection_rate 0.55 for all
games — zero differential signal between teams, plus a positive directional
bias. Replaced with blk_rate*5 (shot contest proxy, same scale as stl_rate*5)
and opp_efg() or 0.5 (opponent eFG% for rim/perimeter defense, fallback 0.5
neutral instead of biased 0.55). Feature names unchanged; values now provide
genuine per-team differentiation. Estimated Brier impact: -0.0005.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
_season_spreads and _season_totals were never reset between seasons, making
line52_spread_season_pct, line52_total_season_pct, line52_season_spread_std,
and ou54_total_trend compute against a growing multi-season pool instead of
the current season only. Fix: detect season change via _era_season_id(gd)
at the top of each game iteration and clear both lists when season flips.
_team_ats and _team_ou trackers are intentionally preserved cross-season.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix(engine): _ats_rate home_only=False was a no-op — ats53_a_away_only returned wrong values
`if home_only:` treated False as falsy, so passing home_only=False never
filtered to away games. Feature ats53_a_away_only was silently duplicating
ats53_a_season (all-game rate) instead of computing road-only ATS rate.
Fixed by using `if home_only is True:` / `elif home_only is False:` guards,
matching the correct pattern already used in Cat 54 _ou_rate(). No API
change — existing callers with home_only=True unaffected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat(engine): add h_next_is_home + a_next_is_home to Cat6 [brain-cycle-71]
Claude
c25c25f
Research (cmunch1/nba-prediction, uncertainty-aware 2025, nature s41598-025-13657-1)
consistently identifies home_next (is team's NEXT game at home?) as top-3 predictor.
Changes:
- Cat6 REST & SCHEDULE: 24 → 26 features
- Pre-compute _team_next_is_home O(n) lookup before main evolution loop
- 1.0 = next game is home, 0.0 = away, 0.5 = unknown (last game in dataset)
- ENGINE_VERSION: v3.1-51cat → v3.1-51cat-sched
- Parity maintained: features/engine.py == hf-space/features/engine.py (6871 lines each)
Expected Brier delta: -0.001 to -0.003 (schedule motivation signal)
Fleet best: 0.2222 (S15), gap to threshold: 0.00383
fix(engine): replace last bare except: with except Exception: in CV fitting block
feat(engine): Add Cat51 Season Era Normalization (v3.1-50cat → v3.1-51cat)
Claude
31a1cb2
8 new features encoding team stats as z-scores vs league-wide running
average for the current season. Removes era drift across 2018-2026
data (league ORtg ~98 in 2018-19 vs ~115 in 2025-26 due to pace/rules).
Features: era51_h_ortg_vs_league, era51_h_drtg_vs_league,
era51_a_ortg_vs_league, era51_a_drtg_vs_league,
era51_h_pace_vs_league, era51_a_pace_vs_league,
era51_h_netrtg_vs_league, era51_h_ortg_a_drtg_edge.
Design: running per-season tracker updated AFTER feature extraction
per game — no lookahead bias. Expected Brier delta -0.001 to -0.003.
Research: MDPI 2026 (Info 17:56) season-fixed effects → Brier 0.199.
Both root + hf-space updated. Diff = 0 lines (parity verified).
Add 12 new features encoding the ORDER of last-10-game outcomes:
- seq50_h/a_early_wp: win% in older half of last 10 games
- seq50_h/a_late_wp: win% in recent half (momentum direction)
- seq50_h/a_slope: late_wp - early_wp (positive = improving trajectory)
- seq50_h/a_margin_slope_norm: recent 3 vs older 3 avg margin (/30 normalized)
- seq50_h/a_streak_norm: current streak direction normalized (/10)
- seq50_slope_diff / seq50_streak_diff: cross-team differentials
Research basis: MDPI 2026 (temporal sequence > rolling averages for NBA
prediction), expected Brier delta -0.001 to -0.005 as GA discovers
that seq50_slope_diff captures transitional team states better than
static window averages. Both root + hf-space updated (diff=0).
Cat47 (Drive-Rim Matchup 14f), Cat48 (Passing Network 10f), Cat49
(Play-Type PPP 10f) were implemented last cycle but version string
was not updated. Fixes Supabase experiment tagging — all new GA
runs will now log v3.1-49cat. Parity maintained root==hf-space.
Brain cycle 53 — 2026-04-02
Three quick-win feature categories using data already on disk but previously unused:
- Cat47: Drive-Offense vs Rim-Defense Matchup (14 features) — drive_fg_pct, def_rim_fg_pct
- Cat48: Passing Network Quality (10 features) — AST/pass ratio, potential assists, ball movement
- Cat49: Play-Type Efficiency (10 features) — iso/PnR/spot-up/transition PPP from NBA play-type data
Engine: 6219 → 6253 features (v3.1-46cat)
Tracking data: 20 → 43 per-team features (defense, passing, play-type aggregation added)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds Cat 42 (Shot Quality Zone, 10 features) and Cat 45 (Player Tracking/Hustle,
12 features) bringing total to 6211 features across 43 categories.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat: engine v3.0-41cat — add Cat 39/41/43 to hf-space
Deploy circadian rhythm & travel fatigue (Cat 39),
transition vs half-court splits (Cat 41), and
clutch performance features (Cat 43) to HF Spaces.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: MOVDA raw delta features (Cat37 6→13) + beta calibration + browser scraper
Engine v3.0-38cat: 6149 features. Venue-specific home/away comparisons
(WP edge, margin edge, ORtg/DRtg cross-matchup) at 5/10/20 game windows.
Updated CLAUDE.md and HF README to reflect current architecture.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix: defensive guard against non-dict game entries
- engine.py: skip non-dict entries in build() loop (both root and hf-space)
- predict_today.py: handle Bovada price field as string or dict
- Colab notebook: handle wrapped JSON format {"games": [...]}
Fixes AttributeError: 'str' object has no attribute 'get' on Colab.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: add MOVDA Elo features to engine (Cat 37, 6 features)
MOVDA (arXiv:2506.00348) — Margin of Victory Differential Analysis.
Update rule: R' = R + K*(S-E) + λ*(MOV-E_MOV) where E_MOV = α*tanh(β*ΔR) + γ + δ
6 new features: movda_rating (×2), mov_surprise_ewm (×2), movda_diff, movda_win_prob
Total features: 6129 → 6135. Validated: Brier 0.21877 vs Elo 0.22134 (+1.16%).
NOT deployed to HF Spaces yet — waiting for xgboost_brier fix to stabilize.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix: Category 36 _travel_dist called with wrong args (string index out of range)
_travel_dist(records, team) was called as _travel_dist(home, away)
which passed a team name string where a record list was expected,
causing IndexError on records[-1][3] → "S"[3].
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
10 new categories (26-35): Advanced Player Impact, Referee Deep Analysis,
Venue & Environmental, Advanced Market III, Time Series Decomposition,
Cross-Team Interaction Matrix, Bayesian Priors, Network/Graph Features,
Ensemble Meta-Features, Temporal Decay Features.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
WS1: Real box score data pipeline
- New ops/backfill-boxscores.py — fetches FGM/FGA/FG3M/FG3A/FTM/FTA/OREB/DREB/PF from NBA API
- engine.py _parse_stats() detects real data, computes real possessions/eFG%/pace/ORtg/DRtg
- app.py /api/command now supports backfill_boxscores (background thread)
WS2: Feature engine cleanup
- skip_placeholder flag skips categories 11-15 (all zeros without real data)
- Fitness weights: Brier 70%, Cal 20%, ROI 5%, Sharpe 5% (was 60/20/10/10)
- Soft penalty 0.001 per feature above 80 (replaces hard cliff at 150)
WS3: Karpathy autoresearch loop (S10 side)
- POST /api/checkpoint — saves best individual + Brier to disk
- POST /api/rollback — reverts to specific or best checkpoint
- GET /api/checkpoint/best — returns lowest Brier checkpoint
- Rule 7 LIVE_REGRESSION in run_logger — auto-rollback if live Brier drifts
WS4: Prediction bridge
- fetch_evolved_predictions() calls S10 /api/predict
- predict_game() blends 60% evolved + 40% ensemble when available
Co-A…
feat: 1064 computed features + stacking ensemble + model diversity
- RunLogger: logs every gen/cycle/eval to Supabase PostgreSQL (4 tables)
- 6 auto-cut rules: regression, stagnation, ROI, diversity, features, brier floor
- Integrated into app.py (S10) and genetic_loop_v3.py
- Feature engine expanded: 580 → 2058 features across 25 categories
- New categories: interactions, advanced rolling, season trajectory, lineup,
game theory, environmental, cross-window momentum, market II, power ratings, fatigue
- S10 API endpoints: /api/run-stats, /api/cuts, /api/brier-trend, /api/recent-runs
- Deploy script for S10 HF Space
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>