This commit is contained in:
2026-04-27 22:50:18 +08:00
parent ded6f6ee2a
commit b6c6640548
77 changed files with 5240 additions and 833 deletions

View File

@@ -150,3 +150,86 @@ npm run typecheck -- --pretty false
```
以上局部测试、局部 ESLint 与全量类型检查已通过。后端代码未在本轮修改中触碰,因此仍不需要执行 `npm run api-server:maincloud`
## 2026-04-27 第四轮复查修正
用户复测后仍出现“进入作品测试没有显示幕配置角色”。本轮继续沿真实结果页入口复查,确认前几轮的第一幕解析已经覆盖 `oppositeNpcId -> primaryNpcId -> encounterNpcIds`,但作品测试入口仍可能在进入选角前拿到旧 profile。
定位结论:
1. 结果页展示和自动保存期望消费 `session.resultPreview.preview`,或者在缺少 resultPreview 时消费 `draftProfile.legacyResultProfile`
2. `rpgCreationPreviewAdapter.buildPreviewFromSession()` 原先优先规范化 `session.draftProfile`,会把基础草稿骨架当成运行态 profile。
3. 当基础草稿骨架与结果页预览中的 `sceneChapterBlueprints`、角色、第一幕对面角色不一致时,作品测试即使后续严格读取第一幕,也会读取到旧世界数据。
本轮修正:
1. `src/services/rpg-creation/rpgCreationPreviewAdapter.ts`
- 结果页 profile 解析顺序调整为:`session.resultPreview.preview -> draftProfile.legacyResultProfile -> draftProfile`
- 作品测试、结果页展示和自动保存使用同一份当前结果页 profile避免选角后加载旧草稿骨架。
2. `src/services/rpg-creation/rpgCreationPreviewAdapter.test.ts`
- 覆盖 `resultPreview.preview` 优先于 `draftProfile`
- 覆盖缺少 resultPreview 时回退到 `draftProfile.legacyResultProfile`
3. `src/components/rpg-entry/useRpgCreationEnterWorld.test.tsx`
- 将作品测试入口断言改为使用“结果页当前 profile”保证入口语义与 UI 展示一致。
本轮语义补齐为:结果页点“作品测试”后,先用当前结果页 profile 进入角色选择;选完角色后再直接加载该 profile 的开局场景第一幕,并把第一幕 `oppositeNpcId` 作为对面 NPC 启动聊天。
验证命令:
```bash
npm test -- --run src/services/rpg-creation/rpgCreationPreviewAdapter.test.ts src/components/rpg-entry/useRpgCreationEnterWorld.test.tsx src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx src/hooks/useGameFlow.customWorld.test.tsx src/data/sceneEncounterPreviews.test.ts src/hooks/rpg-runtime-story/storyChoiceRuntime.test.ts src/data/customWorldLibrary.test.ts
npx eslint src/services/rpg-creation/rpgCreationPreviewAdapter.ts src/services/rpg-creation/rpgCreationPreviewAdapter.test.ts src/components/rpg-entry/useRpgCreationEnterWorld.test.tsx src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx src/hooks/useGameFlow.customWorld.test.tsx src/data/sceneEncounterPreviews.ts src/data/sceneEncounterPreviews.test.ts src/hooks/rpg-runtime-story/storyChoiceRuntime.ts src/hooks/rpg-runtime-story/storyChoiceRuntime.test.ts src/data/customWorldLibrary.ts src/data/customWorldLibrary.test.ts src/data/scenePresets.ts src/services/customWorldSceneActRuntime.ts src/hooks/rpg-session/useRpgSessionBootstrap.ts src/services/customWorldRoleReferences.ts src/services/big-fish-gallery/bigFishGalleryClient.ts
npm run typecheck -- --pretty false
npm run check:encoding
```
以上相关测试、局部 ESLint、全量类型检查与编码检查均通过。后端代码未在本轮修改中触碰因此未执行 `npm run api-server:maincloud`
## 2026-04-27 第五轮误导链路闭口
第四轮修复后,继续清理会误导后续迭代的旧入口:
1. `src/services/rpg-creation/rpgCreationPreviewAdapter.ts`
- 删除普通 `draftProfile -> CustomWorldProfile` 兜底。
- Agent 结果页 profile 只允许来自 `session.resultPreview.preview`,或缺少 resultPreview 时来自明确的 `draftProfile.legacyResultProfile` 兼容快照。
- 基础 `draftProfile` 不再能被静默当作运行态 profile避免作品测试再次读到旧草稿骨架。
2. `src/hooks/rpg-session/useRpgSessionBootstrap.ts`
- 自定义世界选角后的开局状态已经显式构造第一幕 encounter 时,直接返回开局状态。
- 不再把自定义世界开局交给 `ensureSceneEncounterPreview()` 二次推断,避免旧的友好 NPC / 场景预览链路覆盖第一幕 `oppositeNpcId`
3. `src/components/rpg-entry/useRpgCreationEnterWorld.ts``src/components/rpg-entry/useRpgCreationResultAutosave.ts`
- 移除“只读 session.draftProfile / draftProfile 是真相源”这类已经误导本次排查的注释。
- 明确作品测试读取当前结果页 profile不静默回退到基础 draftProfile。
闭口后的主链路:结果页 profile -> 作品测试选角 -> 第一章第一幕 -> `oppositeNpcId` encounter。普通场景预览只作为非自定义世界或非开局场景的兜底不再参与作品测试开局第一幕的角色裁决。
补充闭口:
1. Agent 结果页作品测试与发布入口要求存在当前结果页 profile。
2. 若当前结果页 profile 缺失,入口直接停止,不再使用 `generatedCustomWorldProfile` 旧内存态兜底。
## 2026-04-27 第六轮入口引用与测试态收口
用户复测后再次出现“进入后没有正确显示幕配置角色,且没有进入聊天状态”。本轮继续把问题压回作品测试真实入口,确认前几轮在标准 `oppositeNpcId` 写法下可以正确进入聊天,但真实生成数据可能把第一幕角色引用写成运行时 NPC 形态,例如 `character-npc-角色id`,或混用角色 id、名称、标题、角色职责文本。旧引用解析只覆盖了部分标准形态导致第一幕 encounter 解析失败后,运行态会退回普通开局剧情或其他场景角色,自然也不会进入该幕 NPC 聊天。
本轮修正:
1. `src/services/customWorldRoleReferences.ts`
- 角色引用归一化新增 `character-npc-*``npc-*``story-*``playable-*` 等运行时/草稿前缀剥离。
- 角色别名新增“职责+姓名”“姓名+职责”等组合,兼容生成器把 `role` 文本写入幕槽位的情况。
2. `src/hooks/rpg-session/useRpgSessionBootstrap.ts`
- 第一幕候选 NPC 解析在进入优先队列前先通过当前 profile 统一归一化。
- 跳过当前玩家角色时,不再只比较 `character.id`,而是同时用角色引用解析比较 id/name避免玩家本人被 `oppositeNpcId` 的别名误判为对面 NPC。
- 自定义世界作品测试进入选择世界与选角后的运行态明确标记 `runtimeMode: 'test'``runtimePersistenceDisabled: true`,避免作品测试被普通游玩存档/自动保存链路污染。
3. `src/hooks/useGameFlow.customWorld.test.tsx`
- 增加复现测试:当第一幕 `oppositeNpcId` 写成 `character-npc-story-act-only` 时,选角后仍必须命中陆衡,并由陆衡主动进入聊天。
- 增加作品测试态断言,确保测试入口不参与普通持久化。
补充验证命令:
```bash
npm test -- --run src/hooks/useGameFlow.customWorld.test.tsx src/hooks/rpg-runtime-story/useRpgRuntimeStoryController.test.tsx
npx eslint src/hooks/rpg-session/useRpgSessionBootstrap.ts src/hooks/useGameFlow.customWorld.test.tsx src/services/customWorldRoleReferences.ts
npm run typecheck -- --pretty false
```
以上测试、ESLint 与类型检查已通过。后端代码未在本轮修改中触碰,因此仍不需要执行 `npm run api-server:maincloud`