补记跨层字段名静默忽略的排障口径,并把逐栏目用例提为首选证据

- `pitfalls.md` 新增「manifest 资产分类字段写错名会被静默忽略,跨层字段名相近时尤其危险」:manifest 上的字段名是 `category`,而 `assetCategory` 是前端投影后 `ProjectResource` 的字段名,写错层不报错也不告警,本文档记录现象、原因、处理与通用规则(「设置无效但没有任何报错」时第一优先怀疑字段名或层级错配)。
- 同文件「预览 Hook 的资源入参收窄会连带收窄 identity map」那条的验证行改为以新用例 `mounts a real card body in every non-empty resource section overview` 为首选证据:它逐栏目覆盖五个非空栏目并含变异验证;既有 `uses one full-page canvas per resource section with dependency-only guide lines` 降为补充(只覆盖一两个栏目)。
- 只追加与就地更正该条验证行,未重排任何既有条目。
This commit is contained in:
2026-09-11 02:00:38 +08:00
parent e3616a44cc
commit dcb750c318
+10 -1
View File
@@ -203,9 +203,18 @@
- 原因:`useProjectResourceCardPreviews``resources` 入参**不只喂热预取**,它同时决定返回的 `identityByResourceId`;而 `ProjectDevelopmentView``renderResourceBookCard` 在身份缺失时直接 `return null`。所以「把 `resources` 换成当前栏目」看起来只是缩小预热范围,实际把身份 map 一起收窄了,总览里不在当前栏目的卡片就此不再挂载。技术方案明确要求「主画布展示各子画布的缩略入口,内部按资源类型显示有限层叠卡片……主画布预览和子画布展开态复用同一套卡片视觉」,因此这是产品回归,不是可接受的行为变更。
- 处理:**把「身份 / 渲染口径」与「热预取口径」拆成两个入参**——`resources` 保持全量资源投影不变(决定 `identityByResourceId`、缓存与卡片挂载),新增 `eagerResources` 只用于 `eagerPreviewLimit` 计数的热预取,缺省回退 `resources`。两个入参的语义写进 `useProjectResourceCardPreviews` 的参数注释,调用方 `index.tsx` 也在传参处注明「收窄 `resources` 会让其它栏目只剩标题栏」。**不要**改用「身份未知时用 idle 占位兜底渲染」:那会让总览卡片失去真实预览,观感更差。
- 通用规则:凡 Hook 的某个入参同时参与「身份 / 缓存 key」与「调度 / 预热」,就不能为了优化调度去收窄它。先确认这个入参还有没有别的消费者,再决定是拆参数还是加参数;同理适用于今后任何「只预热一部分」的优化。
- 验证:`apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts``uses one full-page canvas per resource section with dependency-only guide lines` 会断言非当前栏目的 `.game-resource-book-scene-card` 内存在 `.game-resource-card``tests/useProjectResourceCardPreviews.test.ts` 覆盖 `eagerResources` 缺省回退到 `resources` 的语义。
- 验证:**首选证据**是 `apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts``mounts a real card body in every non-empty resource section overview`——它自带 manifest 把 `character` / `audio` / `document` / `unclassified` / `version` 五个栏目同时做成非空,逐栏目断言 `.game-resource-book-scene-card[data-resource-book-category=…]` 内存在 `.game-resource-card` 本体,并用卡片的 `data-resource-card-id` 回查投影结果确认卡片确实落在被断言的栏目;把 `resources` 改回收窄值后该用例失败,是这条坑的**变异验证**。同文件既有的 `uses one full-page canvas per resource section with dependency-only guide lines` 会断言非当前栏目的 `.game-resource-book-scene-card` 内存在 `.game-resource-card`,但只覆盖到一两个栏目`tests/useProjectResourceCardPreviews.test.ts` 覆盖 `eagerResources` 缺省回退到 `resources` 的语义。
- 关联:`apps/ai-game-creator-shell/src/view/project-development/useProjectResourceCardPreviews.ts``apps/ai-game-creator-shell/src/view/project-development/index.tsx``apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts``docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`
## manifest 资产分类字段写错名会被静默忽略,跨层字段名相近时尤其危险(2026-09-11)
- 现象:给 manifest 资产写 `assetCategory: 'document'` 不报错、不告警,但被**静默忽略**:分类回落到按 `kind` 派生,而 `design-document` / `game-code` 这类 kind 又不在 canonical 目录里,于是资产全部落在「待归类」栏目,「文档」栏目为空。表现上完全像「分类没生效 / 分区轴坏了」,实际只是字段名写错了层。
- 原因:manifest 上的字段名是 **`category`**`packages/shared/src/contracts/gameCreationApp.ts``GameCreationAppAssetManifestEntry.category`),派生入口 `gameCreationAppAssetCategory()` 只读 `asset.category``assetCategory` 是**前端投影之后** `ProjectResource` 的字段名(`resourceProjectionModel.ts``projectResourceAssetCategory``resource.assetCategory ?? 'unclassified'`)。两个名字长得像但**属于不同层**,TypeScript 也拦不住——往 manifest 对象上多写一个未知字段不会报错。
- 处理:写 manifest 夹具或任何 manifest 内容时,**只认契约里声明的字段名**;需要确认字段名时直接查契约类型定义,不要按前端投影层的字段名反推。断言「分类生效」时必须**同时**确认该 `kind` 是 canonical,否则会得到「看起来像分类失败、其实是字段名写错 + kind 非 canonical」的双重误导——这次定位额外花掉的时间就在这一步。
- 通用规则:**跨层字段名相近时,静默忽略比报错更危险**。给数据层加字段前先确认它落在哪一层、哪一端才是权威读取方;发现「设置无效但没有任何报错」时,第一优先怀疑字段名 / 层级错配,而不是下游逻辑或渲染。
- 验证:`apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts``mounts a real card body in every non-empty resource section overview` 自带 manifest 并显式写 `category`,五个栏目同时非空即证明字段名与层级正确。
- 关联:`packages/shared/src/contracts/gameCreationApp.ts``apps/ai-game-creator-shell/src/view/project-development/resourceProjectionModel.ts``apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts`
## 依赖线与资源卡不在同一 transform 层时会在滚动和缩放中分离
- 现象:静止时依赖线似乎对齐,触摸板缩放或连续滚动后线段会追赶、漂移或忽隐忽现;某一资源分区的长线还可能出现在相邻分区。