You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Exhaustion and Icebreaker Kraken's compound-subject "don't untap" restriction — "Creatures and lands target opponent controls don't untap during their next untap step."
and "...artifacts and creatures target opponent controls don't untap during that player's next untap step."
— currently strict-fail (verified against data/coverage-data.json: both supported: false, gap_count: 1, with a bare partial-match label "creatures"/no label at all for the restriction
clause).
This is the same structural gap shape as #5219 (Life and Limb's compound-subject animation
static): a compound subject joined by "and" where each individual conjunct is already fully
supported on its own, but the combination is unhandled.
Verified card text (Scryfall API)
Exhaustion (sorcery): Creatures and lands target opponent controls don't untap during their next untap step.
Icebreaker Kraken (ETB trigger): When this creature enters, artifacts and creatures target opponent controls don't untap during that player's next untap step.
Proof the single-subject predicate is already fully correct
Two real, currently-supported: true cards confirm the single-subject sibling of this exact
predicate is complete end-to-end (verified against data/coverage-data.json):
Misstep: Creatures target player controls don't untap during that player's next untap step.
Mana Vapors: Lands target player controls don't untap during their next untap step.
Between them these are literally the two halves Exhaustion combines ("creatures ... don't
untap" + "lands ... don't untap" → "creatures and lands ... don't untap"). The predicate builder
(build_restriction_clause in crates/engine/src/parser/oracle_effect/subject.rs:4350) already
produces the correct StaticMode::CantUntap + Duration::UntilNextStepOf { step: Phase::Untap, player: PlayerScope::Controller } (CR 502.3, see the has_next_untap handling at subject.rs:4397-4410). So this is not a predicate gap (unlike #5219, which needed two
predicate-halves merged) — it is purely a compound-subject gap.
Root cause (subject side)
The single-subject case reaches its filter through parse_subject_application's bare
plural-noun-phrase fallback (oracle_effect/subject.rs:2139-2165), which prepends "all " and
delegates whole to parse_target/parse_type_phrase_with_ctx
(oracle_target.rs:1909). That function does have a general "X and Y <shared suffix>"
core-type splitter (the TYPE_SEPARATORS recursion at oracle_target.rs:2440-2497), which
already Or-combines compound core-type nouns for other suffixes — e.g. the existing passing
test artifacts_and_creatures_your_opponents_control (oracle_target.rs:11048) confirms "artifacts and creatures your opponents control" → Or[Artifact+Opponent, Creature+Opponent]
via distribute_controller_to_or (oracle_target.rs:3723).
parse_zone_controller (oracle_nom/filter.rs:99) separately recognizes "target player controls" → ControllerRef::TargetPlayer and "target opponent controls" → ControllerRef::TargetOpponent as its own suffix arms. Exhaustion/Icebreaker Kraken strict-fail
on the compound form of this specific controller-suffix family — needs tracing at
implementation time to confirm exactly which stage drops the second conjunct (candidates: the starts_with_type_word/can_recurse gate on the right-hand leg, distribute_controller_to_or's
handling of the TargetOpponent/TargetPlayer variants specifically, or parse_subject_application's subject_filter_application(filter, false) call not surfacing the two conjuncts' shared target-player
slot correctly for try_parse_subject_restriction_clause's predicate builder).
Add a compound-subject dispatcher for this restriction-predicate class, following the same
shape as #5219 and its siblings (parse_compound_all_subjects_type_change / try_parse_compound_all_subjects_become_clause):
A new subject-splitter that recognizes "<X> and <Y>[ and <Z>...] target player|opponent controls", splits on " and ", resolves each conjunct's bare type word
independently (reusing the existing single-conjunct path that already works for Misstep/Mana
Vapors), and Or-combines them with the shared controller suffix distributed to every leg —
reusing distribute_controller_to_or if it turns out to already generalize, or extending it
if the TargetPlayer/TargetOpponent variants need explicit registration.
Tests: positive parses for Exhaustion's and Icebreaker Kraken's exact verbatim predicate
(asserting the Or of two Typed filters sharing ControllerRef::TargetOpponent, the CantUntap mode, and the UntilNextStepOf duration), plus confirmation that Misstep/Mana
Vapors (single-subject) still route unchanged.
No new StaticMode, Duration variant, or runtime is needed — CantUntap + Duration::UntilNextStepOf + TargetFilter::Or + ControllerRef::TargetOpponent all already
exist and are exercised end-to-end by existing supported cards.
CR references (grep-verified against docs/MagicCompRules.txt at implementation time)
CR 502.3 — Untap Step: effects that keep a permanent from untapping.
CR 611.3 — a continuous static effect applies to every object its text indicates (the
Or-distributed affected set).
Parser-only (crates/engine/src/parser/oracle_target.rs and/or crates/engine/src/parser/oracle_effect/subject.rs, plus their test files) — no engine
types/runtime changes expected, matching #5219's file footprint.
Summary
Exhaustion and Icebreaker Kraken's compound-subject "don't untap" restriction —
"Creatures and lands target opponent controls don't untap during their next untap step."and
"...artifacts and creatures target opponent controls don't untap during that player's next untap step."— currently strict-fail (verified against
data/coverage-data.json: bothsupported: false,gap_count: 1, with a bare partial-match label"creatures"/no label at all for the restrictionclause).
This is the same structural gap shape as #5219 (Life and Limb's compound-subject animation
static): a compound subject joined by "and" where each individual conjunct is already fully
supported on its own, but the combination is unhandled.
Verified card text (Scryfall API)
Creatures and lands target opponent controls don't untap during their next untap step.When this creature enters, artifacts and creatures target opponent controls don't untap during that player's next untap step.Proof the single-subject predicate is already fully correct
Two real, currently-
supported: truecards confirm the single-subject sibling of this exactpredicate is complete end-to-end (verified against
data/coverage-data.json):Creatures target player controls don't untap during that player's next untap step.Lands target player controls don't untap during their next untap step.Between them these are literally the two halves Exhaustion combines ("creatures ... don't
untap" + "lands ... don't untap" → "creatures and lands ... don't untap"). The predicate builder
(
build_restriction_clauseincrates/engine/src/parser/oracle_effect/subject.rs:4350) alreadyproduces the correct
StaticMode::CantUntap+Duration::UntilNextStepOf { step: Phase::Untap, player: PlayerScope::Controller }(CR 502.3, see thehas_next_untaphandling atsubject.rs:4397-4410). So this is not a predicate gap (unlike #5219, which needed twopredicate-halves merged) — it is purely a compound-subject gap.
Root cause (subject side)
The single-subject case reaches its filter through
parse_subject_application's bareplural-noun-phrase fallback (
oracle_effect/subject.rs:2139-2165), which prepends"all "anddelegates whole to
parse_target/parse_type_phrase_with_ctx(
oracle_target.rs:1909). That function does have a general "X and Y <shared suffix>"core-type splitter (the
TYPE_SEPARATORSrecursion atoracle_target.rs:2440-2497), whichalready Or-combines compound core-type nouns for other suffixes — e.g. the existing passing
test
artifacts_and_creatures_your_opponents_control(oracle_target.rs:11048) confirms"artifacts and creatures your opponents control"→Or[Artifact+Opponent, Creature+Opponent]via
distribute_controller_to_or(oracle_target.rs:3723).parse_zone_controller(oracle_nom/filter.rs:99) separately recognizes"target player controls"→ControllerRef::TargetPlayerand"target opponent controls"→ControllerRef::TargetOpponentas its own suffix arms. Exhaustion/Icebreaker Kraken strict-failon the compound form of this specific controller-suffix family — needs tracing at
implementation time to confirm exactly which stage drops the second conjunct (candidates: the
starts_with_type_word/can_recursegate on the right-hand leg,distribute_controller_to_or'shandling of the
TargetOpponent/TargetPlayervariants specifically, orparse_subject_application'ssubject_filter_application(filter, false)call not surfacing the two conjuncts' shared target-playerslot correctly for
try_parse_subject_restriction_clause's predicate builder).Proposed fix (mirrors #5219's structural shape)
Add a compound-subject dispatcher for this restriction-predicate class, following the same
shape as #5219 and its siblings (
parse_compound_all_subjects_type_change/try_parse_compound_all_subjects_become_clause):"<X> and <Y>[ and <Z>...] target player|opponent controls", splits on" and ", resolves each conjunct's bare type wordindependently (reusing the existing single-conjunct path that already works for Misstep/Mana
Vapors), and
Or-combines them with the shared controller suffix distributed to every leg —reusing
distribute_controller_to_orif it turns out to already generalize, or extending itif the
TargetPlayer/TargetOpponentvariants need explicit registration.drop, with a comment explaining the ordering (mirroring feat(parser): compound-subject animation static — Life and Limb (CR 611.3) #5219's dispatch-order comment
discipline).
(asserting the
Orof twoTypedfilters sharingControllerRef::TargetOpponent, theCantUntapmode, and theUntilNextStepOfduration), plus confirmation that Misstep/ManaVapors (single-subject) still route unchanged.
No new
StaticMode,Durationvariant, or runtime is needed —CantUntap+Duration::UntilNextStepOf+TargetFilter::Or+ControllerRef::TargetOpponentall alreadyexist and are exercised end-to-end by existing supported cards.
CR references (grep-verified against
docs/MagicCompRules.txtat implementation time)Or-distributed affected set).
Scope
Parser-only (
crates/engine/src/parser/oracle_target.rsand/orcrates/engine/src/parser/oracle_effect/subject.rs, plus their test files) — no enginetypes/runtime changes expected, matching #5219's file footprint.