Add Conduit of Worlds - #6958
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe parser and runtime now support Conduit of Worlds-style paid graveyard casting and activator-bound source restrictions. Successful casts update optional-effect state. Token catalog and token-fetching workflow changes are also included. ChangesGameplay casting and restriction handling
Token catalog tooling
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant OracleParser
participant AbilityResolution
participant CastFromZone
participant CastingCosts
participant GameState
OracleParser->>AbilityResolution: lower paid graveyard cast and restriction
AbilityResolution->>CastFromZone: offer cast
CastFromZone->>CastingCosts: process payment and stack placement
CastingCosts->>GameState: commit cast and install restriction
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
Generated for head Parse changes introduced by this PR · 4 card(s), 7 signature(s) (baseline: main
|
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
crates/engine/src/parser/oracle_effect/tests.rs (1)
31669-31678: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winTighten the resolution-gate assertion.
AbilityCondition::QuantityCheck { .. }accepts any quantity, comparator, and subject. A regression that flips the comparator or points the check at a different quantity still passes this assertion. Assert the concrete comparator and count for "you haven't cast a spell this turn" (spells cast this turn equal to zero), matching the precision used for the rider gate at Line 31700.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/engine/src/parser/oracle_effect/tests.rs` around lines 31669 - 31678, The assertion for the cast resolution gate must validate the complete QuantityCheck rather than only its variant. In the assertion around cast.condition, require the spells-cast-this-turn quantity, an equality comparator, and a count of zero, matching the precise rider-gate assertion near Line 31700.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/engine/src/game/casting_costs.rs`:
- Around line 9627-9633: Update the active continuation handling around
active_ability_continuation_frame_mut so completion state is associated with the
specific pending optional cast rather than any optional-effect gate in the
chain. Replace the broad has_optional_effect_performed_gate and recursive setter
usage with identity-based lookup and update only the matching gate, preserving
later independent optional actions as unperformed. Add a regression test
covering two independent optional-effect gates in one resolution chain.
In `@crates/engine/src/game/casting.rs`:
- Around line 842-848: Reject unresolved
RestrictionPlayerScope::SourceController values in both PersistedGameState
restore paths, covering the casting handling near
crates/engine/src/game/casting.rs:842-848 and combat handling near
crates/engine/src/game/combat.rs:3781-3786. Ensure restore either rejects these
serialized states or persists the already-resolved SpecificPlayer; do not infer
a player from the current source controller, and preserve add_restriction’s
lowering behavior.
In `@crates/engine/src/parser/oracle_effect/tests.rs`:
- Around line 31618-31627: Update the Conduit of Worlds full line-2 effect
documentation near the test case to limit CR 608.2g to mana payment and casting
during resolution, and identify CR 608.2c as governing instruction order. Remove
the implication that CR 608.2c separately defines the “if you do” wording while
preserving the existing chain description.
In `@crates/engine/src/parser/oracle_ir/context.rs`:
- Around line 259-268: Add an explicit cast-timing field to the permission AST
and propagate it independently from chain_prior_chosen_target. Update
CastFromZoneDriver to derive during-resolution versus lingering behavior from
this timing, based on the resolving instruction and duration, rather than
inferring it from the chosen target’s zone; preserve chain_prior_chosen_target
solely for target binding.
- Around line 259-268: Update the cast-driver selection that uses
parent_target_is_graveyard_scoped so CastFromZoneDriver::DuringResolution is
selected for any resolving “you may cast that card” instruction without an
explicit lingering duration, regardless of the chosen target’s zone. Derive
timing from the instruction’s duration/timing semantics, preserving
LingeringPermission only when the instruction explicitly grants permission
beyond resolution.
---
Nitpick comments:
In `@crates/engine/src/parser/oracle_effect/tests.rs`:
- Around line 31669-31678: The assertion for the cast resolution gate must
validate the complete QuantityCheck rather than only its variant. In the
assertion around cast.condition, require the spells-cast-this-turn quantity, an
equality comparator, and a count of zero, matching the precise rider-gate
assertion near Line 31700.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 1ea181aa-1a12-491a-8276-53e99ed3c1ef
📒 Files selected for processing (15)
crates/engine/data/known-tokens.tomlcrates/engine/src/game/casting.rscrates/engine/src/game/casting_costs.rscrates/engine/src/game/casting_tests.rscrates/engine/src/game/combat.rscrates/engine/src/game/derived_views.rscrates/engine/src/game/effects/add_restriction.rscrates/engine/src/game/effects/cast_from_zone.rscrates/engine/src/game/effects/mod.rscrates/engine/src/parser/oracle_effect/mod.rscrates/engine/src/parser/oracle_effect/tests.rscrates/engine/src/parser/oracle_ir/context.rscrates/engine/src/parser/oracle_static/tests.rscrates/engine/src/types/ability.rsscripts/fetch-token-sets.sh
|
Maintainer cleanup pushed at |
matthewevans
left a comment
There was a problem hiding this comment.
Changes requested — this head is correct for Conduit itself, but two shared casting/parser paths remain rules-incorrect.
🔴 Blocker
[HIGH] A no-duration paid “cast that card” is treated as immediate only when the chosen card is in a graveyard. Evidence: crates/engine/src/parser/oracle_ir/context.rs:259-268 carries the selected target’s zone to decide timing; crates/engine/src/parser/oracle_effect/mod.rs:22631-22645 implements parent_target_is_graveyard_scoped, and :22756-22782 selects DuringResolution only for that zone. The consumer has the same restriction in crates/engine/src/game/effects/cast_from_zone.rs:568-610.
The official CR 608.2g says, “If an effect specifically instructs or allows a player to cast a spell during resolution,” the cast follows 601.2a–i with no priority afterward. The timing comes from the resolving instruction and an explicit duration, not from the chosen card’s zone. The current Conduit of Worlds Oracle text does choose a graveyard card, so its target case works; the generalized parser path accepts the same no-duration paid anaphor for a chosen card in hand, exile, or library but leaves it as a lingering permission instead.
Suggested fix: model the instruction/duration timing independently of TargetFilter’s zone and use one resolution-cast offer path for the eligible chosen card. Add runtime tests that (a) immediately offer a paid no-duration chosen non-graveyard card while the ability resolves and (b) retain a “this turn” counterpart as a lingering permission.
[MED] Completing a paid resolution cast marks every optional-outcome gate in the retained continuation, rather than the gate belonging to that cast. Evidence: crates/engine/src/game/casting_costs.rs:9614-9633 checks for any gate and calls the recursive setter; crates/engine/src/types/ability.rs:23874-23909 traverses the full sub_ability and else_ability tree. A chain with two independent optional “If you do” outcomes can therefore pre-satisfy the later rider after the first paid cast.
Suggested fix: bind the performed latch to the exact resulting cast/continuation gate at the choice point, rather than recursively stamping the entire retained chain. Add a real pipeline regression with two independent optional gates and prove the later rider remains false until its own optional cast succeeds.
🟡 Non-blocking
crates/engine/data/known-tokens.tomlstill moves generated entries in the current diff. Rebase on currentmain, restore/regenerate the registry so only intentional data changes remain.- The current parse-diff artifact is bound to this head and lists Form of Squirrel, Prahv, Conduit of Worlds, and Innocuous Researcher. Please either contain that parser blast radius or document and validate all four; it does not change the two blockers above.
crates/engine/src/parser/oracle_effect/tests.rs:31669-31678only asserts a genericQuantityCheck; make it assert the intended spells-cast-this-turn zero comparison.
✅ Clean
The Conduit runtime tests do exercise accept and decline through the cast-offer pipeline, and the current required GitHub checks are green. Those facts do not cover the cross-zone timing or two-independent-gate cases above.
Recommendation: request changes. Please address the two blockers with the generalized timing/latch design and discriminating runtime coverage, then rebase/rescope the generated and parse-diff artifacts.
Address CodeRabbit review on phase-rs#6958: - Reject the fail-open path for a restored RestrictionPlayerScope::SourceController placeholder. add_restriction always lowers it to SpecificPlayer at creation, so a live/legitimately-captured state never carries the raw scope; only a corrupt or forged snapshot can. Both casting.rs and combat.rs consumers fail OPEN on it (returning false, bypassing the prohibition; the casting debug_assert would also panic in debug/test after such a restore). Add GameState::drop_unresolved_source_controller_restrictions and call it from the single restore chokepoint PersistedGameState::into_game_state so both the Raw and Trusted paths are scrubbed. The original activator cannot be recovered (CR 611.2c: the effect outlives its source), so the unbindable restriction is dropped rather than rebound to the source's current controller. Add a round-trip regression test across both envelopes and cross-reference the sanitizer from both consumers. - Attribute CR 608.2g (cast during resolution) and CR 608.2c (instruction order / "if you do" rider) per-clause in the Conduit line-2 test doc. - Tighten the cast resolution-gate assertion to the concrete QuantityCheck (spells cast this turn by the controller == 0) instead of matching the variant alone. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/engine/src/types/game_state.rs`:
- Around line 8783-8801: Correct the activator-binding citations in the
sanitizer documentation at crates/engine/src/types/game_state.rs lines 8783-8801
by removing or replacing CR 611.2c with verified rules that describe the
activated ability’s “you” and duration, retaining CR 109.5 and CR 611.2a as
applicable. Apply the same citation correction to the restore test documentation
at lines 21755-21762; no behavior changes are required.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 8edd92ba-0377-4ff2-b401-aef8a032d548
📒 Files selected for processing (4)
crates/engine/src/game/casting.rscrates/engine/src/game/combat.rscrates/engine/src/parser/oracle_effect/tests.rscrates/engine/src/types/game_state.rs
🚧 Files skipped from review as they are similar to previous changes (3)
- crates/engine/src/game/casting.rs
- crates/engine/src/parser/oracle_effect/tests.rs
- crates/engine/src/game/combat.rs
…ding CodeRabbit review: CR 611.2c governs which objects a characteristic/ control-changing continuous effect locks onto — it does NOT establish that a "you can't cast additional spells" restriction stays bound to the original activator. The activator binding is CR 109.5 (an activated ability's "you" is the player who activated it) and the persistence is CR 611.2a (the effect lasts until end of turn regardless of the source). Replace the misattributed CR 611.2c with CR 109.5 + CR 611.2a in the sanitizer doc, its call site, and the restore regression test doc. Comment-only; no behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
matthewevans
left a comment
There was a problem hiding this comment.
Changes requested — reviewed current head 563c6e3871e68e1d242c495006adb66ac5227d57.
🔴 Blocker
[HIGH] Derive paid cast timing from the instruction and duration, not the chosen target's zone. crates/engine/src/parser/oracle_effect/mod.rs:22689-22703 explicitly leaves hand/exile/library chosen targets on the lingering path, and :22819-22841 selects DuringResolution only through parent_target_is_graveyard_scoped; crates/engine/src/game/effects/cast_from_zone.rs:568-610 repeats that graveyard-only runtime gate. A no-duration resolving instruction that permits a paid cast must offer it during resolution; the same supported chosen-target form instead receives later lingering timing outside the graveyard. Carry instruction timing/duration as the cast-driver authority independently of TargetFilter zone, route that one-shot full-cost cast through the shared resolution offer, and add hand/exile/library sibling runtime regressions plus an explicit-duration lingering control.
🟡 Required before merge
[MED] Correct the new CR 611.2c citations. crates/engine/src/types/ability.rs:3073-3084, crates/engine/src/game/effects/add_restriction.rs:164-175, and crates/engine/src/game/casting.rs:835-844 cite 611.2c for activator binding/source independence; the matching rationale is repeated in crates/engine/src/game/casting_tests.rs:27626-27688. That rule concerns determining the affected object set, not the claimed binding/duration behavior. Replace the citation with the verified authorities appropriate to each claim (109.5 and 611.2a), without attributing this behavior to 611.2c.
[LOW] Keep the token-fetch portability change out of this Conduit PR. scripts/fetch-token-sets.sh:22-42 changes Windows/Git-Bash process-substitution handling, but it is unrelated to the declared Conduit engine/parser scope and needs its own focused reproduction and verification. Remove it from this branch or split it into a separate PR.
Maintainer-owned cleanup and gates
The crates/engine/data/known-tokens.toml deletion is generated-registry drift and will be normalized by maintainers; it is not a contributor-blocking request. Approval also requires fresh current-head evidence: the parse-diff sticky is bound to a36ead4…, not this head, and current Rust CI has a failed shard with the other shard still running.
The prompt-census tripwire (engine.rs) was the only failing CI job on the merge ref. This PR's single effects/mod.rs hunk inserts +13 lines at :2957 (the paid graveyard-cast support), entirely above the three pinned `WaitingFor::OptionalEffectChoice` producers, shifting them 5996/6073/9048 -> 6009/6086/9061. The producers are byte-identical to origin/main at their old coordinates and add zero new census needles; scoped_library_search.rs:452 and engine.rs:11427 are unmoved; the total stays 37 and the partition stays 5/7/25. Pure coordinate drift — pin re-baselined with a drift-log adjudication entry, no producer gained or lost. Census test verified passing on the merged tree (the Linux path-separator form the pin uses matches CI's scan). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/engine/src/game/engine.rs (1)
15217-15219: 🎯 Functional Correctness | 🔵 Trivial | 🏗️ Heavy liftUse stable producer anchors in a follow-up refactor.
The current coordinates identify the intended producers, but the census remains vulnerable to unrelated insertions above
game/effects/mod.rs. Replace line-number pins with the function/content-hash anchor described in the surrounding comment, or add executable coordinate-identity checks.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/engine/src/game/engine.rs` around lines 15217 - 15219, Update the producer census entries near the listed game/effects coordinates to use stable function or content-hash anchors as described by the surrounding comment, instead of raw line-number pins. If line coordinates must remain, add executable checks that verify each coordinate still identifies the intended producer.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@crates/engine/src/game/engine.rs`:
- Around line 15217-15219: Update the producer census entries near the listed
game/effects coordinates to use stable function or content-hash anchors as
described by the surrounding comment, instead of raw line-number pins. If line
coordinates must remain, add executable checks that verify each coordinate still
identifies the intended producer.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: d968774f-beaf-4f7c-8a15-855f30b948d5
📒 Files selected for processing (9)
crates/engine/data/known-tokens.tomlcrates/engine/src/game/casting.rscrates/engine/src/game/casting_costs.rscrates/engine/src/game/casting_tests.rscrates/engine/src/game/effects/mod.rscrates/engine/src/game/engine.rscrates/engine/src/parser/oracle_effect/mod.rscrates/engine/src/types/ability.rscrates/engine/src/types/game_state.rs
🚧 Files skipped from review as they are similar to previous changes (8)
- crates/engine/src/game/casting.rs
- crates/engine/src/types/ability.rs
- crates/engine/src/game/casting_costs.rs
- crates/engine/src/game/effects/mod.rs
- crates/engine/src/types/game_state.rs
- crates/engine/src/game/casting_tests.rs
- crates/engine/data/known-tokens.toml
- crates/engine/src/parser/oracle_effect/mod.rs
matthewevans
left a comment
There was a problem hiding this comment.
+## Current-head review — changes requested
Reviewed head: da5a40e806e4bd848cca29ff234be8fec40267d0.
[HIGH] Paid, no-duration casts of a chosen target are still routed by zone
Evidence. crates/engine/src/parser/oracle_effect/mod.rs:22689-22703,22819-22841 lowers the paid, no-duration chosen-target cast form without preserving the required cast-time/zone distinction. crates/engine/src/game/effects/cast_from_zone.rs:568-610 then determines the cast path from the card's current zone. This leaves a selected card's legality/timing dependent on where a prior effect placed it, instead of modelling the chosen-target cast authorization at the resolution seam.
Why this blocks. The implementation can accept or reject the same selected card differently after otherwise equivalent zone movement. That is a rules-correctness defect in a shared casting path, not a test-only gap.
Requested direction. Represent the paid, no-duration chosen-target authorization at the parser/effect boundary and resolve it through the cast authority so the selection's intended timing/permission is retained independently of incidental current-zone routing. Cover the target case and at least sibling cases whose selected card begins in a different eligible zone.
[MED] New CR citations do not describe their annotated behavior
Evidence. The CR 611.2c citations in the ability, add_restriction, and casting changes describe continuous-effect duration, not the implemented cast-permission/restriction behavior.
Why this matters. This repository requires each CR annotation to be verified and to describe the code it annotates.
Requested direction. Remove or replace each citation only after verifying the rule text that directly governs the annotated behavior.
[LOW] Unrelated token-set fetch-script change
Evidence. scripts/fetch-token-sets.sh:23-37 is unrelated to the chosen-target casting feature.
Requested direction. Drop it from this PR or explain its direct necessity.
The generated known-tokens deletion is maintainer-owned normalization and is not a contributor blocker. The available parse-diff marker is bound to earlier head 563…, and the current-head CI run is still pending, so neither is used as acceptance evidence here.
Bring the PR up to date with main @ cdb99ba (Lady Loki, Agent of Chaos phase-rs#6945) and resolve the CR 603.5 prompt-census pin conflict. phase-rs#6945 re-baselined the three pinned `WaitingFor::OptionalEffectChoice` producers 5996/6073/9048 -> 5999/6076/9051 (its own +3 above them). This PR then inserts +13 above the same producers (paid graveyard-cast support at effects/mod.rs:2957), so the merged coordinates are 5999/6076/9051 -> 6012/6089/9064. The producers are byte-identical, add zero new census needles, scoped_library_search.rs:452 and engine.rs:11427 are unmoved, and the total/partition stay 37 and 5/7/25. Pure coordinate drift — pin resolved to the merged coordinates with an updated drift-log entry; census assertion verified matching on the merged tree (the Linux path-separator form the pin uses is what CI scans). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
matthewevans
left a comment
There was a problem hiding this comment.
Current head 476d1cd9982d5de9382fd2c10632cbeedb8810d2 has five unresolved findings.
[HIGH] Paid cast timing is selected from the parse-time zone shape rather than the cast permission's rules semantics. Evidence: crates/engine/src/parser/oracle_effect/mod.rs:22689-22703,22819-22841 upgrades a chosen graveyard target to DuringResolution, and crates/engine/src/game/effects/cast_from_zone.rs:568-610 turns that into an immediate paid offer. Why it matters: zone-dependent anaphors in the same paid one-shot class can receive different timing without a typed timing authority. Suggested fix: model the paid one-shot cast timing explicitly at the permission/effect seam and cover the relevant zone siblings.
[MED] The restriction lifetime/player-lock explanation has invalid CR provenance. Evidence: crates/engine/src/types/ability.rs:3073-3084, crates/engine/src/game/effects/add_restriction.rs:164-175, and crates/engine/src/game/casting.rs:835-850 cite CR 611.2c for the claimed independent-source behavior. Why it matters: rules annotations are an engine correctness contract; a mismatched rule citation gives future changes false authority. Suggested fix: verify and replace/remove the inaccurate provenance, then state the actual rule basis for preserving the affected player.
[MED] The optional-result latch is stamped across the entire pending continuation tree. Evidence: crates/engine/src/game/casting_costs.rs:9632-9638 calls set_optional_effect_performed_recursive, whose traversal includes sub and else branches in crates/engine/src/types/ability.rs:23942-23972. Why it matters: unrelated optional gates in the same continuation can be made true by this cast. Suggested fix: latch only the continuation node causally tied to this cast and add a sibling-gate negative test.
[MED] The current parse impact exceeds the claimed Conduit-only scope. Evidence: the SHA-bound parse artifact reports 4 cards / 7 signatures (Conduit of Worlds, Innocuous Researcher, Form of the Squirrel, and Prahv), while the parser broadening in oracle_effect/mod.rs:3947-3994 and the body/tests center Conduit. Why it matters: unreviewed parser blast radius can change other supported cards. Suggested fix: justify and test every affected card or narrow the grammar to the intended class.
[LOW] scripts/fetch-token-sets.sh:23-37 is unrelated to Conduit/restriction/cast behavior. Why it matters: unrelated maintenance increases review and regression surface. Suggested fix: split it into a dedicated PR.
…cript change Address matthewevans review (head 476d1cd): [MED] CR provenance: replace the PR-added CR 611.2c citations for the SourceController activator-binding / source-independence claim with the verified authorities — CR 109.5 (an activated ability's "you" is the player who activated it) and CR 611.2a (the rules-modifying continuous effect lasts until end of turn, a source-independent turn-based duration). CR 611.2c concerns the affected-object set for characteristic/control-changing effects, not this binding. Fixed in types/ability.rs, game/effects/add_restriction.rs, game/casting.rs, and the four sites in game/casting_tests.rs. Pre-existing correct 611.2c uses (affected-set locking) are untouched. [LOW] Remove the unrelated scripts/fetch-token-sets.sh Windows/git-bash process-substitution portability change; reverted to origin/main so it drops out of this PR (belongs in its own focused PR). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
matthewevans
left a comment
There was a problem hiding this comment.
Request changes — the current head still has three substantive correctness/proof gaps.
🔴 Blocker
crates/engine/src/parser/oracle_effect/mod.rs:22689-22703 and :22819-22840 classify paid, no-duration, chosen-target casts as DuringResolution only when the target is graveyard-scoped, while crates/engine/src/game/effects/cast_from_zone.rs:585-610 re-requires that the target currently be in the graveyard. Equivalent hand, exile, and library instructions can therefore remain unresolved instead of receiving their one-shot authority. Please carry a typed one-shot authority independent of the target zone, with sibling-zone runtime tests plus a duration control.
🟡 Non-blocking before merge
crates/engine/src/game/casting_costs.rs:9632-9638 traverses and stamps every sub/else branch, and crates/engine/src/types/ability.rs:23943-23973 preserves that broad latch. Independent gates can inherit another branch's commit-time state. Please make the latch identity/path-specific and add a two-independent-gates test.
The current-head parse-diff artifact reports four cards / seven signatures, while the runtime and test evidence covers only Conduit. Please either explain and cover each card-level change discriminatively or narrow the parse impact to the intended scope.
The earlier CR-citation correction and restore hardening are accepted; CI is green.
Recommendation: implement the zone-independent one-shot authority and identity-specific latch, then provide card-level parse-diff proof for the current head.
Summary
Adds engine support for Conduit of Worlds.
Files changed
CR references
Track
Developer
LLM
Model: claude-opus-4-8
Thinking: high
Tier: Frontier
Verification
cargo fmt --all— clean (exit 0)./scripts/check-parser-combinators.sh (Gate A)— pass (exit 0): Gate G PASS + Gate A PASS head=d8856f17 base=9169d8f4; detector self-test 10/10 OK. Env fix in-loop: default python3 is a broken Windows Store stub (Permission denied); ran with native C:/msys64/mingw64/bin/python3 on PATH.cargo clippy-strict— clean (exit 0; 0 warnings under -D warnings)cargo test -p phase-engine— clean (exit 0; 18385 passed, 0 failed, plus 12/9/4402 in other suites, 0 failed)./scripts/gen-card-data.sh— clean (exit 0) after in-loop portability fixes: (1) rewrote fetch-token-sets.sh mapfile process-substitution (no /dev/fd on this git-bash) to temp-file+redirect; (2) used documented MTGJSON_SKIP_REFRESH=1 to skip the AllDeckFiles curl --retry-all-errors call (old curl 7.65; all inputs cached). Regenerated card-data.json (94M, ~35627 cards).cargo coverage— clean (exit 0): Conduit of Worlds supported:true gap_count:0 gap_details:nullcargo semantic-audit— clean (exit 0): 32703 audited, 296 flagged; Conduit of Worlds NOT in flagged_cards => 0 findingsScope Expansion
Beyond the plan's 8 steps: fixed an unforeseen double-optionality (OptionalEffectChoice + GraveyardPaidCast offer) by lowering the paid during-resolution cast as mandatory (chunk-level is_optional, mirroring FreeCastFromZones) and excluding it from the mandatory-rider seed (effect_manages_own_outcome_flag); moved the Emry duration-downgrade to lower_imperative_clause. All within Conduit support scope.
Validation Failures
None.
CI Failures
None.
Summary by CodeRabbit
New Features
Bug Fixes
Tests