Skip to content

fix: 权限清扫改为丢弃连接而非 deny,修复并行子代理场景的误拒 - #13

Merged
myunwang merged 1 commit into
myunwang:mainfrom
andglf:fix/perm-sweep-drop-not-deny
Jul 27, 2026
Merged

myunwang merged 1 commit into
myunwang:mainfrom
andglf:fix/perm-sweep-drop-not-deny

Conversation

@andglf

@andglf andglf commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

问题

会话中存在并行/后台子代理(async Agent)时,正在等待用户点击的权限气泡会在弹出后 1~数秒内被自动拒绝,CC 端显示 Error: User answered in terminal / Denied by PermissionRequest hook,Claude 被迫反复重试同一工具。

原因

sweepForSessionEvent 把 PostToolUse / PostToolUseFailure / Stop / UserPromptSubmit / SessionEnd 一律当作"用户已在终端作答",将该会话所有待处理权限请求裁决为 deny。但后台/并行子代理与主会话共用同一 session_id:子代理每完成一个工具就发 PostToolUse,主会话的工具完成也会扫到子代理正在等待的气泡——任何并发工具完成都会误杀仍在等点击的请求。单线程会话中该 bug 潜伏,并行代理场景下近乎必然触发。实测一个含两个后台代理的会话:229 次权限裁决中 86 次(37%)为此类误拒,时间戳与并发工具完成逐条对齐。

修复

清扫裁决由 deny 改为 no-decision:只丢弃挂起的连接(CC 回退到终端自己的权限提示,与免打扰路径行为一致),保留"清掉过期气泡"的本意,且从不替用户做拒绝决定。用户若真在终端作答,CC 早已关闭该连接,丢弃为无副作用的空操作。test/smoke.js [7] 同步改为断言"连接被丢弃、无裁决、无 pending 残留"。

npm test 全量通过。

sweepForSessionEvent 原先在收到 PostToolUse/PostToolUseFailure/Stop/
UserPromptSubmit/SessionEnd 时,把该会话所有待处理权限请求一律裁决为
deny("User answered in terminal")。但这些事件在同一 session_id 的
并发活动里同样会触发——后台/并行子代理每完成一个工具就发 PostToolUse,
主会话的工具完成也会扫到子代理正在等待的气泡——导致真正还在等用户点击
的请求被误拒:CC 端显示 "Error: User answered in terminal / Denied by
PermissionRequest hook",Claude 被迫反复重试同一工具。

改为 no-decision:清扫只丢弃挂起的连接(CC 回退到终端自己的权限提示),
保留「清掉过期气泡」的本意,且从不替用户做拒绝决定。用户若真在终端作答,
CC 早已关闭该连接,丢弃为无副作用的空操作。

test/smoke.js 的 [7] 用例同步改为断言「连接被丢弃、无裁决」;结算收集器
在创建时即挂载,避免清扫断连先于 /state 应答到达而触发 unhandledRejection。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@myunwang myunwang left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感谢这次非常扎实的定位,尤其是 229 次权限裁决及 86 次误拒的实测数据,把并行子代理共享 session_id 导致误杀的问题说明得很清楚。

我重新审阅了完整权限生命周期,并在独立 worktree 中跑过全量 npm test;另外补做了同一 session 同时存在两个不同 pending 权限请求的实验,确认清扫后两条连接都以 no-decision 结束,没有返回或暗中产生 deny。

这份改动正确消除了当前最严重的问题:生命周期事件不能再替用户作出拒绝决定。并行事件仍可能让桌宠授权卡回退到终端,这属于后续体验优化,不阻塞本次止血修复;我会另开 issue 跟踪权限卡保留和正式的双 pending 回归测试。

Approved,感谢贡献!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants