同步分类自愈规则的契约用例:改断言并把盲区补成显式用例
- 修正 resolves asset category and tags with legacy and forward compatibility 中 { kind: 'character', category: 'unclassified' } 的期望:由 'unclassified' 改为 'character'
- 该断言是 09-09 引入的旧口径,与 2026-09-10 落地的分类自愈规则冲突;按拍板保留自愈规则(它修复真机 57 条 kind:ui 资产落待归类),因此精确更新断言而非放宽为 not.toBe
- 在断言处补注释说明这是本批有意行为,并写明已知盲区:用户手动把可明确分类的资产设为待归类时会被覆盖
- 新增用例「自愈规则覆盖落盘 unclassified:这是显式接受的盲区」,覆盖 character / ui / art-spritesheet 三条具体映射
- 新增用例「派生结果本身就是 unclassified 的 kind 不受自愈规则影响,保持落盘值」,覆盖 image / video / code / publication-material 与未知 kind
- 新增用例「落盘为明确分类时信任落盘值,不被 kind 派生结果覆盖」,覆盖 image+scene / character+audio / ui+document
- 变异验证:临时移除自愈规则后上述 2 条断言失败(expected 'unclassified' to be 'character'),恢复后全部通过
This commit is contained in:
@@ -793,9 +793,13 @@ describe('AI 游戏创作 App 共享契约', () => {
|
||||
expect(gameCreationAppAssetCategory(legacy)).toBe('character');
|
||||
expect(gameCreationAppAssetTags(legacy)).toEqual([]);
|
||||
|
||||
// 有意行为(2026-09-10 分类自愈批次):落盘 `unclassified` 而 kind 能派生出明确的
|
||||
// 非 `unclassified` 分类时,读取侧采用派生值。这条规则用于自愈历史上被系统误写成
|
||||
// `unclassified` 的存量(真机 57 条 `kind:"ui"` 资产),无需迁移脚本且永久生效。
|
||||
// 已知盲区:用户手动把可明确分类的资产设为「待归类」时该手动值会被覆盖,属有意接受。
|
||||
expect(
|
||||
gameCreationAppAssetCategory({ ...legacy, category: 'unclassified' }),
|
||||
).toBe('unclassified');
|
||||
).toBe('character');
|
||||
expect(gameCreationAppAssetCategory({ ...legacy, category: 'audio' })).toBe(
|
||||
'audio',
|
||||
);
|
||||
@@ -836,4 +840,63 @@ describe('AI 游戏创作 App 共享契约', () => {
|
||||
).toEqual(['主角', '战斗']);
|
||||
expect(normalizeGameCreationAppAssetTags([])).toEqual([]);
|
||||
});
|
||||
|
||||
/**
|
||||
* 分类自愈规则的三条边界(2026-09-10 批次)。
|
||||
*
|
||||
* 规则:落盘 `category === 'unclassified'` 且该资产 `kind` 能派生出明确的非
|
||||
* `unclassified` 分类时采用派生值;其余情况信任落盘值。目的是自愈历史上被系统误写成
|
||||
* `unclassified` 的存量(真机 57 条 `kind:"ui"` 资产因此从「待归类」归位「UI 交互」),
|
||||
* 不写迁移脚本且永久生效。
|
||||
*/
|
||||
it('自愈规则覆盖落盘 unclassified:这是显式接受的盲区', () => {
|
||||
// 落盘 unclassified + kind 可明确分类 → 派生值覆盖落盘值。
|
||||
// 盲区:用户手动把可明确分类的资产设为「待归类」时同样会被覆盖,属有意接受的
|
||||
// 最小覆盖窗口;若将来产品需要「显式待归类」,应改为在 manifest 区分
|
||||
// 「未设置」与「显式 unclassified」,而不是取消这条规则。
|
||||
expect(
|
||||
gameCreationAppAssetCategory({
|
||||
kind: 'character',
|
||||
category: 'unclassified',
|
||||
}),
|
||||
).toBe('character');
|
||||
expect(
|
||||
gameCreationAppAssetCategory({ kind: 'ui', category: 'unclassified' }),
|
||||
).toBe('ui-interaction');
|
||||
expect(
|
||||
gameCreationAppAssetCategory({
|
||||
kind: 'art-spritesheet',
|
||||
category: 'unclassified',
|
||||
}),
|
||||
).toBe('ui-interaction');
|
||||
});
|
||||
|
||||
it('派生结果本身就是 unclassified 的 kind 不受自愈规则影响,保持落盘值', () => {
|
||||
// image / video / code / publication-material 的 canonical 分类就是 unclassified,
|
||||
// 派生结果等于落盘值,规则不触发,必须继续信任落盘值。
|
||||
for (const kind of ['image', 'video', 'code', 'publication-material']) {
|
||||
expect(
|
||||
gameCreationAppAssetCategory({ kind, category: 'unclassified' }),
|
||||
).toBe('unclassified');
|
||||
}
|
||||
// 无法识别的 kind 落到 image 兜底,派生结果同样是 unclassified。
|
||||
expect(
|
||||
gameCreationAppAssetCategory({
|
||||
kind: 'unknown-kind',
|
||||
category: 'unclassified',
|
||||
}),
|
||||
).toBe('unclassified');
|
||||
});
|
||||
|
||||
it('落盘为明确分类时信任落盘值,不被 kind 派生结果覆盖', () => {
|
||||
expect(
|
||||
gameCreationAppAssetCategory({ kind: 'image', category: 'scene' }),
|
||||
).toBe('scene');
|
||||
expect(
|
||||
gameCreationAppAssetCategory({ kind: 'character', category: 'audio' }),
|
||||
).toBe('audio');
|
||||
expect(
|
||||
gameCreationAppAssetCategory({ kind: 'ui', category: 'document' }),
|
||||
).toBe('document');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user