Persist PageTree expand state via control-plane view-state and align chevron/DOM with restored expansion; keep Sidex-style shallow page-tree scan and drop the unused recursive scanner that only added cargo noise. Add password vault workbench routes/runtime/skill/CLI, split page_ai_pi into a module package, and retire Hermes/ACP/OpenHub recycle + root harness evidence from the index while gitignoring recycle and local diag dumps. Archive superseded design/bugs docs under old/, point architecture at ARCHITECTURE.md, and refresh smokes for Pi S1–S7, vault, and editor regressions so the working tree can stay clean.
544 lines
21 KiB
Markdown
544 lines
21 KiB
Markdown
# 7-48 [reference] Paperless-ngx Reference: Resource Ingestion / Job Ledger / Evidence Index v1
|
||
|
||
> 创建时间:2026-06-05
|
||
>
|
||
> 当前状态:`REFERENCE`
|
||
>
|
||
> 2026-06-07 状态治理:本文只作为 Paperless-ngx 对 LightRAG source registry、job ledger、索引可重建性和历史 evidence.sqlite 设计的参考材料,不再作为 active evidence.sqlite / LiteParse 主线任务源。
|
||
> 文内未勾选项均为历史候选,不作为当前 `process` 任务。
|
||
>
|
||
> Owner:07-ai / 03-rust-web / control-plane / 01-tree-first-graph-kernel
|
||
>
|
||
> 参考项目:Paperless-ngx 本地副本已在 2026-07 清理;本文保留其已提炼的设计结论,不依赖本地源码。
|
||
>
|
||
> 参考版本:`f56f29111`
|
||
>
|
||
> CodeGraph:历史取证时曾单独建立索引;本地参考副本已清理。
|
||
>
|
||
> 上位依据:
|
||
> - `/mnt/Data1T/mnote/ARCHITECTURE.md`
|
||
> - `/mnt/Data1T/mnote/CURRENT_ARCHITECTURE.md`
|
||
> - `/mnt/Data1T/mnote/design/07-ai/reference/7-46-document-evidence-retrieval-kernel-v1.md`
|
||
> - `/mnt/Data1T/mnote/design/03-rust-web/done/3-25-local-folder-mineru-ocr-sidecar-v1.md`
|
||
> - `/mnt/Data1T/mnote/design/07-ai/process/7-18-local-first-agent-file-editing-control-plane-v1.md`
|
||
|
||
## 1. 第一结论
|
||
|
||
Paperless-ngx 对 MNote 最有价值的不是 Django / Angular / Celery 技术栈,而是三套工程结构:
|
||
|
||
1. `PaperlessTask`:所有后台任务有统一账本,能记录来源、状态、耗时、输入、结果和用户是否已确认。
|
||
2. `consume_file` plugin pipeline:资源导入、预检、解析、OCR、存储、索引、通知按阶段推进,失败可以定位到阶段。
|
||
3. `Tantivy search backend + sanity checker`:索引有 schema 版本、权限字段、锁、延迟补偿和可重建性;文件与派生物有一致性检查。
|
||
|
||
MNote 应把这些模式收口成自己的 `Resource Work Kernel`:
|
||
|
||
```text
|
||
- local file / attachment / OCR source / parsed artifact
|
||
-> ResourceWorkJob control-plane ledger
|
||
-> ResourceIngestionPipeline stage runner
|
||
-> sidecar artifact + source-map
|
||
-> evidence.sqlite / local search projection
|
||
-> realtime job events
|
||
-> sanity check / recovery job
|
||
```
|
||
|
||
这不是要引入 paperless-ngx 的运行时。MNote 的数据真相仍然是 local Markdown、附件原文件、resource tree 和 control-plane;索引、OCR Markdown、parse Markdown、source-map 都是可删除重建的派生物。
|
||
|
||
## 2. Paperless-ngx 可借鉴点
|
||
|
||
### 2.1 统一后台任务账本
|
||
|
||
参考路径:
|
||
|
||
- `src/documents/models.py`:`PaperlessTask`
|
||
- `src/documents/signals/handlers.py`:Celery task publish / prerun / postrun / failure handlers
|
||
- `src-ui/src/app/components/admin/tasks/tasks.component.ts`
|
||
|
||
可借鉴点:
|
||
|
||
- 任务不是只存在于内存事件或前端状态,而是落库。
|
||
- 每个任务有 `task_type`、`trigger_source`、`status`、`date_created`、`date_started`、`date_done`、`duration_seconds`、`wait_time_seconds`、`input_data`、`result_data`、`acknowledged`。
|
||
- 系统任务和用户触发任务统一展示,但保留来源差异。
|
||
|
||
MNote 映射:
|
||
|
||
- 当前 `JobTicket`、OCR job、index refresh、agent run、OnlyOffice bridge 任务、recovery job 不应继续分散。
|
||
- 新增 control-plane 表 `resource_work_jobs`,先覆盖 local OCR / evidence parse / index refresh,后续再纳入 agent run 和 recovery job。
|
||
|
||
### 2.2 阶段化资源导入管线
|
||
|
||
参考路径:
|
||
|
||
- `src/documents/tasks.py`:`consume_file`
|
||
- `src/documents/plugins/base.py`:`ConsumeTaskPlugin`
|
||
- `src/documents/consumer.py`:解析、OCR、存储、索引、progress
|
||
- `src/documents/plugins/helpers.py`:`ProgressManager`
|
||
|
||
可借鉴点:
|
||
|
||
- 导入任务按插件链执行,每个 stage 有 `setup / run / cleanup`。
|
||
- 阶段状态通过 websocket 通知。
|
||
- 文件写入、数据库更新、索引更新分层处理,失败时能说明卡在预检、解析、写 sidecar 还是索引。
|
||
|
||
MNote 映射:
|
||
|
||
- 不引入插件框架泛化;先定义窄的 `ResourceIngestionPipeline`。
|
||
- stage 只覆盖当前真实需要:`preflight`、`parse_text`、`ocr`、`write_artifact`、`write_source_map`、`refresh_evidence_index`、`broadcast_done`。
|
||
- 当前 `local_ocr` 里的 stage 字符串和 sidecar 写入逻辑可以作为第一批迁移对象。
|
||
|
||
### 2.3 索引生命周期和自愈
|
||
|
||
参考路径:
|
||
|
||
- `src/documents/search/_backend.py`
|
||
- `src/documents/search/_schema.py`
|
||
- `src/documents/search/_query.py`
|
||
- `src/documents/tasks.py`:`index_document`、`remove_document_from_index`
|
||
|
||
可借鉴点:
|
||
|
||
- schema version sentinel 决定是否重建。
|
||
- 写索引用 file lock 和 retry,锁耗尽后排延迟任务,而不是让前台操作失败。
|
||
- 查询层有权限过滤、autocomplete、highlight、CJK bigram、simple search。
|
||
|
||
MNote 映射:
|
||
|
||
- `.mnote/index/evidence.sqlite` 当前已存在,但需要更明确的 schema sentinel 和 rebuild reason。
|
||
- `query_evidence_sqlite_results` 继续作为默认 evidence path;后续补充 autocomplete / CJK / highlight 时仍以 `EvidenceLocator` 为返回真相。
|
||
- 索引写失败不能悄悄丢失,应写入 `resource_work_jobs` 的 retry-scheduled 状态。
|
||
|
||
### 2.4 权限过滤的实时事件
|
||
|
||
参考路径:
|
||
|
||
- `src/paperless/consumers.py`
|
||
- `src/documents/plugins/helpers.py`
|
||
|
||
可借鉴点:
|
||
|
||
- websocket payload 带 owner / visible users / visible groups。
|
||
- server-side websocket consumer 根据当前用户过滤。
|
||
|
||
MNote 映射:
|
||
|
||
- local-only 阶段可以先只带 `workspaceId`、`actorId`、`rootUri`、`targetDocumentId`、`grantId`。
|
||
- 一旦进入 share / team workspace,OCR / index / agent job event 不能只按广播频道粗暴推送。
|
||
- `AiAccessScope` 和 share grants 应能映射成 job event 可见性字段。
|
||
|
||
### 2.5 Sanity checker
|
||
|
||
参考路径:
|
||
|
||
- `src/documents/sanity_checker.py`
|
||
- `src/documents/management/commands/document_sanity_checker.py`
|
||
|
||
可借鉴点:
|
||
|
||
- 独立检查原文件、派生文件、checksum、孤儿文件和空 OCR 内容。
|
||
- 输出按 error / warning / info 分级,既能 CLI 显示,也能作为后台任务结果。
|
||
|
||
MNote 映射:
|
||
|
||
- 新增 `workspace_sanity_check`,先检查 local-folder resource evidence:
|
||
- Markdown owner 是否存在。
|
||
- 附件路径是否存在且在 allowed root 内。
|
||
- `{pageStem}.ocr/` sidecar 是否能回到 owner Markdown。
|
||
- `*.source-map.json` 是否能解析为 `mnote.resource_source_map.v1`。
|
||
- `evidence.sqlite` 是否能由 sidecar 重建。
|
||
- evidence locator 的 `openAction` 是否能落回 document / resource tab。
|
||
|
||
## 3. 目标架构
|
||
|
||
### 3.1 ResourceWorkJob
|
||
|
||
新增 control-plane job ledger,不替代 domain event,也不替代 agent run receipt。
|
||
|
||
```rust
|
||
pub struct ResourceWorkJob {
|
||
pub job_id: String,
|
||
pub job_type: ResourceWorkJobType,
|
||
pub trigger_source: ResourceWorkTriggerSource,
|
||
pub status: ResourceWorkJobStatus,
|
||
pub stage: Option<String>,
|
||
pub progress_current: Option<u32>,
|
||
pub progress_total: Option<u32>,
|
||
pub stage_label: Option<String>,
|
||
pub workspace_id: String,
|
||
pub root_uri: String,
|
||
pub actor_id: Option<String>,
|
||
pub target_document_id: Option<String>,
|
||
pub source_root_relative_path: Option<String>,
|
||
pub artifact_root_relative_path: Option<String>,
|
||
pub source_map_root_relative_path: Option<String>,
|
||
pub input_json: serde_json::Value,
|
||
pub result_json: Option<serde_json::Value>,
|
||
pub error_code: Option<String>,
|
||
pub error_message: Option<String>,
|
||
pub created_at_ms: u128,
|
||
pub started_at_ms: Option<u128>,
|
||
pub finished_at_ms: Option<u128>,
|
||
pub acknowledged_at_ms: Option<u128>,
|
||
}
|
||
```
|
||
|
||
首批枚举:
|
||
|
||
```text
|
||
job_type:
|
||
- local_ocr
|
||
- resource_parse
|
||
- evidence_index_refresh
|
||
- evidence_index_rebuild
|
||
- workspace_sanity_check
|
||
|
||
trigger_source:
|
||
- web_ui
|
||
- api
|
||
- watcher
|
||
- agent_tool
|
||
- system
|
||
- recovery
|
||
|
||
status:
|
||
- pending
|
||
- running
|
||
- succeeded
|
||
- failed
|
||
- retry_scheduled
|
||
- canceled
|
||
```
|
||
|
||
约束:
|
||
|
||
- `job_id` 由 MNote 生成,不复用外部 provider task id。
|
||
- MinerU task id、LiteParse request id、Reasonix run id 只进入 `input_json / result_json`。
|
||
- `result_json` 必须能存 evidence id、artifact path、source-map path、locator count、index row count。
|
||
- `stage / progress_current / progress_total / stage_label` 是前台任务中心的稳定合同;不能只塞在 provider 私有 payload 里。
|
||
- job ledger 是 control-plane 事实,不是用户正文真相。
|
||
|
||
### 3.2 ResourceIngestionPipeline
|
||
|
||
先实现窄接口,不做任意插件市场:
|
||
|
||
```text
|
||
preflight
|
||
-> detect_resource_kind
|
||
-> choose_provider
|
||
-> parse_or_ocr
|
||
-> write_artifact
|
||
-> write_source_map
|
||
-> refresh_evidence_index
|
||
-> broadcast_job_event
|
||
```
|
||
|
||
Provider 策略:
|
||
|
||
- 文本型 PDF / Office parse 优先走 `LiteParseProvider` 或当前轻量 parser。
|
||
- 扫描件 / 图片走 `MinerUProvider`。
|
||
- mock provider 仅用于 smoke,不得在真实功能报告中冒充成功链路。
|
||
|
||
阶段状态:
|
||
|
||
```text
|
||
queued
|
||
preflight
|
||
parsing
|
||
ocr_uploading
|
||
ocr_processing
|
||
writing_artifact
|
||
writing_source_map
|
||
indexing
|
||
done
|
||
failed
|
||
retry_scheduled
|
||
stale
|
||
```
|
||
|
||
当前 `local_ocr.job.updated` 可兼容保留,但 payload 应逐步包含 `jobId / jobType / stage / workspaceId / rootUri / sourceRootRelativePath / targetDocumentId / artifactPath / sourceMapPath`。
|
||
|
||
### 3.3 Evidence Index Lifecycle
|
||
|
||
当前 `.mnote/index/evidence.sqlite` 继续作为默认 evidence index。升级点:
|
||
|
||
- 增加 `schema_version` 和 `build_settings` sentinel。
|
||
- 每次 write / refresh 记录 `job_id`。
|
||
- 索引 row 必须能通过 `source_map_root_relative_path` 回到 canonical artifact。
|
||
- lock 失败进入 `retry_scheduled` job,不直接吞掉。
|
||
- watcher 增量刷新失败时,不做前端轮询补偿;排 recovery job 并广播一次明确事件。
|
||
|
||
建议最小表:
|
||
|
||
```sql
|
||
CREATE TABLE IF NOT EXISTS evidence_index_meta (
|
||
key TEXT PRIMARY KEY,
|
||
value_json TEXT NOT NULL,
|
||
updated_at_ms INTEGER NOT NULL
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS evidence_index_jobs (
|
||
job_id TEXT PRIMARY KEY,
|
||
last_error_code TEXT,
|
||
last_error_message TEXT,
|
||
updated_at_ms INTEGER NOT NULL
|
||
);
|
||
```
|
||
|
||
如果 control-plane 已存 job,这里只保存 index-local rebuild metadata,不重复完整 job 账本。
|
||
|
||
### 3.4 Workspace Sanity Check
|
||
|
||
新增只读检查,不自动删除、不自动修复。
|
||
|
||
检查项:
|
||
|
||
| 级别 | 检查 | 说明 |
|
||
| --- | --- | --- |
|
||
| error | owner Markdown 不存在 | evidence locator 无法打开 |
|
||
| error | resource file 不存在 | 附件或 OCR source 丢失 |
|
||
| error | source-map JSON 无法解析 | 定位真相损坏 |
|
||
| error | evidence.sqlite schema 不匹配 | 需要 rebuild |
|
||
| warning | sidecar 孤儿文件 | 有 OCR/parse artifact 但找不到 owner link |
|
||
| warning | source hash / mtime stale | 可重建,但不阻断 |
|
||
| info | parse/OCR 内容为空 | 允许,但要可见 |
|
||
|
||
输出既可作为 API:
|
||
|
||
```text
|
||
POST /api/workspaces/sanity/check
|
||
GET /api/work/jobs/:jobId
|
||
```
|
||
|
||
也可作为 smoke / CLI helper 的 JSON 结果。
|
||
|
||
### 3.5 Unified Task Foreground UI
|
||
|
||
统一后台任务必须有统一前台可见入口。否则用户仍然只能在 OCR 设置、索引设置、toast、局部状态灯之间猜系统是否还在运行。
|
||
|
||
当前已有的 `mnote-local-ocr-task-dock` 是迁移起点,不是长期终点。它应升级为全局 `Work Task Center`:
|
||
|
||
```text
|
||
Topbar task button
|
||
-> badge: active / failed / needs attention count
|
||
-> drawer: current jobs + recent completed + failed
|
||
-> row: icon + title + stage label + progress bar + actions
|
||
-> detail: input/result/error + related document/resource + trace/run receipt
|
||
```
|
||
|
||
入口位置:
|
||
|
||
- 顶栏保留一个任务中心图标,建议使用 `progress_activity` 或 `pending_actions`。
|
||
- OCR 和索引设置按钮仍可保留,但它们不再各自承载任务列表。
|
||
- 任务中心抽屉优先靠右打开,保持轻量;不做全屏管理台作为第一阶段。
|
||
|
||
任务行最小字段:
|
||
|
||
| 字段 | 来源 | UI 用途 |
|
||
| --- | --- | --- |
|
||
| `jobId` | job ledger | 稳定 row key 和详情查询 |
|
||
| `jobType` | job ledger | 图标、分类、筛选 |
|
||
| `status` | job ledger | 颜色、分组、是否需要确认 |
|
||
| `stageLabel` | job event | 当前阶段文案 |
|
||
| `progressCurrent / progressTotal` | job event | 确定性进度条 |
|
||
| `createdAtMs / startedAtMs / finishedAtMs` | job ledger | 排队/耗时/最近完成 |
|
||
| `targetDocumentId` | job ledger | 打开 owner 文档 |
|
||
| `sourceRootRelativePath` | job ledger | 打开附件或定位资源 |
|
||
| `artifactRootRelativePath / sourceMapRootRelativePath` | result | 打开 OCR/parse/source-map |
|
||
| `errorCode / errorMessage` | job ledger | 失败摘要和复现证据 |
|
||
|
||
进度规则:
|
||
|
||
- 有 `progressCurrent / progressTotal` 时显示确定性进度条。
|
||
- 没有总量但 status 为 running 时显示细条 indeterminate,不伪造百分比。
|
||
- `queued / retry_scheduled` 显示排队态,不显示假进度。
|
||
- `failed` 和 `retry_scheduled` 必须进入“需要处理”计数。
|
||
- `succeeded` 默认保留在最近完成列表,可由用户清除/ack。
|
||
|
||
任务动作:
|
||
|
||
| 状态 | 动作 |
|
||
| --- | --- |
|
||
| running | 打开目标、查看详情 |
|
||
| succeeded | 打开结果、打开目标、清除 |
|
||
| failed | 查看错误、重试、打开目标、复制错误摘要 |
|
||
| retry_scheduled | 查看重试原因、立即重试、取消重试 |
|
||
| stale | 重新生成、打开旧结果 |
|
||
|
||
事件与数据流:
|
||
|
||
```text
|
||
GET /api/work/jobs?scope=currentWorkspace&active=true
|
||
GET /api/work/jobs?scope=currentWorkspace&recent=true
|
||
GET /api/work/jobs/:jobId
|
||
POST /api/work/jobs/:jobId/ack
|
||
POST /api/work/jobs/:jobId/retry
|
||
SSE/WS event: resource_work.job.updated
|
||
```
|
||
|
||
前端运行时:
|
||
|
||
- 新增 `browser/work-task-center-runtime.js`,由 `layout.rs` 统一注入。
|
||
- 现有 `document-resource-tab-runtime.js` 中 OCR task dock 的 state/render 逻辑迁入该 runtime。
|
||
- `mnote:local-ocr-job-updated` 作为兼容事件继续转发为 `resource_work.job.updated`,直到后端统一 payload 完成。
|
||
- 前端只在启动时拉一次 active/recent snapshot;后续靠 WS/SSE 事件更新,不新增周期轮询。
|
||
|
||
视觉约束:
|
||
|
||
- 顶栏只显示一个任务中心 badge,避免 OCR/索引/AI 各自占顶栏状态位。
|
||
- 抽屉行要密集、可扫描,不能做大卡片堆叠。
|
||
- 每行必须有可见进度或阶段文本,长路径截断但 title 保留完整路径 tooltip。
|
||
- 移动端抽屉宽度占满可用宽度,任务行按钮折到第二行,避免文字溢出。
|
||
|
||
## 4. 不做什么
|
||
|
||
- 不把 paperless-ngx 的 Django model / Angular UI / Celery worker 引入 MNote。
|
||
- 不把 OCR Markdown、parse Markdown 或 evidence.sqlite 变成正文真相。
|
||
- 不新增前端轮询来弥补 job 状态;状态更新走现有 WS / SSE / watcher event。
|
||
- 不把任务 UI 继续拆成 OCR 一套、索引一套、AI 一套;这些只能是任务中心里的分类或过滤。
|
||
- 不让 workflow UI 先行。先做 event-triggered job 和少量内置动作,再考虑可视化配置。
|
||
- 不在本轮实现向量 RAG。Paperless 的 FAISS append-only 方案只作为反例和参考,不作为 MNote 默认路径。
|
||
|
||
## 5. 实施分期
|
||
|
||
### Phase A:设计冻结和接口补齐
|
||
|
||
Owner:07-ai / 03-rust-web
|
||
|
||
任务:
|
||
|
||
- [ ] 在 `core-protocol` 增加 `ResourceWorkJob` / `ResourceWorkJobStatus` / `ResourceWorkTriggerSource` 合同。
|
||
- [ ] 在 job 合同中加入 `stage / stageLabel / progressCurrent / progressTotal`,作为前台任务中心稳定字段。
|
||
- [ ] 明确 `local_ocr.job.updated` 与新 `resource_work.job.updated` 的兼容关系。
|
||
- [x] 本设计已作为 `7-46` 历史 job / index lifecycle 参考,不再作为 active 执行补充。
|
||
|
||
验收:
|
||
|
||
- [ ] Rust unit 覆盖 job status 序列化。
|
||
- [ ] Rust unit 覆盖 progress 字段缺省、确定性进度和 indeterminate 语义。
|
||
- [ ] 不改变现有 OCR smoke 行为。
|
||
|
||
### Phase B:OCR job ledger 收口
|
||
|
||
Owner:03-rust-web / control-plane
|
||
|
||
任务:
|
||
|
||
- [ ] 给 `local_ocr::create_job` 创建 control-plane job 记录。
|
||
- [ ] 每次 stage advance 同步 job ledger。
|
||
- [ ] `done / failed` 写入 `finished_at_ms / result_json / error_code`。
|
||
- [ ] 增加 `GET /api/work/jobs/:jobId`。
|
||
- [ ] 增加 `GET /api/work/jobs?active=true&recent=true`,供任务中心首屏 snapshot 使用。
|
||
|
||
验收:
|
||
|
||
- [ ] 现有 OCR sidecar smoke 仍通过。
|
||
- [ ] 新增 smoke 验证 OCR job 可查询、失败错误脱敏、done 后 result 包含 sidecar 和 source-map。
|
||
- [ ] 新增 smoke 验证 active snapshot 包含运行中 OCR job,完成后转入 recent。
|
||
|
||
### Phase B2:统一任务中心 UI
|
||
|
||
Owner:03-rust-web / 05-editor-mainline
|
||
|
||
任务:
|
||
|
||
- [ ] 新增 `browser/work-task-center-runtime.js`。
|
||
- [ ] 将 `mnote-local-ocr-task-dock` 的状态聚合和 drawer 渲染迁移到 work task center。
|
||
- [ ] 顶栏新增统一任务中心按钮和 badge,OCR 按钮回归 OCR 设置入口或合并进设置面板。
|
||
- [ ] 支持 active / needs attention / recent 三个分组。
|
||
- [ ] 任务行支持确定性 progress bar、indeterminate running bar、失败重试、打开目标、打开结果、ack。
|
||
- [ ] 兼容接收 `mnote:local-ocr-job-updated`,并在后端统一事件上线后接 `resource_work.job.updated`。
|
||
|
||
验收:
|
||
|
||
- [ ] 浏览器 smoke:触发 OCR 后顶栏 badge 从 0 变 1,抽屉显示阶段和进度。
|
||
- [ ] 浏览器 smoke:OCR 完成后任务移入 recent,能打开 OCR sidecar。
|
||
- [ ] 浏览器 smoke:mock 失败任务进入 needs attention,能查看错误和重试。
|
||
- [ ] 截图验证桌面和移动端抽屉不溢出、不遮挡主编辑区关键内容。
|
||
|
||
### Phase C:Evidence index lifecycle
|
||
|
||
Owner:07-ai / 03-rust-web
|
||
|
||
任务:
|
||
|
||
- [ ] 给 evidence.sqlite 增加 schema/settings sentinel。
|
||
- [ ] index refresh 写入 job id 或 index-local job metadata。
|
||
- [ ] lock / write / parse source-map 失败时进入 retry-scheduled 或 failed job。
|
||
- [ ] `mnote.index.status` 返回 schema、last build、last job、pending retry。
|
||
- [ ] index refresh / rebuild 通过任务中心显示阶段和结果摘要。
|
||
|
||
验收:
|
||
|
||
- [ ] `task528-document-evidence-liteparse-agent-smoke.js` 继续通过。
|
||
- [ ] 新增 index stale / rebuild smoke,验证删除 evidence.sqlite 后可通过 job 重建。
|
||
- [ ] 浏览器 smoke 验证 index rebuild 任务出现在任务中心。
|
||
|
||
### Phase D:Workspace sanity check
|
||
|
||
Owner:03-rust-web / 04-tree-domain
|
||
|
||
任务:
|
||
|
||
- [ ] 实现只读 `workspace_sanity_check` job。
|
||
- [ ] 检查 owner Markdown、resource file、sidecar、source-map、evidence.sqlite。
|
||
- [ ] 结果按 error / warning / info 分级。
|
||
- [ ] 从任务中心和 index/OCR 设置 surface 都能启动检查;结果统一进入任务中心详情。
|
||
|
||
验收:
|
||
|
||
- [ ] smoke 构造缺失 source-map、孤儿 sidecar、损坏 sqlite,能得到稳定 JSON。
|
||
- [ ] 不删除、不移动任何用户文件。
|
||
- [ ] 浏览器 smoke 验证 sanity check 运行时有任务行,完成后详情展示 error / warning / info 摘要。
|
||
|
||
### Phase E:内置 workflow actions
|
||
|
||
Owner:01-tree-first-graph-kernel / 07-ai
|
||
|
||
任务:
|
||
|
||
- [ ] 定义内置事件:`resource.created`、`resource.changed`、`ocr.done`、`evidence.index.failed`。
|
||
- [ ] 定义内置动作:`parse_resource`、`run_ocr`、`refresh_evidence_index`、`schedule_sanity_check`。
|
||
- [ ] 先用静态配置或 settings 控制,不做复杂 UI。
|
||
|
||
验收:
|
||
|
||
- [ ] 新增附件后能按 settings 自动排 parse/OCR/index job。
|
||
- [ ] 失败不会循环重试;必须有 retry budget 和可见错误。
|
||
|
||
## 6. 设计验收基线
|
||
|
||
本设计完成后,MNote 应具备以下能力:
|
||
|
||
- 用户能看到后台 OCR / parse / index / sanity job 的真实状态,而不是只看到散落的 toast 或局部状态灯。
|
||
- 顶栏任务中心能显示 active / failed / recent 任务,且所有任务进度来自 job ledger 或 job event,不伪造百分比。
|
||
- agent 调用 evidence 工具时,MNote 能把本次证据索引状态、evidence ids、source-map path 写入 run receipt。
|
||
- 删除或损坏 evidence.sqlite 不会让系统静默退化;会显示 rebuild required 或排 rebuild job。
|
||
- OCR sidecar、parse artifact、source-map 和 evidence locator 可以被 sanity check 证明互相可追溯。
|
||
- 多人 / share 场景下,job event 有明确可见性字段,不把本地单用户广播模型固化成长期事实。
|
||
|
||
## 7. 参考代码索引
|
||
|
||
Paperless-ngx:
|
||
|
||
- `src/documents/models.py`:`PaperlessTask`、workflow model、document version fields。
|
||
- `src/documents/tasks.py`:`consume_file`、index deferred tasks、bulk update。
|
||
- `src/documents/consumer.py`:resource consume main path。
|
||
- `src/documents/plugins/base.py`:plugin lifecycle contract。
|
||
- `src/documents/plugins/helpers.py`:progress websocket payload。
|
||
- `src/documents/search/_backend.py`:Tantivy backend、lock retry、autocomplete、highlight。
|
||
- `src/documents/search/_schema.py`:schema version sentinel。
|
||
- `src/documents/search/_query.py`:permission filter、date rewrite、CJK/simple query。
|
||
- `src/documents/sanity_checker.py`:archive consistency checker。
|
||
- `src/paperless/consumers.py`:permission-aware websocket consumer。
|
||
|
||
MNote 当前落点:
|
||
|
||
- `rust/crates/core-protocol/src/governance.rs`
|
||
- `rust/crates/core-protocol/src/evidence.rs`
|
||
- `rust/crates/core-protocol/src/tool.rs`
|
||
- `rust/crates/mnote-web/src/routes/local_ocr.rs`
|
||
- `rust/crates/mnote-web/src/routes/local_search_index.rs`
|
||
- `rust/crates/mnote-web/src/routes/evidence.rs`
|
||
- `rust/crates/mnote-web/src/routes/local_folder_events.rs`
|
||
- `rust/crates/mnote-web/src/routes/ws.rs`
|
||
- `scripts/task528-document-evidence-liteparse-agent-smoke.js`
|