Skip to content

fix(parser): preserve TrackedSet on plural 'those tokens' delayed exile#6199

Merged
matthewevans merged 6 commits into
phase-rs:mainfrom
andriypolanski:fix/5972-saheeli-those-tokens-tracked-set
Jul 19, 2026
Merged

fix(parser): preserve TrackedSet on plural 'those tokens' delayed exile#6199
matthewevans merged 6 commits into
phase-rs:mainfrom
andriypolanski:fix/5972-saheeli-those-tokens-tracked-set

Conversation

@andriypolanski

Copy link
Copy Markdown
Contributor

Closes #5972

Summary

Discord report: Saheeli, the Gifted's [-7] creates a token copy of each artifact you control, grants them haste, then should exile all of those tokens at the next end step — but only the last-created token was exiled.

Root cause: after rewrite_parent_targets_to_tracked_set correctly bound plural "those tokens" to TrackedSet { id: 0 } with uses_tracked_set: true, the post-token resolve_populated_token_anaphors pass rewrote TrackedSetLastCreated on the delayed ChangeZone exile. LastCreated only snapshots the final token in a multi-token batch.

Fix: preserve TrackedSet in rewrite_parent_target_to_last_created's ChangeZone arm. Singular "it"/"that token" cleanup (Flameshadow Conjuring, Inalla) still rewrites ParentTarget/TriggeringSourceLastCreated.

Changes

  • crates/engine/src/parser/oracle_effect/lower.rs — stop stomping TrackedSet to LastCreated on delayed plural-token exile cleanup.
  • crates/engine/src/parser/oracle_effect/tests.rs — Saheeli -7 regression: delayed exile stays TrackedSet + uses_tracked_set: true.
  • crates/engine/src/parser/oracle_tests.rs — Twinflame regression: inner delayed exile target is TrackedSet, not LastCreated.

Test Plan

  • cargo fmt --all -- --check
  • cargo test -p engine --lib saheeli_minus_seven_those_tokens_delayed_exile_keeps_tracked_set
  • cargo test -p engine --lib twinflame_full_parse
  • cargo test -p engine --lib etb_token_copier_exile_anaphor_binds_created_token
  • cargo test -p engine --lib delayed_trigger_change_zone_after_token_creator_rewrites_to_last_created
  • Regenerate card-data (./scripts/gen-card-data.sh or Tilt card-data) so Saheeli's [-7] execute body picks up the parser fix in runtime

@superagent-security superagent-security Bot added the contributor:flagged Contributor flagged for review by trust analysis. label Jul 19, 2026
@superagent-security

Copy link
Copy Markdown

🚨 Contributor flagged. Click here for more info: Superagent Dashboard

@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 resolves issue #5972 by ensuring that plural 'those tokens' references, which are rewritten to TrackedSet, are not incorrectly overwritten by LastCreated in rewrite_parent_target_to_last_created. The match criteria in lower.rs have been updated to exclude TargetFilter::TrackedSet, and the twinflame_full_parse test has been expanded to assert that the delayed trigger's zone change correctly targets the TrackedSet. No review comments were provided, so there is no additional feedback to address.

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.

@github-actions

github-actions Bot commented Jul 19, 2026

Copy link
Copy Markdown

Parse changes introduced by this PR · 1 card(s), 1 signature(s) (baseline: main 777dbabf8a38)

🟡 Modified fields (1 signature)

  • 1 card · 🔄 ability/ChangeZone · changed field target: last createdtracked set #0
    • Affected (first 3): Mysterio, Master of Illusion

1 card(s) had Oracle-text changes (errata/reprint) — excluded as non-parser.

@matthewevans matthewevans self-assigned this Jul 19, 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.

Request changes — the parser change identifies the plural anaphor but sends battlefield tokens to an exile-only delayed-trigger resolver.

🔴 Blockers

  • crates/engine/src/parser/oracle_effect/lower.rs:3032-3045 preserves TrackedSet for the cleanup, but crates/engine/src/game/effects/delayed_trigger.rs:687-737 then turns every delayed ChangeZone { TrackedSet } into ChangeZoneAll { origin: Exile }. The current parse artifact already shows Mysterio's cleanup origin changing battlefield → ∅. Saheeli, Mysterio, and Twinflame create the referenced tokens on the battlefield, so this resolver cannot exile them. Move the completion semantics to a zone/provenance-aware tracked-set binding at bind_tracked_set_to_effect, and add a production delayed-trigger regression that creates multiple tokens, resolves the cleanup, and proves a token that left the battlefield first is not found.

  • The current head fails parser::oracle::tests::altair_ibn_la_ahad_for_each_exile_memory_counter_copy_parses at crates/engine/src/parser/oracle_tests.rs:800: Altaïr's printed “Exile those tokens at end of combat” now lowers to TrackedSet, while the stale test requires LastCreated. Update this sibling through the same runtime design; do not restore the single-token binding.

  • The current <!-- coverage-parse-diff --> reports only Mysterio, while the PR claims Saheeli. parse_effect_chain shape assertions do not prove the actual card pipeline or resolution. Reconcile the card-level diff and add the runtime proof for the claimed card class.

✅ Clean

  • Scryfall confirms the relevant plural cleanup wording for Saheeli, Mysterio, and Altaïr. The parse-diff is current, and the existing Gemini review raised no separate technical finding.

Recommendation: request changes; move the completion semantics into the delayed-trigger tracked-set binding seam, then cover the multiple-token and left-battlefield cases through the real resolution pipeline.

@matthewevans matthewevans added the bug Bug fix label Jul 19, 2026
@matthewevans matthewevans removed their assignment Jul 19, 2026
@matthewevans matthewevans self-assigned this Jul 19, 2026
@matthewevans

Copy link
Copy Markdown
Member

Maintainer fixup pushed to de8a5fa9867f4dc349b52b95fc1fad9331d7f9ec.

  • Preserved the explicit battlefield origin for plural token cleanup while retaining the Exile default for generic tracked-card returns.
  • Replaced the full card-data test load with the committed integration fixture, addressing the CI gate.
  • Restored unrelated generated-file drift so the PR diff is limited to the tracked-set change and its tests.

The refreshed CI suite is now the verification authority.

@matthewevans matthewevans removed their assignment Jul 19, 2026
@andriypolanski

Copy link
Copy Markdown
Contributor Author

Hi, @matthewevans
This pr is working well without any error block.

@matthewevans

Copy link
Copy Markdown
Member

Acknowledged. The maintainer fixup is still the current head, but its current CI run is red, so this remains blocked pending the failing-check diagnosis and a green rerun.

@andriypolanski
andriypolanski force-pushed the fix/5972-saheeli-those-tokens-tracked-set branch from de8a5fa to 903d268 Compare July 19, 2026 17:07
@matthewevans matthewevans self-assigned this Jul 19, 2026
@matthewevans

Copy link
Copy Markdown
Member

Maintainer fixup pushed to 25c0b2fe3c75b985008a12e607883e6bc69ca081.

The failing assertion required Saheeli in the deliberately curated integration fixture, but that fixture contains Twinflame only. I removed the invalid duplicate card-data assertion; the parser-shape test and the real Twinflame delayed-cleanup regression remain. CI has restarted for the new head.

@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.

Approved after the maintainer fixups and branch update. The delayed-trigger binding now preserves the battlefield-origin tracked set, the remaining runtime regression exercises two Twinflame tokens through end-step cleanup, and the invalid fixture assertion was removed. Required CI is still running; merge queue will wait for it.

@matthewevans
matthewevans enabled auto-merge July 19, 2026 17:29
@matthewevans matthewevans removed their assignment Jul 19, 2026
@matthewevans
matthewevans added this pull request to the merge queue Jul 19, 2026
Merged via the queue into phase-rs:main with commit 5931f7a Jul 19, 2026
12 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Bug fix contributor:flagged Contributor flagged for review by trust analysis.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Saheeli, the Gifted bug — The delayed trigger created by Saheeli's [-7] ability doesn't exile any tokens

3 participants