Add a generic opponent-removal detector to packages/synergy-engine/src/utils/cardHelpers.ts — the one real engine gap (only per-classification hasNegativeTargeting and your-own self-banish exist today).
Scope — getRemovalRoles(card): RemovalRole[] where role ∈ banish | conditional-banish | damage | debuff | bounce.
- Exclude self-banish (reuse
SACRIFICE_SELF_BANISH_PATTERN as a negative gate).
- Reuse
getActionDamage/isMultiTargetDamageAction (damage) and getBounceRoles 'opponent-bounce' (bounce) — don't re-parse.
- Also emit the trigger condition (
low-strength ≤N / evasive / bodyguard / damaged / high-cost ≥N / mass) that feeds the vulnerability (hoser) catalog.
- Export via
utils/index.ts.
Tests: hard banish, conditional banish, burn action, self-banish must NOT match, opponent bounce, condition extraction.
Watch: the engine-auto-rebuild hook runs build:engine + precompute-synergies; keep CodeScene CC ≤10 (extract helpers).
Part of #450 · Deck Builder & Engine Score milestone.
Add a generic opponent-removal detector to
packages/synergy-engine/src/utils/cardHelpers.ts— the one real engine gap (only per-classificationhasNegativeTargetingand your-ownself-banishexist today).Scope —
getRemovalRoles(card): RemovalRole[]where role ∈banish | conditional-banish | damage | debuff | bounce.SACRIFICE_SELF_BANISH_PATTERNas a negative gate).getActionDamage/isMultiTargetDamageAction(damage) andgetBounceRoles'opponent-bounce'(bounce) — don't re-parse.low-strength ≤N/evasive/bodyguard/damaged/high-cost ≥N/mass) that feeds the vulnerability (hoser) catalog.utils/index.ts.Tests: hard banish, conditional banish, burn action, self-banish must NOT match, opponent bounce, condition extraction.
Watch: the
engine-auto-rebuildhook runs build:engine + precompute-synergies; keep CodeScene CC ≤10 (extract helpers).Part of #450 · Deck Builder & Engine Score milestone.