diff --git a/SVSim.UnitTests/BattleNode/Integration/HeadlessConductorTests.cs b/SVSim.UnitTests/BattleNode/Integration/HeadlessConductorTests.cs
index 12794fb..d0342b2 100644
--- a/SVSim.UnitTests/BattleNode/Integration/HeadlessConductorTests.cs
+++ b/SVSim.UnitTests/BattleNode/Integration/HeadlessConductorTests.cs
@@ -12,6 +12,7 @@ namespace SVSim.UnitTests.BattleNode.Integration;
/// SVSim.UnitTests process.
///
[TestFixture]
+[NonParallelizable]
public class HeadlessConductorTests
{
[Test]
diff --git a/SVSim.UnitTests/BattleNode/Integration/NodeNativeBattleHarness.cs b/SVSim.UnitTests/BattleNode/Integration/NodeNativeBattleHarness.cs
index d743385..3811415 100644
--- a/SVSim.UnitTests/BattleNode/Integration/NodeNativeBattleHarness.cs
+++ b/SVSim.UnitTests/BattleNode/Integration/NodeNativeBattleHarness.cs
@@ -39,14 +39,20 @@ internal sealed class NodeNativeBattleHarness : IDisposable
public const long DefaultSeatAViewerId = 1001;
public const long DefaultSeatBViewerId = 1002;
- /// Spellboost cost-reducer card (looking ahead to M-HC-3). Present in cards.json.
+ /// Spellboost cost-reducer card (looking ahead to M-HC-3). Known id present in cards.json
+ /// (sourced from tk2 battle capture / existing engine tests); a cards.json regeneration that drops
+ /// it will produce a traceable failure here.
public const long SpellboostCardId = 101314020;
- /// A second spellboost card seen in the tk2 capture; present in cards.json.
+ /// A second spellboost card seen in the tk2 capture. Known id present in cards.json
+ /// (sourced from tk2 battle capture / existing engine tests); a cards.json regeneration that drops
+ /// it will produce a traceable failure here.
public const long SpellboostCardIdAlt = 100314020;
/// A plain vanilla follower the engine resolution path proved out
- /// (HeadlessFixture.FollowerId). The bulk of the deterministic deck.
+ /// (HeadlessFixture.FollowerId). The bulk of the deterministic deck. Known id present in cards.json
+ /// (sourced from tk2 battle capture / existing engine tests); a cards.json regeneration that drops
+ /// it will produce a traceable failure here.
public const long VanillaFollowerId = 100011010;
public BattleSessionState State { get; }
@@ -135,8 +141,10 @@ internal sealed class NodeNativeBattleHarness : IDisposable
public void Dispose() { /* engine holds no unmanaged resources; nothing to release. */ }
/// Minimal test-only exposing only the
- /// + that the harness reads. All broker members are
- /// no-ops — the harness drives the engine directly, never the session relay.
+ /// + that the harness reads. Broker members
+ /// (PushAsync, RunAsync, TerminateAsync) throw
+ /// — the harness drives the engine directly, so a frame must never reach the participant relay.
+ /// Silent no-ops would let a misrouted push pass undetected.
internal sealed class StubParticipant : IBattleParticipant
{
public long ViewerId { get; }
@@ -152,9 +160,12 @@ internal sealed class NodeNativeBattleHarness : IDisposable
public event Func? FrameEmitted;
#pragma warning restore CS0067
- public Task PushAsync(MsgEnvelope envelope, Stock stock, CancellationToken ct) => Task.CompletedTask;
- public Task RunAsync(CancellationToken ct) => Task.CompletedTask;
- public Task TerminateAsync(BattleFinishReason reason) => Task.CompletedTask;
+ public Task PushAsync(MsgEnvelope envelope, Stock stock, CancellationToken ct) =>
+ throw new NotSupportedException("StubParticipant.PushAsync — harness drives the engine directly; a frame must not reach the participant relay.");
+ public Task RunAsync(CancellationToken ct) =>
+ throw new NotSupportedException("StubParticipant.RunAsync should not be called in harness tests.");
+ public Task TerminateAsync(BattleFinishReason reason) =>
+ throw new NotSupportedException("StubParticipant.TerminateAsync should not be called in harness tests.");
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
}
}