Previous approach baked playerCoaDispels into group.coaRaidFilter during
OnLayoutApplied, which can fire before PLAYER_LOGIN when C_Player isn't
ready yet — Venomancer and other CoA classes got cached as false and
never re-evaluated.
Fix: move all CoA logic into scan() itself so it runs on every
PLAYER_ENTERING_WORLD update. getCoaDispels() no longer caches when
C_Player is unavailable (returns nil without storing), so the first
successful in-world call populates it correctly.
updateGroup() is restored to its original form — no group.coaRaidFilter.
scan() intercepts filter=="HARMFUL|RAID", calls getCoaDispels(), and if
a dispel set is found strips |RAID and applies the per-type check inline.
UnitAura "HARMFUL|RAID" only honours vanilla class dispel knowledge in
the 3.3.5 client — CoA custom classes (Chronomancer, Monk/Templar,
Prophet/Venomancer, etc.) were silently filtered to zero debuffs.
Fix: in updateGroup(), detect CoA dispellers via C_Player:IsCustomClass()
and store their per-class dispel set on group.coaRaidFilter instead of
appending |RAID. scan() skips debuffs whose auraType is not in that
set, preserving contiguous button layout with no gaps.
Class → dispel types (sourced from coa-decursive):
CHRONOMANCER Magic/Curse/Disease/Poison (Roll Back 804490)
MONK Magic/Disease/Poison (Rebuke 525051)
PROPHET Poison (Antivenom 800905; curse-dispel doesn't fire)
PYROMANCER Disease/Poison
RANGER Disease/Poison
CULTIST Curse
SONOFARUGAL Curse
SPIRITMAGE Magic
STARCALLER Magic
WITCHHUNTER Curse
The strata was defaulting much higher than it should be and was overlapping with other frames such as the character pane. This was applying to all bars including raid, player, and party.