diff --git a/tests/AVEVA.Historian.Client.Tests/WcfEventReadSpikeTests.cs b/tests/AVEVA.Historian.Client.Tests/WcfEventReadSpikeTests.cs
new file mode 100644
index 0000000..3db9017
--- /dev/null
+++ b/tests/AVEVA.Historian.Client.Tests/WcfEventReadSpikeTests.cs
@@ -0,0 +1,105 @@
+using System.Runtime.Versioning;
+using AVEVA.Historian.Client.Models;
+using AVEVA.Historian.Client.Wcf;
+using Xunit.Abstractions;
+
+namespace AVEVA.Historian.Client.Tests;
+
+///
+/// C2 live diagnostic spike (pending.md C2): does the managed WCF event-read path return rows
+/// against an event-bearing 2023 R2 historian? gRPC event reads are a proven server-side dead-end
+/// (docs/reverse-engineering/grpc-event-query-capture.md); the WCF transport is C2's only listed
+/// unblock but is itself unproven (the orchestrator documents native code 76 / 85 on this server).
+///
+/// Drives directly over RemoteTcpIntegrated and dumps the
+/// full native chain. It NEVER fails the suite (skip+log diagnostic) and is inert off Windows — the
+/// GREEN/RED call is by reading the printed "events observed" count + native return codes.
+///
+/// Gated by HISTORIAN_WCF_EVENT_HOST (independent of the gRPC live vars so it never runs by
+/// accident). Optional: HISTORIAN_WCF_EVENT_PORT (default 32568), HISTORIAN_WCF_EVENT_USER
+/// + HISTORIAN_WCF_EVENT_PASSWORD (absent => IntegratedSecurity), HISTORIAN_WCF_EVENT_SPN
+/// (Kerberos SPN override; the default is the LocalPipe identity and will not authenticate remotely),
+/// HISTORIAN_WCF_EVENT_DAYS (lookback window, default 90 — the live event store held 71,332
+/// events in -90d).
+///
+/// Run from the Windows capture rig over VPN:
+/// dotnet test --filter "FullyQualifiedName~WcfEventReadSpike" -l "console;verbosity=detailed"
+///
+[SupportedOSPlatform("windows")]
+public sealed class WcfEventReadSpikeTests
+{
+ private readonly ITestOutputHelper _output;
+
+ public WcfEventReadSpikeTests(ITestOutputHelper output) => _output = output;
+
+ [Fact]
+ public async Task WcfEventRead_DiagnosticDump_AgainstRemoteHistorian()
+ {
+ string? host = Environment.GetEnvironmentVariable("HISTORIAN_WCF_EVENT_HOST");
+ if (string.IsNullOrWhiteSpace(host) || !OperatingSystem.IsWindows())
+ {
+ return; // inert without the dedicated gate / off Windows
+ }
+
+ int port = int.TryParse(Environment.GetEnvironmentVariable("HISTORIAN_WCF_EVENT_PORT"), out int p)
+ ? p : HistorianClientOptions.DefaultPort; // 32568
+ int days = int.TryParse(Environment.GetEnvironmentVariable("HISTORIAN_WCF_EVENT_DAYS"), out int d)
+ ? d : 90;
+ string? user = Environment.GetEnvironmentVariable("HISTORIAN_WCF_EVENT_USER");
+ string? password = Environment.GetEnvironmentVariable("HISTORIAN_WCF_EVENT_PASSWORD");
+ string? spn = Environment.GetEnvironmentVariable("HISTORIAN_WCF_EVENT_SPN");
+ bool integrated = string.IsNullOrEmpty(user);
+
+ HistorianClientOptions options = new()
+ {
+ Host = host,
+ Port = port,
+ Transport = HistorianTransport.RemoteTcpIntegrated,
+ IntegratedSecurity = integrated,
+ UserName = user ?? string.Empty,
+ Password = password ?? string.Empty,
+ TargetSpn = string.IsNullOrWhiteSpace(spn) ? "NT SERVICE\\aahClientAccessPoint" : spn,
+ };
+
+ HistorianWcfEventOrchestrator orchestrator = new(options);
+ DateTime endUtc = DateTime.UtcNow;
+ DateTime startUtc = endUtc - TimeSpan.FromDays(days);
+
+ int observed = 0;
+ bool hasFirstEvent = false;
+ string outcome = "completed";
+ try
+ {
+ await foreach (HistorianEvent evt in orchestrator.ReadEventsAsync(startUtc, endUtc, filter: null, CancellationToken.None))
+ {
+ observed++;
+ hasFirstEvent = true;
+ _ = evt; // event identity intentionally NOT logged (sanitized)
+ }
+ }
+ catch (Exception ex)
+ {
+ outcome = $"threw {ex.GetType().Name}"; // message omitted — may carry host/credential text
+ }
+
+ // Sanitized diagnostic dump — counts, native return codes, buffer lengths, sha256 ONLY.
+ _output.WriteLine($"[C2 WCF spike] outcome: {outcome}");
+ _output.WriteLine($"[C2 WCF spike] events observed: {observed}");
+ _output.WriteLine($"[C2 WCF spike] hasFirstEvent: {hasFirstEvent}");
+ _output.WriteLine($"[C2 WCF spike] LastUpdC3ReturnCode: {HistorianWcfEventOrchestrator.LastUpdC3ReturnCode}");
+ _output.WriteLine($"[C2 WCF spike] LastRTag2ReturnCode: {HistorianWcfEventOrchestrator.LastRTag2ReturnCode}");
+ _output.WriteLine($"[C2 WCF spike] LastAddReturnCode(EnsT2): {HistorianWcfEventOrchestrator.LastAddReturnCode}");
+ _output.WriteLine($"[C2 WCF spike] LastAddOutputLength: {HistorianWcfEventOrchestrator.LastAddOutputLength}");
+ _output.WriteLine($"[C2 WCF spike] LastEnsT2PayloadSha256: {HistorianWcfEventOrchestrator.LastEnsT2PayloadSha256}");
+ _output.WriteLine($"[C2 WCF spike] LastResultBufferLength: {orchestrator.LastResultBufferLength}");
+ // Contract-safe: LastErrorBufferDescription is DescribeNativeError's STRUCTURED formatting of the
+ // 5-byte native error buffer ("type=N code=M (0xHEX)" / "") — never freeform server text,
+ // FQDN, SPN, or credentials. The code value (e.g. 76 / 85) is the RED-case signal this spike exists
+ // to capture, so it is dumped in full rather than reduced to a length.
+ _output.WriteLine($"[C2 WCF spike] LastErrorBufferDescription: {orchestrator.LastErrorBufferDescription}");
+ _output.WriteLine($"[C2 WCF spike] window days: {days}");
+
+ // Diagnostic: NEVER fails the suite. GREEN = observed > 0; RED = observed == 0 (read the output).
+ Assert.True(observed >= 0, "diagnostic always passes; the GREEN/RED signal is the printed count");
+ }
+}