Fourth PR of the alarms-over-gateway epic
(docs/plans/alarms-over-gateway.md). Independent of Tracks A and B —
the sidecar slot defined in HistorianFrameHandler line 242 is unwired
today; PR C.2 (next) flips it on in Program.cs.
- AlarmHistorianWriteOutcome (sidecar-local, net48 — twin of
Core.AlarmHistorian.HistorianWriteOutcome which is net10): Ack /
RetryPlease / PermanentFail.
- IAlarmHistorianWriteBackend abstraction so the SDK call can be
faked in unit tests.
- AahClientManagedAlarmEventWriter implements IAlarmEventWriter,
delegates to the backend, maps Ack→true / Retry|Permanent→false
for the IPC bool[] reply contract. Backend exception → whole
batch RetryPlease (preserves the sender's queue across transients
rather than dropping). Wrong-count return defends against a
backend bug desyncing queue accounting.
- SdkAlarmHistorianWriteBackend — production binding skeleton.
Reports RetryPlease for every event and logs a structured
diagnostic until PR D.1 pins the live aahClientManaged entry
point against the dev rig. The sender's SqliteStoreAndForwardSink
retains queued events, mirroring today's NullAlarmHistorianSink
behaviour but with visible diagnostics instead of silent discard.
- MapOutcome shared helper — pinned via theory tests so the D.1
swap can change the SDK call site without reshuffling the
HRESULT → outcome mapping.
Tests:
- 6 writer tests — empty batch / single Ack / mixed Ack-Retry-
Permanent-Ack ordering / backend-throw → RetryPlease batch /
cancellation propagates / wrong-count defensive degrade.
- 5 outcome theory cases — hresult 0 → Ack, malformed wins over
hresult 0, comm error → Retry, unknown failure → Retry,
malformed + comm → Permanent.
- Full sidecar test suite: 48 passed (was 42; 6 new).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move all historian implementation files from Driver.Galaxy.Host/Backend/Historian/
to Driver.Historian.Wonderware/Backend/. Sidecar now owns the aahClientManaged /
aahClientCommon SDK references; Galaxy.Host project-references the sidecar so
MxAccessGalaxyBackend keeps building until PR 7.2 retires Galaxy.Host entirely.
10 source files moved (preserving git history via git mv):
IHistorianDataSource, HistorianDataSource, HistorianClusterEndpointPicker,
HistorianClusterNodeState, HistorianConfiguration, HistorianEventDto,
HistorianHealthSnapshot, HistorianQualityMapper, HistorianSample,
IHistorianConnectionFactory.
2 historian tests moved alongside (HistorianClusterEndpointPickerTests,
HistorianQualityMapperTests). Sidecar test project now hosts 29 tests (1 PR 3.1
smoke + 28 moved historian tests, all passing).
Galaxy.Host's remaining 6 historian-flavored tests (HistorianWiringTests,
HistoryReadAtTimeTests, HistoryReadEventsTests, HistoryReadProcessedTests)
keep passing via the project reference — using directives updated to reach
the new namespace.
Sidecar deliberately speaks no Core.Abstractions — its surface is the legacy
List<HistorianSample> shape; PR 3.4's .NET 10 client translates to the
Core.Abstractions shapes added in PR 1.1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>