Files
mnote/design/04-tree-domain/done/4-4-tree-projection-protocol-contract-v1.md
T
lix-2026 5f97800489 chore: align local-first control plane and editor fixes
- wire SQLite control-plane access/session paths into Rust web local-folder routes

- preserve local Markdown attachment semantics across upload, reload, and secondary-pane resource tabs

- refresh design governance docs, Reasonix task templates, and bug records

- retire root .mcp.json local MCP config
2026-05-23 23:38:42 +08:00

219 lines
5.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.
# 4-4 [done] Tree Projection Protocol Contract v1
> 更新时间:2026-04-18
>
> 关联:
> - `/mnt/Data1T/mnote/design/04-tree-domain/process/4-sidebar-pagetree-filetree-rust-web-rebuild-v1.md`
> - `/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/reference/1-tree-first-graph-kernel-v1.md`
## 1. 目的
这份文档用于冻结树域 projection contract,避免 `sidebar_tree``page_tree``file_tree` 在后续 Rust route、Leptos tree shell、Next 挂载切流阶段继续各自长字段。
这里固定三条原则:
- 树域只消费 projection,不消费前端自己拼出来的结构真相
- Rust 与前端共享同一组 projection 字段语义
- `sidebar_tree``page_tree``file_tree` 是同一协议家族,不是三套无关返回值
## 2. 协议分层
### 2.1 Rust canonical contract
Rust 侧的 canonical contract 统一表达为:
- `projection_id`
- `projection`
- `root_node_id`
- `items`
- `edges`
`items` 里的字段语义冻结如下。
### 2.2 TypeScript transport contract
前端 TypeScript 侧继续使用 camelCase 字段,但语义必须与 Rust 一致:
- `projectionId`
- `projectionKind`
- `rootNodeId`
- `parentNodeId`
- `resourceMeta`
- `iconHint`
- `expandedByDefault`
也就是说:
- Rust 是 canonical truth
- TypeScript 只是命名风格映射,不允许再引入第二套语义
## 3. 共享字段
下面这些字段属于 `sidebar_tree``page_tree``file_tree` 的共享基线。
| canonical | TS | 说明 |
| --- | --- | --- |
| `node_id` | `nodeId` | 当前 projection item 对应的 kernel node |
| `parent_node_id` | `parentNodeId` | 上级 node,根节点为 `null` |
| `node_type` | `nodeType` | `workspace/folder/page/section/asset/book/pdf/mindmap/table/index` 等语义类型 |
| `projection_kind` | `projectionKind` | 当前 item 属于哪种 projection`sidebar_tree/page_tree/file_tree` |
| `title` | `title` | 展示标题,允许兜底为“无标题” |
| `depth` | `depth` | 当前树深度 |
| `position` | `position` | 同级排序位置 |
| `child_count` | `childCount` | 子项数量 |
| `expandable` | `expandable` | 当前 item 是否理论上可展开 |
| `expanded_by_default` | `expandedByDefault` | 默认展开建议 |
| `capabilities` | `capabilities` | 当前行允许的交互能力 |
| `resource_meta` | `resourceMeta` | 绑定到业务资源的元信息 |
| `icon_hint` | `iconHint` | 给 shell / renderer 的图标提示 |
## 4. `capabilities` 冻结口径
当前允许的共享 `capabilities` 为:
- `expand`
- `open`
- `drag`
- `drop`
- `select`
- `create-child`
- `rename`
- `archive`
- `restore`
- `context-menu`
- `reorder`
- `open-asset`
- `pick`
约束:
- `capabilities` 只表达“允许做什么”
- 它不表达局部 UI 状态
- 它不表达 hover、selected、dragging、drop target 这类临时态
## 5. `resource_meta` 冻结口径
`resource_meta` 统一用于表达 projection item 背后的真实资源。
共享字段:
- `resource_kind`
- `document_id`
- `asset_id`
- `workspace_id`
- `asset_kind`
- `icon_hint`
- `extra`
### 5.1 `resource_kind`
当前冻结为:
- `workspace`
- `document`
- `index`
- `asset`
- `asset_folder`
- `mindmap`
- `table`
- `book`
- `pdf`
### 5.2 `asset_kind`
当前冻结为:
- `file`
- `mindmap`
- `table`
- `book`
- `pdf`
- `image`
- `video`
- `audio`
- `unknown`
## 6. 三类 projection 的差异字段
### 6.1 `sidebar_tree`
`sidebar_tree` 是最轻的导航 projection。
要求:
- 保留共享字段
- 不引入 `row_id`
- 资源主语义通常落在 `resource_kind=document`
- 允许后续继续作为 workspace 首屏 / stream snapshot 主链
### 6.2 `page_tree`
`page_tree` 是页面树 projection。
它在共享字段基础上新增:
- `row_id`
当前 `row_id` 命名约束:
- `page:<nodeId>`
要求:
- `page_tree` 必须可直接生成 picker 轻量列表
- `page_tree` 必须可直接生成可见 rows
- `page_tree` 不允许重新回退成前端自行 flatten 嵌套树
### 6.3 `file_tree`
`file_tree` 是页面树骨架上的更宽对象投影。
它在共享字段基础上强调这些字段必须稳定存在:
- `resource_kind`
- `asset_kind`
- `icon_hint`
- `expandable`
- `expanded_by_default`
要求:
- `file_tree` 不能继续由前端用 `asset-folder` / `asset` / `index` 临时猜语义作为长期真相
- `file_tree` 必须由 Rust 直接输出 `document/index/asset/asset_folder/mindmap/table/book/pdf` 等对象投影
## 7. 当前稳定项与过渡项
### 7.1 已稳定
- `sidebar_tree` 基础 contract
- `page_tree``row_id/node_id/parent_node_id/depth/position/capabilities/resource_meta`
- `expanded_by_default`
- `child_count`
### 7.2 仍处于过渡
- `file_tree` 里的 `asset_folder/asset/index` 仍有前端 adapter 残留
- `icon_hint` 还没有完全由 Rust 主导
- `asset_kind` 仍需要从更宽对象类型扩展到 `book/pdf`
## 8. Fixture 与 Contract Test 要求
后续所有树域 fixture / contract tests 至少覆盖:
- `sidebar_tree` 基础 fixture
- `page_tree` fixture
- `file_tree` fixture
- `resource_meta` 差异字段
- `capabilities`
- `icon_hint`
- `expanded_by_default`
## 9. 完成判定
当以下条件同时成立时,视为本 contract 冻结完成:
- `sidebar_tree``page_tree``file_tree` 的共享字段与差异字段都已写成文档与共享类型
- Rust 与前端共享同一组字段语义
- `file_tree` 不再依赖前端“补字段猜语义”
- 后续 shell / renderer / route 改造不再新增破坏性字段