v0.24.0 — ### Added
- **T-204** Empirical DPS check (PLAN §9 M-INFER #4). `analysis/dps_check.py::dps_check_for_encounter()` aggregates per-phase raid-DPS across every ingested kill of an encounter;…
- T-204 Empirical DPS check (PLAN §9 M-INFER #4).
analysis/dps_check.py::dps_check_for_encounter()aggregates per-phase raid-DPS across every ingested kill of an encounter; returns{p25, p50, p75, min, max, n}per phase. The median = the empirical DPS target — if a pull's phase-X raid DPS is below it, that gate is DPS, not mechanics. Powers T-207's gated-vs-mechanics verdict. compare_fight_to_target()returns a per-phase verdict (below_p25/between_p25_p75/above_p75/no_target) for one fight against its encounter's distribution.- API:
GET /api/encounters/{id}/dps-check(target distribution) +GET /api/fights/{id}/dps-check(per-fight comparison). - 9 new tests (3 quartile + 5 end-to-end synthetic + 1 live FRU). 201 tests total.
- Live AC on FRU (11 kills aggregated): P0 median 152k raid-DPS, P1 119k (lowest — long phase with downtime), P2 204k (highest — Adds cleave bonus), P3 170k, P4 149k, P5 187k (burst phase). p25–p75 spread is ~3% on every phase — tight because all 11 kills come from top-ranked groups; loose prog data would widen this.
Note on the "HP at enrage" framing
PLAN §9 M-INFER #4 calls for HP-at-enrage estimation. FFLogs events emit damage deltas, not HP percentages, so direct HP isn't readable. We compute the equivalent gating signal — raid DPS that historically completes each phase — which is what M-GATE needs in practice. If a future requirement needs the literal HP%, FFLogs fightPercentage on the wipe fight plus boss-max-HP from rankings could reconstruct it.