Files
mnote/design/07-ai/done/7-4-page-ai-hermes-panel-execution-checklist-v1.md
T
lix-2026 47e224d419 chore: align sqlite control plane architecture
- replace default Convex control-plane wording with Rust SQLite control-plane across architecture, AGENTS, Reasonix, and design docs

- retire root Convex functions source and deploy script into recycle while keeping explicit cloud/compat/sync-replica boundaries

- add control-plane migration guard/docs and keep CodeGraph refreshed after the SQLite control-plane cutover
2026-05-22 17:45:22 +08:00

86 KiB
Raw Blame History

7-4 [done] 页面 AI Hermes 面板顺序执行 checklist v1

更新时间:2026-05-14

当前状态:DONE。A-M 的实现、旧链退场、持久化审计和正式 3000 全矩阵已完成;N 文档治理已把活跃设计口径统一为 Hermes 页面内客户端 + mnote Hermes skill/plugin。本文已从 process/ 迁入 done/;后续页面 AI 体验与设置面收口由 design/07-ai/process/7-7-page-ai-mini-hermes-control-surface-v1.md 继续承接。

上位依据:

  • /mnt/Data1T/mnote/ARCHITECTURE.md
  • /mnt/Data1T/mnote/design/01-05-current-priority-overview.md
  • /mnt/Data1T/mnote/design/03-rust-web/process/3-rust-web-long-term-architecture-v1.md
  • /mnt/Data1T/mnote/design/03-rust-web/process/3-15-runtime-fallback-retirement-checklist-v1.md
  • /mnt/Data1T/mnote/design/05-editor-mainline/process/5-5-page-aggregate-single-truth-alignment-v1.md
  • /mnt/Data1T/mnote/design/05-editor-mainline/process/5-6-page-aggregate-alignment-checklist-v1.md
  • /mnt/Data1T/mnote/design/05-editor-mainline/done/5-10-wolai-page-settings-and-ai-surface-alignment-v1.md
  • /mnt/Data1T/mnote/design/05-editor-mainline/done/5-11-wolai-page-settings-and-ai-surface-checklist-v1.md
  • /mnt/Data1T/mnote/design/05-editor-mainline/reference-code/hermes-web-ui-0.5.18
  • /mnt/Data1T/mnote/design/07-ai/done/7-2-phase7-structured-artifact-write-chain-v1.md
  • /mnt/Data1T/mnote/design/07-ai/done/7-3-page-ai-hermes-panel-and-mnote-plugin-v1.md

目标:

  • 把页面 AI 从旧 /api/ai-agent/run / mnote-cli host / sidecar 路径迁到 Hermes 页面内客户端。
  • Hermes 持有 AI session/message/tool event/usage/model 真相。
  • mnote 只通过 Hermes skill/plugin 暴露页面、树、artifact、edge 等业务工具。
  • Leptos 负责页面内 Hermes 面板体验,不负责 AI 编排或聊天真相存储。

0. 使用方式

每次只领取一个 task,按顺序执行。除非前一 task 的验收标准全部满足,否则不要进入下一 task。

勾选规则:

  • 已有代码、文档和可复跑验证证据。
  • 还没有完整证据,或只有局部实现。
  • PARTIAL 项不能当作完成项;必须继续拆到对应未勾选子项。

状态标记:

  • TODO:未开始
  • RED:已补失败测试或失败 smoke
  • GREEN:当前 task 本地通过
  • BLOCKED:依赖外部 Hermes、auth、模型网关或数据权限,无法在本轮闭环
  • DONE:代码、测试、文档证据都已回填

执行硬规则:

  • 不新增 Web 私有 AI tool registry。
  • 不把 Hermes 聊天消息复制进 mnote page aggregate / Convex 页面数据。
  • 不让 Hermes plugin 直接写 Convex,写入必须回到 Rust runtime / kernel。
  • 不把 mnote-cli 写回页面 AI 唯一长期执行面;它最多是 plugin 内部 adapter 或调试入口。
  • 不在页面 AI 抽屉里复刻 Hermes 管理台;只实现页面内 chat/session/run/tool event 子集。
  • 不在同一阶段同时迁移所有工具;先读、再写正文、再 artifact、再树与 edge。

当前进度快照:

Task 状态 已有证据 剩余门槛
A [x] GREEN scripts/task-hermes-page-ai-baseline-smoke.jsbugs/07-ai/done/7-1-page-ai-provider-hermes-old-run-502-v1.md
B [x] GREEN design/07-ai/done/7-5-hermes-client-proxy-contract-v1.md
C [x] GREEN rust/crates/mnote-web/src/routes/hermes_client.rscargo test -p mnote-web hermes_
D [x] GREEN design/07-ai/done/7-6-mnote-hermes-plugin-tool-contract-v1.md
E [x] GREEN rust/crates/mnote-web/src/routes/hermes_tools.rsrust/crates/mnote-web/src/hermes_tools/*task-hermes-page-ai-tool-smoke.js 后续可扩 manifest 全量 schema,不阻塞第一版只读工具
F [x] GREEN rust/crates/mnote-web/src/ssr/pages/layout.rstask-hermes-page-ai-smoke.js
G [x] GREEN 真实 Hermes upstream run 已触发 mnote_page_get / mnote.page.getHermes session export 与刷新恢复已验证
H [x] GREEN mnote.page.save route、dryRun、未认证拒绝、workspace ACL 失败、同 key replay、主编辑区立即回显与刷新后持久化 smoke 已有
I [x] GREEN mnote.page.update_titlemnote.page.update_options route 与 smoke 已有;标题 dryRun / idempotency、wired-only warning、页头 / breadcrumb / sidebar / 刷新后一致性已验证
J [x] GREEN mnote.artifact.create_summarymnote.artifact.create_ai_note route 与 smoke 已有;summary 重试、ai_note 独立创建、真实 kernel/projection edge 查询、AI Artifacts projection-only 验收和页面 AI Hermes intent 快捷入口已通过
K [x] GREEN 新页面 AI 主链已不请求 /api/ai-agent/run;旧 endpoint 统一返回 410 legacy_ai_agent_run_retired;旧 smoke 默认退役;legacy 调用方已清点并归类
L [x] GREEN tool 响应已有基础 audit 字段;routes/hermes_tools.rs 已记录 started/completed/failed 结构化日志;写工具 audit.commandId 已指向 Rust command id;审计已追加 JSONL 持久化并支持 persistedOnly=true 反查
M [x] GREEN 正式 http://127.0.0.1:3000 已复跑 8 个 E2E smokesession/run、tool、writeback、title/options、artifact、retirement、mobile、audit
N [x] GREEN 7-3/7-4/7-5/7-6 已写入主线口径;1-13-15-65-910-review 已统一旧 AI 口径为历史/兼容/已覆盖 后续若移动本文件到 done/,需同步更新引用

1. Hermes Web UI 参考索引

需要参考 /mnt/Data1T/mnote/design/05-editor-mainline/reference-code/hermes-web-ui-0.5.18 时,只参考下表列出的文件。参考目标是理解 Hermes 的 session / run / stream / tool event / usage / model 语义,不照搬 Vue、Naive UI、整站导航或后台管理页面。

执行时按 task 精确打开文件,不要整目录通读。需要进一步定位时,优先按下表的“搜索点”打开,不要从整站 UI 或无关管理页开始看:

参考主题 文件 搜索点 / 具体位置 在 mnote 中用于什么
浏览器发起 run 与事件分发 packages/client/src/api/hermes/chat.ts StartRunRequestRunEventregisterSessionHandlersconnectChatRunstartRunViaSocket 对齐 mnote Leptos 面板发起 run、订阅 message.delta / tool.started / tool.completed / run.completed 的事件语义
session 刷新恢复 packages/client/src/api/hermes/chat.tspackages/client/src/stores/hermes/chat.ts resumeSessionswitchSessionrefreshActiveSessionmapHermesMessages 对齐页面刷新后从 Hermes session detail / resume 恢复消息,而不是从 mnote 本地 state 恢复聊天真相
tool message 前端归并 packages/client/src/stores/hermes/chat.ts Message.role = 'tool'toolCallIdtoolArgstoolResultcase 'tool.started'case 'tool.completed' 对齐 mnote 面板如何把 tool started / completed 合并成可读消息项
tool message 展示 packages/client/src/components/hermes/chat/MessageItem.vue message.role === 'tool'formatToolPayloadtoolExpandedtool-previewtool-details 对齐 tool 结果默认折叠、摘要展示、详细 JSON 展开的交互边界
页面面板分层 packages/client/src/components/hermes/chat/ChatPanel.vue showSessionsactiveSessionTitlehandleNewChatMessageListChatInputSessionListItem 只参考 session list / message list / input 的分层,不复制 Vue / Naive UI / Hermes 全屏布局
后端 run 与 resume 房间 packages/server/src/services/hermes/chat-run-socket.ts ChatRunSocketonConnectionresumeSessionhandleRunemitmarkCompleted 对齐 upstream run 生命周期、刷新恢复、房间广播与终止态,不在 mnote 里重建 Hermes 编排器
OpenAI Responses tool event 映射 packages/server/src/services/hermes/chat-run-socket.ts applyResponseStreamEventresponse.output_item.donefunction_callfunction_call_outputtool.startedtool.completedflushResponseRunToDb 对齐真实 Hermes upstream run 如何产生 tool event,并把 tool call / tool result 写回 Hermes session 存储
Hermes session 存储真相 packages/server/src/db/hermes/session-store.ts HermesSessionRowHermesMessageRowcreateSessiongetSessionDetailaddMessageupdateSessionStats 明确 session/message/tool call 真相在 Hermes,不在 mnote page aggregate / Convex 页面数据
session HTTP detail packages/client/src/api/hermes/sessions.tspackages/server/src/routes/hermes/sessions.ts fetchSessionsfetchSessionHermesMessage/api/hermes/sessions/:id 对齐 session list/detail 的字段名,用于 mnote proxy 返回兼容形状
plugin/skill 清单发现 packages/server/src/services/hermes/plugins.ts PYTHON_BRIDGEPluginManageruser_dir = get_hermes_home() / "plugins"manifest_listprovidesToolslistHermesPlugins 对齐 Hermes Web UI 如何发现 user/project plugin 和 provides_tools;mnote 的真正工具必须进入 Hermes plugin/tool registry,不能只停在 mnote-web 私有 route
plugin/skill API 外观 packages/client/src/api/hermes/plugins.tspackages/client/src/api/hermes/skills.tspackages/server/src/routes/hermes/plugins.tspackages/server/src/routes/hermes/skills.ts list / get / enable / disable 类 route 与响应字段 只用于清单和状态展示口径;页面 AI 第一版不复刻 Hermes plugin 管理台

可快速 grep

cd /mnt/Data1T/mnote/design/05-editor-mainline/reference-code/hermes-web-ui-0.5.18
rg -n "StartRunRequest|RunEvent|registerSessionHandlers|startRunViaSocket|resumeSession|tool\\.started|tool\\.completed|applyResponseStreamEvent|flushResponseRunToDb|PluginManager|providesTools|listHermesPlugins" packages/client/src packages/server/src

已分类的常用入口:

  • session / run / SSE:先看 packages/client/src/api/hermes/chat.tspackages/server/src/routes/hermes/chat-run.tspackages/server/src/services/hermes/chat-run-socket.ts
  • session 真相恢复:先看 packages/server/src/db/hermes/session-store.tspackages/server/src/db/hermes/sessions-db.tspackages/server/src/services/hermes/session-sync.ts
  • 面板组件分层:先看 packages/client/src/views/hermes/ChatView.vuepackages/client/src/components/hermes/chat/ChatPanel.vueChatInput.vueMessageList.vueMessageItem.vue
  • tool event:先看 packages/client/src/stores/hermes/chat.tspackages/client/src/components/hermes/chat/MessageItem.vuepackages/server/src/db/hermes/conversations-db.ts
  • plugin / skill 清单:先看 packages/client/src/api/hermes/plugins.tspackages/client/src/api/hermes/skills.tspackages/server/src/routes/hermes/plugins.tspackages/server/src/routes/hermes/skills.tspackages/server/src/services/hermes/plugins.ts
mnote 任务 参考文件 只参考什么 不采用什么
Hermes API client 合同 packages/client/src/api/hermes/chat.tspackages/client/src/api/hermes/sessions.tspackages/client/src/api/hermes/conversations.ts chat run、session detail、conversation list/detail 的请求和响应形状 不直接复用 TS client,不让浏览器绕过 mnote-web proxy
Hermes proxy / route 形态 packages/server/src/routes/hermes/chat-run.tspackages/server/src/routes/hermes/sessions.tspackages/server/src/routes/hermes/proxy.tspackages/server/src/routes/hermes/proxy-handler.ts 服务端 route 如何接收 run、session、proxy 请求以及错误透传边界 不把 Hermes server route 复制进 mnotemnote 只做同源薄代理
session 真相与恢复 packages/server/src/db/hermes/session-store.tspackages/server/src/db/hermes/sessions-db.tspackages/server/src/db/hermes/conversations-db.tspackages/server/src/services/hermes/conversations.tspackages/server/src/services/hermes/session-sync.ts session/message/conversation 的存储、搜索、恢复、thread/lineage 摘要 不在 mnote 里重建这些表或复制聊天历史
usage / model 真相 packages/server/src/db/hermes/usage-store.tspackages/client/src/stores/hermes/usage.tspackages/client/src/stores/hermes/models.tspackages/client/src/components/layout/ModelSelector.vue usage、model selection、model display 的字段和展示语义 不在 mnote page aggregate 保存 usage/model 真相
chat 面板结构 packages/client/src/views/hermes/ChatView.vuepackages/client/src/components/hermes/chat/ChatPanel.vuepackages/client/src/components/hermes/chat/ChatInput.vuepackages/client/src/components/hermes/chat/MessageList.vuepackages/client/src/components/hermes/chat/MessageItem.vuepackages/client/src/components/hermes/chat/HistoryMessageList.vuepackages/client/src/components/hermes/chat/SessionListItem.vue session list、message list、输入框、消息项、历史消息的组件分层 不采用 Vue / Naive UI / Hermes 全屏布局;mnote 仍用 Leptos island 和 Wolai drawer 壳
markdown / thinking 展示 packages/client/src/components/hermes/chat/MarkdownRenderer.vuepackages/client/src/utils/thinking-parser.tstests/client/chat-store-thinking.test.tstests/client/thinking-parser.test.ts markdown 渲染、think/thinking/reasoning 片段解析、streaming 中的 thinking 边界 不直接照搬样式;mnote 只实现页面 AI 抽屉需要的折叠展示
stream / abort / resume packages/client/src/stores/hermes/chat.tspackages/client/src/api/hermes/chat.tspackages/server/src/routes/hermes/chat-run.tspackages/server/src/services/hermes/chat-run-socket.ts run stream 事件、resume session room、abort started/completed、queue/server-working 状态 不强制采用 Socket.IOmnote proxy 可用 SSE 或项目现有 stream 机制,但事件语义要对齐
tool event 展示 packages/client/src/stores/hermes/chat.tspackages/client/src/components/hermes/chat/MessageItem.vuepackages/client/src/components/hermes/chat/HistoryMessageList.vuepackages/server/src/db/hermes/conversations-db.ts tool_call_id、tool message、tool started/completed/failed 的归并与历史展示 不把 tool result 写入 mnote 正文;只展示 Hermes tool event
session 搜索 packages/client/src/components/hermes/chat/SessionSearchModal.vuepackages/client/src/composables/useSessionSearch.tstests/client/session-search.test.tstests/client/sidebar-search.test.ts 后续 session search 的交互和过滤语义 第一版可后置,不进入最小验收
plugins / skills 列表 packages/client/src/api/hermes/plugins.tspackages/client/src/api/hermes/skills.tspackages/server/src/routes/hermes/plugins.tspackages/server/src/routes/hermes/skills.tspackages/server/src/services/hermes/plugins.tspackages/client/src/components/hermes/skills/SkillList.vuepackages/client/src/components/hermes/skills/SkillDetail.vue Hermes 如何表达 plugin/skill 清单、启停和详情 不采用 Hermes skills 管理页面;mnote 只暴露 mnote.* tool manifest
不属于 mnote 页面 AI 第一版 packages/client/src/views/hermes/ChannelsView.vueJobsView.vueFilesView.vueTerminalView.vueGroupChatView.vueSettingsView.vueProfilesView.vueLogsView.vueUsageView.vue 仅作为边界参考,说明这些是 Hermes 管理台能力 不进入页面 AI 抽屉第一版

2. 总体验收标准

7-4 完成时必须同时满足:

  • 页面 AI 抽屉打开后创建或恢复的是 Hermes session。
  • Hermes session 存储里能看到页面 AI 的消息历史。
  • mnote 本地不保存聊天消息真相,只保存业务写入 audit、artifact、edge、page/body/title/options 结果。
  • 页面 AI 发送消息后,事件流来自 Hermes run,而不是旧 /api/ai-agent/run provider / fallback 分支。
  • tool call 展示来自 Hermes tool event;真实 Hermes upstream run 已触发 mnote.page.get,刷新后从 Hermes session detail 恢复。
  • Hermes 至少能调用一个只读 mnote 工具读取当前页面。
  • Hermes 至少能调用一个写入 mnote 工具,经 Rust runtime 写回当前页面正文或创建 artifact。
  • 页面刷新后,AI 会话从 Hermes 恢复,而不是从 mnote 本地 state 恢复。
  • provider=hermes 502 不再出现在新页面 AI 主链。
  • rg 检查活跃设计稿与代码注释不再把 mnote-cli 写成页面 AI 唯一长期执行面;命中已逐条归类为历史/兼容/已覆盖。

最终验收命令建议:

cd /mnt/Data1T/mnote
rg -n "mnote-cli.*唯一|唯一长期 agent|页面 AI.*mnote-cli|provider=hermes" design rust wolai-frontend --glob '*.md' --glob '*.rs' --glob '*.ts' --glob '*.tsx'
MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-smoke.js
MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-tool-smoke.js

通过标准:

  • rg 只允许命中 design/old/ 或明确标注“历史/兼容/已覆盖”的段落。
  • task-hermes-page-ai-smoke.js 证明页面 AI 使用 Hermes session / run / stream,并验证刷新后从 Hermes session detail 恢复。
  • task-hermes-page-ai-tool-smoke.js 证明 Hermes tool call 能回到 mnote Rust runtime 并产生可读业务结果。

2026-05-14 验证记录:

  • cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web hermes_ -- --nocapture15 passed。
  • MNOTE_UI_BASE_URL=http://127.0.0.1:3019 node scripts/task-hermes-page-ai-smoke.js:通过,捕获 session -> session-detail -> run -> events -> session-detail,渲染 mnote.page.get tool event,刷新恢复命中 Hermes session detail 2 次。
  • MNOTE_UI_BASE_URL=http://127.0.0.1:3019 node scripts/task-hermes-page-ai-tool-smoke.js:通过,mnote.page.get 返回标题、正文摘要和 read audit。
  • MNOTE_UI_BASE_URL=http://127.0.0.1:3019 node scripts/task-hermes-page-ai-writeback-smoke.js:通过,mnote.page.save 写入走 page.body.save
  • MNOTE_UI_BASE_URL=http://127.0.0.1:3019 node scripts/task-hermes-page-ai-title-options-smoke.js:通过,标题走 page.head.updateTitle,页面设置走 page.layout.updateOptions
  • MNOTE_UI_BASE_URL=http://127.0.0.1:3019 node scripts/task-hermes-page-ai-artifact-smoke.js:通过,summary / ai_note 都走 tree.node.create
  • 早期临时 3019 验证曾确认旧 /api/ai-agent/run 不再静默 fallback;最终正式 3000 验收已由 Task K/M 覆盖,当前稳定退场码为 410 legacy_ai_agent_run_retired
  • 上述临时 3019 证据已被正式 http://127.0.0.1:3000 全矩阵复跑覆盖;最终以 Task M 的 8 个 3000 smoke 证据为准。
  • 追加验证:task-hermes-page-ai-writeback-smoke.jstask-hermes-page-ai-title-options-smoke.jstask-hermes-page-ai-artifact-smoke.js 已断言 audit.commandId == result.commandId,临时 3019 通过。
  • 追加验证:临时 3019 日志已输出 mnote Hermes tool call started/completed,字段包含 trace_id/session_id/run_id/tool_call_id/tool_name/workspace_id/document_id/actor_id/effect
  • 追加验证:MNOTE_UI_BASE_URL=http://127.0.0.1:3019 node scripts/task-hermes-page-ai-mobile-smoke.js 通过,390px 窄屏下 drawer / panel / document 均无横向溢出。
  • 追加验证:task-hermes-page-ai-writeback-smoke.js 已在 dryRun 后立即读取 /api/documents/content,确认写入标记不存在;随后正式写入再确认标记存在。
  • 追加验证:hermes_tools_write_tools_require_auth 已覆盖未认证写工具返回 401。
  • 追加验证:task-hermes-page-ai-writeback-smoke.js 已用同一 idempotencyKey 重试正式写入,断言返回同一 result.commandId/audit.commandId;临时 3019 日志出现 mnote Hermes tool call idempotency replay
  • 追加验证:task-hermes-page-ai-title-options-smoke.js 已打开真实文档页,确认刷新后标题输入、breadcrumb/current title、data-page-wide-layout=truedata-page-small-text=true 均生效。
  • 追加验证:MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-title-options-smoke.js 通过,tree_1778720870666_1 标题更新为 TEST-HERMES-AI-title-updated-mp4shbjq,页头 / breadcrumb/current title / sidebar 均一致。
  • 追加验证:task-hermes-page-ai-title-options-smoke.js 已断言 pageFont 返回 ignoredOptions=["pageFont"]warningCodes=["page_option_not_wired"],不进入 page.layout.updateOptions 写入 payload。
  • 追加验证:task-hermes-page-ai-title-options-smoke.js 已打开页面 AI 面板,确认 data-mnote-page-ai-session-owner=hermesmnote localStorage 只保存 Hermes activeSessionId,不保存或驱动 mnote 页面标题真相。
  • 追加验证:task-hermes-page-ai-title-options-smoke.js 已验证 mnote.page.update_title dryRun 后 meta 不变化,并验证同一 idempotencyKey 重试返回同一 commandId
  • 追加验证:task-hermes-page-ai-artifact-smoke.js 已验证 summary 同 key 重试返回同一 commandId/artifactDocumentIdai_note 第二次创建得到独立 artifactDocumentId,并验证工具结果里的 referenceEdge.from/to/kind
  • 追加验证:task-hermes-page-ai-audit-smoke.js 已调用 mnote.page.getmnote.page.save,并通过 /api/hermes/tools/mnote/audit?traceId=... 反查 started/completed 事件,写工具 audit 可串到 Rust commandId,且不包含完整正文内容。

3. Task A:运行态基线与旧 502 复现

目标:

先固定当前问题和旧链入口,避免后续改动时把“没有复现”误认为“已经修好”。

建议修改范围:

  • 新增或复用 smoke
    • scripts/task-hermes-page-ai-baseline-smoke.js
  • 只读记录:
    • rust/crates/mnote-web/src/routes/**
    • wolai-frontend/src/**/ai-agent/**
    • design/07-ai/done/7-3-page-ai-hermes-panel-and-mnote-plugin-v1.md

执行步骤:

  • 启动当前前后端,确保测试入口可访问。
  • 用真实测试账号登录。历史执行时使用旧 Auth 后端;当前默认应使用 SQLite control-plane Auth / session。
  • 打开任意测试页面,点击右下角页面 AI。
  • 发送一条只读问题,例如“概括当前页面标题和第一段”。
  • 记录当前请求是否仍命中旧 /api/ai-agent/run
  • 记录是否出现 provider=hermes 相关 502、ai_provider_bridge_unavailable 或旧 fallback 文案。
  • 将证据写入本 task 对应 bug 或执行记录,不修改业务逻辑。

验收标准:

  • 有一份可复跑 smoke 或手动执行记录,明确当前页面 AI 主请求 URL。
  • 能区分以下三类状态:
    • /api/ai-agent/run 仍被页面 AI 调用。
    • 页面 AI 已调用 Hermes proxy,但 proxy 未接通。
    • 页面 AI 已调用 Hermes proxy 且 session/run 可恢复。
  • 若仍出现 502,记录请求 URL、响应 body、mnote-web 日志时间戳和页面截图。
  • 不把本 task 的 502 修复写进同一个提交;本 task 只做基线。

4. Task B:冻结 Hermes client proxy 合同

目标:

先冻结浏览器到 mnote-web 的同源 Hermes client proxy 合同,防止 Leptos 面板直接绑定 Hermes 私有 API 或暴露 key。

建议修改范围:

  • 新增设计/协议文档:
    • design/07-ai/done/7-5-hermes-client-proxy-contract-v1.md
  • 后续代码位置建议:
    • rust/crates/mnote-web/src/routes/hermes_client.rs
    • rust/crates/mnote-web/src/routes/mod.rs
    • rust/crates/mnote-web/src/config.rs

合同路径第一版:

  • GET /api/hermes/client/sessions
  • POST /api/hermes/client/sessions
  • GET /api/hermes/client/sessions/{session_id}
  • POST /api/hermes/client/runs
  • GET /api/hermes/client/events/{run_id}
  • POST /api/hermes/client/runs/{run_id}/abort
  • GET /api/hermes/client/models
  • GET /api/hermes/client/tools

必须统一的请求字段:

  • workspaceId
  • documentId
  • sessionId
  • message
  • pageContext
  • selectedBlockId
  • selectedText
  • traceId

必须统一的响应字段:

  • sessionId
  • runId
  • messageId
  • events[]
  • error.code
  • error.message
  • traceId

执行步骤:

  • 写明每个 proxy route 的输入输出 JSON 示例。
  • 写明 proxy 只做 auth、同源安全、上下文注入和错误码标准化。
  • 写明 proxy 不保存 session/message/tool event。
  • 写明 Hermes API key 或 token 只存在服务端环境变量中。
  • 写明 pageContext 是运行输入,不是 Hermes session 的长期事实源。
  • 写明旧 /api/ai-agent/run 与新 proxy 的并存期规则。

验收标准:

  • 合同文档里每个 route 都有请求/响应示例。
  • 文档明确禁止浏览器直接持有 Hermes API key。
  • 文档明确禁止 mnote 保存 Hermes 聊天历史。
  • 文档明确旧 /api/ai-agent/run 不是新 Hermes 面板主代理。
  • 后续实现者不需要读 Hermes Web UI 源码也能知道 mnote 侧 proxy 的稳定合同。

5. Task C:实现 Hermes client proxy 最小只读链

目标:

让页面 AI 可以通过 mnote-web 同源代理创建/恢复 Hermes session,并发起一个无工具写入的只读 run。

建议修改范围:

  • 新增:
    • rust/crates/mnote-web/src/routes/hermes_client.rs
  • 修改:
    • rust/crates/mnote-web/src/routes/mod.rs
    • rust/crates/mnote-web/src/config.rs
    • rust/crates/mnote-web/src/error.rs
  • 测试:
    • rust/crates/mnote-web/tests/hermes_client_proxy.rs 或同 crate 现有 route 测试文件

执行步骤:

  • 先写 route 测试:未登录请求返回 401 或项目统一 auth 错误。
  • 写 route 测试:未配置 Hermes upstream 时返回稳定错误码 hermes_client_unconfigured
  • 写 route 测试:POST /api/hermes/client/sessions 只代理 session 创建,不写 mnote 数据。
  • 写 route 测试:POST /api/hermes/client/runs 会带上 workspaceId/documentId/pageContext/traceId
  • 实现最小 upstream client,先只支持 session create、session get、run create。
  • 统一错误响应:Hermes 连接失败、401、429、5xx 必须映射成可展示的错误码。
  • 记录日志字段:traceId/sessionId/runId/documentId/workspaceId

验收标准:

  • cargo test -p mnote-web hermes_client 通过。
  • 未配置 Hermes 时,页面 AI 不出现 502,而是得到稳定 hermes_client_unconfigured
  • 配置 Hermes upstream 后,session create 和 run create 请求能从 mnote-web 代理到 Hermes。
  • mnote 数据库、page aggregate、Convex 页面内容没有新增聊天消息字段。
  • 网络请求中浏览器看不到 Hermes API key。

6. Task D:冻结 mnote Hermes plugin tool 合同

目标:

先定义 Hermes 看到的 mnote 工具清单和工具结果格式,避免工具从页面前端私有函数开始长出来。

建议新增文档:

  • design/07-ai/done/7-6-mnote-hermes-plugin-tool-contract-v1.md

第一批工具:

  • mnote.page.get
  • mnote.page.save
  • mnote.page.update_title
  • mnote.page.update_options
  • mnote.artifact.create_summary
  • mnote.artifact.create_ai_note

第二批工具:

  • mnote.tree.create
  • mnote.tree.move
  • mnote.search.documents
  • mnote.kernel.attach_reference

统一入参:

  • workspaceId
  • documentId
  • actorId
  • sessionId
  • runId
  • toolCallId
  • traceId
  • idempotencyKey
  • dryRun
  • capabilityScope

统一出参:

  • ok
  • toolName
  • toolCallId
  • traceId
  • result
  • audit
  • error

执行步骤:

  • 为每个第一批工具写 JSON schema。
  • 为每个第一批工具写成功响应示例。
  • 为每个第一批工具写失败响应示例。
  • 写明权限校验点:登录、workspace member、页面读、页面写、artifact 写。
  • 写明幂等规则:同一 idempotencyKey 重试不得重复创建 artifact。
  • 写明 dryRun=true 时只能返回计划和 diff,不得写入。
  • 写明 plugin 内部可以暂时调用 mnote-cli JSON adapter,但对 Hermes 暴露的名字必须是 mnote.*

验收标准:

  • 合同文档覆盖所有第一批工具。
  • 每个写工具都有 dryRunidempotencyKey、权限失败、业务失败示例。
  • 文档明确 tool 结果最终来自 Rust runtime / kernel。
  • 文档明确 Hermes plugin 不直接写 Convex。
  • 文档明确 mnote-cli 是内部 adapter,不是 Hermes 看到的长期 tool 名称。

7. Task E:实现 mnote tool manifest 与只读工具

目标:

先让 Hermes 能发现 mnote 工具,并调用 mnote.page.get 读取当前页面。

建议修改范围:

  • 新增:
    • rust/crates/mnote-web/src/routes/hermes_tools.rs
    • rust/crates/mnote-web/src/hermes_tools/mod.rs
    • rust/crates/mnote-web/src/hermes_tools/manifest.rs
    • rust/crates/mnote-web/src/hermes_tools/page.rs
  • 修改:
    • rust/crates/mnote-web/src/routes/mod.rs
    • rust/crates/bridge-runtime/src/lib.rs 只在缺少正式 query 时补窄入口
  • 测试:
    • rust/crates/mnote-web/tests/hermes_tools.rs

建议 route

  • GET /api/hermes/tools/mnote/manifest
  • POST /api/hermes/tools/mnote/call

执行步骤:

  • 写 manifest 测试:返回第一批工具名称、schema version、capability scope。
  • mnote.page.get 测试:未登录失败。
  • mnote.page.get 测试:无 workspace 权限失败。
  • mnote.page.get 测试:有权限时返回当前 page aggregate 摘要。
  • 实现 manifest route。
  • 实现统一 tool call dispatcher,只接 mnote.page.get
  • mnote.page.get 接到现有 Rust runtime / page aggregate query。

验收标准:

  • cargo test -p mnote-web hermes_tools 通过。
  • GET /api/hermes/tools/mnote/manifest 返回稳定 mnote.page.get schema。
  • POST /api/hermes/tools/mnote/call 调用 mnote.page.get 返回当前页面标题、正文摘要、page options、可用 block 摘要。
  • 权限失败不会泄露页面标题或正文。
  • 工具返回中包含 traceId/toolCallId/sessionId

8. Task FLeptos Hermes 面板最小只读 UI

目标:

在保留 Wolai 右下角入口和右侧抽屉壳的前提下,把页面 AI 面板改为调用 Hermes client proxy。

建议修改范围:

  • Leptos / Rust SSR 侧按当前真实结构定位:
    • rust/crates/mnote-web/src/ssr/**
    • rust/crates/mnote-web/src/routes/web_shell.rs
    • 页面内 island 挂载资源所在目录
  • 若仍需 React compat,只能作为旧 panel 参考,不得扩展旧执行链:
    • wolai-frontend/src/components/editor/DocumentAiAgentPanel.runtime.tsx
  • smoke
    • scripts/task-hermes-page-ai-smoke.js

第一版 UI 子集:

  • session 创建/恢复
  • message list
  • chat input
  • streaming delta
  • reasoning 展开
  • tool started / completed 展开
  • error / retry / abort
  • model selector 可先只读展示默认模型

执行步骤:

  • 写 smoke:打开页面 AI 后,不允许发送请求到 /api/ai-agent/run
  • 写 smoke:打开页面 AI 后,会请求 /api/hermes/client/sessions
  • 写 smoke:发送消息后,会请求 /api/hermes/client/runs
  • 写 smoke:页面刷新后,面板可从 Hermes session 恢复消息。
  • 实现 Leptos 面板数据层,只保存 UI 临时状态,不保存聊天真相。
  • 接入 session create / restore。
  • 接入 run create / event stream。
  • 接入 abort / retry 的最小状态。
  • 保留右下角入口、右侧 drawer、Esc / close 行为与 5-11 证据一致。

验收标准:

  • node scripts/task-hermes-page-ai-smoke.js 通过。
  • 页面 AI 主链不再请求 /api/ai-agent/run
  • 页面 AI 消息刷新后来自 Hermes session。
  • mnote 本地页面 state 里没有完整聊天消息数组。
  • 抽屉入口、关闭语义、移动端不溢出继续符合 5-11 的历史 Wolai 对齐要求。
  • Hermes 不可用时展示稳定错误态,不出现 502 空白或旧 page_ai_failed_502

9. Task G:接入 Hermes tool event 展示与只读工具调用

目标:

让 Hermes run 调用 mnote.page.get 时,页面 AI 能展示 tool started / completed,并把结果作为 Hermes 消息链的一部分呈现。

建议修改范围:

  • rust/crates/mnote-web/src/routes/hermes_client.rs
  • rust/crates/mnote-web/src/routes/hermes_tools.rs
  • Leptos 面板 island 相关文件
  • scripts/task-hermes-page-ai-tool-smoke.js

执行步骤:

  • 写 smoke:发送“读取当前页面标题和页面设置”,期望出现 mnote.page.get tool started。
  • 写 smoke:同一次 run 出现 mnote.page.get tool completed。
  • 写 smoketool result 中的标题与当前页头标题一致。
  • 实现 tool event 渲染:started、completed、failed 三态。
  • 实现 tool result 折叠展示,默认只显示 tool 名和摘要。
  • 确保 tool result 不被写入 mnote 页面正文。
  • 确保 Hermes session 中保留 tool event,刷新后可恢复。

验收标准:

  • node scripts/task-hermes-page-ai-tool-smoke.js 通过。
  • 工具事件来自真实 Hermes upstream run,而不是前端本地伪造。
  • mnote.page.get 权限失败时,UI 显示 tool failed,正文不泄露。
  • 刷新页面后 tool event 仍从 Hermes session 恢复。
  • mnote page aggregate 不包含 tool event 历史。

10. Task H:接入正文写入工具 mnote.page.save

目标:

让 Hermes 可以通过 mnote plugin 对当前页正文做最小写入,写入仍走正式 page.body.save 链。

建议修改范围:

  • rust/crates/mnote-web/src/hermes_tools/page.rs
  • rust/crates/bridge-runtime/src/lib.rs 仅补必要正式 command adapter
  • 页面保存相关 route / command adapter
  • smoke
    • scripts/task-hermes-page-ai-writeback-smoke.js

执行步骤:

  • 写 tool contract 测试:mnote.page.save 必须要求 documentIdidempotencyKeydryRun
  • 写 dryRun 测试:dryRun=true 返回 diff,不写入。
  • 写权限失败测试:未认证时不进入页面写链。
  • 写幂等测试:同一 idempotencyKey 重试不重复执行写链。
  • 实现 mnote.page.savepage.body.save 的 adapter。
  • 在 Hermes 面板里对写工具结果展示 diff 摘要。
  • smoke 执行:让 AI 在当前测试页面写入一段带测试前缀的文本。
  • smoke 读取 /api/documents/content 或当前正式内容接口,确认刷新后文本存在。

验收标准:

  • dryRun 不改变页面内容。
  • 未认证不进入写链。
  • 同一幂等键不会重复写入。
  • 正式写入后,主编辑区 island 能立即回显。
  • 刷新后内容仍存在。
  • 写入链路日志包含 sessionId/runId/toolCallId/traceId/documentId/actor
  • 写入不经过旧 /api/ai-agent/run

11. Task I:接入标题与页面设置工具

目标:

把 AI 修改标题和页面设置收口到同一组 Page Aggregate command family,而不是靠面板本地副作用。

建议修改范围:

  • rust/crates/mnote-web/src/hermes_tools/page.rs
  • rust/crates/bridge-runtime/src/lib.rs
  • design/05-editor-mainline/process/5-6-page-aggregate-alignment-checklist-v1.md 仅回填完成证据
  • smoke
    • scripts/task-hermes-page-ai-title-options-smoke.js

执行步骤:

  • mnote.page.update_title dryRun / permission / idempotency 测试。
  • mnote.page.update_options dryRun / permission / wired-only 字段测试。
  • 实现标题工具到 page.head.updateTitle
  • 实现页面设置工具到 page.layout.updateOptions
  • 禁止写入 runtimeSupport !== "wired" 的页面设置字段。
  • smoke 修改当前测试页标题,确认页头与 breadcrumb/current title 一致。
  • smoke 修改 smallTextwideLayout,确认主编辑区 page shell 属性变化。

验收标准:

  • 标题修改后页头、breadcrumb、sidebar、刷新后标题一致。
  • 页面设置修改只允许 wired 字段。
  • planned / ui_only 字段返回明确错误或 dryRun 警告。
  • AI 面板不维护独立标题状态。
  • 所有写入都经 Rust runtime / Page Aggregate command family。

12. Task J:接入结构化 Artifact 工具

目标:

落地 7-2summary node / ai_note node / reference edge,触发方改为 Hermes tool call。

建议修改范围:

  • rust/crates/mnote-web/src/hermes_tools/artifact.rs
  • rust/crates/bridge-runtime/src/lib.rs
  • rust/crates/core-protocol/src/** 若缺少正式类型再补
  • smoke
    • scripts/task-hermes-page-ai-artifact-smoke.js

执行步骤:

  • mnote.artifact.create_summary schema 测试。
  • mnote.artifact.create_ai_note schema 测试。
  • 写 summary 单例更新测试:同一页面重复创建 summary 不生成多个 summary node。
  • 写 ai_note 多次创建测试:每次生成独立 ai_note node。
  • 写 reference edge 测试:artifact 与当前页面之间有可查询 reference edge。
  • 实现工具到 Rust runtime / kernel。
  • 页面 AI 面板可提供 创建 Summary / 创建 AI Note 快捷入口,但入口只发送 Hermes intent。
  • smoke 验证 AI Artifacts projection-only 分组可见。

2026-05-14 J1 执行证据:

  • 修正 rust/crates/bridge-runtime/src/lib.rs:从 artifact 文档命名与父子关系派生 metadata.kind="ai_artifact_reference"source_of kernel edge,并在 file-tree projection meta.aiArtifacts 中标记 projectionOnly=truekernelNodeId=null
  • 新增 bridge-runtime 单测 kernel_edges_list_exposes_ai_artifact_reference_edgesfile_tree_projection_marks_ai_artifacts_group_as_projection_only
  • 验证命令:cd rust && cargo test -p bridge-runtime ai_artifact -- --nocapture2 passed。
  • 验证命令:cd rust && cargo build -p mnote-web:通过;正式 3000 已重启到新二进制,PID 2043001
  • 扩展 scripts/task-hermes-page-ai-artifact-smoke.js:调用 /api/kernel/edges 查询 summary / ai_note 的 ai_artifact_reference,调用 /api/tree/projections/file 查询 meta.aiArtifacts.projectionOnly=true,并回查 artifact audit。
  • 修正 rust/crates/mnote-web/src/ssr/pages/layout.rsrust/crates/mnote-web/src/ssr/styles.rs:页面 AI 抽屉提供 创建 Summary / 创建 AI Note 快捷入口,点击后只调用 sendPageAiMessage(...) 发送 Hermes intent。
  • 验证命令:MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-artifact-smoke.js:通过;最终复跑测试页 tree_1778721933687_1summary summary_tree_1778721933687_1ai_note ai_note_tree_1778721933687_1_req_1778721933785_11ai_note_tree_1778721933687_1_req_1778721933813_13referenceEdgeCount=6auditEventCount=6;快捷入口发送的 Hermes intent 分别包含 mnote.artifact.create_summarymnote.artifact.create_ai_note,且页面路由已禁止直连 /api/hermes/tools/mnote/call

验收标准:

  • artifact 创建不绕过 Hermes tool call。
  • artifact 创建不绕过 Rust runtime / kernel。
  • AI Artifacts 仍是 projection-only 分组,不是真实 kernel node。
  • summary node 可重复更新但不重复创建。
  • ai_note node 每次新建。
  • reference edge 可通过 kernel query 或 projection 验证。
  • artifact 写入 audit 包含 Hermes sessionId/runId/toolCallId

13. Task K:退役旧页面 AI 主执行链

目标:

新 Hermes 面板通过后,旧 /api/ai-agent/run 不再作为页面 AI 主入口。

建议修改范围:

  • rust/crates/mnote-web/src/routes/**
  • wolai-frontend/src/app/api/ai-agent/run/route.ts
  • wolai-frontend/src/components/editor/DocumentAiAgentPanel.runtime.tsx
  • design/03-rust-web/process/3-15-runtime-fallback-retirement-checklist-v1.md

执行步骤:

  • 全仓搜索页面 AI 发送路径。
  • 删除或禁用页面 AI 对 /api/ai-agent/run 的主路径调用。
  • 保留 legacy endpoint 时,响应必须明确 legacy_ai_agent_run_retired 或项目统一退场码。
  • 删除 provider=hermes 作为旧 endpoint provider/fallback 的语义。
  • 更新旧 smoke:不再期待 /api/ai-agent/run -> mnote-cli
  • 保留历史 smoke 到 old 或改名为 legacy guard。

2026-05-14 K 执行证据:

  • 修正 rust/crates/mnote-web/src/routes/compat.rsPOST /api/ai-agent/run 不再进入 mnote-cli host,统一返回 410 legacy_ai_agent_run_retired,响应头 x-mnote-ai-execution-owner=legacy-ai-agent-run-retired
  • 更新 compat 单测:direct_ai_agent_run_returns_legacy_retired_guardexplicit_agent_provider_returns_legacy_retired_guardexplicit_hermes_provider_fails_instead_of_using_legacy_next_or_direct_bridge
  • 验证命令:cd rust && cargo test -p mnote-web ai_agent_run -- --nocapture1 passed。
  • 验证命令:cd rust && cargo test -p mnote-web explicit_ -- --nocapture2 passed。
  • 验证命令:cd rust && cargo build -p mnote-web:通过;正式 3000 已重启到新二进制,PID 2108896
  • 验证命令:MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-retirement-guard.js:通过,status 410code legacy_ai_agent_run_retiredowner legacy-ai-agent-run-retired
  • 默认退役历史 smoketask155-e27-ai-edit-smoke.jstask156-e27-ai-writeback-smoke.jstask178-page-ai-local-subtree-context-smoke.jstask052-ai-tools-runtime-smoke.jstask161-wolai-page-ai-shell-smoke.jstask111-phase7-document-ai-online-smoke.js 已移入本机 gitignored recycle/scripts/retired-ai-agent-run-smokes/,历史版本默认输出 { retired: true },不再期待旧 /api/ai-agent/run -> mnote-cli 成功;如需历史对照,必须显式设置 MNOTE_ALLOW_RETIRED_AI_AGENT_RUN_SMOKE=1
  • legacy 调用方清点:wolai-frontend/src/components/ai-agent/AiAgentPanel.tsxwolai-frontend/src/components/editor/blocks/MindmapAiAgentPanel.runtime.tsxwolai-frontend/src/components/onlyoffice/OnlyOfficeAiAgentPanel.runtime.tsxwolai-frontend/src/app/api/mindmap-ai/expand-node/route.ts 仍是旧域/兼容调用点,不属于当前 mnote-web 页面 AI 主链;若被调用会命中 legacy_ai_agent_run_retired guard,后续按各自 domain 另拆 Hermes plugin / Rust bridge 迁移。
  • 活跃设计口径同步:5-65-910-review 已改为历史/已覆盖/legacy guard 说明,不再把 /api/ai-agent/run 写作页面 AI 长期入口。

验收标准:

  • 新页面 AI 主链无 /api/ai-agent/run 请求。
  • 访问旧 /api/ai-agent/run 不会静默 fallback 到 Hermes、Codex、旧 orchestrator。
  • provider=hermes 不再产生新页面 AI 主链 502。
  • 活跃文档不再把 /api/ai-agent/run 描述为页面 AI 长期入口。
  • legacy 调用方清单为空,或全部有明确退场说明。

14. Task L:权限、审计与可观测性闭环

目标:

让 Hermes 调用 mnote 工具后的每一次业务影响都可审计、可追踪、可复盘。

建议修改范围:

  • rust/crates/mnote-web/src/hermes_tools/**
  • rust/crates/bridge-runtime/src/**
  • audit / event log 相关 crate 或 route
  • smoke
    • scripts/task-hermes-page-ai-audit-smoke.js

执行步骤:

  • 定义统一 trace 字段:traceId/sessionId/runId/toolCallId/documentId/workspaceId/actorId/toolName
  • 所有 tool call 开始时记录 intent。
  • 所有成功写入记录 result 和 command id。
  • 所有失败记录错误码,不记录完整隐私正文。
  • smoke 执行一次 mnote.page.get 和一次写工具。
  • smoke 从日志或审计接口确认两次 tool call 都可追踪。

2026-05-14 L 执行证据:

  • 修正 rust/crates/mnote-web/src/routes/hermes_tools.rsaudit_push 同步写入内存缓存与 JSONL 持久化落点,默认路径 tmp/mnote-hermes-tool-audit.jsonl,可用 MNOTE_HERMES_TOOL_AUDIT_LOG 覆盖;GET /api/hermes/tools/mnote/audit?persistedOnly=true 只读取持久化审计。
  • workspace 上下文冲突现在也会写入 started -> failed 审计链,失败审计只包含 trace / tool / actor / workspace / document / status / message,不写入页面标题或正文。
  • 扩展 scripts/task-hermes-page-ai-audit-smoke.js:执行 mnote.page.getmnote.page.save、workspace 权限失败三类调用;分别查询内存 audit 与 persistedOnly=true audit;断言写工具持久化 audit 串到 Rust commandId,权限失败持久化 audit 不包含正文 marker 或页面标题。
  • 验证命令:cd rust && cargo test -p mnote-web hermes_tools_ -- --nocapture9 passed。
  • 验证命令:cd rust && cargo build -p mnote-web:通过;正式 3000 已重启到新二进制,PID 2175265
  • 验证命令:MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-audit-smoke.js:通过;测试页 tree_1778723140835_1,写命令 page_body_save_req_1778723140928_9writePersistedPhases=["started","completed"]deniedPersistedPhases=["started","failed"]

验收标准:

  • 每个 tool call 都有稳定 trace。
  • 写工具能追踪到最终 Rust command。
  • 失败不会泄露无权限页面内容。
  • 日志可以把页面 AI 面板请求、Hermes run、mnote tool call、Rust command 串起来。
  • 审计只保存业务影响,不保存完整 Hermes 聊天历史。

15. Task M:端到端验收矩阵

目标:

用一组固定 smoke 证明新主线能覆盖只读、写正文、写标题/设置、artifact 和旧链退役。

必须具备的 smoke

  • scripts/task-hermes-page-ai-smoke.js
  • scripts/task-hermes-page-ai-tool-smoke.js
  • scripts/task-hermes-page-ai-writeback-smoke.js
  • scripts/task-hermes-page-ai-title-options-smoke.js
  • scripts/task-hermes-page-ai-artifact-smoke.js
  • scripts/task-hermes-page-ai-retirement-guard.js
  • scripts/task-hermes-page-ai-mobile-smoke.js
  • scripts/task-hermes-page-ai-audit-smoke.js

执行顺序:

  • 只读 session/run smoke。
  • 只读 tool smoke。
  • 正文写入 smoke。
  • 标题与页面设置 smoke。
  • artifact smoke。
  • 旧链退役 guard。
  • 移动端 / 窄屏抽屉 smoke。
  • 刷新恢复 smoke。

2026-05-14 M 执行证据:

  • MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-smoke.js:通过;tree_1778723249255_3session mnote_smoke_mp4twavirun run_smoke_mp4twavisessionDetailHits=2
  • MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-tool-smoke.js:通过;tree_1778723260375_5,工具 mnote.page.get,标题 TEST-HERMES-AI-tool-mp4twjgi
  • MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-writeback-smoke.js:通过;tree_1778723271226_7marker TEST-HERMES-AI-WRITEBACK-mp4twrttcommand page_body_save_req_1778723271849_379
  • MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-title-options-smoke.js:通过;tree_1778723295128_9,标题 TEST-HERMES-AI-title-updated-mp4txa9vpageFont 返回 page_option_not_wired warning。
  • MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-artifact-smoke.js:通过;tree_1778723316873_11referenceEdgeCount=6meta.aiArtifacts.projectionOnly=true
  • MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-retirement-guard.js:通过;旧入口返回 410 legacy_ai_agent_run_retired
  • MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-mobile-smoke.js:通过;390px viewport 下 drawer/panel 均无横向溢出。
  • MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-audit-smoke.js:通过;tree_1778723372948_15,写命令 page_body_save_req_1778723373026_707,持久化 audit 可查 started/completed 与权限失败 started/failed

总体验收标准:

  • 所有 smoke 在真实 http://127.0.0.1:3000 上通过。
  • 使用默认真实测试账号,不使用 MNOTE_DEV_AUTH=1 伪登录作为正式验收。历史执行时使用旧 Auth 后端;当前默认应使用 SQLite control-plane Auth / session。
  • smoke 只操作本轮新建测试数据,测试数据前缀统一为 TEST-HERMES-AI-<timestamp>
  • 测试结束后可定位创建的页面、artifact、edge、audit。
  • 任一 smoke 失败时,必须记录到 bugs/ 对应分类,而不是在 checklist 中直接标 GREEN。

16. Task N:文档回填与 old 目录治理

目标:

代码主链切换后,设计目录继续反映真实状态,避免旧 CLI-first 口径回流。

2026-05-14 口径审计记录:

  • find design/07-ai -maxdepth 3 -type f | sort 已确认当前 07-ai 活跃结构为:7-17-27-37-47-57-6done/;后续 Mini Hermes 控制面由 design/07-ai/process/7-7-page-ai-mini-hermes-control-surface-v1.md 承接。
  • design/old/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md 仍保留为历史决策记录,并已标 [recycle]
  • design/07-ai/done/7-3-page-ai-hermes-panel-and-mnote-plugin-v1.mdmnote-cli 命中均用于说明历史 CLI-first / 被覆盖 / 禁止继续采用的口径。
  • design/07-ai/done/7-4-page-ai-hermes-panel-execution-checklist-v1.mdmnote-cliprovider=hermes 命中均用于迁移目标、legacy guard 或验收条件,不把它写成长期主线。
  • 活跃设计命中已收口:5-65-910-review/0410-review/061-13-1 均已把旧 /api/ai-agent/run / mnote-cli host 写成历史、兼容、已覆盖或 legacy guard。
  • design/10-review/04-secondary-domains-and-design-governance-review.md 已继续指向 Hermes plugin / Rust bridge,并明确旧 openai-agents-python / mnote-cli host 只按历史/兼容/对照链处理。

建议修改范围:

  • design/07-ai/done/7-3-page-ai-hermes-panel-and-mnote-plugin-v1.md
  • design/07-ai/done/7-4-page-ai-hermes-panel-execution-checklist-v1.md
  • design/03-rust-web/process/3-rust-web-long-term-architecture-v1.md
  • design/03-rust-web/process/3-15-runtime-fallback-retirement-checklist-v1.md
  • design/05-editor-mainline/process/5-6-page-aggregate-alignment-checklist-v1.md
  • design/05-editor-mainline/process/5-9-wolai-aline-continuous-checklist-v1.md
  • design/old/07-ai/process/*

执行步骤:

  • 把完成证据回填到本 checklist 对应 task。
  • 7-4 的实现证据已满足完成定义,本文已归档到 design/07-ai/done/ 并同步更新引用。
  • 保留 7-3 为主线设计稿;7-4 作为实现与验收执行清单,不覆盖 7-3 的架构口径。
  • 活跃设计稿中只允许历史、兼容、已覆盖或 legacy guard 说明提到 mnote-cli host
  • 旧 CLI-first 文档必须继续留在 design/old/07-ai/process/ 并标 [recycle]
  • 更新 design/10-review 中旧建议,使其指向 Hermes plugin / Rust bridge。

验收标准:

  • find design/07-ai -maxdepth 3 -type f | sort 能清楚看到当前 process/done 状态。
  • rg -n "mnote-cli.*唯一|唯一长期 agent|CLI-first" design --glob '*.md' 的活跃目录命中都带有“历史/回收/已覆盖”说明。
  • design/old/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md 仍保留为历史决策记录。
  • 没有把未完成代码能力提前标成 done。

16.1 剩余顺序执行 checklist(按 G-N 顺序)

这一段只收纳当前仍未完成的项,按顺序逐项勾选。每个 task 都必须在本段回填“执行命令 / 证据路径 / 结果”,不能只写口头结论。

Hermes Web UI 参考目录固定为 /mnt/Data1T/mnote/design/05-editor-mainline/reference-code/hermes-web-ui-0.5.18。下文所有 packages/... 路径都相对此目录。需要对照时按列出的文件和符号打开,不整目录通读,不照搬 Vue / Naive UI / 管理台页面。

G1:把 tool event 刷新恢复补成真实 Hermes upstream 闭环

目标: 证明 mnote.page.get 是由真实 Hermes upstream run 触发,并由 Hermes session 存储回灌;mnote 页面 AI 只消费 Hermes 事件。

必须参考 Hermes Web UI 的位置:

参考目的 具体文件 具体位置 / 搜索点 mnote 采用方式
run 请求与事件字段 packages/client/src/api/hermes/chat.ts StartRunRequest 第 14 行;RunEvent 第 28 行 对齐 mnote proxy / Leptos 面板消费的 run event 字段
session handler 注册 packages/client/src/api/hermes/chat.ts registerSessionHandlers 第 297 行;resumeSession 第 420 行;startRunViaSocket 第 432 行 对齐“按 session 订阅事件、刷新后 resume”的语义
tool event 归并到消息 packages/client/src/stores/hermes/chat.ts mapHermesMessages 第 125 行;case 'tool.started' 第 910 / 1340 行;case 'tool.completed' 第 948 / 1378 行 对齐 tool started / completed 与 session detail 里的消息形态
tool message 展示 packages/client/src/components/hermes/chat/MessageItem.vue message.role === 'tool' 第 508 行;formatToolPayload 第 263 行;tool-preview 第 543 行;tool-details 第 555 行 对齐默认折叠、摘要和详情展开,不照搬样式
upstream tool event 生成 packages/server/src/services/hermes/chat-run-socket.ts applyResponseStreamEvent 第 1035 行;function_call 第 1101 / 1110 行;tool.started 第 1131 行;function_call_output 第 1145 行;tool.completed 第 1165 行;flushResponseRunToDb 第 1207 行 确认 tool event 来源于 upstream response stream,并最终 flush 到 Hermes DB
Hermes plugin 发现 packages/server/src/services/hermes/plugins.ts PluginManager 第 63 / 120 行;user_dir = get_hermes_home() / "plugins" 第 137 行;providesTools 第 200 行;listHermesPlugins 第 310 行 确认 mnote 工具必须进入 Hermes plugin / tool registry

顺序执行 checklist

  • G1.1 运行 hermes plugins list,确认当前 Hermes 是否已经能发现 mnote plugin;把输出摘要回填到本 task。
  • G1.2 运行 hermes tools list --platform api_server,确认 mnote toolset 或 mnote_page_get 是否已经可见;把输出摘要回填到本 task。
  • G1.3 如果 mnote 不可见,创建或修正用户插件目录 /home/lix/.hermes/plugins/mnote/,其中 plugin.yaml 必须声明 name: mnoteprovides_tools__init__.py 必须通过 ctx.register_tool(..., toolset="mnote") 注册工具。
  • G1.4 插件对 Hermes 暴露的函数名使用 OpenAI function-name 兼容名,例如 mnote_page_get;插件内部再映射到 mnote-web tool route 的 toolName: "mnote.page.get"
  • G1.5 插件 handler 只调用 POST http://127.0.0.1:3000/api/hermes/tools/mnote/callMNOTE_UI_BASE_URL 指向的同源 mnote-web route,不直接读写 Convex。
  • G1.6 将 mnote 加入 /home/lix/.hermes/config.yamlplugins.enabled 后,重新运行 hermes plugins listhermes tools list --platform api_server
  • G1.7 触发一次真实 Hermes upstream run,请求内容使用“读取当前页面标题和页面设置”,确认模型实际选择 mnote_page_get / mnote.page.get
  • G1.8 在 mnote 页面 AI 面板网络记录里确认事件来自 /api/hermes/client/runs/api/hermes/client/events/{run_id} 或当前 Hermes proxy 等价入口,不是前端本地拼出的假事件。
  • G1.9 刷新页面后重新打开 AI 面板,确认同一 tool event 从 Hermes session detail 恢复,顺序与首次流式展示一致。
  • G1.10 回填证据:Hermes run id、session id、tool call id、mnote trace id、截图或 smoke 输出路径。

2026-05-14 G1 执行证据:

  • python -m py_compile /home/lix/.hermes/plugins/mnote/__init__.py:通过。
  • hermes plugins listmnote 显示为 enabled user plugin。
  • hermes tools list --platform api_serverPlugin toolsets 中 mnote 显示为 enabled。
  • /home/lix/.hermes/hermes-agent/venv/bin/python 调用 get_tool_definitions(enabled_toolsets=["mnote"]):可见 mnote_page_getmnote_page_savemnote_page_update_titlemnote_page_update_optionsmnote_artifact_create_summarymnote_artifact_create_ai_note
  • 发现并修复运行态差异:Hermes gateway 长进程启动早于 mnote plugin 接入,首次 /v1/runs 只看到 MemPalace 等旧工具;执行 hermes gateway restart 后真实 upstream run 可见 mnote_page_get
  • 3000 主入口已重启为当前 mnote-web,并配置 MNOTE_WEB_HERMES_UPSTREAM_URL=http://127.0.0.1:8642 与服务端 Hermes API keyGET /api/hermes/client/models 经 mnote-web proxy 返回 hermes-agent
  • 修正 rust/crates/mnote-web/src/routes/hermes_client.rsHermes run context 透传 actorId/actorType/sessionId/traceId,并在 toolGuidance 中要求读取标题/页面设置时传 includeBody=false/includeOptions=true/includeBlocks=false
  • 验证命令:cd rust && cargo test -p mnote-web hermes_client_run_body_carries_page_context_into_run_input -- --nocapture1 passed。
  • 验证命令:cd rust && cargo build -p mnote-web:通过。
  • 真实页面 AI 面板不 mock 验证:测试页 TEST-HERMES-AI-realpanel-green-mp4rv3w3,页面 AI 捕获网络请求 POST /api/hermes/client/sessionsGET /api/hermes/client/sessions/{sessionId}POST /api/hermes/client/runsGET /api/hermes/client/events/run_4a8b09db7fbc45b8bb1bbea68b436093,未请求 /api/ai-agent/run
  • Hermes runrun_4a8b09db7fbc45b8bb1bbea68b436093status completedsession mnote_tree_1778719834312_1_page-ai-mp4rv470,输出包含标题 TEST-HERMES-AI-realpanel-green-mp4rv3w3 与页面设置。
  • Hermes session exportmnote_tree_1778719834312_1_page-ai-mp4rv470message_count=4tool_call_count=1assistant tool call 为 mnote_page_getHermes tool call id 为 call_00_5B7fVip245331pk4zYyd5532tool message 内容 ok=truetoolName=mnote.page.get
  • mnote audittrace_1778719842620_2b05ef8600mnote tool call id tool_1778719842620_7687c1860aphase=started/completedeffect=readactorId=a4b72c17-49e3-46d3-8456-24a0a7044d64
  • 刷新恢复:同一页面刷新后重新打开 AI 面板,请求 GET /api/hermes/client/sessions/mnote_tree_1778719834312_1_page-ai-mp4rv470,抽屉文本恢复出 Hermes session 中的页面标题与 tool message。

验收标准:

  • 真实 Hermes upstream run 触发 mnote.page.get,不是直接调用 mnote-web tool smoke 假代替。
  • tool event 通过 Hermes run stream / session detail 回灌到页面。
  • 页面刷新后仍能从 Hermes session detail 恢复同一批 tool event。
  • 前端本地 state 只承担临时渲染,不作为 tool event 最终真相。

H1:补 workspace ACL 负向验证与正文立即回显

目标: 写正文工具必须证明权限失败不泄露、成功写入后主编辑区立即可见,且 AI 面板不保存正文真相。

必须参考 Hermes Web UI 的位置:

参考目的 具体文件 具体位置 / 搜索点 mnote 采用方式
权限失败事件形态 packages/client/src/api/hermes/chat.ts RunEvent 第 28 行;onToolStarted / onToolCompleted 第 69-70 行;onRunFailed 第 73 行 失败也走稳定事件,不出现空白 502
失败事件持久化 packages/server/src/services/hermes/chat-run-socket.ts emit 第 574 / 963 行;markCompleted 第 978 / 1276 行;flushResponseRunToDb 第 1207 行 确认失败信息也能进入可恢复 session
session 只保存消息真相 packages/server/src/db/hermes/session-store.ts HermesMessageRow 第 35 行;addMessage 第 331 行;getSessionDetail 第 313 行 失败消息留在 Hermes session,不写入 mnote 正文
tool failed 展示 packages/client/src/components/hermes/chat/MessageItem.vue tool-error-badge 第 551 行;tool-details 第 555 行 权限失败显示错误摘要,不泄露正文
写入后 UI 刷新边界 packages/client/src/stores/hermes/chat.ts sendMessage 第 646 行;runHadToolActivity 第 737 行;cleanup 附近 tool 完成后刷新业务事实,不复制正文真相到 AI 面板

顺序执行 checklist

  • H1.1 新增或扩展 scripts/task-hermes-page-ai-writeback-smoke.js:构造无 workspace 权限或无页面写权限场景,调用 mnote.page.save
  • H1.2 断言权限失败返回稳定错误码,例如 permission_denied / workspace_access_denied,响应体不得包含页面标题、正文全文或 block 原文。
  • H1.3 在页面 AI 面板断言失败展示为 tool failed / permission denied,不是 502、空白或旧 provider 错误。
  • H1.4 正向写入时,使用测试前缀 TEST-HERMES-AI-<timestamp> 调用 mnote.page.save
  • H1.5 写入完成后不刷新页面,直接断言主编辑区 island 可见新内容。
  • H1.6 刷新页面后再次断言新内容存在,证明业务事实已回到正式正文链。
  • H1.7 检查 AI 面板状态或 session detail,确认不保存完整正文副本,只保存 tool event / tool result 摘要。

2026-05-14 H1 执行证据:

  • 修正 rust/crates/mnote-web/src/routes/hermes_tools.rs:当请求头 x-mnote-workspace-id 与 tool payload workspaceId 不一致时,返回 403 workspace_context_conflict,不进入页面读写链。
  • 新增单测 hermes_tools_reject_workspace_context_conflict_without_content_leak:断言响应不包含测试 fixture 标题 服务端页面 与正文 章节一
  • 验证命令:cd rust && cargo test -p mnote-web hermes_tools_reject_workspace_context_conflict_without_content_leak -- --nocapture1 passed。
  • 扩展 scripts/task-hermes-page-ai-writeback-smoke.js:先构造 workspace 上下文冲突负向调用,断言 403 workspace_context_conflict 且不泄露页面标题 / 正文标记;再用页面 AI 面板 mock Hermes tool.failed 事件断言 UI 展示 mnote.page.savepermission_denied,不是 502 / 空白 / 旧 provider 错误;最后执行 dryRun、正式写入、主编辑区即时回显、幂等重试和刷新后读取。
  • 验证命令:MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-writeback-smoke.js:通过;最终复跑测试页 tree_1778720381778_4,标记 TEST-HERMES-AI-WRITEBACK-mp4s6ubg,写入命令 page.body.savecommandId=page_body_save_req_1778720382427_413
  • smoke 在正式 3000 运行,写入完成后未刷新页面即等待主编辑区出现 TEST-HERMES-AI-WRITEBACK-* 标记;随后通过 /api/documents/content 读取确认刷新后仍存在。

验收标准:

  • 未授权不能写正文,且失败响应不泄露正文。
  • 成功写入后主编辑区即时可见。
  • 刷新后正文仍存在。
  • 页面 AI 不持有正文真相副本。

I1:补标题与 sidebar 一致性验证

目标: mnote.page.update_titlemnote.page.update_options 只改变 mnote 页面事实;Hermes session 标题、模型状态和页面标题不能混成一份真相。

必须参考 Hermes Web UI 的位置:

参考目的 具体文件 具体位置 / 搜索点 mnote 采用方式
session title 只是会话标题 packages/server/src/db/hermes/session-store.ts HermesSessionRow 第 9 行;renameSession 第 202 行 区分 Hermes 会话标题与 mnote 页面标题
session detail 字段 packages/server/src/db/hermes/session-store.ts HermesSessionDetailRow 第 56 行;getSessionDetail 第 313 行 刷新恢复 AI 会话,不恢复页面标题草稿
面板标题展示 packages/client/src/components/hermes/chat/ChatPanel.vue activeSessionTitle 第 193 行;headerTitle 第 197 行;SessionListItem 第 598 / 636 行;MessageList 第 790 行;ChatInput 第 791 行 AI 面板只展示 session 语义,不维护页面标题草稿
session 列表标题 packages/client/src/components/hermes/chat/SessionListItem.vue session-item-title 第 94 行;session.title 第 96 行;session-item-model 第 100 行 不把 sidebar 页面标题同步需求写进 Hermes session list
model 展示边界 packages/client/src/components/layout/ModelSelector.vue selectedDisplayName 第 16 行;handleSelect 第 64 行;model-name 第 105 行;model-item 第 142 行 model 真相不回写 mnote page aggregate

顺序执行 checklist

  • I1.1 扩展 scripts/task-hermes-page-ai-title-options-smoke.js,修改标题为 TEST-HERMES-AI-<timestamp>
  • I1.2 断言页头标题、breadcrumb/current title、sidebar 树节点标题三处立即一致。
  • I1.3 刷新页面后再次断言三处标题一致,且值来自页面真源。
  • I1.4 断言 AI 面板 session 标题没有被当成 mnote 页面标题真相。
  • I1.5 调用 mnote.page.update_options 修改 smallTextwideLayout,确认只接受 runtimeSupport == "wired" 字段。
  • I1.6 对 planned / ui_only 字段执行 dryRun 或正式调用,确认返回明确警告或错误,不产生页面事实写入。

2026-05-14 I1 执行证据:

  • 修正 rust/crates/mnote-web/src/hermes_tools/page.rsmnote.page.update_options 对未接线字段返回 ignoredOptionswarnings,并只把 wired 字段放入 page.layout.updateOptions payload。
  • 扩展单测 hermes_tools_update_options_dry_run_filters_unwired_fields:断言 pageFont 不进入 diff.payload.options,并返回 ignoredOptions[0]="pageFont"warnings[0].code="page_option_not_wired"
  • 验证命令:cd rust && cargo test -p mnote-web hermes_tools_update_options_dry_run_filters_unwired_fields -- --nocapture1 passed。
  • 验证命令:cd rust && cargo build -p mnote-web:通过。
  • 验证命令:MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-title-options-smoke.js:通过;测试页 tree_1778720870666_1,标题 TEST-HERMES-AI-title-updated-mp4shbjq
  • smoke 已断言页头标题、breadcrumb/current title、sidebar 树节点标题一致;data-page-wide-layout=truedata-page-small-text=true 生效。
  • smoke 已打开页面 AI 面板,确认 data-mnote-page-ai-session-owner=hermeslocalStorage 仅保存 {"activeSessionId":"mnote_tree_1778720870666_1_page-ai-mp4shbwk"},不保存页面标题。

验收标准:

  • 标题修改后页头、breadcrumb、sidebar、刷新后标题一致。
  • 页面设置修改只允许 wired 字段。
  • AI 面板没有独立标题状态。

J1:补 artifact reference edge 与 projection-only 验收

目标: artifact 工具经 Hermes tool call 与 Rust kernel 创建业务事实,AI Artifacts 只是 projection 分组,不是真实 kernel node。

必须参考 Hermes Web UI 的位置:

参考目的 具体文件 具体位置 / 搜索点 mnote 采用方式
artifact 工具作为 plugin/tool 暴露 packages/server/src/services/hermes/plugins.ts providesTools 第 200 行;providesHooks 第 201 行;requiresEnv 第 202 行 artifact 能力挂到 Hermes plugin,不做 mnote-web 私有按钮直写
artifact 结果仍是 tool event packages/client/src/api/hermes/chat.ts RunEvent 第 28 行;onToolCompleted 第 70 行 summary / ai_note 结果作为 tool event 展示
tool result 展示 packages/client/src/components/hermes/chat/MessageItem.vue toolPreview 第 543 行;toolResultPayload 第 332 行;tool-details 第 555 行 artifact 结果只展示摘要和详情,不写入正文
历史 tool message 恢复 packages/client/src/stores/hermes/chat.ts mapHermesMessages 第 125 行;case 'tool.completed' 第 948 / 1378 行 刷新后 artifact tool event 仍从 session 恢复
session DB tool 字段 packages/server/src/db/hermes/session-store.ts tool_call_id 第 40 行;tool_calls 第 41 行;tool_name 第 42 行;addMessage 第 331 行 tool call id 与 artifact audit 能串联

顺序执行 checklist

  • J1.1 扩展 scripts/task-hermes-page-ai-artifact-smoke.js,创建或更新 summary,记录 artifactDocumentId
  • J1.2 通过 kernel query 或稳定 projection route 查询 summary 与当前页面之间的 reference edge。
  • J1.3 再创建两次 ai_note,断言每次得到独立 artifactDocumentId
  • J1.4 查询每个 ai_note 与当前页面之间的 reference edge,确认 from/to/kind 可追踪。
  • J1.5 查询 AI Artifacts 分组来源,确认它是 projection-only 分组,不是真实 kernel node。
  • J1.6 回查 artifact audit,确认包含 sessionId/runId/toolCallId/traceId

2026-05-14 J1 执行证据:

  • cargo test -p bridge-runtime ai_artifact -- --nocapture2 passed。
  • MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-artifact-smoke.js:通过;referenceEdgeCount=6meta.aiArtifacts.projectionOnly=truekernelNodeId=nullauditEventCount=6

验收标准:

  • reference edge 可通过 kernel query 或 projection 查询。
  • AI Artifacts 只是 projection-only 分组。
  • summary 与 ai_note 行为符合既定幂等 / 新建规则。
  • artifact 写入 audit 能串到 Hermes tool call。

K1:补 legacy 调用方清点与退场文档

目标:/api/ai-agent/run 只保留为 legacy guard / 历史说明,不再被活跃设计或页面 AI 主链描述为长期入口。

必须参考 Hermes Web UI 的位置:

参考目的 具体文件 具体位置 / 搜索点 mnote 采用方式
新 run 入口 packages/client/src/api/hermes/chat.ts startRunViaSocket 第 432 行 对照新页面 AI 主链,不回到旧 /api/ai-agent/run
run server 注册 packages/server/src/routes/hermes/chat-run.ts setChatRunServer 第 5 行;getChatRunServer 第 9 行 确认 Hermes run server 是真实入口
upstream run 生命周期 packages/server/src/services/hermes/chat-run-socket.ts handleRun 第 488 行;markCompleted 第 1276 行 长期主链是 Hermes upstream run
plugin 发现 packages/server/src/services/hermes/plugins.ts listHermesPlugins 第 310 行 旧入口退场后,mnote 能力从 Hermes plugin/tool 面进入

顺序执行 checklist

  • K1.1 运行 rg -n "/api/ai-agent/run|provider=hermes|mnote-cli host|CLI-first" design rust wolai-frontend scripts --glob '*.md' --glob '*.rs' --glob '*.ts' --glob '*.tsx' --glob '*.js'
  • K1.2 将命中逐项归类为:历史证据legacy guard仍需迁移误导性活跃口径
  • K1.3 对 仍需迁移 的代码调用方补迁移或补退场 guard。
  • K1.4 对 误导性活跃口径 的设计稿改写为“历史/兼容/已覆盖”,必要时移入 design/old/ 并标 [recycle]
  • K1.5 更新旧 smoke:不再期待 /api/ai-agent/run -> mnote-cli 成功,只验证 legacy guard 返回稳定退场码。
  • K1.6 在本 checklist 回填 rg 输出摘要和修改文件清单。

2026-05-14 K1 执行证据:

  • rg 命中已归类:design/old/**design/07-ai/done/7-1** 为历史证据;scripts/task-hermes-page-ai-retirement-guard.jsrust/crates/mnote-web/src/routes/compat.rs 为 legacy guard;旧 E27/phase7/page-ai smoke 已默认退役;wolai-frontend 中 Mindmap / OnlyOffice / generic AI 面板调用点归为非当前页面 AI 主链的 legacy domain 调用点,后续按各自 domain 迁移。
  • 修改文件:rust/crates/mnote-web/src/routes/compat.rsscripts/task-hermes-page-ai-retirement-guard.js、历史退役 smoke 当前本机归档于 gitignored recycle/scripts/retired-ai-agent-run-smokes/design/05-editor-mainline/process/5-6-page-aggregate-alignment-checklist-v1.mddesign/05-editor-mainline/process/5-9-wolai-aline-continuous-checklist-v1.mddesign/10-review/04-secondary-domains-and-design-governance-review.md
  • 旧 smoke 默认退役验证:上述 6 个历史 smoke 均返回 { ok: true, retired: true }

验收标准:

  • 活跃设计稿不再把 /api/ai-agent/run 描述为页面 AI 长期入口。
  • legacy 调用方清单为空,或每一项都有明确退场说明。
  • 旧入口不会静默 fallback 到 Hermes、Codex 或旧 orchestrator。

L1:把审计从进程内缓存收口到持久化可追踪链

目标: 每次 Hermes 调用 mnote 工具都能从页面 AI 请求串到 Hermes run、mnote tool call、Rust command 和最终业务结果。

必须参考 Hermes Web UI 的位置:

参考目的 具体文件 具体位置 / 搜索点 mnote 采用方式
前端事件字段 packages/client/src/api/hermes/chat.ts RunEvent 第 28 行,重点看 run_idsession_idtoolname 前端事件字段要能和审计字段串联
run / tool / session 追踪 packages/server/src/services/hermes/chat-run-socket.ts emit 第 574 / 963 行;applyResponseStreamEvent 第 1035 行;flushResponseRunToDb 第 1207 行;markCompleted 第 1276 行 对齐 run、tool、session 三段追踪模型
tool call 持久字段 packages/server/src/db/hermes/session-store.ts tool_call_id 第 40 行;tool_calls 第 41 行;tool_name 第 42 行;addMessage 第 331 行 mnote audit 至少能关联 Hermes tool call id
usage 不进页面事实 packages/server/src/db/hermes/usage-store.ts recordUsage 第 16 行;getUsage 第 53 行;getUsageBatch 第 73 行;deleteUsage 第 118 行 usage/model 是 Hermes 真相,不写入 mnote page aggregate

顺序执行 checklist

  • L1.1 定义持久化审计落点:复用现有 audit/event log,或新增最小 mnote_hermes_tool_audit 存储;不得只依赖进程内缓存。
  • L1.2 审计字段固定包含 traceId/sessionId/runId/toolCallId/documentId/workspaceId/actorId/toolName/effect/commandId/errorCode
  • L1.3 在 tool call start / success / failure 三个阶段写入同一条可查询链。
  • L1.4 更新 scripts/task-hermes-page-ai-audit-smoke.js,重启进程或绕过进程内缓存后仍能按 traceId 回查审计。
  • L1.5 权限失败场景必须断言审计里没有完整正文、无权限页面标题或 block 原文。
  • L1.6 写工具成功场景必须断言审计能追踪到最终 Rust command id。

2026-05-14 L1 执行证据:

  • MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-audit-smoke.js:通过,persistedOnly=true 查询确认持久化审计可按 traceId 回查。
  • 权限失败审计:deniedPersistedPhases=["started","failed"]smoke 已断言持久化 audit 不含正文 marker 与页面标题。

验收标准:

  • 每个 tool call 都能追踪到 session、run、toolCall 和最终业务结果。
  • 失败不泄露内容。
  • 审计不是只存在于进程内缓存。

M1:把正式 3000 的 E2E smoke 跑成最终验收矩阵

目标: 临时 3019 证据不能作为最终完成;必须在正式 3000 + 真实 SQLite control-plane Auth / session 上复跑全矩阵。历史记录中的 Convex Auth 只作为当时验收背景。

必须参考 Hermes Web UI 的位置:

参考目的 具体文件 具体位置 / 搜索点 mnote 采用方式
run / resume / abort 客户端入口 packages/client/src/api/hermes/chat.ts startRunViaSocket 第 432 行;resumeSession 第 420 行;registerSessionHandlers 第 297 行 作为 E2E smoke 的网络断言依据
session detail packages/client/src/api/hermes/sessions.ts SessionSummary 第 3 行;HermesMessage 第 36 行;fetchSessions 第 50 行;fetchSession 第 81 行 刷新恢复 smoke 必须断言 session detail
run 生命周期 packages/server/src/services/hermes/chat-run-socket.ts resumeSession 第 427 行;handleRun 第 488 行;markCompleted 第 1276 行 正式 3000 上断言 run 生命周期完整
面板组件边界 packages/client/src/components/hermes/chat/ChatPanel.vue SessionListItem import 第 22 行、使用第 598 / 636 行;MessageList 第 790 行;ChatInput 第 791 行 只对齐页面 AI 抽屉需要的子集

顺序执行 checklist

  • M1.1 确认主入口 http://127.0.0.1:3000 运行的是包含本轮改动的 mnote-web,不是旧进程。
  • M1.2 使用默认 SQLite control-plane 测试账号 mnote.e2e@example.com 登录,不使用 MNOTE_DEV_AUTH=1 伪登录作为正式验收;旧 Convex Auth 仅作 compat 回归。
  • M1.3 运行 MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-smoke.js
  • M1.4 运行 MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-tool-smoke.js
  • M1.5 运行 MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-writeback-smoke.js
  • M1.6 运行 MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-title-options-smoke.js
  • M1.7 运行 MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-artifact-smoke.js
  • M1.8 运行 MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-retirement-guard.js
  • M1.9 运行 MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-mobile-smoke.js
  • M1.10 运行 MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task-hermes-page-ai-audit-smoke.js
  • M1.11 确认 smoke 只操作本轮新建测试数据,统一前缀 TEST-HERMES-AI-<timestamp>
  • M1.12 任一 smoke 失败时,把失败写入 bugs/07-ai/process/ 或真实 owner 分类,不在 checklist 里标 GREEN。

验收标准:

  • 所有 smoke 在正式 3000 通过。
  • 可以定位每次 smoke 生成的页面、artifact、edge 和 audit。
  • 任一 smoke 失败都会落到 bugs/,不会在 checklist 中假装通过。

N1:把活跃设计口径和 old 目录治理收口

目标: 设计目录与真实主线一致:页面 AI 是 Hermes 面板,mnote 通过 Hermes skill/plugin 被调用,旧 CLI-first 口径只保留为历史。

必须参考的本仓设计文件:

参考目的 具体文件 具体位置 / 搜索点 处理方式
Page Aggregate 口径 design/05-editor-mainline/process/5-6-page-aggregate-alignment-checklist-v1.md 搜索 /api/ai-agent/runmnote-cli host页面 AI 改成历史残留 / 已覆盖 / 待迁移证据,不写成长期主线
Wolai-aline 过渡基线 design/05-editor-mainline/process/5-9-wolai-aline-continuous-checklist-v1.md 搜索 E27mnote-cli页面 AI 保留为对标基线时必须标明过渡状态
二级域 review 建议 design/10-review/04-secondary-domains-and-design-governance-review.md 搜索 Hermespluginmnote-cliCLI-first 指向 Hermes plugin / Rust bridge 的当前口径
07-ai 历史稿 design/old/07-ai/process/ 搜索 CLI-firstmnote-cli 继续标 [recycle],不迁回活跃 process

顺序执行 checklist

  • N1.1 运行 rg -n "mnote-cli.*唯一|唯一长期 agent|CLI-first|/api/ai-agent/run|provider=hermes" design --glob '*.md'
  • N1.2 把命中分为 design/old 历史命中、活跃历史说明、活跃误导口径三类。
  • N1.3 修改 5-65-910-review 中仍残留的旧 CLI-first 说法,使其明确为历史/兼容/已覆盖。
  • N1.4 确认 design/old/07-ai/process/ 中历史稿继续标 [recycle]
  • N1.5 7-4 全部验收标准已满足,本文已按 design 归档规则移动到 design/07-ai/done/;新的活跃执行清单改由 7-7 承接。
  • N1.6 回填最终 rg 输出摘要和 design 文件迁移清单。

2026-05-14 N1 执行证据:

  • rg -n "mnote-cli.*唯一|唯一长期 agent|CLI-first|/api/ai-agent/run|provider=hermes" design --glob '*.md' 已跑完,活跃命中已逐项归类。
  • 活跃命中主要落在 design/05-editor-mainline/process/5-6-page-aggregate-alignment-checklist-v1.mddesign/05-editor-mainline/process/5-9-wolai-aline-continuous-checklist-v1.mddesign/10-review/04-secondary-domains-and-design-governance-review.mddesign/10-review/06-execution-checklist-and-acceptance.mddesign/01-tree-first-graph-kernel/process/1-1-tree-first-graph-kernel-checklist-v2.mddesign/03-rust-web/process/3-1-rust-web-long-term-checklist-v2.mddesign/07-ai/done/7-3-page-ai-hermes-panel-and-mnote-plugin-v1.mddesign/07-ai/done/7-4-page-ai-hermes-panel-execution-checklist-v1.mddesign/07-ai/done/7-5-hermes-client-proxy-contract-v1.mddesign/07-ai/done/7-6-mnote-hermes-plugin-tool-contract-v1.md
  • design/old/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md 与同目录旧稿继续保留 [recycle],只作为历史证据。
  • 本轮对 5-65-910-review/0410-review/061-13-1 的旧口径改写已完成;活跃文档现已统一为 Hermes 页面内客户端 + mnote Hermes plugin/tool 口径。
  • 本文件仍保留在 process/,原因是它是执行清单而不是代码实现文件;若后续需要归档,可按 N1.5 的规则移动并同步更新引用。

验收标准:

  • 活跃目录的旧 CLI-first 命中都带有历史/回收/已覆盖说明。
  • design/old/07-ai/process/ 保持历史记录定位。
  • 未完成能力不会被提前标 done。

17. 推荐执行顺序总表

顺序 Task 目标 退出门槛
1 A 固定旧链与 502 基线 有可复跑证据
2 B 冻结 Hermes client proxy 合同 route 输入输出示例齐全
3 C 实现 Hermes client proxy 只读链 session/run 可代理
4 D 冻结 mnote plugin tool 合同 第一批 tool schema 齐全
5 E 实现 manifest + mnote.page.get Hermes 可读当前页
6 F 实现 Leptos Hermes 面板 页面 AI 不再请求旧 run route
7 G 展示 tool event tool started/completed 可刷新恢复
8 H 正文写入工具 page.body.save 闭环
9 I 标题与页面设置工具 标题/设置走 Page Aggregate
10 J artifact 工具 summary / ai_note / reference edge 闭环
11 K 退役旧主链 旧 route 不再承载页面 AI 主路径
12 L 审计与可观测性 tool call 到 Rust command 可追踪
13 M 端到端验收矩阵 全 smoke 通过
14 N 文档治理回填 design 口径无旧主线残留

18. 最终完成定义

只有同时满足以下条件,才能宣布本 checklist 完成:

  • Hermes session 是页面 AI 会话真相。
  • mnote 只保存业务事实和审计,不保存聊天真相。
  • 页面 AI 面板是 Leptos Hermes client,不是 mnote-cli 面板。
  • mnote Hermes plugin 至少覆盖读取当前页、写正文、改标题/设置、创建 summary、创建 ai_note。
  • 所有写入经 Rust runtime / kernel。
  • /api/ai-agent/run 不再是页面 AI 主入口。
  • E2E smoke 覆盖只读、写入、artifact、刷新恢复、旧链退役;正式 http://127.0.0.1:3000 已复跑 8 个 smoke,见 Task M。
  • 活跃设计文档和执行清单一致;旧 CLI-first / /api/ai-agent/run 命中均已标为历史、兼容、已覆盖或 legacy guard。

18.1 最终完成审计记录

2026-05-14 最终复核按“完成定义 -> 真实证据”逐项检查,不只依赖本文勾选状态。

  • 运行态入口存在:ss -ltnp | rg ':3000\b|:8642\b' 确认 mnote-web 监听 0.0.0.0:3000Hermes API server 监听 127.0.0.1:8642
  • Rust tool / client / legacy guard 测试通过:
    • cargo test -p bridge-runtime ai_artifact -- --nocapture2 passed。
    • cargo test -p mnote-web hermes_client -- --nocapture4 passed。
    • cargo test -p mnote-web hermes_tools_ -- --nocapture9 passed。
    • cargo test -p mnote-web ai_agent_run -- --nocapture1 passed。
    • cargo test -p mnote-web explicit_ -- --nocapture2 passed。
    • cargo build -p mnote-web:通过。
  • Hermes plugin/toolset 可见:
    • hermes plugins listmnote 为 enabled user plugin。
    • hermes tools list --platform api_serverPlugin toolsets 中 mnote 为 enabled。
    • /home/lix/.hermes/plugins/mnote/plugin.yaml 声明 mnote_page_getmnote_page_savemnote_page_update_titlemnote_page_update_optionsmnote_artifact_create_summarymnote_artifact_create_ai_note
  • 正式 3000 smoke 全矩阵通过:
    • task-hermes-page-ai-smoke.jstree_1778724401995_17session mnote_smoke_mp4ul0c2run run_smoke_mp4ul0c2sessionDetailHits=2
    • task-hermes-page-ai-tool-smoke.jstree_1778724413742_19mnote.page.get 返回标题 TEST-HERMES-AI-tool-mp4ul9ei
    • task-hermes-page-ai-writeback-smoke.jstree_1778724445965_21page.body.savecommand page_body_save_req_1778724446747_1371
    • task-hermes-page-ai-title-options-smoke.jstree_1778724480369_23page.head.updateTitlepage.layout.updateOptions 通过,pageFont 返回 page_option_not_wired
    • task-hermes-page-ai-artifact-smoke.jstree_1778724511207_25summary / ai_note 都走 tree.node.createreferenceEdgeCount=6projectionOnly=true
    • task-hermes-page-ai-retirement-guard.js:旧入口返回 410 legacy_ai_agent_run_retired
    • task-hermes-page-ai-mobile-smoke.js390px viewport 下 drawer / panel 未横向溢出。
    • task-hermes-page-ai-audit-smoke.jstree_1778724538669_29,写命令 page_body_save_req_1778724538893_1707,持久化 audit 覆盖 started/completed 与权限失败 started/failed
  • 真实 Hermes upstream session 补充验证:页面 AI 不拦截 Hermes 请求时触发真实 run,hermes sessions export --session-id mnote_tree_1778724800891_37_page-ai-mp4utko0 - 显示 message_count=4tool_call_count=1api_call_count=2has_mnote_page_get=true
  • 文档治理检查通过:
    • rg -n "mnote-cli.*唯一|唯一长期 agent|CLI-first|/api/ai-agent/run|provider=hermes" design --glob '*.md' 的活跃命中均为历史、兼容、已覆盖、禁止项或 legacy guard 说明。
    • git diff --check 覆盖本轮已跟踪设计稿,无空白错误。
    • rg -n "[ \t]+$" 覆盖本轮设计稿,无尾随空白。