fix(slack): prevent thread parent edit replays - #73450
Open
nahyeongjin1 wants to merge 2 commits into
Open
Conversation
teknium1
reviewed
Jul 30, 2026
teknium1
left a comment
Contributor
There was a problem hiding this comment.
Thanks for isolating a real Slack ingress replay path. Current main still normalizes every message_changed event at plugins/platforms/slack/adapter.py:5251-5283, so filtering metadata-only parent updates is worthwhile.
Problems
- The new classifier can drop a real visible removal. In the PR at
plugins/platforms/slack/adapter.py:5284, a prior non-emptyattachments/files/blocksvalue and an omitted current value is marked unknown, not changed. If reply metadata also changes, the return at the new reply-metadata guard suppresses the event. Treat a formerly non-empty visible field becoming missing/empty as a visible change, and add coverage for that case. - The test hunk is stale: its anchor was removed by
6b81590c55fromtests/gateway/test_slack.py; GitHub currently marks the branchDIRTY.
Suggested changes
- Preserve visible field removals, then relocate the focused regressions into current test structure.
Automated hermes-sweeper review.
Co-authored-by: codex <noreply@openai.com>
nahyeongjin1
force-pushed
the
fix/slack-thread-parent-replay
branch
from
July 30, 2026 23:34
d57215a to
abe5fce
Compare
Slack emits `message_changed` for existing thread parents. When the root timestamp was absent from the process-local `_processed_message_ts` set, the adapter normalized that edit as fresh inbound input and replayed instructions the agent had already acted on. Classify parent edits before normalization: filter metadata-only updates without suppressing proven visible text, block, attachment, or file changes, and suppress later edits of replied parents whose pre-edit snapshot already addressed this workspace's bot by mention, Block Kit, or configured wake pattern. A newly added mention still routes exactly once when the previous snapshot reliably proves the bot was not addressed; a missing, partial, or malformed `previous_message` fails closed. Reply evidence and traversed Block Kit shapes are validated before being used as proof, and bot identity stays scoped to the event team. Co-authored-by: codex <noreply@openai.com>
This was referenced Aug 10, 2026
19 tasks
|
I opened #83501 as a deliberately narrower, current-main alternative for the metadata-only replay path. It filters hidden thread-parent updates that change only Slack reply bookkeeping while preserving visible text, block, attachment, file, and newly-added mention changes. The broader answered-parent and bot-address-history policy in this PR remains a distinct follow-up rather than being silently replaced. |
This was referenced Aug 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Slack can emit
message_changedfor an existing thread parent. In the incident that motivated this follow-up, the Slack thread contained a root text edit but no new user reply; the adapter normalized that edit as fresh inbound input when the root timestamp was absent from the process-local_processed_message_tsset.A missing in-memory timestamp does not prove that the root was never delivered. Replaying an already-addressed parent can therefore create a phantom user turn from instructions the agent already acted on.
This PR now handles both replay classes before message normalization:
previous_messageis missing, partial, or malformedUsers who want revised parent text acted on can send a new thread reply. The adapter does not synthesize one and does not add durable session infrastructure.
Related Issue
N/A — reproduced from a live Slack Socket Mode event sequence and covered by regression tests.
Type of Change
Changes Made
plugins/platforms/slack/adapter.pytests/gateway/test_slack.pyHow to Test
The broader Slack run dynamically resolves every
tests/**/*slack*.pyfile and passes all 33 files.Verification
26 passedtests/gateway/test_slack.py:260 passed33 files, 476 passedpy_compile: passedgit diff --check: passedmainconflict probe: clean; no relevant overlap since the reviewed target snapshotA local canonical full-run attempt did not pass: it reported 73 non-Slack test failures and 10 collection/import failures. No Slack test failed in that run, and the full-suite checklist remains unchecked. Upstream Actions remain the authority for the repository-wide and cross-platform result.
Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
cli-config.yaml.exampleif I added/changed config keys — N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — N/AScreenshots / Logs
The regression tests model sanitized Slack envelopes directly; no workspace-specific logs or identifiers are included.