Files
mnote/design/07-ai/done/7-57-yuxi-reference-ai-run-config-knowledge-facade-v1.md
T

469 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 7-57 [done] Yuxi reference: AI run journal, config schema and knowledge facade v1
> 创建时间:2026-06-09
>
> 当前状态:`DONE`
>
> 2026-07-03 口径回正:当前 runtime 已回到 OpenHub / native agent + LightRAG + Turso/libSQL。本文中的 Knowledge RAG facade 重新作为当前 LightRAG 默认 provider 的 run/config/facade 参考;历史非 LightRAG 默认 provider 口径已标记 stale。
>
> Owner07-ai / Page AI runtime / Hermes client runs / Reasonix ACP / Knowledge RAG facade
>
> 参考代码:
> - `reference-code/Yuxi/backend/package/yuxi/services/run_queue_service.py`
> - `reference-code/Yuxi/backend/package/yuxi/services/agent_run_service.py`
> - `reference-code/Yuxi/web/src/composables/useAgentRunStream.js`
> - `reference-code/Yuxi/backend/package/yuxi/agents/context.py`
> - `reference-code/Yuxi/backend/package/yuxi/agents/toolkits/kbs/tools.py`
>
> 上位依据:
> - `ARCHITECTURE.md`
> - `CURRENT_ARCHITECTURE.md`
> - `design/07-ai/process/7-18-local-first-agent-file-editing-control-plane-v1.md`
> - `design/07-ai/done/7-39-page-ai-agent-selector-context-authorization-settings-v1.md`
> - `design/07-ai/done/7-40-page-ai-context-envelope-and-run-receipt-v1.md`
> - `design/07-ai/done/7-50-lightrag-knowledge-rag-provider-v1.md`
> - `design/07-ai/done/7-51-lightrag-post-commit-hardening-v1.md`
## 1. 第一结论
Yuxi 值得参考的是三类工程模型,不是整体架构:
1. **AI run event journal**:把一次 agent run 变成可查询、可恢复、可断线重连的事件流,而不是只依赖当前浏览器连接上的一次 SSE。
2. **配置 schema 驱动 UI**:用后端声明 agent 可配置字段、权限、默认值和资源选项,前端按 schema 渲染,减少 Hermes / Reasonix / Chat-only 设置漂移。
3. **知识库工具 facade**:agent 只通过稳定工具面访问知识库,query 返回引用,open_reference 负责把 provider reference 转成 MNote 可点击定位。
这些模型适合 MNote 当前 Page AI / ACP / LightRAG 主线,但必须受 MNote 边界约束:
- 不复制 Yuxi 的 LangGraph agent runtime。
- 不引入 Yuxi 的 Milvus / Neo4j / Postgres 知识库主存储。
- 不把 Vue/Ant Design 前端模式迁入 Rust SSR / browser runtime。
- 不改变 local-first 普通 Markdown 编辑主路径:仍是授权文件引用 + agent 原生 patch/diff + watcher/BufferStore/Page Aggregate 同步。
- 不恢复旧 LiteParse / evidence / local OCR 默认路径;知识库问答继续以 LightRAG 为唯一默认 provider。
## 2. Yuxi 对照结论
### 2.1 AI run event journal
Yuxi 的 run 链路是:
```text
POST /api/agent/runs
-> 创建 AgentRun 行和 input message
-> ARQ worker 执行
-> Redis stream append event
-> GET /api/agent/runs/{runId}/events
-> 前端用 Last-Event-ID / after_seq 恢复
```
可借鉴点:
- 事件流有 `seq` cursor,浏览器刷新后可以从最后 seq 继续。
- run 有 terminal reconciliationSSE 断开时查 run 状态,必要时重连或补 terminal event。
- active run snapshot 放在浏览器侧,服务端 `active_run` 是权威判定。
- interrupted / resume run 用 `parent_run_id + resume_request_id` 做幂等。
不适合直接搬:
- MNote 不把 Hermes / Reasonix 包进 LangGraph worker。
- MNote 不要求所有 agent run 进入一个 Python queue;第一阶段只给现有 `/api/hermes/client/runs`、Reasonix ACP bridge、Chat-only provider 增加宿主侧 run journal。
- MNote 不用 Redis 作为默认 local-first 控制面;优先 SQLite control-plane,长连接仍由当前 Rust Web 承载。
### 2.2 配置 schema 驱动 UI
Yuxi 的 `BaseContext` 用 dataclass field metadata 声明 `model/tools/knowledges/mcps/skills` 等配置,并按角色过滤。
可借鉴点:
- agent 后端自己声明配置项,前端不硬编码每个 agent 的全部字段。
- 字段带 `kind`,例如 `llm/tools/knowledges/mcps/skills`,可由后端补资源 options。
- admin-only 字段由服务端过滤,不能只靠前端隐藏。
不适合直接搬:
- MNote 当前已有 `PAGE_AI_AGENT_REGISTRY`、SQLite `user_ui_preferences`、directory grants、Hermes tool manifest 和 Reasonix wrapper selftest。
- 因此不新增一套 Python 式 context schema;应把现有 Rust manifest / control-plane preference / agent registry 收成一个统一的 `mnote.ai_agent_descriptor.v1`
### 2.3 知识库工具 facade
Yuxi 的知识库工具强调:
- `list_kbs` 列出当前 runtime 可访问知识库。
- `query_kb``kb_id + query_text` 检索。
- `open_kb_document``kb_id + file_id + line/window` 打开更完整上下文。
- 工具先做 visible scope 校验,再查 retriever。
可借鉴点:
- query 只返回检索片段和可追踪引用,不暴露 provider 内部目录作为最终引用。
- open 是单独工具,避免 query 结果过大。
- runtime visible scope 是工具入口的第一层校验。
MNote 当前已有更接近目标的实现:
- `mnote.knowledge_rag.status`
- `mnote.knowledge_rag.query`
- `mnote.knowledge_rag.open_reference`
- `/api/knowledge-rag/search`
- `sourceScopeMode=post_filter_mapped_references`
- `citationMarkdown / citationUrl / locatorDegraded`
因此 7-57 不重做知识库工具,而是补 facade 合同和漂移保护。
## 3. 目标架构
```text
Page AI sidebar
-> create host AI run
-> freeze target/contextRefs/allowedRoots/capability snapshot
-> dispatch to Hermes / Reasonix / Chat-only
-> bridge provider events into AI run event journal
-> browser consumes resumable run events
-> tool calls use schema-driven capability manifest
-> knowledge-rag query/open_reference returns MNote citations
```
三条线要共享同一个 run identity
- `hostRunId`MNote 宿主侧 run idPage AI UI、audit、event journal 和 browser resume 使用。
- `providerRunId`Hermes / Reasonix / Chat-only 自己的 run/session id,作为外部关联字段。
- `requestId`:用户一次点击发送生成的幂等键,浏览器重试时不重复创建 run。
## 4. Design AAI run event journal
### 4.1 数据合同
第一阶段优先落 SQLite control-plane,避免引入 Redis。
```json
{
"schema": "mnote.ai_run.v1",
"hostRunId": "run_...",
"requestId": "client_req_...",
"agentId": "reasonix",
"provider": "acp_reasonix",
"providerRunId": "external-run-id",
"sessionId": "session-id",
"actorId": "user-id",
"workspaceId": "local:workspace",
"status": "pending|running|interrupted|completed|failed|cancelled",
"targetSnapshotHash": "sha256...",
"capabilitySnapshotHash": "sha256...",
"createdAt": "2026-06-09T00:00:00Z",
"updatedAt": "2026-06-09T00:00:01Z"
}
```
```json
{
"schema": "mnote.ai_run_event.v1",
"hostRunId": "run_...",
"seq": "000000000000000001",
"kind": "message.delta|tool.started|tool.completed|plan.updated|session.info.updated|changed_files|end|error",
"source": "mnote|hermes|reasonix|chat_only|tool",
"payload": {},
"createdAt": "2026-06-09T00:00:01Z"
}
```
`seq` 第一阶段可用单调递增整数文本,不需要复刻 Redis stream id。要求只满足:
- 同一 `hostRunId` 内严格递增。
- 客户端传 `afterSeq` 时只返回更大的事件。
- terminal event 必须可补发,防止浏览器漏掉结束状态。
### 4.2 API 合同
第一阶段不替换现有 `/api/hermes/client/runs`,而是在其外层增加宿主 run receipt
```text
POST /api/page-ai/runs
GET /api/page-ai/runs/{hostRunId}
GET /api/page-ai/runs/{hostRunId}/events?afterSeq=...
POST /api/page-ai/runs/{hostRunId}/cancel
GET /api/page-ai/sessions/{sessionId}/active-run
```
兼容策略:
-`/api/hermes/client/runs` 可继续存在,但 Page AI runtime 默认走新 receipt route。
- 新 route 内部仍可调用 Hermes client proxy / Reasonix ACP bridge。
- 若 provider 已经有自己的 SSERust Web 只做事件桥接和 journal append,不接管 provider agent loop。
### 4.3 前端恢复规则
浏览器保存轻量 snapshot
```json
{
"hostRunId": "run_...",
"sessionId": "session-id",
"lastSeq": "000000000000000031",
"createdAt": 1780000000000
}
```
恢复流程:
1. 页面可见或 Page AI 打开时,查本地 snapshot。
2.`active-run` 做权威判定。
3. 如果服务端 run 仍是 `pending/running/interrupted`,用 `afterSeq=lastSeq` 继续消费。
4. 如果服务端 run 已 terminal,拉取缺失事件并清掉 snapshot。
5. 如果本地 snapshot 对应的 run 不存在,清掉本地状态,不能伪装仍在运行。
### 4.4 验收
- 刷新浏览器后,正在运行的 Reasonix / Hermes run 不丢消息。
- SSE 断开后,前端能基于 `afterSeq` 续接,不重复渲染旧 tool event。
- terminal event 漏掉时,状态查询能补齐 `completed/failed/cancelled`
- 同一 `requestId` 重试不会创建两个 host run。
- `changed_files`、tool citation、plan/session info 都进入 journal,但不进入页面正文真相。
## 5. Design BAI agent descriptor schema
### 5.1 目标
把 7-39 / 7-40 已经落地的 registry、preference、tool manifest 收成一个后端可查询合同:
```json
{
"schema": "mnote.ai_agent_descriptor.v1",
"agentId": "reasonix",
"displayName": "Reasonix",
"provider": "acp_reasonix",
"capabilities": ["file_read", "file_write", "knowledge_rag", "native_patch"],
"defaultContextRefs": ["current_page", "active_editor"],
"settingScopes": ["ai.common", "ai.agent.reasonix"],
"fields": [
{
"key": "ai.agent.reasonix.profile_id",
"label": "Profile",
"kind": "select",
"default": "default",
"optionsSource": "reasonix_profiles",
"auth": "user",
"secret": false
}
],
"tools": [
{
"name": "mnote.knowledge_rag.query",
"capabilityIds": ["knowledge_rag"],
"enabled": true
}
]
}
```
### 5.2 来源合并顺序
```text
Rust static agent registry
+ Hermes tool manifest
+ Reasonix wrapper mapping/selftest
+ SQLite user_ui_preferences
+ SQLite directory_grants derived allowedRoots
-> ai_agent_descriptor response
```
规则:
- `directory_grants` 不进入普通 field;它是权限事实,只能作为 allowed roots 派生。
- secret / token 类字段不得通过 descriptor 返回明文。
- agent-specific 设置只写入 `ai.agent.<agentId>` scope。
- common 设置只写入 `ai.common` scope,例如默认 agent、默认 contextRefs、citation 显示策略。
- 前端可以缓存 descriptor,但发送 run 前服务端必须重新解析权限和 enabled tools。
### 5.3 UI 结果
前端不再维护多份工具表:
- Agent selector 从 descriptor 渲染。
- 设置页 tabs 从 descriptor 渲染。
- Knowledge RAG 能力是否可用从 descriptor 的 `tools/capabilities` 渲染。
- Chat-only 默认不暴露文件写入和 MNote context tools。
- Hermes / Reasonix wrapper 漂移由 descriptor selftest 捕获。
### 5.4 验收
- `GET /api/page-ai/agents/descriptors` 返回 Hermes / Reasonix / Chat-only 三类 descriptor。
- Alice/Bob 的 common preference 隔离。
- `mnote.knowledge_rag.*` manifest 与 Reasonix wrapper 双向一致。
- 禁用 Knowledge RAG 后,descriptor 中 capability disabledPage AI 不引导 agent 调用该工具。
- 前端删除硬编码工具 enable 列表,只保留渲染逻辑和兼容 fallback。
## 6. Design CKnowledge RAG facade hardening
### 6.1 工具面
维持当前主工具,不新增第二套 provider:
```text
mnote.knowledge_rag.status
mnote.knowledge_rag.query
mnote.knowledge_rag.open_reference
```
建议补一个 facade-level `search` 工具时再单独拆小设计;当前已有 `/api/knowledge-rag/search`,但未必需要默认暴露给 agent。
### 6.2 query 输出要求
`mnote.knowledge_rag.query` 必须稳定返回:
```json
{
"schema": "mnote.knowledge_rag.query_result.v1",
"answer": "...",
"sourceScopeMode": "post_filter_mapped_references",
"references": [
{
"schema": "mnote.knowledge_rag.reference.v1",
"sourcePath": "docs/a.pdf",
"filePath": "a.pdf",
"citationMarkdown": "[a.pdf · p.3](...)",
"citationUrl": "...",
"locatorDegraded": false
}
],
"citations": []
}
```
要求:
- agent 最终回答优先用 `citationMarkdown`
- `locatorDegraded=true` 时只能说“来源定位降级”,不能编页码 / bbox。
- `sourcePaths` 的语义继续是 `post_filter_mapped_references`,不得描述成 provider 原生检索 scope。
- compact tool output 不暴露 provider raw chunks,除非明确进入 debug。
### 6.3 open_reference 输出要求
`open_reference` 是唯一把 provider reference 转成 MNote UI locator 的工具:
- 输入可以是 query 返回的 reference,也可以是 `file_path/chunk_id` 这类 provider hint。
- 输出必须包含 `citationUrl/citationMarkdown`
- 能定位 page/bbox/block 时返回精确 locator。
- 不能定位时返回 degraded resourceTab citation。
- 不返回 `file://`、LightRAG dashboard URL 或 `.mnote/index` 私有路径给 agent 作为最终引用。
### 6.4 与 Yuxi 的差异
Yuxi 的 `open_kb_document(kb_id,file_id,line/window)` 适合普通文本知识库;MNote 的资料库来源包含 PDF、DOCX、图片、resource tab 和 bbox,因此不能把 `file_id + line window` 作为唯一打开模型。
MNote 可以参考它的“两阶段工具”:
```text
query -> reference id / source hint
open_reference -> MNote locator / clickable citation
```
但不要退回“按行打开一切”的模型。
### 6.5 验收
- `task529` 继续覆盖 open_reference 能打开 resource tab。
- `task530` 继续覆盖 Page AI final answer 不泄漏 `citationMarkdown` 字段名、不编造 locator。
- `task538` 继续覆盖 `sourceScopeMode=post_filter_mapped_references`
- Reasonix wrapper selftest 覆盖 `mnote.knowledge_rag.status/query/open_reference`
- 新增一个 descriptor smoke:禁用 Knowledge RAG 时 Page AI 不显示知识库能力,启用时工具表与 manifest 一致。
## 7. 实施拆分
### Batch A:只读对齐与 descriptor 草案
- [x] 读取当前 `PAGE_AI_AGENT_REGISTRY`、Hermes tool manifest、Reasonix wrapper 映射、SQLite AI preferences。
- [x] 输出 `mnote.ai_agent_descriptor.v1` 的 Rust 结构和只读 route。
- [x] 不改 run 创建链路。
- [x] 验证:Rust 单测 + 一个 JS smoke 断言三类 agent descriptor。
执行记录(2026-06-09):
- 已新增 `GET /api/page-ai/agents/descriptors`,返回 `mnote.ai_agent_descriptors.v1`,包含 Hermes / Reasonix / Chat-only 三类 descriptor、当前 actor 的 `ai.common.*` / `ai.agent.*` preference values、manifest tools 和 capability packs。
- Chat-only descriptor 不暴露 MNote tools`canWriteFiles=false`Hermes / Reasonix descriptor 继续从 Hermes manifest 和 MNote capability packs 暴露 `mnote.knowledge_rag.*` 等工具状态。
- 已补 Rust route 单测 `page_ai_agent_descriptors_merge_manifest_capabilities_and_preferences`,覆盖三类 agent、Reasonix Knowledge RAG tool、Chat-only 无工具、Alice/Bob preference 隔离。
- 已补 JS smoke `scripts/task557-page-ai-agent-descriptor-smoke.js`,覆盖真实 `3000` API 返回的三类 agent descriptor、Reasonix `mnote.knowledge_rag.status/query/open_reference`、Chat-only 无 MNote tools 与空默认 context refs。
- 已验证:`cd rust && cargo test -p mnote-web page_ai_agent_descriptors --lib``cargo test -p mnote-web page_ai_capabilities_expose_knowledge_rag_and_toggle_tools --lib``cargo test -p mnote-web hermes_client_tools_uses_manifest_and_profile_disabled_state --lib`
- 已验证:`node scripts/task557-page-ai-agent-descriptor-smoke.js`
前端继续执行记录(2026-06-09):
- Page AI runtime 已新增 descriptor 加载链路:打开 drawer 时请求 `/api/page-ai/agents/descriptors?profile=...`,成功后用后端返回的 Hermes / Reasonix / Chat-only descriptor 覆盖本地 fallback registry。
- Agent picker、当前 agent chip、history agent label 和 mnote tool list 已优先消费 descriptor 的 `displayName``acpRuntime``canWriteFiles``capabilities``tools`
- Agent / Hermes / Reasonix / Chat-only 设置页已按 `descriptor.fields` 渲染最小 schema UI,当前支持 `select``string``boolean/toggle`,并通过 `ai.*` preference key 写回 `/api/ui/preferences`
- `PAGE_AI_AGENT_FALLBACK_REGISTRY` 仅作为 descriptor API 失败时的加载失败 fallback,不再作为正常路径的唯一 agent 字段来源。
- 已补 SSR runtime 合同测试,确保前端 bundle 保留 descriptor endpoint、descriptor field 控件和 agent descriptor card。
### Batch Bhost run journal 最小闭环
- [x] 新增 SQLite run / run_event 存储或复用现有 run 表,明确 migration。
- [x] 为 Page AI run 创建 `hostRunId/requestId/status`
- [x] 将现有 Hermes / Reasonix SSE 事件 append 到 journal。
- [x] 新增 `GET /events?afterSeq=`
- [x] 验证:单测覆盖 seq 去重、terminal 补发、requestId 幂等。
执行记录(2026-06-09):
- 已复用 `control-plane` 现有 `ai_runtime_runs` / `ai_runtime_events`migration `002-ai-runtime-store.sql`),补 `find_ai_runtime_run``list_ai_runtime_journal_events(after_seq, limit)`journal seq 由同一 run 内事件顺序生成并格式化为 18 位文本 cursor。
- 已新增 `GET /api/page-ai/runs/{hostRunId}``GET /api/page-ai/runs/{hostRunId}/events?afterSeq=...`;当前第一步兼容现有 `run_id``hostRunId` 暂时 alias 现有 persisted run id,后续 `POST /api/page-ai/runs` 再拆真正 host/provider 双 id。
- 已新增 `POST /api/page-ai/runs` 创建宿主侧 receipt:写入 `hostRunId/requestId/status=pending`,并追加 `run.created` 初始事件;同一 `requestId + sessionId + workspaceId + documentId` 重试返回既有 run,不重复追加事件。
- `GET /api/page-ai/runs/{hostRunId}/events?afterSeq=...` 已在 terminal status 存在但 terminal event 缺失时补一个 synthetic terminal event,用于浏览器刷新或 SSE 断线后的终态 reconciliation。
- 已补 Rust route 单测 `page_ai_run_events_expose_journal_after_seq`,覆盖 run receipt 查询、`afterSeq=000000000000000001` 只返回 seq 2、event schema/kind/source/payload。
- 已补 Rust route 单测 `page_ai_run_create_is_request_id_idempotent`,覆盖 `requestId` 幂等创建、重复 POST 不重复追加 `run.created`
- 已补 Rust route 单测 `page_ai_run_events_reconcile_missing_terminal_event`,覆盖缺 terminal event 时按 run status 补发 synthetic terminal event。
- 已扩展 `api_chat_events_stream_from_openai_compatible_upstream`,验证 provider SSE 消费后可通过 `/api/page-ai/runs/{runId}/events?afterSeq=0` 读到 journal 中的 `message.delta``run.completed`
- 已把 persisted journal `seq` 回填到 API Chat / ACP SSE payload,前端实时消费时可同步推进 active-run snapshot cursorACP/Reasonix 事件仍由既有 `persist_acp_runtime_event` 写入 SQLite journal。
- 已验证:`cargo test -p control-plane ai_runtime_run_upsert_lists_updates_and_events --lib``cargo test -p mnote-web page_ai_run_ --lib`
### Batch C:前端 resume
- [x] Page AI runtime 保存 `{hostRunId, sessionId, lastSeq}`
- [x] 页面可见 / 打开 sidebar 时执行 active-run 判定。
- [x] 恢复 SSE 时用 `afterSeq`,避免重复 tool card。
- [x] 验证:浏览器 smoke 模拟刷新后继续接收事件。
执行记录(2026-06-09):
- 已新增 `GET /api/page-ai/sessions/{sessionId}/active-run`,按 `workspaceId/documentId/sessionId` 返回当前非 terminal host run,响应 schema 为 `mnote.ai_active_run.v1`
- Page AI session runtime 已新增 `pageAiCheckActiveRun()`;打开 drawer 完成 session 加载后调用一次,页面重新 visible 且 drawer 打开时再次调用。命中 active run 后会更新当前 session `runId/status``data-mnote-page-ai-active-host-run-id` 和 run status UI。
- Page AI runtime 已新增 `mnote.page_ai_active_run_snapshot.v1` localStorage snapshot;实时 SSE payload 含 `seq` 时同步写入 `lastSeq`terminal status 清理 snapshot。
- 打开 drawer / 页面重新 visible 命中 active run 后,会继续调用 `/api/page-ai/runs/{hostRunId}/events?afterSeq={lastSeq}` 恢复 journal,并把 `message.delta` / `tool.*` / `plan.updated` / terminal event 重新投递到当前 conversation。
- 已补 Rust route 单测 `page_ai_session_active_run_returns_non_terminal_run`,覆盖同一 session 下 completed run 被忽略、running run 被选为 active。
- 已补 SSR runtime 合同测试,确保前端 bundle 保留 active-run endpoint、`pageAiCheckActiveRun()``pageAiResumeActiveRunJournal()``afterSeq` cursor、snapshot schema 和 `visibilitychange` 判定。
- 已补 `scripts/task557-page-ai-run-resume-smoke.js`:种入 running host run 与两条 journal event,浏览器 localStorage 保留 `lastSeq=000000000000000001` 后打开页面 AI,验证前端调用 `active-run``/events?afterSeq=...`,只恢复 `resumed-token`,不重复渲染 `old-token`
- Page AI 打开 drawer 后会优先按 active-run snapshot 的 `sessionId` 恢复;后端会话列表加载完成后再次判定,避免 profile/settings 等慢请求阻塞 journal resume。
- 已验证:`cargo test -p mnote-web page_ai_session_active_run_returns_non_terminal_run --lib``cargo test -p mnote-web page_ai_uses_backend_acp_session_runtime_store --lib``cargo test -p mnote-web api_chat_events_stream_from_openai_compatible_upstream --lib`
- 已验证:`node scripts/task557-page-ai-run-resume-smoke.js`
### Batch DKnowledge facade 漂移保护
- [x] descriptor 暴露 Knowledge RAG capability enabled/disabled。
- [x] selftest 同时校验 Rust manifest、Reasonix wrapper、skill 文案中的工具名。
- [x] 若 query 输出缺 `citationMarkdown`Page AI final answer smoke 必须失败。
- [x] 验证:`task529``task530``task538` 加 descriptor 断言。
执行记录(2026-06-09):
- Descriptor 已新增 `capabilityStates` / `disabledCapabilities`;禁用 `mnote-knowledge-rag` 后,Reasonix descriptor 不再在 `capabilities` 中声明 `knowledge_rag`,对应 `mnote.knowledge_rag.*` tool 标记为 disabled。
- 已扩展 Rust 单测 `page_ai_agent_descriptors_merge_manifest_capabilities_and_preferences`,覆盖 Knowledge RAG enabled/disabled descriptor 状态与 disabled tool policy。
- 已扩展 `scripts/task557-page-ai-agent-descriptor-smoke.js`,真实 3000 API smoke 覆盖默认启用与禁用后的 descriptor/tool 状态。
- 已扩展 `scripts/reasonix-acp-wrapper.mjs` selftest:同时校验 Rust manifest、Reasonix wrapper mapping、`skills/mnote-knowledge-rag/SKILL.md` 文案中的 `mnote.knowledge_rag.status/query/open_reference` 工具名一致。
- 已给 `task529` / `task530` / `task538` 补 descriptor 断言;`task530` 现在会先直接调用 `knowledge-rag/query` 并要求 reference 含 `citationMarkdown`,否则 Page AI final answer smoke 直接失败。
- 已把 `task529` / `task530` 的目标图片资料改为先 ingest + 等待 indexed,避免 smoke 依赖现场 registry 预置状态。
- 已给 LightRAG provider HTTP 5xx `RetryError` / `InvalidResponseError` / empty content 增加一次短 retry,避免 Reasonix Page AI 路径因 provider 偶发空响应直接失败。
- 已验证:`node scripts/task529-knowledge-rag-citation-resource-tab-smoke.js``node scripts/task530-knowledge-rag-page-ai-final-answer-smoke.js``node scripts/task538-knowledge-rag-source-scope-api-smoke.js``node scripts/task557-page-ai-agent-descriptor-smoke.js``MNOTE_REASONIX_ACP_SELFTEST=1 node scripts/reasonix-acp-wrapper.mjs`
## 8. 非目标
- 不把 Yuxi 拉入运行依赖。
- 不迁移到 FastAPI / Vue / Milvus / Neo4j。
- 不把 AI run journal 当作聊天全文主存储;provider 自己的历史仍由 provider 管。
- 不让 run journal 写页面正文或 Page Aggregate。
- 不改变 LightRAG provider 的 source truth、delete/reindex 语义。
- 不新增定时轮询刷新 Page AI;恢复靠显式打开、页面可见、SSE reconnect 和 terminal reconciliation。
## 9. 风险
- 如果 journal 记录过多 token deltaSQLite 可能膨胀。第一版应 compact tool/result payload,保留 UI 恢复必需事件,不保存大段 provider raw chunks。
- 如果 descriptor 同时由前端和后端维护,会形成新漂移。必须以后端 route 为准,前端只渲染。
- 如果 `hostRunId` 与 provider run id 混用,审计会断链。所有 UI、audit、changed files 都使用 hostRunIdprovider id 只作为关联字段。
- 如果把 Yuxi 的 `line/window open` 直接套到 PDF/DOCX/image,会破坏 MNote locator 模型。Knowledge facade 必须继续以 `open_reference -> citationUrl` 为中心。