Skip to content

Fix Coalition Relic zero-counter mana prompt - #7218

Merged
matthewevans merged 4 commits into
phase-rs:mainfrom
traemyn:fix/7164-coalition-relic-mana-choice
Aug 12, 2026
Merged

Fix Coalition Relic zero-counter mana prompt#7218
matthewevans merged 4 commits into
phase-rs:mainfrom
traemyn:fix/7164-coalition-relic-mana-choice

Conversation

@traemyn

@traemyn traemyn commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Coalition Relic no longer prompts for a mana color when removing zero charge counters. The shared mana prompt path now checks resolved production before offering a color choice, while positive production and existing count-scoped resolution remain intact.

Closes #7164

Files changed

  • crates/engine/src/game/effects/mana.rs
  • crates/engine/src/game/mana_abilities.rs
  • crates/engine/tests/integration/coalition_relic_integration.rs

Track

Developer

LLM

Model: GitHub Copilot (via GitHub Copilot; canonical id not exposed)
Tier: Frontier
Thinking: high

Implementation method (required)

Method: /engine-implementer

CR references

CR 106.5 — existing mana resolver/prompt authority; no new CR annotation was added.

Verification

  • Required checks ran clean, or the exact CI-owned alternative is stated below.

  • Gate A output below is for the current committed head.

  • Final review-impl below is clean for the current committed head.

  • Both anchors cite existing analogous code at the same seam.

  • cargo fmt --all -- --check — passed.

  • git diff --check — passed.

  • cargo clippy -p phase-engine --all-targets -- -D warnings — passed.

  • cargo test -p phase-engine --test integration coalition_relic_integration::coalition_relic — 2 passed, 0 failed.

  • cargo test -p phase-engine --quiet — 18,832 + 21 + 9 + 4,798 passed, 0 failed; ignored tests: 6 + 0 + 0 + 2 + 7.

  • ./scripts/check-parser-combinators.sh — passed with Gate G and Gate A.

Gate A

Gate G PASS (router/grant architecture: strict router vs permissive grant boundary intact)
Gate A PASS head=a50d51ba496eb366c6a5a53c6908d50eadf329d0 base=97591656218103d8e8c7315725b24cfe64645dd4

Anchored on

  • crates/engine/src/game/mana_abilities.rs:956 — existing AnyCombination branch resolves the production count before creating a combination prompt.
  • crates/engine/src/game/mana_abilities.rs:1109 — existing AnyCombinationOfObjectColors branch resolves the production count before creating a dynamic combination prompt.

Final review-impl

Final review-impl PASS head=a50d51ba496eb366c6a5a53c6908d50eadf329d0

Claimed parse impact

None.

Scope Expansion

None. The sibling guards remain within the same shared mana prompt authority and enforce the same zero-production invariant for existing dynamic production variants.

Validation Failures

  • cargo semantic-audit built successfully but could not run because this checkout lacks client/public/card-data.json; the command reported: card-data.json not found at client/public/card-data.json. CI or a generated card-data checkout is required for that audit.

  • Workspace-wide cargo clippy --all-targets -- -D warnings was blocked while compiling unrelated server-core because openssl-sys v0.9.116 could not find an OpenSSL installation. The touched package passed the scoped Clippy command above.

  • cargo coverage — built successfully but could not load data/card-data.json (No such file or directory); it returned an empty coverage report. CI or generated card data is required for this report.

CI Failures

None known.

Summary by CodeRabbit

  • Bug Fixes

    • Mana color prompts now use the correct sources for available colors and production amounts.
    • Color prompts are no longer shown when an effect would produce no mana.
    • Effects with unresolved production details continue to preserve existing prompt behavior.
    • Mana is correctly awarded to the intended recipient, even when another target determines the amount.
  • Tests

    • Added coverage for zero-production effects, multi-target mana generation, and end-to-end color selection.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@matthewevans, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 21 seconds

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5ac2ae87-5077-4aef-9132-2aa8bc14e478

📥 Commits

Reviewing files that changed from the base of the PR and between 41090b2 and 6798438.

📒 Files selected for processing (2)
  • crates/engine/src/game/effects/mana.rs
  • crates/engine/src/game/mana_abilities.rs

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: dbc01028-3c21-4193-947a-034941322379

📥 Commits

Reviewing files that changed from the base of the PR and between d099d43 and 41090b2.

📒 Files selected for processing (1)
  • crates/engine/src/game/mana_abilities.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/engine/src/game/mana_abilities.rs

📝 Walkthrough

Walkthrough

Mana color prompts now use separate abilities for color discovery and production-count resolution. Zero-production prompts are suppressed. Integration tests cover Coalition Relic and separate recipient and count-source targets.

Changes

Mana prompt resolution

Layer / File(s) Summary
Separate color and count resolution
crates/engine/src/game/effects/mana.rs, crates/engine/src/game/mana_abilities.rs
mana_choice_prompt now receives separate resolution contexts. Dynamic color discovery and production-count resolution use the correct abilities. Zero-production prompts are suppressed.
Coalition Relic prompt validation
crates/engine/tests/integration/coalition_relic_integration.rs
Tests verify that zero counters do not create a color prompt and that three counters produce three mana after color selection.
Recipient and count-source validation
crates/engine/tests/integration/mana_target_recipient_and_count_source.rs
Tests verify that colors come from the recipient, the amount comes from the count source, and mana is assigned only to the recipient.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested labels: test

Suggested reviewers: matthewevans

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the Coalition Relic zero-counter mana prompt fix, which is the primary change.
Linked Issues check ✅ Passed The changes prevent zero-production color prompts and preserve correct color, count, and recipient resolution for Coalition Relic and related mana effects.
Out of Scope Changes check ✅ Passed The implementation and integration tests directly support the linked issue and its required mana prompt behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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

Actionable comments posted: 3

🤖 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/effects/mana.rs`:
- Line 201: Update the color-discovery argument at the `Some(count_ability)`
call site to pass the original unscoped ability, while retaining `count_ability`
exclusively for quantity resolution. Add a regression covering
`ManaTargetRole::Both` with `ControllerRef::TargetPlayer` or `TargetOpponent`,
using distinct recipient and count-source players to verify colors come from the
recipient.

In `@crates/engine/src/game/mana_abilities.rs`:
- Around line 946-951: Add a `CR 106.5` comment annotation to the
`produces_mana` prompt logic, preferably at `mana_choice_prompt` or immediately
above the `AnyOneColor`, `AnyOneColorAmongPermanents`, and
`AnyTypeProduceableBy` gates, while leaving the existing resolver and behavior
unchanged.

In `@crates/engine/tests/integration/coalition_relic_integration.rs`:
- Around line 238-245: Replace the manually constructed
ResolvedAbility/resolve_ability_chain setup with the normal Coalition Relic
production flow through apply, WaitingFor, GameAction, or the scenario runner.
Add a paired positive-counter case that reaches WaitingFor::ChooseManaColor,
while retaining the zero-counter assertion that the state remains at
WaitingFor::Priority.
🪄 Autofix

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: 988eb3a8-fae3-4918-acda-4dbf8223d314

📥 Commits

Reviewing files that changed from the base of the PR and between 15017c3 and a50d51b.

📒 Files selected for processing (3)
  • crates/engine/src/game/effects/mana.rs
  • crates/engine/src/game/mana_abilities.rs
  • crates/engine/tests/integration/coalition_relic_integration.rs

Comment thread crates/engine/src/game/effects/mana.rs
Comment thread crates/engine/src/game/mana_abilities.rs Outdated
Comment thread crates/engine/tests/integration/coalition_relic_integration.rs
@matthewevans matthewevans self-assigned this Aug 10, 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 zero-count prompt gate is on the right authority, but it now conflates two independently scoped target contexts.

🔴 Blocker

crates/engine/src/game/effects/mana.rs:189-202 deliberately creates count_ability by retaining only the count-source player so QuantityRef::TargetZoneCardCount and LifeTotal { player: Target } resolve the right quantity. Passing that view as the sole ability argument to mana_choice_prompt changes the context used at crates/engine/src/game/mana_abilities.rs:978-986 for AnyOneColorAmongPermanents: distinct_colors_among_permanents constructs FilterContext::from_ability, so a ManaTargetRole::Both production whose color filter is relative to the recipient (TargetPlayer/TargetOpponent) derives its color options from the count source instead. AnyCombinationOfObjectColors likewise reads its target from that same argument at mana_abilities.rs:1096-1104.

The prompt needs two explicit contexts: the original resolving ability for color/target-scope discovery, and the count-scoped view only for resolve_mana_types_for_ability. Thread them separately through mana_choice_prompt (the activated-mana-ability caller can use its one context for both), then add a regression with distinct recipient and count-source players proving the offered colors follow the recipient while the produced count follows the count source.

✅ Confirmed

The new zero-counter assertion in coalition_relic_integration.rs:217-248 is discriminating for this regression: resolve_ability_chain reaches the production resolver, and the pre-fix behavior leaves WaitingFor::ChooseManaColor; it need not reconstruct unrelated optional-trigger dispatch to establish the prompt boundary. The existing CR 106.5 annotations at the affected prompt branches correctly describe the no-production behavior.

Recommendation: split the prompt's color-discovery and count-resolution contexts, cover the Both case, then request re-review on the new head.

@matthewevans matthewevans removed their assignment Aug 10, 2026
@matthewevans

Copy link
Copy Markdown
Member

Correction to my formal review: the reference to AnyCombinationOfObjectColors was overbroad and is not part of the blocker. retain_only_player_at in effects/mana.rs:64-71 preserves every object target, and object_colors_for_scope reads an object target, so that branch retains the correct object scope.

The requested change remains: AnyOneColorAmongPermanents at mana_abilities.rs:978-986 uses FilterContext::from_ability for a player-relative filter, so passing count_ability instead of the original ability misidentifies TargetPlayer/TargetOpponent whenever recipient and count-source differ. The formal requested-changes review otherwise stands.

@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown

Generated for head 6798438f974f06f31b12aecd4facafb89a7a323d.

Parse changes introduced by this PR

✓ No card-parse changes detected.

@matthewevans matthewevans self-assigned this Aug 12, 2026
@matthewevans matthewevans added the bug Bug fix label Aug 12, 2026
@matthewevans

Copy link
Copy Markdown
Member

Current-head review is complete; holding only for the current CI evidence.

The prior requested change is resolved at d099d43: effects/mana.rs:197-203 now passes the original ability for dynamic color discovery and the count-scoped view only for quantity resolution; mana_abilities.rs:984-1005 consumes those contexts separately. mana_target_recipient_and_count_source.rs:204-321 drives distinct recipient/count-source targets through casting, verifies the offered colors come from the recipient, the amount comes from the count source, and mana is deposited only to the recipient.

The required Card data (generate, validate, coverage) job is still in progress, so the only parse-diff sticky is bound to superseded a50d51b. I will re-check the fresh current-head parse diff and required checks on the next sweep, then approve/enqueue if they are clean. The bug label is applied.

@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 — zero production is still promptable for one count-bearing mana variant.

[MED] ManaProduction::ChosenColor { fixed_alternative: Some(_), count } does not consult count_ability before returning ManaChoicePrompt::SingleColor. Evidence: crates/engine/src/game/mana_abilities.rs:1018-1049; ChosenColor carries a general QuantityExpr count at crates/engine/src/types/ability.rs:2086-2100, and the parser threads that count through the fixed-alternative form at crates/engine/src/parser/oracle_effect/mana.rs:1435-1445. Why it matters: when such a count resolves to zero (the same legal dynamic-count condition Coalition Relic exercises), the engine still asks a player to select a color even though resolution produces vec![color; 0] in crates/engine/src/game/effects/mana.rs:689-711. CR 106.5 confirms the required result: an ability that would produce mana of an undefined type produces no mana; a zero-unit production must not leave a useless choice pending. Suggested fix: route the ChosenColor fixed-alternative prompt through the same resolved-production gate used by the other count-bearing prompt branches, and add a zero-count regression that reaches the prompt authority.

The current-head CI and current-head parse-diff sticky are otherwise green/current, and the earlier recipient-vs-count-source target-context blocker is resolved at d099d43.

@matthewevans matthewevans removed their assignment Aug 12, 2026
@matthewevans

Copy link
Copy Markdown
Member

Current-head review remains complete; holding only for current CI and parse-diff evidence.

Maintainer update 6798438f974f06f31b12aecd4facafb89a7a323d contains one clean merge of current origin/main to refresh the aged parse baseline; no contributor implementation hunks were discarded. The previously requested zero-count ChosenColor fix is present before that merge, and all earlier reviewer findings were rechecked against its pre-update head.

The new head's required CI is running, including Card data (generate, validate, coverage), and no <!-- coverage-parse-diff --> result is yet bound to this head. I will re-check the required checks and the current-head parse-diff artifact when they settle; if they are clean, the next maintainer action is approval and enqueue.

@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 on 6798438f974f06f31b12aecd4facafb89a7a323d.

Current-head review confirms the prompt authority keeps the original ability for recipient-relative color discovery and uses the count-scoped view only for quantity resolution. The added role-split runtime regression proves colors come from the recipient, quantity from the count source, and deposit reaches only the recipient; the zero-count and fixed-alternative gates suppress no-op prompts. Required CI is green and the clean maintainer main merge was the one permitted parse-baseline refresh.

@matthewevans
matthewevans added this pull request to the merge queue Aug 12, 2026
@matthewevans matthewevans removed their assignment Aug 12, 2026
Merged via the queue into phase-rs:main with commit 8c6f0a0 Aug 12, 2026
15 checks passed
@traemyn
traemyn deleted the fix/7164-coalition-relic-mana-choice branch August 14, 2026 21:47
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.

Coalition Relic prompting player to choose mana color when it has no charge counters — Card text: "... At the beginning…

2 participants