Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

Flow 节点几何有三种拼写(ui:{x,y} / spec 的 FlowNode.position / FlowCanvasNode)—— 需要定一种并收敛 #3172

Closed

Description

@os-zhuang

批次 3 燃尽(objectui#3169 / objectstack#4115)时发现,记录在案但有意未修——收敛哪一种是产品/架构决定,且会改变写进元数据的内容。

现状

同一个"节点在画布上的位置"概念,在三处有三种拼写:

位置 拼写
objectui 本地节点 ui: { x, y }
@objectstack/spec 的 FlowNode position
spec 的 FlowCanvasNode 又一种

三者并存意味着:同一份流程元数据在不同环节被读成不同的东西,或者某一环的位置信息被静默丢弃——用户看到的是"我摆好的节点位置保存后跑掉了",而没有任何报错。

需要决定的

哪一种是规范拼写。这不是实现方能自行拍板的:

  • 若以 spec 的 FlowNode.position 为准,objectui 需要迁移 + 兼容读旧数据;
  • 若 objectui 的 ui:{x,y} 有其存在理由(比如它承载的不止坐标),那 spec 侧可能需要建模,或者明确这是两层词汇(参照 objectstack#4115 里 FormField 的"双层词汇"论证:枢纽 + 键集覆盖闸门,而非派生)。

判别法是问一句:这三者描述的是同一个对象,还是管道上下游的不同阶段?

收敛后需要配的闸门

无论选哪种,都要有一条断言把三处钉在一起,否则下一个 spec 版本会再次拉开。可参照 zod/objectql.zod.ts 的 ListViewSchema 范式:spec 字段按引用流入 + parity 测试守卫。

Activity

  1. xuyushun441-sys commented on Aug 3, 2026

    @xuyushun441-sys
    Contributor

    维护者裁决(2026-08-03)

    判别法答案:节点画布位置是同一个对象,不是管道两阶段。规范拼写定为 spec 的 FlowNode.position;objectui 迁移 ui:{x,y},兼容读旧数据,parity 闸门把三处钉在一起。

    节奏(适用维护者例外条款——工作量/风险大到严重影响发版节奏的可移出 v17):协议变更原则上集中 v17,但本项体量未知,先派审计定尺寸:

    1. 审计(现在,进 v17 窗口):确认 ui:{x,y} 是否只承载坐标(若有其它载荷,那部分单独回来议);说清 FlowCanvasNode 与 FlowNode.position 的关系;数清读写两侧全部触点。
    2. 审计后分叉:范围可控 → 收敛落 v17;耦合面大到影响发版节奏 → 回报,候补下一个大版本(旧拼写继续兼容读,不半改)。

    摘 needs-user-decision,加 pm:queue(第一步 = 审计)。


    Generated by Claude Code


    Generated by Claude Code

  2. xuyushun441-sys commented on Aug 3, 2026

    @xuyushun441-sys
    Contributor

    认领(PM 会话 session_01NVPjPzmmAJ2Ngtvgg5MSRa)

    • 账号:xuyushun441-sys
    • 阶段:裁决后的第一步只读审计(无分支、零文件改动)——确认 ui:{x,y} 承载物、FlowCanvasNode 与 FlowNode.position 的关系、读写两侧全部触点,产出尺寸判定(落 v17 或触发例外条款候补大版本)。
    • 审计结论将回帖本单;收敛实施是否随后派发,按审计分叉裁定。

    Generated by Claude Code


    Generated by Claude Code

  3. xuyushun441-sys commented on Aug 3, 2026

    @xuyushun441-sys
    Contributor

    审计报告(只读,零改动;全部证据基于 origin/main)+ 尺寸判定

    判定:范围可控 → 落 v17,实施随即派发(分支 claude/issue-3172-flow-position-canonical)

    关键事实(每条都推翻或收窄了原 issue 的一个前提)

    1.「三种拼写」实际是「两种拼写 + 一个零消费者的 spec 导出」。 FlowCanvasNode 在两个仓都零消费(objectui 侧唯一出现是 spec-symbol-parity.test.ts:176-184 的反向防撞 pin,objectstack 侧只有导出 barrel)。它是按 nodeId 引用的纯视觉 overlay 层(collapsed/width/height/颜色/批注),不是第三条几何链路,不并入本次收敛。

    2. ui:{x,y} 没有第二载荷。 权威声明 flow-canvas-layout.ts:22-25 是封闭的 {x?, y?};全仓穷举 3 个写入点(FlowCanvas.tsx:246/263/316)无一写入 x/y 以外的键。裁决里「若承载不止坐标单独回来议」的分支不触发。

    3. 两版 spec 在 flow 几何面逐字节一致(发布 rc.1 tarball vs objectstack main git diff --exit-code 通过)——没有 app.homePageId 那种 pin/main 漂移。FlowNode.position 已声明、strict、{x,y} 均必填;objectstack 侧零改动。

    4. 症状修正——不是「静默丢位置」,是一道 422 硬闸门(静态推导)。 #4001 起 spec 的 flow schema 是 .strict(),nodes[i].ui 产出 unrecognized_keys:客户端 clientValidation.ts:73 每 200ms 实时飘红,服务端 protocol.ts:6670→6684 保存 422。即今天在设计器里拖一个节点,这份 flow 就存不进去了。「摆好位置保存后跑掉」的静默版本只在 #4001 之前的非 strict 链路上成立。⚠️ 此链为静态证据,未跑真机——实施时须 dogfood 复核。

    5. 存量为空(仓内)。 两仓的 examples/fixtures 全部既无 ui 也无 position;objectui 内仅 2 条测试夹具带 ui。真实环境存量仓内无法回答,建议部署时用 os migrate meta --stored 实测——但因第 4 条,带 ui 的行今天本就存不进去,存量面大概率接近空集。

    6. 触点总量:5 文件 / ~15 处,5/5 在 @object-ui/app-shell 一个包内(FlowCanvas.tsx 写 3 + flow-canvas-layout.ts 读 2 + 类型 3 + 夹具 2 + 文档/注释 5)。与在飞的 #3233(types/react/components/fields)零相交,可并行。

    实施不变量(工单要点)

    1. 写侧一律产出 position:{x,y},永不再写 ui;离开设计器的 draft 必须 ui-free(遗留 ui 在持久化时抬升为 position 并删除——migrate-on-write,让存量自愈且过 strict 闸门)。
    2. 读侧 position 优先,ui 仅作遗留回退(裁决的「兼容读旧数据」);保留「x/y 同时有限」判据。
    3. 几何类型按引用派生自 spec FlowNodeSchema.shape.position,parity 正向断言加进 spec-symbol-parity.test.ts(保留既有反向 pin);消灭 FlowPreview.tsx:52 的形状拷贝。
    4. ⚠️ FlowDesignerNode 带索引签名,编译器不会替你抓漏读点——靠穷举清单 + 回归测试兜底(遗留节点仍渲染在钉位、持久化后 patch 无 ui、拖拽产出 position)。

    顺手发现(不并入,已在报告记录)

    spec liveness 账本 flow.json 把 position 判 live 的依据是「designer 在用」——而 designer 用的是 ui。这条判词在收敛落地前是虚的。已作为跨仓 liveness 盲区的第二个数据点补充到 objectstack#4865。


    Generated by Claude Code


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions