v0.21.0 — ### Added
- **T-203** Mechanic classification. `analysis/mechanic_classifier.py::classify_canonical_abilities()` walks `fight_model` rows for an encounter, scans damage events each canonica…
- T-203 Mechanic classification.
analysis/mechanic_classifier.py::classify_canonical_abilities()walksfight_modelrows for an encounter, scans damage events each canonical ability produced across ingested kills, and labels by effect signature:raidwide— hits ≥6 players simultaneouslytankbuster— single target, mean damage ≥50kaoe_party— 2–5 simultaneous targets (spread/stack candidate)enrage— last canonical ability in phase + ≥5 player deaths within 3s of cast (rare in pure-kill data, will activate on prog wipes)cosmetic— no damage events found (visual/transition casts)unknown— heuristic couldn't decide
- "Active players" filter intentionally stricter than raw
combatants(FFLogs masterData leaks NPCs on Ultimates) — counts only IDs that produced ≥1 cast or damage. - Writes back to
fight_model.type_label; preserves signature intometa.signaturefor later inspection. - API:
POST /api/encounters/{id}/fight-model/classify. - 8 new tests (5 pure-function label tests + synthetic 3-pull fixture + missing-rows edge case + live FRU AC). 184 tests total.
- Live AC on FRU: 149 abilities labeled — 40 raidwides, 13 tankbusters, 17 aoe_party, 74 cosmetic, 5 unknown. Correctly picked up known mechanics like the P1 tankbuster combo at +11s/+15s (Burnished Glory / Burnt Strike).