94ae186050
RealMxGatewayClient.RunEventLoopAsync stored every streamed MxEvent's WorkerSequence as its StreamEvents resume cursor before filtering by family. The gateway's control sentinels (ReplayGap on a resume that hit evicted events; the opt-in StreamAttached ack) carry worker_sequence 0, so a gap reset the cursor to 0 and the next resume became a fresh stream: no replay, no gap signal, silent loss. Cursor rule: advance-only (max), from real worker events (sequence > 0) only. A ReplayGap anchors the cursor at oldest_available_sequence - 1 (the gateway's documented gap-free resume point, valid for an empty ring too) and is logged as a warning naming the lost interval. Sentinels never reach the value callback. The loop body is split into internal RunEventLoopCoreAsync(IAsyncEnumerable) so tests drive a scripted stream; 4 of the 7 new tests fail on the old loop. Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi