Skip to content

fix(mattermost): keep progress notices in threads - #45861

Open
yong2bba wants to merge 2 commits into
NousResearch:mainfrom
yong2bba:fix/mattermost-progress-threading
Open

fix(mattermost): keep progress notices in threads#45861
yong2bba wants to merge 2 commits into
NousResearch:mainfrom
yong2bba:fix/mattermost-progress-threading

Conversation

@yong2bba

Copy link
Copy Markdown
Contributor

Summary

Fixes Mattermost gateway progress/status/warning messages escaping as flat channel posts when the user starts from a top-level channel message.

  • Mattermost now mirrors Slack's top-level progress-thread fallback by using the triggering post id as the progress/status thread target when source.thread_id is empty.
  • Mattermost progress sends also pass the triggering post id as reply_to, so MATTERMOST_REPLY_MODE=thread can turn it into a Mattermost root_id.
  • MattermostAdapter.send() now honors generic metadata["thread_id"] as a fallback thread anchor for synthetic sends when explicit reply_to is absent.
  • Adds regression coverage for top-level Mattermost progress anchoring and adapter metadata-thread routing.

Related PRs

Related to #36916 and #41640. Those PRs cover overlapping Mattermost thread-routing issues with broader side-channel/delivery hygiene. This PR is a smaller current-main focused fix for the specific Slack-vs-Mattermost regression where top-level Mattermost channel prompts caused warning/progress/status bubbles to land in the parent channel instead of the triggering post's thread.

Test plan

  • uv run --with pytest --with pytest-asyncio --with aiohttp pytest tests/gateway/test_mattermost.py tests/gateway/test_mattermost_thread_routing.py tests/gateway/test_goal_status_notice.py -q
  • uv run --with pytest --with pytest-asyncio --with aiohttp python -m py_compile gateway/run.py plugins/platforms/mattermost/adapter.py tests/gateway/test_mattermost.py tests/gateway/test_mattermost_thread_routing.py
  • git diff --check
  • added-lines static scan for secrets/shell/eval/pickle/SQL patterns: no matches

Notes

reply_to still takes precedence over metadata, and Mattermost root_id is still gated behind reply_mode == "thread".

@yong2bba
yong2bba force-pushed the fix/mattermost-progress-threading branch from 50cd084 to 53371a4 Compare June 13, 2026 23:56
@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have labels Jun 14, 2026
AIalliAI added a commit to AIalliAI/Hermes that referenced this pull request Jun 14, 2026
AIalliAI added a commit to AIalliAI/Hermes that referenced this pull request Jun 14, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the Mattermost routing work. The thread-routing portion is now already covered on current main by 5a0e0d35b (gateway/run.py:488-496, plugins/platforms/mattermost/adapter.py:163-176, and tests/gateway/test_mattermost.py:16-29).

Problems

  • The PR also adds an interactive command-approval callback system beginning at plugins/platforms/mattermost/adapter.py:399 in the PR diff. That is a separate security-boundary feature from the stated progress-threading fix and is not described in the PR summary.

Suggested changes

  • Any salvage should omit the already-landed routing portion.
  • Please handle the approval-action work as a focused change with explicit deployment/configuration documentation and dedicated callback-security review.

This is an automated hermes-sweeper review.

@@ -300,6 +399,176 @@ async def send(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This starts a separate interactive approval callback feature, while the PR summary describes only progress-thread routing. Since approval callbacks cross a security boundary, please split this into a focused change with explicit deployment/configuration documentation and dedicated review; the routing portion is already implemented on current main.

@teknium1 teknium1 added sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 14, 2026

@GottZ GottZ left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was generated by AI during triage.

Summary

Two PRs address the Mattermost top-level-channel progress/status threading gap: #36916 (closed) and #45861 (open, target). Both diffs implement a near-identical fix — anchoring progress/status/heartbeat sends to the triggering post's thread and teaching MattermostAdapter.send() to honor metadata['thread_id'] — and both were reviewed as already implemented on current main via commit 5a0e0d3. #45861 additionally bundles an ~460-line interactive command-approval-button subsystem (HMAC-signed callback contexts, a new aiohttp callback server, allowlist auth) that is unrelated to and undisclosed in its stated progress-threading fix.

Related pull requests

  • #36916 [closed] duplicate — (+153/-12) — closed as implemented_on_main: adds _progress_thread_id_for_source() and a metadata['thread_id'] fallback in MattermostAdapter.send() so top-level channel progress/status bubbles anchor to the triggering post; teknium1 [contributor:7327 commits] confirmed this is superseded by 5a0e0d3 already on main (gateway/run.py:17470-17482, adapter.py:362-367). Still relevant as the reference diff documenting the shape of the landed fix.
  • #45861 related — (+635/-25) — keep_open review (salvageability=medium) from teknium1 [contributor:7327 commits]: the routing portion (_progress_thread_target_for_source, adapter metadata['thread_id'] fallback) duplicates the same already-landed main fix (5a0e0d3). The PR also introduces an undisclosed Mattermost interactive-approval-button subsystem (signed callback contexts, new HTTP action server, allowlist auth) that the reviewer flags as a separate security-boundary feature needing its own focused PR and dedicated callback-security review before merge.

Duplicates

#36916 and the routing-fix portion of #45861 are essentially the same change (top-level Mattermost progress/status thread anchoring plus the metadata['thread_id'] adapter fallback), and both duplicate logic already shipped on main in 5a0e0d3.

Suggested consolidation

In line with teknium1's keep_open review on #45861: do not merge #45861 as-is — its routing fix is redundant with main's 5a0e0d3, and the bundled approval-action feature (adapter.py:399+) must be split into its own PR with explicit deployment documentation and dedicated security review before consideration. #36916 stays closed and can be discarded beyond its reference value. Recommend keeping #45861 open pending the author dropping the redundant routing hunks and splitting out the approval-button work into a separately reviewed PR.

Complex graph

flowchart LR
    classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
    classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
    classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
    classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
    classDef best stroke-width:3px,stroke:#b45309
    classDef target stroke-width:3px,stroke:#4338ca
    subgraph Dup36916 ["PRs duplicating each other"]
        P36916["PR #36916 (closed)"]
        P45861["PR #45861 (open)"]
    end
    class P36916 closed
    class P45861 open
    class P45861 target
    click P36916 "https://github.com/NousResearch/hermes-agent/pull/36916"
    click P45861 "https://github.com/NousResearch/hermes-agent/pull/45861"
Loading

Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed or no verify verdict yet (state tag in the node label).

Cross-PR triage: Reviewed 2 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 48 kB of PR diffs, 5 kB of issue/PR text, 2 kB of discussion (2 comments), 1 verify verdict. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

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

Labels

comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants