# 7-50 [done] LightRAG Knowledge RAG Provider v1

> 创建时间：2026-06-06
>
> 当前状态：`DONE`
>
> Owner：07-ai / knowledge-rag / plugin-ui / external-provider
>
> 取代：`design/old/07-ai/process/7-49-local-understanding-graphrag-kernel-v1.md`
>
> 参考代码：
> - `reference-code/LightRAG`
>
> 本机源码部署：
> - source：`/mnt/Data1T/Mnote_data/lightrag/LightRAG`
> - storage：`/mnt/Data1T/Mnote_data/lightrag/rag_storage`
> - input spike：`/mnt/Data1T/Mnote_data/lightrag/inputs`
> - systemd user service：`mnote-lightrag.service`
> - WebUI：`http://127.0.0.1:9621`
> - current model：`aigc/qwen-3.5`
>
> 上位依据：
> - `/mnt/Data1T/mnote/ARCHITECTURE.md`
> - `/mnt/Data1T/mnote/CURRENT_ARCHITECTURE.md`
> - `design/07-ai/process/7-46-document-evidence-retrieval-kernel-v1.md`
> - `design/07-ai/process/7-48-paperless-ngx-reference-resource-ingestion-job-index-v1.md`
> - `design/03-rust-web/done/3-25-local-folder-mineru-ocr-sidecar-v1.md`

## 1. 第一结论

MNote 后续知识库问答主线改为 **LightRAG 单外挂 Provider**，不继续推进 7-49 的自研 Understanding GraphRAG Kernel / mindmap projection 路线。

目标是减少冗余项目和冲突：

- LightRAG 负责知识库问答相关的 OCR、文档解析调度、MinerU / Docling 接入、sidecar、chunk、向量、图谱、rerank 和跨文档问答。
- MNote 负责 workspace 权限、source truth、resource ownership、引用 UI、agent 授权、任务入口和 LightRAG 结果打开方式。
- LiteParse / MNote 旧解析定位链路退役；旧 OCR / evidence / 本地资料索引入口不再作为默认 fallback，PDF / Office / 图片 OCR 与资料库索引统一交给 LightRAG。
- PageIndex 暂停，不作为当前默认双引擎；未来只在少量书籍确实需要章节树精读时再做定向树索引。
- 插件系统暂不开发完整市场式框架；第一版只做一个薄的 `KnowledgeRagProvider` / `LightRAGAdapter`，让 LightRAG 像插件一样不干扰 MNote 正常功能。

## 2. 为什么放弃 7-49

7-49 的核心假设是 MNote 自己构建本地 Understanding GraphRAG Kernel。这个方向问题不在能力，而在冗余：

- LightRAG 已经覆盖 graph + vector + rerank + parser pipeline 的主体能力。
- 自研 understanding graph 会和 LightRAG 图谱、evidence SQLite、mindmap projection 形成三套相似真相。
- mindmap projection 不能覆盖 NotebookLM 式多书问答的核心体验，反而会牵引 UI 和数据模型提前复杂化。
- 用户当前需求是“很多本书 / 很多篇文献作为资源，agent 能查阅、问答、溯源”，优先级高于自研图谱可视化。

因此 7-49 退役，只保留为历史参考，不再作为 process 设计稿。

## 3. LightRAG 能覆盖的边界

本轮已按最新 LightRAG 代码重新建索引确认：

- LightRAG v1.5 已合并 RagAnything 路线，支持 MinerU / Docling 多模态解析。
- 支持 `legacy` / `native` / `mineru` / `docling` 解析引擎。
- 支持 Fix / Recursive / Vector / Paragraph 四种切分。
- MinerU 支持 `official` / `local` 两种模式；MNote 已有 MinerU token，可先走 official spike。
- sidecar 包含 `blocks.jsonl`、`drawings.json`、`tables.json`、`equations.json`、assets。
- block positions 支持 `bbox`，可表达 page + rectangle。
- chunk 可以通过 `sidecar.refs` 追溯到 block/table/drawing/equation。

关键限制：

- LightRAG 没有集成 LiteParse 本身。
- LightRAG OCR 能力来自 MinerU / Docling 服务，不是内置 OCR 模型。
- LightRAG `/query` 默认引用粒度偏粗，通常是 `reference_id + file_path + chunk content`；MNote 需要额外 adapter 反查 sidecar，生成现有 EvidenceLocator。

结论：LightRAG 可以成为主解析/RAG provider，但不能直接替代 MNote 的权限、locator 和引用 UI。

## 4. 新架构边界

本设计的核心边界是：**LightRAG 是独立本地知识库底座服务，MNote 是 UI + source manager + permission layer**。

这不是把 LightRAG 深度嵌入 MNote，也不是让 MNote 复制 LightRAG 内部索引。LightRAG 可以直接对 MNote 暴露的本地文件夹做 RAG / OCR；MNote 只提供允许访问的目录、用户操作入口、任务控制、结果展示和引用打开。

```text
用户资料库
  PDF / EPUB / DOCX / PPTX / Markdown / 图片
        |
        v
MNote LightRAG Connector
  - allowed roots
  - workspaceId / rootUri
  - source file identity
  - task control UI
  - reference open action
        |
        v
LightRAG Service / Dashboard
  - MinerU / Docling parser
  - sidecar
  - chunk / vector / graph / rerank
  - query / query_data
  - task state
        |
        v
MNote Answer Renderer
  - answer
  - citations
  - LightRAG reference
  - MNote open action
  - locator fallback
```

MNote 不复制 LightRAG 的图谱，不把 LightRAG 的 chunk 当正文真相。LightRAG 是派生知识库；原始文件仍属于 MNote local-folder / resource tree。

### 4.1 OCR / 索引归属

知识库问答相关的 OCR、parse、chunk、vector、graph、rerank、query index 全部归 LightRAG。

MNote 不再为“问一堆书 / 问一堆论文”维护第二套 OCR / parse / chunk / vector / graph。此前 MNote 为 OCR、索引、source-map、evidence graph 维护过多套派生链路，已经制造了过多 bug 和职责冲突；7-50 的目标就是把这部分降为一个外部 provider。

MNote 可以保留轻量 UI 索引，但它只服务 MNote 正常功能：

- 页面标题、Markdown 正文快速搜索。
- tag / backlink / 最近页面。
- 文件树和资源元数据。
- 当前编辑器内搜索。

区分标准：

| 场景 | Owner |
| --- | --- |
| 搜我的笔记页面、标签、最近编辑、backlink | MNote 轻索引 |
| 问多本书 / 多篇论文 / PDF / 扫描件 / Office 附件 | LightRAG |
| 解析 PDF / OCR 图片 / 建向量 / 建图谱 / rerank | LightRAG |
| 点击来源、打开 MNote resource tab、显示降级来源 | MNote connector |

### 4.2 插件式不干扰原则

LightRAG 第一阶段必须像无害插件：

- 不修改用户 Markdown 正文。
- 不写 MNote 文件树中的业务文件。
- 不接管 MNote 普通搜索。
- 不让 MNote UI 依赖 LightRAG 才能打开页面。
- 不在 MNote active code 中复制 LightRAG pipeline。
- 不把 LightRAG parser/cache/index 失败扩散为 MNote 文件树或编辑器故障。

MNote 和 LightRAG 的连接面应尽量小：

- 配置 LightRAG endpoint / working dir / token 注入方式。
- 给 LightRAG 一组 allowed roots 或 source list。
- 触发 ingest / reindex / delete source。
- 查询 LightRAG result。
- 把 LightRAG reference 映射为 MNote open action。
- 在 MNote 中嵌入或打开 LightRAG dashboard，用于任务控制和 graph 查看。

### 4.3 Source Truth / 删除语义

7-50 的基线不采用“上传一份副本到 LightRAG staging 目录再索引”的默认模式。这个模式会制造两个问题：

- 反复真相：MNote 本地文件是一份，LightRAG input/staging 又是一份，用户编辑、移动、删除后两边容易不一致。
- 删除源后仍可检索：LightRAG 索引是派生缓存，如果没有收到 source delete / stale 标记，旧 chunk / vector / graph 仍可能继续回答。

因此 7-50 的 source truth 规则是：

- 原始资料真相永远是 MNote local-folder / resource tree 中的 host absolute path。
- LightRAG 的 storage、sidecar、chunk、vector、graph 都是派生缓存。
- MNote 默认不把用户资料复制到 LightRAG input 目录；除非 LightRAG API 当前阶段只能 upload，才允许使用临时受控 staging，并且必须记录为 spike 降级方案。
- LightRAG connector 必须维护 source registry：
  - `workspaceId`
  - `rootUri`
  - `sourcePath`
  - `sourceHash`
  - `lightRagDocId`
  - `indexedAt`
  - `deletedAt`
  - `stale`
- source 文件删除、移动、重命名或 hash 变化后，MNote watcher 必须把 registry 标记为 stale，并触发 LightRAG delete / reindex。
- 删除 source 后，query scope 必须过滤 stale / deleted source；如果 LightRAG 侧删除尚未完成，MNote 层不得把该 source 的 citation 当成有效来源展示。
- LightRAG 官方 `DELETE /documents/delete_document` 能删除文档状态、chunks、vector、graph；`delete_file=true` 还会删除 input 目录文件。MNote 集成默认只删除 LightRAG 派生索引，不删除用户原始文件。
- 改 parser、embedding dim、storage backend、source parser hint 等影响索引一致性的配置时，必须走“delete old doc -> reindex source”，不能隐式覆盖旧索引。

这个边界决定部署方式：Docker 可以用于隔离 demo，但不作为 7-50 与 MNote connector 的基线。7-50 基线采用源码 / host 部署，保证 LightRAG 能看到 MNote 的真实本地路径、watcher 能做删除同步，MNote adapter 也能以同一套路径身份做引用打开。

### 4.4 Source Truth Spike 结果

2026-06-06 已完成一个受控 source-truth spike：

- MNote source 文件：`/mnt/Data1T/Mnote_data/lightrag/source-spike/mnote-source-truth-spike.txt`
- LightRAG input 入口：`/mnt/Data1T/Mnote_data/lightrag/inputs/mnote-source-truth-spike.txt`，以 symlink 指向 source 文件。
- 触发方式：`POST /documents/scan`
- LightRAG doc id：`doc-0092d6976b80946591c9d129e92d989a`
- 处理结果：`processed`，`chunks_count=1`，`parse_engine=legacy`，`file_path=mnote-source-truth-spike.txt`
- `query` 能回答 `CARBOXY_PROTECTOR_ALPHA_7349`，并返回 reference。
- `query/data` 能返回 entities / relationships / chunks / references，其中 chunk 带 `chunk_id` 与 `file_path`。
- `DELETE /documents/delete_document` + `delete_file=false` 删除后，documents 为空，`query/data` 返回 `no_results`，`query` 返回 no-context 且 references 为空。
- 删除 LightRAG 派生索引没有删除 MNote source 文件；symlink 被 LightRAG scan 移入 `inputs/__parsed__/`。

结论：

- symlink scan 可以避免复制 source 内容，但 LightRAG 内部 `file_path` 只保留 basename，不保留 host absolute path。
- 因此 MNote connector 仍必须维护 source registry，把 `workspaceId/rootUri/sourcePath/sourceHash/lightRagDocId/indexedAt/deletedAt/stale` 映射到 LightRAG doc id 和 basename。
- `delete_file=false` 是 MNote 删除 LightRAG 派生索引的默认语义；不能让 LightRAG 删除用户 source。
- source delete / move / rename 的自动触发仍需要 MNote watcher + registry，不能仅依赖 LightRAG scan。

### 4.5 Ingestion Path Spike 结果

2026-06-06 继续补测 SDK / REST upload / input scan / symlink scan 四种入口：

| 入口 | 测试方式 | 结果 | 对 MNote connector 的判断 |
| --- | --- | --- | --- |
| SDK `ainsert` | 独立临时 storage 调用 `LightRAG.ainsert(..., file_paths=/mnt/.../source.txt)` | `processed`，chunk token 命中；source 文件未被删除；`file_path` 仍被规整成 basename | 可作为 adapter 内部能力，但不能依赖 LightRAG 保存 host absolute path；仍要 registry |
| REST `/documents/text` | 调用 text API，`file_source` 传 host absolute path | `processed`，`process_options=F`；`file_path` 被规整成 basename | 适合纯文本 / Markdown 内容直入，但无法表达真实附件生命周期 |
| REST `/documents/upload` | multipart 上传一个文本文件 | `processed`，文件被放入 `inputs/__parsed__/`；`file_path` 为上传文件名 | 只适合作 fallback / UI 手动上传，不适合作 MNote 默认 source truth |
| `input_dir` real file + `/documents/scan` | 写入真实 input 文件后触发 scan | `processed`，scan 会把 input 文件移入 `__parsed__` | 可用于受控 staging，但会制造第二份 source，不作为默认 |
| symlink + `/documents/scan` | `inputs/*.txt` symlink 指向 MNote source 文件 | `processed`，symlink 被移入 `inputs/__parsed__/`，原始 source 保留；`file_path` 为 symlink basename | 当前最接近 MNote source-truth 基线；必须由 registry 管理 symlink basename 到 host source |

额外观察：

- `/documents/scan` 在 pipeline busy 时会返回 `scanning_skipped_pipeline_busy`，不会排队；MNote connector 必须做 job ledger / retry，而不能把一次 scan 失败视作 ingestion 完成。
- SDK、text API、upload、scan 都不会保留 host absolute path 到 LightRAG `file_path`；LightRAG 引用只能作为 provider-local reference，MNote 侧必须用 `source registry` 反查。
- 本轮临时 server storage 中产生的四个测试 doc 已用 `DELETE /documents/delete_document` + `delete_file=false` 删除；独立 SDK storage 留在 `/tmp/mnote-lightrag-sdk-*` 作为一次性验证产物。

### 4.6 MNote Connector First Cut

2026-06-06 已落第一版 MNote connector，不引入完整插件市场：

- 新增 `rust/crates/mnote-web/src/routes/knowledge_rag.rs`。
- 新增 routes：
  - `GET /api/knowledge-rag/status`
  - `POST /api/knowledge-rag/ingest`
  - `POST /api/knowledge-rag/query`
  - `POST /api/knowledge-rag/open-reference`
  - `POST /api/knowledge-rag/delete-source`
- 新增 source registry：`.mnote/index/lightrag-source-registry.json`。
- `ingest` 默认创建 `input_dir` symlink 后触发 `/documents/scan`，不复制用户 source 内容。
- `delete-source` 调用 LightRAG `DELETE /documents/delete_document` 时固定 `delete_file=false`，只删除派生索引，不删除用户 source。
- `query` 只把 LightRAG raw result 作为 provider 结果返回；MNote 额外生成 `references`，用 registry 把 LightRAG `file_path` 映射回 MNote source。
- `open-reference` 未命中 registry 或 source 已 stale/deleted 时返回 `locatorDegraded=true`，不伪造 page / bbox。
- Hermes/Page AI manifest 新增：
  - `mnote.knowledge_rag.status`
  - `mnote.knowledge_rag.query`
  - `mnote.knowledge_rag.open_reference`
- 新增 skill：`skills/mnote-knowledge-rag/SKILL.md`。
- Reasonix ACP wrapper 新增对应工具：`mnote_knowledge_rag_status` / `mnote_knowledge_rag_query` / `mnote_knowledge_rag_open_reference`。
- Route smoke 已通过：
  - `GET /api/knowledge-rag/status` 返回 LightRAG `healthy` / `webui_available=true`。
  - `POST /api/knowledge-rag/ingest` 对 `knowledge-rag-route-probe.md` 创建 symlink 并触发 `scanning_started`。
  - registry 同步到 `lightRagDocId=doc-0b7eabd99e33100ed94fc929143bb632`，`indexedAtMs` 有值。
  - `POST /api/knowledge-rag/query` 返回 1 条 registry 命中的 reference，`locatorDegraded=false`。
  - `POST /api/knowledge-rag/delete-source` 返回 `deletion_started`，registry 标记 `stale=true/deletedAtMs`，原始 source 文件仍存在。
  - Hermes manifest 带 `mnote-knowledge-rag` capability pack 和三项 `mnote.knowledge_rag.*` tool。

2026-06-06 运行态复核发现：3000 dev runtime 继承了历史 `LIGHTRAG_API_KEY` 环境变量，导致 MNote connector 优先使用旧 key，请求当前 `mnote-lightrag.service` 返回 `403 Invalid API Key`。已修正 `lightrag_api_key()` 优先级为 `MNOTE_LIGHTRAG_API_KEY` -> LightRAG source `.env` -> 通用 `LIGHTRAG_API_KEY` 兜底，避免旧 LightRAG 环境污染 MNote connector。临时 3027 server 带 `LIGHTRAG_API_KEY=bad-legacy-key` 复测，status / query 均可通过 source `.env` 正确访问当前 LightRAG。

### 4.7 PDF / MinerU Sidecar 验证结果

2026-06-06 已用 `mnote-e2e` local workspace 通过 MNote connector 跑 1 本书籍 PDF、2 篇论文 PDF、1 个扫描 PDF：

| 样本 | MNote source | LightRAG doc | 结果 | 观察 |
| --- | --- | --- | --- | --- |
| 书籍 PDF | `knowledge-rag-fixtures-7-50/book-q1-fy25-earnings.pdf` | `doc-32765c52c02777e6c8f8bc452ac0157e` | `processed` | MinerU，`chunks_count=38`，`mm_chunks=25` |
| 论文 PDF | `knowledge-rag-fixtures-7-50/paper-brotli-comparison.pdf` | `doc-06f4c43d18a0398beeb0f31e91b81466` | `processed` | MinerU，`chunks_count=6`，`mm_chunks=3` |
| 论文 PDF | `knowledge-rag-fixtures-7-50/paper-masterformat-partial.pdf` | `doc-633d81d17d26727bf600f54a7591657b` | `processed` | MinerU，`chunks_count=1` |
| 扫描 / 图片 PDF | `knowledge-rag-fixtures-7-50/scan-image-start.pdf` | `doc-14a5926e5c673f446d2be735259c622f` | `processed` | MinerU，`chunks_count=1` |

补充观察：

- PDF 不应强制 `parserHint=native`；LightRAG 当前 native hint 不支持 PDF，之前强制 native 的 PDF 已验证会失败。
- 对同内容扫描 PDF 再入库时，LightRAG 会标记 duplicate，并通过 `metadata.original_doc_id` 指向原始 doc；MNote registry 当前只把 processed doc 当成可索引完成，duplicate failed 不应作为有效 citation。
- Sidecar 样本实际落在 `/mnt/Data1T/Mnote_data/lightrag/inputs/__parsed__/*.{pdf}.parsed/*.blocks.jsonl` 与对应 `*.mineru_raw/`，不提交原文 fixture。
- `blocks.jsonl` 的 content block 已包含 `positions: [{ type: "bbox", anchor: "1", range: [...] }]`，其中 `anchor` 可作为页码来源，`range` 可转为 bbox。
- LightRAG `kv_store_text_chunks.json` 与 `/query/data` chunks 当前没有 `refs` 字段；chunk 只能拿到 `chunk_id`、`file_path`、`reference_id`、`content`。因此 MNote 先把 query reference enrich 出 `chunkId` / `quote`，再用 `file_path -> parsed sidecar -> blocks.jsonl -> positions` 反查 page/bbox。
- 已新增第一版 `LightRAGSidecarLocator`：用 chunk content / chunk id fallback 匹配 sidecar block，生成 MNote `EvidenceLocator`；匹配失败时继续显示 locator degraded，不伪造页码。

当前已能把一部分 LightRAG PDF 引用升级成真正的 PDF page/bbox EvidenceLocator，但仍不是无损映射：因为 LightRAG chunk 缺少 `refs`，MNote 当前依赖 chunk quote 与 sidecar block 文本近似匹配。后续如果 LightRAG 暴露 chunk refs，应改为 refs 优先、文本匹配 fallback。

### 4.8 运行态复核结果

2026-06-06 运行态复核：

- `mnote-lightrag.service` 为 systemd user service，当前 active running；入口为 `/mnt/Data1T/Mnote_data/lightrag/LightRAG/.venv/bin/lightrag-server`，配置来自 `/mnt/Data1T/Mnote_data/lightrag/LightRAG/.env`。
- `GET /api/knowledge-rag/status` 返回 LightRAG `healthy`，`webui_available=true`，`dashboardUrl=http://127.0.0.1:9621`。
- `GET http://127.0.0.1:9621/` 跳转 `/webui/`，`GET /webui/` 返回 200；但尚未做完整浏览器交互验证 dashboard 的 documents / graph / task 面板。
- `scripts/task529-knowledge-rag-citation-resource-tab-smoke.js` 已通过：`POST /api/knowledge-rag/query` 能召回 `knowledge-rag-fixtures-7-50/scan-image-start.pdf`，citationUrl 打开本地 PDF resource tab，带 `page=1` / `bbox=171,126,648,152`，页面内 evidence 高亮渲染。
- `POST /api/hermes/tools/mnote/call` 调用 `mnote.knowledge_rag.query` 已通过，工具层能返回 references 与 `citationMarkdown`；这验证的是 agent tool 检索通道，不等于 Page AI 真实最终回答质量已验收。
- 召回已经可用，但排序还未验收：`scan image start` 查询能召回目标扫描 PDF，不过 top-1 可能是其他 PDF，后续需要专门评估 query mode / rerank / source scope。
- MNote topbar 已新增独立“资料库问答”设置入口，不混入本地索引设置；该面板能读取 `/api/knowledge-rag/status`，展示 LightRAG healthy 状态、dashboard/input/storage、source registry，并提供相对路径 source 输入、ingest、刷新、打开 dashboard 动作。浏览器 smoke 已验证面板在 3000 打开后显示 `LightRAG healthy，已登记 5 个来源`。
- `/api/knowledge-rag/ingest` 已支持 sourcePath 指向文件或目录；目录会在授权 root 内递归展开受支持文件，跳过 `.mnote` / `.git` / `node_modules` / `target` / `__parsed__` / `.venv`，并限制单次最多 200 个文件，避免误把整个工作区无限制灌入 LightRAG。对应单元测试已覆盖目录展开、内部目录跳过和不支持扩展名拒绝。
- 资料库问答设置面板已支持从当前 filetree 选中项填入 sourcePath，并在 ingest 输入行展示 `待索引` / `索引中` / `已提交` / `需重试` / `失败` 状态。浏览器 smoke 已验证选中 `knowledge-rag-fixtures-7-50` 后点击“使用选中文件树项”能把该目录写入 source 输入框。
- 运行态继续发现 `3000` dev runtime 继承了旧 Windows `INPUT_DIR=F:/SOFT/MNOTE/LightRAG/inputs` / `WORKING_DIR=F:/SOFT/MNOTE/LightRAG/data`，导致 sidecar locator 在当前 Linux LightRAG storage 中查不到 `blocks.jsonl`，`task529` 一度降级。已修正 connector 路径优先级为 `MNOTE_LIGHTRAG_*` -> LightRAG source `.env` -> 通用 legacy env -> 默认值，并补 `lightrag_paths_prefer_source_env_over_legacy_process_env` 单测。
- `task529-knowledge-rag-citation-resource-tab-smoke.js` 复跑通过：`scan image start` 当前 top reference 为 `knowledge-rag-fixtures-7-50/scan-image-start.pdf`，`citationMarkdown=[scan-image-start.pdf · p.1](...)`，`citationUrl` 带 `resourceTab/page=1/bbox=171,126,648,152/blockId=f69c1af99063b608b4031a3c51864265`，浏览器资源标签页能渲染 PDF 和 evidence 高亮。
- Agent 工具输出已改为 `mnote.knowledge_rag.agent_query_result.v1` 紧凑结构，优先给 `references/citations/citationMarkdown/locator`，不再把 LightRAG raw chunks 放在工具输出前面，避免 Page AI 最终回答看不到 citation 或把 raw retrieval 当回答。
- `hybrid` mode 已在 MNote connector 中别名到 `mix`，避免 agent 复用本地 evidence search 的 `hybrid` 习惯时召回偏离；同时对 mapped references 做 query lexical rerank，让明确文件名 / 关键词的命中优先出现在 references 前列。`query_ranking_prefers_exact_source_and_quote_match` 与 `query_mode_aliases_hybrid_to_mix_for_lightrag` 已覆盖。
- 新增 `scripts/task530-knowledge-rag-page-ai-final-answer-smoke.js`，真实浏览器打开 Page AI drawer，切到 Reasonix，发送资料库问题并验证最终可见回答包含 `scan-image-start.pdf · p.1` 的可点击 resourceTab citation，且不泄漏 raw JSON / 工具名 / 检索过程叙述。该 smoke 已通过。
- 新增 `scripts/task531-lightrag-dashboard-ui-smoke.js`，从 MNote `/api/knowledge-rag/status` 读取 `dashboardUrl` 后打开 LightRAG WebUI，真实浏览器验证 Documents / Knowledge Graph / Retrieval 三个入口可见：Documents 显示 `Completed (5)` / `Fail (4)` / 扫描 PDF doc id 与 summary，Graph 显示 `Connected`，Retrieval 显示 `Query Mode` / `KG Top K` / `Connected`。截图落在 `tmp/task531-lightrag-dashboard-ui-smoke/`。

### 4.9 旧搜索 / Evidence 退役结果

LightRAG 引入后，旧搜索链路先完成回归确认，随后按最新产品决策退役 LiteParse / evidence fallback。当前分工是：

- `/api/evidence/search` 已返回 `410 Gone` / `mnote_evidence_search_retired`，不再作为 agent fallback。
- `mnote.evidence.search/read/open` 与 `mnote.index.status/refresh/update_settings` 不再暴露在 Hermes / Reasonix manifest 与 capability pack 中。
- `/api/local-folder/ocr/jobs/status/read/insert/delete` 已返回 `410 Gone` / `mnote_local_ocr_retired`，旧 OCR sidecar API 不再作为 UI 或 agent 通道。
- `mnote-local-index` skill 退役；兼容 alias `mnote-document-evidence` / `mnote-local-index` 映射到 `mnote-knowledge-rag`。
- `/api/search/documents` 继续保留 MNote 页面 / Markdown resource 普通搜索，但 `includeOcr` 不再读取 `.mnote/ocr-index.json`；PDF / Office / 图片 OCR 与资料库问答走 LightRAG。
- `/api/knowledge-rag/query` / `mnote.knowledge_rag.query` 是资料库问答和跨资料 citation 的默认路径。
- FileTree `data-index-status` 已改为读取 LightRAG source registry，而不是 LiteParse sidecar / evidence.sqlite / local OCR index。

2026-06-06 已补跑旧链路 smoke，作为退役前基线；随后相关 active smoke 已软归档到 `recycle/20260606-liteparse-retirement/`：

- `scripts/task528-document-evidence-liteparse-agent-smoke.js` 通过：直接 `/api/evidence/search` 命中 `Printer test page`；`mnote.evidence.search` 返回同一 PDF evidence 的 `quote/page/bbox/sourceMapPath`；Reasonix ACP 实际调用 `mnote_evidence_search`；LiteParse sidecar 与 `.mnote/index/evidence.sqlite` 均存在。
- `scripts/task529-local-search-result-open-locator-smoke.js` 通过：`/api/search/documents` 搜索 `三甲基硅酯` 后，点击结果仍停留在当前文档页并打开 Markdown resource tab，定位到 `docs/Silicon.md` 命中段落，截图落在 `tmp/task529-local-search-result-open-locator-smoke/`。
- `scripts/task452-local-search-index-browser-smoke.js` 已按当前独立索引设置 surface 更新并通过：显式保存 `includePaths=["."]` 后刷新索引，初次搜索能找到新建 Markdown；导航页和文档页都能打开独立索引面板，不回落到页面设置页签；`/api/search/local-index/backlinks` 与 `/api/search/local-index/tags` 仍返回 200；重命名后刷新索引，搜索结果更新到新路径且不再返回旧路径。
- `scripts/task526-local-folder-ocr-api-smoke.js` 已从 active scripts 移到 recycle；Page AI raw resource target smoke 已改为确认不再携带 `ocrContext` / `ocrRootRelativePath`。

结论：旧 evidence 能力曾验证可用，但当前默认产品路径已切到 LightRAG；历史 sidecar 只作为归档数据解释材料，不再驱动新的 OCR / 索引 / agent 检索。

### 4.10 DOCX / Office Ingestion 验证结果

2026-06-06 新增 `scripts/task532-knowledge-rag-docx-ingestion-smoke.js`，用现有 OnlyOffice smoke DOCX 生成带唯一 marker 的 DOCX fixture，走 MNote `/api/knowledge-rag/ingest` 入库并真实查询：

- DOCX source：`knowledge-rag-fixtures-7-50/docx-rag-smoke-1780745370830.docx`
- LightRAG doc id：`doc-2f561f74048372a3f66b7bbe8a6e713a`
- LightRAG file path：`mnote-4e26c0dd3d2bf575-docx-rag-smoke-1780745370830.docx`
- 查询 marker：`DOCX RAG SMOKE 1780745370830`
- 结果：LightRAG 能解析 DOCX 正文并召回包含 marker 的 chunk；MNote registry 能把 LightRAG file_path 映射回 workspace source path。
- citation：DOCX 当前没有 PDF page/bbox sidecar locator，因此 `locatorDegraded=true`；但 connector 已补 fallback citation URL，把引用打开到同工作区 Markdown host 页并恢复 DOCX resource tab，浏览器验证 `panelKind=office`、`panelResourcePath=knowledge-rag-fixtures-7-50/docx-rag-smoke-1780745370830.docx`。

结论：DOCX ingestion、召回、source registry 映射和资源 tab 回跳已跑通；DOCX 仍没有页码/bbox 级定位。PPTX/XLSX 还未作为 7-50 验收样本补测。

### 4.11 Source Watcher / Stale Sync 验证结果

2026-06-06 已把 LightRAG source registry 同步接入 MNote 现有 local-folder watcher，而不是新增第二套 watcher：

- `rust/crates/mnote-web/src/routes/local_folder_events.rs` 的 tree live watcher 收到 `watch_batch` 前，会调用 `knowledge_rag::sync_registry_for_root(...)`。
- `knowledge_rag::sync_registry_with_documents(...)` 会同步 LightRAG `/documents` 状态，并额外检查 registry 中 source 的当前文件状态。
- source 文件不存在时：registry 标记 `stale=true`、`deletedAtMs`、清空 `lightRagDocId/indexedAtMs`，并 best-effort 调用 LightRAG `DELETE /documents/delete_document`，固定 `delete_file=false`。
- source hash 变化时：registry 标记 `stale=true`、清空旧 `lightRagDocId/indexedAtMs`、更新 `sourceHash`，并 best-effort 删除旧 LightRAG doc，避免旧 chunk 继续作为有效引用。
- `mapped_references(...)` 过滤 stale / deleted registry 命中的 references；即使 LightRAG 删除尚未完成，MNote query 结果也不把该 source 当成有效 citation 返回。

新增验证：

- `cargo test -p mnote-web knowledge_rag -- --nocapture` 通过 14 项；其中 `source_state_marks_deleted_and_changed_entries_stale` 覆盖删除 / hash 变化 registry 状态。
- `scripts/task533-knowledge-rag-source-watcher-sync-smoke.js` 通过：真实 ingest `knowledge-rag-fixtures-7-50/watcher-stale-1780745838741.md`，打开 `/api/local-folder/events?treeLive=true`，删除 source 后收到 `Remove(File)` watch_batch；不调用 status 的情况下直接读 registry，确认 `stale=true`、`deletedAtMs`、`lightRagDocId=null`、`indexedAtMs=null`；随后 query marker 不再返回该 source 的有效 reference。

当前边界：delete / missing source 的 watcher 闭环已浏览器验证；hash 变化由单元测试覆盖；rename / move 本质上会让旧 source path missing，走同一 stale/delete 逻辑，但尚未单独补浏览器 smoke。hash 变化后的自动“重建新 doc”仍保守为 stale + 需要重新 ingest，避免在任意文件保存事件上自动把大文件重新灌入 LightRAG。

### 4.12 Source 管理 UI / Query Scope 验证结果

2026-06-06 继续补齐 source 管理和查询范围：

- 资料库问答设置面板的 registry 行新增 `重索引` / `删除索引` 操作。
- `重索引` 对单个 source 调用 `/api/knowledge-rag/ingest`，用于 stale / retry source 的行级重试。
- `删除索引` 对单个 source 调用 `/api/knowledge-rag/delete-source`，仍固定 `delete_file=false`，只删除 LightRAG 派生索引，不删除用户 source。
- `mnote.knowledge_rag.query` / `/api/knowledge-rag/query` 新增 `sourcePaths` 参数，接受 workspace 相对文件或目录；MNote 对 mapped references 做 source scope 过滤。
- LightRAG `/query/data` 在部分情况下只返回 `data.chunks`，不返回可直接消费的 top-level references；MNote connector 已补 chunks fallback，把 chunk 的 `file_path/reference_id` 生成 reference candidate，再走 registry 映射和 source scope。
- 修复了一个 stale registry 匹配 bug：没有 `doc_id` 的 reference 不得错误命中 `lightRagDocId=None` 的已删除 entry。

新增验证：

- `cargo test -p mnote-web knowledge_rag -- --nocapture` 通过 17 项；新增覆盖 source scope、chunks fallback reference、已删除 entry 不误匹配。
- `scripts/task534-knowledge-rag-source-management-scope-smoke.js` 通过：创建 alpha/beta 两个 Markdown sources，`sourcePaths=[alpha]` 时 scoped query 只返回 alpha；浏览器打开资料库问答面板，确认 source row 有行级 `重索引` / `删除索引`；点击 `删除索引` 后 UI 显示已删除，原始 alpha 文件仍存在；删除后 scoped query 不再返回 alpha reference。

结论：source 管理 UI 已从“只能批量输入路径”推进到 registry 行级 reindex/delete；query scope 已可按 source 文件或目录过滤 MNote references。排序层已有 query lexical rerank 和 `hybrid -> mix` alias；真实 rerank 模型仍保持关闭，后续仅在样本证明需要时评估。

## 5. Provider 合同

第一版只需要一个内部 provider 合同，不做完整插件系统。

```rust
KnowledgeRagProvider {
  status(workspace_id, root_uri) -> ProviderStatus
  configure_sources(source_refs, options) -> ConfigureResult
  ingest_or_reindex(source_refs, options) -> IngestJob
  query(question, scope, options) -> RagAnswer
  query_data(question, scope, options) -> RagRetrievalData
  open_reference(reference_id, chunk_id?) -> OpenReferencePlan
  delete_source(source_ref) -> DeleteResult
}
```

LightRAGAdapter 实现该合同。

MNote 侧保留：

- `workspaceId`
- `rootUri`
- `allowedRoots`
- resource source path
- owner document / resource tab mapping
- open action / locator fallback
- citationMarkdown / citationUrl 生成
- LightRAG dashboard embedding

LightRAG 侧保留：

- parser routing
- OCR / MinerU / Docling
- sidecar artifacts
- vector / graph storage
- query modes
- reranker
- parse cache
- task state / graph view / dashboard

## 6. 初始配置

第一阶段优先把 LightRAG 以源码 / host 方式独立跑起来，再让 MNote 通过 connector 访问。不要先改 MNote 主链。

部署原则：

- 7-50 基线：源码编译 / host service。
- Docker：只用于隔离 demo 或确认官方 dashboard，不作为 MNote connector 默认路径。
- LightRAG 服务绑定 `127.0.0.1`，不暴露公网。
- LightRAG storage 放到 MNote 控制范围外的派生缓存目录，例如 `/mnt/Data1T/Mnote_data/lightrag/rag_storage`。
- LightRAG source 读取 MNote allowed roots 中的真实文件路径；如果官方 scan 只能扫描单一 input dir，先用最小 source spike 确认是否支持 host path / symlink / SDK 直入，再决定是否需要 adapter。
- 任何 staging / upload 降级都必须带 registry 映射和删除同步，不得成为长期主线。

LightRAG 初始配置优先使用官方 MinerU API，减少本地服务数量：

```bash
HOST=127.0.0.1
PORT=9621
CORS_ORIGINS=http://localhost:3000,http://127.0.0.1:3000
WORKING_DIR=/mnt/Data1T/Mnote_data/lightrag/rag_storage
INPUT_DIR=/mnt/Data1T/Mnote_data/lightrag/inputs

LIGHTRAG_KV_STORAGE=JsonKVStorage
LIGHTRAG_VECTOR_STORAGE=NanoVectorDBStorage
LIGHTRAG_GRAPH_STORAGE=NetworkXStorage
LIGHTRAG_DOC_STATUS_STORAGE=JsonDocStatusStorage

LLM_BINDING=openai
LLM_BINDING_HOST=http://127.0.0.1:20128/v1
LLM_MODEL=aigc/qwen-3.5
LLM_TIMEOUT=180
MAX_ASYNC_LLM=4
KEYWORD_MAX_ASYNC_LLM=4
QUERY_MAX_ASYNC_LLM=4

VLM_LLM_BINDING=openai
VLM_LLM_BINDING_HOST=http://127.0.0.1:20128/v1
VLM_LLM_MODEL=aigc/qwen-3.5
VLM_MAX_ASYNC_LLM=1

EMBEDDING_BINDING=openai
EMBEDDING_BINDING_HOST=http://127.0.0.1:20128/v1
EMBEDDING_MODEL=nvidia/baai/bge-m3
EMBEDDING_DIM=1024
EMBEDDING_TOKEN_LIMIT=8192
EMBEDDING_SEND_DIM=false
EMBEDDING_FUNC_MAX_ASYNC=8
EMBEDDING_BATCH_NUM=32
EMBEDDING_TIMEOUT=60

ENABLE_LLM_CACHE=false
ENABLE_LLM_CACHE_FOR_EXTRACT=true

CHUNK_SIZE=1200
CHUNK_OVERLAP_SIZE=100
TOP_K=40
CHUNK_TOP_K=20
MAX_ENTITY_TOKENS=6000
MAX_RELATION_TOKENS=8000
MAX_TOTAL_TOKENS=30000
KG_CHUNK_PICK_METHOD=VECTOR
RELATED_CHUNK_NUMBER=5
COSINE_THRESHOLD=0.2

MAX_PARALLEL_INSERT=3
MAX_PARALLEL_PARSE_NATIVE=5
MAX_PARALLEL_PARSE_MINERU=2
MAX_PARALLEL_ANALYZE=3
MAX_UPLOAD_SIZE=0

LIGHTRAG_PARSER=*:native-iteP,*:mineru-iteP,*:legacy-R
MINERU_API_MODE=official
MINERU_API_TOKEN=<from MNote secret store>
MINERU_OFFICIAL_ENDPOINT=https://mineru.net
MINERU_MODEL_VERSION=vlm
MINERU_IS_OCR=false
MINERU_LANGUAGE=ch
MINERU_ENABLE_TABLE=true
MINERU_ENABLE_FORMULA=true
MINERU_POLL_INTERVAL_SECONDS=2
MINERU_MAX_POLLS=300
VLM_PROCESS_ENABLE=true
SUMMARY_LANGUAGE=Chinese
ENTITY_EXTRACTION_USE_JSON=true
```

当前默认文本 LLM、extract/query 与 VLM 已统一为 `aigc/qwen-3.5`，服务入口为 `http://127.0.0.1:20128/v1`。此前 `deepseek-v4-flash` / Nemotron VLM 结论只保留为历史模型筛选记录，不再作为当前默认配置。embedding 继续使用 OmniRoute / NVIDIA 的 `nvidia/baai/bge-m3`，维度固定为 `1024`，必须在首次 ingest 前确定，后续不能随意改。

VLM 候选实测结论：

- `nvidia/nemotron-nano-12b-v2-vl:free`：OpenRouter 直连可用；红色矩形识别正确约 2.7s，真实杯子图片约 6.1s；曾作为免费 VLM canary 对照，当前默认已切到 `aigc/qwen-3.5`。
- `nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free`：OpenRouter 直连返回空内容，不采用。
- `nvidia/nemotron-3.5-content-safety:free`：主要返回安全分类，不适合作通用 VLM。
- OmniRoute / NVIDIA 的 Nemotron VLM 路线：当前多返回图片 unavailable / 无法查看图片，暂不采用。
- `agnes-2.0-flash`：文本问答可用；图像输入可识别简单图片，但 VLM 延迟不稳定，真实图片可到 80s+，降为备选。
- `geminipay/gemini-3.1-flash-lite-preview`：通过简单图像输入测试，响应约 1s，但属于收费账号，不作为默认。
- `cx/gpt-5.4-mini` / `codex/gpt-5.4-mini` / `xx/gpt-5.4-mini`：可调用，但对图像回答“无法判断”，不适合作为 VLM 默认。
- `agnes-image-2.0-flash` / `agnes-image-2.1-flash` 属于图像生成 / 编辑方向，不是 LightRAG 所需的 image-to-text VLM；按 chat completions 测试返回 404，暂不纳入 LightRAG VLM。

复杂截图补测：

- 测试图：MNote Page AI 复杂网页截图，压缩到 `888x650`、约 `41KB`。
- `nvidia/nemotron-nano-12b-v2-vl:free`：约 `5.9s`，能提取中心标题和关键 token，但把右侧标题误读为“页面截面视图”。
- `agnes-2.0-flash`：约 `9.6s`，中心标题、右侧“页面 AI”和 token 提取更准确。
- 历史结论：Nemotron 免费 VLM 速度和可用性较好，曾适合作 canary；当前默认已切到 `aigc/qwen-3.5`，高精度 UI/OCR 场景仍需继续用样本评估。

本地 embedding 平台补测：

- 本机 Ollama 已有 `bge-m3:latest`，embedding 维度 `1024`，模型 F16，约 `1.1GB`，当前通过 Ollama 100% CPU 执行。
- 64 段中文文本 embedding：Ollama 本地 `bge-m3` 约 `33.7s`；OmniRoute / NVIDIA `nvidia/baai/bge-m3` 约 `1.6s`。
- Ollama 运行 `bge-m3` 后新增 runner RSS 约 `1.3GB`，GPU 显存基本不变。
- 当前不建议切本地 embedding 默认；若要本地化，应优先评估 llama.cpp / CUDA 或 quantized GGUF server，而不是直接用 Ollama F16 CPU 路线。

Embedding / rerank 当前建议：

- 默认 embedding 继续使用 `nvidia/baai/bge-m3`，不要在正式样本 ingestion 前频繁切换；embedding 模型或维度变化会要求重建索引。
- 本地 embedding 只保留为后续优化方向，优先路线是 `llama.cpp + bge-m3 GGUF + CUDA`；Ollama F16 CPU 路线不适合作默认批量建库。
- 备选 embedding 中，`nvidia/nv-embedqa-e5-v5` 实测可用且维度 `1024`，但需要 `input_type=query/passage` 这类 asymmetric 参数；LightRAG 接入复杂度高于当前 `bge-m3`，暂不切换。
- `openrouter/openai/text-embedding-3-small` 可用但维度 `1536`，切换会改变索引维度；当前不采用。
- rerank 先保持 `RERANK_BINDING=null`。OmniRoute 中可见 `nvidia/nv-rerankqa-mistral-4b-v3`，但当前 `/v1/rerank`、`/rerank`、`/v2/rerank`、`/v1/ranking` 等常见端点实测 404，暂不能直接按 LightRAG rerank binding 配。
- 若真实样本出现“召回足够但排序差”，优先本地评估 `bge-reranker-v2-m3` 或 `Qwen3-Reranker-0.6B`，通过 Cohere-compatible / vLLM-compatible 服务接入 LightRAG。

不要直接套用泛化配置里的旧变量名：

- `LLM_API_KEY` / `LLM_API_BASE` 应改为 LightRAG v1.5 的 `LLM_BINDING_API_KEY` / `LLM_BINDING_HOST`。
- `EMBEDDING_API_KEY` / `EMBEDDING_API_BASE` 应改为 `EMBEDDING_BINDING_API_KEY` / `EMBEDDING_BINDING_HOST`。
- `SERVER_HOST` / `SERVER_PORT` 应改为 `HOST` / `PORT`。
- `CHUNK_OVERLAP` 应改为 `CHUNK_OVERLAP_SIZE`。
- `KV_STORAGE` / `VECTOR_STORAGE` / `GRAPH_STORAGE` / `DOC_STATUS_STORAGE` 应改为 `LIGHTRAG_*_STORAGE`。
- `TEXTRACT_USE_OCR` / `OCR_ENGINE` / `OCR_WORKERS` 不是当前 LightRAG v1.5 API server 的 MinerU 路线变量；当前应使用 `LIGHTRAG_PARSER` + `MINERU_API_MODE` + `MINERU_*`。

`ENABLE_LLM_CACHE=false` 是有意设置：source delete / stale 语义验证前，不缓存最终问答，避免删除源后自然语言回答仍从 cache 命中。`ENABLE_LLM_CACHE_FOR_EXTRACT=true` 保留，只缓存抽取过程，降低重复建库成本。

后续大量书籍批处理时再评估本地 MinerU：

```bash
MINERU_API_MODE=local
MINERU_LOCAL_ENDPOINT=http://localhost:8000
```

默认 query 策略：

- 宽泛跨书总结：`mode=mix` 或 `mode=global`，开启 rerank。
- 指定文档细节：先在 MNote scope 限制到 source，再用 LightRAG query。
- 只要需要可点击来源，必须走 `query_data` 或补充读取 chunk/sidecar，不能只消费自然语言 answer。

第一阶段可接受 MNote 只打开 LightRAG 自身 UI / dashboard，先验证 ingestion、OCR、query、graph view 和引用质量；MNote 内嵌 UI 延后。

## 7. LiteParse 退役结果

LiteParse 已从默认路径退役：

- [x] LightRAG 能处理当前样本 PDF / DOCX / 图片 PDF。（PDF / 图片 PDF 已跑通；DOCX 已通过 `task532` 验证 ingestion / query / resource tab fallback citation）
- [x] MinerU official token 路线在 MNote secret 注入后可跑通。
- [x] LightRAG sidecar `blockid -> positions -> page/bbox` 能映射到 MNote EvidenceLocator。（已通过扫描 PDF smoke；当前为 quote/block 文本匹配 fallback，不是 refs 无损映射）
- [x] 查询结果能返回可点击 citation，打开到 resource tab / page / bbox。（`task529-knowledge-rag-citation-resource-tab-smoke` 已通过）
- [x] 旧 evidence search 已完成退役前回归，随后 `/api/evidence/search` / agent evidence tools 从默认路径移除。
- [x] 删除或重建知识库不会删除用户原始文件。
- [x] 旧 LiteParseProvider 的测试覆盖有替代路径或明确归档说明。（见 7.1；LightRAG PDF/DOCX/扫描 PDF 路线作为新资料默认）

### 7.1 LiteParse -> LightRAG Cutover

当前切换策略是“active 退役 + recycle 软归档 + 新资料默认 LightRAG”：

| 代码 / 能力 | 当前状态 | Cutover 决策 |
| --- | --- | --- |
| `evidence_parse.rs` / `LiteParseProvider` | active provider 返回 `liteparse_retired`；历史实现软归档到 `recycle/20260606-liteparse-retirement/` | 不再调用 `lit` / `liteparse` CLI |
| `local_search_index.rs` 的资源 parse sidecar 入库 | 不再为 PDF / Office 调用 LiteParse parse sidecar | PDF / Office / 图片 OCR 走 LightRAG source registry + query |
| `/api/evidence/search`、`mnote.evidence.search/read/open` | `/api/evidence/search` 返回 retired；agent manifest 不再暴露 evidence tools | 使用 `mnote.knowledge_rag.query/open_reference` |
| `/api/local-folder/ocr/*` 与 `.mnote/ocr-index.json` 检索 | HTTP API 返回 retired；active UI 不再调用旧 OCR sidecar；`includeOcr` 不再追加 OCR sidecar 搜索结果 | 图片 / PDF / Office 统一通过 `mnote.knowledge_rag.status/ingest/query/delete-source` |
| `skills/mnote-local-index/SKILL.md` | 软归档到 recycle；active capability pack 删除 | 兼容 alias 映射到 `mnote-knowledge-rag` |
| FileTree `data-index-status` | 从 LightRAG registry 读取 indexed / indexing / failed | 旧 evidence.sqlite / OCR index 不再决定文件树勾选状态 |
| `skills/mnote-knowledge-rag/SKILL.md` | 新资料库问答优先走 LightRAG | 作为多书 / 多论文 / PDF / DOCX 的默认入口 |
| 7-46 / 7-48 evidence 设计稿 | 仍解释旧 sidecar / evidence index 生命周期 | 保留为历史解释 / migration note |

执行顺序：

1. 退役 LiteParse active provider 和 agent evidence / local-index capability。
2. 顶栏 OCR / 本地索引入口并入 LightRAG 资料库问答入口。
3. FileTree 勾选 / 失败状态从 LightRAG registry 读取。
4. FileTree 右键“生成 OCR”替换成“加入资料库索引”。
5. 资源页 / Page AI target / Reasonix ACP 不再调用旧 OCR/evidence/index 工具。
6. 历史 LiteParse / local OCR 代码、skill、smoke 软归档到 recycle。

退役顺序：

1. 新导入资料默认走 LightRAG。
2. Agent 工具默认只暴露 LightRAG knowledge RAG。
3. FileTree 状态绑定 LightRAG source registry。
4. 历史 LiteParse sidecar 只保留 migration note，不再作为 UI / agent fallback。

### 7.2 MNote / LightRAG Coupling Review Fix

2026-06-06 人工复核后继续收口 MNote 与 LightRAG 的耦合状态：

- 顶栏只保留 1 个 `资料库问答` 入口；历史 OCR task toggle 不再由 resource tab runtime 动态创建。
- 删除 source 后，`/api/knowledge-rag/delete-source` 会把 registry 标为 `delete_submitted` 或 `delete_completed`；后续 `/api/knowledge-rag/status` 会对照 LightRAG `/documents` 自动把已消失的 doc 标为 `delete_completed`。
- FileTree 状态语义调整为：`indexed` 绿灯、`indexing` 黄灯、`failed` 红灯、未索引或 `delete_completed` 无灯；`delete_submitted` 作为黄灯，不再被误显示成失败。
- 新增 `/api/knowledge-rag/prune-registry` 与 UI `清除失效记录`，用于一键清理已删除 / 过期 / 失败的 registry 记录；仍在 `delete_submitted` 的记录不会被清掉，避免隐藏 LightRAG 后台删除尚未确认的状态。
- 新增索引输入去重，同一批重复 source 不会重复提交；相同 `sourcePath + sourceHash` 已登记且未过期时，非 `force` ingest 会返回 `already_registered`。
- 新增索引 / 删除 / prune 成功后会触发 `mnote:knowledge-rag-source-updated`，设置面板和 FileTree 会立即刷新；LightRAG busy 时也会刷新 registry 并把 source 保持为等待 / 处理中状态。
- 设置面板不再默认显示空输入行的 `待索引` 标签，避免与上方 source registry 状态重复。
- Dashboard URL 在 LAN 访问 MNote 时会把 `127.0.0.1` / `localhost` 改写为当前 MNote host；如果 LightRAG 服务自身仍只绑定 loopback，下一步应改 LightRAG bind host 或做 MNote 反向代理。
- 2026-06-06 追加复核：LightRAG 已切到 `aigc/qwen-3.5`，MNote status 面板会显示当前 LLM model；`/api/knowledge-rag/status` 额外返回 LightRAG `/documents` 摘要和状态分组，UI 同时显示 `MNote 登记来源数` 与 `LightRAG 文档数`，并把未映射到 MNote registry 的 LightRAG 文档列为 `LightRAG 未映射` 分类。
- 资料库设置 UI 调整为“操作在上、列表在下”，来源列表新增分类过滤：`需处理`、`索引中`、`失败/过期`、`已索引`、`已移除`、`LightRAG 未映射`、`全部`；默认优先显示需处理项，减少成功项噪音。
- 补齐 `travel_explore` 本地 SVG mask，避免资料库入口在 Material Symbols 字体不可用时显示成黑色方块。

本轮验证：

- `node --check` 覆盖 `sidebar-page-settings-runtime.js`、`sidebar-tree-runtime.js`、`document-resource-tab-runtime.js`、`sidebar-tree-live-apply-runtime.js`。
- `cargo check -p mnote-web` 通过。
- `cargo test -p mnote-web knowledge_rag -- --nocapture` 通过 21 项。
- `cargo test -p mnote-web local_file_tree_marks_lightrag_indexed_indexing_and_failed_source_files -- --nocapture` 通过，覆盖 indexed / indexing / failed / delete_submitted / delete_completed。
- `cargo test -p mnote-web sidebar_settings_runtime_routes_index_and_ocr_to_lightrag_settings -- --nocapture` 与 `page_layout_exposes_lightrag_knowledge_rag_settings_only` 通过。
- 浏览器复核 `http://127.0.0.1:3000/`：topbar `资料库问答` 入口数量为 1，旧 OCR / 本地索引入口数量为 0；面板显示 `LightRAG healthy`、有 `清除失效记录`，空输入行不显示 `待索引`；旧 deleted registry 已同步为 `LightRAG 已移除` 且 FileTree 无灯。

### 7.3 Status Bridge / Image Wrapper Follow-up

2026-06-07 复核确认：LightRAG 切到 `aigc/qwen-3.5` 后索引速度恢复，但 MNote 仍必须主动同步后台完成状态，不能假设 LightRAG 会向 MNote 推送事件。

当前补充口径：

- LightRAG 当前文本 LLM、extract/query 与 VLM 统一使用 `aigc/qwen-3.5`；VLM host 为 `http://127.0.0.1:20128/v1`，status 为 healthy。此前 `deepseek-v4-flash` 只作为历史调试背景，不再作为当前默认模型口径。
- MNote ingest / reindex 后启动有界 status bridge/backoff，对照 LightRAG `/documents` 同步 `processing/submitted -> processed/failed`，再刷新 source registry、资料库设置面板和 FileTree 灯号；这不是长期无界轮询。
- LightRAG Documents 页面看不到原始图片文件是预期边界：当前 `/documents/scan` 不直接索引 `png/jpg`，MNote 为图片 source 生成 Markdown wrapper，再由 LightRAG 索引 wrapper 文档，同时 registry 仍映射回原始图片路径。
- `MNote 登记来源数` 与 `LightRAG 文档数` 应优先看是否一一映射；未映射文档只作为 LightRAG 残留 / 外部手动导入提示，不作为 MNote source truth。
- 清空历史时只清 LightRAG 派生 documents / input wrapper / parsed cache 与 MNote registry，不删除 workspace 原始资料。

## 8. 不做事项

- 不继续开发 7-49 的 `mnote.understanding.*` 工具。
- 不继续开发自研 understanding.sqlite。
- 不做 mindmap projection 作为知识库默认视图。
- 不默认接入 PageIndex。
- 不把 Understand Anything dashboard 作为 MNote 主 dashboard。
- 不同时默认维护 LiteParse + LightRAG + PageIndex 多套 provider。
- 不让 LightRAG 写用户 Markdown 正文。
- 不把 LightRAG sidecar 当用户可编辑真相。
- 不让 MNote 为 LightRAG 结果再建一套 RAG 索引。
- 不为了 LightRAG 改动 MNote 文件树、编辑器、普通搜索的主路径。

## 9. 插件系统判断

当前不开发完整插件系统，但按插件边界实施。

原因：

- 近期真实需要的知识库 provider 只有 LightRAG 一个。
- 过早插件化会引入 manifest、生命周期、权限、版本、升级、隔离和 UI 管理成本。
- MNote 现在更需要稳定 provider boundary，而不是多 provider marketplace。
- LightRAG 已经有自己的任务、图谱、解析和 dashboard 能力，MNote 不应复制一套控制面。

第一版只做“无害集成”：

- 配置项：LightRAG endpoint / working dir / MinerU token secret key / parser mode。
- 状态页：provider status、job status、storage path、最近错误、dashboard URL。
- 工具层：query / ingest / reindex / delete source / open reference。
- UI 层：先外链或 iframe 嵌入 LightRAG dashboard，用于任务控制、graph 查看和 ingestion 状态。

当出现第二个稳定 provider，且必须和 LightRAG 并存时，再抽正式插件系统。

## 10. 实施 Checklist

### A. 退役 7-49

- [x] 7-49 从 active `design/07-ai/process` 移出。
- [x] 7-49 标记为 `[recycle]`。
- [x] 撤回 `mnote.understanding.*` route / tool / skill 接线。
- [x] 删除未落地主线的 `understanding.rs` untracked 代码。
- [x] 7-50 明确不再沿 Docker staging 作为 MNote connector 基线。

### B. LightRAG Spike

- [x] 固定 LightRAG 参考版本和源码 / host 运行方式。
- [x] 建立最小 LightRAG server / SDK 本地运行脚本。
- [x] 验证 LightRAG 源码运行依赖版本；如 Python 3.14 不兼容，改用专用 Python 3.12/3.13 venv。
- [x] 验证 OmniRoute OpenAI-compatible 模型在 LightRAG client 下可用；当前默认已从历史 `deepseek-v4-flash` 切到 `aigc/qwen-3.5`。
- [x] 挑选快速 / 便宜的 OmniRoute 视觉模型，`geminipay/gemini-3.1-flash-lite-preview` 可用但因收费不作为默认。
- [x] 筛选 OpenRouter 免费 VLM 与 Agnes 免费模型；当前默认已统一为 `aigc/qwen-3.5`，历史 VLM canary 仅保留为对照记录。
- [x] 验证 `nvidia/baai/bge-m3` embedding 维度和 LightRAG 配置一致。
- [x] 测试本地 Ollama `bge-m3` embedding 代价，并与 OmniRoute / NVIDIA embedding 对照。
- [x] 筛选 embedding / rerank 候选并冻结当前默认：embedding 继续 `nvidia/baai/bge-m3`，rerank 暂不开。
- [x] 使用复杂 MNote UI 截图补测 VLM OCR / UI 理解能力。
- [x] 接入 MinerU official token，不把 token 暴露给前端。
- [x] 对照外部 env 建议，补齐 LightRAG v1.5 实际识别的 storage / chunk / query / concurrency / MinerU 参数。
- [x] 用 symlink scan 跑通受控 source 文件 ingestion，避免默认复制 source 内容。
- [x] 明确 source registry 字段和 stale / deleted 过滤规则。
- [x] 验证 `query_data` 返回 chunk/reference。
- [x] 验证 `DELETE /documents/delete_document` 删除后旧 source 不再可检索。
- [x] 验证 SDK / upload / symlink / scan 四种路径中哪一种最适合 MNote connector 长期使用。
- [x] 验证 MNote source 删除后能触发 LightRAG delete，不删除用户原始文件。（显式 `delete-source` route 与 watcher stale sync 均已覆盖；watcher smoke 见 `task533`）
- [x] 用 1 本书籍 PDF、1 个扫描 PDF、2 篇论文跑 ingestion。
- [x] 保存 sidecar 样本到 `tmp/` 或测试 fixture，不提交敏感原文。（样本保留在 LightRAG `inputs/__parsed__` 派生缓存，不提交）
- [x] 验证 LightRAG dashboard 能查看任务、graph、文档状态。（`task531-lightrag-dashboard-ui-smoke.js` 已通过：Documents 显示 completed/fail/doc summary，Knowledge Graph / Retrieval 均显示 connected）
- [x] 验证 chunk 能反查 sidecar 并生成 locator。（当前不是 refs 无损映射，而是 `file_path + quote/chunk content` 匹配 sidecar block）
- [x] 验证 sidecar position 能生成 MNote EvidenceLocator。（`task529` 已验证 PDF resource tab / page / bbox / 高亮）

### C. MNote Adapter

- [x] 新增内部 `KnowledgeRagProvider` 合同。
- [x] 新增 `LightRAGAdapter`，只封装 HTTP / SDK 调用，不复制 LightRAG 逻辑。（当前落为 `knowledge_rag` route adapter，未额外抽 trait）
- [x] 新增 provider status route。
- [x] 新增 dashboard URL / open route。
- [x] 新增 ingestion / reindex job 控制 route。
- [x] 新增 query route。
- [x] 新增 open reference resolver。
- [x] Hermes / Page AI 只看到 MNote tool，不直接看到 LightRAG 内部路径。
- [x] MNote 普通页面搜索、文件树、编辑器不依赖 LightRAG 可用性。
- [x] Connector 避免被历史 `LIGHTRAG_API_KEY` 污染，优先使用 MNote 专用 key 或 LightRAG source `.env`。

### D. UI / Agent 闭环

- [x] Page AI 能选择“资料库问答”模式。（通过 `mnote-knowledge-rag` capability pack 暴露）
- [x] Agent skill 只暴露少量知识库工具：status、query、open_reference。（reindex/ingest 暂只保留 HTTP route，不暴露给只读 agent）
- [x] 回答必须带 citations。（skill 要求引用 `references` / `citationMarkdown`）
- [x] citation 能打开到原文 resource tab。（`task529` 已通过）
- [x] citation 能展示 page / bbox / quote 降级状态。（已返回 `chunkId` / `quote`，并能在扫描 PDF 样本生成 page/bbox；未命中时继续降级，不伪造）
- [x] 没有 locator 时明确显示“来源定位降级”，不伪造页码。
- [x] Page AI 真实回答能使用 RAG citation，而不是只验证 tool 层。（`task530-knowledge-rag-page-ai-final-answer-smoke.js` 已通过：Reasonix 最终可见回答引用 `scan-image-start.pdf · p.1` 可点击 resourceTab 链接）
- [x] MNote 中可以进入 LightRAG UI 进行任务控制和 graph 查看。（通过 MNote `/api/knowledge-rag/status` 的 `dashboardUrl` 打开 WebUI，`task531` 已浏览器验证 Documents / Knowledge Graph / Retrieval）

### E. LiteParse 退役

- [x] 对照 LiteParse 当前能力和 LightRAG sidecar 能力。（见 7.1）
- [x] 列出仍依赖 LiteParse 的代码路径。（见 7.1）
- [x] 把 LiteParse 默认 provider 切到 LightRAG，不再 fallback 到 evidence。
- [x] 删除 active UI 中的 LiteParse / 本地索引 / OCR 专属入口。
- [x] FileTree 勾选 / 失败状态改为读取 LightRAG source registry。
- [x] 软归档 LiteParse / local OCR 历史代码与 smoke 到 `recycle/20260606-liteparse-retirement/`。

### F. 当前剩余闭环

当前 7-50 v1 已可归档；下面是本轮收口项与非阻塞后续：

- [x] LightRAG 资料库设置 UI：不能混入现有 MNote 本地索引设置；需要独立 surface，显示 provider status、dashboard URL、working dir、input dir、source registry、最近错误。（已落独立 topbar 入口与状态面板）
- [x] LightRAG source 管理 UI：支持从当前 local-folder 中选择要索引的文件 / 目录，调用 `/api/knowledge-rag/ingest`，展示 indexing / processed / stale / deleted / retryRequired 状态。（已支持手填、从 filetree 选中项填入路径、输入行状态、registry 行级 reindex/delete；`task534` 已浏览器验证）
- [x] LightRAG dashboard 接入：第一步可以外链打开 `dashboardUrl`，第二步再评估 iframe；必须浏览器验证 documents / graph / task 状态可见。（`task531` 已完成外链 dashboard 的 documents / graph / retrieval 验证；iframe 仍作为后续体验评估，不阻塞 v1）
- [x] source watcher 自动同步：source 删除 / 移动 / 重命名 / hash 变化后，自动标记 registry stale，并触发 delete / reindex；不能只依赖显式 `delete-source` route。（`task533` 验证删除事件；hash 变化有单测；重命名 / 移动复用旧 path missing 逻辑；自动重建新 doc 当前保守为 stale + 重新 ingest）
- [x] 查询 scope 与排序：支持按选中 source / 目录限制 RAG 查询；`hybrid -> mix` alias 和 MNote lexical rerank 已先落地，仍需评估 `mix/global/local`、`topK/chunkTopK` 与 rerank。（`sourcePaths` 已落 route / Hermes / Reasonix schema，`task534` 验证按 source 文件过滤；rerank 仍按 7-50 结论默认关闭）
- [x] Page AI 真实回答 smoke：不仅验证 Hermes tool 能返回 references，还要验证 Page AI 最终回答使用 `citationMarkdown`，不会把 retrieval raw 当最终答案，也不会伪造页码。（`task530` 已通过）
- [x] DOCX / Office 样本 ingestion：补测 LightRAG 对 DOCX / Office 附件的解析与 citation 回跳能力。（`task532` 已验证 DOCX 解析、marker 召回、registry 映射和 DOCX resource tab fallback citation；PPTX/XLSX 未纳入本轮）
- [x] 旧 evidence search 退役：保留历史回归证据，但 active route / agent tool 不再作为 fallback；新检索与 OCR / 索引统一走 LightRAG。
- [x] LiteParse 退役设计：见 7.1；结论已从冻结 fallback 更新为 active 退役 + recycle 软归档。

## 11. 验收标准

- 用户能把多本书 / 多篇论文纳入同一个资料库。
- LightRAG 可以在不改动 MNote 普通功能的情况下完成 OCR、parse、index、query。
- LightRAG 读取的是 MNote 允许的真实 source，或有明确 registry 映射的临时 staging；不能存在无人管理的第二份资料真相。
- agent 能回答跨资料问题。
- 回答不能只给“看起来合理”的总结，必须有来源。
- 至少 PDF 页码和 chunk quote 可追溯。
- 对支持 bbox 的 sidecar，能打开到页面区域或保留 bbox metadata。
- 删除知识库索引不会删除用户原始文件。
- 删除 / 移动 / 重命名 source 后，旧索引不会继续作为有效来源参与回答；删除同步失败时必须显示 stale 状态。
- MNote active 代码中不再出现未完成的 `mnote.understanding.*` 主线接线。
- LightRAG 不可用时，MNote 文件树、编辑器、普通页面搜索仍可正常使用。
