f264977fb0
v2-ci / unit-tests (push) Has been cancelled
mxaccessgw#227 (Contracts/Client 0.4.0) adds an opt-in attach acknowledgement on StreamEvents: a StreamAttached sentinel MxEvent sent first, only after the stream's subscriber is registered on the session. This closes the #865 attach race that waiting for "stream requested" only narrowed. - Bump vendored MxGateway.Client/Contracts 0.3.0 -> 0.4.0 (nuget-packages/, pulled from the Gitea feed; local-mxgw stays the mapped source). - IGalaxySubscriber.SupportsStreamAttachedAck (default false, so fakes and older seams keep the fallback); GatewayGalaxySubscriber reads it from the live session's capabilities (stream-events-attached-ack) and passes emitStreamAttached accordingly; TracedGalaxySubscriber forwards it. - EventPump: records AttachAckExpected before the stream opens (published before StreamRequested completes); intercepts ev.StreamAttached ahead of the ReplayGap check - completes StreamAttached and continues: never dispatched, never counted as received, never a resume cursor (worker_sequence 0). The signal also completes when the loop ends so no waiter hangs. One pump = one stream, so a reconnect's new pump has a fresh signal. New counter galaxy.events.stream_attached. - AwaitCurrentEventStreamAsync: with the capability, waits on StreamAttached within the same StreamRequestWait budget (1 s); a missing ack logs a rate-limited Warning and proceeds instead of hanging. Without the capability the old StreamRequested wait is the fallback. Tests (StreamAttachedAckTests, 6): ack-gated subscribe gets its initial value; capability absent uses the fallback; missing ack times out with a warning; the sentinel is never dispatched; a dead stream releases ack waiters; reconnect gives each stream a fresh signal. With the ack wait skipped, 3 of them fail. Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi