- 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
5.4 KiB
5.4 KiB
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_idprojectionroot_node_iditemsedges
items 里的字段语义冻结如下。
2.2 TypeScript transport contract
前端 TypeScript 侧继续使用 camelCase 字段,但语义必须与 Rust 一致:
projectionIdprojectionKindrootNodeIdparentNodeIdresourceMetaiconHintexpandedByDefault
也就是说:
- 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 为:
expandopendragdropselectcreate-childrenamearchiverestorecontext-menureorderopen-assetpick
约束:
capabilities只表达“允许做什么”- 它不表达局部 UI 状态
- 它不表达 hover、selected、dragging、drop target 这类临时态
5. resource_meta 冻结口径
resource_meta 统一用于表达 projection item 背后的真实资源。
共享字段:
resource_kinddocument_idasset_idworkspace_idasset_kindicon_hintextra
5.1 resource_kind
当前冻结为:
workspacedocumentindexassetasset_foldermindmaptablebookpdf
5.2 asset_kind
当前冻结为:
filemindmaptablebookpdfimagevideoaudiounknown
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必须可直接生成可见 rowspage_tree不允许重新回退成前端自行 flatten 嵌套树
6.3 file_tree
file_tree 是页面树骨架上的更宽对象投影。
它在共享字段基础上强调这些字段必须稳定存在:
resource_kindasset_kindicon_hintexpandableexpanded_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基础 contractpage_tree的row_id/node_id/parent_node_id/depth/position/capabilities/resource_metaexpanded_by_defaultchild_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基础 fixturepage_treefixturefile_treefixtureresource_meta差异字段capabilitiesicon_hintexpanded_by_default
9. 完成判定
当以下条件同时成立时,视为本 contract 冻结完成:
sidebar_tree、page_tree、file_tree的共享字段与差异字段都已写成文档与共享类型- Rust 与前端共享同一组字段语义
file_tree不再依赖前端“补字段猜语义”- 后续 shell / renderer / route 改造不再新增破坏性字段