diff --git a/SVSim.UnitTests/BattleNode/Integration/CaptureConformanceTests.cs b/SVSim.UnitTests/BattleNode/Integration/CaptureConformanceTests.cs index 8473a0a..92c3fe5 100644 --- a/SVSim.UnitTests/BattleNode/Integration/CaptureConformanceTests.cs +++ b/SVSim.UnitTests/BattleNode/Integration/CaptureConformanceTests.cs @@ -353,6 +353,28 @@ public class CaptureConformanceTests Assert.That(ourEntry.GetProperty("to").GetInt32(), Is.EqualTo(20)); } + [Test] + public void MineCopyTokens_extracts_the_prod_capture_copy_op_shape() + { + // Prod copy op (battle-traffic_tk2_regular.ndjson:196) — the ONLY copy op in any capture, an + // isSelf:0 Echo: {add:{idx:[49], isSelf:0, card:{baseIdx:21, isPremium:0}}}. No later play-reveal + // of idx 49 exists, so this locks the copy-op PARSE + map-resolution only (spec §5), not a reveal. + var orderList = new List + { + new Dictionary { ["add"] = new Dictionary + { ["idx"] = new List { 49L }, ["isSelf"] = 0L, + ["card"] = new Dictionary { ["baseIdx"] = 21L, ["isPremium"] = 0L } } }, + }; + // baseIdx 21 lives in the opponent's (isSelf:0 -> otherMap) index space. The capture never reveals + // idx 21's cardId, so seed a sentinel; this verifies parse + resolution of the op shape, not an id. + var otherMap = new Dictionary { [21] = 123_456_789L }; + var mined = SVSim.BattleNode.Sessions.Dispatch.KnownListBuilder + .MineCopyTokens(orderList, new Dictionary(), otherMap) + .ToList(); + + Assert.That(mined, Is.EquivalentTo(new[] { (49, 123_456_789L, 0) })); + } + [Test] public void SynthesizedChoiceGeneration_matches_prod_recv_keyAction_and_knownList_shape() {