13 KiB
7-51 LightRAG post-commit hardening v1
创建时间:2026-06-07
状态:
done2026-07-03 口径回正:当前 runtime 已回到 OpenHub / native agent + LightRAG + Turso/libSQL。本文重新作为当前默认 LightRAG provider 的 hardening 基线;历史非 LightRAG 默认 provider 口径已标记 stale。
Owner:07-ai / knowledge-rag / 03-rust-web / plugin-ui
来源:
design/10-review/done/20-post-lightrag-runtime-hardening-checklist-v1.mdP0 审计上位依据:
design/07-ai/done/7-50-lightrag-knowledge-rag-provider-v1.mddesign/10-review/done/20-post-lightrag-runtime-hardening-checklist-v1.md
1. 第一结论
7-50 作为 LightRAG 资料库问答主线可以保持 done,但 post-commit audit 发现若干需要单独硬化的边界:
- watcher stale sync 在 best-effort 删除失败时会吞掉错误,并且已经清空 registry 中的
lightRagDocId,后续难以重试删除 provider orphan doc。 sourcePaths当前是 provider 检索后过滤 MNote mapped references,不是 provider 预过滤;HTTP API 仍返回未过滤raw,存在调用方误用 raw 的风险。- sidecar locator 在 quote 未命中时会 fallback 到
first_positioned_block,可能生成错误 page/bbox,却表现为非 degraded locator。 mnote-knowledge-ragskill 文案对 degraded citation 过强,容易让 agent 误以为不能使用返回的降级 resourceTab 链接。- Reasonix wrapper 仍手写工具表,能力注册漂移问题还没有真正解决。
本稿不恢复旧 evidence / LiteParse / local OCR 路径,不开发第二套 RAG,只硬化 7-50 已选定的 LightRAG provider 边界。
2. 非目标
- 不重建
mnote.evidence.*/mnote.index.*agent 工具。 - 不把 source scope 伪装成 LightRAG provider 原生过滤,除非实际实现了 provider 级约束。
- 不清空用户资料库、不删除用户原始 source、不自动大规模 reindex。
- 不把 LightRAG sidecar / chunk / graph 当作 MNote 正文真相。
- 不在本稿内实施完整 capability registry;只补必要漂移测试或文案约束,完整 registry 仍按
7-47/20 P4推进。
3. Phase A:Delete retry / orphan doc guard
目标:source 删除或 hash 变化后,即使 LightRAG 删除失败,也不能丢失重试 provider doc id;prune 不能隐藏仍可能参与回答的 orphan doc。
Checklist:
- 修改
sync_registry_source_state(...):source missing / hash changed 时不要立即清空lightRagDocId;应进入stale=true+lightRagStatus=delete_submitted或delete_retry_required。 sync_registry_with_documents(...)调用 LightRAG delete 失败时,把失败写入 registry entry 的可见状态,而不是吞掉后只保留 stale。- 只有确认 LightRAG
/documents不再包含该 doc 后,才清空lightRagDocId并标记delete_completed。 prune_registry不清理仍带lightRagDocId且 delete 未确认完成的 stale entry。mapped_references(...)对 missing registry 的 provider reference 需要区分:- provider orphan / unknown source:默认不作为有效 MNote citation 返回,或明确返回 degraded + unmapped 分类,但不得进入 scoped answer citation。
- registry 命中但 stale / deleted:继续过滤。
- 对
delete-sourceroute 保持delete_file=false,并保留“不删除用户原始 source”的断言。
验证:
- 单测:LightRAG delete 失败时 registry 保留 doc id 和 retry 状态。
- 单测:delete completed 后才清 doc id。
- 单测:prune 不删除
delete_submitted/delete_retry_requiredentry。 - 单测:missing registry provider reference 不会作为正常 citation 返回。
cargo test -p mnote-web knowledge_rag -- --nocapture
实施记录:
- 2026-06-07:
sync_registry_source_state(...)在 source missing / hash changed 时保留lightRagDocId,并把状态置为delete_submitted。 - 2026-06-07:
sync_registry_with_documents(...)会重试delete_submitted/delete_retry_requireddoc id;LightRAG delete 失败时写入delete_retry_required,成功提交后保持delete_submitted,等/documents消失后才标记delete_completed并清空 doc id。 - 2026-06-07:当前 registry schema 先用
lightRagStatus=delete_retry_required表达失败状态,不额外扩写错误 message 字段,避免扩大持久化迁移面。
4. Phase B:Source scope 语义收紧
目标:避免调用方误以为 sourcePaths 已限制 LightRAG provider 检索范围。
Checklist:
- 在
/api/knowledge-rag/query返回中新增sourceScopeMode,当前值明确为post_filter_mapped_references。 - 若
sourcePaths非空,默认不向普通 agent / Page AI 暴露未过滤rawchunks;至少 compact tool output 继续不暴露 raw chunks。 - HTTP API 如仍保留
raw,必须标注rawScopeFiltered=false或等价字段,提醒 raw 未受 source scope 过滤。 mnote.knowledge_rag.querymanifest / Reasonix wrapper / skill 文案从“限制检索来源”改为“按 MNote source 过滤返回 references;provider raw 可能仍为全局检索结果”。- Page AI final answer 只允许引用 filtered
references/citations,不得引用 raw LightRAG chunks。
验证:
- 单测:
sourcePaths=[alpha]时references只含 alpha。 - 运行态 smoke:
sourceScopeMode=post_filter_mapped_references且rawScopeFiltered=false。 - 单测或 wrapper selftest:agent compact result 不含 raw chunks。
task538-knowledge-rag-source-scope-api-smoke.js更新并通过。task534-knowledge-rag-source-management-scope-smoke.jsUI source management 部分已修复并通过。
实施记录:
- 2026-06-07:
/api/knowledge-rag/query返回sourceScopeMode=post_filter_mapped_references与rawScopeFiltered=false。 - 2026-06-07:
mnote.knowledge_rag.querycompact agent result 继续只暴露 filteredreferences/citations,不暴露raw.chunks。 - 2026-06-07:manifest、Reasonix wrapper、
skills/mnote-knowledge-rag/SKILL.md已统一 sourcePaths post-filter 口径;新增task538-knowledge-rag-source-scope-api-smoke.js覆盖 API scope metadata、filtered references、delete-source不删原始 source。 - 2026-06-07:
task534修正为打开资料库设置后切到“全部”来源,避免默认“需处理”过滤隐藏已索引 source;在 3300 最新构建通过。
5. Phase C:Locator strict match / degradation
目标:没有真实匹配到 quote / chunk 对应 sidecar block 时,不生成看似精确的 page/bbox。
Checklist:
- 修改
find_lightrag_sidecar_block(...):移除或限制first_positioned_blockfallback;只有 quote 与 block content 达到明确匹配阈值时才返回 page/bbox locator。 - 若只找到 source resource 但没有精确 block match,返回 clickable degraded resourceTab citation,但
locatorDegraded=true。 citationMarkdown对 degraded resourceTab 使用稳定文案,例如来源定位降级:<file>,不包含伪造页码。- 对 PDF / image / DOCX fallback citation 分别保留打开能力,但不伪造 bbox。
- 记录 LightRAG chunk 缺
refs的当前边界;未来若 provider 暴露 refs,再改为 refs 优先、文本匹配 fallback。
验证:
- 单测:quote 不匹配 sidecar block 时不返回 page/bbox locator。
- 单测:quote 匹配 sidecar block 时仍返回 page/bbox locator。
- 单测:known resource + no locator 返回 clickable degraded citation。
task529-knowledge-rag-citation-resource-tab-smoke.js更新为当前 fixture 可重复的正例,并通过。
实施记录:
- 2026-06-07:
find_lightrag_sidecar_block(...)已移除first_positioned_blockfallback;未匹配 quote 时返回降级 resourceTab citation,不生成 page / bbox。 - 2026-06-07:当前 LightRAG
/query/datachunks 未提供可稳定回跳 MNote sidecar block 的 providerrefs;MNote 暂以文本匹配做严格定位,未匹配时只给 degraded resourceTab。 - 2026-06-07:
task529改为当前 image source 降级 citation 正例,验证open_reference与 citation URL 能打开 image resource tab,且不携带伪造 page locator。
6. Phase D:Agent / UI degraded citation 口径统一
目标:agent 可以使用 MNote 返回的 degraded citation,但不能编造页码、bbox 或 provider 内部路径。
Checklist:
- 更新
skills/mnote-knowledge-rag/SKILL.md:locatorDegraded=true时,可以引用返回的citationMarkdown,但必须说明来源定位降级;禁止编造 page / bbox。 - 更新 Reasonix system prompt 中 knowledge-rag 能力说明,保持同一口径。
- 更新 Page AI final answer smoke,增加 degraded citation 场景:最终回答可以含降级 citation,但不能说成 p.N / bbox。
- 更新 dashboard smoke,不再依赖固定
Completed (5)/Fail (4)/ 固定 doc id;改为验证 Documents / Graph / Retrieval 入口与当前 documents summary 可见。
验证:
MNOTE_REASONIX_ACP_SELFTEST=1 node scripts/reasonix-acp-wrapper.mjsnode scripts/task530-knowledge-rag-page-ai-final-answer-smoke.jsnode scripts/task531-lightrag-dashboard-ui-smoke.js
7. Phase E:Reasonix / manifest drift guard
目标:在完整 7-47 capability registry 实施前,先降低 Reasonix wrapper 与 Rust manifest 的漂移风险。
Checklist:
- 增加一个轻量 selftest:Rust manifest 中
mnote.knowledge_rag.*三个工具必须都存在于 Reasonix wrapper 映射。 - 增加一个反向 selftest:Reasonix wrapper 暴露的
mnote_knowledge_rag_*必须能映射到 Rust manifest tool name。 - 保留手写工具表作为短期现实,但在 7-47 中继续推进 manifest 动态注册。
- 若发现旧
mnote.evidence.*/mnote.index.*函数被 grep 误判,给 manifest 源码附近加注释:dead code 仅保留历史对照,不在 manifest vector 中注册。
验证:
MNOTE_REASONIX_ACP_SELFTEST=1 node scripts/reasonix-acp-wrapper.mjscargo test -p mnote-web hermes_client_tools_uses_manifest_and_profile_disabled_state -- --test-threads=1
实施记录:
- 2026-06-07:Reasonix wrapper selftest 会读取 Rust
hermes_tools/manifest.rs,校验mnote.knowledge_rag.*manifest tools 与 wrapperMNOTE_TOOL_NAMES/REASONIX_TOOL_TO_MNOTE_TOOL双向一致。
8. Phase F:legacy OCR / Convex media visible runtime 退役跟进
目标:LightRAG 成为资料库主线后,继续清掉仍可能被浏览器 runtime 或 worker 误读为 active fallback 的旧 OCR / Convex Files 链路。
Checklist:
/api/local-folder/events不再转发local_ocr.job.updated;resource tab 不再依赖 local OCR SSE 或synthetic_resource_write刷新 filetree。- UI preference 不再接受
localOcr.*写入;历史 effective preference 强制为false/ retired。 - FileTree 右键入口不再保留
local-ocraction alias;资料索引只走knowledge-rag-index与/api/knowledge-rag/ingest。 - 浏览器 runtime 不再调用
/api/media/sign//api/media/upload;旧 Convex Files 前端链路只标记 retired guard。 AppState移除local_ocr_job_tx/local_ocr_active_jobs,旧 local OCR helper 不再广播 runtime event。- local search incremental refresh 遇到 OCR sidecar 时只清理旧 evidence sqlite 投影,不再重建 OCR evidence。
routes/local_ocr.rs从历史 HTTP job / MinerU runtime 实现收缩为历史 OCR sidecar 识别、frontmatter 解析和索引读取 helper;旧 ignored HTTP route tests 已移除。- resource tab 后台任务抽屉、toolbar 与 CSS 从
mnote-local-ocr-*重命名为mnote-knowledge-rag-*,Knowledge RAG ingest/delete 不再挂旧 OCR DOM / function 名。 - Page AI 目标包删除空实现的 OCR sidecar context enrichment,local-first agent 只携带当前文件/selection/allowed roots,不再保留
ocrContext/ocrRootRelativePath注入点。 - Sidebar 旧
open-ocr-settings/toggle-ocr-tasks/data-local-ocr-*委托移除;历史.ocr/*.ocr.mdsidecar 仅以retired-ocr-sidecar:*资源身份打开,不再伪装为 active local OCR。
验证:
cargo test -p mnote-web local_ocr -- --test-threads=1cargo test -p mnote-web local_search_ocr_sidecar_is_hidden_after_lightrag_retirement -- --test-threads=1cargo test -p mnote-web -- --test-threads=1cargo test --workspace -- --test-threads=1git diff --checkcodegraph sync ./codegraph_status
9. 归档条件
- delete retry / orphan doc guard 有单测覆盖,prune 不会隐藏未确认删除的 provider doc。
sourcePaths的 post-filter 语义在 API、skill、wrapper 和 tests 中一致。- locator 不再用不匹配的 first positioned block 生成非 degraded page/bbox。
- degraded citation 的 agent / UI 文案统一。
task529/task530/task531不依赖已漂移的固定历史 LightRAG documents 数量或 doc id。- 7-50 保持
done,本稿完成后移动到design/07-ai/done/。