fix(r2-02): write dispatch defaults to non-idempotent — no-retry arm authoritative (03/S12 layer 2)

This commit is contained in:
Joseph Doherty
2026-07-13 10:04:09 -04:00
parent eab0b6be12
commit 496f97da20
3 changed files with 14 additions and 7 deletions
@@ -75,6 +75,9 @@ public sealed class DriverInstanceActorResilienceWiringTests : RuntimeActorTestB
reply!.Success.ShouldBeTrue();
driver.Writes.Count.ShouldBeGreaterThanOrEqualTo(1); // the invoker's call-site actually ran
invoker.Calls.ShouldContain(c => c.Capability == DriverCapability.Write && c.Host == "plc-7");
// 03/S12: the dispatch site must default writes to NON-idempotent so the invoker's no-retry arm is
// authoritative — a command-shaped write (pulse, counter, supervisory) must never replay.
invoker.WriteCalls.ShouldContain(c => c.Host == "plc-7" && c.IsIdempotent == false);
}
/// <summary>Records every capability + resolved-host key routed through it, then delegates to the
@@ -83,6 +86,7 @@ public sealed class DriverInstanceActorResilienceWiringTests : RuntimeActorTestB
private sealed class RecordingInvoker : IDriverCapabilityInvoker
{
public ConcurrentQueue<(DriverCapability Capability, string Host)> Calls { get; } = new();
public ConcurrentQueue<(string Host, bool IsIdempotent)> WriteCalls { get; } = new();
public ValueTask<TResult> ExecuteAsync<TResult>(
DriverCapability capability, string hostName,
@@ -105,6 +109,7 @@ public sealed class DriverInstanceActorResilienceWiringTests : RuntimeActorTestB
Func<CancellationToken, ValueTask<TResult>> callSite, CancellationToken cancellationToken)
{
Calls.Enqueue((DriverCapability.Write, hostName));
WriteCalls.Enqueue((hostName, isIdempotent));
return callSite(cancellationToken);
}
}