fix(mattermost): harden threaded root session isolation - #18280
fix(mattermost): harden threaded root session isolation#18280randomsnowflake wants to merge 1 commit into
Conversation
|
Additional context from running Mattermost in production: The Mattermost integration has been broken for threaded usage since at least 0.7 , and possibly earlier. I can see that the integration has been improving, but this specific issue is still a showstopper for using the bridge properly in threaded mode. Without this fix, separate Mattermost root threads in the same channel collapse into one Hermes session and block/interrupt each other. That makes the threaded interface effectively unusable for real parallel conversations. Thank you for taking a look and for merging this. My previous PRs have all been closed - this is not AI slop, it fixes an actual reproducable issue. |
|
Updated this PR branch on top of the v2026.5.7 release tag and re-ran the targeted Mattermost regression suite. Local verification before pushing:
The branch now contains the release baseline plus the Mattermost root-thread session isolation fix. |
e3893ee to
9ee050b
Compare
9ee050b to
39fa3ea
Compare
|
Update after the v2026.5.16 / v0.14.0 release: This PR is still required. I checked the clean upstream release/tag and the bug still reproduces there. Semantic repro against upstream That means two new top-level Mattermost root posts in the same channel still collapse into the same Hermes gateway session upstream. Replies inside existing Mattermost threads are distinct, but new root posts are not isolated. I updated this PR branch on top of Post-patch semantic repro: Local validation run after rebasing/updating: Note: I did not run the entire repository test suite locally; the targeted Mattermost/gateway regression suite passes, and CI should cover the broader repo matrix. |
39fa3ea to
9940f73
Compare
|
Updated this PR branch onto current upstream |
9940f73 to
267f71c
Compare
|
Follow-up: upstream |
f98fab1 to
6fde8ec
Compare
6fde8ec to
7374077
Compare
|
Rebased this PR again onto current Current state: I re-checked current upstream semantics before updating. The bug is still present upstream for fresh top-level Mattermost posts: That means upstream fixes/changes around Mattermost threading are adjacent, but they do not isolate new root posts with no I also trimmed/confirmed the PR shape: Verification on the rebased branch: Additional local adapter/session E2E check confirms: This is still the narrow fix for #18279: fresh Mattermost root posts need to become Hermes thread/session roots by using the post id when Mattermost has no |
7374077 to
129915d
Compare
|
Rebased again onto current upstream Current state: No semantic redesign was needed. The patch still does the same narrow thing: use the Mattermost post id as Hermes Fresh local verification on the rebased branch: Additional adapter-level E2E routing check: I also installed and dogfooded this locally on Hermes Agent |
|
Thank you for staying on top of this. I wonder if we could get all of the people who have been force pushing amazing fixes and features for the Hermes Mattermost integration to collectively start a Messaging Platform Adapter Plugin called something like Just a thought. |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the focused Mattermost coverage.
Problems
- Current main already implements top-level root session IDs for threaded Mattermost replies:
plugins/platforms/mattermost/adapter.py:869-876, added in5a0e0d35b, with regression coverage attests/gateway/test_mattermost.py:1029-1085. - This diff removes the
reply_mode="thread"boundary. Since the adapter defaults toreply_mode="off"(plugins/platforms/mattermost/adapter.py:95-99) and threaded session keys suppress normal per-user partitioning (gateway/session.py:941-956), the change makes every flat top-level post a separate session. That is a compatibility/design change, not the already-fixed threaded case.
Suggested changes
- Retain the thread-mode condition unless flat-mode per-post sessions are an explicitly approved behavior.
- If that broader behavior is intended, add a regression through
build_session_key()or the active-session path rather than asserting only the adapter source field.
Automated hermes-sweeper review.
| # root in CRT. Use the post id so concurrent root posts do not share | ||
| # one Hermes session/active-session guard. DMs keep the historical | ||
| # channel-scoped session behavior. | ||
| thread_id = post.get("root_id") or (post_id if chat_type != "dm" else None) |
There was a problem hiding this comment.
Current main intentionally limits top-level post IDs to reply_mode="thread" (plugins/platforms/mattermost/adapter.py:869-876). Removing that boundary changes default flat-mode channel conversations into one session per post through gateway/session.py:941-956; please retain the condition unless that compatibility change is explicitly intended.
129915d to
dabac62
Compare
|
Updated in response to the maintainer review:
Fresh verification on the rebased head I also deployed the v2026.7.20 release plus this carried commit and verified real Mattermost API thread routing: two distinct roots each received a reply whose persisted |
dabac62 to
6ecac26
Compare
|
Closing this because the threaded root-session isolation is now implemented upstream and is present in v2026.8.3 (notably via 5a0e0d3). I re-verified the release semantics: separate top-level Mattermost roots build distinct session keys in reply_mode="thread". The remaining blank-post guard is a separate, smaller behavior change and does not justify keeping this threading PR open. |
Summary
Harden Mattermost root-thread session isolation and cover the real session-key path.
Current upstream already seeds top-level channel posts as thread roots when
reply_mode="thread". This revision incorporates the maintainer review instead of broadening that behavior:reply_mode="thread"boundarybuild_session_key()valuesWhy this remains useful
The original root-thread bug is now implemented upstream, but the previous tests stopped at the adapter's
source.thread_id. The added regression exercises the downstream session-key contract that caused the real production symptom: unrelated Mattermost root posts sharing one active-session guard.The blank-post guard is the remaining behavior fix. It prevents an empty wake-up from becoming a blank user turn after the bot mention is stripped.
Scope
Two files, one commit:
plugins/platforms/mattermost/adapter.pytests/gateway/test_mattermost.pyNo flat-mode or DM compatibility change.
Current rebase
Tests
The adapter/session regression confirms: