feat(battle-node): push Judge after opponent TurnEnd so client transitions

Third frame in the burst, per prod TurnEnd -> Judge pairing observed in
battle-traffic_tk2_regular.ndjson (positions 10->11, 17->18, etc.).
The client's TurnEndOperation sends its own Judge and gates the next turn
on a server-pushed Judge via JudgeOperation -> ControlTurnStartPlayer.
Closes the v1.1 'Opponent's turn... forever' hang caught during smoke.
This commit is contained in:
gamer147
2026-06-01 17:37:55 -04:00
parent 007513e55c
commit 1ef101f851

View File

@@ -257,14 +257,17 @@ public sealed class BattleSession
}
case NetworkBattleUri.TurnEnd when Phase == BattleSessionPhase.AfterReady:
case NetworkBattleUri.TurnEndFinal when Phase == BattleSessionPhase.AfterReady:
// Scripted opponent: opens its turn, immediately ends it, hands control back.
// Two-frame burst — see docs/superpowers/specs/2026-06-01-battle-node-opponent-turn-loop-design.md.
// Scripted opponent: opens its turn, ends it, then pushes Judge so the
// client's JudgeOperation -> ControlTurnStartPlayer fires and the player's
// next turn begins. Three-frame burst — see
// docs/superpowers/plans/2026-06-01-battle-node-opponent-turn-judge.md.
// OpponentTurn is set then cleared within the same call to document intent;
// the only externally-observable phase after the call is AfterReady, ready for
// the next player TurnEnd to fire the cycle again.
Phase = BattleSessionPhase.OpponentTurn;
result.Add((ScriptedLifecycle.BuildOpponentTurnStart(), NoStock: false));
result.Add((ScriptedLifecycle.BuildOpponentTurnEnd(), NoStock: false));
result.Add((ScriptedLifecycle.BuildOpponentJudge(), NoStock: false));
Phase = BattleSessionPhase.AfterReady;
break;
case NetworkBattleUri.Retire: