# Reasonix 任务：ACP permission 决策闭环

Project root: `/mnt/Data1T/mnote`

你不是唯一在代码库中工作的 agent。不要回滚、覆盖或整理与你任务无关的改动；不要提交 git；不要修改 `.gitignore`、`.codegraph/`、`auth-console.txt`、`auth-network.txt`。

## 背景

Codex 已写 review：`design/10-review/process/13-hermes-vscode-plugin-gap-review-v1.md`

本任务对应 checklist：`design/07-ai/process/7-31-acp-permission-decision-loop-checklist-v1.md`

当前问题：`AcpClient` 对 incoming JSON-RPC `session/request_permission` 立即返回 unsupported/deny；Page AI UI 虽有按钮，但点击不能真正影响 ACP 请求。

## Ownership

允许直接修改：

- `rust/crates/mnote-web/src/acp_client.rs`
- `rust/crates/mnote-web/src/acp_session_manager.rs`
- `rust/crates/mnote-web/src/acp_bridge.rs`
- `rust/crates/mnote-web/src/routes/hermes_client.rs`
- `rust/crates/mnote-web/src/ssr/pages/layout.rs` 中 permission 决策接线相关的小范围代码
- 相关 Rust 测试
- `design/07-ai/process/7-31-acp-permission-decision-loop-checklist-v1.md` 的执行记录

注意：`layout.rs` 可能被其他 worker 改动。只做 permission endpoint 调用与事件处理，不重排 Page AI drawer。

## 目标

实现 `permission.requested -> UI allow/deny -> ACP JSON-RPC response -> permission.allowed/denied` 的闭环。超时、缺失 pending request、缺失 run 时默认 deny 或返回清晰错误。

## 具体要求

1. `AcpClient` 支持注册 incoming request handler，handler 可异步返回 result/error。
2. `session/request_permission` 不应立即 unsupported；应进入 pending request，向前端发 `permission.requested`。
3. 增加后端 endpoint 或扩展现有 endpoint，让前端按 run id / permission id 提交 allow/deny。
4. 前端 `pageAiResolvePermission()` 必须调用后端，而不只是本地改 UI 状态。
5. 决策完成后向 SSE/UI 发送 `permission.allowed` 或 `permission.denied`。
6. 补 mock ACP 测试覆盖 allow、deny、timeout/default deny。

## 验收命令

请至少运行：

```bash
cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web acp_client permission -- --test-threads=1
cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web acp_bridge permission -- --test-threads=1
cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web page_ai_uses_backend_acp_session_runtime_store -- --test-threads=1
```

## 最终回复格式

- 修改文件列表
- 关键实现说明
- 实际运行的验证命令和结果
- 未完成项 / 风险
