fix(imessage): detect and recover anchorless watch payloads before routing#84503
fix(imessage): detect and recover anchorless watch payloads before routing#84503zhangguiping-xydt wants to merge 6 commits into
Conversation
|
Thanks for the context here. I swept through the related work, and this is now duplicate or superseded. Close as superseded: #86150 now owns the same iMessage anchorless-payload repair on current main, with broader detection, route-level assertions, changelog coverage, and explicit credit for this contribution. Canonical path: Use #86150 as the canonical landing path for #84470, porting any uniquely useful assertion from this branch only if maintainers want it. So I’m closing this here and keeping the remaining discussion on #86150 and #84470. Review detailsBest possible solution: Use #86150 as the canonical landing path for #84470, porting any uniquely useful assertion from this branch only if maintainers want it. Do we have a high-confidence way to reproduce the issue? Yes at source level: current main enqueues the reported chat_id=0, empty identifier, is_group=false shape before repair, where coalesceSameSenderDms can bucket it as a sender DM. I did not reproduce a fresh live malformed iMessage notification in this checkout. Is this the best way to solve the issue? No for this branch as the landing vehicle: the repair direction is valid, but the newer canonical PR carries the same fix on current main with broader detection, route-level proof, and changelog coverage. The best solution is to land or close that canonical PR, not merge both. Security review: Security review cleared: No dependency, CI, secret-handling, or supply-chain regression was found; the privacy-sensitive routing behavior is covered by merge-risk and superseded-branch handling. What I checked:
Likely related people:
Codex review notes: model gpt-5.5, reasoning high; reviewed against ad71a998ff94. |
|
ClawSweeper PR egg 🎁 Pass real behavior proof to wake the egg and unlock a hatchable treat. Where did the egg go?
|
81e73b2 to
de725a8
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞👀 Command router queued. I will update this comment with the next step. Re-review progress:
|
…uting When watch.subscribe delivers a group link-preview payload with chat_id=0, empty chat_guid/chat_identifier, and is_group=false, the message loses its conversation anchor and was being routed to the sender DM instead of the group. Add an anchorless detection guard that recovers the real conversation via chats.list + messages.history RPC lookup, or drops the event fail-closed when recovery is not possible.
The conversation-repair integration passed `repaired` to resolveIMessageInboundDecision but continued using the original `message` for rate limiting, allowlist warnings, and context building. This meant repaired chat_id/chat_name/chat_guid were lost after the routing decision, causing wrong rate-limit keys and stale metadata in the agent context payload.
Narrow anchorless recovery to explicit empty conversation fields so direct messages that rely on sender routing pass through unchanged.
Move anchor recovery ahead of live debounce classification so malformed group payloads cannot be coalesced as sender DMs before routing.
e22876f to
ee15ec6
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
ClawSweeper applied the proposed close for this PR.
|
Repair explicit anchorless iMessage watch payloads by GUID before debounce/routing, and drop unrecoverable payloads fail-closed instead of routing them as sender DMs. Closes #84470. Refs #84503. Thanks @zhangguiping-xydt and @zqchris.
|
Superseded by the maintainer fix in #86150, merged as f37fbc9. Thanks @zhangguiping-xydt for the contributor repair direction here. The landed fix keeps the same goal, reapplies it on current |
Repair explicit anchorless iMessage watch payloads by GUID before debounce/routing, and drop unrecoverable payloads fail-closed instead of routing them as sender DMs. Closes openclaw#84470. Refs openclaw#84503. Thanks @zhangguiping-xydt and @zqchris.
Repair explicit anchorless iMessage watch payloads by GUID before debounce/routing, and drop unrecoverable payloads fail-closed instead of routing them as sender DMs. Closes openclaw#84470. Refs openclaw#84503. Thanks @zhangguiping-xydt and @zqchris.
Repair explicit anchorless iMessage watch payloads by GUID before debounce/routing, and drop unrecoverable payloads fail-closed instead of routing them as sender DMs. Closes openclaw#84470. Refs openclaw#84503. Thanks @zhangguiping-xydt and @zqchris.
Repair explicit anchorless iMessage watch payloads by GUID before debounce/routing, and drop unrecoverable payloads fail-closed instead of routing them as sender DMs. Closes openclaw#84470. Refs openclaw#84503. Thanks @zhangguiping-xydt and @zqchris.
Repair explicit anchorless iMessage watch payloads by GUID before debounce/routing, and drop unrecoverable payloads fail-closed instead of routing them as sender DMs. Closes openclaw#84470. Refs openclaw#84503. Thanks @zhangguiping-xydt and @zqchris.
Repair explicit anchorless iMessage watch payloads by GUID before debounce/routing, and drop unrecoverable payloads fail-closed instead of routing them as sender DMs. Closes openclaw#84470. Refs openclaw#84503. Thanks @zhangguiping-xydt and @zqchris.
Repair explicit anchorless iMessage watch payloads by GUID before debounce/routing, and drop unrecoverable payloads fail-closed instead of routing them as sender DMs. Closes openclaw#84470. Refs openclaw#84503. Thanks @zhangguiping-xydt and @zqchris.
Summary
chat_id=0, emptychat_guid/chat_identifier,is_group=false) before they can be classified as sender DMs.coalesceSameSenderDmscannot merge malformed group payloads under the rawchat:0DM bucket.Real behavior proof
Behavior or issue addressed: iMessage group link-preview watch payloads can arrive without usable conversation anchor fields. Before this fix, live notifications entered the inbound debouncer first, so with
coalesceSameSenderDms=truemultiple anchorless group payloads from the same sender could be merged underimessage:<account>:dm:chat:0:<sender>before recovery. The merged turn was then repaired using only the first GUID and could route content from another group under the first recovered group.Real environment tested: macOS 26.4.1, Node.js v24.15.0, OpenClaw v2026.5.19, worktree SHA
e22876fd1bef,imsg0.9.0 installed at/opt/homebrew/bin/imsg.Exact steps or command run after this patch:
Evidence after fix:
Observed result after fix: The patched PR source starts a real OpenClaw gateway with the real iMessage plugin enabled, not skipped. The gateway starts
/opt/homebrew/bin/imsgagainst the local Messages database, reachesready, reports the iMessage account as configured/running withlastError: null, and the live channel probe confirms thewatch.subscribe,messages.history, andchats.listRPC methods required by the anchorless-payload recovery path. The regression test for the reported live coalescing path still verifies that two anchorless payloads from different groups are repaired before debounce classification, so they no longer share the rawchat:0DM bucket.Additional live evidence gathered after this patch:
chat_id=3,is_group=true), andimsg messages.historyshows a live URL message in that group:https://github.com/openclaw/openclaw/pull/84503imsg watch.subscribewas started live and returned a real notification for a new group URL message sent with the same account:subscription=1chat_id=3is_group=truetext=https://github.com/openclaw/openclaw/pull/84503Messages.app+imsg+ OpenClaw watch pipeline is live end-to-end on a real group conversation, but the notification payload itself was not malformed.What was not tested: No new malformed group link-preview notification arrived from the local Messages account during this run, so the evidence does not include a live incoming private message/GUID. The live proof above verifies the patched OpenClaw runtime, real
imsgbridge, local Messages DB access, and iMessage watch-capable channel startup; the exact malformed payload branch is covered by the monitor-level regression test using redacted synthetic GUIDs and handles.Fixes #84470
Regression Test Plan
extensions/imessage/src/monitor.watch-subscribe-retry.test.ts,extensions/imessage/src/monitor/conversation-repair.test.ts,extensions/imessage/src/monitor.gating.test.ts,extensions/imessage/src/monitor/coalesce.test.tswatch.subscribenotifications enter OpenClaw, while keeping private iMessage handles and GUIDs out of the repository.Root Cause
chat_id=0, empty chat identifiers, andis_group=false,coalesceSameSenderDmscould classify it as a sender DM before the GUID-based repair path had a chance to recover the real group.