6b3c117d1e
Replaces the inline diagnostic strings in PR A.3's AcknowledgeAlarm + QueryActiveAlarms handlers with an IAlarmRpcDispatcher seam. - IAlarmRpcDispatcher (new) — gateway-side abstraction over the worker-RPC path that fronts AlarmClient.AlarmAckByGUID and the active-alarm walk. AcknowledgeAsync returns the AcknowledgeAlarmReply directly; QueryActiveAlarmsAsync yields an IAsyncEnumerable<ActiveAlarmSnapshot>. - NotWiredAlarmRpcDispatcher (new, default impl) — returns PROTOCOL_STATUS_OK with a structured worker-pending diagnostic on Acknowledge, yields an empty stream on QueryActiveAlarms. Same observable shape as PR A.3, but the integration seam is now in code instead of hardcoded inside the handler. - MxAccessGatewayService — handlers delegate to the dispatcher. Constructor accepts an optional IAlarmRpcDispatcher (default NotWiredAlarmRpcDispatcher); a future WorkerAlarmRpcDispatcher registration in DI swaps in the live worker-IPC routing without changing the public RPC surface. - 2 new dispatcher tests pin the not-wired contract; 279 → 281 total tests, all green. Worker-side dispatch (translating Acknowledge / QueryActiveAlarms to the IPC method that calls IMxAccessAlarmConsumer from PR A.5) is the dev-rig follow-up — it depends on validating the AVEVA GetAlarmChangesCompleted event subscription against a live alarm provider before pinning a wire format. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>