Skip to content

fix(engine): scope hexproof-bypass statics to their beneficiary (Glaring Spotlight)#5389

Merged
matthewevans merged 2 commits into
phase-rs:mainfrom
galuis116:fix/ignore-hexproof-you-control
Jul 8, 2026
Merged

fix(engine): scope hexproof-bypass statics to their beneficiary (Glaring Spotlight)#5389
matthewevans merged 2 commits into
phase-rs:mainfrom
galuis116:fix/ignore-hexproof-you-control

Conversation

@galuis116

@galuis116 galuis116 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Closes #5386.

What

Glaring Spotlight — "Creatures your opponents control with hexproof can be the targets of spells and abilities you control as though they didn't have hexproof." — restricts the hexproof bypass to the static controller's spells and abilities. Nowhere to Run's unqualified form ("...can be the targets of spells and abilities as though they didn't have hexproof") opens the affected creatures to every player.

The parser previously consumed the you control qualifier and discarded it, emitting an identical unrestricted IgnoreHexproof for both cards. That is correct in 1v1 but wrong in multiplayer: a third player would wrongly be able to target the affected creatures through Glaring Spotlight.

How (building block, not a special case)

Parameterize the bypass beneficiary on StaticDefinition — mirroring the existing mode-specific optional fields attack_defended (CantAttack) and source_controller (lure statics):

pub bypass_beneficiary: Option<ControllerRef>,
//   None      = every player's spells and abilities (Nowhere to Run)
//   Some(You) = the static controller's only          (Glaring Spotlight)
  • Parser (oracle_static/shared.rs): opt(tag(" you control")) now drives bypass_beneficiary = you_control.then_some(ControllerRef::You) instead of being discarded.
  • Resolver (static_abilities::target_ignores_hexproof): now takes the targeting source's controller and gates the grant through ignore_hexproof_beneficiary_allowsNone ⇒ any player; Some(You) ⇒ only the static controller (CR 109.5); other refs fail closed.
  • Serde-defaulted, so all existing serialized statics (unrestricted) round-trip unchanged.

CR

Corrects the citations flagged in review: the "as though it didn't have hexproof" targeting permission is CR 702.11e / CR 609.4, not CR 702.11b (which only defines hexproof itself). Beneficiary resolution is CR 109.5.

Tests

  • Parser: you controlSome(You); unqualified ⇒ None.
  • Multiplayer enforcement (targeting.rs): controller can target the affected creature; a third player cannot (revert-probe) — alongside the existing Nowhere to Run "any player" test.

Verification

cargo fmt --all ✓ · full engine lib suite 15,775 pass / 0 fail ✓ · clippy -p engine -p phase-ai --all-targets -D warnings clean ✓

@galuis116 galuis116 requested a review from matthewevans as a code owner July 8, 2026 19:18

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the static hexproof bypass parser to optionally consume the 'you control' qualifier and adds a corresponding test. The review feedback highlights that the comments and tests cite the incorrect Comprehensive Rules section (CR 702.11b instead of CR 702.11e / CR 609.4) and identifies a multiplayer rules fidelity gap because the engine currently discards this qualifier rather than parameterizing the static mode.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +35 to +40
// CR 702.11b: an optional "you control" qualifier scopes WHICH spells and
// abilities bypass hexproof (Glaring Spotlight, Detection Tower, Kaya,
// Bane of the Dead). The bypass is a targeting permission on the affected
// permanents regardless of whose spell/ability targets them, so the
// qualifier doesn't change the emitted `IgnoreHexproof` — it just has to
// be consumed. Nowhere to Run omits it (bare "of spells and abilities").

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

[HIGH] Incorrect CR citation and unhandled multiplayer rules difference. Evidence: crates/engine/src/parser/oracle_static/shared.rs:35-40.

Why it matters:

  1. CR Citation (R6): CR 702.11b only defines the basic hexproof keyword on a permanent. The rules governing "as though" targeting permissions and hexproof bypasses are CR 702.11e and CR 609.4.
  2. CR Fidelity (Pillar 2): Glaring Spotlight restricts the bypass to spells and abilities you control, whereas Nowhere to Run allows any player's spells and abilities to target the affected creatures in multiplayer. Discarding the qualifier and emitting the same unqualified IgnoreHexproof static mode creates a functional rules discrepancy in multiplayer games.

Suggested fix: Update the comment to cite CR 702.11e / CR 609.4 and document this engine gap. Ideally, StaticMode::IgnoreHexproof should be parameterized with Option<ControllerRef> (per R2/R3) in a follow-up engine PR to fully resolve the multiplayer rules difference.

Suggested change
// CR 702.11b: an optional "you control" qualifier scopes WHICH spells and
// abilities bypass hexproof (Glaring Spotlight, Detection Tower, Kaya,
// Bane of the Dead). The bypass is a targeting permission on the affected
// permanents regardless of whose spell/ability targets them, so the
// qualifier doesn't change the emitted `IgnoreHexproof` — it just has to
// be consumed. Nowhere to Run omits it (bare "of spells and abilities").
// CR 702.11e / CR 609.4: an optional "you control" qualifier scopes WHICH spells and
// abilities bypass hexproof (Glaring Spotlight, Detection Tower, Kaya,
// Bane of the Dead). Note: Currently, the engine's IgnoreHexproof static mode
// does not distinguish this scope from unqualified bypasses (like Nowhere to Run),
// which is a multiplayer rules fidelity gap to be addressed in the engine.
References
  1. Strict fidelity to the MTG Comprehensive Rules (CR) — every game rule, validation, and computed value matches the CR exactly. Convenience shortcuts that get rules wrong are not simpler; they are wrong. (link)
  2. CR annotations are mandatory and verified. Every rules-touching line of engine code must carry a comment of the form CR : . (link)

Comment on lines +524 to +530
/// CR 702.11b: Glaring Spotlight — "Creatures your opponents control with
/// hexproof can be the targets of spells and abilities YOU CONTROL as though
/// they didn't have hexproof." The optional "you control" qualifier between
/// "spells and abilities" and "as though" must be consumed; the bypass is a
/// targeting permission on the affected permanents, so it emits the same single
/// `IgnoreHexproof` as the unqualified Nowhere to Run form, scoped to opponents'
/// creatures.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

[MEDIUM] Incorrect CR citation in test documentation. Evidence: crates/engine/src/parser/oracle_static/tests.rs:524.

Why it matters: CR 702.11b only defines the basic hexproof keyword on a permanent. The rules governing "as though" targeting permissions and hexproof bypasses are CR 702.11e and CR 609.4.

Suggested fix: Update the test documentation to cite CR 702.11e and CR 609.4.

Suggested change
/// CR 702.11b: Glaring Spotlight — "Creatures your opponents control with
/// hexproof can be the targets of spells and abilities YOU CONTROL as though
/// they didn't have hexproof." The optional "you control" qualifier between
/// "spells and abilities" and "as though" must be consumed; the bypass is a
/// targeting permission on the affected permanents, so it emits the same single
/// `IgnoreHexproof` as the unqualified Nowhere to Run form, scoped to opponents'
/// creatures.
/// CR 702.11e / CR 609.4: Glaring Spotlight — "Creatures your opponents control with
/// hexproof can be the targets of spells and abilities YOU CONTROL as though
/// they didn't have hexproof." The optional "you control" qualifier between
/// "spells and abilities" and "as though" must be consumed; the bypass is a
/// targeting permission on the affected permanents, so it emits the same single
/// IgnoreHexproof as the unqualified Nowhere to Run form, scoped to opponents'
/// creatures.
References
  1. CR annotations are mandatory and verified. Every rules-touching line of engine code must carry a comment of the form CR : . (link)

@matthewevans matthewevans left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MED] you control is consumed but not represented, so Glaring Spotlight gets a broader hexproof bypass than printed. Evidence: crates/engine/src/parser/oracle_static/shared.rs:35 says the qualifier does not change the emitted IgnoreHexproof, and crates/engine/src/parser/oracle_static/tests.rs:524 only asserts the parser emits the unqualified mode. The existing runtime contract for object-scoped IgnoreHexproof is source-controller-independent (see targeting.rs's Nowhere to Run multiplayer coverage), which is correct for unqualified “spells and abilities” but wrong for “spells and abilities you control.” Why it matters: this would make opponents’ and third players’ spells/abilities able to target the affected hexproof creatures, falsely marking Glaring Spotlight supported with stronger behavior than Oracle grants. Suggested fix: model the source-controller axis on the bypass authority, or leave the you control form unsupported until the runtime can enforce it.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Parse changes introduced by this PR

Baseline pending for cad7062e46ef10af5e5c935feb507e1cde74e90c — this populates once main publishes its coverage snapshot (a few minutes after that commit landed).

galuis116 added 2 commits July 8, 2026 16:54
phase-rs#5386)

Glaring Spotlight's "Creatures your opponents control with hexproof can be the
targets of spells and abilities you control as though they didn't have hexproof"
dropped to Unimplemented. `parse_ignore_hexproof_static` matched the bypass
phrase verbatim as "of spells and abilities as though", so the optional
"you control" qualifier some cards insert (Glaring Spotlight) failed the match
and the `IgnoreHexproof` static was never emitted.

Split the phrase and consume an optional " you control" between "spells and
abilities" and "as though". The qualifier scopes which spells/abilities bypass
hexproof but the bypass is a targeting permission on the affected permanents, so
the emitted `IgnoreHexproof` is unchanged — Nowhere to Run (no qualifier) still
parses identically. Glaring Spotlight now emits `IgnoreHexproof` scoped to
opponents' hexproof creatures.

Closes phase-rs#5386.

Test: the "you control" form emits a single `IgnoreHexproof` scoped to
opponents' creatures; existing Nowhere to Run tests unchanged.
…e-rs#5386)

Address review on phase-rs#5386: the "you control" qualifier on a hexproof-bypass
static is semantically load-bearing in multiplayer. Glaring Spotlight —
"Creatures your opponents control with hexproof can be the targets of
spells and abilities YOU CONTROL as though they didn't have hexproof" —
restricts the bypass to the static controller's spells and abilities,
whereas Nowhere to Run's unqualified form opens the affected creatures to
every player. The prior commit consumed and discarded the qualifier,
emitting an identical unrestricted IgnoreHexproof for both — wrong in
multiplayer.

Parameterize the bypass beneficiary via a new StaticDefinition
`bypass_beneficiary: Option<ControllerRef>` field (mirrors the existing
mode-specific `attack_defended` / `source_controller` optional fields):
  - None      = every player's spells and abilities (Nowhere to Run)
  - Some(You) = the static controller's only (Glaring Spotlight)

`target_ignores_hexproof` now takes the targeting source's controller and
honors the beneficiary before granting the bypass. Also corrects the CR
citations to CR 702.11e / CR 609.4 (the "as though ... no hexproof"
targeting-permission rules) instead of CR 702.11b (which only defines
hexproof itself).

CR 702.11e / CR 609.4 / CR 109.5.
@galuis116 galuis116 force-pushed the fix/ignore-hexproof-you-control branch from 8b49313 to f4f4901 Compare July 8, 2026 19:55
@galuis116 galuis116 changed the title fix(parser): accept "you control" qualifier in hexproof-bypass statics (Glaring Spotlight) fix(engine): scope hexproof-bypass statics to their beneficiary (Glaring Spotlight) Jul 8, 2026
@galuis116

Copy link
Copy Markdown
Contributor Author

Thanks — both points addressed in the latest push.

CR citation (MEDIUM): corrected to CR 702.11e / CR 609.4 (the "as though ... no hexproof" targeting-permission rules) in the code, tests, and doc comments; CR 702.11b remains only where it's cited as the definition of hexproof itself.

Multiplayer fidelity (HIGH): the you control qualifier is no longer discarded. It now drives a new StaticDefinition::bypass_beneficiary: Option<ControllerRef> field (mirroring the existing mode-specific attack_defended / source_controller fields):

  • None — every player (Nowhere to Run)
  • Some(ControllerRef::You) — the static controller only (Glaring Spotlight)

target_ignores_hexproof now takes the targeting source's controller and honors the beneficiary (CR 109.5), so in a 3-player game Glaring Spotlight lets its controller bypass hexproof while a third player stays blocked. Added a multiplayer enforcement test (with a revert-probe) plus the parser-level Some(You) / None assertions.

@matthewevans matthewevans self-assigned this Jul 8, 2026

@matthewevans matthewevans left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainer review: current head represents the Glaring Spotlight beneficiary qualifier and covers the multiplayer targeting split; auto-merge will wait for pending checks.

@matthewevans matthewevans added the bug Bug fix label Jul 8, 2026
@matthewevans matthewevans enabled auto-merge July 8, 2026 20:07
@matthewevans matthewevans removed their assignment Jul 8, 2026
@matthewevans matthewevans added this pull request to the merge queue Jul 8, 2026
Merged via the queue into phase-rs:main with commit 2418d7a Jul 8, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Card Bug] Glaring Spotlight — hexproof bypass with "you control" qualifier doesn't parse

2 participants