Files
mnote/design/05-editor-mainline/done/5-15-local-markdown-path-identity-unification-checklist-v1.md
T
lix-2026 1956a8a21a chore: align mvp design governance
- 统一 local-first MVP 后阶段架构口径,补充 process 执行总序和 Reasonix 协作记录

- 归档已完成的 design checklist,标注参考型 process,更新 AGENTS/REASONIX/架构文档

- 补充文件树/主编辑器下载与上下文菜单相关实现、bug 记录和 smoke 脚本

验证:git diff --check;codegraph sync .;cargo test -p mnote-web;node --check scripts/task476-filetree-editor-context-menu-download-smoke.js
2026-05-21 09:04:13 +08:00

139 lines
7.4 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.
# 5-15 本地 Markdown 路径身份统一 Checklist v1
> 状态:done
>
> 归档说明(2026-05-21):本地 Markdown 路径身份统一 checklist 已完成并从 `process/` 归档到 `done/`。
## 背景
当前本地 Markdown 主链正在对齐 VS Code 文件模型:普通 `.md` 文件的运行时身份应来自文件资源地址,而不是 frontmatter 或 MNote 内部稳定 ID。
VS Code 参考:
- `design/05-editor-mainline/reference-code/vscode/src/vs/platform/files/common/fileService.ts`
- `createFile(resource)``URI` 创建文件。
- `design/05-editor-mainline/reference-code/vscode/src/vs/workbench/contrib/files/browser/fileCommands.ts`
- 新建文件后 `openEditor({ resource: saveUri })`
- `design/05-editor-mainline/reference-code/vscode/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts`
- `matches()` 使用 `isEqual(otherInput.resource, this.resource)`
- `design/05-editor-mainline/reference-code/vscode/src/vs/workbench/contrib/files/browser/editors/fileEditorHandler.ts`
- working copy 与 editor 是否同一打开项,比较 `workingCopy.resource``editor.resource`
本阶段目标不是引入新的稳定语义 ID,而是先消除普通本地 Markdown runtime 中的多 ID 竞争。
## 身份原则
- 普通本地 Markdown 的真实身份是 `sourceKind + rootUri + relativePath`
- 对外 `documentId` 继续使用路径型短句柄:`local-md:<encoded relative_path>`
- `mnote_id` 只作为已有 frontmatter 元数据保留,不参与普通本地 Markdown 的 `documentId` 决策。
- `.mnote/page-ids.json` 只允许作为历史兼容/迁移辅助,不参与普通本地 Markdown 的主身份生成。
- 不主动修改、删除或重写用户 Markdown frontmatter。
## 允许修改范围
- `rust/crates/mnote-web/src/routes/local_search_index.rs`
- `rust/crates/mnote-web/src/routes/local_folder_source.rs`
- 必要时更新直接相关测试:
- `rust/crates/mnote-web/src/routes/search.rs`
- `rust/crates/mnote-web/src/routes/tree.rs`
- `rust/crates/mnote-web/src/routes/documents.rs`
不要修改用户数据目录,不要清理仓库中无关脏文件,不要做 git commit。
## P0 Checklist
### 1. 搜索索引 documentId 与树形列表统一
- [ ] `local_search_index.rs``index_markdown_file()` 永远按 `relative_path` 生成 `local-md:<encoded relative_path>`
- [ ] frontmatter `mnote_id` 不再生成 `local-mdid:*`
- [ ] 搜索结果、最近修改、反链接口返回的 Markdown `documentId` 与文件树一致。
- [ ]`mnote_id` 的 Markdown 搜索测试必须断言仍返回路径型 ID,例如 `local-md:docs~2Fchild.md`
验收:
```bash
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_search_index -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web search_local_index -- --nocapture
```
### 2. 清理本地 Markdown 身份生成的误导参数
- [ ] `local_markdown_page_id(relative_path, _mnote_id, _metadata)` 不再保留无用参数签名。
- [ ] 普通调用点直接使用 `local_markdown_path_page_id(relative_path)` 或新的清晰命名函数。
- [ ] 如果必须保留 legacy resolver,函数名必须包含 `legacy` / `compat`,并且不能参与普通本地 Markdown 主链。
验收:
```bash
rg -n "local_markdown_page_id\\(|local-mdid|mnote_id|page-ids" rust/crates/mnote-web/src/routes/local_folder_source.rs rust/crates/mnote-web/src/routes/local_search_index.rs
```
期望:
- `local_markdown_page_id(` 不应再出现在普通主链调用中。
- `local_search_index.rs` 不应再出现 `local-mdid` 生成逻辑。
- `mnote_id` 可以继续出现在解析、兼容测试或“保留 frontmatter”测试中,但不能参与普通 `documentId` 生成。
### 3. 不污染用户文件
- [ ] 新建本地 Markdown 不写 `mnote_id` frontmatter。
- [ ] 复制本地 Markdown 不改写 `mnote_id`
- [ ] 保存已有 Markdown 时保留原 frontmatter,但不新增身份字段。
验收:
```bash
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_tree_command_local_folder_lifecycle -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_page_aggregate_accepts_path_id_when_frontmatter_has_mnote_id -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_save -- --nocapture
```
## P1 Checklist
### 4. 路径型身份覆盖打开/保存/搜索一致性
- [ ] 同一个含 `mnote_id``.md` 文件,在文件树、页面 aggregate、搜索索引中返回同一个 `local-md:<encoded relative_path>`
- [ ] `documents.content.get` / 页面打开不再需要 `local-mdid:*` 才能命中文件。
- [ ] rename/move 后新路径返回新的路径型 `documentId`,旧路径型 ID 不作为稳定页面 ID 保留。
验收:
```bash
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_markdown_identity_uses_path_even_when_frontmatter_has_mnote_id -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_page_aggregate_accepts_path_id_when_frontmatter_has_mnote_id -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web tree_command_local_folder_lifecycle -- --nocapture
```
## 最终验收
```bash
cargo fmt --check --all --manifest-path rust/Cargo.toml
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_search_index -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web search_local_index -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_markdown_identity_uses_path_even_when_frontmatter_has_mnote_id -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_page_aggregate_accepts_path_id_when_frontmatter_has_mnote_id -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web tree_command_local_folder_lifecycle -- --nocapture
```
若涉及浏览器可见行为,Codex 复核阶段必须使用真实浏览器验证并将截图放在 `tmp/` 下。
## 执行状态(2026-05-19
- [x] P0-1 搜索索引 `documentId` 已统一为 `local-md:<encoded relative_path>`,不再由 frontmatter `mnote_id` 生成 `local-mdid:*`
- [x] P0-2 普通本地 Markdown 主链已移除 `local_markdown_page_id(relative_path, _mnote_id, _metadata)` 误导签名,文件树、page aggregate、find-by-id 改用路径型 ID。
- [x] P0-3 新建、复制、rename/move/restore/purge 普通本地 Markdown 不再写 `.mnote/page-ids.json`,也不再写入或改写 `mnote_id`
- [x] P1-4 rename/move 后返回新路径型 `documentId`,旧 ID 不再作为稳定页面 ID 保留。
- [x] 追加清理:删除 `ParsedLocalMarkdownPage.mnote_id` 字段,避免后续代码重新把 frontmatter `mnote_id` 当身份入口。
已通过验收:
```bash
cargo fmt --check --all --manifest-path rust/Cargo.toml
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_search_index -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web search_local_index -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_markdown_identity_uses_path_even_when_frontmatter_has_mnote_id -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_page_aggregate_accepts_path_id_when_frontmatter_has_mnote_id -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_page_id_initialization_returns_path_id_without_writing_page_ids -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web tree_command_local_folder -- --nocapture
```