fix: pass thread_originator_guid through bridge for iMessage threading - #208
fix: pass thread_originator_guid through bridge for iMessage threading#208dkattan wants to merge 3 commits into
Conversation
…hreading When deriveThreadIdentifier fails to load the parent message from IMChatHistoryController (older messages, cache misses), the bridge now accepts an explicit threadOriginatorGuid parameter from the RPC caller and sets it directly on the IMMessageItem via setThreadOriginatorGUID: before the IMMessage wrap. Also adds bridge.introspect RPC method for runtime class introspection of IMChat and IMMessageItem, used to discover threading/typing APIs. The typing indicator uses setTypingGUID: + setLocalUserIsTyping: when a message GUID is provided. setLocalUserIsComposing: and _setLocalUserIsComposing:suppliedGUID: both block the main thread (loading message via IMChatHistoryController) and crash Messages.app, so they are avoided. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ebug logging When IMChatHistoryController.loadMessageWithGUID:completionBlock: times out (3s), fall back to searching the chat's loaded chatItems directly to find the parent IMMessage. This prevents thread_originator_guid from being NULL when the history cache doesn't have the message. Also adds diagnostic logging to handleSend for tracing transport decisions.
|
Codex review: needs real behavior proof before merge. Reviewed August 4, 2026, 6:25 PM ET / 22:25 UTC. ClawSweeper reviewWhat this changesThe branch forwards a thread-originator field through RPC send paths and the Messages bridge, while also adding bridge introspection and typing changes. Regression provenancePossible regression — suspected (reviewed change). No predecessor PR is attributed. Merge readiness⛔ Blocked until stronger real behavior proof is added - 12 items remain Keep open: the threading work is distinct, but the current head introduces reply compatibility failures and persistent sensitive metadata logging; its runtime proof is not for the reviewed head. Priority: P2 Review scores
Verification
How this fits togetherThe RPC server accepts send requests and passes them to an injected Messages bridge. That bridge constructs Messages framework objects for text and attachment delivery, including reply metadata. flowchart LR
A[RPC send request] --> B[RPC server]
B --> C[Bridge parameter mapping]
C --> D[Injected Messages bridge]
D --> E[Thread metadata resolution]
E --> F[Messages.app send]
F --> G[Remote chat database]
Before merge
Findings
Agent review detailsSecurityNeeds attention: The branch persists sensitive send-routing metadata to a predictable temporary log on every send. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Use thread_originator_guid when available, retain selected-message fallback for existing reply-only requests, remove persistent diagnostics, and prove text and attachment replies on the exact final head. Do we have a high-confidence way to reproduce the issue? No for the requested final runtime behavior: the supplied device output names an earlier head and omits reply_to-only and attachment cases. The introduced reply rejection and persistent logging are directly reproducible from current-head source. Is this the best way to solve the issue? No. The best fix must preserve the current reply_to-only contract while using originator metadata as an enhancement, rather than making that field mandatory. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 9392815f76f0. LabelsLabel justifications:
EvidenceSecurity concerns:
What I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (2 earlier review cycles)
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Thanks for the deep dive into bridge threading — the thread_originator_guid direction is genuinely interesting. After a full review at the exact head (43dbdfd), we're closing this iteration rather than landing it:
If you'd like to pursue this, a narrower follow-up built around the existing reply fallback — focused tests, bounded/no persistent logging, and an exact-head live proof on a real Messages setup — would get a fresh review. Appreciate the work that went into this. |
Threading EvidenceScreenshot of threaded iMessage conversation confirming Threaded replies were sent and received correctly, with each reply properly threaded under its parent message. This validates the bridge changes that forward |

Summary
Adds
thread_originator_guidsupport to the imsg RPC bridge so iMessage replies appear as threaded replies in Messages.app.Changes
Sources/imsg/RPCServer+Handlers.swift: Parsesthread_originator_guid/threadOriginatorGuidfrom RPC send params and passes tosendViaBridge. Fails closed (throws) instead of falling back to AppleScript when threading params are set. Removed all persistent debug logging (P1/security: previous version wrote recipient/chat/reply metadata to a predictable temp file without rotation).Sources/imsg/RPCServer+Support.swift:sendViaBridgepassesthreadOriginatorGuidto the bridge dylib params for bothsendMessageandsendAttachmentactions.Sources/imsg/RPCServer.swiftandSources/imsg/RPCServer+BridgeMessageHandlers.swift: PassthreadOriginatorGuidthrough bridge message handlers. Also addedthreadOriginatorGuidforwarding to the directhandleSendAttachmentroute (P2: previously only the generic send route forwarded it).Sources/IMsgCore/IMsgBridgeProtocol.swift: Added thread originator support to the bridge protocol.Sources/IMsgHelper/IMsgInjected.m:handleSendMessagereadsthreadOriginatorGuidfrom params and uses it asthreadLookupGuidforderiveThreadIdentifier.setThreadOriginator:on the wrappedIMMessagewhen the parent message is resolved.setThreadIdentifier:when the parent can't be loaded (macOS 26.5 compatibility).selectedMessageGuidis set (threaded replies) — not for all sends.handleSendMessage.Test Results
Build (exact head:
6d7f581)Runtime proof (redacted)
Bridge log from E2E test:
chat.db on remote sender:
Both fields match the inbound message GUID. Based on v0.13.4.
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com