ui editor 页面优化 #337

Merged
k88936 merged 132 commits from feat/ui-editor-v3 into master 2026-09-24 19:45:47 +08:00
Member

style: 把各个工具栏做在画布之上

  • before shotmd-1789215480.jpg
  • after shotmd-1789215182.png
style: 把各个工具栏做在画布之上 * before ![shotmd-1789215480.jpg](/attachments/d87030e5-1a30-45bd-9540-662b09a440f4) * after ![shotmd-1789215182.png](/attachments/73ab73fd-8c08-4ed3-b5c3-ff1d6d8e0a73)
k88936 self-assigned this 2026-09-12 19:26:46 +08:00
k88936 added this to the 陶泥儿gameAgent project 2026-09-12 19:26:46 +08:00
k88936 force-pushed feat/ui-editor-v3 from d4796a90ab to 706563378b 2026-09-14 10:16:29 +08:00 Compare
k88936 force-pushed feat/ui-editor-v3 from 706563378b to 6dbc4a39cb 2026-09-14 13:00:00 +08:00 Compare
k88936 added 20 commits 2026-09-14 19:00:10 +08:00
- 预览改为全区域背景层。
  - 左右面板、顶部流程条改为覆盖层,可遮挡预览。
  - 左右面板开合状态仅保存在当前 React 会话。
  - 增加左右面板“收起/展开”入口。
  - 编辑器关闭入口改为单独的 ×,继续通过 onBack 注入关闭逻辑。
  - 保留全局顶部栏与现有快捷键、业务状态、保存流程。
  - 底层页面仍由现有父级路由控制,不新增 URL 状态。
通过 portal 将资源编辑器挂载到 body 并覆盖标题栏以下区域

移除外层 FocusTrap,保留内部确认对话框的模态行为

统一左右浮动面板的顶部与底部留白
为无限视口添加跟随平移和缩放的点阵背景

恢复画布快捷缩放与初始适配比例控制

保留节点平移选择并屏蔽浏览器原生拖拽选择
将识别概览指标改为四列横向排列

将素材切分概览改为四列网格以减少纵向高度
从实际节点事件目标验证删除快捷键

验证 portal 右键菜单启用后会执行操作并关闭
修复受控树选中回调清除 Inspector 高亮的问题

循环游标同时使用界面树与节点 ID

补充多节点循环和动画重启回归测试
向 SeparationOverview 传入 fonts 数据

修复 UI 编辑器 TS2741 类型错误
新增 Node offset min/max 数据结构

统一新树默认横向布局入口

增加树级偏移状态更新操作与实施计划
预览画布同时渲染全部界面树并支持树级拖动

拆分显示框线、原图和组件开关

预览节点选择与左侧当前图片解耦
为合并产出的节点补齐 NodeOffset
统一识别和合并结果的 createTree 流程

按选中节点所属树驱动 Inspector 编辑

补充多树预览与树级偏移权威文档
预览菜单携带所属树 ID

避免非当前图片树的结构操作写错目标
完成三开关替代 render mode 的类型清理
新增保存成功、代码生成成功和失败状态弹窗

提供项目相对路径复制按钮及复制失败提示
让普通保存和保存并生成流程返回结构化结果

将成功与失败反馈接入独立弹窗并保留保存并返回直返行为
覆盖保存和生成成功弹窗与项目相对路径复制

覆盖保存失败、冲突和剪贴板失败反馈
补充保存与代码生成结果弹窗及相对路径复制行为

记录复制失败、重试和保存并返回边界
移除 activeImageId 对预览拖动和缩放手势的门控

按树 wrapper 提供几何上下文并允许任意树操作

保留 activeImageId 仅用于左侧图片与图片级检查
拆分 UI 编辑器路径复制按钮
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 2m27s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 2m23s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Failing after 2m5s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Failing after 2m8s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m57s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m15s
Project CI / Frontend tests (pull_request) Failing after 3m22s
Project CI / Repository checks (pull_request) Successful in 3m38s
Project CI / Native shell tests (pull_request) Successful in 6m42s
Project CI / AI game creator shell web tests (pull_request) Failing after 3m12s
Project CI / Backend tests (pull_request) Successful in 8m24s
8a0d5600b3
将剪贴板状态与写入逻辑提取为独立小组件

保持保存结果弹窗只负责结果布局与动作编排
k88936 force-pushed feat/ui-editor-v3 from 15c633986d to 8a0d5600b3 2026-09-14 19:00:10 +08:00 Compare
k88936 added 6 commits 2026-09-14 19:54:01 +08:00
增加普通保存成功与保存后生成失败的场景断言

验证路径弹窗和失败重试按钮的可见行为
将复制失败提示与操作按钮分离排列
为主窗口补充 clipboard-manager 写文本权限

保留手动复制提示并继续抛出原始 Tauri 剪贴板错误
提取预览网格自适应步长到独立模块

补充缩放网格计算与背景样式测试

同步预览画布缩放交互文档
记录 UI fallback 后仍需抛出原始原生错误

明确未知异常必须进入 error report 链路
扩大未知 JavaScript 异常上报原则
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
1e992bcdf8
明确所有未解决和非契约化 JS 异常必须继续抛出

说明用户 fallback 不得替代全局 error report 链路
kdletters moved this to 进行中 in 陶泥儿gameAgent on 2026-09-16 12:11:04 +08:00
k88936 added 1 commit 2026-09-16 14:58:23 +08:00
Merge remote-tracking branch 'origin/master' into feat/ui-editor-v3
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 3m0s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 3m4s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Failing after 3m7s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Failing after 3m9s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m41s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m32s
Project CI / Frontend tests (pull_request) Failing after 4m47s
Project CI / Repository checks (pull_request) Failing after 4m39s
Project CI / Native shell tests (pull_request) Successful in 7m14s
Project CI / Backend tests (pull_request) Successful in 8m12s
Project CI / AI game creator shell web tests (pull_request) Failing after 2m54s
4df4708ba1
# Conflicts:
#	docs/project-memory/shared-memory/pitfalls.md
k88936 added 3 commits 2026-09-18 10:36:51 +08:00
新增 React-free 语义状态迁移 seam

收敛 State 级节点几何与保存前不变量校验

统一四类异步编辑器操作生命周期

补充状态迁移和不变量测试
统一必需 tool-call 定位与有界 JSON 参数解析

让语义建议、结构识别、组件绑定和多树合并复用稳定机械

保留各操作的 prompt、schema、领域校验与 materializer
更新UI编辑器深模块架构文档
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 4m16s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 4m23s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Failing after 4m24s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Failing after 4m26s
Project CI / Backend tests (pull_request) Failing after 13s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m52s
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 3m28s
Project CI / Frontend tests (pull_request) Failing after 3m30s
Project CI / AI game creator shell web tests (pull_request) Failing after 4m33s
Project CI / Native shell tests (pull_request) Successful in 9m17s
55a8513de4
记录状态迁移、几何、不变量与操作生命周期 seam

同步结构化 LLM 适配器边界与验证结果
k88936 added 30 commits 2026-09-18 18:45:15 +08:00
补齐 NodeOffset 默认值以恢复 Rust 测试构建
补齐 NodeOffset 默认值以恢复 Rust 测试构建
恢复缺失工具调用的独立日志阶段和提示
恢复识别工具缺失的独立日志阶段和提示
恢复缺失工具调用的独立日志阶段和提示
为跨树选择回调参数添加下划线前缀
选择节点时同步激活所属设计图
复制失败仅保留界面错误状态
保留部分更新对未提供字段的原有语义
用显式分支替换嵌套三元表达式
移除不会被发出的 missing-image 类型
将窄侧栏概览调整为两列网格
将窄侧栏概览调整为两列网格
仅重启动 UI 编辑器关注动画而不影响过渡效果
为二维数组字段补充 ts-rs 元组覆盖
返回路径保存失败时沿用确认弹窗错误状态
将实际异常传递到保存状态和重试提示
用显式条件替换嵌套三元表达式
移除未被调用的 setRunning 与 reset 暴露
删除失效的 generateError 状态及写入路径
避免无效 pixels_per_unit 产生无限尺寸
复用单一 Node 类型导入声明
仅将有限偏移量纳入画布布局
从指针释放坐标直接计算树位置
移除仅通过 ref 读取的画布尺寸依赖
用显式早返回替换嵌套三元渲染
统一关闭与重试按钮的布局和样式
从公开 offset 模块导入 NodeOffset
更新 ts-rs 生成的 NodeOffset 类型文件
Merge remote-tracking branch 'origin/master' into feat/ui-editor-v3
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 5m0s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m54s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 7m15s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Failing after 6m32s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 6m56s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m21s
Project CI / Frontend tests (pull_request) Failing after 4m23s
Project CI / Repository checks (pull_request) Failing after 5m22s
Project CI / Native shell tests (pull_request) Successful in 9m10s
Project CI / Backend tests (pull_request) Successful in 9m41s
Project CI / AI game creator shell web tests (pull_request) Failing after 5m32s
e4369cd82e
# Conflicts:
#	apps/ai-game-creator-shell/tests/uiEditorPage.test.ts
#	docs/project-memory/shared-memory/decision-log.md
Author
Member

UI Editor review 复核结果

说明:[x] 表示已自动修复并单独提交;[ ] 表示保留给用户处理的高风险/产品取舍项。每项均按“当前实现 → 问题 → 建议”说明。此文件是临时复核清单,不提交。

  • 1. apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/merge.rs:306(提交 6b8a10641):当前合并测试 helper 构造 Node 时没有 offset;新增字段后测试无法编译。已补 NodeOffset::default()。若未来统一提供 Node 构造器,可再减少测试样板。
  • 2. .../commands/merge.rs:490-493(提交 d37064886):当前直接用 required_tool_arguments,工具调用缺失和参数 JSON 错误共用 parse_arguments。已先解析工具调用并记录 parse_tool_call/missing_tool_call,再单独解析参数;建议继续保持这两个阶段分离。
  • 4. .../commands/separation/mod.rs(提交 4f4fb0873365e530b5):当前切分测试 helper 同样漏填 offset;已补默认值并修正从公开 layout::offset 模块导入类型。建议保留显式默认值,避免测试依赖结构体字段顺序。
  • 5. .../components/InputSidebar.tsx:93-94(提交 08c3b89b6):当前跨树节点点击只更新节点选择,不切换 active design image;Delete 等操作可能命中旧树。已在真实跨节点选择分支先调用 selectDesignImage 再选择节点。建议保留同节点通知去重逻辑。
  • 6. .../UiEditorCopyPathButton.tsx:22-23(提交 abd95a623):当前复制失败已设置 failed 状态,却又从 void copyPath() 抛出异常,造成未处理 Promise rejection。已移除重复抛出;用户可见错误仍由状态提示。
  • 7. .../features/ui-editor/stateTransition.ts:120(提交 ce309a3b2):当前 spread 会把类型允许但值为 undefined 的补丁写回 metadata。已过滤 undefined 后再 clone/merge,恢复“未提供字段不覆盖”的语义。
  • 8. .../features/ui-editor/stageStatusOverview.ts:91-99(提交 bec225436):当前上一项索引使用嵌套三元表达式。已改为显式 if/else,行为不变且便于区分字符串游标与树游标。
  • 9. .../features/ui-editor/stateInvariants.ts:5-9(提交 f455d3edb):当前 missing-image 只在 union 中声明,校验器从不发出;实际缺失树图片使用 missing-tree-image。已移除死类型,建议以后新增 issue code 时同步发出路径或不加入 union。
  • 10. .../commands/recognition.rs:773-778(提交 0988c4907):当前识别流程把缺失工具调用当成参数解析失败。已区分 parse_tool_call/missing_tool_callparse_arguments,并恢复专门的“未返回工具调用”提示。
  • 11. .../commands/ui_design_suggestion.rs:217-219(提交 899a591cd):当前语义建议流程同样混淆缺失工具调用和坏 JSON。已拆分工具查找与参数解析,并记录独立诊断阶段。
  • 13. .../components/RecognitionOverview.tsx:47(提交 91f534ed6):当前固定窄侧栏使用四列,标签宽度不足会换行拥挤。已改为两列;建议后续若面板宽度可变再加响应式断点。
  • 14. .../components/SeparationOverview.tsx:50(提交 2d8b51885):当前同样在窄侧栏使用四列。已改为两列,长标签可读性更好。
  • 15. .../components/Inspector/InspectorSidebar.tsx:844-849(提交 f4e9414d6):当前 getAnimations() 会同时拿到 transition 和多个 pseudo-element animation。已只重启名称以 ui-editor-status-attention 开头的动画,避免干扰无关过渡。
  • 16. .../components/UiEditorSaveResultModal.tsx:118-129(提交 d46cdfb28):当前成功、生成、失败通知分别复制 footer 按钮 markup。已抽取 NoticeFooter,统一关闭/重试布局和样式;不改变 retry handler 行为。
  • 17. .../layout/offset.rs:7-8(提交 3ce2977e3、绑定同步提交 54b9bd435):当前 ts-rs 默认把 [f32; 2] 导出为 Array<number>,而前端 NodeOffset 使用 tuple。已为 min/max 加 [f32; 2] 覆盖并同步生成绑定,避免类型漂移。
  • 18. .../view/ui-editor/index.tsx:147-152(提交 1e7a3f17f):当前返回路径保存失败时确认弹窗仍打开,同时叠加保存结果弹窗。已对 afterReturn 失败直接沿用确认弹窗中的 save error,不再打开第二个 focus trap。
  • 19. .../useUiEditorPage.ts:1559-1562(提交 31c084fce):当前 catch 丢弃底层异常,固定显示“保存失败”。已保留 Error.message/字符串异常并写入 save error 和返回结果,便于诊断和重试。
  • 20. .../view/ui-editor/index.tsx:92-93(提交 c921ae3b1):当前 overview 渲染是嵌套三元。已改为显式分支,保持三个步骤映射不变。
  • 21. .../operationLifecycle.ts:6-10(提交 a6c3db60f):当前 hook 对外暴露 setRunningreset,但现有调用方只使用 running/status/begin/finish/setStatus。已收窄公开返回面并删除无调用的 reset 实现;若未来需要外部重置,应按明确生命周期重新接入。
  • 22. .../useUiEditorPage.ts:1551(提交 6d02a0c29):当前 generateError 只写不读,页面已通过返回结果 notice 展示生成失败。已删除该状态、写入和 projection 字段,避免形成误导性的死状态。
  • 23. .../components/preview/PreviewWorkspace.tsx:124-126(提交 1ab7fa999):当前 pixels_per_unit 为 0/非有限值时直接相除,可产生 Infinity 并污染 bounds/viewport。已在相除前校验有限且大于 0,无效图片按 0 尺寸处理。
  • 24. .../components/preview/PreviewWorkspace.tsx:33(提交 0a102ea1c):当前同一模块分两次导入 Node 和别名 UiNode。已合并为单一类型导入并复用 Node
  • 25. .../components/preview/PreviewWorkspace.tsx:132(提交 e72637789):当前 offset.min 是必填数组,Boolean(array) 永远为真,过滤无效。已改为检查两个坐标均为有限数。
  • 26. .../components/preview/PreviewWorkspace.tsx:427-428(提交 70c65c37d):当前 pointerup 从 React state 快照读偏移,可能落后一帧。已从 drag 起点、释放坐标和当前 viewport scale 直接计算最终偏移再提交。
  • 27. .../components/preview/PreviewWorkspace.tsx:211-212(提交 8fdf39f37):当前 effect 读取 canvasSizeRef 却依赖 canvasSize 状态,依赖项本身惰性且初始适配由 ref/一次性 guard 控制。已移除无效依赖;没有擅自改变 resize 适配时机,若要修正零尺寸首次 fit 需另做交互验证。
  • 28. .../components/InputSidebar.tsx:93-94(提交 337133734):当前移除切图调用后 treeId 参数变成未使用参数,会触发 ESLint。已先将其改为 _treeId,再在第 5 项恢复实际使用。
  • 29. .../components/UiEditorSaveResultModal.tsx:33-39(提交 2142027f8):当前 notice 内容使用嵌套三元链。已抽取 renderNoticeContent,用早返回映射三种 notice。
# UI Editor review 复核结果 说明:`[x]` 表示已自动修复并单独提交;`[ ]` 表示保留给用户处理的高风险/产品取舍项。每项均按“当前实现 → 问题 → 建议”说明。此文件是临时复核清单,不提交。 - [x] 1. `apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/merge.rs:306`(提交 `6b8a10641`):当前合并测试 helper 构造 `Node` 时没有 `offset`;新增字段后测试无法编译。已补 `NodeOffset::default()`。若未来统一提供 `Node` 构造器,可再减少测试样板。 - [x] 2. `.../commands/merge.rs:490-493`(提交 `d37064886`):当前直接用 `required_tool_arguments`,工具调用缺失和参数 JSON 错误共用 `parse_arguments`。已先解析工具调用并记录 `parse_tool_call/missing_tool_call`,再单独解析参数;建议继续保持这两个阶段分离。 - [x] 4. `.../commands/separation/mod.rs`(提交 `4f4fb0873`、`365e530b5`):当前切分测试 helper 同样漏填 `offset`;已补默认值并修正从公开 `layout::offset` 模块导入类型。建议保留显式默认值,避免测试依赖结构体字段顺序。 - [x] 5. `.../components/InputSidebar.tsx:93-94`(提交 `08c3b89b6`):当前跨树节点点击只更新节点选择,不切换 active design image;Delete 等操作可能命中旧树。已在真实跨节点选择分支先调用 `selectDesignImage` 再选择节点。建议保留同节点通知去重逻辑。 - [x] 6. `.../UiEditorCopyPathButton.tsx:22-23`(提交 `abd95a623`):当前复制失败已设置 `failed` 状态,却又从 `void copyPath()` 抛出异常,造成未处理 Promise rejection。已移除重复抛出;用户可见错误仍由状态提示。 - [x] 7. `.../features/ui-editor/stateTransition.ts:120`(提交 `ce309a3b2`):当前 spread 会把类型允许但值为 `undefined` 的补丁写回 metadata。已过滤 `undefined` 后再 clone/merge,恢复“未提供字段不覆盖”的语义。 - [x] 8. `.../features/ui-editor/stageStatusOverview.ts:91-99`(提交 `bec225436`):当前上一项索引使用嵌套三元表达式。已改为显式 `if/else`,行为不变且便于区分字符串游标与树游标。 - [x] 9. `.../features/ui-editor/stateInvariants.ts:5-9`(提交 `f455d3edb`):当前 `missing-image` 只在 union 中声明,校验器从不发出;实际缺失树图片使用 `missing-tree-image`。已移除死类型,建议以后新增 issue code 时同步发出路径或不加入 union。 - [x] 10. `.../commands/recognition.rs:773-778`(提交 `0988c4907`):当前识别流程把缺失工具调用当成参数解析失败。已区分 `parse_tool_call/missing_tool_call` 与 `parse_arguments`,并恢复专门的“未返回工具调用”提示。 - [x] 11. `.../commands/ui_design_suggestion.rs:217-219`(提交 `899a591cd`):当前语义建议流程同样混淆缺失工具调用和坏 JSON。已拆分工具查找与参数解析,并记录独立诊断阶段。 - [x] 13. `.../components/RecognitionOverview.tsx:47`(提交 `91f534ed6`):当前固定窄侧栏使用四列,标签宽度不足会换行拥挤。已改为两列;建议后续若面板宽度可变再加响应式断点。 - [x] 14. `.../components/SeparationOverview.tsx:50`(提交 `2d8b51885`):当前同样在窄侧栏使用四列。已改为两列,长标签可读性更好。 - [x] 15. `.../components/Inspector/InspectorSidebar.tsx:844-849`(提交 `f4e9414d6`):当前 `getAnimations()` 会同时拿到 transition 和多个 pseudo-element animation。已只重启名称以 `ui-editor-status-attention` 开头的动画,避免干扰无关过渡。 - [x] 16. `.../components/UiEditorSaveResultModal.tsx:118-129`(提交 `d46cdfb28`):当前成功、生成、失败通知分别复制 footer 按钮 markup。已抽取 `NoticeFooter`,统一关闭/重试布局和样式;不改变 retry handler 行为。 - [x] 17. `.../layout/offset.rs:7-8`(提交 `3ce2977e3`、绑定同步提交 `54b9bd435`):当前 ts-rs 默认把 `[f32; 2]` 导出为 `Array<number>`,而前端 NodeOffset 使用 tuple。已为 min/max 加 `[f32; 2]` 覆盖并同步生成绑定,避免类型漂移。 - [x] 18. `.../view/ui-editor/index.tsx:147-152`(提交 `1e7a3f17f`):当前返回路径保存失败时确认弹窗仍打开,同时叠加保存结果弹窗。已对 `afterReturn` 失败直接沿用确认弹窗中的 save error,不再打开第二个 focus trap。 - [x] 19. `.../useUiEditorPage.ts:1559-1562`(提交 `31c084fce`):当前 catch 丢弃底层异常,固定显示“保存失败”。已保留 `Error.message`/字符串异常并写入 save error 和返回结果,便于诊断和重试。 - [x] 20. `.../view/ui-editor/index.tsx:92-93`(提交 `c921ae3b1`):当前 overview 渲染是嵌套三元。已改为显式分支,保持三个步骤映射不变。 - [x] 21. `.../operationLifecycle.ts:6-10`(提交 `a6c3db60f`):当前 hook 对外暴露 `setRunning`、`reset`,但现有调用方只使用 running/status/begin/finish/setStatus。已收窄公开返回面并删除无调用的 reset 实现;若未来需要外部重置,应按明确生命周期重新接入。 - [x] 22. `.../useUiEditorPage.ts:1551`(提交 `6d02a0c29`):当前 `generateError` 只写不读,页面已通过返回结果 notice 展示生成失败。已删除该状态、写入和 projection 字段,避免形成误导性的死状态。 - [x] 23. `.../components/preview/PreviewWorkspace.tsx:124-126`(提交 `1ab7fa999`):当前 `pixels_per_unit` 为 0/非有限值时直接相除,可产生 Infinity 并污染 bounds/viewport。已在相除前校验有限且大于 0,无效图片按 0 尺寸处理。 - [x] 24. `.../components/preview/PreviewWorkspace.tsx:33`(提交 `0a102ea1c`):当前同一模块分两次导入 `Node` 和别名 `UiNode`。已合并为单一类型导入并复用 `Node`。 - [x] 25. `.../components/preview/PreviewWorkspace.tsx:132`(提交 `e72637789`):当前 `offset.min` 是必填数组,`Boolean(array)` 永远为真,过滤无效。已改为检查两个坐标均为有限数。 - [x] 26. `.../components/preview/PreviewWorkspace.tsx:427-428`(提交 `70c65c37d`):当前 pointerup 从 React state 快照读偏移,可能落后一帧。已从 drag 起点、释放坐标和当前 viewport scale 直接计算最终偏移再提交。 - [x] 27. `.../components/preview/PreviewWorkspace.tsx:211-212`(提交 `8fdf39f37`):当前 effect 读取 `canvasSizeRef` 却依赖 `canvasSize` 状态,依赖项本身惰性且初始适配由 ref/一次性 guard 控制。已移除无效依赖;没有擅自改变 resize 适配时机,若要修正零尺寸首次 fit 需另做交互验证。 - [x] 28. `.../components/InputSidebar.tsx:93-94`(提交 `337133734`):当前移除切图调用后 `treeId` 参数变成未使用参数,会触发 ESLint。已先将其改为 `_treeId`,再在第 5 项恢复实际使用。 - [x] 29. `.../components/UiEditorSaveResultModal.tsx:33-39`(提交 `2142027f8`):当前 notice 内容使用嵌套三元链。已抽取 `renderNoticeContent`,用早返回映射三种 notice。
k88936 added 8 commits 2026-09-18 22:48:55 +08:00
校验 offset 前安全处理旧状态和测试夹具
按现役浮动关闭按钮的可访问名称查询
让当前 schema 夹具继续验证原有业务约束
让动画 mock 匹配仅重启提示动画的现役筛选逻辑

保留非提示动画不被重启的生产行为
从仍挂载的窗口目标触发全局删除快捷键

按全部同名节点消失断言删除结果
无框线场景不再传入选中节点以匹配选中态高亮规则

保留显式 showFrame 时的选中框与控制点断言
覆盖上下文菜单回调的可选树标识参数

区分编辑器树目标与最终预览的无树标识回调
迁移节点变换交互测试接口
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 4m8s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 4m25s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 4m24s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 5m13s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m34s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m39s
Project CI / Frontend tests (pull_request) Successful in 5m56s
Project CI / AI game creator shell web tests (pull_request) Successful in 8m34s
Project CI / Repository checks (pull_request) Successful in 15m18s
Project CI / Native shell tests (pull_request) Successful in 22m28s
Project CI / Backend tests (pull_request) Successful in 27m38s
47c07f9d12
将旧单树测试夹具改为 trees 与 logicalSizes 参数

为拖拽和缩放入口补充所属 treeId 并更新树移除语义
k88936 added 6 commits 2026-09-23 10:12:20 +08:00
# Conflicts:
#	apps/ai-game-creator-shell/src/features/resource-canvas/resourceCanvasAssetGenerationQueue.ts
#	apps/ai-game-creator-shell/src/features/resource-canvas/useResourceCanvasGenerationPlaceholders.ts
#	apps/ai-game-creator-shell/tests/resourceCanvasGenerationFloatingPanel.test.tsx
#	docs/project-memory/shared-memory/decision-log.md
- decision-log 新增 2026-09-22 条目:右键拖拽平移的判定链、菜单改到抬起弹出、按下即拦截 contextmenu 的实测依据与代价
- 【UI编辑器】拖动变换提交边界补「视口平移不写 State、不进历史」以及右键平移与节点菜单按同一拖动阈值互斥的约定
- 同一文档的实现边界补拖动阈值落点 previewDragThreshold.ts 与右键裁决落点 previewRightPanGesture.ts
- 新增 previewDragThreshold.ts,导出 DRAG_THRESHOLD_SCREEN_PX 与屏幕坐标阈值判定 passedDragThresholdScreen
- useNodeTransformInteraction 删除本地阈值常量,改为复用该模块,左键拖动/缩放行为不变

验证:npx vitest run useNodeTransformInteraction.test.tsx previewWorkspaceZoom.test.tsx(18 passed)
- 新增 previewRightPanGesture.ts:按下起手、按共用阈值判定是否进入平移、按起点全量 delta 复用 moveViewportFromPan 算视口
- 抬起裁决统一收口到 resolvePreviewRightPanRelease:平移过就只回视口,未平移且在预览内才按节点菜单处理
- shouldInterceptRightContextMenu 记录"按钮 2 且处于右键按下序列"的拦截窗口,兼容按下触发与抬起后触发的两类平台时序
- 新增 tests/previewRightPanGesture.test.ts 覆盖阈值边界、越阈值后不回弹、全量 delta、预览外抬起与拦截判据

验证:npx vitest run previewRightPanGesture.test.ts(5 passed)
- PreviewWorkspace 右键按下记录起手并捕获指针,越过共用阈值后按起点全量 delta 平移视口,抬起时由 resolvePreviewRightPanRelease 裁决平移还是节点菜单
- 捕获阶段拦截按钮 2 的 contextmenu,拦截窗口保留到下一次指针按下之前,兼容"按下触发"与"抬起后触发"两类平台时序
- 右键抬起用 [data-node-id] 加树容器新增的 data-tree-id 命中节点,沿用"右键即选中该节点"语义;未平移但抬起在预览外时不弹菜单,空白网格右键静默
- 视口接线共享 isPanning,让空格、中键、右键三个平移绑定共用 grabbing 光标;onPointerCancel 拆成不进菜单的独立处理
- 新增 tests/previewRightPanDrag.test.tsx:右键拖拽只平移不弹菜单、阈值内仍弹菜单、空白右键不改选择、预览外抬起不弹、非右键 contextmenu 仍即时、中键平移回归、右键平移后左键拖动仍可用

验证:npx vitest run 定向 7 个文件 59 passed、apps/ai-game-creator-shell npx tsc --noEmit、改动文件 eslint、npm run check:encoding、git diff --check
固化键盘菜单键不被右键手势拦截的口径
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m58s
Project CI / Backend tests (pull_request) Failing after 12s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 3m57s
Project CI / Frontend tests (pull_request) Successful in 3m6s
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / AI game creator shell web tests (pull_request) Successful in 1m41s
Project CI / Native shell tests (pull_request) Successful in 6m13s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 9m32s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 10m50s
d5e06de33e
- 实测 Chromium 151 下键盘菜单键触发的是 button: -1,previewRightPanGesture 注释写明只认按钮 2 的原因
- previewRightPanGesture.test.ts 增加 button: -1 不拦截的判据用例
- previewRightPanDrag.test.tsx 增加键盘菜单键仍走原有节点菜单路径的集成用例
- decision-log 条目补上该实测结论与新增用例的验证口径

验证:npx vitest run previewRightPanDrag.test.tsx previewRightPanGesture.test.ts(13 passed)
k88936 added 4 commits 2026-09-23 16:33:48 +08:00
- 定义 `Rust` 权威层、`React` 会话层与视图层的职责边界
- 描述数据流、关键模块设计与核心命令
- 补充扩展指引与关联文档链接
- 更新 `docs/README.md` 引用路径
- 删除 ui_editor/commands/ui_design_suggestion.rs 与 main.rs 的 suggest_ui_design_semantic 命令注册

- 收敛 UIDesignImage 为 path/pixel_size/pixels_per_unit,删除 UIDesignImageRole 与 UIDesignImageMetadata

- 结构识别改为每张界面图各自一棵树,删除 recognition_root_image_ids 与 slave_image_ids 及 ROOT/SLAVE 上下文标注

- 多树合并删除 slave_to 祖先链优先级,输入树优先级恒置 0 并留 TODO

- 持久化校验删除 slave_to 引用与环校验,html 片段注释不再携带界面图 name/description

- 页面级工作流构造页面设计图时不再写入界面图元数据
- model.ts 收敛为“识别界面结构 / 自动切分素材”两步并删除界面角色标签表

- 删除 suggestion 异步操作、结果通知分支、uiDesignSuggestions 与其 ts-rs 生成类型

- InputSidebar、InspectorSidebar、PreviewWorkspace 的界面图显示名改用 path basename,Inspector 只保留尺寸与资源 ID

- 删除因步骤退役而不可达的 ImportOverview,ToolNavigation 改为两格,删除“清空界面归属”提示

- requisites 删除角色/归属前置校验与参考图分析结果校验,importAdapter 不再写入界面图元数据

- 测试夹具去掉界面图元数据,删除界面角色与归属用例,历史用例改用 sprite 名称断言
同步文档:界面图参考语义建议退役
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
26c6bdbbd5
- UI 编辑器代码地图更新 resource/commands 职责、关键命令列表、两步工作流与类型文件数量

- UI 工作流资源桥接文档改为普通桥接从 structure-recognition 开始

- UI 编辑器工作流完成通知弹窗文档收敛为两个动作并删除分析参考图文案

- UI 编辑会话模块边界删除 suggestion seam 描述

- App 实施计划追加 2026-09-23 退役条目覆盖旧 slave_to 口径

- decision-log 记录退役决策、合并优先级恒 0 与无迁移后果及验证结果
k88936 added 24 commits 2026-09-24 13:57:43 +08:00
- 删除 ui_editor/workflow.rs 与 agent/runtime_tools/ui_workflow.rs 两个工作流实现模块
- agent_native_tools 去掉 ui.workflow.run 的工具描述与 schema 分支
- prompts/runtime/texts/native-tools.json 删除 ui.workflow.run.description 文案
- runtime_tools/policy、tool_policy_snapshot、parallel_ledger、project_gates 移除该工具的白名单与门禁引用
- action_execution 去掉 ui.workflow.run 分发分支,action_audit 删除整块工作流审计与枚举项
- runtime_protocol 的 verification 与 acceptance_graph 去掉工作流校验项
- tool_plan_handoff/content_validation 去掉 ui-design pages 校验分支
- ui_editor/mod.rs 去掉 workflow 模块声明
- 删除 ui_editor/commands/merge.rs 与 binding.rs 两个实现及其 MergeDTO、BindingDTO
- commands/mod.rs 去掉两个模块声明、DTO 导出与 impl 再导出
- main.rs 去掉 merge_ui、bind_components 两个 Tauri 命令及注册项
- 删除 features/ui-editor/merge.ts 与 MergeDTO、BindingDTO、BindingChange 类型文件
- useUiEditorPage 去掉 mergeUi 操作、合并运行态、合并状态与投影字段
- isAiRunning 不再把合并运行态计入编辑器忙状态
- CONTEXT.md 新增 UI 设计文档、设计图、UI 工作流步骤、工作流检查点日志四个词条
- 新增 ADR 说明检查点采用追加式 JSONL 日志并记录两种被否方案
- docs/README.md 收录该 ADR
- 新增技术方案:三个工具契约、两步工作流、JSONL 检查点、Rust 与提示词目录模块布局、落地顺序
- 代码地图同步退役 merge/binding/workflow.rs、关键命令列表与类型文件数量
- docs/README.md 收录该方案
- 新增 prompts/runtime/texts/ui-design-doc.json,承载 from-images、run-workflow、into-js 三个工具的描述与参数文案
- manifest.json 的 textCatalogs 登记 uiDesignDoc 目录
- 新增 ui_editor/design_doc/creation.rs:由一至四张设计图新建文档,未登记路径顺带登记成 ui-design 图片资源,文档内设计图身份取图片 assetId
- persistence.rs 把单图初始化泛化为 initialize_ui_design_state_with_images_at,支持多张设计图并拒绝重复
- 删除 resource_bridge.rs 与 create_ui_design_resource、ensure_ui_design_resource_for_prototype 两个命令,取消「原型 → 已存在文档」的幂等查找
- main.rs 注册 create_ui_design_doc_from_images 并移除两个旧命令注册项
- 前端 uiDesignResourceBridge 改为调用新命令,project-development 去掉 ui-workflow.completed 的自动打开与阶段跳转分支
- 代码地图同步 design_doc 模块与关键命令列表,测试改为覆盖新入口的编号避让
- 检查点行补充 outdated 与起始 revision,明确 write-back / outdated 都是轮次结束行
- 追加前截断半行,避免崩溃留下的半行夹在日志中间
- 文档中途漂移时追加 outdated 并返回错误,由下一次调用显式开新一轮,不在同一次调用内自动重启
- 写回按「目标 State 与文档当前 State 相等」判幂等,并记录该判据成立的前提
- 切图资源失败不回滚,NeedReview 由 separation DTO 的 problematic_nodes 在编排阶段统一回写
- design_doc/checkpoint.rs:run / recognize / separate / write-back / outdated 五种行
- 路径推导 ui/.<文档名>-workflow.jsonl,与文档同级且不进 manifest
- 追加时先截断崩溃留下的半行再一次性写入并 sync,避免半行夹在日志中间
- 扫描只保留最后一轮,写回或 outdated 视为轮次结束;坏行失败关闭
- 载荷一律按 serde_json::Value 存回,模块不认识业务 DTO 与 State 类型
- 六个单测覆盖路径推导、轮次遮蔽、两种结束行、半行丢弃与坏行失败
- design_doc/steps/recognize.rs:apply_recognition 整树替换,并按 DTO 顺序逐棵重推横向偏移
- 镜像 deriveTreeOffset / treeSize 与 UI_TREE_PADDING=48,先落位的树把后面的树推到右边
- 设计图缺失或像素比非法时按前端同口径报「界面图 X 缺少合法尺寸」
- 三个单测覆盖左右排布、整树替换与缺失设计图失败
- SpriteAsset 新增 path 访问器与 from_registered_image,镜像前端 prepareSpriteAssetBatch 的空名称、无边框、像素比 1 口径
- 新增 design_doc/test_support.rs,集中 State、节点、素材的最小构造夹具
- recognize 单测改用共用夹具,删除本地重复的 image/state_with/root 构造
- Node 新增 find_mut,深度优先可变定位节点,镜像前端 findUiNodeLocation
- 新增 design_doc/steps/separate.rs:素材合并去重与资源校验、按 bound_nodes 回填 target_graphic、统一写 problematic_nodes 的 NeedReview
- 覆盖重复素材、缺失素材、节点缺失、非 Image 组件、已绑定其他素材与问题文案回退的单测
- 新增 design_doc/run_workflow.rs:recognize → separate → write-back 编排,按检查点行恢复,文档漂移追加 outdated 并报错
- 新增 design_doc/cut_images.rs:按切分路径登记图片并构造 SpriteAsset,按路径复用 manifest 条目、失败不回滚
- persistence 新增 load_ui_design_document_snapshot_at 并让 load_ui_design_state_at 复用它
- checkpoint 新增 checkpoint_timestamp 秒级时间戳
- 切分路径归一下沉到 steps/mod.rs,separate 步骤改用共享实现
- 技术方案同步 design_doc 模块布局与 into-js 复用 persistence 的说明
- 新增 agent/runtime_tools/ui_design_doc.rs:三个工具的参数解析、项目 ID 与 provider 身份注入、manifest 失效广播
- agent_native_tools 增加三个工具的描述与入参 schema,函数名归一同时处理 '.' 与 '-'
- Runtime 可执行工具目录、并行账本命令映射、design-foundation 自主白名单同步登记
- 新增工具描述可用性与入参校验单测
- 代码地图补 design_doc 各模块与三个 Agent 工具,并标注旧工具已退役
- project-overview 用三个新工具替换 ui.workflow.run 的旧口径
- App 实施计划追加 2026-09-23 节,记录工具拆分、检查点恢复与退役范围
- decision-log 新增本次决策、取舍与验证方式
- UI 工作流资源桥接旧方案标记 historical,从 docs/README 移入历史集合
- 退役 ensureUiDesignResourceForPrototype / findLinkedUiDesignResource 的 6 条旧用例已随实现删除而无对应导出,测试文件整体失败
- 改为覆盖 createUiDesignDocFromImages:空图片列表拒绝且不调用命令,正常调用透传项目身份与设计图引用
- run-workflow 干净跑完后调用 finalize_separation 清理 sidecar,有回填问题时保留给编辑器恢复,与前端切分链路一致
- 检查点恢复校验轮次归属文档,漂移与写回冲突说明带上基线 revision
- WorkflowLog 删除仅供测试的 path 访问器,测试直接用 workflow_log_path
- mod.rs 不再导出仅内部使用的 next_ui_design_path,消除未使用告警
- 技术方案同步 sidecar 收尾口径
- 内部 enforce_project_permission_policy 改用与并行账本一致的 asset.register,避免引入无法在项目策略里配置的私有命令 ID
- 明确本工具会把切分素材回填到 Image 组件、清组件状态、写 NeedReview 后写回并推进 revision
- 明确不做页面发现、多树合并与独立组件绑定,漂移时本轮作废需重新调用
把 steps/separate.rs 提升为 steps/separate/mod.rs,只保留纯 State 变换
把 design_doc/cut_images.rs 移到 steps/separate/cut_images.rs,与它服务的切分步骤同层
把 normalize_cut_image_path 从 steps/mod.rs 下沉到 steps/separate/mod.rs,紧邻两个使用点
run_workflow.rs 改从 steps::separate 统一导入切分入口与登记入口
同步两份 UI 编辑器技术方案的模块布局与代码地图
新增 steps/write_back.rs,承载保存 State、追加 write-back / outdated 行与漂移文案
把 rebuild_target_state 从 run_workflow.rs 移到 steps/mod.rs,作为已记录 DTO 的重放入口
run_workflow.rs 只保留输入输出类型、三步编排与检查点恢复判定
把 DRIFT_REASON 与两条漂移文案收敛到 write_back 模块,避免编排层和写回层各写一套
同步两份 UI 编辑器技术方案的模块布局与代码地图
- 重命名 src-tauri/src/ui_editor/design_doc/{checkpoint,creation,mod,run_workflow,test_support}.rs 与 steps/** 到 ui_editor/agent_tools/
- 更新 main.rs、ui_editor/mod.rs、agent/runtime_tools/ui_design_doc.rs 中的模块路径引用
- 更新 steps/recognize.rs 与 steps/separate/mod.rs 内部对 agent_tools 夹具的引用
- 更新 tests/project.rs 注释中的 creation.rs 与 next_ui_design_path 模块路径
- 更新 agent_tools/test_support.rs 模块注释为 agent_tools 单测共用夹具
- 更新技术方案《UI编辑器代码地图与模块职责》《UI编辑器Agent工具化重写》的模块树与落地顺序路径
- 更新 shared-memory decision-log 中该次重写的测试过滤器为 agent_tools
合并 origin/master 到 feat/ui-editor-v3
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m27s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m5s
Project CI / Native shell tests (pull_request) Failing after 1m47s
Project CI / Backend tests (pull_request) Successful in 3m53s
Project CI / Frontend tests (pull_request) Successful in 1m38s
Project CI / AI game creator shell web tests (pull_request) Failing after 38s
Project CI / Repository checks (pull_request) Failing after 1m33s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 9m0s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 9m2s
2873bed732
- 合入 master 179 个提交(后台管理页、游戏发行入口、AGC 运行页签、编译 warning 清理等)
- policy.rs 采用 master 版本:删除无调用方的 autonomous_design_foundation_command_is_allowed 重复名单,design-foundation 权限以 tool_policy_snapshot.rs 为准
- native-tools.json 保留双方结果:master 的描述文本 + 分支删除已退役的 ui.workflow.run.description
- useUiEditorPage.ts 保留分支的 save / saveAndGenerateCode 状态返回契约,并接上 master 的 beginUiSaveAnalytics 与 saveSource: 'auto' 埋点
- 验证:cargo check --bin genarrative-ai-game-creator-shell、npm run check:rustfmt、tsc --noEmit、vitest tests/uiEditorPage.test.ts + tests/clientAnalytics.test.tsx(47 passed)
k88936 added 1 commit 2026-09-24 14:42:24 +08:00
修复合并后 CI 失败:退役命令的残留清单与用例
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m21s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m57s
Project CI / Backend tests (pull_request) Successful in 4m0s
Project CI / Frontend tests (pull_request) Successful in 1m53s
Project CI / Native shell tests (pull_request) Successful in 5m51s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 9m13s
Project CI / Repository checks (pull_request) Successful in 2m1s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 9m20s
Project CI / AI game creator shell web tests (pull_request) Failing after 2m40s
dc5a5a4a62
- scripts/check-config.mjs 的 native-only 白名单删除已退役的 bind_components 与 create_ui_design_resource,两端原生能力检查重新自洽
- appSurface 的 UI 原型入口用例改断言 create_ui_design_doc_from_images,并按新契约补齐 relativePath / imageIds 返回形状
- 验证:npm run typecheck(含 skill-pack 与 check-config)、npx vitest run tests/appSurface.test.ts(211 passed / 9 skipped)
k88936 changed title from WIP: Feat/ui editor v3 to WIP: ui editor v3 页面优化 2026-09-24 14:43:20 +08:00
k88936 changed title from WIP: ui editor v3 页面优化 to WIP: ui editor 页面优化 2026-09-24 14:43:30 +08:00
k88936 marked the pull request as ready for review 2026-09-24 16:08:55 +08:00
Author
Member
    1. [bug·high|已修 9694faa62] 现状:Node.offset 是普通 serde 字段。问题:字段级缺省会漏;但评审说“旧文档因此读不了”只对了一半——真正拒绝整份旧文档的是 parse_ui_design_document 的 canonical 往返比对(缺 offset 会导致 值 != canonical),字段级 #[serde(default)] 只救缺字段的子结构(如检查点里的 State 快照)。建议:已加 #[serde(default)];若要让缺 offset 的整份旧文档可读,需放开 canonical 检查或写迁移,属 breaking,留给你。
    1. [bug·medium|已修 ec9a4fcba] 现状:validate_node 只校验 Transform 的 anchor/offset,node.offset 完全不校验。问题:NaN/Infinity 的树级偏移能存盘,而预览按 offset.min 定位,会把整棵树渲染坏。建议:加有限数值校验(已做);min <= max 我没加,因为 offset.max 目前没有任何渲染或后端消费者(前端只读 offset.min),硬性排序校验会引入无依据的拒绝。
    1. [maintainability·low|已修 d082c5ab1] 现状:required_tool_argumentspub(crate) 组合封装,recognition.rs 直接调两个底层函数。问题:死代码且会触发 dead_code 告警。建议:删除(已做)。
    1. [bug·high|已修 1c7d90a95] 现状:acceptance_evidence_tool_may_advance_project_revision 在退役 ui.workflow.run 时只删未补,而 ui-design-doc.run-workflow 仍是验收证据工具且会推进项目 revision。问题:validate_acceptance_evidence_revision 会以「evidence project revision 不匹配」拒掉真实证据。建 议:把 ui-design-doc.run-workflow 加入该白名单,并补契约测试(已做)。
    1. [security·medium|已修 c844f857e] 现状:删 ui.workflow.runpages[].applicationPath 分支时,没给 ui-design-doc.from-imagesimages[].path 补校验。问题:交接阶段的绝对路径逃逸早筛丢失,只剩后置的 resolve_local_project_path。建议:按 images/{index}/pathcollect_native_string_field 收集(已做)。补充:ledger.rs 的 native 函数映射与 normalize_runtime_tool_input_paths 同样没有 ui-design-doc.*,但那是 native 函数名维度,不是本次回归。
    1. [bug·high|已修 940d7b579] 现状:用 RunUiDesignDocWorkflowOutput.revision(文档级)跟 revision_before(项目级 sidecar)比较。问题:两个计数器不同源,项目 revision 一旦超过文档 revision 条件恒假,emit_game_creator_manifest_invalidated 永不触发,前端 manifest 一直过期。建议:比较 workflow 前后读到的项目 revision(已做)。
    1. [bug·high|未修·留给你] 现状:project_gates.rsis_agent_runtime_project_mutation_observationagent_runtime_observation_advances_project_revision、验证资格分支只认旧的 ui.workflow.run,新工具 ui-design-doc.from-images|run-workflow 会推进项目 revision 却不被当成 mutation。问题:任务可能 不要求验证就判完成、pending revision 少算导致 pending_project_revision_drift 误报、tool_policy_snapshot 与门禁口径不一致。建议:按工具名 + status == "ok" 纳入,或在 observation detail 里带 revisionAdvanceCount 再消费;这会改完成/验证判定语义,需要你定口径。
    1. [performance·medium|未修·留给你] 现状:observe_agent_runtime_ui_design_doc_from_images / ..._into_js 是同步函数,直接在 async 执行器线程上做 image::open 解码、manifest/文件 IO 与 SHA-256 + 写文件。问题:阻塞 executor,而仓库别处统一用 spawn_blocking。建议:改成 async + spawn_blocking 包住阻塞核心;属签名与调用链调整。
    1. [bug·medium|未修·留给你] 现状:ui.workflow.run 的 safe-detail 脱敏分支删除后,三个 ui-design-doc.* 都没补,agent_runtime_action_receipt_safe_detail_with_owner 落到 fallback 返回 Noneagent_runtime_public_action_input_summary 同理。问题:作为验收证据的工具,其 receipt 里 assetId/relativePath/backfillErrors 未脱敏。建议:照旧分支补 assetId/relativePath 校验、长度与控制字符处理;留给你是因为要定脱敏字段口径。
    1. [bug·medium|未修·属产品行为] 现状:点「UI 编辑器」每次都新建文档,无幂等或在途保护,create_ui_design_doc_from_images 文档注释明确“每次调用都新建”。问题:双击或关掉重开会重复登记文档与 manifest 条目。建议:加在途 ref 或先查已关联文档。历史:648ead215 有意取消了「原型 → 已有文档」的幂等查找,所 以可能是设计选择,需要你确认。
    1. [bug·critical|评审判断有误,但同处有真问题·未修] 现状:file.take(..) 是方法调用自动重借用,不会 move,file.set_len/seek 照常可用(我用最小复现验证过),所以“无法编译”的 critical 结论不成立。真问题:该文件以 append 模式打开,set_len 只改大小、不移动写指针,半行截断路径下保留的是旧文件头而不是刚读出的尾部,会截错位置。建议:改用 OpenOptions::write(true).truncate(false) + 显式 seek 后再截断;属写盘语义 breaking,留给你。
    1. [bug·medium|已修 ac870fd41] 现状:文档登记失败时只删文档文件,prepare_design_images 已登记的图片留在 manifest 里无人引用。问题:孤儿 manifest 条目。建议:失败分支调用 drop_manifest_assets(root, &[], &registered_image_ids),并保留 reconciliation-required 文案(已做,含用例)。
    1. [maintainability·low|未修·留给你] 现状:already_written_back 恢复路径里 resume_progress → rebuild_target_state 已跑过 register_cut_image_sprites/apply_separation,主流程又跑一遍。问题:重复 manifest IO,且失败描述会重复追加进 backfill_errors。建议:该分支跳过这些步骤;会改变副作用与错误 列表,属行为变更。
    1. [security·medium|已修 588768bff] 现状(评审判断错):rejected 不只用于输入解析失败,三个观察都把“项目上下文缺失”的错误传进来,而这些错误嵌了宿主绝对路径。问题:摘要原样交给 provider,与注释里“无需脱敏”的说法矛盾。建议:rejected(root, tool, …) 统一走 redact_agent_runtime_project_paths(已做)。
    1. [maintainability·low|已修 0e15d7604] 现状:texts/ui-design-doc.json 里写好的参数描述没人引用,from-imagesimagesdescriptionone_string_input_schema 只产出裸 type: string。问题:模型看不到这些文案,目录条目等于死配置。建议:用 one_string_input_schema_with_description / prompt_text! 把描述接进 schema(已做)。
    1. [bug·medium|未修·留给你] 现状:treeSize 直接 throw,且不校验 pixel_size;它由 deriveTreeOffset → createTree → synchronizeDesignImageTreesreplaceState 里对持久化 State 直接调用。问题:脏文档在加载期抛异常,绕过 {ok:false, reason:'invalid'} 和不变量文案。建议:返回 null 交给调用方 ;注意评审给的补丁只改了函数体,null 必须向上传播到 deriveTreeOffset/createTree,不是一行改动。
    1. [maintainability·low|未修·重构项] 现状:pixel_size / pixels_per_unit 加有限性校验在四处重复(nodeTransformGeometry.tsstateTransition.tsuseUiEditorState.tsstateInvariants.ts),且 treeSize 已经漂移。建议:抽一个共享 helper,和 16 一起做收益最大。
    1. [maintainability·low|已修 0f9e2f173] 现状:UiDesignDocImageReference 两个字段都可选,{} 或都给要等 Rust 侧才报错。问题:契约没进类型系统。建议:改成 {assetId: string; path?: never} | {assetId?: never; path: string}(已做,tsc 通过)。
    1. [maintainability·medium|未修·需你确认] 现状:LayoutEditor 的 JSX 被注释掉,但函数体(约 270 行)仍在文件里,靠 eslint-disable-next-line 压未用告警,onLayoutChange 仍挂在 props 与调用处。问题:大块死代码 + 无消费者 prop。建议:删除注释 JSX、LayoutEditor 函数与 onLayoutChange。注意评审说 SizeFlagOptions/InspectorSelect 失去唯一调用点是错的,两者仍在活跃使用。我没动是因为“被注释”看起来像还打算恢复。
    1. [bug·medium|未修·留给你] 现状:prepare_design_image 先做 manifest 副作用 register_local_asset_at,再校验格式/尺寸与查重;批次中后面某张失败时,前面已登记的图片留在 manifest 里,rollback_created_document 跑在更晚阶段救不回来。建议:先全量校验再登记,或把已登记 id 提到跨函数状态统一回收;属跨 函数状态改造。
    1. [bug·low|已修 a871684bd] 现状:round.at 是秒级时间戳,却被写进“第 N 轮”的漂移文案(评审正文和代码块自相矛盾)。建议:改文案说明它是检查点时间戳,不改 u64 字段类型(已做)。
    1. [bug·high|已修 064c26d7c] 现状:右键 pointerdown 把指针捕获在视口上,pointerup 被重定向到捕获元素,openNodeContextMenuAt 拿到的 event.target 是视口,resolveRightClickMenuTarget 找不到 [data-node-id]。问题:节点右键菜单永不出现。建议:pointerdown 时记下命中的 event.target(新增 rightPanTargetRef),抬起时用它解析(已做,含反向验证)。
    1. [bug·medium|已修 134046f80] 现状:onPointerCancel={handleTreePointerUp} 把浏览器发起的取消当成成功释放。问题:会提交非预期的树偏移。建议:新增 handleTreePointerCancel,清 treeDragRef 并释放捕获,不提交偏移(已做)。
    1. [bug·medium|已修 d7f3790fc] 现状:节点拖动守卫只判 !treeId,不判 !tree || !logicalSize,与缩放路径不一致。问题:树在拖动中被删除会留下悬空捕获手势。建议:补齐与 resize 相同的守卫(已做)。
    1. [bug·low|已修 12e8287f9] 现状:step * viewportScale 溢出成 Infinity 时,while (screenSpacing >= MAX)Infinity / 2 仍是 Infinity。问题:死循环冻住画布。建议:进入循环前挡掉非有限 screenSpacing(已做)。
    1. [bug·low|已修 76dfd74de] 现状:onWindowBlur 清了右键平移状态,却漏了 treeDragRef。问题:失焦时若没有 pointercancel,残留引用会被后续 move/up 复用并提交偏移。建议:blur 里一并清 treeDragRef 与预览偏移(已做,含反向验证)。
    1. [maintainability·medium|已修 95fec72ef] 现状:会话投影里仍暴露独立 generateCode,全仓无调用方,失败静默返回 null。建议:删除该包装(saveAndGenerateCodestateStore.generateCode 保留)。
    1. [style·low|已修 c8852ac2a] 现状:overview 在每个分支只赋值一次。建议:改成 const + 三元表达不可变意图(已做)。
    1. [bug·medium|与 4 同处,已修 1c7d90a95] 现状:tool_policy_snapshotui-design-doc.run-workflow 列为验收证据,但 acceptance_evidence_tool_may_advance_project_revision 不含它。问题:证据工具与 revision 推进识别不一致。建议:加入该白名单,两处口径统一(已做)。
    1. [bug·high|已修 ef4601c55] 现状:节点增删改已按 treeForSelectedNode 找树,但 deleteNode 仍默认 treeId = activeImageId,而 selectNode 可选中任意渲染树里的节点。问题:Inspector 删除按钮与 Delete/Backspace 会去删激活图那棵树,删别棵树的节点静默失败。建议:deleteNode 默认落到选中节点所在树; 键盘删除改调 deleteNode(selectedNodeId)(顺带去掉 activeImageId 入参),PreviewWorkspace 显式传 contextMenu.treeId 语义不变(已做,含页面级用例)。
    1. [bug·low|已修 e2e924341] 现状:set-tree-offset 只校验每个元素有限,[] 空真通过、[5] 也能过。问题:command.min[1]undefinedoffset.max 变成 NaN。建议:加 command.min.length !== 2 判定(已做)。
    1. [maintainability·low|已修 9e49db419] 现状:不变量 seam 直接取 image.path.trim()image.pixel_size.every(...)。问题:旧/残缺文档抛 TypeError,被 save 的 catch 吞成通用的「保存失败,请稍后重试。」。建议:取字段前先判类型(typeof image.path === 'string'Array.isArray(image.pixel_size)) (已做)。
- 1. **[bug·high|已修 9694faa62]** 现状:`Node.offset` 是普通 serde 字段。问题:字段级缺省会漏;但评审说“旧文档因此读不了”只对了一半——真正拒绝整份旧文档的是 `parse_ui_design_document` 的 canonical 往返比对(缺 `offset` 会导致 `值 != canonical`),字段级 `#[serde(default)]` 只救缺字段的子结构(如检查点里的 State 快照)。建议:已加 `#[serde(default)]`;若要让缺 `offset` 的整份旧文档可读,需放开 canonical 检查或写迁移,属 breaking,留给你。 - 2. **[bug·medium|已修 ec9a4fcba]** 现状:`validate_node` 只校验 Transform 的 anchor/offset,`node.offset` 完全不校验。问题:NaN/Infinity 的树级偏移能存盘,而预览按 `offset.min` 定位,会把整棵树渲染坏。建议:加有限数值校验(已做);`min <= max` 我没加,因为 `offset.max` 目前没有任何渲染或后端消费者(前端只读 `offset.min`),硬性排序校验会引入无依据的拒绝。 - 3. **[maintainability·low|已修 d082c5ab1]** 现状:`required_tool_arguments` 是 `pub(crate)` 组合封装,`recognition.rs` 直接调两个底层函数。问题:死代码且会触发 `dead_code` 告警。建议:删除(已做)。 - 4. **[bug·high|已修 1c7d90a95]** 现状:`acceptance_evidence_tool_may_advance_project_revision` 在退役 `ui.workflow.run` 时只删未补,而 `ui-design-doc.run-workflow` 仍是验收证据工具且会推进项目 revision。问题:`validate_acceptance_evidence_revision` 会以「evidence project revision 不匹配」拒掉真实证据。建 议:把 `ui-design-doc.run-workflow` 加入该白名单,并补契约测试(已做)。 - 5. **[security·medium|已修 c844f857e]** 现状:删 `ui.workflow.run` 的 `pages[].applicationPath` 分支时,没给 `ui-design-doc.from-images` 的 `images[].path` 补校验。问题:交接阶段的绝对路径逃逸早筛丢失,只剩后置的 `resolve_local_project_path`。建议:按 `images/{index}/path` 用 `collect_native_string_field` 收集(已做)。补充:`ledger.rs` 的 native 函数映射与 `normalize_runtime_tool_input_paths` 同样没有 `ui-design-doc.*`,但那是 native 函数名维度,不是本次回归。 - 6. **[bug·high|已修 940d7b579]** 现状:用 `RunUiDesignDocWorkflowOutput.revision`(文档级)跟 `revision_before`(项目级 sidecar)比较。问题:两个计数器不同源,项目 revision 一旦超过文档 revision 条件恒假,`emit_game_creator_manifest_invalidated` 永不触发,前端 manifest 一直过期。建议:比较 workflow 前后读到的项目 revision(已做)。 - 7. **[bug·high|未修·留给你]** 现状:`project_gates.rs` 的 `is_agent_runtime_project_mutation_observation`、`agent_runtime_observation_advances_project_revision`、验证资格分支只认旧的 `ui.workflow.run`,新工具 `ui-design-doc.from-images|run-workflow` 会推进项目 revision 却不被当成 mutation。问题:任务可能 不要求验证就判完成、pending revision 少算导致 `pending_project_revision_drift` 误报、`tool_policy_snapshot` 与门禁口径不一致。建议:按工具名 + `status == "ok"` 纳入,或在 observation detail 里带 `revisionAdvanceCount` 再消费;这会改完成/验证判定语义,需要你定口径。 - 8. **[performance·medium|未修·留给你]** 现状:`observe_agent_runtime_ui_design_doc_from_images` / `..._into_js` 是同步函数,直接在 async 执行器线程上做 `image::open` 解码、manifest/文件 IO 与 SHA-256 + 写文件。问题:阻塞 executor,而仓库别处统一用 `spawn_blocking`。建议:改成 async + `spawn_blocking` 包住阻塞核心;属签名与调用链调整。 - 9. **[bug·medium|未修·留给你]** 现状:`ui.workflow.run` 的 safe-detail 脱敏分支删除后,三个 `ui-design-doc.*` 都没补,`agent_runtime_action_receipt_safe_detail_with_owner` 落到 fallback 返回 `None`;`agent_runtime_public_action_input_summary` 同理。问题:作为验收证据的工具,其 receipt 里 `assetId`/`relativePath`/`backfillErrors` 未脱敏。建议:照旧分支补 `assetId`/`relativePath` 校验、长度与控制字符处理;留给你是因为要定脱敏字段口径。 - 10. **[bug·medium|未修·属产品行为]** 现状:点「UI 编辑器」每次都新建文档,无幂等或在途保护,`create_ui_design_doc_from_images` 文档注释明确“每次调用都新建”。问题:双击或关掉重开会重复登记文档与 manifest 条目。建议:加在途 ref 或先查已关联文档。历史:`648ead215` 有意取消了「原型 → 已有文档」的幂等查找,所 以可能是设计选择,需要你确认。 - 11. **[bug·critical|评审判断有误,但同处有真问题·未修]** 现状:`file.take(..)` 是方法调用自动重借用,不会 move,`file.set_len/seek` 照常可用(我用最小复现验证过),所以“无法编译”的 critical 结论不成立。真问题:该文件以 append 模式打开,`set_len` 只改大小、不移动写指针,半行截断路径下保留的是**旧文件头**而不是刚读出的尾部,会截错位置。建议:改用 `OpenOptions::write(true).truncate(false)` + 显式 `seek` 后再截断;属写盘语义 breaking,留给你。 - 12. **[bug·medium|已修 ac870fd41]** 现状:文档登记失败时只删文档文件,`prepare_design_images` 已登记的图片留在 manifest 里无人引用。问题:孤儿 manifest 条目。建议:失败分支调用 `drop_manifest_assets(root, &[], &registered_image_ids)`,并保留 reconciliation-required 文案(已做,含用例)。 - 13. **[maintainability·low|未修·留给你]** 现状:`already_written_back` 恢复路径里 `resume_progress → rebuild_target_state` 已跑过 `register_cut_image_sprites`/`apply_separation`,主流程又跑一遍。问题:重复 manifest IO,且失败描述会重复追加进 `backfill_errors`。建议:该分支跳过这些步骤;会改变副作用与错误 列表,属行为变更。 - 14. **[security·medium|已修 588768bff]** 现状(评审判断错):`rejected` 不只用于输入解析失败,三个观察都把“项目上下文缺失”的错误传进来,而这些错误嵌了宿主绝对路径。问题:摘要原样交给 provider,与注释里“无需脱敏”的说法矛盾。建议:`rejected(root, tool, …)` 统一走 `redact_agent_runtime_project_paths`(已做)。 - 15. **[maintainability·low|已修 0e15d7604]** 现状:`texts/ui-design-doc.json` 里写好的参数描述没人引用,`from-images` 的 `images` 没 `description`,`one_string_input_schema` 只产出裸 `type: string`。问题:模型看不到这些文案,目录条目等于死配置。建议:用 `one_string_input_schema_with_description` / `prompt_text!` 把描述接进 schema(已做)。 - 16. **[bug·medium|未修·留给你]** 现状:`treeSize` 直接 `throw`,且不校验 `pixel_size`;它由 `deriveTreeOffset → createTree → synchronizeDesignImageTrees` 在 `replaceState` 里对持久化 State 直接调用。问题:脏文档在加载期抛异常,绕过 `{ok:false, reason:'invalid'}` 和不变量文案。建议:返回 `null` 交给调用方 ;注意评审给的补丁只改了函数体,`null` 必须向上传播到 `deriveTreeOffset`/`createTree`,不是一行改动。 - 17. **[maintainability·low|未修·重构项]** 现状:`pixel_size / pixels_per_unit` 加有限性校验在四处重复(`nodeTransformGeometry.ts`、`stateTransition.ts`、`useUiEditorState.ts`、`stateInvariants.ts`),且 `treeSize` 已经漂移。建议:抽一个共享 helper,和 16 一起做收益最大。 - 18. **[maintainability·low|已修 0f9e2f173]** 现状:`UiDesignDocImageReference` 两个字段都可选,`{}` 或都给要等 Rust 侧才报错。问题:契约没进类型系统。建议:改成 `{assetId: string; path?: never} | {assetId?: never; path: string}`(已做,`tsc` 通过)。 - 19. **[maintainability·medium|未修·需你确认]** 现状:`LayoutEditor` 的 JSX 被注释掉,但函数体(约 270 行)仍在文件里,靠 `eslint-disable-next-line` 压未用告警,`onLayoutChange` 仍挂在 props 与调用处。问题:大块死代码 + 无消费者 prop。建议:删除注释 JSX、`LayoutEditor` 函数与 `onLayoutChange`。注意评审说 `SizeFlagOptions`/`InspectorSelect` 失去唯一调用点是**错的**,两者仍在活跃使用。我没动是因为“被注释”看起来像还打算恢复。 - 20. **[bug·medium|未修·留给你]** 现状:`prepare_design_image` 先做 manifest 副作用 `register_local_asset_at`,再校验格式/尺寸与查重;批次中后面某张失败时,前面已登记的图片留在 manifest 里,`rollback_created_document` 跑在更晚阶段救不回来。建议:先全量校验再登记,或把已登记 id 提到跨函数状态统一回收;属跨 函数状态改造。 - 21. **[bug·low|已修 a871684bd]** 现状:`round.at` 是秒级时间戳,却被写进“第 N 轮”的漂移文案(评审正文和代码块自相矛盾)。建议:改文案说明它是检查点时间戳,不改 `u64` 字段类型(已做)。 - 22. **[bug·high|已修 064c26d7c]** 现状:右键 pointerdown 把指针捕获在视口上,pointerup 被重定向到捕获元素,`openNodeContextMenuAt` 拿到的 `event.target` 是视口,`resolveRightClickMenuTarget` 找不到 `[data-node-id]`。问题:节点右键菜单永不出现。建议:pointerdown 时记下命中的 `event.target`(新增 `rightPanTargetRef`),抬起时用它解析(已做,含反向验证)。 - 23. **[bug·medium|已修 134046f80]** 现状:`onPointerCancel={handleTreePointerUp}` 把浏览器发起的取消当成成功释放。问题:会提交非预期的树偏移。建议:新增 `handleTreePointerCancel`,清 `treeDragRef` 并释放捕获,不提交偏移(已做)。 - 24. **[bug·medium|已修 d7f3790fc]** 现状:节点拖动守卫只判 `!treeId`,不判 `!tree || !logicalSize`,与缩放路径不一致。问题:树在拖动中被删除会留下悬空捕获手势。建议:补齐与 resize 相同的守卫(已做)。 - 25. **[bug·low|已修 12e8287f9]** 现状:`step * viewportScale` 溢出成 `Infinity` 时,`while (screenSpacing >= MAX)` 里 `Infinity / 2` 仍是 `Infinity`。问题:死循环冻住画布。建议:进入循环前挡掉非有限 `screenSpacing`(已做)。 - 26. **[bug·low|已修 76dfd74de]** 现状:`onWindowBlur` 清了右键平移状态,却漏了 `treeDragRef`。问题:失焦时若没有 `pointercancel`,残留引用会被后续 move/up 复用并提交偏移。建议:blur 里一并清 `treeDragRef` 与预览偏移(已做,含反向验证)。 - 27. **[maintainability·medium|已修 95fec72ef]** 现状:会话投影里仍暴露独立 `generateCode`,全仓无调用方,失败静默返回 `null`。建议:删除该包装(`saveAndGenerateCode` 与 `stateStore.generateCode` 保留)。 - 28. **[style·low|已修 c8852ac2a]** 现状:`overview` 在每个分支只赋值一次。建议:改成 `const` + 三元表达不可变意图(已做)。 - 29. **[bug·medium|与 4 同处,已修 1c7d90a95]** 现状:`tool_policy_snapshot` 把 `ui-design-doc.run-workflow` 列为验收证据,但 `acceptance_evidence_tool_may_advance_project_revision` 不含它。问题:证据工具与 revision 推进识别不一致。建议:加入该白名单,两处口径统一(已做)。 - 30. **[bug·high|已修 ef4601c55]** 现状:节点增删改已按 `treeForSelectedNode` 找树,但 `deleteNode` 仍默认 `treeId = activeImageId`,而 `selectNode` 可选中任意渲染树里的节点。问题:Inspector 删除按钮与 Delete/Backspace 会去删激活图那棵树,删别棵树的节点静默失败。建议:`deleteNode` 默认落到选中节点所在树; 键盘删除改调 `deleteNode(selectedNodeId)`(顺带去掉 `activeImageId` 入参),`PreviewWorkspace` 显式传 `contextMenu.treeId` 语义不变(已做,含页面级用例)。 - 31. **[bug·low|已修 e2e924341]** 现状:`set-tree-offset` 只校验每个元素有限,`[]` 空真通过、`[5]` 也能过。问题:`command.min[1]` 是 `undefined`,`offset.max` 变成 NaN。建议:加 `command.min.length !== 2` 判定(已做)。 - 32. **[maintainability·low|已修 9e49db419]** 现状:不变量 seam 直接取 `image.path.trim()` 与 `image.pixel_size.every(...)`。问题:旧/残缺文档抛 `TypeError`,被 save 的 catch 吞成通用的「保存失败,请稍后重试。」。建议:取字段前先判类型(`typeof image.path === 'string'`、`Array.isArray(image.pixel_size)`) (已做)。
k88936 added 28 commits 2026-09-24 19:16:21 +08:00
ui_editor/layout/node.rs 给 Node.offset 加 #[serde(default)],历史设计文档缺该字段时按零偏移解析
ui_editor/persistence.rs 补 legacy_nodes_without_offset_field_fall_back_to_zero_offset 锁定该回退口径
ui_editor/commands/utils.rs 去掉只做「找工具调用 + 解析参数」拼接的封装,识别与切分调用点都自带日志与错误映射,没有消费方
tool_plan_handoff/content_validation.rs 为 from-images 的 images[].path 逐项做绝对路径与逃逸判据,恢复退役工作流工具留出的早检位
agent/runtime_protocol/acceptance_graph.rs 在 acceptance_evidence_tool_may_advance_project_revision 里补回被退役工具腾出的位置,写回文档会让 before 与 after 不同,不再被误判为 revision 不匹配
同一文件补 ui_design_doc_workflow_evidence_may_advance_project_revision 用例,锁住「证据工具」与「可推进 revision」两处识别一致
agent/runtime_tools/ui_design_doc.rs 改为在工作流结束后重读项目 revision,与开始前的项目 revision 比较;原先比较的 result.revision 是随文档重置的文档 revision,项目 revision 一超过它就永远判不出清单变化,前端会一直看到旧清单
agent/runtime_tools/ui_design_doc.rs 让 rejected 接收项目根并复用 redact_agent_runtime_project_paths:项目上下文缺失时的报错会带上宿主路径,原先把 rejected 当成「只含模型参数」直接透出,摘要会泄露绝对路径
ui_editor/agent_tools/creation.rs 登记文档资源失败时先摘掉 prepare_design_images 登记进来的图片条目,避免 manifest 留下没有文档引用的孤儿设计图
把「按 id 摘条目」抽成 drop_manifest_assets,rollback_created_document 复用同一实现
agent_native_tools.rs 给 from-images 的 images 属性挂上 texts/ui-design-doc.json 里已写好的说明,run-workflow 与 into-js 改用带 description 的单字符串 schema 生成器 one_string_input_schema_with_description,原先这三条文案没有任何引用点,模型看不到
ui_editor/agent_tools/steps/write_back.rs 的 checkpoint_drift_message 原先输出「检查点第 1759... 轮基线 revision」,round.at 其实是秒级 Unix 时间戳;改为先给基线 revision,再标注时间戳含义
src/features/ui-editor/stateTransition.ts 的 set-tree-offset 分支增加 min.length !== 2 判据:空数组会让 every 空真通过,缺坐标时 max 会算出 NaN 污染渲染消费的偏移
tests/uiEditorState.test.ts 补「[12] 与 [] 都判 invalid」用例
src/features/ui-editor/stateInvariants.ts 在取 path.trim 与 pixel_size.every 前先判 string / Array.isArray,残缺持久化文档此前会在 firstUiDesignInvariantMessage 里抛 TypeError,被保存流程吞成通用失败文案
tests/uiEditorState.test.ts 补三组残缺界面图都回落到 invalid-image 的用例
previewGrid.ts 的 resolvePreviewGridStep 在 screenSpacing 溢出成 Infinity 时直接回基础步长:原先第二个 while 里 Infinity/2 仍是 Infinity,画布会卡死
previewWorkspaceZoom.test.tsx 补 Number.MAX_VALUE 缩放的回退用例
src/view/ui-editor/useUiEditorPage.ts 的 deleteNode 默认 treeId 改为 treeForSelectedNode?.src_ui_design ?? activeImageId:选中节点可以来自非激活界面图,Inspector 删除按钮不给 treeId 时会静默删不掉
src/view/ui-editor/uiEditorKeyboardShortcuts.ts 与 view/ui-editor/index.tsx 去掉键盘删除强制传 activeImageId 的接线,treeId 改为可选,同时删掉已无消费者的 activeImageId 入参
tests/uiEditorPage.test.ts 补「非激活树里的节点默认也能删除」用例,uiEditorKeyboardShortcuts.test.ts 断言改为只传节点 id
PreviewWorkspace.tsx 在右键按下时记住命中元素,抬起时改成按它解析节点与树:指针被视口捕获后 pointerup 的 target 是捕获元素,原先按抬起目标找不到 [data-node-id],节点菜单永远打不开
指针取消时同步清掉记录的目标
tests/previewRightPanDrag.test.tsx 补「抬起被重定向到捕获元素仍弹菜单」用例
PreviewWorkspace.tsx 拆出 handleTreePointerCancel:pointercancel 只清拖拽状态与指针捕获,不再按抬手坐标算最终偏移,避免浏览器取消手势时把意外偏移写进文档
tests/previewRightPanDrag.test.tsx 补「抬起提交、取消不提交」用例,并给画布夹具补上 setTreeOffset 桩
PreviewWorkspace.tsx 的 onWindowBlur 一并清掉 treeDragRef 与树拖拽预览偏移:失焦时浏览器不一定补 pointercancel,陈旧手势会被后续 pointerup 复用并把意外偏移写进文档
tests/previewRightPanDrag.test.tsx 补失焦后抬起不提交偏移的用例
useNodeTransformInteraction.ts 的 onNodePointerDown 补上 !tree || !logicalSize 守卫,与 onNodeResizePointerDown 一致:命中不到树或逻辑尺寸时不再启动手势并占用指针捕获
src/view/ui-editor/useUiEditorPage.ts 移除 save.generateCode 及其实现:全仓只有 saveAndGenerateCode 与 stateStore.generateCode 有消费者,这个包装失败时静默返回 null,留着容易让后续调用方拿到没有原因的 null
src/view/ui-editor/index.tsx 用三元表达式声明 overview,去掉 let + if/else 两处赋值,表达不可变意图
src/features/ui-editor/uiDesignResourceBridge.ts 的 UiDesignDocImageReference 改为判别联合:原先两个字段都可选,`{}` 或两个都给要等到 Rust 运行时才被判错
tests/workflowCompletionNotice.test.ts 改为遍历 UI_EDITOR_STEPS 逐一比对 workflowStepLabel(step.id) 与 step.label,断言里写死的 reference-analysis 步骤已在「前端移除分析参考图步骤与界面图元编辑」中退役,导致用例在 HEAD 上必然失败
src-tauri/src/ui_editor/persistence.rs 的 validate_node 现在校验 node.offset.min/max 必须是有限数值,与相邻的 Transform/custom_minimum_size 校验一致;此前只有 Transform 的 anchor/offset 被校验,NaN 或 Infinity 的树级偏移可以存盘,预览按 offset.min 定位时整棵树的渲染会一起失效

同文件新增 rejects_non_finite_node_offset,覆盖「offset 全有限可保存、min 变成 Infinity 后校验失败」
src/features/ui-editor/types/Node.ts 补回末位逗号:该目录在 .prettierignore 内,文件内容就是 ts-rs 直出,46f859237 手工补 offset 字段时漏掉这个逗号,导致每次 cargo test 跑导出后这个文件都会以「已修改」状态留在工作区
src-tauri/src/ui_editor/agent_tools/creation.rs 把 prepare_design_image 拆成只读的 resolve_design_image 与登记两步:旧实现边校验边 register_local_asset_at,批次里后面某张设计图格式/尺寸不合法或路径缺失时,前面已登记的图片会留在 manifest.json 里且没有任何文档引用,而 rollback_created_document 只覆盖更晚的初始化失败

同批次查重改为按解析出的身份(已登记图片用 assetId、待登记图片用归一化路径)在登记前判定,重复引用不再先写一次 manifest

同文件新增 ResolvedDesignImage 承载「已登记 / 本次待登记」两种解析结果,待登记项在第二阶段登记后才拿到 assetId

src-tauri/src/tests/project.rs 新增 create_ui_design_doc_from_images_leaves_no_orphan_assets_when_a_later_image_fails,覆盖「第二张缺图时第一张不得进 manifest」(已用回退实现的失败结果反证过)
src-tauri/src/agent/runtime_tools/ui_design_doc.rs 的 from-images 与 into-js 观察函数改为 async,核心逻辑用 tokio::task::spawn_blocking 执行:from-images 要逐张 image::open 解码设计图再写 manifest,into-js 要读整份文档、算 SHA-256 再落盘 JS,原先都在 async 执行器线程上同步跑,会和其它已派发的动作抢执行器

阻塞任务未完成(join 失败)时返回 status=error 的观察,沿用仓库既有的 spawn_blocking 失败兜底写法

src-tauri/src/agent/runtime_actions/action_execution.rs 两个分发分支改为 await;ui_design_doc.rs 的两个用例改成 #[tokio::test] 并 await
- 检查点每步除记录结果外,再落一份「该步应用完之后」的状态快照,切分那步另带回填出错说明,旧日志无快照仍可解析
- 主流程只应用本次新完成那一步的改动,已完成步骤整步跳过,不再重复登记切图或重复累加回填说明
- 崩溃恢复改为只读检查点里的状态快照并逐级取回,删掉按记录结果重算目标状态的旧实现
- 只有结果、没有状态快照的旧检查点行按未完成处理,由主流程重跑该步
- 漂移与写回幂等判据改为对照快照:状态既不是本轮起点、也不是切分后那份才算漂移;文档已等于切分后快照即视为写回完成
- 同步 ADR、技术方案、代码地图与共享记忆里的检查点口径
- 项目变更判定与项目版本号推进判定补上 UI 设计文档的三个工具:成功返回即算改过项目
- 只重写派生产物的代码生成工具不推进项目版本号,避免虚报推进量、把"项目被别处改动"的误报再造出来
- 新建文档与跑工作流这两个工具在观察明细里报出真实推进格数,失败路径也报,避免切图素材已登记却漏计
- 非法人写的读明细逻辑收敛成一个helper,三处调用共用
- 补六条门禁用例覆盖成功即算、只出代码不算推进、真实推进量优先、失败但已推进才算
- 同步共享记忆的项目概览与决策记录
给 UI 设计文档三个工具补上可读的回执明细与入参摘要
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
065b4ea330
- 三个工具的持久回执补白名单分支:只放身份、相对路径、计数与回填说明,不再整块变成明细不可用
- 身份字段禁控制字符并限长,相对路径必须归一化后落在 ui/ 下,含宿主路径或 file URI 即失败关闭
- 回填说明按既有口径把绝对路径脱敏成占位符,超长或带控制字符的整条明细失败关闭
- 明细总长仍守 500 字符上限:清单能放多少放多少,放不下的部分用总数表达
- 入参摘要给出设计图逐张身份或目标文档 id,并把三个工具加进可读名单,不再只报哈希
- 补四条用例覆盖可读明细、脱敏、越界路径失败关闭与入参摘要
k88936 added 1 commit 2026-09-24 19:43:54 +08:00
Merge remote-tracking branch 'origin/master' into feat/ui-editor-v3
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m25s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m57s
Project CI / Backend tests (pull_request) Successful in 4m44s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Failing after 6m40s
Project CI / Native shell tests (pull_request) Successful in 6m11s
Project CI / Frontend tests (pull_request) Successful in 2m27s
Project CI / Repository checks (pull_request) Successful in 2m50s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 9m44s
Project CI / AI game creator shell web tests (pull_request) Successful in 1m38s
fecb8fe76f
# Conflicts:
#	docs/project-memory/shared-memory/decision-log.md
k88936 merged commit 34eee8ec6a into master 2026-09-24 19:45:47 +08:00
k88936 deleted branch feat/ui-editor-v3 2026-09-24 19:45:48 +08:00
Sign in to join this conversation.