Persist PageTree expand state via control-plane view-state and align chevron/DOM with restored expansion; keep Sidex-style shallow page-tree scan and drop the unused recursive scanner that only added cargo noise. Add password vault workbench routes/runtime/skill/CLI, split page_ai_pi into a module package, and retire Hermes/ACP/OpenHub recycle + root harness evidence from the index while gitignoring recycle and local diag dumps. Archive superseded design/bugs docs under old/, point architecture at ARCHITECTURE.md, and refresh smokes for Pi S1–S7, vault, and editor regressions so the working tree can stay clean.
51 lines
3.1 KiB
Markdown
51 lines
3.1 KiB
Markdown
# [recycle] 3-22 [done][bug] ACP permission 自动拒绝后 UI 仍展示审批动作
|
||
|
||
> 发现时间:2026-05-18
|
||
>
|
||
> 状态:`[done]`
|
||
>
|
||
> 关联主线:`03-rust-web` / ACP runtime 与页面 AI 事件映射
|
||
|
||
## 1. 问题定义
|
||
|
||
当前 ACP client 收到 `session/request_permission` 后会立即返回 JSON-RPC error,并把事件转换为 `permission.denied`。这是为了避免 agent 等待权限响应直到超时。
|
||
|
||
但页面 AI UI 仍在权限卡片和权限弹窗里展示“允许 / 拒绝”按钮。即使这些按钮在 `permission.denied` 下会被禁用,用户仍会看到审批入口,误以为可以把真实协议结果改成允许。
|
||
|
||
## 2. 证据
|
||
|
||
- [acp_client.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/acp_client.rs:350) 对 incoming `id + method` request 直接返回 JSON-RPC error。
|
||
- [acp_session_manager.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/acp_session_manager.rs:121) 对 `session/request_permission` 生成 `decision="denied"`。
|
||
- [acp_bridge.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/acp_bridge.rs:237) 将 decision 映射为 `permission.denied`。
|
||
- [layout.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/ssr/pages/layout.rs:4060) 权限弹窗仍渲染“允许 / 拒绝”按钮。
|
||
- [layout.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/ssr/pages/layout.rs:5805) 权限消息卡片仍渲染“允许 / 拒绝”按钮。
|
||
|
||
## 3. 影响
|
||
|
||
- 用户看到的“允许”动作与 ACP wire contract 不一致。
|
||
- 点击动作只修改本地 UI 状态,不会回写 ACP JSON-RPC response。
|
||
- 对已经自动拒绝的权限请求展示审批按钮,会掩盖真实失败原因。
|
||
|
||
## 4. 修复
|
||
|
||
- [acp_client.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/acp_client.rs:350) 维持 `session/request_permission` 自动拒绝协议响应,避免 agent 等待超时。
|
||
- [layout.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/ssr/pages/layout.rs:4003) `pageAiApplyPermissionEvent()` 对 `permission.denied` / `permission.allowed` 只保留结果态,不再展示可点击审批弹窗。
|
||
- [layout.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/ssr/pages/layout.rs:4048) `pageAiShowPermissionDialog()` 对已决权限事件直接隐藏对话框。
|
||
- [layout.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/ssr/pages/layout.rs:5797) 权限消息卡片对已决事件只展示结果,不再渲染审批按钮。
|
||
|
||
## 5. 验证
|
||
|
||
```bash
|
||
cargo test --manifest-path rust/Cargo.toml -p mnote-web page_ai_uses_backend_acp_session_runtime_store -- --nocapture
|
||
cargo test --manifest-path rust/Cargo.toml -p mnote-web acp_permission_request_emits_frontend_decision_event -- --nocapture
|
||
cargo test --manifest-path rust/Cargo.toml -p mnote-web ssr::pages::layout::tests -- --nocapture
|
||
cargo fmt --manifest-path rust/Cargo.toml --all -- --check
|
||
git diff --check -- rust/crates/mnote-web/src/ssr/pages/layout.rs bugs/03-rust-web/done/3-22-acp-permission-auto-deny-ui-shows-approval-actions-v1.md
|
||
```
|
||
|
||
结果:
|
||
|
||
- `page_ai_uses_backend_acp_session_runtime_store`:`1 passed`。
|
||
- `acp_permission_request_emits_frontend_decision_event`:`1 passed`。
|
||
- 版面相关静态测试继续通过,权限消息代码路径未破坏。
|