diff --git a/SVSim.BattleNode/Lifecycle/ScriptedLifecycle.cs b/SVSim.BattleNode/Lifecycle/ScriptedLifecycle.cs
index d8ec94c..0b9e6d6 100644
--- a/SVSim.BattleNode/Lifecycle/ScriptedLifecycle.cs
+++ b/SVSim.BattleNode/Lifecycle/ScriptedLifecycle.cs
@@ -99,9 +99,10 @@ public static class ScriptedLifecycle
Spin: ScriptedProfiles.ReadySpin));
///
- /// Generic TurnStart push used to transition the client into "Opponent's turn…" state
- /// after the player's TurnEnd. v1 doesn't simulate the opponent — once this lands the
- /// client sits at the opponent-turn display indefinitely.
+ /// First half of the v1.1 scripted opponent turn cycle: pushed after the player's
+ /// TurnEnd, transitions the client into "Opponent's turn…" state. Paired with
+ /// , which immediately follows and hands control
+ /// back to the player.
///
public static MsgEnvelope BuildOpponentTurnStart() =>
EnvelopeForPush(NetworkBattleUri.TurnStart,
diff --git a/SVSim.UnitTests/BattleNode/Lifecycle/TypedBodyWireShapeTests.cs b/SVSim.UnitTests/BattleNode/Lifecycle/TypedBodyWireShapeTests.cs
index 73ef459..f35e54f 100644
--- a/SVSim.UnitTests/BattleNode/Lifecycle/TypedBodyWireShapeTests.cs
+++ b/SVSim.UnitTests/BattleNode/Lifecycle/TypedBodyWireShapeTests.cs
@@ -158,6 +158,18 @@ public class TypedBodyWireShapeTests
Assert.That(node["uri"]!.GetValue(), Is.EqualTo("TurnStart"));
}
+ [Test]
+ public void BuildOpponentTurnEnd_SerializesTurnStateAndResultCode()
+ {
+ var env = ScriptedLifecycle.BuildOpponentTurnEnd();
+ var json = MsgEnvelope.ToJson(env);
+ var node = JsonNode.Parse(json)!.AsObject();
+
+ Assert.That(node["turnState"]!.GetValue(), Is.EqualTo(0));
+ Assert.That(node["resultCode"]!.GetValue(), Is.EqualTo(1));
+ Assert.That(node["uri"]!.GetValue(), Is.EqualTo("TurnEnd"));
+ }
+
///
/// Wire-shape fixture: 30 copies of the legacy DummyCardId (100_011_010L) so the
/// existing literal assertions on selfDeck[0].cardId (line 81 above) keep working