anthropics / anthropics/claude-code

Cross-session messages held for approval are indistinguishable from delivered ones at both sender and recipient

未关闭
#91,372 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
area:permissions enhancement platform:macos user-experience
主要语言
Python
星标
145k
派生
23.1k
PR 合并指标
PR 指标待抓取

描述

### Summary

When `crossSessionInbound` is unset and the recipient session runs with bypassed permissions, inbound peer messages are **held for approval** and dropped at `dialogExpiry`. That behaviour is documented and correct.

The problem is that **a held message is indistinguishable from a delivered one at the sender, and an approval dialog is indistinguishable from a delivered card at the recipient.** Nothing either side can observe separates "waiting for approval" from "delivered".

This is a discoverability report, not a claim that delivery is broken.

### What we observed

Four concurrent local sessions on one machine, messaging each other. For two days:

- The **sender** received `success: true` naming the correctly-resolved recipient.
- The **recipient's** client rendered something that looked like an ordinary message card.
- Nothing was written to the recipient's transcript, and nothing entered its context.
- Roughly 173 consecutive sends were affected.

Every hypothesis we formed was about the transport, because the transport is what the observable surface described. We disproved twelve of them — stale addresses, socket rotation, session identity, registry staleness, fork artefacts, warm-up races — before finding that `crossSessionInbound` was simply not set.

Setting `"crossSessionInbound": "accept"` fixed it immediately: both push transports delivered within 15 seconds after two days of failure.

### Why it took two days

The answer was in front of us the entire time, in two places:

1. **On every send receipt**, which included the words *"it may be waiting for approval there"*.
2. **In the changelog**, which stated that messages to a session with bypassed permissions are held for approval.

Neither is wrong. Both were read past, repeatedly, by four sessions, because:

- `success: true` is the dominant signal and reads as delivery. The approval caveat is a subordinate clause in the same string.
- The held state has **no distinct surface**. There is no "1 message awaiting approval" indicator, no distinguishing marker on the card, nothing in the transcript, and no error at expiry.
- The failure is **silent and delayed**. The message does not bounce; it expires quietly at `dialogExpiry` (default 5 minutes), long after the sender has moved on.
- The default depends on **permission mode**, which is a property of the *recipient*, so the sender has no local reason to suspect it.

The result is a failure mode where the sender believes the message landed, the recipient believes nothing was sent, and no artefact anywhere records the disagreement.

### Suggested changes

Any one of these would likely have saved the two days:

1. **Make the held state visible to the recipient** — an indicator that N inbound messages are awaiting approval, rather than only a dialog that can be missed or dismissed.
2. **Make expiry observable.** When a held message expires, surface it somewhere: recipient-side notice, sender-side notification, or a transcript record. Currently expiry produces no artefact at all.
3. **Differentiate the sender receipt.** If the recipient's configuration means the message will be held, say so distinctly rather than returning the same `success` shape as a delivered message. The sender's side already knows enough to distinguish the cases.
4. **Consider whether the permission-mode-derived default is the right one**, or at least warn once per session when a message is held because `crossSessionInbound` is unset.

### Environment

- macOS, four concurrent local sessions, Claude Code CLI
- `crossSessionInbound` unset (no user settings entry), recipients running with bypassed permissions
- Affected both `SendMessage` (peer socket) and the session-channel transport
- A filesystem-based fallback we used as a control was unaffected — correctly, since it has no delivery step to hold

### Note on scope

We initially diagnosed this as a delivery/commit defect and were wrong. The setting behaves exactly as documented. We are filing only the discoverability finding, and the cost of that finding is the evidence for it: four sessions, two days, twelve disproved hypotheses, with the correct answer printed on every receipt throughout.

贡献指南

这个仓库没有索引到贡献指南

调研方向

Start with the SendMessage and session-channel transport entry points, then inspect handling of crossSessionInbound, bypassed permissions, and dialogExpiry. Compare sender receipts, recipient approval UI, transcript behavior, and expiry handling; done means the held state and expiry are visibly distinct from delivery on the affected surfaces.

由索引模型根据 Issue 内容生成。

评估

领域
backend, cli
Issue 类型
功能
难度
5/5
预计耗时
一周以上
活跃度
活跃
描述清晰度
基本清楚
新手友好度
35/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。