refactor(battlenode): drop obsolete pre-ingest spellboost peek (Phase 2 revised, O-HC-5)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-06-06 19:28:21 -04:00
parent fcd64c8c11
commit fcc30ffe5e
2 changed files with 0 additions and 90 deletions

View File

@@ -1,10 +1,7 @@
using NUnit.Framework;
using SVSim.BattleNode.Sessions.Engine;
using System.Collections.Generic;
using System.Linq;
using SVSim.BattleEngine.Tests;
using SVSim.BattleNode.Protocol;
using SVSim.BattleNode.Sessions.Dispatch;
namespace SVSim.BattleEngine.Tests.SessionEngine;
@@ -28,60 +25,4 @@ public class SessionEngineSpellboostTests
Assert.That(engine.IsReady, Is.True, "engine must be ready after EngineGlobalInit (carried-risk fix)");
}
// BLOCKED (Phase 2 N2 Task 3): this is the non-circular oracle for engine-derived spellboost — it
// replays cl1's RAW send frames (which build charges via `alter` ops but NEVER carry the count) and
// asserts the engine's derived count equals prod's INDEPENDENT emission to cl2:
// cl1 playIdx 2 (cardId 100314020) -> spellboost 1
// cl1 playIdx 14 (cardId 101314020) -> spellboost 2
//
// It currently FAILS ({2:0, 14:0}) — NOT because of the read surface (PlayedCardSpellboost /
// PeekPlayedCardSpellboost are correct and wired), but because the headless receive path does not
// apply the wire's authoritative card resolution at all:
// * Deal / Swap / Ready do NOT seat the mulligan hand (hand stays empty through them); the
// authoritative hand seating is deferred into VfxMgr InstantVfx delegates + an OnReceiveDeal
// view callback that the headless shadow does not drive.
// * TurnStart draws the engine's OWN deck-top instead of the wire `move` op's idx (so e.g. the
// drawn card idx14 never enters hand).
// * PlayActions never removes the played card from hand (the play does not resolve), so the
// spell_charge skill never fires and no `alter` spellboost accumulates (all cards stay sb0).
// Both seats degrade to "top N of the seeded deck", every wire orderList (move/alter/play) a no-op.
//
// Closing this requires Engine/*.cs (and VfxMgr-execution) LOGIC changes to make the recovery-mode
// receive path consume the live wire orderList — which the N2 playbook classifies as an ESCALATION,
// not a mechanical no-op fill. [Ignore] keeps the SessionEngine suite green; remove it (and the
// skip-list ts-replay scaffolding can collapse to InterleavedSends) once the receive path applies
// wire-authoritative resolution. N1's shadow-replay passes only because it asserts structural
// INVARIANTS (life/pp/board/hand bounds), never the actual card identities or spellboost VALUE.
[Test]
[Ignore("BLOCKED N2 Task 3: headless receive path does not apply wire orderList (Deal/draw/play/alter); needs Engine logic change — see comment.")]
public void Engine_derives_played_card_spellboost_matching_prod_emission()
{
EngineGlobalInit.EnsureInitialized();
var cl1 = CaptureReplay.Load("battle_test_cl1.ndjson");
var cl2 = CaptureReplay.Load("battle_test_cl2.ndjson");
var deckA = CaptureReplay.SelfDeckFrom(cl1);
var deckB = CaptureReplay.SelfDeckFrom(cl2);
foreach (var id in deckA.Concat(deckB).Distinct()) HeadlessCardMaster.Load((int)id);
var engine = new SessionBattleEngine();
engine.Setup(masterSeed: CaptureReplay.SeedFrom(cl1), seatADeck: deckA, seatBDeck: deckB);
var expected = new Dictionary<int, int> { [2] = 1, [14] = 2 };
var seen = new Dictionary<int, int>();
foreach (var (env, seat) in CaptureReplay.InterleavedSends(cl1, cl2))
{
engine.Receive(env, isPlayerSeat: seat);
if (seat && env.Uri == NetworkBattleUri.PlayActions)
{
int playIdx = (int)KnownListBuilder.AsLong(
((env.Body as RawBody)?.Entries ?? new()).GetValueOrDefault(WireKeys.PlayIdx));
if (expected.ContainsKey(playIdx)) seen[playIdx] = engine.PlayedCardSpellboost;
}
}
Assert.That(seen, Is.EquivalentTo(expected),
"engine-derived spellboost must match prod's independent emission to cl2");
}
}