Skip to content

Discord and Mattermost keep the pending cursor across pipeline reinitialize #2013

Description

@Aaronontheweb

Found during the binding-actor consolidation (PR #2005) and documented in openspec/specs/channel-binding-parity/spec.md ("Pipeline reinitialize keeps each channel's cursor discipline").

The divergence. On pipeline reinitialize while a turn is in flight, Slack discards the pending message cursor (ChannelOutputEngine.DiscardPendingCursor() — only Slack calls it). Discord and Mattermost keep theirs.

Why the Discord/Mattermost behavior looks like a message-loss bug. The pending cursor belongs to a turn the reinitialize just abandoned. If a later TurnCompleted commits it, the cursor advances past messages the session never actually processed — they are then excluded from every future gap hydration. Slack's discard means the interrupted turn's messages are re-included in the next hydration instead.

Proposed fix. Align Discord and Mattermost to Slack's discard: call DiscardPendingCursor() in their ResetForPipelineReinitialize path, add a cross-channel contract scenario (reinitialize mid-turn, then complete a turn, assert the abandoned cursor was not committed and the interrupted messages hydrate), and update the parity spec scenario to a single SHALL. Small change; the engine hook already exists.

Why not fixed in #2005. That change was zero-behavior-change by contract; this is a deliberate behavior decision, so it is tracked here for a product call.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions