合并最新主线并对齐资源类型枚举更新
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 4m25s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m14s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 5m38s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 5m39s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 6m25s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m6s
Project CI / Repository checks (pull_request) Successful in 8m12s
Project CI / Native shell tests (pull_request) Successful in 10m54s
Project CI / Frontend tests (pull_request) Successful in 13m34s
Project CI / Backend tests (pull_request) Successful in 13m55s
Project CI / AI game creator shell web tests (pull_request) Successful in 8m2s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 4m25s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m14s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 5m38s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 5m39s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 6m25s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m6s
Project CI / Repository checks (pull_request) Successful in 8m12s
Project CI / Native shell tests (pull_request) Successful in 10m54s
Project CI / Frontend tests (pull_request) Successful in 13m34s
Project CI / Backend tests (pull_request) Successful in 13m55s
Project CI / AI game creator shell web tests (pull_request) Successful in 8m2s
同步 master 的资源类型枚举、共享契约与依赖锁文件更新 保留本分支的窄依赖、集中鉴权和异步追踪实现 通过路由、项目元数据、图片编辑策略和共享契约定向回归
This commit is contained in:
@@ -2,6 +2,39 @@
|
||||
|
||||
> 用途:记录已经确认、会影响后续开发的长期技术/产品/协作决策。短期讨论不要写在这里。
|
||||
> 当前口径:历史条目的旧路径、旧版本和已退役对象只用于追溯,不构成现行实现依据;如与当前代码或 `docs/README.md` 冲突,以当前代码和最新专题文档为准。
|
||||
## 2026-09-17 GameCreationApp 资源 kind 只保留一份词汇表:严格解析 + `app_log!` 留痕
|
||||
|
||||
- 背景:kind 曾经有三份实现——Rust 手写 `GAME_CREATION_APP_CANONICAL_ASSET_KINDS` + `canonical_game_creation_app_asset_kind()`(带 legacy 别名表与 `font → document` 特例)、TS 手写 `GAME_CREATION_APP_CANONICAL_ASSET_KINDS` + `GAME_CREATION_APP_LEGACY_ASSET_KINDS` + `canonicalGameCreationAppAssetKind()`、以及 ts-rs 生成的 TS union。两份手写表互相引用又各自收口,判据直接分叉(同一个 `"UI"` 一边归一成 `ui-design`、一边收口成 `unknown`),跨语言一致性只能靠正则解析源码的测试来钉。
|
||||
- 决策(唯一真源):kind 的变体、线上值、`as_str()`、`ALL`、严格解析与 ts-rs 绑定全部由 `server-rs/crates/shared-contracts/src/game_creation_app/asset_kind.rs` 的声明表派生。两份手写 canonical 列表、legacy 别名表、`canonical_*()` 函数一律删除;生成的 TS union 落在 `packages/shared/src/contracts/generated/GameCreationAppAssetKind.ts`,`packages/shared/src/contracts/gameCreationApp.ts` 只 re-export 它,运行期列表 `GAME_CREATION_APP_ASSET_KINDS` 用穷举 `Record<GameCreationAppAssetKind, true>` 守住。
|
||||
- 决策(单一解析入口):`GameCreationAppAssetKind::parse_with_context()` 是唯一公开解析入口,严格匹配降为私有 `match_canonical()`;易混的 `from_str_lossy()` 与公开 `from_str_or_unknown()` 都已删除,认不出 canonical 值只有这一处收口并留痕(读侧回捞 legacy kind 只查 `ALL` 判真值,不另开解析函数)。口径是等值匹配——不 trim、不 lowercase、不查别名、不迁移;认不出的值收口成 `Unknown`(分类落 `unclassified`)。这是有意接受的行为(历史误写的 kind 不会被"救回"正确栏目),不再提供任何兼容入口;`font` 是正式成员,不再走别名。
|
||||
- 决策(登记边界的 kind 口径):外部登记统一走 `assets::registration_asset_kind()`——空白入参落中性 `image`,非空认不出的值严格收口成 `unknown` 并留痕;三条登记边界(Tauri `register_local_asset`、画板导入、平台导入)不再各写一份 trim/兜底。`Unknown` 是无法解析的边界结果,具体写入方必须自行决定拒绝或保留待后续归类,不能静默猜成其他 kind。栅格归一化的 `source_subtype` 只接受图片族成员,文档/字体/音频等一律按 `image` 登记;Agent 回执派生物按 `Text => Document` 落 `document`。
|
||||
- 决策(判据不许散落):切片残留登记只看 `assets/art-spritesheet-slices/` 路径(不再附带 `kind == Icon`);sprite 身份比较忽略随 kind 派生的 `metadata.asset_type`;TS 侧「UI 编辑器文档资产」判据只留 `isGameCreationAppUiDesignDocAsset()` 一份,资源画布入口 / UI 编辑器桥接 / 资源引用缩略图统一调用。
|
||||
- 决策(已知代价,不补救):既有项目里无法解析的 kind 读入即 `unknown`,依赖 kind 等值比较的运行门禁会按"缺少该资源"处理。这是严格解析的必然结果,本次明确不为存量数据做迁移;将来若要迁就必须单独立项,不能改写解析边界。
|
||||
- 决策(留痕必须真的落地):原实现用 `tracing::warn!`,而 AGC 壳没有 tracing subscriber,等于没有日志。现在 `shared-contracts` 只暴露可注册回调 `set_non_canonical_asset_kind_reporter()`,AGC 壳在 `main()` 里接到 `app_log!`,日志同时含原始输入串与调用上下文;`kind-observability` feature 与 `tracing` 依赖一并删除。TS 侧对应 `parseGameCreationAppAssetKind()` 的 `console.warn`。
|
||||
- 决策(平台/画板词汇表):平台生成输入先严格解析为 `GameCreationAppAssetKind`,登记时直接写入已解析的 enum,不再保留 `platform_art_asset_manifest_kind()` 或任何平台别名/fallback 映射;图片快速编辑来源同样只允许 canonical 静态图片成员并要求 `mediaType=image`,原 `EDITOR_IMAGE_EDIT_STATIC_IMAGE_ASSET_KINDS` 兼容白名单已删除。
|
||||
- 验证:`cargo test -p shared-contracts`(含词汇表唯一性、严格性与留痕用例)、`cargo test --locked -p shared-contracts --features ts-bindings export_bindings` 后 `git diff` 为空、AGC bin 定向用例(`derived_asset_manifest_kind_is_never_unknown_for_text_derivatives`、`non_canonical_manifest_asset_kinds_report_raw_values_only`)、`npx vitest run packages/shared/src/contracts/gameCreationApp.test.ts apps/ai-game-creator-shell/tests/uiDesignResourceBridge.test.ts apps/ai-game-creator-shell/tests/appSurface.test.ts`。
|
||||
- 关联文档:[AI 游戏创作智能体 App 实施计划](../../technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md) 的 2026-09-17 节。
|
||||
|
||||
## 2026-09-16 DirectProject 引用渲染收敛到 canonical user item 深模块
|
||||
|
||||
- 背景:`agent/direct_codex_references.rs`(平行 `DirectCodexTurnReference` DTO 与渲染路径)已退役,引用身份、上限与投影收敛到 `agent/direct_codex_user_item/`;本轮 prompt 里引用只投影为 `[素材引用 resourceId=…;项目路径=…]` 摘要,`MAX_DIRECT_CODEX_REFERENCES` 归 `direct_codex_user_item/validation.rs`。
|
||||
- 决策:2026-09-14「Direct Codex 引用 UI 设计文档生成代码上下文」的 prompt 注入改落在 `agent/direct_codex_user_item/wire.rs`,入口是 `direct_codex_user_item_to_prompt`:引用命中 `ui-design-doc` + `application/json` 时顺序调用 `generate_ui_design_code_at`,成功追加 `请先阅读生成的带有文档的代码片段: {relative_path}`,失败追加原始 `生成代码遇到错误{error}`,其它引用继续处理,manifest 身份摘要不变。
|
||||
- 决策(无写副作用):只在生成本轮 prompt 时展开该上下文;历史 item 回读走 `direct_codex_user_item_to_response_item` 的纯投影,不得触发 UI 代码导出或任何项目写入。
|
||||
- 验证:`agent::direct_codex_user_item` 定向 16 条通过,覆盖成功注入、生成失败保留引用摘要、非 UI 文档不触发与历史回读不产生 `ui/generated-*.js`。
|
||||
|
||||
|
||||
## 2026-09-19 AGC Direct 删除每回合四项媒体资源请求上限
|
||||
|
||||
- 背景:2026-08-24 引入的单回合四项上限以「整个 agent run(一条用户消息到回合结束)」为窗口,计数只增不减、请求完成不释放额度;autonomous 游戏构建要求 agent 不停下跑完整局,额度耗尽后的报错实际是终态,与技能的三次重试纪律冲突,现场表现为长时间无效重试。2026-09-18 先将不计费的抠图豁免,但付费 create/derive 仍受同一窗口问题影响。
|
||||
- 决策:整体删除该上限机制。移除 `DIRECT_TOOL_BRIDGE_MAX_RESOURCE_CALLS_PER_TURN` 常量、回合授权状态中的 `resource_request_ids` 计数 map 与 `resource_request_ids()` 方法;`agc_create_or_derive_resource`(含 `agc_edit_image` 委托)与 `agc_remove_background` 统一按回合身份 + 请求指纹确定性派生 operation/idempotency id,同指纹重试复用与 pending 对账语义不变。付费提交串行仍由 `resource_generation_gate` 互斥保证,成本控制由服务端计费与泥点余额兜底,客户端不再按回合计数设限。
|
||||
- 验证方式:`cargo check`(ai-game-creator-shell src-tauri)通过,203 项警告与基线一致;无测试断言该上限,未新增测试。
|
||||
|
||||
## 2026-09-18 AGC Direct 抠图不占每回合四项付费媒体额度
|
||||
|
||||
- 状态:2026-09-19 起该上限机制整体删除(见上条),本条目仅作追溯。
|
||||
- 背景:2026-08-24 起 `agc_create_or_derive_resource` 与 `agc_remove_background` 共用每回合四项媒体资源请求上限。抠图服务端持久化 `generation_cost_mud_points: 0`(不计费),bgfilter 实测单张约 1 秒,上限导致一回合抠超过四张时后续请求被直接拒绝、agent 反复无效重试。
|
||||
- 决策:`agc_remove_background` 不再经过 `resource_request_ids` 计数,直接按回合身份与请求指纹确定性派生 operation/idempotency id(与 map 复用结果一致),同指纹重试与 pending 对账语义不变。付费的 create/derive(含 `agc_edit_image` 委托)维持四项上限与原有报错文案,且抠图请求不再挤占其额度。
|
||||
- 验证方式:`cargo check`(ai-game-creator-shell src-tauri)与 `git diff --check` 通过;未新增测试。
|
||||
|
||||
## 2026-09-18 Provider 瞬态重试次数严格按设置执行(游戏开发 Agent 与策划 Agent 不再被档位收进区间)
|
||||
|
||||
@@ -8883,6 +8916,12 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
|
||||
- 决策:采用后台继续运行语义。Direct 回合由进程内项目身份锁持有,页面离开不取消;重进项目通过活动回合只读快照与 Thread Manager bootstrap/consume 恢复忙碌态和进度。左上角面板复用同一快照列出正在运行的 Direct 项目并支持进入。
|
||||
- 边界:快照不写项目文件、不进入公共 API、不跨应用重启恢复;读取失败保留上一份结果并单独提示,不改写成权限或审批失败。身份锁排他性、付费身份和项目写锁不变。
|
||||
|
||||
## 2026-09-14 Direct Codex 引用 UI 设计文档生成代码上下文
|
||||
|
||||
- 决策:UI Editor JSON 文档资产唯一使用 `kind:"ui-design-doc"` 且 `mediaType:"application/json"`;`ui-prototype` 保持图片语义,旧 `UI` / `ui` / `ui-design` 不作为该文档分支输入,不做 fallback 或迁移。
|
||||
- 决策:Direct Codex 结构化资源引用命中该 kind 时,顺序调用 UI Editor persistence 的 `generate_ui_design_code_at`,生成 `ui/generated-*.js`,并把 `请先阅读生成的带有文档的代码片段: {relative_path}` 追加到当前 prompt。生成失败不阻断本轮引用,追加原始 `生成代码遇到错误{error}`,其它引用继续处理。
|
||||
- 原因:复用 `html_renderer/mod.rs` 统一产物,确保 LLM 读取的代码包含 UI 节点元数据和文档注释;严格 kind + mediaType 判定避免图片资产误走代码生成。
|
||||
|
||||
## 2026-09-17 AGC 模板库落在 oss://agc-dev/templates/
|
||||
|
||||
- 背景:AGC 需要「真·游戏模板」库,让用户能浏览、筛选、下载模板并直接由模板创建项目,且模板内容更新不依赖客户端发版。
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# 踩坑与排障记录
|
||||
|
||||
## 2026-09-19 资源 kind 词汇收敛后,前端判据与 fixture 必须一起按 canonical 成员重写
|
||||
|
||||
- **现象**:工具栏入口的 `assetKind` 换成共享 `GameCreationAppAssetKind`(图集从平台词 `art-spritesheet` 改成 `icon-spritesheet`)后,「图集不接受用户参考」的判据仍写在旧的 `['art-spritesheet']` 字符串清单里,判据恒假:生成面板重新给图集渲染参考图选择器,原生提交再按合同显式拒绝多余参考。
|
||||
- **同类第二处**:把 `hasRegisteredArtImageAssets` 从 `kind === 'art-spritesheet'` 直接换成「kind ∈ 视觉族」会把候选 UI 原型图(`ui-design`)算成美术图片产出,提前顶掉「美术资源计划已完成,尚未生成或登记图片」;判据必须显式排除 `GAME_CREATION_APP_UI_DESIGN_ASSET_KIND`。
|
||||
- **处理(现行口径)**:前端的资源 kind 判据只比较 canonical 成员或共享契约导出的谓词,不再维护第二份字符串清单;词汇收敛时先 grep 旧词在 `src/` 与 `tests/` 两侧的落点,fixture 同步按 canonical 成员重写。
|
||||
- **易错点**:fixture 与生产代码写着同一个旧词时,单测会陪着一起变绿,用例证明不了任何事;另外 `tests/appSurface.test.ts` 不是全部同族用例,资源画布 / 画布生成参考等用例散在 `tests/*.test.ts(x)`,词汇收敛必须连这些一起跑。
|
||||
|
||||
## 2026-09-17 ts-rs 生成物换目录后,忘记同步忽略规则会让「生成物抖动」假装成代码改动
|
||||
|
||||
- **现象**:`GameCreationAppAssetKind` 的 ts-rs `export_to` 从 `apps/ai-game-creator-shell/src/contracts/generated/` 换到 `packages/shared/src/contracts/generated/` 后,任何 `cargo build` / `cargo test` 都会重写生成文件;若新目录没进 `.prettierignore` 与 `.eslintrc.cjs` 的 `ignorePatterns`,lint-staged / prettier 会把生成物重新格式化,于是每次提交都出现「生成物被改」,`cargo test export_bindings` 也不再幂等(跑完 `git diff` 不为空)。
|
||||
- **处理(现行口径)**:生成目录一律成对登记 `.prettierignore` + eslint `ignorePatterns`;改 `export_to` 时同步改这两处,并用 `cargo test --locked -p shared-contracts --features ts-bindings export_bindings --manifest-path server-rs/Cargo.toml` 后 `git diff` 为空来验证幂等。
|
||||
- **易错点**:旧的 `apps/ai-game-creator-shell/src/contracts/generated/` 目录下的同名文件不会自动删除,换目录后必须显式删除旧文件,否则会出现「两个同名 union,改动只落在一个目录」的假绿。
|
||||
## 生成草稿与异步展示边界必须按身份隔离
|
||||
|
||||
非模态生成浮层切换占位时按 draftId 分实例,卸载保留未提交/失败草稿,成功提交不再复活草稿;旧项目占位不存在时丢弃其保存回调。失败重试保留原请求输入和引用身份,引用失效不能静默过滤;修改已绑定输入须明确另起请求,不伪装成原请求重试。
|
||||
@@ -5462,11 +5474,12 @@ Cocos Creator 根目录由 `package.json.creator.version` 与普通 `assets/`
|
||||
## 资源 kind 别名只救新登记,不救存量 category(2026-09-10)
|
||||
|
||||
- 现象:真机 `What do u wanna do kitten` 的 66 项资源里 58 项落「待归类」,其中 57 项是 `kind:"ui"` 的 UI 资产,本该在「UI 交互」。
|
||||
- 成因链:`ui` 不在 `GAME_CREATION_APP_CANONICAL_ASSET_KINDS` 里、也没有别名,于是走 `canonicalGameCreationAppAssetKind` 的 `image` 兜底,再经 `image → unclassified` 被误分到「待归类」。它并不是历史遗留值——`assets.rs:1656` 的 `infer_canvas_export_asset_kind`(画板导出导入)**现在仍在写出** `ui` / `animation` / `asset`。
|
||||
- 成因链:`ui` 不在 canonical 词汇表里、也没有别名,于是落「待归类」。它并不是历史遗留值——`assets.rs` 的 `infer_canvas_export_asset_kind`(画板导出导入)当时仍在写出 `ui` / `animation` / `asset`。
|
||||
- **现行口径(2026-09-17 起,改这里之前必读)**:kind 只有一份词汇表(Rust `GameCreationAppAssetKind` 声明表 → ts-rs 生成 TS union),解析是**严格等值匹配**:不 trim、不 lowercase、不查别名、不迁移;非 canonical 原值收口成 `unknown`(分类 `unclassified`)并把**原始串 + 调用上下文**交给壳层注册的 `app_log!` 回调。**别名表已整体删除,不要再加回来**——这条现象现在的表现是「日志里能查到谁还在写旧值」,先修写入方,不要在读侧做兼容。
|
||||
- **关键陷阱(2026-09-11 已修)**:补别名只影响「今后新登记」的资产。`register_local_asset_entry`(`assets.rs`)命中同 `localPath` 的既有资产时,旧实现只覆盖 `kind` / `media_type` / `source`、**不重算 `category`**;而读取侧优先信任落盘 `category`、只在它缺失或非法时才按 `kind` 派生。所以这 57 条的落盘 `category: "unclassified"` 会一直有效,重导入也自愈不了。**修法与必须保留的不变量**:更新分支只在 `kind` 真的变化时才重派生 `category`,否则「同路径重登记且 kind 变了」会留下「新 kind + 旧分类」的错位,而陈旧的非 `unclassified` 值会被无条件信任、自愈也不触发;反过来同 kind 重登记**禁止**动 `category`,落盘分类是权威值,被 `register_local_asset_keeps_explicit_category_when_kind_is_unchanged` 钉住。
|
||||
- 为什么读取侧要信任落盘值:存在用户手动改分类的正式链路 `update_manifest_asset_classification_at`(`project/manifest.rs:1110`),读时无条件重派生会吃掉用户的手动设置。
|
||||
- 根治选项(需产品拍板):① 读时把 `unclassified` 当作「未设置」再按 kind 派生(简单但失去"我就是要 unclassified"的表达力);② 一次性回填这 57 条(保留人工设置语义,需迁移脚本);③ 只改写入侧让新素材 canonical 化(治不了存量)。
|
||||
- 另一处必须成对维护:别名表有**两份实现**——TS 侧 `packages/shared/src/contracts/gameCreationApp.ts` 的 `GAME_CREATION_APP_LEGACY_ASSET_KINDS`(读投影用)与 Rust 侧 `server-rs/crates/shared-contracts/src/game_creation_app.rs` 的 `canonical_game_creation_app_asset_kind`(写入侧按 kind 派生 category 用)。只改一边就会让落盘 category 与读侧栏目互相矛盾。交叉守卫见 `apps/ai-game-creator-shell/tests/assetKindCanonicalMapping.test.ts`(直接解析 Rust 源码比对)。
|
||||
- 成对维护点(**2026-09-17 起不再存在**):当时别名表有**两份实现**——TS 侧 `GAME_CREATION_APP_LEGACY_ASSET_KINDS` 与 Rust 侧 `canonical_game_creation_app_asset_kind`,靠 `apps/ai-game-creator-shell/tests/assetKindCanonicalMapping.test.ts` 正则解析 Rust 源码交叉钉住。现在两份手写表与那个守卫测试都已删除:唯一词汇表由 Rust 枚举声明表派生、经 ts-rs 生成 union,跨语言一致性回到**编译期**(TS 侧 `Record<GameCreationAppAssetKind, …>` 穷举,少一个成员就编译不过)。不要再引入"正则解析 Rust 源码"的跨语言守卫。
|
||||
- 真机计数守卫见 `apps/ai-game-creator-shell/tests/resourceCardPreviewRealManifest.test.ts`。
|
||||
- 关联:`apps/ai-game-creator-shell/src-tauri/src/assets.rs`、`apps/ai-game-creator-shell/src-tauri/src/project/manifest.rs`、`packages/shared/src/contracts/gameCreationApp.ts`、`server-rs/crates/shared-contracts/src/game_creation_app.rs`。
|
||||
|
||||
@@ -5475,20 +5488,20 @@ Cocos Creator 根目录由 `package.json.creator.version` 与普通 `assets/`
|
||||
- 规则(已拍板落地):`gameCreationAppAssetCategory` 在「落盘 `category === 'unclassified'` **且** 该资产 `kind` 能派生出明确的非 `unclassified` 分类」时采用派生值,其余情况信任落盘值。
|
||||
- 为什么需要这条:`register_local_asset_entry`(`assets.rs`)命中同 `localPath` 的既有资产时**只在 `kind` 变化时**重算 `category`(2026-09-11 起);所以历史上被写成 `unclassified` 的资产(典型是 `kind:"ui"` / `kind:"UI"` 因不在 canonical 目录而落到 `image → unclassified`)在补齐别名后**不会自愈**。选读时重派生而不是写迁移脚本:不需要迁移、且永久自愈(任何历史上被系统错判成 unclassified 的都会自动归位)。真机验证:`What do u wanna do kitten` 的待归类从 58 降到 1(只剩 code 类 `game-entry`),UI 交互从 2 升到 59。
|
||||
- **两个口径不能混用(2026-09-11 收口)**:`gameCreationAppAssetCategory` / `game_creation_app_asset_effective_category` 是**读显示**口径;写回 manifest 必须用 `gameCreationAppAssetPersistedCategory`(只做缺失 / 非法兜底),它等于 Rust 反序列化后的落盘原值。把自愈值回写会把「只改标签」变成静默改分类——真机上同一条 `kind:"ui"` 资产因此同时存在 `unclassified` 与 `ui-interaction` 两种落盘值。
|
||||
- **跨端必须同构**:Agent 侧资源投影(`direct_tool_bridge.rs`)走 Rust 的 `game_creation_app_asset_effective_category`,不许直接透传落盘 `category`;两侧不一致时同一条资产会出现「UI 显示 UI 交互、Agent 读到待归类」(真机 55 条)。守卫是 `assetKindCanonicalMapping.test.ts` 解析 Rust 源码里的 `EFFECTIVE_CATEGORY_CONTRACT` 决策矩阵。
|
||||
- **跨端必须同构**:Agent 侧资源投影(`direct_tool_bridge.rs`)走 Rust 的 `game_creation_app_asset_effective_category`,不许直接透传落盘 `category`;两侧不一致时同一条资产会出现「UI 显示 UI 交互、Agent 读到待归类」(真机 55 条)。**现行守卫(2026-09-17 起)**:`shared-contracts` 的 `EFFECTIVE_CATEGORY_CONTRACT` 决策矩阵用例 + `packages/shared` 的 `gameCreationApp.test.ts` 同口径用例;解析 Rust 源码的 `assetKindCanonicalMapping.test.ts` 已删除。
|
||||
- 为什么可以覆盖落盘值:落盘 `category` 的权威性来自「用户可在分类与标签面板手动设置」(`update_manifest_asset_classification_at`,`project/manifest.rs`)。收窄条件把覆盖窗口压到最小——只有当落盘值是 `unclassified`(即"没有明确分类")时才覆盖。
|
||||
- **唯一盲区**:用户**手动**把一个 kind 已能明确分类的资产设成「待归类」时,该手动值会被覆盖。这是有意接受的取舍:「手动设为待归类」意图边缘,且 kind 已经表达了分类;而漏掉这条规则,所有历史误判都无法自愈。若将来产品需要"显式待归类",应改成在 manifest 里区分"未设置"与"显式 unclassified"(例如 `category` 缺省 vs 显式写入),而不是取消本条规则。
|
||||
- 不受影响:`image` / `video` / `code` / `publication-material` 的 canonical 分类本身就是 `unclassified`,派生结果等于落盘值,规则不触发(已用断言钉住)。
|
||||
- 写入侧已同步 canonical 化:`infer_canvas_export_asset_kind`(`assets.rs`)现在直接产出 canonical kind(`ui → ui-design`、`animation → character-animation`、`asset → image`),不再依赖别名表兜底;`canvas_export_asset_kind_is_always_canonical` 用例逐分支钉死,别名表从此只承担存量兼容。
|
||||
- 写入侧已同步 canonical 化:`infer_canvas_export_asset_kind`(`assets.rs`)现在直接产出 canonical kind(`ui → ui-design`、`animation → character-animation`、`asset → image`),不再依赖别名表兜底;`canvas_export_asset_kind_is_always_canonical` 用例逐分支钉死。**2026-09-17 起别名表整体删除**,存量兼容也不做:读侧严格解析,认不出的原值只留痕。
|
||||
- 关联:`packages/shared/src/contracts/gameCreationApp.ts` 的 `gameCreationAppAssetCategory`、`apps/ai-game-creator-shell/src-tauri/src/assets.rs`、`apps/ai-game-creator-shell/tests/resourceCardPreviewRealManifest.test.ts`。
|
||||
|
||||
## 大写 `UI` / `font` 不在 alias 表 → 8 条真机 UI 资产永远落「待归类」,且自愈救不回(2026-09-11)
|
||||
|
||||
- 现象:真机 `What do u wanna do kitten` 有 8 条资产的 `kind` 是**大写** `"UI"`、`mediaType` 是 `application/json`、`localPath` 是 `ui/UI 设计 N.json`,永远停在「待归类」。
|
||||
- 成因链:写入侧写大写——`ui_editor/resource_bridge.rs` 的 `register_local_asset_at(root, &relative_path, "UI", "application/json", …)`,`workflow.rs` / `persistence.rs` 同;而 alias 表只有小写 `"ui" => "ui-design"`,于是 `"UI"` 落到 `canonical_game_creation_app_asset_kind` 的 `image` 兜底 → `image → unclassified`。
|
||||
- **为什么读时自愈救不回来**:自愈规则的前提是「派生值不是 unclassified」,而 `"UI"` 的派生值**就是** `unclassified`,规则永不触发。所以只能在 alias 表收口——别名表必须**大小写不敏感**(`UI` / `ui` / `ui-prototype` 都要落 `ui-design`),并把 `font`(`ttf / otf / woff / woff2` 上传登记的 kind,见 `commands.rs` 的 `register_local_asset_entry(root, &relative_path, "font", …)`)一并补进别名表落 `document`。
|
||||
- 守卫三层:Rust `asset_category_mapping_covers_every_canonical_kind` 逐条断言(旧断言曾把 `"UI" → unclassified` 钉死,正是这条 bug 的护栏反向加固);`ui_editor/resource_bridge.rs` 的 `bridge_is_idempotent_and_installs_source_image` 走真实生产函数 → 真实写入 → 断言落盘 `category`;TS `assetKindCanonicalMapping.test.ts` 的「写侧 kind 字面量 → 分类」直接解析写侧源码的第 3 个实参,写点换个新字面量就会红。
|
||||
- 关联:`server-rs/crates/shared-contracts/src/game_creation_app.rs`、`packages/shared/src/contracts/gameCreationApp.ts`、`apps/ai-game-creator-shell/src-tauri/src/ui_editor/resource_bridge.rs`、`apps/ai-game-creator-shell/tests/assetKindCanonicalMapping.test.ts`。
|
||||
- 成因链:写入侧写大写——`ui_editor/resource_bridge.rs` 的 `register_local_asset_at(root, &relative_path, "UI", "application/json", …)`,`workflow.rs` / `persistence.rs` 同;当时的 alias 表只有小写 `"ui" => "ui-design"`,`"UI"` 因此落 `image` 兜底 → `unclassified`。**注意 `font` 早已是正式 canonical 成员(不再靠别名落 `document`)**。
|
||||
- **为什么读时自愈救不回来**:自愈规则的前提是「派生值不是 unclassified」,而 `"UI"` 的派生值**就是** `unclassified`,规则永不触发。**现行口径(2026-09-17 起)**:不给 `"UI"` 找归一口径,而是修写入侧写 canonical 字面量;读侧严格解析,认不出的原值收口 `unknown` + `app_log!` 留痕(原始串 + 上下文)。
|
||||
- 守卫三层:Rust `asset_category_mapping_covers_every_kind` 穷举断言(旧的 `"UI" → unclassified` 断言正是这条 bug 的反向加固,已删);`ui_editor/resource_bridge.rs` 的 `bridge_is_idempotent_and_installs_source_image` 走真实生产函数 → 真实写入 → 断言落盘 `category`;TS `parseGameCreationAppAssetKind` / `console.warn` 用例钉住"非 canonical 值收口 + 留痕原值"。
|
||||
- 关联:`server-rs/crates/shared-contracts/src/game_creation_app/asset_kind.rs`、`packages/shared/src/contracts/gameCreationApp.ts`、`apps/ai-game-creator-shell/src-tauri/src/ui_editor/resource_bridge.rs`、`apps/ai-game-creator-shell/tests/assetKind.test.ts`。
|
||||
|
||||
## AGC 资源搜索栏改成「临时叫出」的浮层,工具条带与它的下移逻辑一并撤掉(2026-09-11)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user