收口 MNote P0 P1 P2 审查尾项
- 归档 OnlyOffice live bridge、Page AI、mindmap、design governance 与相关 bug 条目 - 补齐 MinerU OCR 后端 runtime 合同与 smoke/test 基线 - 收口 ChatOnly/Doubao、ObjectIdentity、Page Aggregate compat 与 runtime owner 文档口径 验证: - cargo test --manifest-path rust/Cargo.toml -p mnote-web local_ocr -- --test-threads=1 - cargo test --manifest-path rust/Cargo.toml -p mnote-web onlyoffice_bridge -- --test-threads=1 - git diff --check - git diff --cached --check - codegraph index . --force && codegraph status . - codegraph sync . && codegraph status .
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
# 3-26 Sidebar dev hot reload 在主 runtime 中使用 setInterval
|
||||
|
||||
## 状态
|
||||
|
||||
- 状态:done
|
||||
- Owner:03-rust-web / browser runtime
|
||||
- 发现时间:2026-05-31
|
||||
|
||||
## 现象
|
||||
|
||||
`sidebar-tree-runtime.js` 在主 Sidebar runtime 中安装 dev hot reload,并无前置环境 guard 地执行 `window.setInterval(tick, 1000)`。项目架构约束要求浏览器主链默认禁止新增基于 `setInterval`、周期 `setTimeout` 或轮询 fallback 的数据刷新和状态同步;即使这是 dev hot reload,也应该显式限制在 debug/dev 边界。
|
||||
|
||||
## 证据
|
||||
|
||||
- `rust/crates/mnote-web/browser/sidebar-tree-runtime.js` 中 `installMnoteDevHotReload()` 执行:
|
||||
- 先调用 `tick()`。
|
||||
- 再执行 `timer = window.setInterval(tick, 1000)`。
|
||||
- 末尾无条件调用 `installMnoteDevHotReload()`。
|
||||
- `tick()` 每次请求 `/api/dev/hot-reload`,服务端返回 `enabled !== true` 时才清理 timer;这仍意味着页面启动后先进入轮询逻辑。
|
||||
|
||||
## 影响
|
||||
|
||||
- 主 Sidebar runtime 默认携带 dev 轮询逻辑,和“主链不叠加轮询 fallback”的架构约束冲突。
|
||||
- 若 `/api/dev/hot-reload` 异常或返回形态变化,可能引入重复请求、console 噪音或性能误判。
|
||||
- 后续 worker 可能把这种模式复制到其他可见路径。
|
||||
|
||||
## 修复建议
|
||||
|
||||
- 在 Rust SSR bootstrap 中显式注入 dev/hot 模式标记,只有 dev hot 模式启用时才安装该逻辑。
|
||||
- 或将 hot reload 逻辑迁到 debug/internal runtime,不放在默认 Sidebar runtime。
|
||||
- 如果仍保留定时器,必须在设计/注释中说明退出条件和边界,并保证生产/普通 desktop 模式不可达。
|
||||
|
||||
## 本轮进展
|
||||
|
||||
- 2026-05-31:
|
||||
- `sidebar-tree-runtime.js` 已改为通过 `import.meta.url` 检查当前模块 URL 是否携带 `devHot` cache buster;只有 dev hot 模式才安装 hot reload 轮询。
|
||||
- 已补 `layout.rs` 静态断言,禁止无条件 `installMnoteDevHotReload()` 回流。
|
||||
- 已通过 `node --check rust/crates/mnote-web/browser/sidebar-tree-runtime.js` 和 Rust 定点测试。
|
||||
- 已补 `scripts/task514-sidebar-dev-hot-reload-gating-smoke.js` 固化真实浏览器验证。
|
||||
- 验证通过:`node scripts/task514-sidebar-dev-hot-reload-gating-smoke.js`。结果显示普通入口 `hotReloadRequestCount=0`、`scriptHasDevHot=false`;hot 模式 `scriptHasDevHot=true`、`hotReloadRequestCount=2`、`data-mnote-dev-hot-reload=enabled`,且无 console/network 错误。
|
||||
|
||||
## 验收
|
||||
|
||||
- [x] 普通 `desktop` / 非 hot 入口打开后,浏览器不会请求 `/api/dev/hot-reload`。
|
||||
- [x] `npm run desktop:hot` 或等价 hot 模式下仍能刷新。
|
||||
- [x] `setInterval(tick, 1000)` 仅在 `mnoteDevHotReloadEnabled()` guard 后可达。
|
||||
@@ -0,0 +1,103 @@
|
||||
# 3-27 MinerU OCR 后端 runtime 已落地但缺前端任务链
|
||||
|
||||
## 状态
|
||||
|
||||
- 状态:process
|
||||
- Owner:03-rust-web / local-folder OCR / MinerU sidecar
|
||||
- 发现时间:2026-05-31
|
||||
|
||||
## 现象
|
||||
|
||||
P2 目标中包含 MinerU OCR 能力收口。当前已补后端 mock route、真实 MinerU HTTP client、sidecar 写入、`.mnote/ocr-index.json`、`includeOcr=true` 搜索命中和浏览器 API smoke。但 active job store、realtime job event、前端入口/任务栏仍未落地。
|
||||
|
||||
## 证据
|
||||
|
||||
- `rust/crates/mnote-web/src/routes/local_ocr.rs` 已注册 `jobs/status/read/insert`,`provider=mock` 能写入 `{pageStem}.ocr/*.ocr.md` 和 `.mnote/ocr-index.json`。
|
||||
- `provider=mineru` 在有 token 时会走真实 HTTP client:申请上传 URL、PUT 上传、轮询结果、下载 zip、提取 Markdown,并写入 `{pageStem}.ocr/*.ocr.md` / `.mnote/ocr-index.json`。该路径已有本地 HTTP mock 单测覆盖,不访问外网。
|
||||
- `local_search_index` 已支持 `includeOcr=true` 命中 OCR owner page;`task526-local-folder-ocr-api-smoke.js` 已覆盖浏览器上下文调用 mock OCR API、搜索命中和显式 insert 链接。
|
||||
- 设计中的活动任务生命周期、`local_ocr.job.updated` 和浏览器可见入口仍未完成。
|
||||
|
||||
## 影响
|
||||
|
||||
- 用户无法从本地图片或图片型 PDF 通过 UI 手动触发 MinerU OCR。
|
||||
- 搜索的 `includeOcr=true` 已能命中 OCR sidecar,但真实 MinerU 结果仍缺 UI 触发链和任务状态可见性。
|
||||
- AI 资源上下文无法优先读取已有 OCR Markdown。
|
||||
|
||||
## 下一步
|
||||
|
||||
1. 已完成后端 mock 最小闭环:路径规划、sidecar frontmatter、`.mnote/ocr-index.json`、mock OCR job route、status/read、Page Tree 过滤和 `includeOcr=true` 搜索 owner page。
|
||||
2. 已补浏览器 API smoke:mock OCR、status/read/jobs、`includeOcr=true` 搜索 owner page 和显式 insert link。
|
||||
3. 下一步接长任务状态、`local_ocr.job.updated` realtime 事件、前端 OCR 入口/任务栏和 AI 资源上下文读取 OCR sidecar。
|
||||
|
||||
## 验收
|
||||
|
||||
- [x] Rust route/helper 测试覆盖 sidecar 路径/frontmatter、index stale/error redaction、mock OCR job 写入、status/read、无 token、越界拒绝、非图片/PDF 拒绝、mock 失败 response 脱敏和显式 insert link。
|
||||
- [x] local search 测试覆盖 OCR 命中返回 owner page,OCR sidecar 不作为普通页面。
|
||||
- [x] Page Tree 测试覆盖 OCR sidecar 可在 File Tree 作为资源文件可见,但不作为普通页面进入 Page Tree。
|
||||
- [x] Rust route 测试覆盖无 token response 形态。
|
||||
- [x] Rust route 测试覆盖 `provider=mineru` 后端成功路径:申请上传 URL、PUT 上传、轮询结果、下载 zip、提取 Markdown、写 sidecar/index。
|
||||
- [~] 浏览器 smoke 覆盖图片/PDF 手动 OCR、任务栏状态、打开 OCR、搜索 OCR 命中和插入 OCR 链接。(当前 `task526` 覆盖 mock OCR API、搜索命中、显式 insert link 和 OCR sidecar resource tab 打开;真实 UI 入口/任务栏待做)
|
||||
|
||||
## 2026-06-01 后端 mock 闭环记录
|
||||
|
||||
新增 `rust/crates/mnote-web/src/routes/local_ocr.rs`,注册:
|
||||
|
||||
- `POST /api/local-folder/ocr/jobs`
|
||||
- `GET /api/local-folder/ocr/jobs`
|
||||
- `GET /api/local-folder/ocr/status`
|
||||
- `GET /api/local-folder/ocr/read`
|
||||
- `POST /api/local-folder/ocr/insert`
|
||||
|
||||
当前真实 MinerU HTTP client 仍未接入;`provider=mock` 用于本地后端闭环和测试,`provider=mineru` 在缺少 token 时返回 `mineru_token_missing`,有 token 时返回 `mineru_runtime_not_enabled`,避免伪装真实能力已完成。
|
||||
|
||||
已通过验证:
|
||||
|
||||
- `cargo test --manifest-path rust/Cargo.toml -p mnote-web local_ocr -- --test-threads=1`
|
||||
- `cargo test --manifest-path rust/Cargo.toml -p mnote-web local_search_ocr -- --test-threads=1`
|
||||
|
||||
2026-06-01 续补 route 边界测试:
|
||||
|
||||
- 越界来源路径拒绝:`local_ocr_path_escape`
|
||||
- 非图片/PDF 来源拒绝:`local_ocr_source_type_unsupported`
|
||||
- provider `mineru` 且缺 token 时拒绝:`mineru_token_missing`
|
||||
- mock 失败响应与 `.mnote/ocr-index.json` 失败条目统一脱敏为 `provider_error_redacted`
|
||||
- 显式 `ocr/insert` link 模式把 `[OCR:photo.png](./Page.ocr/photo.png.ocr.md)` 追加进 owner Markdown;未调用 insert 时不改正文
|
||||
|
||||
本文继续保持 `process`:前端 OCR 入口、任务栏和 active job / realtime event 尚未完成。
|
||||
|
||||
2026-06-01 只读复核更新:
|
||||
|
||||
- Subagent 复核确认:route/mock/search 测试已落地,早期“没有实际 OCR route”的描述已经过时。
|
||||
- 本 bug 不归档的阻塞点更新为:真实 MinerU HTTP client、active job store / `local_ocr.job.updated`、前端入口/任务栏、AI 资源上下文读取 OCR sidecar 和完整 UI browser smoke。
|
||||
|
||||
2026-06-01 浏览器 API smoke 续补:
|
||||
|
||||
- 新增 `scripts/task526-local-folder-ocr-api-smoke.js`,在真实浏览器登录态页面内通过 `fetch` 串起 `POST /api/local-folder/ocr/jobs`、`status`、`read`、`jobs`、`/api/search/documents includeOcr=true` 和 `POST /api/local-folder/ocr/insert`。
|
||||
- 已验证 `provider=mock` 会生成 `docs/Page.ocr/photo.png.ocr.md`,`includeOcr=false` 不命中 OCR 文本,`includeOcr=true` 返回 owner page 且带 `hasOcr/ocrEvidence`,显式 insert 才向 owner Markdown 追加 `[OCR:photo.png](...)`。
|
||||
- 续补后已验证 OCR sidecar 可作为 Markdown resource tab 打开,截图写入 `tmp/task526-local-folder-ocr-api-smoke/02-ocr-resource-tab.png`。
|
||||
- 已通过:
|
||||
- `node --check scripts/task526-local-folder-ocr-api-smoke.js`
|
||||
- `MNOTE_UI_BASE_URL=http://127.0.0.1:3301 MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3301 node scripts/task526-local-folder-ocr-api-smoke.js`
|
||||
- `cargo test --manifest-path rust/Cargo.toml -p mnote-web local_ocr -- --test-threads=1`
|
||||
- `cargo test --manifest-path rust/Cargo.toml -p mnote-web local_search_ocr -- --test-threads=1`
|
||||
|
||||
2026-06-01 MinerU API 口径复核:
|
||||
|
||||
- 官方文档当前仍以 `https://mineru.net/api/v4/extract/task` 或 `https://mineru.net/api/v4/file-urls/batch` 作为精准解析入口;`model_version` 支持 `pipeline` / `vlm` / `MinerU-HTML`,Markdown/JSON 为默认结果格式,图片/PDF/Office 等文档受文件大小与页数限制。
|
||||
- 当前设计稿中的“申请上传地址 -> PUT 上传 -> 轮询批量结果 -> 下载 zip -> 提取 Markdown”方向仍成立。
|
||||
- 旧回归测试曾要求 `MNOTE_MINERU_API_TOKEN` 存在且 provider 为 `mineru` 时返回 `mineru_runtime_not_enabled`;该口径已被真实后端 runtime 合同测试替代。
|
||||
|
||||
## 2026-06-01 后端 MinerU runtime 补齐记录
|
||||
|
||||
- `rust/crates/mnote-web/src/routes/local_ocr.rs` 已补 `mineru_api_base_url`、`mineru_poll_interval`、`mineru_max_polls` 配置函数。
|
||||
- `provider=mineru` 后端路径已接入 `run_mineru_ocr`,执行申请上传 URL、PUT 上传、轮询 batch 结果、下载 zip、提取 Markdown。
|
||||
- 新增本地 HTTP mock 测试 `local_ocr_jobs_route_runs_mineru_runtime_against_http_mock`,不访问外网,验证真实 client 合同和 sidecar/index 写入。
|
||||
- 已通过:
|
||||
- `cargo test --manifest-path rust/Cargo.toml -p mnote-web local_ocr -- --test-threads=1`
|
||||
|
||||
本文继续保持 `process` 的剩余原因:
|
||||
|
||||
- 前端本地文件 / 图片 / PDF 资源没有 OCR 操作入口。
|
||||
- OCR jobs 仍是同步请求 + `.mnote/ocr-index.json` 历史状态,没有 active job store。
|
||||
- 缺少 `local_ocr.job.updated` realtime event 与全局任务栏 UI。
|
||||
- AI 资源上下文还没有优先读取 OCR sidecar。
|
||||
Reference in New Issue
Block a user