aaif-goose / aaif-goose/goose

claude-acp fails to initialize under a managed policy that disables bypassPermissions

未关闭
#11,640 0 条评论 0 个 reaction 已指派 1 人 已被 @jbg 认领 在 GitHub 查看
主要语言
Rust
星标
54.2k
派生
6.2k
平均合并
3 天 4 小时
30 天内合并 PR
240

描述

**Describe the bug**

When Goose drives the Claude Code ACP harness (`claude-acp`, via `@agentclientprotocol/claude-agent-acp`) in an environment where a Claude Code **managed policy** disables bypass mode (`managed-settings.json` → `"permissions": { "disableBypassPermissionsMode": "disable" }`), the provider fails to initialize:

```
Failed to initialize provider: ACP agent rejected session/set_mode:
Internal error: { "details": "Cannot set permission mode to bypassPermissions
because it is disabled by settings or configuration" }
```

Root cause: Goose's default session mode is `Auto`, which `claude_acp.rs` maps solely to `bypassPermissions`. `apply_session_mode` selects the first *advertised* candidate and issues one `session/set_mode`, treating any rejection as fatal. `claude-agent-acp` advertises `bypassPermissions` regardless of whether the managed policy will actually grant it (its gate is only `!IS_ROOT`), so Goose requests it, the SDK rejects it, and session init aborts — even though permitted modes (`acceptEdits`, `default`) are available and advertised.

Codex and interactive `claude` are unaffected: interactive Claude Code never requests bypass (the human approves), and Codex has no equivalent managed-policy gate.

---

**To Reproduce**
1. On a machine with a Claude Code managed policy that disables bypass — `/Library/Application Support/ClaudeCode/managed-settings.json` (macOS) containing `"permissions": { "disableBypassPermissionsMode": "disable" }`.
2. Configure Goose with the `claude-acp` provider and leave the session mode at the default `Auto`.
3. Start a session (e.g. via `goose serve` driving `claude-acp`, or any ACP client).
4. Session initialization fails with the `session/set_mode` rejection above; no non-bypass mode is attempted.

---

**Expected behavior**

Goose should degrade to a permitted, less-permissive mode (`acceptEdits`, then `default`) rather than aborting, initializing the session successfully under the managed policy. It should fail only if the agent refuses *all* candidate modes.

---

**Please provide the following information**
- **OS & Arch:** macOS (Apple Silicon); policy path is OS-specific but the logic is platform-independent
- **Interface:** ACP harness (`claude-acp`) via `goose serve`
- **Version:** goose 1.46.0; `@agentclientprotocol/claude-agent-acp` 0.66.0; Claude Code 2.1.x
- **Extensions enabled:** n/a (reproduces with defaults)
- **Provider & Model:** Claude Code (claude-agent-acp), any model

---

**Additional context**

*Proposed fix* (already prototyped): in `apply_session_mode`, try each advertised candidate in preference order and degrade on rejection, failing only if all are refused; give the `claude_acp.rs` `Auto`/`SmartApprove` mappings ordered fallbacks (`Auto: bypassPermissions → acceptEdits → default`; `SmartApprove: acceptEdits → default`). `Chat` keeps no fallback so the chat-only contract can't silently degrade into an executing mode.

Prototype branch (single commit, **not** opened as a PR pending this issue reaching Ready, per CONTRIBUTING): https://github.com/datgrass/goose/tree/acp-permission-mode-fallback

*Verification plan:*
- **Unit:** new tests for the candidate-selection helper (order preserved; unavailable modes filtered; empty when none offered).
- **Protocol-level:** drive `claude-agent-acp` directly under the live managed policy — confirm `set_mode(bypassPermissions)` is rejected while `set_mode(acceptEdits)` / `set_mode(default)` are accepted, and that init now lands on the first permitted mode.
- **Regression:** with no managed policy, `Auto` still resolves to `bypassPermissions` (first candidate) unchanged.

贡献指南

打开贡献指南

调研方向

问题位于 `claude_acp.rs` 中的会话模式初始化逻辑。首先阅读 `apply_session_mode` 函数以及 `Auto` 模式的映射。prototype branch 展示了修复思路:修改候选项选择逻辑,以尝试回退模式(`bypassPermissions → acceptEdits → default`),并妥善处理拒绝。通过运行现有测试并为候选项选择 helper 添加新的单元测试进行验证。使用禁用 bypass 的 managed policy 进行测试,以确认会话能够成功初始化。

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

评估

技术栈
rust
领域
ai-infra-agents, backend-api-design
Issue 类型
缺陷
难度
3/5
预计耗时
1-2 天
活跃度
活跃
描述清晰度
描述清楚
新手友好度
65/100

把新 issue 发到你的邮箱

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