v1.0.1 — T-109 combatant filter
- `ingest/events.py::prune_inactive_combatants(session, fight_id)` — deletes combatants whose `player_id` never appears as a `source_id` in this fight's `cast`/`damage`/`calculate…
Added — T-109 tighten T-004 combatant filter for Ultimate reports
ingest/events.py::prune_inactive_combatants(session, fight_id)— deletes combatants whoseplayer_idnever appears as asource_idin this fight'scast/damage/calculateddamageevents. Same active-players definition T-203/T-206/T-207 already use downstream. No-op when the fight has no events yet, so the speculative roster seeded by T-004 isn't wiped before T-005 runs.- Wired into
ingest_events_for_report: after the event loop flushes, every fight in the report is pruned in one pass. Result dict grows acombatants_prunedcounter. scripts/backfill_prune_combatants.py [report_code…]— one-shot to clean up reports that landed before this patch. Per-report before/after counts + grand total.- 6 new unit tests covering active intersection / idempotency / no-events safety / non-active event-type rejection / null source-id rejection / scoping. 287 tests total (281 → 287).
- Live AC on FRU report
4RVNq7drBDLG3JZw: fight#163(the one kill with events ingested) dropped from 11,899 → 10 combatants (99.92% reduction, ≈ the 8 real players + 2 game-actor stragglers). The 207 metadata-only fights stayed at 11,899 each — by design, since they have no events to filter against; the next time their events land, the prune kicks in automatically. Backfill swept 56 reports total, pruned 16,599 rows where events existed.
Note
- Downstream
_active_players()workarounds in T-203/T-206/T-207/etc. still function unchanged — they're now redundant for fights whose events have been pulled, but harmless. Leaving them in place keeps a belt-and-suspenders guard.