Skip to content

fix(channels): emit poll bursts in chronological order across sidecar adapters#5305

Merged
houko merged 1 commit into
mainfrom
fix/sidecar-poll-message-order
May 20, 2026
Merged

fix(channels): emit poll bursts in chronological order across sidecar adapters#5305
houko merged 1 commit into
mainfrom
fix/sidecar-poll-message-order

Conversation

@houko

@houko houko commented May 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Surfaced while reviewing the Rocket.Chat sidecar migration (#5298): four
polling sidecar adapters delivered multi-message poll bursts to the agent
in reverse chronological order.

rocketchat (channels.history), mastodon (/api/v1/notifications),
reddit (?sort=new), and bluesky (listNotifications) all poll
upstreams that return newest-first, but each iterated the raw response
and emitted in that order. When a single poll caught more than one new
message, the agent received them backwards — wrong for conversation
context. nextcloud (the closest sibling) is unaffected because Talk's
chat feed already returns oldest-first.

The bug was faithfully reproduced from the original in-process Rust
adapters, so each migration carried it forward.

Fix

Reverse each batch to oldest-first before emitting:

  • rocketchat.pyfor msg in reversed(messages) in _poll_once
  • mastodon.pyfor notif in reversed(notifs) in _poll_once
  • reddit.pyfor child in reversed(children) in _poll_once
  • bluesky.pyfor notif in reversed(notifs) in _poll_once

Dedupe sets and the per-room / since_id / max-indexedAt high-water
marks are all order-independent, so this changes delivery order only
no impact on watermark advancement or duplicate suppression.

Tests

  • Added test_poll_once_emits_in_chronological_order to each of the four
    adapter suites: feeds a realistic newest-first batch, asserts oldest →
    newest emit, and (where applicable) asserts the high-water mark still
    tracks the newest item regardless of emit order.
  • Updated existing fixtures that hand-ordered input ascending (which masked
    the bug) to the realistic newest-first shape:
    test_poll_once_emits_messages_and_advances_watermark (rocketchat),
    test_poll_once_emits_parsed_comments (reddit).
  • test_poll_once_dedupes_same_ts_repeats (rocketchat) assertion made
    order-insensitive since it covers dedupe, not ordering.

Verification

cd sdk/python && PYTHONPATH=. pytest tests/ -q
478 passed

No Rust changed (Python SDK only); cargo clippy --workspace ran clean via
the pre-push hook.

Out-of-scope (flagged, not changed here)

CHANGELOG.md on main already has two ## [Unreleased] sections
(line 8 and ~1105) — a pre-existing structural issue (the pre-commit guard
warns release tooling silently drops entries from all but the first). It
predates this branch and would require merging hundreds of lines of
unrelated entries, so I left it alone and omitted a CHANGELOG entry for
this fix rather than reorganize others' notes. Worth a dedicated cleanup.

… adapters

Rocket.Chat (channels.history), Mastodon (/api/v1/notifications), Reddit
(?sort=new), and Bluesky (listNotifications) all poll upstreams that
return newest-first, but each iterated the raw response and emitted in
that order. So a single poll catching more than one new message
delivered them to the agent in reverse chronological order.

Reverse each batch to oldest-first before emitting, matching the
chronological order nextcloud's Talk feed already yields. Dedupe sets
and per-room / since high-water marks are order-independent, so this
only changes delivery order.

Faithfully reproduced from the original in-process Rust adapters;
surfaced while reviewing the rocketchat sidecar migration (#5298).

Tests: test_poll_once_emits_in_chronological_order added to each
adapter's suite; existing fixtures that hand-ordered input ascending
updated to the realistic newest-first shape. 478 Python tests pass.
@houko
houko merged commit 526b4f8 into main May 20, 2026
14 of 15 checks passed
@houko
houko deleted the fix/sidecar-poll-message-order branch May 20, 2026 05:15
@github-actions github-actions Bot added the area/sdk JavaScript and Python SDKs label May 20, 2026
@github-actions github-actions Bot added the size/M 50-249 lines changed label May 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/sdk JavaScript and Python SDKs size/M 50-249 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant