Skip to content

Post the Slack reply before acking its recovery delivery #44

Description

@mariohercules

Problem

pollRun acks a run's recovery delivery as soon as the run reaches a terminal state (src/slack/core-bridge.ts:154-156), which tombstones the durable copy. The reply itself is posted afterwards by the turn handler (src/slack/turn-handler.ts:543,548) through postReply, which is a plain chat.postMessage with retries disabled (NO_RETRY, src/slack/config.ts:3, applied at src/slack/index.ts:47) and carries no idempotency metadata.

If that single post attempt fails — a chat.postMessage rate limit, a transient 5xx, or a redeploy during the attachment upload window — the exception is swallowed, the run is already terminal, and the delivery is already stamped delivered. The user never receives the answer and nothing retries it.

The quarantine refusal path deliberately does the opposite, posting before it acks (postThenAckRunDelivery, src/slack/refusals.ts:15-27).

The current ordering is load-bearing for duplicate suppression: the live post carries no qm_delivery metadata, so the delivery poller's verify-first scan could not recognize it and would repost. Any fix needs to preserve that.

Expected behavior

A run's reply is durably recoverable until it has actually been posted. A post failure leaves the delivery pending so the existing poller retries it, without introducing a duplicate for the common case where the live post succeeded.

Acceptance criteria

  • The recovery delivery is acked only after the reply has been posted successfully.
  • The live post carries the same identifying metadata the delivery poller verifies against, so a retry cannot double-post.
  • A failed live post leaves the delivery claimable, and the poller delivers it.
  • Tests cover a failing chat.postMessage and assert the user still receives exactly one reply.

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