From 29ba9a358ecce46578e2541be8b4b37a5f7301f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Thu, 17 Sep 2026 13:42:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AD=97=E4=BD=93=20kind=20=E6=8F=90=E5=8D=87?= =?UTF-8?q?=E4=B8=BA=20canonical=20=E5=B9=B6=E5=8E=BB=E6=8E=89=20font=20?= =?UTF-8?q?=E5=88=AB=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - game_creation_app.rs:`GAME_CREATION_APP_CANONICAL_ASSET_KINDS` 加入 `font`(17 → 18 项),分类表补 `font → document`,删除 `"font" => "document"` 别名。 - gameCreationApp.ts:TS 侧同步加入 `font`、删除别名表条目、补 `font: 'document'` 分类,并同步别名表注释。 - 测试:两侧用例改为断言 `font` 是 canonical 成员(大小写仍不敏感)、栏目仍是 document。 - 理由:字体上传写入侧直接落 `font`,再把它当别名会让「落盘值集合」与「canonical 集合」分叉;严格解析下写入侧的值必须本身就是 canonical。 --- .../tests/assetKindCanonicalMapping.test.ts | 2 +- packages/shared/src/contracts/gameCreationApp.test.ts | 8 +++++--- packages/shared/src/contracts/gameCreationApp.ts | 6 ++---- .../crates/shared-contracts/src/game_creation_app.rs | 9 ++++----- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/apps/ai-game-creator-shell/tests/assetKindCanonicalMapping.test.ts b/apps/ai-game-creator-shell/tests/assetKindCanonicalMapping.test.ts index 7584ff535..9bbedf2db 100644 --- a/apps/ai-game-creator-shell/tests/assetKindCanonicalMapping.test.ts +++ b/apps/ai-game-creator-shell/tests/assetKindCanonicalMapping.test.ts @@ -251,7 +251,7 @@ describe('真机出现的 kind 归类口径', () => { canonical: GAME_CREATION_APP_UI_DESIGN_DOC_ASSET_KIND, category: 'ui-interaction', }, - { kind: 'font', canonical: 'document', category: 'document' }, + { kind: 'font', canonical: 'font', category: 'document' }, // `Object.prototype` 上的键不是别名:TS 侧必须用 `Object.hasOwn` 挡住对象字面量的 // 原型命中,Rust 侧 match 字面量本来就落 `image`;这类极端输入两侧也必须一致。 { kind: 'constructor', canonical: 'image', category: 'unclassified' }, diff --git a/packages/shared/src/contracts/gameCreationApp.test.ts b/packages/shared/src/contracts/gameCreationApp.test.ts index 04da16962..89ff41a77 100644 --- a/packages/shared/src/contracts/gameCreationApp.test.ts +++ b/packages/shared/src/contracts/gameCreationApp.test.ts @@ -756,9 +756,11 @@ describe('AI 游戏创作 App 共享契约', () => { // 别名表大小写不敏感:UI 设计资产的现役写入侧写的是大写 `"UI"`。 expect(canonicalGameCreationAppAssetKind('UI')).toBe('ui-design'); expect(canonicalGameCreationAppAssetKind('UI-Prototype')).toBe('ui-design'); - // 字体资产的现役写入侧写的是 `font`。 - expect(canonicalGameCreationAppAssetKind('font')).toBe('document'); - expect(canonicalGameCreationAppAssetKind('FONT')).toBe('document'); + // 字体是 canonical 成员(现役写入侧就直接写 `font`),不再走 `font → document` 别名, + // 否则「落盘值集合」与「canonical 集合」会分叉。大小写仍不敏感。 + expect(canonicalGameCreationAppAssetKind('font')).toBe('font'); + expect(canonicalGameCreationAppAssetKind('FONT')).toBe('font'); + expect(gameCreationAppAssetCategoryForKind('font')).toBe('document'); /** * `Object.prototype` 上的键不是别名:别名表是对象字面量,直接下标取值会拿到原型上的 * 函数/对象(truthy)并被当成 canonical kind 返回;Rust 侧是 `match` 字面量,只会落 diff --git a/packages/shared/src/contracts/gameCreationApp.ts b/packages/shared/src/contracts/gameCreationApp.ts index 735940906..8bf6bd92a 100644 --- a/packages/shared/src/contracts/gameCreationApp.ts +++ b/packages/shared/src/contracts/gameCreationApp.ts @@ -505,6 +505,7 @@ export const GAME_CREATION_APP_CANONICAL_ASSET_KINDS = [ 'sound-effect', 'background-music', 'audio', + 'font', 'document', 'code', ] as const; @@ -520,9 +521,6 @@ export type GameCreationAppCanonicalAssetKind = * 否则会落到 `canonicalGameCreationAppAssetKind` 的 `image` 兜底,再经 * `image → unclassified` 被误分到「待归类」。 * - * `font` 同样属于现役写入侧:字体上传(`ttf / otf / woff / woff2`)登记的 manifest - * 资产 `kind` 就是 `font`,不在此收口就只能落「待归类」。 - * * 本表与 Rust 侧 `server-rs/crates/shared-contracts/src/game_creation_app.rs` 的 * `canonical_game_creation_app_asset_kind` 必须成对维护,由 * `tests/assetKindCanonicalMapping.test.ts` 交叉钉住。 @@ -546,7 +544,6 @@ const GAME_CREATION_APP_LEGACY_ASSET_KINDS: Record< 'game-style': 'code', animation: 'character-animation', asset: 'image', - font: 'document', }; export function canonicalGameCreationAppAssetKind( @@ -606,6 +603,7 @@ export const GAME_CREATION_APP_ASSET_CATEGORY_BY_KIND: Record< 'sound-effect': 'audio', 'background-music': 'audio', audio: 'audio', + font: 'document', document: 'document', code: 'unclassified', }; diff --git a/server-rs/crates/shared-contracts/src/game_creation_app.rs b/server-rs/crates/shared-contracts/src/game_creation_app.rs index b47581893..0f3f28678 100644 --- a/server-rs/crates/shared-contracts/src/game_creation_app.rs +++ b/server-rs/crates/shared-contracts/src/game_creation_app.rs @@ -570,7 +570,7 @@ impl<'de> Deserialize<'de> for GameCreationAppAssetManifestEntry { } } -pub const GAME_CREATION_APP_CANONICAL_ASSET_KINDS: [&str; 17] = [ +pub const GAME_CREATION_APP_CANONICAL_ASSET_KINDS: [&str; 18] = [ "image", "scene", "character", @@ -586,6 +586,7 @@ pub const GAME_CREATION_APP_CANONICAL_ASSET_KINDS: [&str; 17] = [ "sound-effect", "background-music", "audio", + "font", "document", "code", ]; @@ -608,9 +609,6 @@ pub fn canonical_game_creation_app_asset_kind(value: &str) -> &'static str { "game-entry" | "game-script" | "game-style" => "code", "animation" => "character-animation", "asset" => "image", - // 字体上传(`ttf / otf / woff / woff2`)登记的 manifest 资产 kind 就是 `font`, - // 不收口同样只能落「待归类」。 - "font" => "document", canonical => match GAME_CREATION_APP_CANONICAL_ASSET_KINDS .iter() .find(|candidate| **candidate == canonical) @@ -642,7 +640,7 @@ pub const GAME_CREATION_APP_ASSET_CATEGORIES: [GameCreationAppAssetCategory; 6] ]; /// canonical kind 到功能分类的默认映射,必须穷举 `GAME_CREATION_APP_CANONICAL_ASSET_KINDS`。 -pub const GAME_CREATION_APP_ASSET_CATEGORY_BY_KIND: [(&str, GameCreationAppAssetCategory); 17] = [ +pub const GAME_CREATION_APP_ASSET_CATEGORY_BY_KIND: [(&str, GameCreationAppAssetCategory); 18] = [ ("image", GameCreationAppAssetCategory::Unclassified), ("scene", GameCreationAppAssetCategory::Scene), ("character", GameCreationAppAssetCategory::Character), @@ -670,6 +668,7 @@ pub const GAME_CREATION_APP_ASSET_CATEGORY_BY_KIND: [(&str, GameCreationAppAsset ("sound-effect", GameCreationAppAssetCategory::Audio), ("background-music", GameCreationAppAssetCategory::Audio), ("audio", GameCreationAppAssetCategory::Audio), + ("font", GameCreationAppAssetCategory::Document), ("document", GameCreationAppAssetCategory::Document), ("code", GameCreationAppAssetCategory::Unclassified), ];