Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
1026 commits
Select commit Hold shift + click to select a range
90097a1
Fix Serpent's Soul-Jar exile and cast-from-exile (fixes #1524) (#2772)
kiannidev Jun 9, 2026
348b11d
fix(engine): scope 'is renowned' condition to event subject vs source…
matthewevans Jun 9, 2026
900cb9c
feat(server): self-host reachability — ngrok tunnel + shareable join …
matthewevans Jun 9, 2026
1489c49
fix(engine): decompose Case 'To solve' conditions via the single cond…
matthewevans Jun 9, 2026
e31a5cd
fix(parser): split Gathering Stone ETB/upkeep trigger and chosen-type…
kiannidev Jun 10, 2026
ad3e8d2
fix(engine): Aven Interrupter ETB exiles chosen stack spell, not itse…
kiannidev Jun 10, 2026
45d3d4b
ci: guard scheduled/deploy workflows against fork execution (#2793)
matthewevans Jun 10, 2026
56f25c5
style(client): enhance deck builder and modal components with thin sc…
milosde111 Jun 10, 2026
517b7f4
fix(engine): add 'becomes the target of a backup ability' trigger pri…
matthewevans Jun 10, 2026
1b6a49b
ship/architecture opinionation (#2802)
matthewevans Jun 10, 2026
872683b
ci: make coverage ratchet informational on push-to-main (#2806)
matthewevans Jun 10, 2026
6ebc42e
chore: refresh metagame feeds (#2810)
matthewevans Jun 10, 2026
db1ece0
release: v0.1.53
Jun 10, 2026
c6e9996
docs(skills): add pr-review-loop continuous PR review sweep skill (#2…
matthewevans Jun 10, 2026
6096258
Zone-change pipeline + type dedup + parser grammar consolidation (#2824)
matthewevans Jun 10, 2026
e606eb8
fix missing art for reversible cards (#2682)
claytonlin1110 Jun 10, 2026
1fdd261
fix(engine): Abundance optional draw replacement followups (#2789)
kiannidev Jun 10, 2026
f39e68b
refactor(engine): dedupe explicit zone extraction for SBA enchant che…
kiannidev Jun 10, 2026
949d054
test(engine): add discriminating Devour post-replacement regression t…
kiannidev Jun 10, 2026
a14f155
test(engine): regression for ChangeZoneAll NeedsChoice resume (Fixes …
kiannidev Jun 10, 2026
d62841d
fix(engine): Wishclaw Talisman passes control to chosen opponent (Fix…
kiannidev Jun 10, 2026
b90db0b
fix(deck-builder): make filter dropdowns full-width and improve Selec…
milosde111 Jun 10, 2026
8c165b4
style(client): theme native number input steppers for dark UI (#2812)
milosde111 Jun 10, 2026
461ad37
test(engine): pin Birthing Ritual end-step trigger behavior (Fixes #5…
kiannidev Jun 10, 2026
21ecbf8
fix(match-setup): improve mobile format picker modal layout and stack…
milosde111 Jun 10, 2026
1c11698
Zone pipeline: bucket-B/C tail migration — graveyard redirects + paus…
matthewevans Jun 10, 2026
f79eb75
fix(engine): honor effective Dash keyword for Ragavan dash cast (Fixe…
kiannidev Jun 10, 2026
57a3402
fix(parser): capture tapped-and-attacking when followed by where-X cl…
nickmopen Jun 10, 2026
29ad009
fix(engine): resolve enters_under for any player ControllerRef (CR 11…
galuis116 Jun 10, 2026
46e1b95
feat(engine): conjure a duplicate of a referenced card (CR 707.2) (#2…
galuis116 Jun 10, 2026
f3916e3
fix(parser): generalize "as long as enchanted creature is X, it ..." …
philluiz2323 Jun 10, 2026
ff32a19
fix(engine): strip cast-only copiables from copy tokens and resolve o…
jsdevninja Jun 10, 2026
c15eb0e
fix(engine): count non-tap combination mana toward castability and au…
kiannidev Jun 10, 2026
78fe73c
test(engine): cover phasing aura re-application after until-EOT expir…
dripsmvcp Jun 10, 2026
65cfa6d
refactor(engine): collapse CastPaymentMode into cast GameAction field…
kiannidev Jun 10, 2026
23842cb
fix(engine): prompt Food/Treasure choice on Tireless Provisioner land…
jsdevninja Jun 10, 2026
e1348a2
fix(engine): merged Mutate permanent leaving fires dies/leaves trigge…
carlos4s Jun 10, 2026
d01f5c0
Zone pipeline Phase B: bucket-A deliveries onto the ApprovedZoneChang…
matthewevans Jun 10, 2026
2776039
fix(engine): revert MDFC back face to front face on zone exit (CR 712…
nickmopen Jun 10, 2026
ea4bce8
refactor(engine): unify tap effects into Effect::SetTapState (#2777) …
dripsmvcp Jun 10, 2026
4960130
Add regression tests for Szarekh attack mill-and-return filter (#2846)
kiannidev Jun 10, 2026
64afa21
fix(deck-builder): honor Seven Dwarves copy-limit override (#2833)
kiannidev Jun 10, 2026
56a38c9
fix(parser): Weathered Wayfarer activation when opponent has more lan…
kiannidev Jun 10, 2026
cad5a6f
fix(parser): Glademuse off-turn intervening-if (#2836)
kiannidev Jun 10, 2026
5c1243f
fix(deck-builder): replace Load deck select with MenuSelect (#2842)
milosde111 Jun 10, 2026
63153c2
fix(engine): Nadier's Nightblade triggers on creature tokens leaving …
kiannidev Jun 10, 2026
5b53a67
Zone pipeline: OQ#3 cast-link preservation + bucket-A closure + cost-…
matthewevans Jun 10, 2026
5592c03
feat(parser): extend conjure-duplicate anaphors to that creature/spel…
philluiz2323 Jun 10, 2026
85e48d4
feat(menu): integrate MenuSelect for format filtering in MyDecks (#2947)
milosde111 Jun 10, 2026
10d809f
fix(parser): keep all keywords when an animation has a 'still a land'…
philluiz2323 Jun 10, 2026
e4e507f
feat(engine): enter under an opponent’s control on ETB (CR 110.2a) (#…
galuis116 Jun 10, 2026
f1b47e3
Cost-payment unification Phase 2: PaymentScope + route effects/pay.rs…
matthewevans Jun 11, 2026
59e919d
fix(engine): Pest token attack life gain from catalog (#2840)
kiannidev Jun 11, 2026
ce12c3b
fix(parser): share one target across compound "target opponent does A…
philluiz2323 Jun 11, 2026
e9b70e6
feat(deck-builder): enhance DeckBuilderToolbar with MenuSelect for fo…
milosde111 Jun 11, 2026
c7f7c93
fix(parser): recognize "that turn’s end step" delayed loss (Final For…
galuis116 Jun 11, 2026
86c55f2
fix(engine): publish RevealTop cards for ChooseFromZone picks (#2953)
jsdevninja Jun 11, 2026
18df130
fix(parser): parse "equal to the number of … destroyed this way" quan…
jsdevninja Jun 11, 2026
d9ad6e9
Add regression tests for issue #861 (Tree of Perdition, First Sliver)…
kiannidev Jun 11, 2026
f2df55a
Cost-payment unification Phase 3: route handle_unless_payment through…
matthewevans Jun 11, 2026
4c22978
fix(engine): flickering a merged Mutate permanent returns all compone…
carlos4s Jun 11, 2026
ef3a517
fix(frontend): auto-open graveyard viewer above prompts during zone c…
claytonlin1110 Jun 11, 2026
e1046f2
fix(engine): Rod of Absorption exile-tracking and free-cast (#2845)
dripsmvcp Jun 11, 2026
1030931
feat(engine): promote Effect::Animate power/toughness to Option<PtVal…
nickmopen Jun 11, 2026
84333b6
ship/cost payment phase4 delete paymentcost (#2960)
matthewevans Jun 11, 2026
b8b3183
ship/zone phase e t1 (#2958)
matthewevans Jun 11, 2026
a63405e
fix(engine): preserve cost-payment pause semantics (#2959)
matthewevans Jun 11, 2026
3c78f76
fix(engine): derive merged Mutate permanent token-ness from the topmo…
carlos4s Jun 11, 2026
dc6e703
fix(engine): keep keyword suffixes on final Or disjunct for comma-OR …
claytonlin1110 Jun 11, 2026
1b78a92
fix(engine): Gate lands offer fixed color and chosen color when tappe…
claytonlin1110 Jun 11, 2026
599cd0c
fix(engine): Mystic Remora cumulative upkeep after card rehydration (…
kiannidev Jun 11, 2026
b2e9684
fix(parser): Breena attack trigger intervening-if (#2839)
kiannidev Jun 11, 2026
ae44da6
ship/cost payment phase5 (#2966)
matthewevans Jun 11, 2026
ca4d536
ship/zone phase e t2 (#2967)
matthewevans Jun 11, 2026
95594fa
fix(parser+runtime): handle 'N fewer [type] counter' pattern in enter…
Whovencroft Jun 11, 2026
8368267
fix(parser): parse opponent-control and cards-drawn CDA quantities (#…
jony376 Jun 11, 2026
df7aaad
fix(parser): recognize unconditional life-floor replacement (CR 614.1…
galuis116 Jun 11, 2026
91ea530
fix(parser): parse leading "N/M" as a power/toughness filter, not a s…
philluiz2323 Jun 11, 2026
2e757a4
Fix ParentTargetSlot resolution to use accumulated targets from chain…
Kelvinchen03 Jun 11, 2026
d15b379
fix(engine): read a left-battlefield target's power/toughness from la…
philluiz2323 Jun 11, 2026
af2f074
feat(engine): conditional activation cost reduction — "costs {N} less…
galuis116 Jun 11, 2026
5eaba9c
fix(parser): parse unconditional life-floor damage replacements (Ali …
jony376 Jun 11, 2026
aa3c749
fix(parser): parse conditional flat activated cost reductions (#2983)
jony376 Jun 11, 2026
9bd17a6
fix(lobby): improve mobile format filter and server chip layout (#2972)
milosde111 Jun 11, 2026
9334362
fix(parser): honor positive 'that's a/an X [or a/an Y]' subtype relat…
philluiz2323 Jun 11, 2026
3c91019
fix(parser): passive "spells with the chosen name can't be cast" (CR …
galuis116 Jun 11, 2026
2f71229
chore: refresh metagame feeds (#2993)
matthewevans Jun 11, 2026
fdbf2e3
ship/zone t3 (#2989)
matthewevans Jun 11, 2026
3d91e1a
fix(parser): parse "for each player who has lost the game" quantity (…
jony376 Jun 11, 2026
e2b73b7
fix(parser): split scoped "can't attack you" from compound static lin…
nickmopen Jun 11, 2026
4ec5ee3
feat(engine): zone pipeline tranche 4 — route draws through move_obje…
matthewevans Jun 11, 2026
dc46373
fix(parser): parse exile X cards from graveyard additional cost (Harv…
jony376 Jun 11, 2026
24afeef
fix: ParentTarget GenericEffect binding for targeted pump/debuff abil…
claytonlin1110 Jun 11, 2026
ebf4afe
fix(parser): keep Krark win-flip copy+retarget in one clause (#2956)
jsdevninja Jun 11, 2026
a9eddfb
Fix targeting and controller assignment bugs (#2803)
Kelvinchen03 Jun 11, 2026
62849b7
release: v0.1.54
Jun 11, 2026
6bf3efc
fix(parser): parse Deflecting Swat "choose new targets" as ChangeTarg…
jsdevninja Jun 11, 2026
ac88dd0
test(engine): re-freeze anaphoric allowlist at 166 (crumble/sly spy/s…
matthewevans Jun 11, 2026
75903b3
fix(engine): up-to-N target bounce honors 0-target opt-out (#3012)
dripsmvcp Jun 11, 2026
c65eb21
feat(ai): avoid casting spells into a Chalice of the Void (#3003)
dripsmvcp Jun 11, 2026
dc26573
test(engine): regression test for Mind into Matter artifact put (#688…
kiannidev Jun 11, 2026
d898cef
fix(engine): flush layers before sub-ability reads P/T (issue #2384) …
dripsmvcp Jun 11, 2026
138e965
fix(engine): add CanOnlyAttackAlone static mode and enforcement (clos…
nickmopen Jun 11, 2026
fbab869
fix(engine): draw only when no copy was made (issue #1370) (#3018)
dripsmvcp Jun 11, 2026
1f9faa6
fix(engine): apply no-target sibling grant to triggering object (#237…
dripsmvcp Jun 11, 2026
0c25e6a
fix(engine): bestow-cast Detective's Phoenix from graveyard (#3014)
dripsmvcp Jun 11, 2026
302f877
test(engine): regression tests for Resonating Lute hand-size gate (#6…
kiannidev Jun 11, 2026
d99eb29
fix(parser): accept "if you do, it becomes plotted" Plot grant (CR 70…
galuis116 Jun 11, 2026
f7977d2
fix(engine): seed saga lore counter on transformed DFC entry (#691) (…
kiannidev Jun 11, 2026
cc8a67e
fix(parser): split dual-subject anthem statics (issue #1489) (#3007)
dripsmvcp Jun 11, 2026
dd60cc5
fix(parser): evaluate combat-damage-by-type intervening-if (issue #13…
dripsmvcp Jun 11, 2026
452b8e3
fix(parser): parse Astarion's modal "life they lost this turn" amount…
philluiz2323 Jun 11, 2026
8e8f91f
Migrate reveal-until zone moves to pipeline (#3024)
matthewevans Jun 11, 2026
b804294
fix(parser): parse Library of Leng discard-to-top replacement (#2998)
jony376 Jun 11, 2026
101fbe5
Fix Phyrexian Dreadnought ETB unless-sacrifice (#864) (#2843)
kiannidev Jun 11, 2026
0f6d869
fix(parser): attach multi-target spec for Trystan's Command return mo…
jony376 Jun 11, 2026
43bed51
fix(engine): correct reveal-until CR annotations (#3025)
matthewevans Jun 11, 2026
e93dccd
fix(parser): existential opponent control activation restrictions (#3…
claytonlin1110 Jun 11, 2026
738f9c8
fix(engine): enforce any-other-target distinctness for Arc Trail (clo…
jony376 Jun 11, 2026
7c5c7bb
fix(engine): bind connive count to creatures-died-this-turn quantity …
claytonlin1110 Jun 11, 2026
9ee3b73
fix(engine): synthesize runtime-granted keyword triggers from LKI on …
Kelvinchen03 Jun 11, 2026
39323f7
Fix Flurry target gate for Shiko and Narset, Unified (#2914) (#3032)
kiannidev Jun 11, 2026
64b90a8
fix(engine): Alexios can't attack owner + upkeep GiveControl (closes …
kiannidev Jun 11, 2026
f18fecc
feat(engine): turn the exiled card face up (Imprint flip cards) (#3034)
galuis116 Jun 11, 2026
a473cbf
fix(engine): Torrential Gearhulk exile-on-resolve rider (closes #2937…
jony376 Jun 11, 2026
0b2062a
fix(parser): split compound statics with foreign keyword-grant subjec…
nickmopen Jun 11, 2026
c3fbd91
feat(engine): dynamic P/T for "unspent <color> mana you have" (Omnath…
philluiz2323 Jun 11, 2026
3995418
feat(engine): implement the Cloak keyword action (CR 701.58a) (#3038)
galuis116 Jun 11, 2026
d745eca
Fix Torment of Hailfire repeat resolution order (#2916) (#3033)
kiannidev Jun 11, 2026
1a345c6
fix(engine): Future Sight library top reveal at runtime (closes #2918…
kiannidev Jun 11, 2026
388eb9c
fix(engine): StaticCondition::WasCast for cast-gated continuous stati…
kiannidev Jun 12, 2026
1ccc486
fix(engine): gate Amareth reveal on shared card type (#3028)
jsdevninja Jun 12, 2026
9fc23fa
fix(parser): bind "deals N damage to them" to the upkeep player (#3046)
philluiz2323 Jun 12, 2026
559fe0b
fix(engine): apply "each player's life total becomes N" to all player…
galuis116 Jun 12, 2026
6ebfbb3
fix(parser): hoist "if it's not a token" intervening-if and goad toke…
claytonlin1110 Jun 12, 2026
adb7c66
fix(parser): gate first-{X}-spell cost reduction (#3011)
dripsmvcp Jun 12, 2026
f853968
feat(engine): mass "gain control of all" via GainControlAll (closes #…
philluiz2323 Jun 12, 2026
04621c4
feat(engine): implement Meld keyword action runtime (CR 701.42 / CR 7…
carlos4s Jun 12, 2026
f1b3607
fix(parser): route subject-led mana to ScopedPlayer for Blinkmoth Urn…
claytonlin1110 Jun 12, 2026
c3ad3c0
fix(parser): preserve "may" optionality for each-player discard (Mog,…
galuis116 Jun 12, 2026
7293c72
fix(parser): bind "deals N damage to them" to a player-actor trigger …
philluiz2323 Jun 12, 2026
39b6ad9
fix(engine): charge each repeated modal unless-pay instance (#2925) (…
dripsmvcp Jun 12, 2026
3cfac62
fix(parser): scope self-recipient "~ would be dealt damage" preventio…
galuis116 Jun 12, 2026
da6cadb
fix(parser): bind "where X is …" into a continuous grant’s dynamic P/…
philluiz2323 Jun 12, 2026
b07aa39
fix(parser): handle zone-qualified card keyword grants (Six #536) (#3…
Whovencroft Jun 12, 2026
86bad55
fix(engine): type-filter + single-use bound on cast-from-exile grant …
dripsmvcp Jun 12, 2026
266f9d7
fix(parser): parse "no creatures attacked this turn" intervening-if (…
jsdevninja Jun 12, 2026
de6b7a9
fix(engine): resume mass return-to-battlefield after an Aura host cho…
philluiz2323 Jun 12, 2026
bb6bf47
Fix trigger index routing for 'from anywhere to graveyard' triggers (…
Kelvinchen03 Jun 12, 2026
1da91b1
fix(ci): pin tauri time dependency
matthewevans Jun 12, 2026
ba48530
fix(ci): lock Tauri app dependency resolution (#3081)
matthewevans Jun 12, 2026
62dda87
Merge branch 'main' into deck-contribute-workflow
matthewevans Jun 12, 2026
8befdf9
fix(ci): refresh tauri lockfile
matthewevans Jun 12, 2026
e30bc16
Merge branch 'main' into deck-contribute-workflow
matthewevans Jun 12, 2026
b072730
chore: refresh metagame feeds (#3071)
matthewevans Jun 12, 2026
2b10e3a
fix(engine): fire unblocked opponent-attack triggers after blockers (…
jsdevninja Jun 12, 2026
06d1222
fix(parser): graveyard zone + origin if for Prized Amalgam (issue #28…
dripsmvcp Jun 12, 2026
ae9cc31
fix(engine): pay as-enters MayCost discard cost for real (#2853) (#3067)
dripsmvcp Jun 12, 2026
253eff0
fix(engine): resolve venture and initiative dungeon triggers (#3069)
claytonlin1110 Jun 12, 2026
070114e
fix(parser): parse damage-source-type intervening-if (#2867) (#3063)
dripsmvcp Jun 12, 2026
1c7a430
fix(parser): parse untyped "for each counter on this [type]" as dynam…
nickmopen Jun 12, 2026
3247ff6
fix: nexus of Fate shuffle-back replacement on stack resolution (#3048)
jsdevninja Jun 12, 2026
41328fc
fix(engine): cap divided-damage targets by divisible pool (issue #285…
dripsmvcp Jun 12, 2026
28b5fb8
fix(engine): resolve mass put-all Dig deterministically (Muxus) (#3066)
dripsmvcp Jun 12, 2026
3e696d3
fix(client): handle all alternative-cast keywords in modal (#2939) (#…
dripsmvcp Jun 12, 2026
353662f
fix(engine): stamp source_incarnation on warp delayed trigger (#539) …
Whovencroft Jun 12, 2026
eb47d4d
fix(engine): apply +X/+X-where-X-is-power boost on trigger (#3044)
dripsmvcp Jun 12, 2026
082966e
fix(engine): Winding Way reveal-and-partition routing (issue #2931) (…
dripsmvcp Jun 12, 2026
bb005b5
fix(engine): Tabernacle granted upkeep destroys on decline (#1326) (#…
kiannidev Jun 12, 2026
8993f3b
fix: Inti reflexive counter after interactive discard (#1328) (#3083)
kiannidev Jun 12, 2026
c7b5044
ship/Standardize AI measurement and policy gates (#3093)
matthewevans Jun 12, 2026
516f097
fix(ci): refresh tauri lock during nightly release (#3089)
matthewevans Jun 12, 2026
c755a3c
feat: support [−X] variable-loyalty planeswalker abilities (#3088)
galuis116 Jun 12, 2026
6b388d5
fix(client): surface Impending alternative-cast option (#2859) (#3049)
dripsmvcp Jun 12, 2026
faadc32
fix(parser): bind a token creator's "it gains/gets X" grant to the cr…
philluiz2323 Jun 12, 2026
3f27ad5
fix(engine): scope DamageReceived triggers by valid_card recipient fi…
claytonlin1110 Jun 12, 2026
cbff204
fix(engine): bind 'deal damage to that player' to triggering drawer (…
dripsmvcp Jun 12, 2026
adebcc1
Improve mobile battlefield zone overflow (#3102)
matthewevans Jun 12, 2026
b306a14
fix(engine): bind "for as long as it has a counter" to the recipient …
philluiz2323 Jun 12, 2026
07e04ae
fix(engine): snapshot TriggeringSource object in delayed triggers at …
nickmopen Jun 12, 2026
d8d0028
fix(engine): resolve Reality Shift chained manifest via parent-target…
claytonlin1110 Jun 12, 2026
1b45cff
feat: grant "all activated abilities of cards exiled with it" (Myr We…
galuis116 Jun 12, 2026
ed14dae
Fix Blast-Furnace Hellkite Artifact offering and attacking-opponents …
kiannidev Jun 12, 2026
4a1e204
fix(engine): impose additional life cost on spells targeting Terror o…
jsdevninja Jun 12, 2026
e834fc1
feat: parse "spend mana only to cast X spell or activate an ability" …
galuis116 Jun 12, 2026
d7565ec
fix(engine): model enlist as attack cost (#3108)
matthewevans Jun 12, 2026
253c7eb
Fix Teferi's Protection mass phase-out targeting (fixes #2907) (#3092)
kiannidev Jun 12, 2026
5fbe439
test(engine): Brain in a Jar charge-then-cast regression (#1333) (#3091)
kiannidev Jun 12, 2026
9e3d505
Fix Master of Cruelties can only attack alone parsing (fixes #2910) (…
kiannidev Jun 12, 2026
76ce53d
Fix Agitator Ant end-step counters and scoped goad (fixes #2903) (#3085)
kiannidev Jun 12, 2026
e49560e
fix(engine): track additional cost instances (#3114)
matthewevans Jun 12, 2026
4c8c78d
fix: implement Zack Fair activated ability (#1327) (#3082)
kiannidev Jun 12, 2026
88981bd
fix(engine): return dying creatures as face-down Forest lands (#2923)…
dripsmvcp Jun 12, 2026
cf70ff7
fix(parser): fix tracked-set scan shadowed by intermediate clause and…
nickmopen Jun 12, 2026
e7a0d93
fix(engine): apply Najeela untap + keyword grant with extra combat (#…
dripsmvcp Jun 12, 2026
1d171aa
fix(engine): gate Suppressor Skyguard’s prevent trigger on an unattac…
philluiz2323 Jun 12, 2026
0c5bdde
test(engine): Marchesa +1/+1 dies return regression (#1334) (#3094)
kiannidev Jun 13, 2026
e87a841
feat: fire "when you spend this mana to cast [filter] spell" triggers…
galuis116 Jun 13, 2026
c35d521
fix(engine): exile from controller library on combat-damage ExileFrom…
claytonlin1110 Jun 13, 2026
e74119b
fix(engine): gate Caesar's reflexive choose-two on the optional sacri…
philluiz2323 Jun 13, 2026
1b42654
fix(engine): resolve impossible Choose as no-op instead of wedging (#…
dripsmvcp Jun 13, 2026
023f84d
Fix Dragon's Rage Channeler cast trigger timing on flashback (issue #…
kiannidev Jun 13, 2026
8dad2f8
Allow enchantment adventure cards to cast their spell face (issue #28…
kiannidev Jun 13, 2026
e3edb4e
Fix Currency Converter creating tokens with no exiled card (issue #28…
kiannidev Jun 13, 2026
2f9f7d9
fix(engine): cast opponent-graveyard free-cast during resolution (#28…
dripsmvcp Jun 13, 2026
ee0f40f
fix(engine): Bronzehide Lion no-target ReturnAsAura hang (#1332) (#3087)
kiannidev Jun 13, 2026
961ce6d
test(engine): regression test for #1558 — Myriad on copy creature (#3…
Whovencroft Jun 13, 2026
c1f98c2
fix(parser): count "cards your opponents have drawn this turn" as a s…
philluiz2323 Jun 13, 2026
a7f913c
feat(parser): consume "draft matters" draft-time text (#3129)
galuis116 Jun 13, 2026
c4a8cf1
Add regression test for Kaldra Compleat haste equipment grant. (#3133)
kiannidev Jun 13, 2026
49d2f53
fix(parser): rewrite 'copy of it' to TrackedSet after exile clause (#…
Whovencroft Jun 13, 2026
45bf57b
Fix aura attachment cleanup on commander zone changes (#2863) (#3136)
kiannidev Jun 13, 2026
cea1a0e
fix(parser): resolve 'draw cards equal to the difference' in triggers…
galuis116 Jun 13, 2026
e5afa87
fix(engine): keep sacrificed creatures out of exiled-this-way set (#2…
dripsmvcp Jun 13, 2026
5597a74
chore: refresh metagame feeds (#3142)
matthewevans Jun 13, 2026
10ba349
fix(parser): parse all-player static step skips (#3141)
jaso0n0818 Jun 13, 2026
61e58c8
fix(engine): Mechtitan token keeps haste + becomes all colors (#2343)…
dripsmvcp Jun 13, 2026
af87c4a
release: v0.1.55
Jun 13, 2026
c50267d
feat(engine): Planechase runtime — planes/phenomena, planar deck, pla…
carlos4s Jun 13, 2026
a2dcae2
Fix Professor Onyx magecraft on spell copy (#2866) (#3132)
kiannidev Jun 13, 2026
7b822f0
Add Telepathy hand reveal static (#3144)
jaso0n0818 Jun 13, 2026
3a281fd
fix(engine): pay sacrifice cost on modal activated abilities (#3146)
kiannidev Jun 13, 2026
aa49066
fix(engine): Sevinne's Reclamation flashback self-copy (#2860) (#3145)
kiannidev Jun 13, 2026
1c14b91
Add Baldin toughness damage static (#3147)
jaso0n0818 Jun 13, 2026
b90fc70
Fix Teferi loyalty loss when counter map is missing (#2862) (#3137)
kiannidev Jun 13, 2026
97eda9e
fix(engine): parse Wall of Mourning ETB as ExileTop (#3148)
kiannidev Jun 13, 2026
4284775
test(engine): add Obuun land animation regression (#3152)
kiannidev Jun 13, 2026
cfb685f
fix(parser): token Flying keyword before equal-to count (#3151)
kiannidev Jun 13, 2026
11c8e27
fix(parser): Lulu Stern Guardian stun targets attackers only (#3149)
kiannidev Jun 13, 2026
b19db36
fix(engine): Bring to Light free-cast is resolution-only, not a linge…
matthewevans Jun 13, 2026
c377bfe
fix(parser): scope 'creatures that died under your control' count to …
matthewevans Jun 13, 2026
dd5945f
fix(engine): scope 'If you do' tracked-set reset to producer riders s…
matthewevans Jun 13, 2026
9f75a07
test(engine): regression for Station counter-gated static teardown (#…
matthewevans Jun 13, 2026
8131b26
fix(parser): Gideon Blackblade turn-conditional 'is a creature ... st…
matthewevans Jun 13, 2026
c3db233
fix(parser): Dig 'reveal ... on top of your library, rest on bottom' …
matthewevans Jun 13, 2026
af99e0c
fix(parser): mass return-to-battlefield preserves enter-with-counters…
matthewevans Jun 13, 2026
141a243
fix(parser): 3000-the tokens are goaded (#3158)
andriypolanski Jun 13, 2026
02641d5
fix(parser): Gonti-class look-and-exile-face-down exiles the dug card…
matthewevans Jun 13, 2026
67dd41e
refactor(client): frontend cleanup & optimization pass (#3162)
matthewevans Jun 13, 2026
e1407fc
fix(engine): sacrifice triggers look back via LKI for ceased-to-exist…
matthewevans Jun 13, 2026
87e69a0
fix(parser): lower 'gains no life instead' to Prevent replacement (#7…
matthewevans Jun 13, 2026
b508491
fix(parser): Trailing 'for each ...' multiplier clause is not convert…
ntindle Jun 13, 2026
b73621c
feat(engine): is_mana_ability flag + #3162 Gemini follow-ups (#3164)
matthewevans Jun 13, 2026
c8b4019
fix(engine): replay deferred entry events on as-enters-choice resolut…
matthewevans Jun 13, 2026
c8235dd
fix(engine): play-from-exile permission is consultable from the grave…
matthewevans Jun 13, 2026
8ea7dcf
fix(parser): Taigam exiles the cast spell (not itself) with time coun…
matthewevans Jun 13, 2026
06588d6
Merge branch 'main' into deck-contribute-workflow
ntindle Jun 13, 2026
29ec8b1
Delete docs/superpowers/plans/2026-05-28-contribute-card-workflow.md
ntindle Jun 13, 2026
e2a0c29
Delete docs/superpowers/specs/2026-05-28-contribute-card-workflow-des…
ntindle Jun 13, 2026
7dff707
workflow: route implementation through /engine-implementer (executor …
ntindle Jun 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ rules-audit = "run --profile tool --bin rules-audit --features audit --"
semantic-audit = "run --profile tool --features cli --bin oracle-gen -- semantic-audit"
scrape-feeds = "run --release -p feed-scraper --"
tune-ai = "run --release --features tune --bin ai-tune --"
ai-gate = "run --bin ai-gate --"
engine-inventory = "run --quiet -p engine-inventory-gen"

[env]
Expand Down
38 changes: 31 additions & 7 deletions .claude/agents/engine-implementation-executor.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,12 @@ If any modified file is under `crates/engine/src/parser/`, inspect added lines f
```bash
git diff --name-only | grep 'crates/engine/src/parser/' | while read f; do
git diff "$f" | grep '^+' | grep -v '^+++' | grep -vE '^\+\s*//' \
| grep -E '\.(contains|starts_with|ends_with|find)\(' \
| grep -E '\.(contains|starts_with|ends_with|find|rfind|split|splitn|rsplit|split_once)\(' \
| grep -v '#\[test\]' | grep -v '#\[cfg(test)\]'
done
```

Any output is a hard failure unless it is a test, comment, explicitly annotated non-dispatch structural use, or `oracle_util.rs` dual-string `TextPair` helper work.
The `rfind`/`split`/`split_once`/`rsplit` arms are deliberate: `scripts/check-parser-combinators.sh` does not catch them, so a green gate is not proof of combinator compliance — this inline grep covers that blind spot. Any output is a hard failure unless it is a test, comment, explicitly annotated non-dispatch structural use, or `oracle_util.rs` dual-string `TextPair` helper work.

For parser changes always run additionally:

Expand All @@ -140,17 +140,41 @@ cargo coverage
cargo semantic-audit
```

### Discriminating-test gate

Every behavioral change MUST ship at least one test that drives the real pipeline (`apply()` / the scenario runner / the cast-pipeline harness) and **would fail if the fix were reverted**. A test that only asserts the parsed AST shape — an `assert_eq!` on a parsed `AbilityDefinition` / `Effect` / `StaticMode` without resolving it through the engine — does NOT satisfy this gate. It is a shape test, not a regression test.

Confirm discrimination concretely before returning:

- For the primary fix, name the assertion that flips when the fix is reverted. If you cannot name one, the test does not discriminate — add one that does.
- Trace each test fixture through the fix's first input-shape dispatches (`is_none()` / `is_empty()` / variant `match` / "has-X" guards). If every fixture is degenerate in the same way (no ability, no targets, empty or single-element collection, all-generic cost), the test likely takes a different internal branch than production inputs and silently passes — reach the real arm instead. (Precedent: an Emerge cost-reduction test whose all-generic sacrifice made the wrong reduction coincide with the right one; an Undaunted test that called a function the reduction never runs in, so the positive case could not pass.)

This is the single most common defect the `/review-impl` loop catches (shape-only tests on keyword and parser PRs). Catch it here, before review.

### CR-annotation diff gate

Before returning, grep every CR number you added or changed **in the diff** against `docs/MagicCompRules.txt` — not just the ones you remember writing:

```bash
git diff | grep -E '^\+' | grep -oE 'CR [0-9]{3}(\.[0-9]+[a-z]?)?' | sed 's/^CR //' | sort -u \
| while read -r n; do grep -qE "^${n}([^0-9]|$)" docs/MagicCompRules.txt || echo "UNVERIFIED: CR ${n}"; done
```

Any `UNVERIFIED:` line is a hard stop — the rule number does not exist in the rules text (a hallucinated subpart, e.g. the recurring `702.808` / wrong-keyword-subpart class) or is malformed. Re-derive the correct rule or flag it explicitly; never ship an unverified CR annotation. A clean grep is necessary but not sufficient: also confirm the cited rule actually *describes* the annotated code, not merely that the number exists.

## Output

Return a structured report to the orchestrator:

1. **Diff summary** — files touched, grouped by subsystem, with a one-line purpose per file.
2. **Verification results** — which Tilt resources are green; any failures with `tilt logs` excerpts (own vs unrelated).
3. **Parser diff gate** — pass/fail with offending lines if any.
4. **Judgement calls** — any place you had to choose between two readings of the plan, with the reasoning.
5. **Stop-and-return items** — any places you stopped rather than improvise.
6. **CR annotations added/changed** — each one with the grep command that verified it.
7. **Deviations from the plan** — what changed vs. the plan and why.
8. **Risks** — anything the orchestrator's `/review-impl` loop should pay extra attention to.
4. **Discriminating-test gate** — for the primary fix, the assertion that flips when the fix is reverted, and confirmation no production-reachable arm is left covered only by a degenerate fixture. State if any test is shape-only.
5. **CR-annotation diff gate** — the grep result; list any `UNVERIFIED:` rule, or confirm zero.
6. **Judgement calls** — any place you had to choose between two readings of the plan, with the reasoning.
7. **Stop-and-return items** — any places you stopped rather than improvise.
8. **CR annotations added/changed** — each one with the grep command that verified it.
9. **Deviations from the plan** — what changed vs. the plan and why.
10. **Risks** — anything the orchestrator's `/review-impl` loop should pay extra attention to.

Do NOT commit. Do NOT push. The orchestrator decides what to stage and when.
37 changes: 33 additions & 4 deletions .claude/agents/pr-review-comment-resolver.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,43 @@ Accept:

### 2. Fetch Review Feedback

Fetch all relevant feedback:
Fetch all feedback in ONE GraphQL call. **Most actionable feedback on this repo is top-level — PR review bodies (where Gemini's summary review and most human reviews land) and issue/conversation comments — not file/line-anchored inline threads.** GraphQL is the idle rate-limit bucket, so one query avoids the per-PR REST `--paginate` walk that drains `core`; more importantly it fetches all three feedback objects **comprehensively**, which the "all blocking review comments resolved" gate requires:

```bash
gh pr view <PR> --repo phase-rs/phase --json reviewDecision,reviews,comments
gh api repos/phase-rs/phase/pulls/<PR>/comments --paginate
gh api repos/phase-rs/phase/issues/<PR>/comments --paginate
# First page: omit the cursor vars (they default to null = from the start).
# To paginate, pass the connection's endCursor back via -F <conn>Cursor=<endCursor>.
gh api graphql -F owner=phase-rs -F name=phase -F pr=<PR> -f query='
query($owner:String!,$name:String!,$pr:Int!,$reviewsCursor:String,$commentsCursor:String,$threadsCursor:String) {
repository(owner:$owner, name:$name) {
pullRequest(number:$pr) {
reviewDecision
reviews(first:100, after:$reviewsCursor) { # top-level review bodies (Gemini summary, human reviews) — the MAJORITY
pageInfo { hasNextPage endCursor }
nodes { author{login} body state submittedAt url }
}
comments(first:100, after:$commentsCursor) { # top-level issue/conversation comments
pageInfo { hasNextPage endCursor }
nodes { author{login} body url createdAt }
}
reviewThreads(first:100, after:$threadsCursor) { # inline (file/line) threads + resolved state — the minority
pageInfo { hasNextPage endCursor }
nodes { isResolved isOutdated path line
comments(first:50) { pageInfo { hasNextPage endCursor }
nodes { author{login} body url createdAt } } }
}
}
}
}' --jq '.data.repository.pullRequest'
```

Comprehensiveness rules for the gate:

- **Top-level `reviews` and `comments` have no `isResolved` flag** — read every one's **body** for actionable findings and judge whether each is addressed in the current commits. Do NOT gate on review `state`: the dominant reviewer here (Gemini) posts its findings in a `COMMENTED` review with `reviewDecision: null` (verified on live PRs), so a `state`-based gate would skip the majority of review content. Treat `state == CHANGES_REQUESTED` as an *additional* hard block, never the sole blocking signal. Compare reviews by each author's **latest** `submittedAt` — a later approval from the same author supersedes their earlier change-request, and vice-versa.
- **Inline `reviewThreads`** are the minority here but still binding: filter to `isResolved == false` for actionable items.
- If ANY connection's `pageInfo.hasNextPage` is true, paginate by passing that connection's `endCursor` back via its cursor variable (`-F reviewsCursor=<endCursor>`, `-F commentsCursor=…`, `-F threadsCursor=…`) and re-running — do not stop at the first page; this is the comprehensive gate, not a triage slice. Truncating `reviews`/`comments` would silently hide top-level blockers, the majority case. The nested per-thread `comments` connection also exposes `pageInfo`: if a single thread's `comments.pageInfo.hasNextPage` is true (50+ replies — rare), refetch that thread's comments with its own `after` cursor.

Never substitute a per-PR `gh api .../pulls/<PR>/comments --paginate` REST walk (drains `core`, inline-only, lacks resolved-state) or a time-windowed `since=` sweep (risks dropping old unaddressed top-level feedback).

For each item, extract source, author, body, file path and line/range, timestamps, and whether it is resolved, outdated, duplicated, or still actionable. Skip resolved and informational comments. If uncertain, keep the item and mark it `needs-human-confirmation`.

### 3. Categorize And Prioritize
Expand Down
Loading
Loading