af318fb442
Native ADS notifications (the default subscribe mode) were stored as opaque handles with no record of the symbol/type/interval/handler needed to replay. On a client swap (EnsureConnectedAsync building a fresh client after a drop) the notifications were silently orphaned — no Bad status, no error, pushes just stopped until redeploy. Compounding: the IsConnected fast-path keys on AMS-port state, not wire liveness, and a probe failure only transitioned state without recycling the dead client. Fix: - Store REPLAYABLE INTENT: NativeRegistration (symbol/type/bit/interval/onChange + swappable live handle) hung off DeviceState.NativeRegistrations, populated by SubscribeAsync via RegisterNotificationAsync (under ConnectGate). - Split EnsureConnectedAsync into a gate wrapper + EnsureConnectedUnderGateAsync core; when the core installs a NEW client it replays every stored intent onto it and swaps the live handle (disposing the dead one). Register + replay both run under ConnectGate so they can't race. - Probe loop: on a wire-probe failure (false or throw) RecycleClientAsync disposes+nulls the client so the next tick rebuilds + replays — closes the fast-path-keys-on-port-state compounding bug. No TwinCAT docker fixture exists (integration needs a real TC3 XAR), so the fake-client unit tests are the authoritative coverage: - 4 new guards in TwinCATReconnectReplayTests (replay-onto-fresh-client + push reaches OnDataChange + old handle disposed; replay-all-tags; unsubscribe-after-reconnect stops replaying; probe-failure recycles+rebuilds). - Full TwinCAT unit suite 174/174 green; full solution builds 0 errors.