Repository navigation
fix(ios): show Mac handoff for Cloud requests the phone cannot answer (HQ-14) - #34088
teamleaderleo wants to merge 5 commits into
Conversation
teamleaderleo
left a comment
There was a problem hiding this comment.
Independent code review — mobile Cloud permission/question handoff (HQ #6236 brief 34 continuation)
Exact reviewed head: 8a76fb2b0f7dc3de2c9c0cf8474046f50d413268 (draft, five files). Verdict: source-level safety improvement, with one narrow P2 presentation follow-up and missing negative tests. No device/simulator capture or live Cloud permission was run.
What the changed path does correctly:
LiveCloudChats.swift:159–168constructs Cloud chat stores withcanAnswerPendingRequests: false. The publicAgentChatStore(source:)default remainstruefor local-Mac chats.AgentChatStore.swift:418–432, 472–504refuses Cloud permission responses, question answers/declines, and Reply Instead (which otherwise first sends a deny), leaving the pending ask and queue alone.AgentChatScreen.swift:679–710replaces Cloud's bottom permission actions with Mac handoff text, and suppresses the Reply Instead composer label.ChatRowView.swift:119–160removes the transcript's Allow/Deny link and replaces a pending Cloud question with static prompts and options.PermissionCardonly renders an action whenshowChoicesis present; passing nil genuinely removes the secondary entry point. The native-row renderer sends permission/question kinds through the SwiftUI hosted views.
P2 follow-up — incomplete read-only question choices: The new Cloud question branch prints item.options, but ignores item.allowsOther (ChatRowView.swift:151–159). The existing actionable QuestionCard explicitly adds an Other response when allowsOther is true. A pending Cloud question that permits custom text therefore looks like an options-only question on the phone, even though the Mac has an additional response. Show a static “Other — write your own answer on Mac” row for this condition; it remains read-only on phone.
Regression gaps: New cloudPermissionRequiresMacHandoff covers denial of a Cloud permission and Reply Instead, but does not exercise pendingQuestion answer/decline refusals, a custom-Other question, or prove local-Mac permission answers still reach their source. Add a fixture verifying (1) Cloud answer and decline emit zero AgentClientIntent requests and retain the ask; (2) local-Mac store still sends; (3) read-only Other is named on screen.
Broader design consideration: Keep the current fail-closed stopgap while the paired-Mac cloud-acpmux carrier lacks answer RPCs. Future phone approval should be enabled by negotiated per-carrier capabilities (permission and question separately), rather than a permanent device-level Bool. Do not enable those actions until owner identity, session routing, and reply refusal propagation are proved.
Execution evidence: cross-file source/UX-path review only. I did not build an iOS simulator, trigger a real permission, change permissions, or push into the owner lane. No P1 blocking source error found at this head.
HQ #6236 / brief 14 — Cloud requests should have an honest phone handoff
Starting ref:
manaflow-ai/cmux@6c3fe3648ba4b44e7bf38c4982a665ec2d5d5712(feat-cmux-next, 2026-11-03). Research and owner follow-up: HQ #6236, Cloud permission owner #30584, atomic VM mode owner #30588.Why
The Cloud
cloud-acpmuxadapter emits_acpmux/permission_pendingto the iPhone, yetcloud_acp.rssupports only read/prompt/cancel/detach; it refuses_acpmux/permission_respondand any question-answer call, deliberately avoiding transfer of Mac approval authority to a VM. The shared iPhone chat view nevertheless draws Face ID Allow, Deny, and Reply instead controls; questions have enabled Answer and Decline. A person away from their desk sees a usable-looking decision that the transport refuses.This isolated change
AgentChatStore.canAnswerPendingRequests(defaults true for existing/local Mac chats; false only when binding a Cloud chat); any programmatic answer/decline andReply insteadgo through that guard.cloudPermissionRequiresMacHandoffSwift Testing regression with the existing mock adapter: attempts to allow/deny/reply instead retain the pending request and never queue a replacement prompt.Scope: iPhone UI and shared chat-store presentation policy only. No VM-mode policy, auth, Rust hostd, entitlement, or server changes. This is a short-term disclosure; implementing an actual Cloud-scoped approval receipt belongs to #30584, with its atomic VM authorization dependency #30588. Avoid relabeling this as remote permission support.
Verification and explicit limits
CmuxMobileAgentChatTestson an authorized iOS simulator and visually verify the two Cloud pending cards; verify a local Mac chat still offers signed Allow/Deny and its question form.cloud-acpmuxreceives a pending permission/question, phone shows the exact content but no actionable answer; opening the same session on Mac permits policy-compliant decision and phone history updates on replay. Revoke/change account, background/resume and re-tap an old push; no previously authenticated request is actionable in another account.This PR intentionally stays draft for native validation and owner review.
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Fixes the iPhone chat UI showing dead-end decision controls for Cloud requests that the transport refuses to answer. Cloud chats now display a read-only "Open this Cloud chat on your Mac to answer" notice for pending permissions and questions, while local Mac chats keep their existing signed Allow/Deny and question-answer flow.
AgentChatStore.canAnswerPendingRequests(defaults true; false when binding a Cloud chat) and guards all programmatic answer/decline/reply-instead paths behind it.Written for commit 8a76fb2. Summary will update on new commits.