fix(parser): honest coverage for 'double each kind of counter' class (CR 701.10e)#6068
Conversation
…(CR 701.10e)
Teach the DynamicQty swallow detector that Effect::Double{Counters} is the
intrinsic dynamic carrier for 'double the number of each kind of counter'
(it previously recognized only Effect::MultiplyCounter), clearing a
false-positive SwallowedClause on 7 correctly-parsed targeted cards
(Arcade Cabinet, Deepglow Skate, Ferrafor Young Yew, Gilder Bairn,
The First Tyrannic War, Vorel of the Hull Clade, Zimone Paradox Sculptor).
Gate the non-targeted MASS form to an honest Effect::unimplemented: Effect::Double
is targeted-only (no battlefield-enumeration path; absent from mass_all_target_filter),
so a mass population would double nothing at runtime. classify_counter_target keys
on TargetSyntax::Descriptor after the anaphor guards; resolve_counter_target is a
thin wrapper (byte-equivalent for its remove/move/multiply callers). Keeps
Ultimate Spider-Man honestly red instead of a silent false-green pending the
DoubleCountersAll mass-runtime epic.
Assisted-by: ClaudeCode:claude-opus-4.8
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
Parse changes introduced by this PR · 1 card(s), 2 signature(s) (baseline: main
|
# Conflicts: # crates/engine/src/parser/swallow_check.rs
…resolution Merge 3023f44 hand-resolved the DamageModification/DoubleTarget import conflict without running cargo fmt; reflow the use-list for the CI fmt gate. No logic change. Assisted-by: ClaudeCode:claude-opus-4.8
|
🤖 AI text below 🤖 @matthewevans — #6068 is green +
No action needed from your side beyond enqueue — I don't have merge-queue permission on the repo, so I'm handing the trigger to you. Thanks! |
matthewevans
left a comment
There was a problem hiding this comment.
Approved after current-head review: targeted counter doubling remains on the existing resolver, while the untargeted mass form is explicitly Unimplemented so coverage stays honest.
🤖 AI text below 🤖
Summary
Two parser-layer fixes for the "double the number of each kind of counter" class (CR 701.10e). FIX 1 teaches the
DynamicQtyswallow detector thatEffect::Double{ DoubleTarget::Counters }is the intrinsic dynamic carrier for this phrase (it previously recognized onlyEffect::MultiplyCounter), clearing a false-positiveSwallowedClausethat kept 7 correctly-parsed targeted cards red. §5 gates the non-targeted mass form of the phrase to an honestEffect::unimplemented, becauseEffect::Doubleis targeted-only (no battlefield-enumeration path) and would otherwise double nothing at runtime — keeping Ultimate Spider-Man honestly red rather than a silent false-green.Implementation method (required)
Method: /engine-implementer
CR references
CR 701.10e— doubling a kind of counter gives as many more as already present (amount is intrinsic to the resolver, never aQuantityExprcarrier).CR 115.1— the "target" keyword distinguishes a chosen target (TargetKeyword) from a mass descriptor.CR 608.2k— untargeted anaphor ("on it" / "that creature") binds to the cost/trigger object.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— cleancargo clippy -p engine --lib -- -D warnings— exit 0, no warningscargo test -p engine --lib(counter + swallow_check modules) — 196 passed, 0 failed, 2 ignored; 6 new tests (5 original + 1 singular-descriptor hardening)scripts/check-parser-combinators.sh— exit 0Coverage isolation (warm
oracle-gen --filterregen vs merge-basecard-data.json; full-corpuscoverage_parse_diff+semantic-auditrun in CI):[DynamicQty]→[], correctDouble{Counters}): Arcade Cabinet, Deepglow Skate, Ferrafor Young Yew, Gilder Bairn, The First Tyrannic War, Vorel of the Hull Clade, Zimone Paradox Sculptor.[DynamicQty]→[]+Effect::Unimplemented("double_counters_nontargeted")→ stays honestly red, does NOT flip (non-targeted mass; runtime deferred to theDoubleCountersAllepic).resolve_counter_targetcaller set) byte-identicalabilities+triggersvs base.Gate A
Gate A PASS head=30585b9a7040dfa9ecb894a21335196e00471663 base=be22e078bb1b05661d1ce34a21f3fbc07a136cab
Anchored on
detect_dynamic_qtyMultiplyCounter escape hatch) — analogous intrinsic-dynamic-carrier suppression extended toDouble{Counters}.resolve_counter_targetanaphor precedence) — analogous SelfRef/it-pronoun/TriggeringSource guard order reused byclassify_counter_target.Final review-impl
Final review-impl PASS head=30585b9a7040dfa9ecb894a21335196e00471663
Head history: the review-impl loop ran clean on 03b6dce. A maintainer then merged current
main(incl. the already-merged dq-a PR #6066) into this branch via merge commit 3023f44, preserving this PR's parser logic byte-for-byte; a formatting-only rustfmt reflow of the swallow_check import block (30585b9) was applied on top. No parser logic changed after the reviewed head — Gate A above is re-run on the current head.Claimed parse impact
SwallowedClausecleared (now honestly supported).Unimplemented(was a silent false-green: parsedDouble{Counters}that doubles nothing at runtime). Full support deferred (see below).Deferred follow-up (documented; not yet filed)
Making Ultimate Spider-Man (and any non-targeted mass "double each kind of counter on each X") an honest green requires an engine mass-runtime that does not exist yet:
Effect::DoubleCountersAll { target, counter_type }— a mass sibling of the targetedEffect::Double, mirroringPutCounterAll/DoublePTAll: registered inmass_all_target_filter, resolver enumerates the battlefield viamatches_target_filterwith CR 701.10e per-permanent dedupe (a permanent that is both a Spider and legendary is doubled once), plus the ~17 exhaustiveEffectmatch sites across the 5 crates. Full/add-engine-effect+/add-engine-variantlifecycle.starts_with_type_wordsupertype branch) that makes "each Spider and legendary creature you control" assemble the correctOr, travelling with the runtime above so USM's grammar + runtime land as one tested unit.This PR intentionally keeps that scope out and USM honestly red, per the honesty gate.