From f3760109b428dc4ba1958c987de624173d05b239 Mon Sep 17 00:00:00 2001 From: Chris Hondl Date: Tue, 28 Jul 2026 11:52:41 -0700 Subject: [PATCH] docs(backend): EPA rating is EPARating, not SkewNormal Upstream #412 (169330e, 2026-06-11) deleted the SkewNormal class and replaced it with a mean-only EPARating. backend/CLAUDE.md still described the old model. Also record the API break that came with it, since it generates user reports: dropping the distribution dropped epa_sd/epa_skew/epa_n from TeamEvent/TeamYear, which flattened epa.total_points from {mean, sd} to a float and removed epa.conf on /v3/team_events and /v3/team_years. --- backend/CLAUDE.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/backend/CLAUDE.md b/backend/CLAUDE.md index 62b42b2b..2f1d8e51 100644 --- a/backend/CLAUDE.md +++ b/backend/CLAUDE.md @@ -57,9 +57,21 @@ The `EPA` class (in `main.py`) extends the `Model` base class (`src/models/templ - `start_season()` — initialize per-team ratings from prior years - `predict_match()` — produce score predictions for both alliances - `attribute_match()` — compute per-team error attribution after a match -- `update_team()` — update the team's rating distribution - -Each team's rating is a `SkewNormal` distribution (`src/models/epa/math.py`). +- `update_team()` — update the team's rating + +Each team's rating is an `EPARating` (`src/models/epa/math.py`): a per-dimension +mean vector updated by an exponentially-weighted moving average (`add_obs`). It +carries **no variance** — there is no per-team `sd`. + +> **Gotcha — this replaced a `SkewNormal` distribution in upstream #412 +> (`169330e`, 2026-06-11), and that removed public API fields.** Along with the +> distribution went the `epa_sd`/`epa_skew`/`epa_n` columns on `TeamEvent` and +> `TeamYear`, and with them `epa.total_points.{mean,sd}` (now a bare float) and +> `epa.conf` on `/v3/team_events` and `/v3/team_years`. Clients written against +> the pre-June-2026 API break on this. `Event.epa_sd` is unrelated and still +> exists — it is the stdev *across* a field's teams (`src/data/epa/agg.py`), not +> a team's own uncertainty. Restoring `sd` would mean re-adding model state, not +> just a serializer change. **EPA dimensions** (for 2016+): `[total, auto, teleop, endgame, rp_1, rp_2, rp_3, tiebreaker, comp_0..comp_9]` — indices 0-17 (max). Pre-2016 only uses `total`.