chore: 收口 review 执行清单与 runtime 验证

- 补齐 design/10-review 执行清单、验收标准与相关设计治理记录

- 迁移已完成的 tree、mindmap、runtime fallback、AI kernel 等设计和缺陷条目

- 推进 Rust Web runtime、tree/sidebar、page aggregate、mindmap 与 OnlyOffice 路由侧验证支撑

- 增加 task177-task180 smoke/audit 脚本及前端相关测试覆盖
This commit is contained in:
lix-2026
2026-05-14 05:52:08 +08:00
parent b4a452a8b7
commit 96e03645f7
69 changed files with 4780 additions and 979 deletions
@@ -115,6 +115,8 @@
- 页面本地 aggregate state reducer
- preferred sidebar snapshot / 页头标题补偿链
需要特别区分“Rust route 主读链”和“完整 kernel-native projection”:当前 `/api/page-aggregate/:id` 已经由 Rust route / Rust runtime adapter 对外提供稳定 `mnote.page_aggregate.v1` 契约,前端不再恢复 TS runtime builder 主链;但底层 substrate 仍主要来自 `documents:getMeta + documents:getContent` 的兼容聚合。因此当前 projection provenance 应标记为 `CompatMetaContentJoin`,不能写成已经完全由 Rust kernel 原生投影闭环的 `KernelProjection`
这意味着当前已经不再是:
- `page.tsx` 手工拉 `meta + content` 再现场拼 props
@@ -81,6 +81,8 @@
补充:当前 `page-aggregate-loader.ts`、文档页 SSR 入口与 `DocumentContent` 的内容重试补拉都已经直接消费 Rust `/api/page-aggregate/:id` 返回的 `PageAggregateProjection`,不再由 `page.tsx` 手工拼 `meta + content`。Next `/api/documents/page` 已降级为显式 `410` 的 compat 边界;`page-aggregate-loader.ts` 现在只校验并消费这条 Rust 正式读链,不再在 runtime 中回退到 TS builder。与此同时,`storage-convex-bridge``bridge-runtime` 已开始接受 `page.head.updateTitle / page.layout.updateOptions / page.body.save` 这组 page command family 的命名口径,因此这里按“读取契约已进入 Rust-first,写入命令面已开始收口”勾选完成。
补充:这里的“Rust-first”只表示 `/api/page-aggregate/:id` 的对外 route、契约校验和前端消费主链已经收口到 Rust,不表示底层已经完全 kernel-native。2026-05-13 复核后,当前 route 仍由 Rust runtime adapter 消费 `documents:getMeta + documents:getContent` substrate 构建聚合快照,因此 response `source` / `x-mnote-page-aggregate-owner` 应反映为 `CompatMetaContentJoin` / `compat-join`。只有底层真实改为 kernel 原生 page aggregate projection 后,才应标记为 `KernelProjection` / `rust-kernel`
### 4.3 退出标准
- [x] 后续再讨论标题、页面设置、正文保存时,能够直接定位到它属于 `page_head / page_layout / page_body / page_tree` 的哪一层。
@@ -113,6 +115,8 @@
补充:当前首屏 SSR 与客户端内容重试补拉都已经直接走 `/api/page-aggregate/:id -> PageAggregateProjection`,因此“页面明显由 `meta + content` 两次查询拼起来”的入口级痕迹已经消失;但新增字段仍可能需要继续补 loader / route / island 消费链,所以第二项继续保留未完成。
补充:入口级痕迹消失不等于来源语义消失。当前前端 loader 仍只接受 `mnote.page_aggregate.v1`,不会恢复 TS builder 主链;但 Rust response 的 provenance 必须继续暴露真实构建来源,避免把兼容 join 误验收成 kernel-native projection。
补充:本轮已新增 `page-aggregate-client-state.ts`,并让 `DocumentContent` 把原先分散维护的 `title / options / content / serverContentSnapshot / serverPageSubtreeSnapshot / contentRevision / conflictDetectionKey` 继续收口为同一份 client aggregate state reducer;标题的 draft / committed / persisted 语义也已并入这份 reducer,不再额外维护独立 `usePageHeadTitle` hook 或 `serverPageSubtreeTitle` 双轨状态。这里代表“页面本地 `head/body/layout/tree` 真相已经开始统一”,不等于页面设置运行时分类、AI 对页面设置面的正式入口都已闭环,因此本阶段不提前宣称聚合完成。对应最小回归测试为 `page-aggregate-client-state.test.ts``document-content.test.ts`
---
@@ -160,7 +164,7 @@
- [x] 对未支持项给出显式降级说明,而不是仅保存字段。
- [x] 让“页面设置有值但编辑器内部没变化”这类状态在产品上消失。
补充:本轮已把 AI 页面设置结构化结果接入 `DocumentContent` 现有的 `patch_page_options + page.layout.updateOptions` 正式链路,页面设置不再只能靠人类点击 inspector 才能进入同一条页面命令面。同时,AI 正式写回白名单已限制为 `page-option-semantics.ts``runtimeSupport === "wired"` 的字段,`protectEditing / showStructure / showBlockRefCount` 继续排除在正式写回外,避免把 planned / ui_only 选项误描述为稳定能力。`mnote-cli host` 侧也已新增最小服务端分支:命中页面设置 patch 时,直接执行 `page.layout.updateOptions` 并产出结构化 `tool_result(action=update_page_options)`,不再只把整段结果退化成 assistant 文本。对应最小回归测试为 `DocumentAiAgentPanel.runtime.test.tsx``mnote-cli-agent-host.test.ts`
补充:本轮已把 AI 页面设置结构化结果接入 `DocumentContent` 现有的 `patch_page_options + page.layout.updateOptions` 正式链路,页面设置不再只能靠人类点击 inspector 才能进入同一条页面命令面。同时,AI 正式写回白名单已限制为 `page-option-semantics.ts``runtimeSupport === "wired"` 的字段,`protectEditing / showStructure / showBlockRefCount` 继续排除在正式写回外,避免把 planned / ui_only 选项误描述为稳定能力。历史 `mnote-cli host` 侧也已新增最小服务端分支:命中页面设置 patch 时,直接执行 `page.layout.updateOptions` 并产出结构化 `tool_result(action=update_page_options)`,不再只把整段结果退化成 assistant 文本。2026-05-13 起后续主线改为 Hermes tool call -> mnote skill/plugin -> `page.layout.updateOptions`,该 host 分支只保留为过渡证据。对应最小回归测试为 `DocumentAiAgentPanel.runtime.test.tsx``mnote-cli-agent-host.test.ts`
补充:本轮继续把 Inspector 产品态与这份分类对齐:`showHeadingNumbers / embedDefaultBlockId` 已按“正式接通项”更新文案,不再继续显示“已保存字段但未接通”;`showBlockRefCount` 作为纯占位项也不再继续暴露可点击的假开关,而是明确显示 `待接线`。对应最小回归测试为 `page-options-sidebar.test.tsx``page-option-semantics.test.ts`
### 6.4 退出标准
@@ -230,7 +234,7 @@
补充:本轮继续把 AI 面板的读取边界开始收口到统一页面本地快照:`DocumentContent` 不再向 `DocumentAiAgentPanel` 透传 `getLatestBlocks / getLatestPageSubtree / getLatestPersistedMeta` 三组分散 getter,而是改为一份 `getLatestPageAggregateSnapshot`,由 `page-aggregate-client-state` 导出 `blocks / pageSubtree / persistedMeta / pageOptions`。这代表 AI 面板已开始消费同一份页面本地 aggregate state,而不是继续拼接独立局部真相;但页面设置写工具本身仍未进入 Hermes 正式 tool surface,因此这里仍然只算“开始收口”,不提前打满。
补充:本轮还把 `pageOptions``editorRuntimePageOptions` 一并带入 `/api/ai-agent/run -> buildHermesInstructions`,因此 AI 在服务端至少能看到“当前页面设置是什么”以及“哪些设置已经进入 island runtime payload”,不再只依赖正文块快照和树快照来猜测页面语义。对应回归测试为 `src/app/api/ai-agent/run/route.test.ts`。这推进的是 AI 读侧上下文,不等于页面设置写工具已经具备正式入口。
补充:本轮还把 `pageOptions``editorRuntimePageOptions` 一并带入历史 `/api/ai-agent/run -> buildHermesInstructions`,因此 AI 在服务端至少能看到“当前页面设置是什么”以及“哪些设置已经进入 island runtime payload”,不再只依赖正文块快照和树快照来猜测页面语义。对应回归测试为 `src/app/api/ai-agent/run/route.test.ts`2026-05-13 起同类上下文后续应改为 Hermes run/session context,并由 Hermes 通过 mnote plugin 回读最新 page aggregate这推进的是 AI 读侧上下文,不等于页面设置写工具已经具备正式入口。
### 8.2 与主编辑区的关系
@@ -240,27 +244,27 @@
补充:进入这一步后,当前最大的真实 blocker 已经明确下来,不再继续靠口头描述模糊处理:
- `/api/ai-agent/run` 当前默认主路仍是 `mnote-cli host`
- `mnote-cli host` 目前没有真正的模型/tool 执行环,而是 `cargo ... tool run --tool-name doc_get --mode explain-plan` 的说明型入口
- 因此,当前新增的 `page_options_patch -> page.layout.updateOptions -> structured tool_result` 仍然只是“主路内的最小结构化兼容分支”,不是完整正式 tool surface
- 页面 AI 历史实现仍残留 `/api/ai-agent/run` / `mnote-cli host` 路径
- Hermes 页面内客户端、Hermes session 真相和 mnote skill/plugin tool surface 还没有在页面 AI 主链落地
- 因此,当前新增的 `page_options_patch -> page.layout.updateOptions -> structured tool_result` 仍然只是“历史主路内的最小结构化兼容分支”,不是完整正式 Hermes tool surface
这意味着 `8.2` 后续完成标准必须至少包含:
1. 页面设置进入真正的 agent/tool 执行环,而不是继续靠 host 内部的自然语言/最小规则分支识别
2. 页面设置结构化结果由正式 tool 调用产出,而不是只由 host 自己补一条兼容 `tool_result`
1. 页面设置进入 Hermes tool call -> mnote plugin -> Rust runtime 的正式执行环,而不是继续靠 host 内部的自然语言/最小规则分支识别
2. 页面设置结构化结果由正式 mnote plugin tool 调用产出,而不是只由 host 自己补一条兼容 `tool_result`
3. 树标题 / 页头 / 页面设置三条 AI 写回链在同一条正式 page aggregate command family 中闭环,并补 smoke 验证
### 8.3 退出标准
- [x] AI 写入口已经可以被明确描述为“操作 page aggregate command family”,而不是“绕过系统写编辑器”。
注:当前 `/api/ai-agent/run``Hermes tool.completed` 后,会优先尝试把 `slash_run / doc_insert_blocks / doc_replace_range` 恢复成 `mnote-web bridge-runtime` 的结构化 `tool_result`,不再只把 Hermes 事件当作薄日志。其后:
注:历史 `/api/ai-agent/run``Hermes tool.completed` 后,会优先尝试把 `slash_run / doc_insert_blocks / doc_replace_range` 恢复成 `mnote-web bridge-runtime` 的结构化 `tool_result`,不再只把 Hermes 事件当作薄日志。2026-05-13 起这只保留为过渡证据;新的主线应由 Hermes 直接发起 mnote plugin tool call,再由 Rust runtime / kernel 返回 tool result。其后:
- `doc_insert_blocks / doc_replace_range` 继续按 `page.body.save` 语义落到 `/api/documents/save`,再正式回显主编辑区 island。
- `slash_run(rename current page)` 会把结构化结果回接到当前页 `DocumentContent` 的同一条标题提交链,并继续广播 `emitDocumentsChanged(documentId)`,因此页头标题与树标题不再靠 AI 面板内部本地状态各自漂移。
- 当前 AI 面板已经能消费结构化 `update_page_options` 结果,并把 `pageOptionsPatch` 回接到当前页 `DocumentContent` 的同一条 `patch_page_options + page.layout.updateOptions` 提交链;同时只允许 `runtimeSupport === "wired"` 的字段进入正式写回,避免 planned / ui_only 页面设置混入主链。对应最小回归测试为 `DocumentAiAgentPanel.runtime.test.tsx``document-content.test.ts`
- `mnote-cli host` 现已能在命中页面设置 patch 时直接执行 `page.layout.updateOptions`,并向前端回放结构化 `tool_call/tool_result` 事件;这意味着“服务端完全没有页面设置结构化写回结果”的状态已经结束。
-`pageOptions` 仍没有进入 Hermes 正式 tool surface,当前服务端 patch 识别也仍是最小规则分支而不是完整模型工具编排,因此“页面设置类 AI 命令”仍不能算整条线已闭环;`8.2` 的最后一项继续保留未完成,避免误判为整条线已经闭环。
- 历史 `mnote-cli host` 现已能在命中页面设置 patch 时直接执行 `page.layout.updateOptions`,并向前端回放结构化 `tool_call/tool_result` 事件;这意味着“服务端完全没有页面设置结构化写回结果”的状态已经结束。
-`pageOptions` 仍没有进入 mnote Hermes plugin 的正式 tool surface,当前服务端 patch 识别也仍是最小规则分支而不是完整 Hermes tool 编排,因此“页面设置类 AI 命令”仍不能算整条线已闭环;`8.2` 的最后一项继续保留未完成,避免误判为整条线已经闭环。
---
@@ -391,8 +391,8 @@ GREEN
- E26 执行前口径纠偏:2026-05-02 已按 `5-2``5-4``5-5``5-6``5-7` 设计确认,E26 不是“前端引入 Tiptap UniqueID 即完成”。正式块身份必须来自 Rust `EditorBlock.block_id`,经 Tiptap bridge 映射为 `data-block-id` 供浏览器 runtime 使用,再通过 `page.body.save` 写回 Convex-backed 持久化底座;复制锚点和 hash 定位只能消费这个真源 id。Tiptap `UniqueID` 可以参考其节点身份策略,但不得生成长期块 id、不得绕过 Rust `EditorBlockDocument`、不得绕过 Page Aggregate / `page.body.save`
- E26 执行边界:实现与 smoke 必须把 `EditorBlockDocument -> Tiptap attrs.blockId/data-block-id -> DOM 锚点 -> page.body.save -> /api/documents/content -> reload/hash 定位` 串成一条链。允许在浏览器 runtime 内用 `UniqueID` 或等价插件帮助定位节点,但只能读取/补齐已有 Rust block id;若某块缺少正式 id,应通过 Rust/保存适配链生成并持久化,而不是让前端临时 id 成为长期合同。Convex 只验证持久化结果可读可刷新,不作为语义真源。
- E26 最小真源闭环:2026-05-02 已完成第一段 anchor 切片。`leptos-tiptap` paragraph/heading/blockquote/codeBlock/image/table 的 `blockId` 渲染同时输出 `data-block-id` 与 DOM `id`,浏览器 hash 命中走 `id=:blockId` + CSS `:target`,不是手工给 ProseMirror DOM 写临时 classRust runtime 复制链接和 hash 滚动继续只消费 `EditorBlock.block_id` 派生的 `attrs.blockId``mnote-web` 保存 payload 不再发送空 `content: []`,而是派生 `editorDocument`、legacy `content``tiptapDocument``blockCount` 写回 Convex-backed 持久化底座;reload 侧 legacy block 恢复继续补 `attrs.blockId`。本地 smoke `node scripts/task154-e26-anchor-smoke.js` 已覆盖保存请求、`/api/documents/content`、复制链接、DOM `id/:target` 和 reload/hash 定位,截图目录:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task154-e26-anchor-local-smoke`。剩余:列表项/分割线等更多块类型的统一 anchor attr 覆盖、Wolai 视觉细节、块引用/页面引用预览与移动端行为另拆后续。
- E27 执行前口径纠偏:AI 编辑能力包不是“补 AI 菜单文案”或“点击后显示 feedback”。最小闭环必须从 `leptos-tiptap` 的 slash / 块菜单入口出发,携带当前 `documentId``workspaceId`、Rust `blockId`、selection 摘要和 Tiptap JSON 快照,调用 mnote 现有 AI 真源边界。2026-05-05 起长期口径进一步修正:`/api/ai-agent/run` 不应长期绑定 `openai-agents-python` sidecar,而应收口为 `mnote-cli` 唯一长期 agent 执行面上的 host / adapter`openai-agents-python``Hermes``Codex` 只允许作为可插拔外置 agent。结构化写入仍必须回到 Rust tool / `page.body.save` / Convex-backed content 链。E27 第一刀已完成的 sidecar 路径只作为过渡基线,不宣称是长期主线。
- E27 AI agent 入口与写入闭环:2026-05-02 已完成主路径纠偏,修正此前把 `/api/hermes/bridge` 当作 E27 主入口的误导口径。块菜单 `AI 助理` 现在从当前 `leptos-tiptap` editor 读取 `documentId``workspaceId`、Rust `blockId`、selection state、selected text 与 `tiptapDocument` 快照,发起 `/api/ai-agent/run` 请求,payload 固定 `scope=document``stream=true``options.ai.provider=online`,并显示 `mnote-leptos-tiptap-ai-status``idle/pending/ready/error` 状态;请求上下文标记 `source=leptos-tiptap-island``action=ask_ai`Next sidecar adapter 已透传 `workspaceId / selectedBlockId / selection / tiptapDocument` 等 block 级上下文给 `openai-agents-python`。本地 smoke `node scripts/task155-e27-ai-edit-smoke.js` 已先 RED 于 Hermes 主入口,再 GREEN 覆盖请求 URL、payload 真源字段和 ready 状态;`node scripts/task156-e27-ai-writeback-smoke.js` 已先 RED 于只返回不写入,再 GREEN 覆盖 SSE `doc_replace_range` tool_result -> 编辑器改写 -> `/api/documents/save` -> `/api/documents/content` 真源读回 -> reload 后页面读回。截图目录:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task156-e27-ai-writeback-local-smoke`。剩余:Wolai AI 菜单视觉基线断流未完成、slash AI/selection toolbar AI、Improve/continue/regenerate/summarize/translate 子命令、SSE 分段 UI 状态、`doc_insert_blocks` 多块插入和标题 `slash_run` 应用另拆后续。
- E27 执行前口径纠偏:AI 编辑能力包不是“补 AI 菜单文案”或“点击后显示 feedback”。最小闭环必须从 `leptos-tiptap` 的 slash / 块菜单入口出发,携带当前 `documentId``workspaceId`、Rust `blockId`、selection 摘要和 Tiptap JSON 快照,进入 Hermes run/session contextHermes 通过 mnote skill/plugin 调用稳定工具,再由 Rust runtime / `page.body.save` / Convex-backed content 链写回。2026-05-13 起长期口径进一步修正:`/api/ai-agent/run``openai-agents-python` sidecar `mnote-cli host` 都只作为历史/兼容路径,不再代表页面 AI 长期主入口;`mnote-cli` 只可作为 mnote plugin 内部适配器或调试入口。E27 第一刀已完成的 sidecar / `/api/ai-agent/run` 路径只作为过渡基线,不宣称是长期主线。
- E27 AI agent 入口与写入闭环:2026-05-02 已完成历史主路径纠偏,修正此前把 `/api/hermes/bridge` 当作 E27 主入口的误导口径。块菜单 `AI 助理` 当时从当前 `leptos-tiptap` editor 读取 `documentId``workspaceId`、Rust `blockId`、selection state、selected text 与 `tiptapDocument` 快照,发起 `/api/ai-agent/run` 请求,payload 固定 `scope=document``stream=true``options.ai.provider=online`,并显示 `mnote-leptos-tiptap-ai-status``idle/pending/ready/error` 状态;请求上下文标记 `source=leptos-tiptap-island``action=ask_ai`Next sidecar adapter 已透传 `workspaceId / selectedBlockId / selection / tiptapDocument` 等 block 级上下文给 `openai-agents-python`。本地 smoke `node scripts/task155-e27-ai-edit-smoke.js` 已先 RED 于 Hermes 主入口,再 GREEN 覆盖请求 URL、payload 真源字段和 ready 状态;`node scripts/task156-e27-ai-writeback-smoke.js` 已先 RED 于只返回不写入,再 GREEN 覆盖 SSE `doc_replace_range` tool_result -> 编辑器改写 -> `/api/documents/save` -> `/api/documents/content` 真源读回 -> reload 后页面读回。截图目录:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task156-e27-ai-writeback-local-smoke`。剩余:把入口改为 Hermes client proxy,把上下文作为 Hermes run/session context 传入,把写入工具注册为 mnote Hermes pluginWolai AI 菜单视觉基线、slash AI/selection toolbar AI、Improve/continue/regenerate/summarize/translate 子命令、Hermes streaming UI 状态、`doc_insert_blocks` 多块插入和标题写入另拆后续。
- E27 Auth 真源纠偏:2026-05-02 补充确认,AI 编辑和在线 smoke 的用户身份必须以真实 Convex Auth 为主线;不同账号的数据隔离依赖 Convex `getAuthUserId(ctx)` 解析真实 identity subject,并由 workspace/member 权限链校验。`/auth` 复用既有 Convex Auth 页面和统一测试账号 `test@example.com` / `Test123456``/api/auth/session``/api/auth/whoami`、AI orchestrator 转发和 Convex transport 均应真实 token / forwarded actor 优先。`DEV_USER_ID` / admin acting identity 只允许作为本地底层 fallback 或显式 `MNOTE_DEV_AUTH=1` 联调模式,不能作为 E27 在线验收、多账号隔离或正式数据真源。
- E27 当前推进备注:2026-05-03 主线程先切到 E28 Mention / EmojiE27 暂停在 online smoke 模型网关层排障状态。当前已确认 `3000 -> 8000` orchestrator 主链可达,本地 `task155/task156` 通过;剩余在线阻塞点在 `20128 /v1/responses` 上游模型/渠道可用性,以及后续真实 actor 收口。恢复 E27 时应从这两点继续,不要回退成“主入口未迁完”。
- E28/E29 暂停与 E30 先行口径:2026-05-03 主线程先暂停 E28 Mention / Emoji 与 E29 Comment / History,转入 E30 Menu / Floating 状态机能力包。E28 已有 Wolai Hermes baseline 显示正文输入 `@` 当前弹出提醒/会议/成员候选,并可插入成员 mention,不是页面引用搜索;证据目录为 `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task157-e28-wolai-mention-baseline/`,恢复 E28 时需先重新定 `@mention` 口径,不要按“页面引用第一刀”继续。E29 在评论/历史后端边界未重新确认前保持暂停。E30 第一刀只收敛已有 slash、块菜单、二级菜单、selection/image/table floating toolbar 的打开互斥、Esc、外部点击、方向键、Enter 与层级收起,不扩新业务命令。
@@ -418,7 +418,7 @@ GREEN
| E24 | PARTIAL | Image / Media 能力包 | 已完成图片 `/tp` 最小真源闭环与图片 toolbar 小闭环:slash `媒体与附件` 分组入口调用 `leptos-tiptap` 官方 `set_image(TiptapImageResource)`,启用 `TiptapExtension::Image`,保存链新增 `EditorBlockType::Image` / `TiptapNode::Image` 并保留 `props.tiptapImage``mnote-web` reload 恢复 `<img>`;点击图片后出现 `image-floating-toolbar`,删除入口本切片保持禁用,左/中/右对齐通过官方 Image 扩展 `addAttributes("data-align")` + `updateAttributes("image")` 持久化,同源下载通过隐藏 `<a download>` 触发且不改文档;`task152-e24-image-smoke.js` 覆盖入口、实际图片加载、toolbar、同源下载、删除入口禁用态、居中对齐、保存请求、content API 和刷新恢复;剩余上传、最近上传、caption、resize、replace、跨源下载 fallback、删除保存链、移动端 toolbar、失败态 |
| E25 | PARTIAL | TOC 能力包 | 已完成 `/toc` 最小真源闭环:`leptos-tiptap` 新增真实 `tocNode` schema/commandslash `页面目录 /toc` 插入真实节点,NodeView 从当前 headings 派生目录项,支持点击定位、标题显示开关、保存请求、content API 与 reload 恢复;`task153-e25-toc-smoke.js` 覆盖入口、动态 heading 更新、hash 定位和 `props.tiptapTocNode`。剩余 TOC sidebar、active heading 高亮、完整块菜单入口、官方 TableOfContents v3 数据源评估、移动端与像素级视觉 |
| E26 | PARTIAL | UniqueID / Anchor 能力包 | 已完成最小真源闭环:Rust `EditorBlock.block_id` -> Tiptap `attrs.blockId` -> DOM `data-block-id` + `id` -> 复制链接 hash -> `page.body.save` / `/api/documents/content` -> reload 后 `:target` 定位;`task154-e26-anchor-smoke.js` 覆盖保存、复制、reload/hash 和截图。Tiptap `UniqueID` 仍只作为参考/辅助口径,不作为正式块 id;剩余更多块类型 anchor 覆盖、Wolai 视觉细节、引用预览和移动端行为。 |
| E27 | PARTIAL | AI 编辑能力包 | 已完成块菜单 `AI 助理` 主路径与最小写入闭环:点击后发起 `/api/ai-agent/run`payload 使用 `scope=document``stream=true``options.ai.provider=online`,携带 `documentId``workspaceId`、Rust `blockId`、selection、selected text、Tiptap 快照和 `action=ask_ai`历史基线里 `Hermes` 只作为 `/api/ai-agent/run` 内部 fallback。2026-05-05 起长期口径改为:`/api/ai-agent/run` 后续应收口为 `mnote-cli` 唯一长期 agent 执行面上的 host / adapter`Hermes``Codex``openai-agents-python` 仅为可插拔外置 agent`task155-e27-ai-edit-smoke.js``task156-e27-ai-writeback-smoke.js` 保留为过渡主链行为基线。Auth 验收必须复用 Convex Auth 测试账号,真实 token / actor 优先,`dev identity` 仅为本地 fallback。当前主线程已于 2026-05-03 先切 E28E27 暂停在 online smoke 的 `20128 /v1/responses` 模型网关排障与真实 actor 收口。剩余 slash AI/selection toolbar AI、Improve/continue/regenerate/summarize/translate、Wolai 视觉基线、SSE 分段 UI、`doc_insert_blocks` 多块插入与标题写入。 |
| E27 | PARTIAL | AI 编辑能力包 | 已完成历史块菜单 `AI 助理` 主路径与最小写入闭环:点击后发起 `/api/ai-agent/run`payload 使用 `scope=document``stream=true``options.ai.provider=online`,携带 `documentId``workspaceId`、Rust `blockId`、selection、selected text、Tiptap 快照和 `action=ask_ai``task155-e27-ai-edit-smoke.js``task156-e27-ai-writeback-smoke.js` 保留为过渡行为基线。2026-05-13 起长期口径改为:页面 AI 入口应调用 Hermes client proxyHermes session/message/tool event/usage/model 是会话真相,mnote 通过 Hermes skill/plugin 执行 `page.body.save`、标题、页面设置、artifact、edge 等业务工具;`mnote-cli` 仅可作为 plugin 内部适配器。Auth 验收必须复用 Convex Auth 测试账号,真实 token / actor 优先,`dev identity` 仅为本地 fallback。当前主线程已于 2026-05-03 先切 E28E27 暂停在 online smoke 的 `20128 /v1/responses` 模型网关排障与真实 actor 收口。剩余 Hermes client proxy 接入、mnote plugin tool 注册、slash AI/selection toolbar AI、Improve/continue/regenerate/summarize/translate、Wolai 视觉基线、Hermes streaming UI、`doc_insert_blocks` 多块插入与标题写入。 |
| E28 | PAUSED | Mention / Emoji 能力包 | 2026-05-03 暂停;Wolai baseline 已纠偏:正文 `@` 当前是提醒/会议/成员候选入口,不是页面引用搜索,恢复时先重定 mention/emoji 口径,再决定 Tiptap JSON 与 mnote 保存链 |
| E29 | PAUSED | Comment / History 能力包 | 2026-05-03 暂停;评论/历史入口仍需后端边界和 Wolai 基线复核,待 E30 统一菜单状态机后再接入,避免继续复制独立弹层逻辑 |
| E30 | PARTIAL | Menu / Floating 状态机能力包 | 2026-05-03 第一刀已完成本地统一状态机 smoke:`task158` 覆盖 slash、块菜单/二级菜单、selection toolbar/color panel、image floating toolbar、table toolbar/options 的互斥打开、Esc 统一关闭、方向键 active,以及打开块菜单时关闭 image toolbarWolai 只读基线已确认 selection/type menu 和 table popper 的 Esc/外部点击/URL 不变,slash 与块菜单二级菜单在只读条件下不稳定,后续仍需 editable-test 复核 Enter、外部点击和更多层级收起 |