@@ -0,0 +1,255 @@
# 7-74 Page AI Pi RPC Parity 与产品化补全 Checklist v1
状态:done
Owner: 07-ai / mnote-web / browser runtime / control-plane
日期:2026-07-10
## 1. 结论
当前 MNote Pi Lab 的架构边界保持不变:MNote Rust Web 托管 `pi_agent_rust` RPC 子进程,MNote 负责 `AiAccessScope` 、allowed roots、bridge tools、receipt、MCP、LightRAG 和 control-plane 审计;不迁移到 `pi-web` 的 Next.js / in-process AgentSession 架构。
`pi-web` 与官方 `pi_agent_rust` 的参考价值主要在产品化和 RPC 命令面:
- 补齐官方 RPC 命令:`get_state` 、`get_messages` 、`compact` 、`fork` 、`set_steering_mode` 、`set_follow_up_mode` 、`set_auto_compaction` 。
- 用官方 session tree / JSONL entry 模型支撑历史 replay、entry 级 fork、compaction 摘要展示。
- 完善 composer: draft 持久化、`@` 文件补全、运行中 steer/follow-up 队列状态。
- 完善 artifacts: file patch split diff、citation/open-reference、MCP raw、receipt audit 统一入口。
本稿是 `7-69 Page AI Pi-first Lab` 与 `7-72 Page AI Pi UI 补全方案` 之后的执行稿,目标是把 Pi Lab 从“可用实验面板”推进到“能长期作为 MNote-native Page AI runtime 候选”的最小闭环。
## 2. 对照证据
### 2.1 pi-web
本轮只读拉取:
- 仓库:`https://github.com/agegr/pi-web`
- 本地路径:`/tmp/pi-web-analysis`
- commit: `82f9442`
可参考文件:
- `/tmp/pi-web-analysis/lib/session-reader.ts` :读取 Pi JSONL,构建 UI messages、entryIds、compaction、branch summary。
- `/tmp/pi-web-analysis/components/BranchNavigator.tsx` :会话分支树、active path、压缩线性链。
- `/tmp/pi-web-analysis/components/ChatInput.tsx` : draft、slash commands、`@` 文件补全、运行中 steer/follow-up。
- `/tmp/pi-web-analysis/lib/patch.ts` : unified patch 解析为 split diff rows。
- `/tmp/pi-web-analysis/components/FileViewer.tsx` :文件预览、diff、图片/音频/PDF/DOCX 入口。
- `/tmp/pi-web-analysis/lib/worktree.ts` : Git worktree 分组与切换,暂只作为未来 MNote workspace 参考。
不迁移:
- Next API routes 与 `globalThis` hot reload cache。
- `~/.pi/agent/sessions` 作为 MNote 默认事实源。
- in-process `@earendil-works/pi-coding-agent` 生命周期。
- Pi 原生 `bash/read/write/edit` 默认开放策略。
### 2.2 pi_agent_rust
本轮只读核对:
- 仓库:`https://github.com/Dicklesworthstone/pi_agent_rust`
- 本地路径:`/tmp/pi-agent-rust-official-20260710`
- commit: `43fddc06`
- 时间:2026-07-09
关键证据:
- `/tmp/pi-agent-rust-official-20260710/src/rpc.rs`
- `prompt` 支持 `streamingBehavior=steer/followUp/follow_up` 。
- `get_state` 返回 model、thinking、context usage、pending queue、auto compaction/retry。
- `compact` 会生成 compaction entry 并替换 agent context。
- `fork` 能从 `entryId` 生成新 session。
- `set_steering_mode` / `set_follow_up_mode` / `set_auto_compaction` 是官方 RPC 命令;queue mode 只接受 `one-at-a-time` / `all` 。
- `/tmp/pi-agent-rust-official-20260710/docs/rpc.md`
- 明确 `extension_ui_request` / `extension_ui_response` 、`agent_end` 、`tool_execution_*` 、`auto_compaction_*` 等事件。
- `/tmp/pi-agent-rust-official-20260710/docs/session.md`
- Session JSONL entry 类型包括 `message` 、`model_change` 、`thinking_level_change` 、`compaction` 、`branch_summary` 、`custom` 。
## 3. 当前 MNote 状态
当前已存在能力:
- `rust/crates/mnote-web/src/routes/page_ai_pi.rs`
- `status/start/send/configure/abort/events/tool-call/tool-call-bridge/ui-response/sessions/session-events` 。
- session owner 校验、bridge token、allowed roots、tool receipt、MCP sync bridge、permission mode。
- `send` 已透传 `streamingBehavior` 。
- `configure` 已在当前工作区脏改动中接入 `set_model` / `set_thinking_level` 。
- `rust/crates/mnote-web/browser/sidebar-page-ai-pi-lab-runtime.js`
- `PiRunViewModel` 、tool timeline、history drawer、queue badge、Artifacts/Receipts、extension UI、model/thinking controls。
- 已有 `pendingQueue` reducer 入口,但需要后端 `get_state` /官方 queue state 兜底同步。
- `packages/pi-mnote/extensions/mnote-bridge.ts`
- 当前脏改动已把 `mnote.local_file.read/patch` 尽量转为 Pi Rust native fs + context file 路径。
- `scripts/task-pi-lab-*`
- 已有 static/API/UI/real skill MCP/input controls 等 smoke 基线。
主要缺口:
- 缺少 MNote API 层对官方 `get_state` 、`compact` 、`fork(entryId)` 、queue mode、auto compaction 的稳定封装。
- 历史 replay 主要依赖 MNote runtime events,还没有完整读取 Pi JSONL entry tree。
- Composer 没有本地 draft 持久化和 `@` 文件补全。
- Artifact diff 仍偏摘要,缺少 split diff 预览与 open-file 定位。
## 4. 架构边界
### 4.1 MNote 继续拥有权限
Pi 运行时只能通过 MNote 托管的安全面访问 MNote 数据:
- `mnote.current_page.read`
- `mnote.selection.read`
- `mnote.allowed_roots.describe`
- `mnote.local_file.read`
- `mnote.local_file.patch`
- `mnote.knowledge_rag.*`
- `mnote.reference.open`
- `mnote.tool_receipt.write`
原生 Pi `read/write/edit/bash/hashline_edit` 只有在 MNote 明确启用 permission-system 或 debug/admin 模式时才允许。普通用户路径不得绕过 `directory_grants` 与 `AiAccessScope` 。
### 4.2 Pi session 是 runtime log,不是正文真相
Pi JSONL 可以作为:
- history replay source
- fork/branch source
- debugging/export source
- runtime recovery source
但不能成为:
- MNote 页面正文真相
- local-folder source truth
- allowed roots 真相
- tool audit 主存储
MNote control-plane 的 `ai_runtime_runs` 、`ai_runtime_events` 、`ai_tool_events` 、`ai_file_patches` 仍是 MNote 侧可查询审计和历史入口。
### 4.3 不新增轮询
前端主路径不新增 `setInterval` 或周期轮询。状态同步优先:
- Pi RPC event -> MNote SSE
- 显式 command response
- `get_state` 只在打开面板、发送前后、SSE reconnect、abort/compact/configure 后定点调用
- 页面/文件变化走 MNote watcher / realtime
## 5. 分阶段 Checklist
### Phase A: RPC parity 最小闭环
- [x] A1. 新增 `/api/page-ai/pi/state` ,封装官方 `get_state` 。
- 输入:`sessionId`
- 输出:`running/isStreaming/isCompacting/model/thinkingLevel/contextUsage/pendingMessageCount/queuedMessages/autoCompactionEnabled/autoRetryEnabled`
- 约束:mock runtime 返回稳定假数据;未启动返回明确错误。
- 当前真实 runtime 只发送 `get_state` one-way RPC,并返回 MNote session 推导状态;真实 Pi response correlation 进入 A7。
- [x] A2. 前端在 drawer open、start、send ack、abort、SSE reconnect 后定点刷新 state。
- 不使用周期轮询。
- 将 `queuedMessages` 同步到 `PiRunViewModel.pendingQueue` 。
- [x] A3. 新增 `/api/page-ai/pi/compact` ,封装官方 `compact` 。
- 支持 `customInstructions/reserveTokens/keepRecentTokens` 。
- 返回 compaction summary、firstKeptEntryId、tokensBefore、details。
- 持久化 `runtime_compacted` event。
- [x] A4. 前端增加 compact 按钮与 compaction result 卡片。
- streaming 中禁用。
- 失败时显示明确 error,不写入正文。
- [x] A5. 新增 queue mode / auto compaction 配置薄 API。
- `/api/page-ai/pi/queue-config`
- 封装 `set_steering_mode` 、`set_follow_up_mode` 、`set_auto_compaction` 。
- mode 值域按官方合同限制为 `one-at-a-time` / `all` ,兼容 `oneAtATime` / `one_at_a_time` 输入。
- 第一版 UI 可仅放在折叠设置区。
- [x] A6. smoke 覆盖 state/compact/queue-config 路由存在、禁用态稳定、runtime asset 无轮询。
- [x] A7. 增加 Pi RPC request-response correlation。
- 为 `get_state` 、`compact` 、`queue-config` 追踪 RPC `id` 与 stdout response。
- 将真实 `contextUsage/queuedMessages/autoCompactionEnabled/autoRetryEnabled/compaction result` 映射到 MNote schema。
- timeout 时返回 `rpcResponsePending=true` 或明确 degraded reason,不伪装成完整真实状态。
### Phase B: Session tree / history replay
- [x] B1. 记录并返回 `pi_session_file` 。
- start 后从 Pi RPC response、session dir 扫描或 runtime event 中确定。
- 写入 `ai_runtime_runs` 。
- [x] B2. 新增受控读取 Pi JSONL 的内部 helper。
- 限制只能读取当前 session 自己的 `pi_session_file` 。
- 单行大小、总字节数、entry 数量有上限。
- 不读任意路径。
- [x] B3. 新增 `/api/page-ai/pi/sessions/{id}/tree` 。
- 输出 entry tree、active leaf、compaction/branch summary、message preview。
- [x] B4. 前端 history replay 优先使用 session tree。
- 保留 control-plane events 作为 fallback。
- 显示 compaction summary 和 branch summary。
- [x] B5. 新增 `/api/page-ai/pi/fork` 。
- 输入:`sessionId` 、可选 `entryId` 。
- 优先调用官方 `fork` 。
- 输出新 session/run 绑定。
- [x] B6. history UI 支持 entry 级 “从这里继续”。
### Phase C: Composer 可用性
- [x] C1. 输入草稿持久化。
- key: `pi-lab:${workspaceId}:${rootUri}:${pagePath}:${sessionId || new}` 。
- 保存 textarea、context selection、model/thinking 临时选择。
- 发送成功后清理当前 draft。
- [x] C2. `@` 文件补全。
- 数据源:MNote allowed roots / FileTree projection。
- 不扫描未授权目录。
- 插入格式优先 `@relative/path` ,发送时进入 `contextRefs` 。
- [x] C3. composer 中显示已引用文件 chips。
- 可删除。
- 发送时与 `selectedContext` 一起写入 Pi context file。
- [x] C4. streaming 中 steer/follow-up 的队列状态与 state API 对齐。
- abort 后保留未发送文本与 queue summary。
### Phase D: Artifacts / Diff / Citation
- [x] D1. file patch receipt 生成统一 artifact。
- `rootUri/relativePath/beforeFileVersion/afterFileVersion/diffSummary/toolEventId`
- [x] D2. 后端提供受控 diff 预览。
- 优先从 `ai_file_patches.patch_summary_json` 或 receipt payload 取。
- 不允许直接读未授权路径。
- [x] D3. 前端 split diff viewer。
- 借鉴 `pi-web/lib/patch.ts` ,但落成 MNote 原生 JS helper。
- 支持折叠 unchanged lines。
- [x] D4. citation/open-reference artifact 与 LightRAG `open_reference` 对齐。
- 引用打开失败时显示 stale/deleted/permission denied。
### Phase E:验证与归档
- [x] E1. 静态 smoke: `node scripts/task-pi-lab-static-smoke.js`
- [x] E2. API smoke: `node scripts/task-pi-lab-api-endpoint-smoke.js`
- [x] E3. UI smoke:复用或扩展 `scripts/task-pi-lab-ui-completion-smoke.js`
- [x] E4. Rust 单元:`cargo test -p mnote-web page_ai_pi --lib`
- [x] E5. 若触及 control-plane schema/helper,补对应 control-plane 测试。
- 本轮未改 control-plane schema/helper;相关验证由 API / browser smoke 覆盖。
- [x] E6. 浏览器验证:
- desktop viewport: `node scripts/task-pi-lab-browser-smoke.js`
- mobile viewport:沿既有 7-72 Phase 1 mobile smoke 证据保留;本轮没有新增移动专属布局改动。
- real Pi runtime: `node scripts/task-pi-lab-browser-smoke.js`
- disabled/missing runtime: `node scripts/task-pi-lab-api-endpoint-smoke.js` 覆盖 disabled may 401/404 稳定返回。
- 补充:`dev:hot` 已默认启用 `MNOTE_WEB_ALLOW_DEV_FIXTURES=1` ;重启 Node 主进程后,`node scripts/task-pi-lab-input-controls-smoke.js` 完整通过,证据:`/tmp/mnote-pi-input-controls-1783715878475/result.json` 。
- [x] E7. 完成后运行 `codegraph sync . && codegraph status .` 。
- [x] E8. 全部完成后把本稿移动到 `design/07-ai/done/` ,并在 `7-72` 中补一行后续完成链接。
## 6. 第一批执行范围
第一批已完成 Phase A-D 的产品化闭环:
1. 后端新增 `state` 、`compact` 、`queue-config` API,并补齐 RPC request-response correlation。
2. 后端新增 session tree、fork、artifact diff 受控 API。
3. 前端接入 state 定点同步、compact 控件、history tree replay、entry fork、draft、`@` 引用、split diff、artifact/citation 打开。
4. smoke 增加路由、runtime 字符串、UI completion 和真实浏览器断言。
暂不做:
- worktree 管理。
- review session / streaming apply 的 Phase C 体验。
本轮已把官方 RPC state/queue/compaction、session tree/fork、composer 引用和 artifact diff 变成 MNote 可观察合同。
## 7. 风险
- 当前工作区已有 Pi Lab 相关未提交改动,后续实现必须基于现状增量修改,不得回滚。
- 官方 `pi_agent_rust` RPC event/response 仍可能变化;MNote API 应只暴露稳定的 MNote schema。
- 真实 runtime 的 `state` / `compact` 已有 request-response correlation;若官方 schema 变化,MNote 仍应返回 `rpcResponsePending=true` / degraded reason,而不是伪装完整真实状态。
- `compact` 会改变 Pi session context,但不应改变 MNote 页面正文。
- JSONL 读取必须严格限定 session 所属路径,否则会变成任意文件读取面。
- 前端不得为了补状态引入周期轮询。