chore: land tree view-state, vault, Pi module split, and repo hygiene
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.
This commit is contained in:
@@ -1,49 +0,0 @@
|
||||
# 3-19 [done][bug] Reasonix ACP wrapper 调 mnote tool 缺少身份与幂等字段 v1
|
||||
|
||||
> 发现时间:2026-05-17
|
||||
>
|
||||
> 状态:`[done]`
|
||||
>
|
||||
> 关联主线:`03-rust-web`
|
||||
|
||||
## 1. 问题定义
|
||||
|
||||
Reasonix ACP wrapper 调用 mnote tool 时只发送 `toolName`、`args`、`workspaceId`,没有传递 `actorId`、`sessionId`、`runId`、`toolCallId`、`traceId`、`dryRun`、`idempotencyKey` 等工具合同字段。
|
||||
|
||||
## 2. 证据
|
||||
|
||||
- [reasonix-acp-wrapper.mjs](/mnt/Data1T/mnote/scripts/reasonix-acp-wrapper.mjs:230) 附近构造 `callMnoteTool` 请求体。
|
||||
|
||||
## 3. 影响
|
||||
|
||||
- Rust tool executor 难以稳定进行鉴权、审计、追踪和幂等。
|
||||
- 写工具可能被拒绝,或在缺少幂等键时产生重复写入风险。
|
||||
- Reasonix 与 Hermes 对同一 tool 的调用合同不一致。
|
||||
|
||||
## 4. 建议修复
|
||||
|
||||
- wrapper 必须从 ACP run/session 中透传 actor、session、run、toolCall、trace、dryRun、idempotency 字段。
|
||||
- 写工具缺失必要字段时应 fail fast。
|
||||
- 增加 Reasonix 端到端 smoke,断言请求字段完整。
|
||||
|
||||
## 5. 修复
|
||||
|
||||
已修复:
|
||||
|
||||
- [reasonix-acp-wrapper.mjs](/mnt/Data1T/mnote/scripts/reasonix-acp-wrapper.mjs:34) 新增 `buildMnoteToolPayload`,统一构造 mnote tool 请求体。
|
||||
- [reasonix-acp-wrapper.mjs](/mnt/Data1T/mnote/scripts/reasonix-acp-wrapper.mjs:43) tool payload 现在包含 `actorId`、`sessionId`、`runId`、`toolCallId`、`traceId`、`dryRun`、`idempotencyKey`、`workspaceId`、`documentId`。
|
||||
- [reasonix-acp-wrapper.mjs](/mnt/Data1T/mnote/scripts/reasonix-acp-wrapper.mjs:303) HTTP 请求头同步携带 `x-mnote-actor-id` 与 `x-mnote-workspace-id`。
|
||||
- [reasonix-acp-wrapper.mjs](/mnt/Data1T/mnote/scripts/reasonix-acp-wrapper.mjs:379) ACP `session/prompt` 期间通过 `AsyncLocalStorage` 保存 mnote tool context,tool 调用继承 run/session/actor/trace。
|
||||
- [acp_types.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/acp_types.rs:163) `SessionPromptParams` 扩展可选 mnote 上下文字段。
|
||||
- [acp_session_manager.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/acp_session_manager.rs:193) 增加 `run_prompt_with_mnote_context`。
|
||||
- [hermes_client.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/hermes_client.rs:754) ACP Reasonix prompt 启动时透传 mnote session/run/actor/trace/workspace/document 上下文。
|
||||
|
||||
## 6. 验证
|
||||
|
||||
```bash
|
||||
node --check scripts/reasonix-acp-wrapper.mjs
|
||||
MNOTE_REASONIX_ACP_SELFTEST=1 node scripts/reasonix-acp-wrapper.mjs
|
||||
cargo test --manifest-path rust/Cargo.toml -p mnote-web acp_session_manager -- --nocapture
|
||||
```
|
||||
|
||||
结果:JS 语法检查通过,wrapper selftest 通过,ACP session manager 5 个测试通过。
|
||||
@@ -1,40 +0,0 @@
|
||||
# 3-20 [done][bug] ACP incoming request 只记录日志不响应 v1
|
||||
|
||||
> 发现时间:2026-05-17
|
||||
>
|
||||
> 状态:`[done]`
|
||||
>
|
||||
> 关联主线:`03-rust-web`
|
||||
|
||||
## 1. 问题定义
|
||||
|
||||
ACP client 收到 `session/request_permission` 等 incoming request 时当前只记录日志,没有返回协议响应。
|
||||
|
||||
## 2. 证据
|
||||
|
||||
- [acp_client.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/acp_client.rs:347) 附近处理 incoming request。
|
||||
|
||||
## 3. 影响
|
||||
|
||||
- ACP agent 侧可能等待到超时。
|
||||
- 权限请求无法进入用户确认或自动拒绝流程。
|
||||
- run 状态可能卡在进行中,SSE 输出也无法表达真实阻塞原因。
|
||||
|
||||
## 4. 建议修复
|
||||
|
||||
- 为已知 request type 实现明确响应:允许、拒绝或要求人工确认。
|
||||
- 未支持的 request type 也应返回结构化 error,而不是只日志。
|
||||
- 增加 ACP request/response 协议测试。
|
||||
|
||||
## 5. 修复
|
||||
|
||||
- [acp_client.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/acp_client.rs:157) 将 ACP 子进程 stdin writer 作为共享 `Arc<Mutex<BufWriter<_>>>` 传入后台 reader loop。
|
||||
- [acp_client.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/acp_client.rs:335) 对带 `id + method` 的 incoming request 写回 JSON-RPC error 响应,当前无权限确认 UI 时明确拒绝,避免 agent 等待超时。
|
||||
- [acp_client.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/acp_client.rs:551) 增加 mock ACP server 测试,覆盖 `session/request_permission` 主动请求必须收到响应。
|
||||
|
||||
## 6. 验证
|
||||
|
||||
- `cargo test --manifest-path rust/Cargo.toml -p mnote-web test_incoming_permission_request_gets_response -- --nocapture`
|
||||
- 结果:1 passed
|
||||
- `cargo test --manifest-path rust/Cargo.toml -p mnote-web acp_client -- --nocapture`
|
||||
- 结果:6 passed
|
||||
@@ -1,38 +0,0 @@
|
||||
# 3-21 [done][bug] ACP run payload 被第一次 stream_events 消费后移除 v1
|
||||
|
||||
> 发现时间:2026-05-17
|
||||
>
|
||||
> 状态:`[done]`
|
||||
>
|
||||
> 关联主线:`03-rust-web`
|
||||
|
||||
## 1. 问题定义
|
||||
|
||||
ACP run 的 payload 在 `stream_events` 路径被消费后从内存表移除。刷新页面、多个 SSE 订阅、断线重连时,后续订阅可能无法再取到同一个 run 的 payload。
|
||||
|
||||
## 2. 证据
|
||||
|
||||
- [hermes_client.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/hermes_client.rs:789) 进入 `stream_events`。
|
||||
- ACP 分支中存在 `ACP_RUN_PAYLOADS.remove` 语义,payload 生命周期与第一次 stream 订阅绑定。
|
||||
|
||||
## 3. 影响
|
||||
|
||||
- 浏览器刷新或 SSE 重连可能导致同一 run 无法恢复。
|
||||
- 多个客户端观察同一 run 时只有第一个订阅者成功。
|
||||
- abort / retry / reconnect 语义不可靠。
|
||||
|
||||
## 4. 建议修复
|
||||
|
||||
- payload 应有 run 级持久生命周期,至少保留到 run completed / failed / aborted 后短 TTL。
|
||||
- stream subscription 不应拥有 payload 的删除权。
|
||||
- 增加 SSE 断线重连与重复订阅测试。
|
||||
|
||||
## 5. 修复
|
||||
|
||||
- [hermes_client.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/hermes_client.rs:2051) `acp_run_payload_for_stream` 使用 `ACP_RUN_PAYLOADS.get(run_id).cloned()`,stream subscription 只读取 payload,不再拥有删除权。
|
||||
- [hermes_client.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/hermes_client.rs:4116) 增加重复读取测试,锁定刷新、重连、多个观察者不会因为第一次读取而丢失 run payload。
|
||||
|
||||
## 6. 验证
|
||||
|
||||
- `cargo test --manifest-path rust/Cargo.toml -p mnote-web hermes_client_acp_stream_payload_lookup_keeps_payload_for_reconnect -- --nocapture`
|
||||
- 结果:1 passed
|
||||
@@ -1,50 +0,0 @@
|
||||
# 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`。
|
||||
- 版面相关静态测试继续通过,权限消息代码路径未破坏。
|
||||
Reference in New Issue
Block a user