This commit is contained in:
@@ -0,0 +1,369 @@
|
||||
# 当前工程优化点盘点(2026-04-20)
|
||||
|
||||
更新时间:`2026-04-20`
|
||||
|
||||
## 0. 盘点目标
|
||||
|
||||
这份文档用于回答一个更直接的问题:
|
||||
|
||||
**基于当前仓库状态,接下来最值得投入工程时间的优化点是什么。**
|
||||
|
||||
本轮只做文档盘点,不直接修改业务代码;结论同时参考了当前工作区现状。
|
||||
需要注意,仓库当前存在一批未提交改动,尤其集中在 `custom world`、`assets`、`platform shell` 相关模块,所以本文更强调“优先级与切入方式”,而不是要求做大范围整仓改写。
|
||||
|
||||
---
|
||||
|
||||
## 1. 当前快照
|
||||
|
||||
## 1.1 本轮复核方式
|
||||
|
||||
本轮主要复核了以下内容:
|
||||
|
||||
1. 现有工程优化审计文档与目录索引
|
||||
2. `package.json`、`vite.config.ts`、`.eslintrc.cjs` 等门禁脚本
|
||||
3. 当前前端、后端、脚本目录的大文件热点
|
||||
4. 运行时、鉴权、自定义世界、资产链路的边界实现
|
||||
5. 当前 `typecheck / lint / build` 状态
|
||||
|
||||
---
|
||||
|
||||
## 1.2 当前门禁结果
|
||||
|
||||
| 项目 | 结果 | 当前判断 |
|
||||
| --- | --- | --- |
|
||||
| `npm run typecheck` | 失败 | 当前第一优先级问题,类型基线已失真 |
|
||||
| `npm run lint:eslint` | 失败 | `136` 个 error、`4` 个 warning,且 `95` 个可自动修复 |
|
||||
| `npm run build` | 通过 | 发布链路未红,但体积压力仍明显存在 |
|
||||
|
||||
### 关键说明
|
||||
|
||||
当前状态和 `2026-04-10` 那轮“build warning 直接拦截”的状态不同:
|
||||
|
||||
1. **构建现在可以通过。**
|
||||
2. **真正变成第一阻塞项的是 `typecheck` 与 `lint`。**
|
||||
3. **构建虽然通过,但主包、功能包、CSS 体积依然偏重,说明性能类优化仍然值得做。**
|
||||
|
||||
---
|
||||
|
||||
## 1.3 当前热点文件快照
|
||||
|
||||
本轮按源码目录统计的大文件热点如下:
|
||||
|
||||
| 文件 | 当前行数 | 判断 |
|
||||
| --- | --- | --- |
|
||||
| `src/components/CustomWorldEntityEditorModal.tsx` | `6122` | 当前前端最大热点 |
|
||||
| `server-node/src/app.test.ts` | `3568` | 后端测试聚合度过高 |
|
||||
| `server-node/src/modules/assets/characterAssetRoutes.ts` | `2802` | 资产路由职责过重 |
|
||||
| `src/services/ai.ts` | `2432` | 浏览器侧 AI 编排仍然偏重 |
|
||||
| `server-node/src/modules/story/storyActionRoutes.test.ts` | `2402` | 运行时路由测试聚合度过高 |
|
||||
| `src/data/npcInteractions.ts` | `2274` | NPC 规则数据仍然集中 |
|
||||
| `src/prompts/storyPromptBuilders.ts` | `1728` | prompt 构造成为新的复杂度中心 |
|
||||
| `server-node/src/modules/custom-world/runtimeProfile.ts` | `1623` | custom world runtime 编译热点 |
|
||||
| `src/hooks/story/npcEncounterActions.ts` | `1582` | NPC 行动流仍然偏重 |
|
||||
| `src/components/game-shell/PlatformHomeView.tsx` | `1474` | 平台首页壳层继续膨胀 |
|
||||
| `src/components/game-shell/PreGameSelectionFlow.tsx` | `1418` | 前置选择流程职责过多 |
|
||||
| `src/services/customWorld.ts` | `1383` | 自定义世界服务虽然收缩,但仍偏大 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 结论先行
|
||||
|
||||
当前仓库的优化重点,已经不是“继续清旧 Vite 插件链路”或者“继续讨论前后端是否要分离”。
|
||||
|
||||
更准确地说,当前最值得做的优化点已经收敛成四类:
|
||||
|
||||
1. **先恢复可信的工程基线。**
|
||||
`typecheck` 与 `lint` 当前都是红线,继续扩功能会放大返工成本。
|
||||
2. **拆掉正在持续膨胀的新热点。**
|
||||
热点已经从早期运行时主链,迁移到 `custom world`、`asset routes`、`platform shell`、`prompt builders`。
|
||||
3. **继续把前端退出“运行时真相”和“鉴权真相”。**
|
||||
当前前端仍保留本地快照镜像与自动登录凭证持久化。
|
||||
4. **补一轮入口归档,减少疑似孤岛模块和大测试聚合文件。**
|
||||
这部分不一定最急,但会持续拉低仓库可维护性。
|
||||
|
||||
一句话判断:
|
||||
|
||||
**当前最值得投入的不是横向加功能,而是把质量门禁重新拉绿,再把 custom world / asset / platform 这批新复杂度中心拆开。**
|
||||
|
||||
---
|
||||
|
||||
## 3. 优化点清单
|
||||
|
||||
## 3.1 P0:先恢复类型基线
|
||||
|
||||
这是当前最优先的工程优化点。
|
||||
|
||||
### 证据
|
||||
|
||||
`npm run typecheck` 当前失败,主要问题集中在两类:
|
||||
|
||||
1. `CustomWorldCampScene` 结构漂移
|
||||
- `src/components/CustomWorldEntityEditorModal.test.tsx`
|
||||
- `src/data/customWorldLibrary.ts`
|
||||
- `src/services/customWorld.ts`
|
||||
- `src/services/customWorldCamp.ts`
|
||||
2. 局部实现与类型定义不同步
|
||||
- `src/components/auth/AccountModal.test.tsx` 的测试数据缺少新增字段
|
||||
- `src/components/game-canvas/GameCanvasShared.tsx` 引用了未定义的 `DEFAULT_IMAGE_STYLE`
|
||||
|
||||
### 影响
|
||||
|
||||
1. 类型系统已经不能提供可信回归信号。
|
||||
2. 自定义世界链路当前正在迭代,如果继续在红线状态叠加修改,后续会反复出现“改 A 崩 B”的情况。
|
||||
3. 测试 fixture 与正式类型脱节,会让测试文件逐渐失去文档价值。
|
||||
|
||||
### 建议
|
||||
|
||||
1. 先补一个统一的 `CustomWorldCampScene` 构造/归一化入口,禁止在多个文件里手写不完整字面量。
|
||||
2. 把 `auth`、`custom world` 的测试 fixture 改成工厂函数,避免字段新增后多处漏改。
|
||||
3. 单独清掉 `GameCanvasShared.tsx` 这类“编译即失败”的确定性问题,优先恢复 `typecheck` 绿色基线。
|
||||
|
||||
---
|
||||
|
||||
## 3.2 P0:恢复 lint 可信度,区分机械问题和真实问题
|
||||
|
||||
这项和类型基线同级。
|
||||
|
||||
### 证据
|
||||
|
||||
`npm run lint:eslint` 当前结果是:
|
||||
|
||||
- `136` 个 error
|
||||
- `4` 个 warning
|
||||
- 其中 `95` 个问题可自动修复
|
||||
|
||||
当前 lint 问题明显分成两层:
|
||||
|
||||
1. 机械问题
|
||||
- import 排序
|
||||
- export 排序
|
||||
- 未使用导入
|
||||
2. 真实问题
|
||||
- `server-node/src/modules/inventory/inventoryStoryActionService.ts` 出现 React Hook 规则错误
|
||||
- `server-node/src/migrate.ts` 仍触发 `no-console`
|
||||
- `packages/shared/src/http.ts` 触发 `@typescript-eslint/ban-types`
|
||||
- 若干文件存在真正未使用变量、转义和规则误配问题
|
||||
|
||||
### 影响
|
||||
|
||||
1. 当前 lint 信号噪音仍然较高,不利于 review。
|
||||
2. 真实问题会被大量机械问题掩盖。
|
||||
3. 团队会更倾向于跳过 lint,而不是信任 lint。
|
||||
|
||||
### 建议
|
||||
|
||||
1. 先跑一轮仅机械修复的清理批次,优先吃掉 import sort、unused imports 这类低风险项。
|
||||
2. 再单独处理 Hook 误用、共享契约类型、脚本规则豁免这类语义问题。
|
||||
3. 之后把“自动可修复问题”与“必须人工处理的问题”拆成两个门禁视角,减少下次再次堆积。
|
||||
|
||||
---
|
||||
|
||||
## 3.3 P1:拆 custom world / asset / platform 新热点
|
||||
|
||||
这是当前最有性价比的结构性优化点。
|
||||
|
||||
### 证据
|
||||
|
||||
当前复杂度最高的业务热点,已经集中在这些模块:
|
||||
|
||||
1. `src/components/CustomWorldEntityEditorModal.tsx`
|
||||
2. `server-node/src/modules/assets/characterAssetRoutes.ts`
|
||||
3. `src/services/ai.ts`
|
||||
4. `src/prompts/storyPromptBuilders.ts`
|
||||
5. `server-node/src/modules/custom-world/runtimeProfile.ts`
|
||||
6. `src/components/game-shell/PlatformHomeView.tsx`
|
||||
7. `src/components/game-shell/PreGameSelectionFlow.tsx`
|
||||
8. `src/hooks/story/npcEncounterActions.ts`
|
||||
|
||||
### 问题本质
|
||||
|
||||
这些文件并不是单纯“代码多”,而是同时承载了多类职责:
|
||||
|
||||
1. UI 状态
|
||||
2. 领域规则
|
||||
3. 请求编排
|
||||
4. 文本构造
|
||||
5. 运行时映射
|
||||
6. 面板切换与流程控制
|
||||
|
||||
### 建议
|
||||
|
||||
1. `CustomWorldEntityEditorModal.tsx`
|
||||
- 先按“实体列表/表单区/资源区/高级设置/预览区”拆组件
|
||||
- 再把数据准备与提交编排抽成 hook
|
||||
2. `characterAssetRoutes.ts`
|
||||
- 拆成 route、prompt payload、job orchestration、产物发布、错误响应五层
|
||||
3. `PlatformHomeView.tsx` 与 `PreGameSelectionFlow.tsx`
|
||||
- 把页面壳层、数据加载、卡片渲染、弹层控制拆开
|
||||
4. `storyPromptBuilders.ts` 与 `runtimeProfile.ts`
|
||||
- 把“模板片段”“上下文归一化”“规则裁剪”“最终拼接”分层
|
||||
|
||||
---
|
||||
|
||||
## 3.4 P1:继续控制构建产物体积
|
||||
|
||||
构建虽通过,但体积已经给出明显信号。
|
||||
|
||||
### 当前证据
|
||||
|
||||
本轮 `npm run build` 输出里,几个值得关注的点是:
|
||||
|
||||
1. `dist/assets/AuthenticatedApp-*.js`:`794.77 kB`
|
||||
2. `dist/assets/index-*.js`:`197.44 kB`
|
||||
3. `dist/assets/CustomWorldResultView-*.js`:`163.38 kB`
|
||||
4. `dist/assets/ai-*.js`:`131.73 kB`
|
||||
5. `dist/assets/PreGameSelectionFlow-*.js`:`96.39 kB`
|
||||
6. `dist/assets/index-*.css`:`201.44 kB`
|
||||
|
||||
### 影响
|
||||
|
||||
1. 虽然还没触发新的 build gate 红线,但首屏、缓存和移动端体验会继续承压。
|
||||
2. `AuthenticatedApp` 主包偏大,说明平台壳层仍然装入了过多首屏不必需能力。
|
||||
3. CSS 体积继续上涨,说明样式正在跨模块相互堆叠。
|
||||
|
||||
### 建议
|
||||
|
||||
1. 继续把 custom world、asset studio、平台详情页、角色资产工具从主壳层路径中抽离。
|
||||
2. 审查 `ai.ts`、`custom world result view`、`pregame selection` 是否还能再延迟加载。
|
||||
3. 对全局样式做一次按模块归属清理,减少公共样式无限增长。
|
||||
|
||||
---
|
||||
|
||||
## 3.5 P1:继续收紧前端与后端边界
|
||||
|
||||
这项已经不是“要不要做”的问题,而是“还剩多少尾巴没收完”。
|
||||
|
||||
### 当前证据
|
||||
|
||||
1. `src/services/apiClient.ts`
|
||||
- 当前仍把 `access token`
|
||||
- 自动登录用户名
|
||||
- 自动登录密码
|
||||
写入 `window.localStorage`
|
||||
2. `src/hooks/story/runtimeStoryCoordinator.ts`
|
||||
- 当前仍会在调用后端运行时前先 `putSaveSnapshot(...)`
|
||||
- 响应后继续 `rehydrateSavedSnapshot(...)`
|
||||
3. `src/hooks/story/npcEncounterActions.ts`
|
||||
- 当前仍从前端动作流触发 `generateQuestForNpcEncounter(...)`
|
||||
- 说明 NPC 任务“换单/重抽”分支尚未完全后端化
|
||||
|
||||
### 影响
|
||||
|
||||
1. 前端仍保留了一部分运行时真相与鉴权真相。
|
||||
2. 自动登录凭证持久化在边界和安全上都不理想。
|
||||
3. 运行时快照前置写入,会让“前端镜像状态”和“后端会话状态”继续纠缠。
|
||||
|
||||
### 建议
|
||||
|
||||
1. 优先移除自动登录用户名/密码本地持久化,收敛到服务端 session / refresh 机制。
|
||||
2. 把运行时快照改为“展示缓存”而不是“提交前真相源”。
|
||||
3. 把 NPC 任务更换动作补齐到后端 runtime/session 边界,不再由前端直接发起生成决策。
|
||||
|
||||
---
|
||||
|
||||
## 3.6 P2:做一次疑似孤岛模块与旧入口归档
|
||||
|
||||
这项不一定最紧急,但现在做会明显降低后续维护噪音。
|
||||
|
||||
### 当前现象
|
||||
|
||||
从当前入口关系看,以下模块值得做一次正式复核:
|
||||
|
||||
1. `src/components/GameShell.tsx`
|
||||
2. `src/components/custom-world-home/CustomWorldCreationHub.tsx`
|
||||
3. `src/components/custom-world-home/CustomWorldCreationLauncherModal.tsx`
|
||||
4. `src/components/custom-world-agent/CustomWorldAgentLauncherModal.tsx`
|
||||
5. `src/components/custom-world-agent/CustomWorldAgentDraftDrawer.tsx`
|
||||
6. `src/hooks/story/storyBootstrap.ts`
|
||||
7. `src/hooks/useEquipmentFlow.ts`
|
||||
8. `src/hooks/useForgeFlow.ts`
|
||||
9. `src/hooks/useInventoryFlow.ts`
|
||||
10. `src/services/typewriter.ts`
|
||||
|
||||
### 当前判断
|
||||
|
||||
这批模块不一定全部是垃圾代码,但至少说明一件事:
|
||||
|
||||
**仓库里仍然存在一批“不是正式入口、也没有清晰归档标签”的过渡实现。**
|
||||
|
||||
### 建议
|
||||
|
||||
把这类模块统一分成三类:
|
||||
|
||||
1. 正式保留并接回入口
|
||||
2. 明确标记为实验稿
|
||||
3. 直接归档或删除
|
||||
|
||||
这样可以减少后续开发时的误判成本。
|
||||
|
||||
---
|
||||
|
||||
## 3.7 P2:拆测试聚合文件,恢复测试的定位能力
|
||||
|
||||
当前测试文件也已经出现“大一统热点”。
|
||||
|
||||
### 证据
|
||||
|
||||
1. `server-node/src/app.test.ts`:`3568` 行
|
||||
2. `server-node/src/modules/story/storyActionRoutes.test.ts`:`2402` 行
|
||||
3. `server-node/src/modules/assets/characterAssetRoutes.test.ts`:`1235` 行
|
||||
4. `src/hooks/story/npcEncounterActions.test.ts`:`1199` 行
|
||||
|
||||
### 影响
|
||||
|
||||
1. 失败定位成本高。
|
||||
2. fixture 复用差,字段一变容易整片测试跟着漂移。
|
||||
3. 测试文件本身开始变成新的维护热点。
|
||||
|
||||
### 建议
|
||||
|
||||
1. 按领域动作拆测试文件,而不是继续堆到单一总测文件中。
|
||||
2. 补 fixture builder / factory,减少字面量散落。
|
||||
3. 对 `runtime / auth / custom world / assets` 这几条链路增加更明确的契约测试分层。
|
||||
|
||||
---
|
||||
|
||||
## 4. 推荐执行顺序
|
||||
|
||||
如果只按工程收益排序,建议按下面的顺序推进:
|
||||
|
||||
1. 先修 `typecheck`
|
||||
2. 再把 `lint` 分成机械修复和语义修复两轮
|
||||
3. 然后拆 `custom world / asset / platform` 热点
|
||||
4. 再继续收前端运行时与鉴权边界
|
||||
5. 最后处理孤岛模块归档和测试拆分
|
||||
|
||||
---
|
||||
|
||||
## 5. 当前不建议优先做的事
|
||||
|
||||
1. 不建议在 `typecheck` 和 `lint` 仍为红线时继续横向扩功能。
|
||||
2. 不建议直接在 `CustomWorldEntityEditorModal.tsx`、`characterAssetRoutes.ts`、`PlatformHomeView.tsx` 里继续堆新逻辑。
|
||||
3. 不建议把 bundle 体积问题简单理解为“先放宽阈值”,当前更适合继续拆职责和延迟加载。
|
||||
4. 不建议在未确认入口关系前随手删除可疑旧模块,先做归档分类更稳。
|
||||
|
||||
---
|
||||
|
||||
## 6. 本文依据
|
||||
|
||||
文档依据:
|
||||
|
||||
1. `docs/audits/engineering/README.md`
|
||||
2. `docs/technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md`
|
||||
3. `docs/audits/engineering/ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-20.md`
|
||||
4. `docs/experience/PROJECT_WORK_EXPERIENCE_PLAYBOOK.md`
|
||||
|
||||
当前仓库复核依据:
|
||||
|
||||
1. `package.json`
|
||||
2. `.eslintrc.cjs`
|
||||
3. `vite.config.ts`
|
||||
4. `scripts/build-gate.mjs`
|
||||
5. `src/App.tsx`
|
||||
6. `src/services/apiClient.ts`
|
||||
7. `src/hooks/story/runtimeStoryCoordinator.ts`
|
||||
8. `src/hooks/story/npcEncounterActions.ts`
|
||||
9. 当前源码大文件体量扫描结果
|
||||
10. `npm run typecheck`
|
||||
11. `npm run lint:eslint`
|
||||
12. `npm run build`
|
||||
@@ -0,0 +1,606 @@
|
||||
# 工程清理与后端边界审计(2026-04-19)
|
||||
|
||||
更新时间:`2026-04-20`
|
||||
|
||||
## 0.1 执行回填(2026-04-19)
|
||||
|
||||
本文审计项 `3.2` 与 `4.4` 已于 `2026-04-19` 当日完成首轮处置:
|
||||
|
||||
1. 已删除 `scripts/dev-server/localApiPlugins.ts`
|
||||
2. 已删除 `scripts/dev-server/characterAssetStudioPlugins.ts`
|
||||
3. 已删除 `scripts/dev-server/qwenSpriteSheetToolPlugins.ts`
|
||||
4. `scripts/dev-server/` 目录仅保留迁移说明,不再保留旧 Vite 本地 API 实现代码
|
||||
5. 当前正式入口统一为 `scripts/dev-node.mjs + vite proxy + server-node/src/modules/**`
|
||||
|
||||
本文其余段落保留为本次审计时的原始问题快照,用于解释为什么要做这轮删除。
|
||||
|
||||
## 0.2 执行回填(2026-04-19,仓库噪音产物)
|
||||
|
||||
本文审计项 `3.1` 已于 `2026-04-19` 当日完成首轮处置:
|
||||
|
||||
1. 已从版本库删除以下根目录历史扫描/截图产物:
|
||||
- `npc-editor-dom.html`
|
||||
- `npc-editor-shot.png`
|
||||
- `temp-write-check.txt`
|
||||
- `tmp_character_presets_scan.txt`
|
||||
- `tmp_jsx_text_scan.txt`
|
||||
- `tmp_runtime_text_scan.txt`
|
||||
- `tmp_text_candidates.txt`
|
||||
- `tmp_text_candidates_refined.txt`
|
||||
- `tmp_visible_props_scan.txt`
|
||||
- `tmp_volc_seedance_doc.html`
|
||||
2. 已从版本库删除 `scripts/__pycache__/generate-build-tag-similarity.cpython-313.pyc`。
|
||||
3. 已清理本地工作区中的 `.codex-*.log`、`.preview.*`、`npc-editor-console.log` 与 `temp-build-goal-check/`,清理前对应体量约为:
|
||||
- 根目录噪音文件 `60` 个,约 `49.94 MB`
|
||||
- `temp-build-goal-check/` 共 `15620` 个条目,约 `158.85 MB`
|
||||
4. 已补齐 `.gitignore`、`.prettierignore` 与 `.eslintrc.cjs` 的忽略口径,显式覆盖 `tmp_*`、`tmp/`、`npc-editor-*`、`temp-write-check.txt`、`temp-build-goal-check/`、`__pycache__/`。
|
||||
5. `scripts/dev-server/localApiPlugins.ts` 之外的后端边界收口项不在本轮噪音清理范围内,后续继续按本文第二至第四阶段推进。
|
||||
|
||||
## 0.3 执行回填(2026-04-19,运行时边界第一轮收口)
|
||||
|
||||
本文审计项 `4.1` 与 `5.1` 已于 `2026-04-19` 当日完成一轮工程收口:
|
||||
|
||||
1. `RuntimeStoryOptionView` 现在由后端直接附带 `interaction` 元数据。
|
||||
2. `server-node/src/modules/story/runtimeSession.ts` 已成为 runtime option interaction 的唯一构建位置。
|
||||
3. `src/services/runtimeStoryService.ts` 不再根据 `currentEncounter + functionId` 在前端本地重建一份 interaction 映射。
|
||||
4. `/api/custom-world/scene-image` 已补齐服务端 prompt 兜底组装能力,允许前端只提交 `profile + landmark + userPrompt` 上下文。
|
||||
5. `src/services/aiService.ts` 的场景图 SDK 已改为直接调用后端接口,不再为了该链路动态加载 `src/services/ai.ts`。
|
||||
|
||||
## 0.4 执行回填(2026-04-19,自定义世界后端边界第二轮收口)
|
||||
|
||||
本文审计项 `5.2` 与“第三阶段第 4 条:清理 `server-node -> src/**` 的反向依赖”已于 `2026-04-19` 当日完成第二轮工程收口:
|
||||
|
||||
1. `server-node/src/modules/custom-world/` 已新增服务端自持 runtime 模块,承接:
|
||||
- `creator intent` 归一化
|
||||
- `anchorPack / lockState` 推导
|
||||
- custom world framework/profile compile 与 normalize
|
||||
2. `server-node/src/modules/ai/customWorldOrchestrator.ts` 与 `server-node/src/services/customWorldAgentFoundationDraftService.ts` 已不再运行时依赖:
|
||||
- `src/services/customWorld.js`
|
||||
- `src/services/customWorldBuilder.js`
|
||||
- `src/services/customWorldCreatorIntent.js`
|
||||
- `src/types.js`
|
||||
3. `server-node/src/prompts/customWorldPrompts.ts` 已成为后端自持的 custom world prompt source,`scene image` 与 `foundation draft` 相关 builder 不再从前端 `src/prompts/customWorldPrompts.ts` 反向 import。
|
||||
4. 本轮只迁移 prompt source 位置,没有改动任何 custom world 提示词正文,也没有改动功能需求。
|
||||
|
||||
## 0.5 执行回填(2026-04-20,NPC 待接委托正式接取收口)
|
||||
|
||||
本文审计项 `5.3` 已于 `2026-04-20` 完成一轮补充收口:
|
||||
|
||||
1. `src/hooks/story/npcEncounterActions.ts` 中“聊天里的待接委托正式接取”已不再由前端本地直接写入:
|
||||
- `quests`
|
||||
- `runtimeStats.questsAccepted`
|
||||
- `npcChatState.pendingQuestOffer`
|
||||
2. `server-node/src/modules/quest/questStoryActionService.ts` 现在会优先读取服务端快照里已保存的 `pendingQuestOffer.quest`,按当前聊天态中已经展示给玩家的那份委托完成正式接取。
|
||||
3. `server-node/src/modules/story/storyActionService.ts` 已补齐待接委托接取后的聊天态投影:
|
||||
- 保留 NPC 对话展示模式
|
||||
- 清空 `pendingQuestOffer`
|
||||
- 回到既有的三条自由追问建议
|
||||
4. 本轮没有新增任何 runtime functionId,也没有改动任务生成提示词或任务需求,只是把既有“接任务”正式结算权收回到后端。
|
||||
|
||||
## 0.6 执行回填(2026-04-20,NPC 聊天任务草案与浏览器 LLM fallback 收口)
|
||||
|
||||
本文审计项 `5.1` 与 `5.3` 已于 `2026-04-20` 完成一轮补充收口:
|
||||
|
||||
1. `server-node/src/modules/ai/chatOrchestrator.ts` 现在会基于 `NPC chat turn` 的运行时上下文,在后端判断是否触发 `pendingQuestOffer`,并把 quest draft 与引导文案一并回填给前端。
|
||||
2. `src/hooks/story/npcEncounterActions.ts` 不再在 NPC 单轮聊天完成后本地调用 `generateQuestForNpcEncounter(...)` 再决定是否挂出待接委托。
|
||||
3. `src/services/questDirector.ts` 浏览器端在后端失败时不再退回本地 LLM 生成 quest draft,而是直接走 deterministic fallback compile。
|
||||
4. `src/services/runtimeItemAiDirector.ts` 浏览器端在后端失败时不再退回本地 LLM 生成 runtime item intent,而是直接返回 deterministic fallback intents。
|
||||
5. 本轮仍未改动任何业务提示词正文,也没有改动 quest / runtime item 的需求能力面,只是继续清理浏览器里的正式 AI orchestration 残留。
|
||||
|
||||
## 0. 审计目标
|
||||
|
||||
本次审计只回答四类问题:
|
||||
|
||||
1. 项目里哪些内容已经是高置信度的垃圾、临时产物或无入口代码。
|
||||
2. 哪些实现属于双份真相、重复映射或旧链路残留。
|
||||
3. 哪些前端代码仍然承担了应迁移到 Express 后端的职责。
|
||||
4. 哪些文件已经大到会持续拖累迭代效率,需要优先拆分。
|
||||
|
||||
---
|
||||
|
||||
## 1. 结论先行
|
||||
|
||||
当前仓库的主要问题不是“有一些小工具没人用”,而是四类结构性噪音同时存在:
|
||||
|
||||
1. **仓库噪音产物仍然很多。**
|
||||
根目录残留了大量 `.codex-*.log`、`tmp_*`、旧截图/HTML,以及 `temp-build-goal-check/` 这类大体量检查产物,已经不是单个文件层面的脏数据,而是在持续污染工程视野。
|
||||
2. **旧入口和新入口并存,形成了明显的冗余链路。**
|
||||
`scripts/dev-server/localApiPlugins.ts` 已经退出当前正式开发入口,但仍保留了 LLM proxy、JSON 写盘、资产发布等整套旧 Vite 本地 API 机制。
|
||||
3. **前端仍然承载了过多运行时规则与 AI 编排。**
|
||||
`src/services/ai.ts`、`src/services/customWorld.ts`、`src/hooks/story/npcEncounterActions.ts` 这类文件,仍在浏览器里承担 prompt 组装、规则判定、奖励结算、剧情推进等职责。
|
||||
4. **后端边界还没有真正闭合。**
|
||||
`server-node` 虽然已经承接了大量路由和运行时动作,但仍直接 import `src/services/customWorld*.ts` 和 `src/types.ts`,说明后端领域层还没有完全从前端目录中独立出来。
|
||||
|
||||
一句话判断:
|
||||
|
||||
**这轮优先级不该再是继续堆功能,而是先清仓库噪音与无入口孤岛,再把前后端双份真相收口,最后拆新的巨型热点文件。**
|
||||
|
||||
---
|
||||
|
||||
## 2. 本次审计方法与口径
|
||||
|
||||
### 2.1 方法
|
||||
|
||||
本次审计结合了四类证据:
|
||||
|
||||
1. 文档基线:
|
||||
- `docs/audits/engineering/README.md`
|
||||
- `docs/technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md`
|
||||
- `scripts/dev-server/README.md`
|
||||
2. 当前入口核对:
|
||||
- `src/main.tsx`
|
||||
- `src/routing/appRoutes.tsx`
|
||||
- `src/App.tsx`
|
||||
- `package.json`
|
||||
- `server-node/package.json`
|
||||
3. 静态依赖扫描:
|
||||
- 对 `src/`、`server-node/src/`、`packages/shared/src/`、`scripts/` 共 `650` 个 TS/JS 文件做本地依赖图扫描。
|
||||
4. 定向 grep:
|
||||
- 核对旧 dev 插件入口、后端跨层 import、localStorage 使用、运行时快照双写、重复映射代码。
|
||||
|
||||
### 2.2 口径说明
|
||||
|
||||
为避免误判,本次审计明确排除了两类对象:
|
||||
|
||||
1. **包脚本入口**:例如 `scripts/build-gate.mjs`、`scripts/check-encoding.mjs`、`server-node/build.mjs` 这类由 `package.json` 直接执行的脚本,不因“无 import”而判为垃圾。
|
||||
2. **字符串路径消费的资源**:例如 `src/data/itemOverrides.json`、`src/data/monsterOverrides.json` 会被校验脚本和 editor route 以文件路径读取,不按“无 import”处理。
|
||||
|
||||
另外,当前工作区存在未提交改动,因此本次结论以**已纳入当前主链且能确认未接线/重复/越界的内容**为主,不把明显的当日 WIP 文件计入垃圾结论。
|
||||
|
||||
---
|
||||
|
||||
## 3. 高置信度垃圾、临时产物与无入口代码
|
||||
|
||||
## 3.1 仓库噪音产物已经到了需要集中清理的程度
|
||||
|
||||
### 证据
|
||||
|
||||
| 项目 | 当前证据 | 判断 |
|
||||
| ------------------------ | ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- |
|
||||
| 根目录日志/临时文件 | 根目录命中 `60` 个 `.codex-*.log`、`.preview.*`、`tmp_*`、`npc-editor-*`、`temp-write-check.txt`,合计约 `52.36 MB` | 已经不是偶发临时文件,而是长期堆积的开发残留 |
|
||||
| `temp-build-goal-check/` | 当前包含 `15099` 个文件,合计约 `166.56 MB` | 大体量检查产物,应该移出主工程视野 |
|
||||
| Python 缓存 | 当前存在 `scripts/__pycache__/` | 纯缓存产物,不应长期留在仓库工作区中 |
|
||||
|
||||
### 影响
|
||||
|
||||
1. 根目录信噪比明显下降,真实工程文件被大量一次性产物淹没。
|
||||
2. `temp-build-goal-check/` 虽然已被 `.gitignore` 和 `vite.config.ts` 的 watch 忽略模式覆盖,但 `.eslintrc.cjs` 的 `ignorePatterns` 里没有对应口径,仍存在工具口径不一致问题。
|
||||
3. 这类目录会持续干扰检索、review、lint 判断和本地扫描速度。
|
||||
|
||||
### 建议
|
||||
|
||||
1. 把根目录临时日志、扫描 txt/html、旧截图统一迁到单独的 `tmp/` 或本地缓存目录,默认不留在仓库根目录。
|
||||
2. 把 `temp-build-goal-check/` 改成真正的外置检查产物目录,或者在 lint/脚本口径上一起排除。
|
||||
3. 清理 `scripts/__pycache__/`,并统一补上 Python 缓存忽略规则。
|
||||
|
||||
---
|
||||
|
||||
## 3.2 旧 Vite 本地 API 插件链已经退出主入口,但仍保留整套旧实现
|
||||
|
||||
### 证据
|
||||
|
||||
1. `scripts/dev-server/README.md` 已明确写明:`scripts/dev-server/**` 不再是当前开发入口,只保留为迁移参考。
|
||||
2. `scripts/dev-server/localApiPlugins.ts` 当前仍有 `1664` 行。
|
||||
3. 仓库内已经找不到 `localApiPlugins` 的实际代码入口引用,当前只剩文档引用。
|
||||
4. 该文件内部仍然同时定义和拼装:
|
||||
- `createLlmProxyPlugin`
|
||||
- `createJsonFileEditorPlugin`
|
||||
- `createCustomWorldSceneImagePlugin`
|
||||
- `createCharacterVisualPublishPlugin`
|
||||
- `createCharacterAnimationPublishPlugin`
|
||||
- `createCharacterAssetStudioPlugins`
|
||||
- `createQwenSpriteSheetToolPlugins`
|
||||
|
||||
### 判断
|
||||
|
||||
这不是“一个小工具暂时没用”,而是**整条旧 editor/assets 本地 API 链路仍然完整保留在仓库里**。它在工程上已经属于高置信度的历史残留。
|
||||
|
||||
### 建议
|
||||
|
||||
1. 如果只保留迁移证据,建议把 `scripts/dev-server/localApiPlugins.ts` 和相关说明迁到 `docs/reference/` 或单独的 `archive/` 目录。
|
||||
2. 如果确实还要保留参考代码,至少要在文件顶部加更强的“只读参考、禁止继续扩展”标识,并从主工程扫描面上进一步隔离。
|
||||
3. 不建议继续在这条旧链路里新增任何 `/api/*` 能力。
|
||||
|
||||
---
|
||||
|
||||
## 3.3 当前存在一批“无运行时入口”或“仅测试引用”的孤岛模块
|
||||
|
||||
### 高置信度无入口/仅测试引用清单
|
||||
|
||||
| 模块 | 证据 | 判断 |
|
||||
| --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
|
||||
| `src/components/GameShell.tsx` | 文件体量 `761` 行;当前 `src/App.tsx` 只接入 `components/game-shell/GameShellRuntime.tsx`;仓库内无其它 import | 旧版壳层残留 |
|
||||
| `src/components/custom-world-home/CustomWorldCreationHub.tsx` | 仅被 `CustomWorldCreationHub.test.tsx` 和 `CustomWorldCreationHub.interaction.test.tsx` 引用;`src/routing/appRoutes.tsx` 只有 `game` 和 `qwen-sprite-tool` 两条路由 | 已做出 UI,但未进入正式入口 |
|
||||
| `src/components/custom-world-home/CustomWorldCreationLauncherModal.tsx` | 当前无运行时引用 | 同属未接线入口壳层 |
|
||||
| `src/components/custom-world-agent/*` 中 `9` 个子模块 | 当前合计约 `826` 行;典型文件包括 `CustomWorldAgentLauncherModal.tsx`、`CustomWorldAgentDraftDrawer.tsx`、`CustomWorldAgentLockBar.tsx`、`CustomWorldAgentQuickActions.tsx`、`CustomWorldAgentSummaryPanel.tsx`;部分文件完全无引用,部分仅被测试引用 | 处于“做了一部分 UI,但未进入主链”的孤岛状态 |
|
||||
| `src/hooks/story/storyBootstrap.ts` | `250` 行,仓库内只定义不消费 | 已被新流程替代的可能性高 |
|
||||
| `src/hooks/useEquipmentFlow.ts` / `useForgeFlow.ts` / `useInventoryFlow.ts` | 合计约 `393` 行,当前无运行时引用 | 旧流转层残留 |
|
||||
| `src/editor/shared/cloneValue.ts` / `EditorEmptyState.tsx` / `EditorSelectionCard.tsx` / `useJsonSave.ts` | 当前无运行时引用 | editor 旧共享层碎片 |
|
||||
| `src/services/customWorldPresentation.stub.ts` | 当前无引用,且文件本身就是 stub | 高置信度占位残留 |
|
||||
| `src/services/typewriter.ts` | 当前无引用,仅提供一个 `getTypewriterDelay` | 已被其它链路内联实现替代 |
|
||||
| `src/data/buildTagSimilarity.generated.ts` | 当前 `823` 行,仅能被生成脚本自身检索到,没有消费方 | 生成产物未接入任何业务链路 |
|
||||
| `src/data/customWorldCharacterLoadout.stub.ts` | 当前无引用,且实现只返回空数组 | 占位残留 |
|
||||
| `src/components/DeveloperTeamModal.tsx` / `src/components/LazySkillEffectPreview.tsx` | 当前无运行时引用 | 小体量零散孤岛 |
|
||||
|
||||
### 判断
|
||||
|
||||
这批文件不一定都应该“立刻删除”,但它们已经满足两个至少其一:
|
||||
|
||||
1. 当前正式入口完全不消费。
|
||||
2. 只剩测试在消费,本体没有真实运行时位置。
|
||||
|
||||
所以它们至少都应该进入以下三选一处理:
|
||||
|
||||
1. 立即归档/删除。
|
||||
2. 明确接回正式入口。
|
||||
3. 改名或迁目录,标明“实验稿/参考稿/未接线”身份。
|
||||
|
||||
### 特别提醒
|
||||
|
||||
`src/components/custom-world-home/` 和 `src/components/custom-world-agent/` 这两组文件里,存在**已经有一定 UI 完成度、但没有进入真实路由/流程**的情况。
|
||||
这类文件最危险的点不是体量,而是会让后来者误以为“这块功能已经在主链上”。
|
||||
|
||||
---
|
||||
|
||||
## 4. 冗余实现与双份真相
|
||||
|
||||
## 4.1 Story option interaction 映射在前后端各维护了一份
|
||||
|
||||
### 证据
|
||||
|
||||
1. 前端 `src/services/runtimeStoryService.ts` 的 `buildRuntimeOptionInteraction` 维护了 `npcActionMap`、`treasureActionMap`。
|
||||
2. 后端 `server-node/src/modules/story/storyActionService.ts` 的 `buildStoryOptionInteraction` 维护了几乎同构的一份 `npcActionMap`、`treasureActionMap`。
|
||||
|
||||
### 风险
|
||||
|
||||
1. 任何一个 functionId 增删改,前后端都要同步。
|
||||
2. 一边先改、一边漏改时,表现层和运行时层会出现静默漂移。
|
||||
|
||||
### 建议
|
||||
|
||||
把 interaction/view model 映射收口到后端,前端只消费后端返回的结构,不再根据 `functionId` 本地重建一遍交互语义。
|
||||
|
||||
---
|
||||
|
||||
## 4.2 浏览历史已经有后端接口,但前端仍维护本地真相与迁移状态
|
||||
|
||||
### 证据
|
||||
|
||||
1. `src/components/game-shell/PreGameSelectionFlow.tsx` 中,`appendBrowseHistoryEntry` 先调用 `writePlatformBrowseHistory` 写本地,再调用 `upsertProfileBrowseHistory` 写后端。
|
||||
2. 同文件启动阶段又会先读 `readPlatformBrowseHistory`,再根据 `hasPendingPlatformBrowseHistoryMigration` 把本地历史同步回后端。
|
||||
3. 后端 `server-node/src/routes/runtimeRoutes.ts` 已经提供了 `/profile/browse-history` 路由,而前端 `src/services/storageService.ts` 也已有对应 API SDK。
|
||||
|
||||
### 判断
|
||||
|
||||
当前浏览历史并不是单纯的“本地缓存”,而是**本地存储 + 远端持久化 + 迁移标记**三套状态并存。
|
||||
|
||||
### 建议
|
||||
|
||||
1. 后端结果作为唯一真相源。
|
||||
2. 前端如果要保留缓存,只保留一个明确的 cache wrapper,不再把它做成独立状态系统。
|
||||
3. `markPlatformBrowseHistoryMigrated` 这种迁移标记应尽量在后端一次性收口,而不是长期停留在正式前端逻辑里。
|
||||
|
||||
---
|
||||
|
||||
## 4.3 运行时快照依然由前端先落本地,再与后端会话互相回填
|
||||
|
||||
### 证据
|
||||
|
||||
1. `src/hooks/story/runtimeStoryCoordinator.ts` 在读状态和提交 action 前都会先调用 `putSaveSnapshot`。
|
||||
2. 同文件以及 `src/services/runtimeStoryService.ts` 又会在响应后多次 `rehydrateSavedSnapshot`。
|
||||
3. 这意味着浏览器仍然在“后端 action 之前”先写一份自己的快照解释。
|
||||
|
||||
### 判断
|
||||
|
||||
这条链路说明当前运行时还处在**前端快照解释权没有完全退出**的过渡状态。
|
||||
|
||||
### 建议
|
||||
|
||||
1. 前端逐步退化为 view model 消费层。
|
||||
2. 运行时快照、版本迁移、恢复解释权继续往后端收口。
|
||||
3. 前端保留最小必要的离线展示缓存,但不再成为正式运行时状态真相来源。
|
||||
|
||||
---
|
||||
|
||||
## 4.4 旧 Vite 本地 API 与正式 Express 路由仍然形成重复能力面
|
||||
|
||||
### 证据
|
||||
|
||||
1. `scripts/dev-server/localApiPlugins.ts` 里仍有 JSON 编辑、场景图生成、角色视觉发布、角色动作发布等插件。
|
||||
2. 当前正式路径已经迁到:
|
||||
- `server-node/src/modules/editor/**`
|
||||
- `server-node/src/modules/assets/**`
|
||||
3. `scripts/dev-server/README.md` 已明确说明旧链路只保留为迁移参考。
|
||||
|
||||
### 判断
|
||||
|
||||
这属于典型的**旧能力未删除,新能力已落地,双链路长期并存**。
|
||||
|
||||
### 建议
|
||||
|
||||
尽快把旧 Vite 本地 API 参考实现移出主工程扫描面,避免后续继续被误用或被误认为正式入口。
|
||||
|
||||
---
|
||||
|
||||
## 5. 需要迁移到后端的代码
|
||||
|
||||
## 5.1 `src/services/ai.ts` 仍然承担了过多正式运行时职责
|
||||
|
||||
### 当前职责
|
||||
|
||||
`src/services/ai.ts` 当前约 `2632` 行,仍然同时承担:
|
||||
|
||||
1. function 可用性与 option 构造相关逻辑。
|
||||
2. NPC 对话 / 招募 prompt 构造。
|
||||
3. 自定义世界生成 prompt 与 JSON 修复请求。
|
||||
4. 直接调用 `requestPlainTextCompletion` / `streamPlainTextCompletion`。
|
||||
5. 浏览器内 fallback 与响应解析。
|
||||
|
||||
### 判断
|
||||
|
||||
这不是单纯的“前端请求 SDK”,而是**前端仍在承担正式运行时 AI orchestration**。
|
||||
|
||||
### 建议迁移方向
|
||||
|
||||
1. prompt 组装、模型调用、超时重试、JSON repair 继续收口到 `server-node/src/modules/ai/**`。
|
||||
2. 前端只保留轻量 SDK 和展示态拼装。
|
||||
3. fallback 如果必须保留,也应明确区分“开发兜底”与“正式运行时”。
|
||||
|
||||
---
|
||||
|
||||
## 5.2 `src/services/customWorld.ts` 仍然是前端侧的大型规则中心
|
||||
|
||||
### 当前职责
|
||||
|
||||
`src/services/customWorld.ts` 当前约 `2413` 行,仍然承担:
|
||||
|
||||
1. 世界框架与角色/地标 outline 归一化。
|
||||
2. 世界属性 schema 生成。
|
||||
3. `ownedSettingLayers` 归一化。
|
||||
4. 最终世界 profile 校验。
|
||||
5. fallback story graph/theme pack 生成。
|
||||
|
||||
### 当前越界证据
|
||||
|
||||
后端目前直接从以下文件 import 这些能力:
|
||||
|
||||
1. `server-node/src/modules/ai/customWorldOrchestrator.ts`
|
||||
2. `server-node/src/services/customWorldAgentFoundationDraftService.ts`
|
||||
|
||||
它们仍直接引用:
|
||||
|
||||
1. `src/services/customWorld.js`
|
||||
2. `src/services/customWorldBuilder.js`
|
||||
3. `src/services/customWorldCreatorIntent.js`
|
||||
4. `src/types.js`
|
||||
|
||||
### 判断
|
||||
|
||||
这说明自定义世界的核心领域规则仍然以**前端目录为事实源**,后端只是在反向复用。
|
||||
|
||||
### 建议迁移方向
|
||||
|
||||
1. `types/schema/contracts` 抽到 `packages/shared`。
|
||||
2. 规则编译、校验、fallback 与 AI 编排迁到 `server-node`。
|
||||
3. 前端只保留编辑器表现层和字段草稿态。
|
||||
|
||||
---
|
||||
|
||||
## 5.3 `src/hooks/story/npcEncounterActions.ts` 仍在浏览器里做任务、奖励、战斗与招募结算
|
||||
|
||||
### 当前职责
|
||||
|
||||
`src/hooks/story/npcEncounterActions.ts` 当前约 `1623` 行,仍然直接编排:
|
||||
|
||||
1. `quest_accept` / `quest_turn_in`
|
||||
2. 招募、切磋、离开、帮助奖励
|
||||
3. 掉落/背包写入
|
||||
4. HP / MP / cooldown 奖励变化
|
||||
5. NPC 亲和度变化
|
||||
6. 战斗场景切换与遭遇状态推进
|
||||
|
||||
### 判断
|
||||
|
||||
这条链已经明显超出“前端表现协调层”的边界,仍属于**正式运行时规则在前端执行**。
|
||||
|
||||
### 建议迁移方向
|
||||
|
||||
1. quest 信号推进 -> `server-node/src/modules/quest/**`
|
||||
2. 奖励与背包变更 -> `server-node/src/modules/inventory/**`
|
||||
3. 招募/关系变化 -> `server-node/src/modules/npc/**`
|
||||
4. 战斗结算 -> `server-node/src/modules/combat/**`
|
||||
|
||||
前端应该只保留选项触发、加载态、动画态和最终结果展示。
|
||||
|
||||
---
|
||||
|
||||
## 5.4 `src/services/apiClient.ts` 仍保留了本地 token 与自动登录凭证存储
|
||||
|
||||
### 证据
|
||||
|
||||
`src/services/apiClient.ts` 当前仍把以下内容放在 `window.localStorage`:
|
||||
|
||||
1. access token
|
||||
2. 自动登录用户名
|
||||
3. 自动登录密码
|
||||
|
||||
### 判断
|
||||
|
||||
这既是安全面问题,也是边界问题。
|
||||
在“后端负责鉴权、前端只做表现”的目标下,正式凭证体系不应长期依赖浏览器本地保存账号密码。
|
||||
|
||||
### 建议迁移方向
|
||||
|
||||
1. 正式态优先走服务端 session / HttpOnly cookie。
|
||||
2. 自动登录不要继续保存明文用户名/密码。
|
||||
3. 前端仅保留最小必要的登录态感知,不保留额外认证真相。
|
||||
|
||||
---
|
||||
|
||||
## 6. 需要优先优化和拆分的代码
|
||||
|
||||
## 6.1 `src/components/CustomWorldEntityEditorModal.tsx`
|
||||
|
||||
### 当前状态
|
||||
|
||||
文件体量约 `4487` 行,已同时吞下:
|
||||
|
||||
1. 世界营地编辑
|
||||
2. playable NPC 编辑
|
||||
3. story NPC 编辑
|
||||
4. 地标与世界地图布局
|
||||
5. 场景图生成
|
||||
6. 技能编辑
|
||||
7. 初始物品编辑
|
||||
8. 资产工作台串联
|
||||
9. 多层 modal 开关与保存逻辑
|
||||
|
||||
### 判断
|
||||
|
||||
这是当前前端最明显的“巨型工作台单体文件”。
|
||||
|
||||
### 建议拆分方向
|
||||
|
||||
1. 按实体拆:营地 / playable NPC / story NPC / 地标。
|
||||
2. 按能力拆:基础信息 / 关系 / 技能 / 初始物品 / 视觉资产。
|
||||
3. 把 AI 生成与资产工作流进一步外置成独立 coordinator。
|
||||
|
||||
---
|
||||
|
||||
## 6.2 `server-node/src/modules/assets/characterAssetRoutes.ts`
|
||||
|
||||
### 当前状态
|
||||
|
||||
文件体量约 `3579` 行,已同时承担:
|
||||
|
||||
1. route 注册
|
||||
2. 请求解析
|
||||
3. LLM prompt bundle 生成
|
||||
4. JSON 解析与修复
|
||||
5. 文件系统写盘
|
||||
6. visual publish
|
||||
7. animation publish
|
||||
8. 资产目录管理
|
||||
|
||||
### 直接证据
|
||||
|
||||
文件内同时存在:
|
||||
|
||||
1. `mkdir` / `writeFile`
|
||||
2. `UpstreamLlmClient`
|
||||
3. `parseJsonResponseText`
|
||||
4. 多条 publish 路径
|
||||
5. 大量本地文件落盘逻辑
|
||||
|
||||
### 建议拆分方向
|
||||
|
||||
1. route 层
|
||||
2. prompt bundle service
|
||||
3. file publish service
|
||||
4. animation persistence service
|
||||
5. asset metadata service
|
||||
|
||||
---
|
||||
|
||||
## 6.3 `src/services/ai.ts`
|
||||
|
||||
### 当前状态
|
||||
|
||||
文件体量约 `2632` 行,同时承载运行时 story、自定义世界、NPC 对话、招募等多条链路。
|
||||
|
||||
### 建议
|
||||
|
||||
即使短期内不能全部迁后端,也应该先按职责拆成:
|
||||
|
||||
1. runtime story client
|
||||
2. npc dialogue client
|
||||
3. recruit dialogue client
|
||||
4. custom world generation client
|
||||
5. parser / fallback / error helpers
|
||||
|
||||
---
|
||||
|
||||
## 6.4 `src/services/customWorld.ts`
|
||||
|
||||
### 当前状态
|
||||
|
||||
文件体量约 `2413` 行,已经变成世界生成、校验、归一化、fallback 的综合体。
|
||||
|
||||
### 建议
|
||||
|
||||
至少拆成:
|
||||
|
||||
1. 世界框架与 outline schema
|
||||
2. profile normalize / validate
|
||||
3. role / landmark 编译器
|
||||
4. fallback builder
|
||||
5. world rule helpers
|
||||
|
||||
---
|
||||
|
||||
## 6.5 `src/hooks/story/npcEncounterActions.ts`
|
||||
|
||||
### 当前状态
|
||||
|
||||
文件体量约 `1623` 行,已经不是单纯 hook,而是前端运行时 action resolver。
|
||||
|
||||
### 建议
|
||||
|
||||
按动作域拆开:
|
||||
|
||||
1. npc chat / recruit
|
||||
2. npc help / affinity
|
||||
3. quest accept / turn-in
|
||||
4. battle entry / exit
|
||||
5. async streaming / typewriter / presentation glue
|
||||
|
||||
---
|
||||
|
||||
## 7. 推荐执行顺序
|
||||
|
||||
### 第一阶段:先清仓库噪音和旧入口残留
|
||||
|
||||
1. 清根目录日志、扫描文件、旧截图、`__pycache__`
|
||||
2. 迁出 `temp-build-goal-check/`
|
||||
3. 明确处置 `scripts/dev-server/localApiPlugins.ts`
|
||||
|
||||
### 第二阶段:再处理无入口孤岛模块
|
||||
|
||||
1. 逐个确认 `GameShell.tsx`、custom-world-home、custom-world-agent、旧 flow hooks 是要接回还是归档
|
||||
2. 对确认不再使用的 stub / helper / generated dead file 直接清理
|
||||
|
||||
### 第三阶段:把双份真相收口
|
||||
|
||||
1. runtime option interaction 映射只保留一份
|
||||
2. 浏览历史以后端为真相源
|
||||
3. 运行时快照解释权继续后移
|
||||
4. 清理 `server-node -> src/**` 的反向依赖
|
||||
|
||||
### 第四阶段:最后拆巨型热点文件
|
||||
|
||||
1. `CustomWorldEntityEditorModal.tsx`
|
||||
2. `characterAssetRoutes.ts`
|
||||
3. `ai.ts`
|
||||
4. `customWorld.ts`
|
||||
5. `npcEncounterActions.ts`
|
||||
|
||||
---
|
||||
|
||||
## 8. 本文依据
|
||||
|
||||
文档依据:
|
||||
|
||||
1. `docs/audits/engineering/README.md`
|
||||
2. `docs/technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md`
|
||||
3. `scripts/dev-server/README.md`
|
||||
|
||||
当前仓库扫描依据:
|
||||
|
||||
1. `src/main.tsx`
|
||||
2. `src/routing/appRoutes.tsx`
|
||||
3. `src/App.tsx`
|
||||
4. `package.json`
|
||||
5. `server-node/package.json`
|
||||
6. `vite.config.ts`
|
||||
7. `.eslintrc.cjs`
|
||||
8. `git grep` 对关键模块引用、后端跨层 import、localStorage、旧 dev 插件入口的扫描结果
|
||||
@@ -0,0 +1,382 @@
|
||||
# 工程清理与后端边界复核审计(2026-04-20)
|
||||
|
||||
更新时间:`2026-04-20`
|
||||
|
||||
## 0. 审计目标
|
||||
|
||||
这份文档不是重复 `2026-04-19` 的原始扫描,而是基于当前仓库状态做一轮复核,重点回答三个问题:
|
||||
|
||||
1. 昨天审计里已经提出的问题,哪些今天已经真正落地。
|
||||
2. 哪些结论在当前代码里仍然成立,哪些表述需要纠正。
|
||||
3. 当前工程热点和边界问题有没有发生迁移。
|
||||
|
||||
---
|
||||
|
||||
## 1. 结论先行
|
||||
|
||||
和 `2026-04-19` 那份基线相比,当前仓库已经有一批明确进展:
|
||||
|
||||
1. **旧 Vite 本地 API 链路已经真正出清。**
|
||||
`scripts/dev-server/` 当前只剩一份 `README.md`,旧的 `localApiPlugins.ts`、角色资产插件、精灵表插件都不在仓库里了。
|
||||
2. **根目录噪音产物已经清理完成。**
|
||||
当前根目录临时日志/扫描产物扫描结果为空,`temp-build-goal-check/` 也不存在。
|
||||
3. **`server-node -> src/**` 反向依赖已经收掉。**
|
||||
当前复核没有再发现 `server-node/src/**` 直接 import 前端 `src/**` 的情况。
|
||||
4. **runtime option interaction 已经收口成后端单一真相。**
|
||||
这部分现在由 `server-node/src/modules/story/runtimeSession.ts` 统一构造,前端 `src/services/runtimeStoryService.ts` 不再本地再建一份映射表。
|
||||
|
||||
但这不代表边界问题已经结束,当前剩余问题主要集中在三块:
|
||||
|
||||
1. **前端仍保留运行时镜像与登录凭证本地真相。**
|
||||
`runtimeStoryCoordinator.ts` 仍会先写本地快照,`apiClient.ts` 仍把 token/自动登录凭证放在 `localStorage`。
|
||||
2. **NPC 聊天任务链路还没有完全后端化。**
|
||||
“聊天后挂出待接委托”已经移到后端,但“更换待接委托”这条分支仍由前端 `npcEncounterActions.ts` 触发 `generateQuestForNpcEncounter(...)`。
|
||||
3. **未接线孤岛和热点文件问题仍然明显。**
|
||||
一批 UI/Hook/Prompt 残留模块还没有正式入口;同时热点已经从已删除的旧插件链路,转移到 `CustomWorldEntityEditorModal.tsx`、`storyPromptBuilders.ts`、`runtimeProfile.ts`、`PreGameSelectionFlow.tsx`、`PlatformHomeView.tsx` 等新中心。
|
||||
|
||||
一句话判断:
|
||||
|
||||
**当前仓库已经完成“清垃圾、拆旧入口、切断后端反向依赖”的第一阶段,但还没有完成“前端退出运行时真相”和“未接线孤岛归档”的第二阶段。**
|
||||
|
||||
---
|
||||
|
||||
## 2. 已完成项复核
|
||||
|
||||
## 2.1 旧 dev-server 链路已经不是“逻辑上废弃”,而是“代码上删除”
|
||||
|
||||
### 当前证据
|
||||
|
||||
| 项目 | 当前状态 | 结论 |
|
||||
| --- | --- | --- |
|
||||
| `scripts/dev-server/` | 当前只剩 `README.md` 一份说明文件 | 旧 Vite 本地 API 链路已从仓库代码层出清 |
|
||||
| `scripts/dev-server/README.md` | 已明确声明当前正式入口为 `scripts/dev-node.mjs + server-node/src/modules/**` | 文档与代码状态一致 |
|
||||
|
||||
### 结论
|
||||
|
||||
`2026-04-19` 文档里关于旧本地 API 插件链路的清理结论,在当前仓库里已经可以确认成立,不再只是“计划删除”。
|
||||
|
||||
---
|
||||
|
||||
## 2.2 根目录噪音产物已经从当前工作区移除
|
||||
|
||||
### 当前证据
|
||||
|
||||
| 项目 | 当前状态 | 结论 |
|
||||
| --- | --- | --- |
|
||||
| 根目录历史日志/扫描产物 | 本轮扫描结果为空 | 之前的 `.codex-*.log`、`tmp_*`、旧截图/HTML 不再占据当前工作区 |
|
||||
| `temp-build-goal-check/` | 当前不存在 | 大体量检查产物已移出当前仓库视野 |
|
||||
|
||||
### 结论
|
||||
|
||||
`2026-04-19` 文档中关于“仓库噪音产物”的问题,在当前工作区层面已经完成首轮治理。
|
||||
这部分不再是当前工程第一优先级。
|
||||
|
||||
---
|
||||
|
||||
## 2.3 `server-node -> src/**` 反向依赖已清零
|
||||
|
||||
### 当前证据
|
||||
|
||||
本轮用脚本复核 `server-node/src/**` 中所有 `import` 后,当前结果为:
|
||||
|
||||
`NO_DIRECT_SERVER_TO_FRONTEND_SRC_IMPORTS`
|
||||
|
||||
同时,仓库里已经看不到类似下面这类旧反向依赖:
|
||||
|
||||
1. `server-node -> src/services/customWorld.js`
|
||||
2. `server-node -> src/services/customWorldBuilder.js`
|
||||
3. `server-node -> src/services/customWorldCreatorIntent.js`
|
||||
4. `server-node -> src/types.js`
|
||||
|
||||
### 结论
|
||||
|
||||
`2026-04-19` 文档里“清理 `server-node -> src/**` 反向依赖”的阶段性目标,在当前仓库里已经真正落地。
|
||||
|
||||
---
|
||||
|
||||
## 2.4 runtime option interaction 已经收口到后端
|
||||
|
||||
### 当前证据
|
||||
|
||||
1. `server-node/src/modules/story/runtimeSession.ts` 当前仍保留 `buildOptionInteraction(...)`,负责构造:
|
||||
- `npcActionMap`
|
||||
- `treasureActionMap`
|
||||
2. `src/services/runtimeStoryService.ts` 当前只做:
|
||||
- 直接读取 `option.interaction`
|
||||
- 把后端返回的 interaction 投影成 `StoryOption`
|
||||
3. 前端文件里已经找不到旧的 `buildRuntimeOptionInteraction` / `npcActionMap` / `treasureActionMap` 实现。
|
||||
|
||||
### 结论
|
||||
|
||||
这项收口已经成立,当前不会再出现“前后端各维护一份 interaction 映射表”的旧问题。
|
||||
|
||||
---
|
||||
|
||||
## 2.5 浏览器端的 quest/runtime item 本地 LLM fallback 已移除
|
||||
|
||||
### 当前证据
|
||||
|
||||
1. `src/services/questDirector.ts`
|
||||
- 浏览器路径先请求 `/api/runtime/quests/generate`
|
||||
- 后端失败时只走 deterministic fallback compile
|
||||
2. `src/services/runtimeItemAiDirector.ts`
|
||||
- 浏览器路径先请求 `/api/runtime/items/runtime-intent`
|
||||
- 后端失败时只返回 deterministic fallback intents
|
||||
3. 这两个文件虽然仍保留 `requestChatMessageContent(...)` 分支,但那是非浏览器分支,不再是浏览器端正式兜底链路。
|
||||
|
||||
### 结论
|
||||
|
||||
`2026-04-19` 文档里关于“浏览器本地 LLM fallback”这部分,当前应更新为:
|
||||
|
||||
**浏览器端本地 LLM fallback 已移除,但这两个模块仍然是双环境混合实现,还没有彻底后端化。**
|
||||
|
||||
---
|
||||
|
||||
## 3. 需要纠正的旧文档表述
|
||||
|
||||
## 3.1 NPC 任务链路不是“全部后端化”,而是“挂单已后移、换单仍前触发”
|
||||
|
||||
### 需要纠正的点
|
||||
|
||||
`2026-04-19` 文档中的回填里有一条表述是:
|
||||
|
||||
“`src/hooks/story/npcEncounterActions.ts` 不再在 NPC 单轮聊天完成后本地调用 `generateQuestForNpcEncounter(...)` 再决定是否挂出待接委托。”
|
||||
|
||||
### 当前代码状态
|
||||
|
||||
这句话对“聊天后挂出待接委托”这条主链是成立的,因为当前后端 `server-node/src/modules/ai/chatOrchestrator.ts` 已经会回填 `pendingQuestOffer`。
|
||||
|
||||
但它对整条 NPC 任务链路来说并不完整,因为当前前端仍保留这条分支:
|
||||
|
||||
1. `src/hooks/story/npcEncounterActions.ts`
|
||||
2. `replacePendingNpcQuestOffer()`
|
||||
3. `generateQuestForNpcEncounter(...)`
|
||||
|
||||
也就是:
|
||||
|
||||
**待接委托的“正式挂出”已后端化,但“更换委托”仍然由前端动作流发起。**
|
||||
|
||||
### 当前应改成的结论
|
||||
|
||||
更准确的描述应该是:
|
||||
|
||||
1. NPC 单轮聊天里“是否挂出待接委托”的决定权已收回后端。
|
||||
2. 但待接委托的“换单/重抽”分支仍通过前端 `npcEncounterActions.ts -> questDirector.ts` 发起。
|
||||
|
||||
---
|
||||
|
||||
## 4. 当前仍然成立的遗留问题
|
||||
|
||||
## 4.1 未接线/仅测试引用孤岛模块仍然明显
|
||||
|
||||
本轮依赖图复核后,当前仍能确认一批高置信度孤岛模块:
|
||||
|
||||
| 模块 | 当前状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `src/components/GameShell.tsx` | `765` 行,无运行时引用 | 旧版壳层残留仍在 |
|
||||
| `src/components/custom-world-home/CustomWorldCreationHub.tsx` | `161` 行,仅测试引用 | UI 已有完成度,但仍未进入正式入口 |
|
||||
| `src/components/custom-world-home/CustomWorldCreationLauncherModal.tsx` | `147` 行,无运行时引用 | 未接线入口壳层 |
|
||||
| `src/components/custom-world-agent/CustomWorldAgentLauncherModal.tsx` | `91` 行,无运行时引用 | agent UI 孤岛仍在 |
|
||||
| `src/components/custom-world-agent/CustomWorldAgentDraftDrawer.tsx` | `116` 行,无运行时引用 | agent UI 孤岛仍在 |
|
||||
| `src/hooks/story/storyBootstrap.ts` | `250` 行,无运行时引用 | 旧 bootstrap hook 仍未归档 |
|
||||
| `src/hooks/useEquipmentFlow.ts` | `134` 行,无运行时引用 | 旧 flow hook 残留 |
|
||||
| `src/hooks/useForgeFlow.ts` | `159` 行,无运行时引用 | 旧 flow hook 残留 |
|
||||
| `src/hooks/useInventoryFlow.ts` | `100` 行,无运行时引用 | 旧 flow hook 残留 |
|
||||
| `src/services/customWorldPresentation.stub.ts` | `55` 行,无运行时引用 | 占位 stub 仍在 |
|
||||
| `src/services/typewriter.ts` | `7` 行,无运行时引用 | 小型 helper 残留 |
|
||||
| `src/prompts/customWorldOrchestratorPrompts.ts` | `9` 行,无运行时引用 | prompt source 已迁走后留下的孤岛 |
|
||||
| `src/prompts/storyOrchestratorPrompts.ts` | `6` 行,无运行时引用 | prompt source 已迁走后留下的孤岛 |
|
||||
| `src/data/buildTagSimilarity.generated.ts` | `823` 行,无运行时引用 | 生成产物未接入正式业务链路 |
|
||||
|
||||
### 说明
|
||||
|
||||
`src/data/itemOverrides.json`、`src/data/monsterOverrides.json` 这类文件虽然没有 import 引用,但会被脚本和 editor route 以路径消费,所以不计入垃圾判断。
|
||||
|
||||
### 结论
|
||||
|
||||
仓库已经完成“删旧插件”,但还没有完成“清未接线孤岛”。
|
||||
当前这批模块应该进入明确处置表:
|
||||
|
||||
1. 直接归档/删除
|
||||
2. 正式接回入口
|
||||
3. 改名/迁目录,标记为实验稿
|
||||
|
||||
---
|
||||
|
||||
## 4.2 前端仍保留运行时镜像真相
|
||||
|
||||
### 当前证据
|
||||
|
||||
1. `src/hooks/story/runtimeStoryCoordinator.ts`
|
||||
- 仍会在读状态和提交动作前先 `putSaveSnapshot(...)`
|
||||
- 仍会在响应后多次 `rehydrateSavedSnapshot(...)`
|
||||
2. `src/services/runtimeStoryService.ts`
|
||||
- 仍对响应快照做 `rehydrateSavedSnapshot(...)`
|
||||
|
||||
### 结论
|
||||
|
||||
当前运行时已经不是“前端主算”,但仍然是:
|
||||
|
||||
**前端先写一份本地镜像,再和后端会话互相回填。**
|
||||
|
||||
这说明前端还没有完全退出正式运行时状态解释层。
|
||||
|
||||
---
|
||||
|
||||
## 4.3 前端仍保留本地登录凭证真相
|
||||
|
||||
### 当前证据
|
||||
|
||||
`src/services/apiClient.ts` 当前仍把以下内容写入 `window.localStorage`:
|
||||
|
||||
1. `ACCESS_TOKEN_KEY`
|
||||
2. `AUTO_AUTH_USERNAME_KEY`
|
||||
3. `AUTO_AUTH_PASSWORD_KEY`
|
||||
|
||||
对应代码仍包括:
|
||||
|
||||
1. `window.localStorage.getItem(...)`
|
||||
2. `window.localStorage.setItem(...)`
|
||||
3. `window.localStorage.removeItem(...)`
|
||||
|
||||
### 结论
|
||||
|
||||
这一点和“前端只做表现、后端负责鉴权”的目标仍然不一致。
|
||||
尤其是自动登录用户名/密码继续存本地,风险和边界问题都还在。
|
||||
|
||||
---
|
||||
|
||||
## 4.4 quest/runtime item 仍是双环境混合实现
|
||||
|
||||
### 当前证据
|
||||
|
||||
1. `src/services/questDirector.ts`
|
||||
- 浏览器路径走 `requestJson('/api/runtime/quests/generate')`
|
||||
- 非浏览器路径仍有 `requestChatMessageContent(...)`
|
||||
2. `src/services/runtimeItemAiDirector.ts`
|
||||
- 浏览器路径走 `requestJson('/api/runtime/items/runtime-intent')`
|
||||
- 非浏览器路径仍有 `requestChatMessageContent(...)`
|
||||
3. `src/hooks/story/npcEncounterActions.ts`
|
||||
- 当前仍 import `generateQuestForNpcEncounter`
|
||||
- `replacePendingNpcQuestOffer()` 仍会调用它
|
||||
|
||||
### 结论
|
||||
|
||||
浏览器兜底已经收掉,但模块职责仍然是混合的:
|
||||
|
||||
1. 同一个文件同时承担前端 SDK 和非浏览器编排逻辑
|
||||
2. NPC 换单动作仍由前端发起服务调用
|
||||
|
||||
这部分还不能算真正后端化完成。
|
||||
|
||||
---
|
||||
|
||||
## 4.5 `src/services/ai.ts` 仍然是浏览器端正式 AI orchestration 热点
|
||||
|
||||
### 当前证据
|
||||
|
||||
`src/services/ai.ts` 当前约 `2608` 行,仍直接使用:
|
||||
|
||||
1. `requestChatMessageContent`
|
||||
2. `requestPlainTextCompletion`
|
||||
3. `streamPlainTextCompletion`
|
||||
|
||||
### 结论
|
||||
|
||||
这说明浏览器侧的大型 AI orchestration 仍然没有真正退出主工程。
|
||||
虽然部分链路已经迁走,但整体边界还没有收完。
|
||||
|
||||
---
|
||||
|
||||
## 5. 当前热点已经发生迁移
|
||||
|
||||
## 5.1 当前主要大文件快照
|
||||
|
||||
| 文件 | 当前行数 | 判断 |
|
||||
| --- | --- | --- |
|
||||
| `src/components/CustomWorldEntityEditorModal.tsx` | `4898` | 仍是前端最大热点 |
|
||||
| `server-node/src/modules/assets/characterAssetRoutes.ts` | `3181` | 仍是后端资产链路最大热点 |
|
||||
| `src/services/ai.ts` | `2608` | 浏览器 AI orchestration 热点仍在 |
|
||||
| `src/data/npcInteractions.ts` | `2409` | 仍是大型规则数据中心 |
|
||||
| `server-node/src/services/customWorldAgentFoundationDraftService.ts` | `1902` | custom world agent 后端热点上升 |
|
||||
| `src/prompts/storyPromptBuilders.ts` | `1882` | prompt source 已成为新的前端热点 |
|
||||
| `server-node/src/modules/custom-world/runtimeProfile.ts` | `1735` | custom world runtime 编译中心已转到后端 |
|
||||
| `src/components/game-shell/PreGameSelectionFlow.tsx` | `1547` | 平台/入口流程热点上升 |
|
||||
| `src/components/game-shell/PlatformHomeView.tsx` | `1522` | 平台首页热点上升 |
|
||||
| `src/services/customWorld.ts` | `1489` | 仍然大,但已明显缩小 |
|
||||
| `src/hooks/story/npcEncounterActions.ts` | `1434` | 仍然是前端 action 热点 |
|
||||
|
||||
---
|
||||
|
||||
## 5.2 热点变化判断
|
||||
|
||||
和 `2026-04-19` 相比,当前热点不是单纯“没变”,而是出现了明显迁移:
|
||||
|
||||
1. `characterAssetRoutes.ts` 从 `3579` 行降到 `3181` 行,说明资产路由已经有过一轮拆分,但仍然偏大。
|
||||
2. `src/services/customWorld.ts` 从 `2413` 行降到 `1489` 行,说明自定义世界规则已拆出一部分。
|
||||
3. `src/hooks/story/npcEncounterActions.ts` 从 `1623` 行降到 `1434` 行,说明 NPC 运行时逻辑也有收口。
|
||||
4. 新的复杂度中心开始转移到:
|
||||
- `src/prompts/storyPromptBuilders.ts`
|
||||
- `server-node/src/modules/custom-world/runtimeProfile.ts`
|
||||
- `src/components/game-shell/PreGameSelectionFlow.tsx`
|
||||
- `src/components/game-shell/PlatformHomeView.tsx`
|
||||
|
||||
### 结论
|
||||
|
||||
当前问题已经不再是“原来的热点完全没动”,而是:
|
||||
|
||||
**部分旧热点正在缩小,但复杂度正在向 prompt source、custom world runtime profile、平台入口壳层继续迁移。**
|
||||
|
||||
---
|
||||
|
||||
## 6. 最新建议执行顺序
|
||||
|
||||
### 第一阶段:先清理当前仍明确无入口的孤岛
|
||||
|
||||
1. 处理 `GameShell.tsx`
|
||||
2. 处理 `custom-world-home/*`
|
||||
3. 处理 `custom-world-agent/*`
|
||||
4. 处理 `storyBootstrap.ts`、`useEquipmentFlow.ts`、`useForgeFlow.ts`、`useInventoryFlow.ts`
|
||||
5. 处理已脱钩的 `src/prompts/*OrchestratorPrompts.ts`
|
||||
|
||||
### 第二阶段:再收运行时和鉴权真相
|
||||
|
||||
1. 收掉 `runtimeStoryCoordinator.ts` 的本地快照前置写入
|
||||
2. 收掉 `apiClient.ts` 中的自动登录用户名/密码本地持久化
|
||||
3. 优先把 token/session 统一到服务端鉴权边界
|
||||
|
||||
### 第三阶段:补完 NPC 任务链路的后端化
|
||||
|
||||
1. 把“更换待接委托”从 `npcEncounterActions.ts -> questDirector.ts` 继续迁到后端
|
||||
2. 把 `questDirector.ts` / `runtimeItemAiDirector.ts` 拆成明确的后端服务与前端 SDK 两层
|
||||
|
||||
### 第四阶段:最后拆新热点
|
||||
|
||||
1. `CustomWorldEntityEditorModal.tsx`
|
||||
2. `characterAssetRoutes.ts`
|
||||
3. `storyPromptBuilders.ts`
|
||||
4. `runtimeProfile.ts`
|
||||
5. `PreGameSelectionFlow.tsx`
|
||||
6. `PlatformHomeView.tsx`
|
||||
|
||||
---
|
||||
|
||||
## 7. 本文依据
|
||||
|
||||
文档依据:
|
||||
|
||||
1. `docs/audits/engineering/ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-19.md`
|
||||
2. `docs/audits/engineering/README.md`
|
||||
3. `docs/technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md`
|
||||
|
||||
当前仓库复核依据:
|
||||
|
||||
1. `scripts/dev-server/README.md`
|
||||
2. `server-node/src/modules/story/runtimeSession.ts`
|
||||
3. `src/services/runtimeStoryService.ts`
|
||||
4. `src/hooks/story/runtimeStoryCoordinator.ts`
|
||||
5. `src/hooks/story/npcEncounterActions.ts`
|
||||
6. `src/services/questDirector.ts`
|
||||
7. `src/services/runtimeItemAiDirector.ts`
|
||||
8. `src/services/apiClient.ts`
|
||||
9. 当前依赖图扫描结果与当前大文件体量扫描结果
|
||||
@@ -0,0 +1,141 @@
|
||||
# 工程死分支清理执行记录 A(2026-04-21)
|
||||
|
||||
更新时间:`2026-04-21`
|
||||
|
||||
## 0. 本批次目标
|
||||
|
||||
这份记录对应:
|
||||
|
||||
- `docs/planning/ENGINEERING_DEAD_CODE_AND_HIDDEN_BRANCH_CLEANUP_PLAN_2026-04-21.md`
|
||||
- 其中的 `P0 + 批次 A`
|
||||
|
||||
本批次只做一件事:
|
||||
|
||||
**先清理高置信度、低耦合、无正式入口的小型孤岛与残留壳子。**
|
||||
|
||||
这批对象有一个共同特征:
|
||||
|
||||
1. 当前没有正式运行时引用
|
||||
2. 没有当前主链计划要接回
|
||||
3. 删除后有明确替代路径,或者本身只是历史占位
|
||||
|
||||
因此这批次不碰运行时真相链、不碰鉴权链、不碰任务物品主链,只先做低风险去噪。
|
||||
|
||||
---
|
||||
|
||||
## 1. 本批次已处理对象
|
||||
|
||||
## 1.1 已删除文件
|
||||
|
||||
| 文件 | 判定 | 删除原因 | 替代路径 / 当前真相源 | 验证口径 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `src/services/customWorldPresentation.stub.ts` | 无引用占位 stub | 文件本身就是占位实现,且正式逻辑已由 `customWorldPresentation.ts` 承接 | `src/services/customWorldPresentation.ts` | 符号级检索确认正式调用方都指向正式实现 |
|
||||
| `src/services/typewriter.ts` | 无引用 helper 残留 | 独立 helper 已失效,正式链路已在 `storyPresentation.ts` / `storyRenderingHelpers.ts` 等处内联或迁移 | `src/hooks/story/storyPresentation.ts`、`src/hooks/story/storyRenderingHelpers.ts` | `getTypewriterDelay` 调用点未指向该文件 |
|
||||
| `src/prompts/customWorldOrchestratorPrompts.ts` | 前端孤岛 prompt 壳 | 当前无正式 import,正式主编排 prompt 已收口到后端 prompt 目录,前端 `ai.ts` 也保留自己的现行实现 | `server-node/src/prompts/customWorldOrchestratorPrompts.ts`、`src/services/ai.ts` | 全仓检索仅剩文档引用,无代码消费 |
|
||||
| `src/prompts/storyOrchestratorPrompts.ts` | 前端孤岛 prompt 壳 | 当前无正式 import,剧情语言修复 prompt 已由后端 prompt 目录承接,前端当前执行路径不依赖该文件 | `server-node/src/prompts/storyOrchestratorPrompts.ts`、`src/services/ai.ts` | 全仓检索仅剩文档引用,无代码消费 |
|
||||
| `src/components/custom-world-home/CustomWorldCreationLauncherModal.tsx` | 无入口 UI 壳层 | 最近两轮工程审计都确认无运行时引用,当前平台主流程未接这条入口 | 当前平台正式入口链 | 文件级检索确认无组件 import |
|
||||
| `src/components/custom-world-agent/CustomWorldAgentLauncherModal.tsx` | 无入口 UI 壳层 | Agent 创作主流程已切到当前工作区链路,这个旧 modal 没有接线价值 | 当前 Agent 工作区主链 | 文件级检索确认无组件 import |
|
||||
| `src/components/custom-world-agent/CustomWorldAgentDraftDrawer.tsx` | 无入口 UI 壳层 | 只有孤立 UI 实现,没有正式调用链,也不在当前结果页 / 工作区主链中 | 当前 Agent 工作区与结果页正式链 | 文件级检索确认无组件 import |
|
||||
|
||||
---
|
||||
|
||||
## 2. 本批次为什么先删这 7 个
|
||||
|
||||
这批文件适合先处理,不是因为它们最大,而是因为它们最清晰:
|
||||
|
||||
1. **没有正式入口。**
|
||||
本轮检索没有发现主工程 import。
|
||||
2. **删除后不会形成职责空洞。**
|
||||
要么已有正式替代路径,要么本身只是历史占位。
|
||||
3. **不会误伤当前重点链路。**
|
||||
这批不涉及运行时快照、鉴权、任务、物品、AI 正式编排主链。
|
||||
4. **可以最快降低目录噪音。**
|
||||
先把真假并存的壳子删掉,后面做批次 B/C/D 时判断成本会更低。
|
||||
|
||||
---
|
||||
|
||||
## 3. 本批次暂不处理对象
|
||||
|
||||
以下对象虽然已进入首轮台账,但本批次暂不删除:
|
||||
|
||||
1. `src/components/GameShell.tsx`
|
||||
2. `src/components/custom-world-home/CustomWorldCreationHub.tsx`
|
||||
3. `src/hooks/story/storyBootstrap.ts`
|
||||
4. `src/hooks/useEquipmentFlow.ts`
|
||||
5. `src/hooks/useForgeFlow.ts`
|
||||
6. `src/hooks/useInventoryFlow.ts`
|
||||
7. `src/data/buildTagSimilarity.generated.ts`
|
||||
|
||||
暂缓原因分别是:
|
||||
|
||||
1. 仍属于旧主流程 / 旧 flow 级别对象,删除前要先核对更多历史依赖和替代路径
|
||||
2. 部分对象仍有测试引用或更大的上下文耦合
|
||||
3. `buildTagSimilarity.generated.ts` 虽无正式业务 import,但属于生成产物,处理前还要确认脚本链与文档链
|
||||
|
||||
这批对象更适合进入:
|
||||
|
||||
1. `批次 B:旧 flow / 旧 shell / 旧 hook`
|
||||
2. 或独立的数据产物复核批次
|
||||
|
||||
---
|
||||
|
||||
## 4. 本批次同步更新的文档
|
||||
|
||||
本批次除了删文件,还同步做了文档回填:
|
||||
|
||||
1. 新增本执行记录,说明本批删了什么、为什么删、哪些对象暂缓
|
||||
2. 更新 `docs/audits/engineering/README.md`,把这份执行记录加入当前审计入口
|
||||
|
||||
这样做的目的,是避免再次出现:
|
||||
|
||||
1. 代码删了
|
||||
2. 但审计入口还是旧状态
|
||||
3. 后续开发又从旧清单里重复判断一遍
|
||||
|
||||
---
|
||||
|
||||
## 5. 验证方式
|
||||
|
||||
本批次验证采用两层口径:
|
||||
|
||||
## 5.1 删除前验证
|
||||
|
||||
1. 文件级检索确认无正式 import
|
||||
2. 符号级检索确认关键导出没有被主链消费
|
||||
3. 结合 `2026-04-20` 工程审计交叉确认这些对象已被标记为高置信度孤岛
|
||||
|
||||
## 5.2 删除后验证
|
||||
|
||||
建议至少执行:
|
||||
|
||||
1. `npm run check:encoding`
|
||||
2. `npm run build`
|
||||
|
||||
说明:
|
||||
|
||||
- 当前仓库已知 `typecheck` 与 `lint` 仍处于红线阶段,因此本批不把它们作为“由本批引入的新失败”判断口径
|
||||
- 本批主要验证目标是:删除小残留后,不产生新的导入断裂和构建断裂
|
||||
|
||||
---
|
||||
|
||||
## 6. 本批次结果判断
|
||||
|
||||
本批次完成后,工程至少获得了 3 个直接收益:
|
||||
|
||||
1. `src/prompts/`、`src/services/`、`src/components/custom-world-*` 中少了一批无入口孤岛
|
||||
2. 当前目录里“看起来像正式入口,其实已经废弃”的误导性对象减少
|
||||
3. 后续可以把精力集中到真正高价值的批次 B/C/D,而不是继续被小残留分散判断成本
|
||||
|
||||
---
|
||||
|
||||
## 7. 下一批建议
|
||||
|
||||
建议严格按计划继续往下推进:
|
||||
|
||||
1. 批次 B:`GameShell`、`storyBootstrap`、`useEquipmentFlow`、`useForgeFlow`、`useInventoryFlow`
|
||||
2. 批次 C:`runtimeStoryCoordinator`、`runtimeStoryService`、`apiClient`
|
||||
3. 批次 D:`npcEncounterActions`、`questDirector`、`runtimeItemAiDirector`、`ai.ts`
|
||||
|
||||
一句话总结本批次:
|
||||
|
||||
**先把最确定的死分支和占位壳子清掉,让主工程少一些假入口、假主源、假能力,再进入更重的主链收口。**
|
||||
@@ -0,0 +1,145 @@
|
||||
# 工程死分支清理执行记录 B(2026-04-21)
|
||||
|
||||
更新时间:`2026-04-21`
|
||||
|
||||
## 0. 本批次目标
|
||||
|
||||
这份记录对应清洗计划中的:
|
||||
|
||||
- `批次 B:旧 flow / 旧 shell / 旧 hook`
|
||||
|
||||
本批次聚焦的不是小型 stub,而是:
|
||||
|
||||
**已经退出正式主流程、但仍占着高辨识度命名和旧职责心智的壳层与流程 Hook。**
|
||||
|
||||
这类文件如果继续留在仓库里,问题比小 helper 更大,因为它们会持续制造误判:
|
||||
|
||||
1. 新人会以为它们还是正式入口
|
||||
2. 后续开发会误判“应该往这里接逻辑”
|
||||
3. review 时会多出一层“旧主链是不是还活着”的判断成本
|
||||
|
||||
---
|
||||
|
||||
## 1. 本批次已处理对象
|
||||
|
||||
## 1.1 已删除文件
|
||||
|
||||
| 文件 | 判定 | 删除原因 | 替代路径 / 当前真相源 | 验证口径 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `src/components/GameShell.tsx` | 旧主流程壳层残留 | 当前正式壳层已由 `src/components/game-shell/GameShellRuntime.tsx` 承接,旧文件无正式 import | `src/components/game-shell/GameShellRuntime.tsx`、`src/hooks/useGameShellRuntime.ts` | 全仓检索未发现对旧 `GameShell` 组件的正式消费 |
|
||||
| `src/hooks/story/storyBootstrap.ts` | 旧启动流程 Hook 残留 | 当前主剧情启动链已不再调用该 Hook,继续保留只会误导人以为它还是故事初始化入口 | 当前 story runtime / coordinator 链 | 全仓检索未发现 `useStoryBootstrap` 消费方 |
|
||||
| `src/hooks/useEquipmentFlow.ts` | 旧装备流程 Hook 残留 | 当前正式背包与装备链未消费该 Hook,属于旧流程实现残留 | 当前 inventory / runtime 正式链 | 符号级检索仅命中定义文件自身 |
|
||||
| `src/hooks/useForgeFlow.ts` | 旧锻造流程 Hook 残留 | 当前正式锻造入口未通过该 Hook 进入主链,保留会制造旧流程错觉 | 当前 inventory / runtime 正式链 | 符号级检索仅命中定义文件自身 |
|
||||
| `src/hooks/useInventoryFlow.ts` | 旧背包使用流程 Hook 残留 | 当前主流程未消费该 Hook,属于旧状态推进实现残留 | 当前 inventory / runtime 正式链 | 符号级检索仅命中定义文件自身 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 为什么这批要紧跟批次 A 处理
|
||||
|
||||
批次 A 清掉的是“小型假入口”。
|
||||
|
||||
批次 B 清掉的是“高辨识度旧主链”。
|
||||
|
||||
这批必须紧跟着做,原因是:
|
||||
|
||||
1. 它们虽然比 stub 更大,但引用关系同样清楚
|
||||
2. 它们的误导性比小残留更强
|
||||
3. 不先处理这批,后面做批次 C/D 时,很容易继续有人拿旧 flow Hook 当候选接线点
|
||||
|
||||
一句话讲:
|
||||
|
||||
**批次 A 是去噪,批次 B 是拔掉旧路牌。**
|
||||
|
||||
---
|
||||
|
||||
## 3. 本批次删除后的结构变化
|
||||
|
||||
本批次完成后,仓库里的流程心智会更清楚:
|
||||
|
||||
1. 游戏壳层正式入口继续收敛到 `src/components/game-shell/**`
|
||||
2. 旧 `GameShell.tsx` 不再和 `GameShellRuntime.tsx` 并存
|
||||
3. 旧的装备 / 锻造 / 背包单独 flow Hook 不再伪装成还在生效的正式实现
|
||||
4. 旧 `storyBootstrap` 不再和当前 story runtime 链并存
|
||||
|
||||
这会直接减少两类误判:
|
||||
|
||||
1. “是不是还有旧主流程没迁完”
|
||||
2. “我是不是应该把新逻辑继续补进这些旧 Hook”
|
||||
|
||||
---
|
||||
|
||||
## 4. 本批次暂不处理对象
|
||||
|
||||
虽然批次 B 已经处理了旧 shell / old flow / old bootstrap,但以下对象仍暂缓:
|
||||
|
||||
1. `src/components/custom-world-home/CustomWorldCreationHub.tsx`
|
||||
2. `src/data/buildTagSimilarity.generated.ts`
|
||||
3. 批次 C 的运行时真相链:
|
||||
- `src/hooks/story/runtimeStoryCoordinator.ts`
|
||||
- `src/services/runtimeStoryService.ts`
|
||||
- `src/services/apiClient.ts`
|
||||
4. 批次 D 的混合执行层:
|
||||
- `src/hooks/story/npcEncounterActions.ts`
|
||||
- `src/services/questDirector.ts`
|
||||
- `src/services/runtimeItemAiDirector.ts`
|
||||
- `src/services/ai.ts`
|
||||
|
||||
暂缓原因很明确:
|
||||
|
||||
1. 这些对象要么仍在当前正式链上
|
||||
2. 要么涉及运行时真相与鉴权边界
|
||||
3. 不能按“无引用旧壳”同一口径直接删除
|
||||
|
||||
---
|
||||
|
||||
## 5. 本批次验证方式
|
||||
|
||||
## 5.1 删除前验证
|
||||
|
||||
1. 全仓检索 `GameShell` 旧组件消费方,确认当前正式壳层已切到 `game-shell/` 目录
|
||||
2. 全仓检索 `useStoryBootstrap`
|
||||
3. 全仓检索旧装备 / 锻造 / 背包 flow Hook 导出的 handler 名称
|
||||
4. 交叉确认当前正式主链入口已存在替代实现
|
||||
|
||||
## 5.2 删除后验证
|
||||
|
||||
建议至少执行:
|
||||
|
||||
1. `npm run check:encoding`
|
||||
2. `npm run build`
|
||||
|
||||
如果这两项通过,说明:
|
||||
|
||||
1. 删除没有引入新的导入断裂
|
||||
2. 主工程构建链仍然成立
|
||||
|
||||
---
|
||||
|
||||
## 6. 本批次结果判断
|
||||
|
||||
本批次完成后,工程获得的直接收益是:
|
||||
|
||||
1. 旧主流程壳层不再和现行壳层并存
|
||||
2. 旧流程 Hook 不再占据 `src/hooks/` 的主路径注意力
|
||||
3. 当前正式入口和历史残留的边界更清楚
|
||||
4. 后续开发更不容易把新逻辑接回旧流程壳子
|
||||
|
||||
---
|
||||
|
||||
## 7. 下一批建议
|
||||
|
||||
建议下一步进入真正有结构价值的收口:
|
||||
|
||||
1. `批次 C:运行时真相收口`
|
||||
- `runtimeStoryCoordinator`
|
||||
- `runtimeStoryService`
|
||||
- `apiClient`
|
||||
2. `批次 D:任务 / 物品 / AI 混合执行层收口`
|
||||
- `npcEncounterActions`
|
||||
- `questDirector`
|
||||
- `runtimeItemAiDirector`
|
||||
- `ai.ts`
|
||||
|
||||
一句话总结本批次:
|
||||
|
||||
**这一步不是在“删几个没用 Hook”,而是在把已经退场的旧主流程壳层和旧 flow 路牌从主工程里真正拔掉,让现行架构不再和历史壳子并排站着。**
|
||||
@@ -0,0 +1,241 @@
|
||||
# 工程死分支清理执行记录 C(2026-04-21)
|
||||
|
||||
更新时间:`2026-04-21`
|
||||
|
||||
## 0. 本批次目标
|
||||
|
||||
这份记录对应清洗计划中的:
|
||||
|
||||
- `批次 C:运行时真相收口`
|
||||
|
||||
但这次不是“一口气把运行时真相链全删干净”,而是先做其中最明确、风险最低、最不该继续拖的那一段:
|
||||
|
||||
1. **收掉前端本地自动登录用户名 / 密码真相**
|
||||
2. **把登录恢复改成优先依赖服务端 session / refresh**
|
||||
|
||||
同时,这一批也明确记录了一件事:
|
||||
|
||||
**运行时快照前置写入链当前还不能直接砍。**
|
||||
|
||||
原因不是“不想动”,而是服务端当前 `runtime story` 动作入口仍然以远端快照作为执行基线。
|
||||
在后端 contract 没先改好之前,前端不能假装自己已经退出这条链。
|
||||
|
||||
---
|
||||
|
||||
## 1. 本批次已处理对象
|
||||
|
||||
## 1.1 已收口的鉴权链
|
||||
|
||||
| 文件 | 处理动作 | 本批结论 |
|
||||
| --- | --- | --- |
|
||||
| `src/services/apiClient.ts` | 删除本地自动登录用户名 / 密码存取逻辑 | 前端不再保存 auto auth 账号密码 |
|
||||
| `src/services/authService.ts` | 去掉对本地游客凭证的读写依赖 | 自动游客登录改为仅本次生成凭证,不再长期落本地 |
|
||||
| `src/components/auth/AuthGate.tsx` | 去掉“必须先有本地 access token 才尝试恢复”的前置假设 | 登录恢复改为优先尝试服务端 `getCurrentAuthUser()` / refresh session |
|
||||
| `src/services/authService.test.ts` | 改写游客自动登录相关断言 | 验证改为“生成临时凭证并完成登录”,而不是“落本地账号密码” |
|
||||
| `src/components/auth/AuthGate.test.tsx` | 改写登录恢复 mock | 验证改为“先尝试服务端会话恢复,再决定是否走游客兜底” |
|
||||
|
||||
---
|
||||
|
||||
## 2. 本批次为什么先做这段
|
||||
|
||||
这批优先级高,是因为它同时满足 4 条:
|
||||
|
||||
1. **风险明确。**
|
||||
浏览器保存自动登录用户名 / 密码,本身就不符合“前端只做表现、后端负责鉴权真相”的方向。
|
||||
2. **替代路径已经存在。**
|
||||
后端已经有 refresh session cookie 与 `getCurrentAuthUser()`,不是没有可替代能力。
|
||||
3. **改动边界清楚。**
|
||||
这一段主要落在前端鉴权恢复逻辑和测试,不会直接波及运行时战斗、任务、物品、剧情主链。
|
||||
4. **收益直接。**
|
||||
一旦收掉,前端就少了一份最不该长期保留的高风险真相。
|
||||
|
||||
一句话讲:
|
||||
|
||||
**这一步先把“浏览器记住游客账号密码再重登”这条假真相链拔掉。**
|
||||
|
||||
---
|
||||
|
||||
## 3. 本批次明确没做的事
|
||||
|
||||
## 3.1 没有直接删除 `runtimeStoryCoordinator.ts` 里的前置 `putSaveSnapshot(...)`
|
||||
|
||||
这不是漏做,而是明确暂缓。
|
||||
|
||||
当前复核结果是:
|
||||
|
||||
1. `server-node/src/modules/story/storyActionService.ts`
|
||||
2. `server-node/src/routes/runtimeRoutes.ts`
|
||||
3. `server-node/src/repositories/runtimeRepository.ts`
|
||||
|
||||
这条后端链当前仍然通过远端快照读取运行时状态,再执行:
|
||||
|
||||
1. `getRuntimeStoryState`
|
||||
2. `resolveRuntimeStoryAction`
|
||||
|
||||
也就是说,当前真实情况不是“前端多写了一份完全没用的镜像”,而是:
|
||||
|
||||
**前端在提交动作前先把当前状态写回远端快照,后端再基于这份快照执行业务动作。**
|
||||
|
||||
在这个 contract 没先升级为“前端只发 action,后端自己持有完整 session 真相”之前,前端不能直接把这一步砍掉。
|
||||
|
||||
否则会出现:
|
||||
|
||||
1. 动作请求仍在走
|
||||
2. 但服务端读取到的执行基线不完整
|
||||
3. 最后不是收口真相,而是把主链打断
|
||||
|
||||
## 3.2 没有删除 `runtimeStoryService.ts` / `runtimeStoryCoordinator.ts` 的快照再水合逻辑
|
||||
|
||||
这一步本轮也做了复核,结论是:
|
||||
|
||||
1. 我曾尝试把 `runtimeStoryCoordinator.ts` 中对服务端返回快照的重复再水合去掉
|
||||
2. 但对应的 `runtimeStoryCoordinator` 测试立即暴露出:当前后端返回的快照在部分战斗场景下还不是完整水合态
|
||||
3. 说明前端当前这层再水合仍然有现实职责,不是纯多余代码
|
||||
|
||||
所以这一步本批明确结论是:
|
||||
|
||||
**暂不删除,等后端快照 contract 先补完整后再做。**
|
||||
|
||||
---
|
||||
|
||||
## 4. 本批次验证结果
|
||||
|
||||
本批次已完成的定向验证:
|
||||
|
||||
1. `npx vitest run src/services/authService.test.ts`
|
||||
2. `npx vitest run src/components/auth/AuthGate.test.tsx`
|
||||
3. `npx vitest run src/hooks/story/runtimeStoryCoordinator.test.ts`
|
||||
4. `npm run check:encoding`
|
||||
|
||||
结果:
|
||||
|
||||
1. `authService` 测试通过
|
||||
2. `AuthGate` 测试通过
|
||||
3. `runtimeStoryCoordinator` 测试通过
|
||||
4. 编码检查通过
|
||||
|
||||
另外执行了:
|
||||
|
||||
1. `npm run build`
|
||||
|
||||
结果:
|
||||
|
||||
构建产物生成成功,但 `build-gate` 仍因主包 chunk warning 拦截失败。
|
||||
当前失败点仍是已知的主包体积问题:
|
||||
|
||||
- `AuthenticatedApp-*.js` 超过当前 warning 门槛
|
||||
|
||||
这属于仓库当前既有工程问题,不是本批次引入的新断裂。
|
||||
|
||||
## 4.1 2026-04-21 补充修正:会话探测 401 自触发循环
|
||||
|
||||
在这批收口完成后,前端又暴露出一条更细的鉴权恢复回路问题:
|
||||
|
||||
1. `AuthGate` 启动时会调用 `getCurrentAuthUser()` 探测现有会话
|
||||
2. `/api/auth/me` 返回 `401` 时,`apiClient.ts` 会默认广播一次 `AUTH_STATE_EVENT`
|
||||
3. `AuthGate` 自己又监听这个事件并重新 `hydrate()`
|
||||
4. 最终形成 `hydrate -> /auth/me 401 -> emit -> hydrate` 的自触发循环
|
||||
|
||||
这条链的问题不在“是否允许 401”,而在:
|
||||
|
||||
**会话探测请求把“未登录态探测”错误地当成了“全局登录态变更”。**
|
||||
|
||||
因此这里补了一条更细粒度的约束:
|
||||
|
||||
1. `apiClient.ts` 新增 `notifyAuthStateChange` 选项,默认仍保持原有广播行为
|
||||
2. `getCurrentAuthUser()` 作为会话探测请求,显式关闭这类 401 广播
|
||||
3. 真实登录、登出、刷新成功后,仍保留全局鉴权变更通知
|
||||
|
||||
这样修完后:
|
||||
|
||||
1. `AuthGate` 仍会优先尝试服务端会话恢复
|
||||
2. 无会话时会正常落回未登录分支
|
||||
3. 不会因为探测型 401 把自己重新唤醒并刷爆控制台
|
||||
|
||||
## 4.2 2026-04-22 补充修正:公开认证入口误触发 refresh
|
||||
|
||||
在登录弹窗链路继续联调时,又暴露出一条更细的请求边界问题:
|
||||
|
||||
1. 用户处于未登录态,浏览器本地没有 access token
|
||||
2. 点击“获取验证码”会调用 `sendPhoneLoginCode()`
|
||||
3. `authService.ts` 复用了通用 `requestJson(...)`
|
||||
4. `apiClient.ts` 在“无本地 token 且未显式关闭 refresh”时,会先尝试 `POST /api/auth/refresh`
|
||||
5. 若当前浏览器本来也没有 refresh session cookie,就会先打出一条 `401 Unauthorized`
|
||||
6. 最终表现成:验证码接口真正发送前,前端控制台先报一次 `/api/auth/refresh 401`
|
||||
|
||||
这条链的问题不在“验证码接口失败”,而在:
|
||||
|
||||
**登录前公开认证入口被错误当成了需要先补票的受保护请求。**
|
||||
|
||||
因此这里再补一条明确约束:
|
||||
|
||||
1. `sendPhoneLoginCode()`
|
||||
2. `loginWithPhoneCode()`
|
||||
3. `authEntry()`
|
||||
4. `getAuthLoginOptions()`
|
||||
5. `startWechatLogin()`
|
||||
|
||||
以上这些“获取登录态之前”的公开认证入口,统一显式传入:
|
||||
|
||||
1. `skipAuth: true`
|
||||
2. `skipRefresh: true`
|
||||
|
||||
这样修完后:
|
||||
|
||||
1. 未登录用户点击“获取验证码”不会先打 `/api/auth/refresh`
|
||||
2. 公开认证入口不会误带旧 token,也不会制造无意义的 401 噪音
|
||||
3. 真正需要 refresh 的仍然只有已拿到登录态后的受保护请求
|
||||
|
||||
本次补修的定向验证:
|
||||
|
||||
1. `npx vitest run src/services/authService.test.ts`
|
||||
2. `npm run check:encoding`
|
||||
|
||||
---
|
||||
|
||||
## 5. 本批次完成后的实际收益
|
||||
|
||||
这一步完成后,工程在鉴权边界上有了两个明确改善:
|
||||
|
||||
1. **前端不再保存自动登录用户名 / 密码。**
|
||||
浏览器只保留 access token,本地高风险游客凭证真相已经收掉。
|
||||
2. **登录恢复逻辑更接近服务端为真相源。**
|
||||
`AuthGate` 不再假设“没有本地 token 就一定还没登录”,而是优先尝试服务端会话恢复。
|
||||
|
||||
这意味着前端鉴权链已经从:
|
||||
|
||||
```text
|
||||
本地用户名/密码 -> 再次 entry -> 拿 token
|
||||
```
|
||||
|
||||
进一步收到了:
|
||||
|
||||
```text
|
||||
refresh session / 当前会话 -> 恢复用户
|
||||
兜底时才创建一次游客凭证
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 本批次后续建议
|
||||
|
||||
要继续完成批次 C,下一步不该直接在前端硬删,而应该先补后端 contract:
|
||||
|
||||
1. 让 `runtime story` 动作链逐步摆脱“前端先写远端快照”的依赖
|
||||
2. 让服务端自己持有更完整的运行时 session 真相
|
||||
3. 等后端返回快照已经稳定水合后,再删前端的重复再水合
|
||||
|
||||
换句话说,批次 C 的后半段应该拆成:
|
||||
|
||||
1. **C-1:鉴权真相收口**
|
||||
本批已完成
|
||||
2. **C-2:运行时快照 contract 后端化**
|
||||
需要先改后端
|
||||
3. **C-3:前端镜像写入与重复水合退场**
|
||||
依赖 C-2
|
||||
|
||||
---
|
||||
|
||||
## 7. 一句话总结
|
||||
|
||||
**批次 C 这一轮已经先把“浏览器长期保存游客账号密码”这条最不该存在的鉴权假真相链收掉了;而运行时快照前置写入这条链经过复核确认仍受后端 contract 约束,不能在服务端未先补齐前硬砍。**
|
||||
@@ -0,0 +1,56 @@
|
||||
# 工程死分支清理执行记录 D(2026-04-21)
|
||||
|
||||
更新时间:`2026-04-21`
|
||||
|
||||
## 0. 本批次目标
|
||||
|
||||
本批次继续清理上一轮复核后剩余的低风险数据产物与测试占位:
|
||||
|
||||
1. 未接入业务的生成产物
|
||||
2. 只为测试替换真实实现的空 stub
|
||||
3. 支撑这些残留的配置与脚本
|
||||
|
||||
---
|
||||
|
||||
## 1. 已删除对象
|
||||
|
||||
| 文件 | 判定 | 删除原因 | 替代路径 / 当前真相源 |
|
||||
| --- | --- | --- | --- |
|
||||
| `src/data/buildTagSimilarity.generated.ts` | 未接入业务的生成产物 | 运行时代码不 import;Build 相似度当前由 `buildTags.ts` 中的属性亲和度逻辑计算 | `src/data/buildTags.ts` |
|
||||
| `scripts/generate-build-tag-similarity.py` | 已无输出目标的生成脚本 | 只负责生成已删除的矩阵文件,继续保留会误导后续开发恢复旧主源 | `src/data/buildTags.ts` 的手工审表逻辑 |
|
||||
| `src/data/customWorldCharacterLoadout.stub.ts` | 测试专用空 stub | 只通过 `vitest.config.ts` alias 替换真实实现;真实实现已经稳定存在 | `src/data/customWorldCharacterLoadout.ts` |
|
||||
|
||||
---
|
||||
|
||||
## 2. 同步更新
|
||||
|
||||
本批次同步移除了:
|
||||
|
||||
1. `vitest.config.ts` 中指向 `customWorldCharacterLoadout.stub.ts` 的 alias
|
||||
2. `BUILD_SYSTEM_ATTRIBUTE_SIMILARITY_PRD_2026-04-02.md` 中把旧 generated 矩阵描述为当前文件的表述
|
||||
3. 清理计划里对 `buildTagSimilarity.generated.ts` 的未处理状态说明
|
||||
|
||||
---
|
||||
|
||||
## 3. 验证口径
|
||||
|
||||
删除前已确认:
|
||||
|
||||
1. `buildTagSimilarity.generated.ts` 无运行时代码引用
|
||||
2. `customWorldCharacterLoadout.stub.ts` 只被 `vitest.config.ts` alias 引用
|
||||
3. 真实 `customWorldCharacterLoadout.ts` 仍被 `characterPresets.ts` 与 `npcInteractions.ts` 使用,不能删除
|
||||
|
||||
删除后建议验证:
|
||||
|
||||
1. `npm run check:encoding`
|
||||
2. 与自定义世界开局物品相关的测试
|
||||
|
||||
---
|
||||
|
||||
## 4. 当前结论
|
||||
|
||||
本批次完成后,剩余清理对象已经不再适合按“无引用直接删”推进。后续如果继续清,需要先改 contract 或主链职责:
|
||||
|
||||
1. 运行时快照真相链
|
||||
2. 任务 / 物品 / AI 混合执行层
|
||||
3. 大型主流程组件继续拆分,而不是直接删除
|
||||
@@ -0,0 +1,117 @@
|
||||
# 工程死分支清理执行记录 E(2026-04-21)
|
||||
|
||||
更新时间:`2026-04-21`
|
||||
|
||||
## 0. 本批次目标
|
||||
|
||||
本批次承接批次 D,继续清掉已经退出 RPG 游戏创作主流程、RPG 运行时玩法主流程、平台基本功能主流程的历史壳层。
|
||||
|
||||
本批次不处理仍需后端 contract 先收口的对象,例如:
|
||||
|
||||
1. `src/services/questDirector.ts`
|
||||
2. `src/services/runtimeItemAiDirector.ts`
|
||||
3. `src/hooks/rpg-runtime-story/runtimeStoryCoordinator.ts`
|
||||
4. `src/services/apiClient.ts`
|
||||
|
||||
这些对象仍属于“前端越界逻辑继续后端化”的后续批次,不按无引用文件直接删除。
|
||||
|
||||
---
|
||||
|
||||
## 1. 删除判定口径
|
||||
|
||||
本批只删除满足下面条件之一的对象:
|
||||
|
||||
1. 无运行时入口、无脚本入口、无当前路由挂载。
|
||||
2. 已有现行正式实现,旧文件只剩 re-export / facade / 兼容命名。
|
||||
3. 只被测试验证旧壳自身,且该测试不再服务当前主流程门禁。
|
||||
4. 文档已明确该对象处于“后续只允许收缩、不再接新逻辑”的兼容残留状态。
|
||||
|
||||
---
|
||||
|
||||
## 2. 本批次已处理对象
|
||||
|
||||
| 文件 | 判定 | 删除原因 | 替代路径 / 当前真相源 |
|
||||
| --- | --- | --- | --- |
|
||||
| `server-node/src/routes/rpgCreationAgentRoutes.ts` | 旧命名 re-export | 当前后端正式路由直接使用 `customWorldAgent.ts` | `server-node/src/routes/customWorldAgent.ts` |
|
||||
| `server-node/src/routes/rpgWorldGalleryRoutes.ts` | 空路由骨架 | 世界广场实际列表和详情已经进入世界库路由 | `server-node/src/routes/rpg-entry/rpgWorldLibraryRoutes.ts` |
|
||||
| `server-node/src/services/RpgAgentOrchestrator.ts` | 旧命名 re-export | 当前正式上下文直接使用 `CustomWorldAgentOrchestrator` | `server-node/src/services/customWorldAgentOrchestrator.ts` |
|
||||
| `server-node/src/services/RpgAgentSessionStore.ts` | 旧命名 re-export | 当前正式上下文直接使用 `CustomWorldAgentSessionStore` | `server-node/src/services/customWorldAgentSessionStore.ts` |
|
||||
| `server-node/src/services/customWorldWorkSummaryService.ts` | 旧兼容入口 | 测试和路由已改为直接使用 RPG 命名服务 | `server-node/src/services/RpgWorldWorkSummaryService.ts` |
|
||||
| `server-node/src/services/customWorldAgentPublishGateService.ts` | 旧发布门禁实现 | 当前 action executor 与作品库发布链已统一走 PublishingService | `server-node/src/services/customWorldAgentPublishingService.ts` |
|
||||
| `server-node/src/services/customWorldAgentPublishService.ts` | 旧发布实现 | 当前发布链不再编译旧 legacy result profile | `server-node/src/services/customWorldAgentPublishingService.ts` |
|
||||
| `server-node/src/modules/custom-world/runtime-profile/runtimeProfileCompiler.ts` | 旧 facade | runtime profile 已拆到目录模块并由 `index.ts` / `runtimeProfile.ts` 承接 | `server-node/src/modules/custom-world/runtime-profile/index.ts` |
|
||||
| `server-node/src/bridges/legacyBuildRuntimeBridge.ts` | 无引用旧桥 | 后端 runtime build / equipment 已直接在正式模块内使用 | `server-node/src/modules/runtime/**` |
|
||||
| `server-node/src/bridges/legacyRuntimeItemResolutionBridge.ts` | 旧桥 | runtime item 解析服务一并删除,正式运行时使用 `runtimeItemModule.ts` | `server-node/src/modules/runtime-item/runtimeItemModule.ts` |
|
||||
| `server-node/src/modules/runtime-item/runtimeItemResolutionService.ts` | 无正式入口 wrapper | 只被 barrel 和自身测试引用,未挂入 Express 运行时主链 | `server-node/src/modules/runtime-item/runtimeItemModule.ts` |
|
||||
| `server-node/src/modules/**/index.ts` | 无引用 barrel | 这些 barrel 没有被当前后端入口消费,反而制造“公共模块入口仍存在”的错觉 | 直接 import 具体正式模块 |
|
||||
| `server-node/src/routes/rpg-*/index.ts` | 无引用 barrel | 当前 Express app 直接 import 具体 route 文件 | `server-node/src/app.ts` 中的具体路由 |
|
||||
| `server-node/src/repositories/rpg-*/index.ts` | 无引用 barrel | 当前上下文直接 import 具体 repository | `server-node/src/server.ts` 中的具体仓储 |
|
||||
| `src/components/DeveloperTeamModal.tsx` | 无入口 UI | 平台主流程没有打开该弹窗的入口 | 无替代 UI,删除历史壳 |
|
||||
| `src/components/LazySkillEffectPreview.tsx` | 无入口 lazy 壳 | 正式技能预览直接使用 `SkillEffectPreview` | `src/components/SkillEffectPreview.tsx` |
|
||||
| `src/components/npcVisualEditorModel.ts` | 旧 NPC 形象写回模型 | 当前 RPG 创作编辑器使用 `CustomWorldNpcVisualEditor` 与结果页新入口 | `src/components/CustomWorldNpcVisualEditor.tsx`、`src/components/rpg-creation-editor/**` |
|
||||
| `src/components/npcVisualEditorPersistence.ts` | 旧 NPC 形象写回持久层 | 只被旧持久化测试引用,正式编辑入口已迁移 | `src/components/rpg-creation-editor/**` |
|
||||
| `src/components/rpg-creation-*/index.ts` | 无引用 barrel | 当前入口直接 import 具体 facade 文件,barrel 没有主流程消费 | 直接 import `RpgCreation*` 具体文件 |
|
||||
| `src/components/rpg-creation-editor/CustomWorldSceneChapterEditorSection.tsx` | 旧 facade | 当前编辑器 section 直接在 `RpgCreationEntityEditorShared.tsx` 中分发 | `src/components/rpg-creation-editor/RpgCreationEntityEditorShared.tsx` |
|
||||
| `src/data/editorValidation.ts` | 旧预设编辑器校验 | 当前主流程和内容门禁不再调用 | `scripts/validate-overrides.ts`、后端 editor API |
|
||||
| `src/editor/shared/EditorNotice.tsx` | 无入口共享 UI | 只被同批删除的 FormFields 使用 | 无替代 UI,删除历史编辑器壳 |
|
||||
| `src/editor/shared/FormFields.tsx` | 无入口共享 UI | 旧编辑器共享表单未接主流程 | 当前 RPG 编辑器组件内聚在 `rpg-creation-editor/**` |
|
||||
| `src/editor/shared/SectionCard.tsx` | 无入口共享 UI | 旧编辑器卡片未接主流程 | 当前 RPG 编辑器组件内聚在 `rpg-creation-editor/**` |
|
||||
| `src/hooks/rpg-runtime-story/npcEncounterActions.ts` | 旧 wrapper | 正式实现已在 `useRpgRuntimeNpcInteraction.ts`,测试已改到正式文件 | `src/hooks/rpg-runtime-story/useRpgRuntimeNpcInteraction.ts` |
|
||||
| `src/hooks/rpg-runtime-story/openingAdventure.ts` | 旧前端开局特殊流程 | 开局营地对白已由后端 `RpgRuntimeStoryActionDomain` 和当前 story context 承接 | `server-node/src/modules/rpg-runtime-story/RpgRuntimeStoryActionDomain.ts` |
|
||||
| `src/hooks/rpg-runtime-story/storyCampCompanion.ts` | 旧前端营地同伴 helper | 只剩旧开局流程和自身测试引用,正式开局上下文已迁到当前 runtime story 链 | 后端 runtime story action domain 与 `storyContextBuilder.ts` |
|
||||
| `src/hooks/rpg-runtime-story/storyRenderingHelpers.ts` | 无入口旧渲染 helper | 当前正式 story presentation 不再 import | `src/hooks/rpg-runtime-story/storyPresentation.ts` |
|
||||
| `src/prompts/questPrompts.ts` | 前端 prompt 残留 | Quest prompt 真相已迁到后端 | `server-node/src/prompts/questPrompts.ts` |
|
||||
| `src/prompts/runtimeItemPrompts.ts` | 前端 prompt 残留 | Runtime item prompt 真相已迁到后端 | `server-node/src/prompts/runtimeItemPrompts.ts` |
|
||||
| `src/services/questPrompt.ts` | 前端 prompt re-export | 只指向同批删除的前端 prompt | `server-node/src/prompts/questPrompts.ts` |
|
||||
| `src/services/runtimeItemAiPrompt.ts` | 前端 prompt re-export | 只指向同批删除的前端 prompt | `server-node/src/prompts/runtimeItemPrompts.ts` |
|
||||
| `src/services/storyEngine/contentDependencyGraph.ts` | 实验性孤岛 | 只被自身测试引用,没有主流程消费 | 后续如需要重新设计到后端 story graph 服务 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 同步调整
|
||||
|
||||
1. `customWorldAgentPhase2/3/4` 测试改为直接实例化 `RpgWorldWorkSummaryService`。
|
||||
2. `customWorldWorkSummaryService.integration.test.ts` 改为直接覆盖 `RpgWorldWorkSummaryService`。
|
||||
3. `npcEncounterActions.test.ts` 改为直接覆盖 `useRpgRuntimeNpcInteraction.ts`,不再通过旧 wrapper。
|
||||
4. `story_opening_camp_dialogue` 的 function catalog 执行路径改为后端 runtime action domain,不再指向已删除旧前端文件。
|
||||
5. NPC function catalog 中 `npc_chat / npc_help / npc_leave / npc_fight / npc_spar / npc_preview_talk` 的 executor 路牌改到现行 `useRpgRuntimeNpcInteraction.ts`。
|
||||
|
||||
---
|
||||
|
||||
## 4. 本批次暂缓对象
|
||||
|
||||
以下对象仍然保留,原因是它们不是“无引用死代码”,而是需要下一轮按 contract 或主链职责迁移:
|
||||
|
||||
1. `src/services/questDirector.ts`
|
||||
2. `src/services/runtimeItemAiDirector.ts`
|
||||
3. `src/services/ai.ts`
|
||||
4. `src/data/sceneObservation.ts`
|
||||
5. `server-node/ecosystem.config.cjs`
|
||||
6. `server-node/src/scripts/syncCustomWorldSavedProfileAssets.ts`
|
||||
|
||||
其中 `ecosystem.config.cjs` 被部署脚本直接使用;`sceneObservation.ts` 被内容 smoke 脚本验证;`syncCustomWorldSavedProfileAssets.ts` 是一次性运维脚本,后续要单独按运维脚本治理口径确认是否归档。
|
||||
|
||||
---
|
||||
|
||||
## 5. 验证口径
|
||||
|
||||
本批删除后建议验证:
|
||||
|
||||
1. `npm run check:encoding`
|
||||
2. `npx tsx --test server-node/src/services/customWorldWorkSummaryService.integration.test.ts`
|
||||
3. `npx vitest run src/hooks/rpg-runtime-story/npcEncounterActions.test.ts`
|
||||
4. `npm run server-node:build`
|
||||
5. `npm run build`
|
||||
|
||||
如果 `npm run build` 仍被既有 chunk warning 拦截,需要单独记录为既有门禁问题,不归因到本批删除。
|
||||
|
||||
---
|
||||
|
||||
## 6. 当前结论
|
||||
|
||||
本批次进一步删除了“旧命名入口、旧 facade、旧 prompt 前端镜像、无入口编辑器壳层”这批容易误导后续开发的文件。
|
||||
|
||||
后续清理不应继续按“静态无引用”直接推进,而应进入两类工作:
|
||||
|
||||
1. 运行时 / 任务 / 物品 / AI 的后端 contract 收口。
|
||||
2. RPG 创作编辑器与运行时热点文件的职责拆分。
|
||||
@@ -0,0 +1,91 @@
|
||||
# 工程死分支清理执行记录 F(2026-04-21)
|
||||
|
||||
更新时间:`2026-04-21`
|
||||
|
||||
## 0. 本批次目标
|
||||
|
||||
本批次承接批次 E 的验证结果,继续处理删除后暴露出的最后一组高置信残留:
|
||||
|
||||
1. 已经没有任何代码入口引用的前端任务生成 director。
|
||||
2. 只被内容 smoke 牵住、但不再是正式运行时入口的旧观察文案 helper。
|
||||
3. 带有固定用户、固定 session、固定 profile 的一次性历史同步脚本。
|
||||
4. 清理后暴露出的 function catalog 契约覆盖缺口。
|
||||
|
||||
本批次仍然不按文件名直接删除 `legacy` 命名对象。经核对,`server-node/src/bridges/legacyInventoryRuntimeBridge.ts`、`legacyNpcTask6Bridge.ts`、`legacyQuestProgressBridge.ts`、`legacyQuestRuntimeBridge.ts`、`legacyRuntimeItemBridge.ts`、`legacyTreasureRuntimeBridge.ts` 仍被后端战斗、背包、任务、宝藏主链直接引用,不能按历史命名硬删。
|
||||
|
||||
---
|
||||
|
||||
## 1. 删除判定口径
|
||||
|
||||
本批删除对象必须同时满足:
|
||||
|
||||
1. 修正 `.js -> .ts` 后端源码解析、前端懒加载入口解析后,仍不可从正式入口到达。
|
||||
2. 全仓库代码引用扫描没有正式入口引用。
|
||||
3. 如只被 smoke 或测试牵住,先把 smoke / 测试改到当前正式主链,再删除旧对象。
|
||||
4. 删除后通过对应门禁验证,没有新增悬空 import。
|
||||
|
||||
---
|
||||
|
||||
## 2. 本批次已处理对象
|
||||
|
||||
| 文件 | 判定 | 删除 / 调整原因 | 替代路径 / 当前真相源 |
|
||||
| --- | --- | --- | --- |
|
||||
| `src/services/questDirector.ts` | 无代码入口残留 | 正式 quest 生成已由后端 `/api/runtime/quests/generate` 与 `questService.ts` 承接,前端当前没有任何 import | `server-node/src/services/questService.ts`、`server-node/src/modules/quest/runtimeQuestModule.ts` |
|
||||
| `src/data/sceneObservation.ts` | 旧观察文案 helper | 只被 `scripts/smoke-content.ts` 引用,正式观察动作已走 `idle_observe_signs` function 与运行时 story continuation | `src/data/functionCatalog/state/idleObserveSigns.ts`、`src/hooks/rpg-runtime-story/storyChoiceContinuation.ts` |
|
||||
| `server-node/src/scripts/syncCustomWorldSavedProfileAssets.ts` | 一次性硬编码运维脚本 | 脚本内固定用户、session、profile,只服务历史补丁,没有 CLI 参数和当前运维入口 | 无替代;如未来需要,按参数化运维脚本重新设计 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 同步调整
|
||||
|
||||
1. `scripts/smoke-content.ts` 不再 import 旧 `sceneObservation.ts`,改为通过 `resolveFunctionOption('idle_observe_signs', ...)` 验证当前正式 function 目录。
|
||||
2. `packages/shared/src/contracts/rpgRuntimeContracts.test.ts` 不再验证已移除的旧 `story` façade,改为直接验证当前拆分契约。
|
||||
3. `src/data/functionCatalog/` 补齐仍在后端运行时契约中的 function 文档:
|
||||
- `battle_attack_basic`
|
||||
- `battle_use_skill`
|
||||
- `npc_chat_quest_offer_view`
|
||||
- `npc_chat_quest_offer_replace`
|
||||
- `npc_chat_quest_offer_abandon`
|
||||
4. `battle_attack_basic` 与 `battle_use_skill` 只作为后端契约文档登记,不进入 `STATE_FUNCTION_DEFINITIONS`,避免前端本地候选池生成缺少 `runtimePayload.skillId` 的假技能 option。
|
||||
|
||||
---
|
||||
|
||||
## 4. 本批次暂缓对象
|
||||
|
||||
以下对象经本批复核后继续保留:
|
||||
|
||||
1. `server-node/src/services/customWorldAgentRepositoryTestHelpers.ts`
|
||||
2. `server-node/src/services/customWorldAgentTestHelpers.ts`
|
||||
3. `server-node/src/testFixtures/runtimeCharacter.ts`
|
||||
4. `server-node/src/testHttp.ts`
|
||||
|
||||
这些文件不属于正式运行时入口,但当前被后端测试、smoke 与路由边界门禁使用。它们不是 RPG 创作 / 运行时玩法主流程代码,但仍是平台基本质量门禁的一部分,不能在“删除冗余业务代码”批次里直接硬删。
|
||||
|
||||
另保留:
|
||||
|
||||
1. `src/services/runtimeItemAiDirector.ts`
|
||||
2. `src/services/ai.ts`
|
||||
3. `src/services/apiClient.ts`
|
||||
|
||||
这些文件仍被当前主链或前端 SDK 入口引用,后续如继续压缩,必须先完成对应 contract / SDK 拆分,不按无引用规则删除。
|
||||
|
||||
---
|
||||
|
||||
## 5. 验证结果
|
||||
|
||||
本批已通过:
|
||||
|
||||
1. `npx vitest run src/data/functionCatalog/functionCatalog.test.ts packages/shared/src/contracts/rpgRuntimeContracts.test.ts`
|
||||
2. `npx tsx scripts/smoke-content.ts`
|
||||
3. `npm run check:encoding`
|
||||
|
||||
并额外确认:
|
||||
|
||||
1. 全仓库代码中不再引用 `sceneObservation`、`questDirector`、`syncCustomWorldSavedProfileAssets`。
|
||||
2. `buildStateFunctionDefinitions()` 中不会出现 `battle_attack_basic` / `battle_use_skill`,这两个 function 只由后端运行时 option 池下发。
|
||||
|
||||
---
|
||||
|
||||
## 6. 当前结论
|
||||
|
||||
本批次后,静态入口扫描中剩余的高置信“不可达源码”已经收敛为测试辅助、测试夹具和 smoke helper。继续删除前需要先重构测试基础设施或迁移剩余前端 SDK,而不应再按文件名或历史命名直接硬删。
|
||||
@@ -0,0 +1,553 @@
|
||||
# 前端应迁后端逻辑审计(2026-04-21)
|
||||
|
||||
更新时间:`2026-04-21`
|
||||
|
||||
## 0. 审计目标
|
||||
|
||||
这份文档只回答一个问题:
|
||||
|
||||
**当前前端代码里,哪些逻辑已经明显越过“前端只做表现,Express 后端负责逻辑、数据与存储”的边界,应该继续迁到后端。**
|
||||
|
||||
本轮不改业务代码,只做:
|
||||
|
||||
1. 基于当前仓库状态给出高置信度候选点
|
||||
2. 标明代码证据
|
||||
3. 给出迁移优先级
|
||||
4. 说明迁移后前端应该保留什么、移走什么
|
||||
|
||||
---
|
||||
|
||||
## 1. 结论先行
|
||||
|
||||
结合当前代码与已有边界文档,前端里仍有 7 类逻辑应该继续后移:
|
||||
|
||||
1. **运行时快照前置写入与本地镜像解释**
|
||||
2. **鉴权 token 的浏览器本地真相**
|
||||
3. **平台浏览历史的本地真相与迁移状态**
|
||||
4. **NPC 待接委托“换单”仍由前端直接触发正式生成**
|
||||
5. **quest/runtime item 的双环境混合编排**
|
||||
6. **浏览器侧大型 AI orchestration 与 prompt/repair/fallback 主链**
|
||||
7. **NPC 招募对白之后的正式结算链路**
|
||||
|
||||
一句话判断:
|
||||
|
||||
**当前前端已经不是最早那种“大量主算”的状态,但仍然保留了运行时镜像、生成编排和部分正式真相。后端边界还需要再收一轮,前端才算真正退回表现层。**
|
||||
|
||||
---
|
||||
|
||||
## 2. 审计依据
|
||||
|
||||
### 2.1 文档依据
|
||||
|
||||
1. `docs/experience/PROJECT_WORK_EXPERIENCE_PLAYBOOK.md`
|
||||
2. `docs/technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md`
|
||||
3. `docs/technical/RUNTIME_STORY_BACKEND_BOUNDARY_MIGRATION_2026-04-19.md`
|
||||
4. `docs/audits/engineering/ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-20.md`
|
||||
5. `docs/audits/engineering/CURRENT_ENGINEERING_OPTIMIZATION_OPPORTUNITIES_2026-04-20.md`
|
||||
|
||||
### 2.2 当前代码依据
|
||||
|
||||
1. `src/hooks/story/runtimeStoryCoordinator.ts`
|
||||
2. `src/services/apiClient.ts`
|
||||
3. `src/services/platformBrowseHistory.ts`
|
||||
4. `src/components/game-shell/PreGameSelectionFlow.tsx`
|
||||
5. `src/hooks/story/npcEncounterActions.ts`
|
||||
6. `src/services/questDirector.ts`
|
||||
7. `src/services/runtimeItemAiDirector.ts`
|
||||
8. `src/services/ai.ts`
|
||||
|
||||
---
|
||||
|
||||
## 3. 当前高置信度应后移逻辑
|
||||
|
||||
## 3.0 本轮已完成后移
|
||||
|
||||
以下链路已在本轮或上一轮连续落地中完成后移,不再属于“仍残留在前端”的正式主链:
|
||||
|
||||
1. access token 浏览器本地真相
|
||||
2. browse history 本地真相
|
||||
3. runtime story 前置 `PUT /runtime/save/snapshot`
|
||||
4. NPC 待接委托 `replace / abandon / accept`
|
||||
5. custom world profile 正式浏览器入口
|
||||
6. `questDirector` / `runtimeItemAiDirector` 浏览器正式编排
|
||||
7. NPC 招募正式结算
|
||||
|
||||
其中 NPC 招募已从“前端本地改 companions / roster / npcStates / storyHistory”收回到后端 runtime action。
|
||||
|
||||
## 3.1 运行时快照前置写入仍在前端
|
||||
|
||||
### 代码证据
|
||||
|
||||
`src/hooks/story/runtimeStoryCoordinator.ts` 当前仍存在以下链路:
|
||||
|
||||
1. `syncRuntimeSnapshot(...)`
|
||||
2. `syncRuntimeSnapshot(...)` 内部直接调用 `putSaveSnapshot(...)`
|
||||
3. `loadServerRuntimeOptionCatalog(...)` 在请求 `getRuntimeStoryState(...)` 之前先写本地快照
|
||||
4. `resolveServerRuntimeChoice(...)` 在请求 `resolveRuntimeStoryAction(...)` 之前先写本地快照
|
||||
|
||||
对应位置:
|
||||
|
||||
1. `src/hooks/story/runtimeStoryCoordinator.ts:21`
|
||||
2. `src/hooks/story/runtimeStoryCoordinator.ts:25`
|
||||
3. `src/hooks/story/runtimeStoryCoordinator.ts:36`
|
||||
4. `src/hooks/story/runtimeStoryCoordinator.ts:99`
|
||||
|
||||
### 当前问题
|
||||
|
||||
这意味着运行时正式动作发起前,前端仍会先落一份自己的快照真相,再去请求后端。
|
||||
|
||||
这条链的问题不是“有没有缓存”,而是:
|
||||
|
||||
1. 前端仍在承担正式提交前的状态镜像
|
||||
2. 快照解释权没有完全收回到后端
|
||||
3. 运行时主链仍处于“本地镜像 + 服务端会话”并存状态
|
||||
|
||||
### 迁移建议
|
||||
|
||||
后端继续承接:
|
||||
|
||||
1. 运行时快照写入
|
||||
2. 快照版本解释
|
||||
3. 动作提交前的状态一致性校验
|
||||
|
||||
前端只保留:
|
||||
|
||||
1. 当前展示用的 view model
|
||||
2. 可选的只读恢复缓存
|
||||
3. 纯表现态的 loading / transition / animation state
|
||||
|
||||
### 优先级
|
||||
|
||||
`P0`
|
||||
|
||||
---
|
||||
|
||||
## 3.2 鉴权 token 仍由前端 localStorage 持有真相
|
||||
|
||||
### 代码证据
|
||||
|
||||
`src/services/apiClient.ts` 当前仍直接访问 `window.localStorage` 保存 access token:
|
||||
|
||||
1. `getStoredAccessToken()`
|
||||
2. `setStoredAccessToken(...)`
|
||||
3. `clearStoredAccessToken(...)`
|
||||
4. `withAuthorizationHeaders(...)` 直接从本地 token 组装请求头
|
||||
|
||||
对应位置:
|
||||
|
||||
1. `src/services/apiClient.ts:333`
|
||||
2. `src/services/apiClient.ts:341`
|
||||
3. `src/services/apiClient.ts:362`
|
||||
4. `src/services/apiClient.ts:382`
|
||||
|
||||
### 当前问题
|
||||
|
||||
第三批清理已经收掉了“自动登录用户名/密码”本地真相,但 access token 仍然由浏览器长期持有。
|
||||
|
||||
这在当前项目边界下仍有两个问题:
|
||||
|
||||
1. 正式鉴权真相仍没有完全收回后端 session 边界
|
||||
2. 前端 SDK 仍然负担 token 生命周期的关键部分
|
||||
|
||||
### 迁移建议
|
||||
|
||||
后端继续承接:
|
||||
|
||||
1. session / refresh / cookie 真相
|
||||
2. 鉴权状态续期
|
||||
3. token 更新与失效策略
|
||||
|
||||
前端只保留:
|
||||
|
||||
1. 当前是否已登录的展示态
|
||||
2. 统一的请求封装
|
||||
3. 401 后的 UI 响应
|
||||
|
||||
### 优先级
|
||||
|
||||
`P0`
|
||||
|
||||
---
|
||||
|
||||
## 3.3 平台浏览历史仍是“前端本地历史 + 后端回填”的双真相
|
||||
|
||||
### 代码证据
|
||||
|
||||
`src/services/platformBrowseHistory.ts` 当前仍维护一整套本地历史真相:
|
||||
|
||||
1. `readPlatformBrowseHistory(...)`
|
||||
2. `writePlatformBrowseHistory(...)`
|
||||
3. `hasPendingPlatformBrowseHistoryMigration(...)`
|
||||
4. `markPlatformBrowseHistoryMigrated(...)`
|
||||
|
||||
对应位置:
|
||||
|
||||
1. `src/services/platformBrowseHistory.ts:77`
|
||||
2. `src/services/platformBrowseHistory.ts:103`
|
||||
3. `src/services/platformBrowseHistory.ts:151`
|
||||
4. `src/services/platformBrowseHistory.ts:164`
|
||||
|
||||
`src/components/game-shell/PreGameSelectionFlow.tsx` 当前仍显式做:
|
||||
|
||||
1. 先 `writePlatformBrowseHistory(...)`
|
||||
2. 再调用 `upsertProfileBrowseHistory(...)`
|
||||
3. 同步成功后 `markPlatformBrowseHistoryMigrated(...)`
|
||||
4. 启动阶段读取 `readPlatformBrowseHistory(...)`
|
||||
5. 根据 `hasPendingPlatformBrowseHistoryMigration(...)` 决定是否补同步
|
||||
|
||||
对应位置:
|
||||
|
||||
1. `src/components/game-shell/PreGameSelectionFlow.tsx:383`
|
||||
2. `src/components/game-shell/PreGameSelectionFlow.tsx:392`
|
||||
3. `src/components/game-shell/PreGameSelectionFlow.tsx:394`
|
||||
4. `src/components/game-shell/PreGameSelectionFlow.tsx:433`
|
||||
5. `src/components/game-shell/PreGameSelectionFlow.tsx:466`
|
||||
|
||||
### 当前问题
|
||||
|
||||
这条链已经不是单纯缓存,而是:
|
||||
|
||||
1. 本地历史存储
|
||||
2. 本地同步标记
|
||||
3. 后端历史持久化
|
||||
|
||||
三套状态同时存在。
|
||||
|
||||
### 迁移建议
|
||||
|
||||
后端继续承接:
|
||||
|
||||
1. 浏览历史唯一持久化真相
|
||||
2. 历史去重、排序、截断
|
||||
3. 迁移完成标记
|
||||
|
||||
前端只保留:
|
||||
|
||||
1. 展示缓存
|
||||
2. 弱网下的临时 optimistic UI
|
||||
3. 刷新后重新拉取远端结果
|
||||
|
||||
### 优先级
|
||||
|
||||
`P1`
|
||||
|
||||
---
|
||||
|
||||
## 3.4 NPC 待接委托“换单”仍由前端直接发起正式生成
|
||||
|
||||
### 代码证据
|
||||
|
||||
`src/hooks/story/npcEncounterActions.ts` 当前仍保留:
|
||||
|
||||
1. `replacePendingNpcQuestOffer = async () => { ... }`
|
||||
2. 内部直接调用 `generateQuestForNpcEncounter(...)`
|
||||
|
||||
对应位置:
|
||||
|
||||
1. `src/hooks/story/npcEncounterActions.ts:1561`
|
||||
2. `src/hooks/story/npcEncounterActions.ts:1595`
|
||||
|
||||
### 当前问题
|
||||
|
||||
聊天后是否挂出待接委托已经后移,但“换一份委托”这条分支仍然是:
|
||||
|
||||
1. 前端组装上下文
|
||||
2. 前端决定调用生成
|
||||
3. 前端直接把结果写回当前 story UI
|
||||
|
||||
这仍属于正式运行时任务编排没有收干净。
|
||||
|
||||
### 迁移建议
|
||||
|
||||
后端继续承接:
|
||||
|
||||
1. NPC 待接委托换单决策
|
||||
2. 是否允许换单
|
||||
3. 换单后的任务草案生成
|
||||
4. 对应聊天态快照回填
|
||||
|
||||
前端只保留:
|
||||
|
||||
1. 点击“换一份委托”
|
||||
2. loading / error 展示
|
||||
3. 消费后端返回的新 pending quest offer
|
||||
|
||||
### 优先级
|
||||
|
||||
`P0`
|
||||
|
||||
---
|
||||
|
||||
## 3.5 questDirector 仍是前端 SDK 与生成编排混合体
|
||||
|
||||
### 代码证据
|
||||
|
||||
`src/services/questDirector.ts` 当前同时承担:
|
||||
|
||||
1. `generateQuestForNpcEncounter(...)`
|
||||
2. 浏览器路径 `requestJson('/api/runtime/quests/generate')`
|
||||
3. 非浏览器路径 `requestChatMessageContent(...)`
|
||||
4. 本地 `compileQuestIntentToQuest(...)` fallback
|
||||
|
||||
对应位置:
|
||||
|
||||
1. `src/services/questDirector.ts:213`
|
||||
2. `src/services/questDirector.ts:242`
|
||||
3. `src/services/questDirector.ts:267`
|
||||
4. `src/services/questDirector.ts:256`
|
||||
5. `src/services/questDirector.ts:281`
|
||||
6. `src/services/questDirector.ts:293`
|
||||
|
||||
### 当前问题
|
||||
|
||||
这类文件虽然浏览器正式路径已经优先走后端,但职责仍混在一起:
|
||||
|
||||
1. 前端 SDK
|
||||
2. Quest prompt 编排
|
||||
3. Quest intent 解析
|
||||
4. deterministic fallback compile
|
||||
|
||||
这会导致边界长期模糊,也让前端仍像“半个服务端”。
|
||||
|
||||
### 迁移建议
|
||||
|
||||
后端继续承接:
|
||||
|
||||
1. quest intent 生成
|
||||
2. prompt 组装
|
||||
3. JSON 解析
|
||||
4. fallback compile
|
||||
|
||||
前端只保留:
|
||||
|
||||
1. `requestGenerateQuest(...)` 这类轻量 SDK
|
||||
2. 请求参数组装
|
||||
3. 结果消费
|
||||
|
||||
### 优先级
|
||||
|
||||
`P1`
|
||||
|
||||
---
|
||||
|
||||
## 3.6 runtimeItemAiDirector 仍是前端 SDK 与意图生成混合体
|
||||
|
||||
### 代码证据
|
||||
|
||||
`src/services/runtimeItemAiDirector.ts` 当前同时承担:
|
||||
|
||||
1. `generateRuntimeItemAiIntents(...)`
|
||||
2. 浏览器路径 `requestJson('/api/runtime/items/runtime-intent')`
|
||||
3. 非浏览器路径 `requestChatMessageContent(...)`
|
||||
4. 本地 `buildRuntimeItemAiIntent(...)` fallback
|
||||
|
||||
对应位置:
|
||||
|
||||
1. `src/services/runtimeItemAiDirector.ts:84`
|
||||
2. `src/services/runtimeItemAiDirector.ts:94`
|
||||
3. `src/services/runtimeItemAiDirector.ts:118`
|
||||
|
||||
### 当前问题
|
||||
|
||||
它和 `questDirector` 是同类问题:
|
||||
|
||||
1. 正式浏览器路径已经走后端
|
||||
2. 但前端文件仍然承担完整生成逻辑认知
|
||||
3. 文件职责仍然是双环境混合
|
||||
|
||||
### 迁移建议
|
||||
|
||||
后端继续承接:
|
||||
|
||||
1. runtime item intent prompt
|
||||
2. 模型调用
|
||||
3. 结果解析与 fallback
|
||||
|
||||
前端只保留:
|
||||
|
||||
1. 轻量请求 SDK
|
||||
2. 结果到 UI 的映射
|
||||
|
||||
### 优先级
|
||||
|
||||
`P1`
|
||||
|
||||
---
|
||||
|
||||
## 3.7 `src/services/ai.ts` 仍是浏览器侧正式 AI orchestration 热点
|
||||
|
||||
### 代码证据
|
||||
|
||||
当前 `src/services/ai.ts` 仍直接承担以下正式链路:
|
||||
|
||||
1. `requestChatMessageContent(...)`
|
||||
2. `requestPlainTextCompletionFromClient(...)`
|
||||
3. `streamPlainTextCompletionFromClient(...)`
|
||||
4. `generateCustomWorldProfile(...)`
|
||||
5. `generateInitialStory(...)`
|
||||
6. `generateNextStep(...)`
|
||||
7. `streamNpcChatDialogue(...)`
|
||||
8. `streamNpcRecruitDialogue(...)`
|
||||
|
||||
对应位置:
|
||||
|
||||
1. `src/services/ai.ts:1732`
|
||||
2. `src/services/ai.ts:1868`
|
||||
3. `src/services/ai.ts:2038`
|
||||
4. `src/services/ai.ts:2339`
|
||||
5. `src/services/ai.ts:2447`
|
||||
6. `src/services/ai.ts:2487`
|
||||
7. `src/services/ai.ts:2529`
|
||||
8. `src/services/ai.ts:2570`
|
||||
|
||||
并且文件内仍保留:
|
||||
|
||||
1. JSON repair
|
||||
2. prompt 组装
|
||||
3. response normalize
|
||||
4. fallback/offline 响应
|
||||
5. 角色聊天建议与摘要生成
|
||||
|
||||
### 当前问题
|
||||
|
||||
这说明浏览器端并不只是“请求一个后端接口”,而是还在承担:
|
||||
|
||||
1. prompt source
|
||||
2. 生成策略
|
||||
3. 错误修复
|
||||
4. fallback 编排
|
||||
5. 多类业务场景的正式 AI 出口
|
||||
|
||||
这与“前端只做表现”存在明确冲突。
|
||||
|
||||
### 迁移建议
|
||||
|
||||
后端继续承接:
|
||||
|
||||
1. story / npc / recruit / custom-world 的 prompt 编排
|
||||
2. JSON repair
|
||||
3. fallback 策略
|
||||
4. streaming orchestration
|
||||
5. 模型调用与日志
|
||||
|
||||
前端只保留:
|
||||
|
||||
1. 轻量 AI SDK
|
||||
2. SSE 文本流展示
|
||||
3. UI fallback 呈现
|
||||
|
||||
### 优先级
|
||||
|
||||
`P0`
|
||||
|
||||
---
|
||||
|
||||
## 3.8 NPC 招募对白之后的正式结算链路已完成后移
|
||||
|
||||
### 本轮前状态
|
||||
|
||||
迁移前,`src/hooks/story/npcInteraction.ts` 中的 `buildRecruitmentOutcome / executeRecruitment / startRecruitmentSequence` 仍在前端本地正式结算:
|
||||
|
||||
1. 改 `npcStates`
|
||||
2. 改 `companions`
|
||||
3. 改 `roster`
|
||||
4. 清 `currentEncounter / inBattle / sceneHostileNpcs`
|
||||
5. 直接写 `storyHistory`
|
||||
6. 再触发后续剧情推进
|
||||
|
||||
这与“前端只做表现,所有正式逻辑、数据都放到 Express 后端”直接冲突。
|
||||
|
||||
### 本轮后状态
|
||||
|
||||
本轮已完成:
|
||||
|
||||
1. `server-node/src/modules/story/runtimeSession.ts`
|
||||
- 正式承接完整 `companions`
|
||||
- 正式承接 `roster`
|
||||
2. `server-node/src/modules/npc/npcInteractionService.ts`
|
||||
- `npc_recruit` 已支持正常入队
|
||||
- `npc_recruit` 已支持满员换队招募
|
||||
3. `src/hooks/story/npcInteraction.ts`
|
||||
- 前端只保留招募对白流式展示
|
||||
- 正式招募结算改为调用后端 runtime action
|
||||
|
||||
### 当前判断
|
||||
|
||||
这一项已不再属于前端残留正式逻辑。
|
||||
|
||||
---
|
||||
|
||||
## 4. 可以暂时保留在前端的部分
|
||||
|
||||
下面这些内容即使和上述模块同文件出现,也不属于必须后移的对象:
|
||||
|
||||
1. 面板开关、loading、error、streaming 文本展示
|
||||
2. 动画时间线、过场状态、临时 UI 回显
|
||||
3. 表单草稿、筛选词、排序选项
|
||||
4. 只影响表现、不影响正式真相的 view model 拼接
|
||||
|
||||
迁移时要注意:
|
||||
|
||||
**不是把所有前端代码都往后端搬,而是把“正式状态解释、规则裁决、生成编排、持久化真相”搬走。**
|
||||
|
||||
---
|
||||
|
||||
## 5. 推荐迁移顺序
|
||||
|
||||
## 5.1 第一阶段
|
||||
|
||||
先收最危险的正式真相:
|
||||
|
||||
1. `runtimeStoryCoordinator.ts`
|
||||
2. `apiClient.ts`
|
||||
3. `npcEncounterActions.ts` 里的 quest replace 分支
|
||||
|
||||
原因:
|
||||
|
||||
1. 这三处最直接影响运行时真相和动作主链
|
||||
2. 不先收这些,前端仍然不是纯表现层
|
||||
|
||||
## 5.2 第二阶段
|
||||
|
||||
再拆双环境混合服务:
|
||||
|
||||
1. `questDirector.ts`
|
||||
2. `runtimeItemAiDirector.ts`
|
||||
3. `platformBrowseHistory.ts`
|
||||
|
||||
原因:
|
||||
|
||||
1. 这几处已经有后端承接基础
|
||||
2. 迁移成本相对可控
|
||||
|
||||
## 5.3 第三阶段
|
||||
|
||||
最后继续压缩浏览器 AI orchestration:
|
||||
|
||||
1. `src/services/ai.ts`
|
||||
2. 相关 prompt builder / repair helper / offline fallback
|
||||
|
||||
原因:
|
||||
|
||||
1. 这部分体量大
|
||||
2. 链路多
|
||||
3. 更适合在前两阶段把 contract 稳住后集中拆
|
||||
|
||||
---
|
||||
|
||||
## 6. 建议产出物
|
||||
|
||||
如果后续按这份文档继续落地,建议每一批都至少同步产出:
|
||||
|
||||
1. 一份落地文档,说明迁移了哪条链
|
||||
2. 一组 contract/route 变更说明
|
||||
3. 一组前端 SDK 收缩说明
|
||||
4. 一组防回退测试
|
||||
|
||||
---
|
||||
|
||||
## 7. 一句话结论
|
||||
|
||||
当前前端最需要继续后移的,不是零散小工具,而是:
|
||||
|
||||
**运行时快照前置写入、鉴权 token、本地浏览历史真相、NPC 委托换单、quest/runtime item 双环境混合编排,以及 `src/services/ai.ts` 里仍然留在浏览器的正式 AI orchestration。**
|
||||
@@ -0,0 +1,173 @@
|
||||
# 怪物-NPC 脚本统一整改审计
|
||||
|
||||
日期:2026-04-06
|
||||
|
||||
## 核心结论
|
||||
|
||||
当前工程仍然没有真正落实“怪物就是初始好感度为负数的 NPC”这一原则。
|
||||
|
||||
现状不是“NPC 脚本里支持 hostile 状态”,而是同时存在两条并行链路:
|
||||
|
||||
1. `npc / encounter / npcStates / npcInteraction`
|
||||
2. `monster / hostileNpc / sceneMonsters / sceneHostileNpcs / hostileNpcPresets`
|
||||
|
||||
这会直接导致:
|
||||
|
||||
- 同一个敌对实体同时拥有 NPC 身份和 monster 身份。
|
||||
- 场景、战斗、渲染、提示词都在维护两套入口。
|
||||
- 后续修 bug 时,任何位置、死亡、血条、入场、掉落问题都要同时查两条链路。
|
||||
|
||||
本次文档的目标不是立刻改代码,而是先把应该删除的分叉脚本、应该降级成素材层的文件、以及必须合并的字段全部列清楚,作为后续统一改造的依据。
|
||||
|
||||
## 当前违背原则的根因
|
||||
|
||||
### 1. 场景数据仍然把“怪物”和“NPC”当成两类实体
|
||||
|
||||
当前场景层同时维护:
|
||||
|
||||
- `ScenePreset.monsterIds`
|
||||
- `SceneNpc[]`
|
||||
- `ScenePresetInfo.hostileNpcIds`
|
||||
- `SceneNpc.monsterPresetId / hostileNpcPresetId`
|
||||
|
||||
这意味着场景里一个敌对单位既可以来自 `monsterIds`,也可以来自 `npcs`,甚至会被脚本再生成为 hostile scene npc。
|
||||
|
||||
### 2. 运行时仍然存在“怪物专用实体状态”
|
||||
|
||||
当前运行时仍然同时维护:
|
||||
|
||||
- `GameState.sceneMonsters`
|
||||
- `GameState.sceneHostileNpcs`
|
||||
- `SceneHostileNpc / SceneMonster`
|
||||
|
||||
这和“怪物本质上只是 hostile NPC”是冲突的。真正统一后,运行时只应该保留一套“场景 NPC / 战斗 NPC”状态。
|
||||
|
||||
### 3. 战斗脚本仍然把怪物当独立 actor
|
||||
|
||||
战斗层目前不是“NPC 战斗,只是 hostile 的那部分会出手”,而是显式写了:
|
||||
|
||||
- `TurnActor = 'player' | 'companion' | 'monster'`
|
||||
- `getClosestMonster`
|
||||
- `resetCombatPresentation(monsters, ...)`
|
||||
- `sceneMonsters` 全链路结算
|
||||
|
||||
这会强制后面所有视觉、掉落、提示词、AI 上下文都跟着叫 monster。
|
||||
|
||||
### 4. 渲染层仍然有 monster 专属显示入口
|
||||
|
||||
画布层当前仍然依赖:
|
||||
|
||||
- `sceneMonsters`
|
||||
- `sceneHostileNpcs`
|
||||
- `monsterPresetId`
|
||||
- `HostileNpcAnimator`
|
||||
|
||||
也就是“敌对 NPC 是否按 NPC 脚本渲染”这件事,到最终显示层仍然没有统一。
|
||||
|
||||
## 一级删除清单
|
||||
|
||||
下面这些文件属于“业务流程分叉脚本”,不是单纯资源适配层。后续统一时应优先删除或并入 NPC 主链路。
|
||||
|
||||
| 文件 | 当前分叉角色 | 处理建议 |
|
||||
| --- | --- | --- |
|
||||
| `src/data/monsters.ts` | 对 `hostileNpcs.ts` 的别名出口 | 直接删除,禁止继续保留 monster 专属入口名。 |
|
||||
| `src/data/hostileNpcs.ts` | 负责 monster 创建、编队、距离、朝向、变化、落位 | 按 hostile NPC 运行时工具重写并并入 NPC 体系;原文件名不应继续保留。 |
|
||||
| `src/data/sceneEncounterPreviews.ts` | 单独构造 hostile encounter group、auto battle、hostile preview | 删除 monster 专线逻辑,改为“负好感 NPC 预览/入场/转战斗”。 |
|
||||
| `src/hooks/combat/battlePlan.ts` | 使用 `monster` actor、`sceneMonsters`、`getClosestMonster` | 改成统一的 hostile NPC combatant 规划脚本;monster actor 概念应移除。 |
|
||||
| `src/hooks/combat/playback.ts` | 使用 `sceneMonsters` 播放怪物战斗演出 | 改成统一 NPC 战斗回放;不再区分 monster 播放器。 |
|
||||
| `src/components/game-canvas/GameCanvasRuntime.tsx` | 运行时按 `sceneMonsters / sceneHostileNpcs` 双数据源选敌方实体 | 删除双源兜底,统一成单一 hostile NPC 列表。 |
|
||||
| `src/components/game-canvas/GameCanvasEntityLayer.tsx` | 敌方实体按 monsterPreset 分支渲染 | 改成同一套 NPC 实体渲染,视觉差异仅由 visual preset 决定。 |
|
||||
| `src/components/game-canvas/GameCanvasShared.tsx` | 定义 `sceneMonsters / sceneHostileNpcs` props 与 monster 专属计算 | 删除这些字段与 helper,改成统一 NPC 画布协议。 |
|
||||
| `src/components/preset-editor/MonsterPresetPanel.tsx` | 独立怪物预设编辑面板 | 并回 NPC hostile visual preset 面板,或删除该独立编辑器入口。 |
|
||||
| `src/components/preset-editor/MonsterPresetTab.tsx` | 独立怪物预设页签 | 与上面一并删除或并入 NPC preset 编辑器。 |
|
||||
| `src/components/preset-editor/ScenePresetPanel.tsx` | 仍然单独编辑 `monsterIds` | 删除 `monsterIds` 编辑项,只保留场景 NPC 列表。 |
|
||||
|
||||
## 二级归并清单
|
||||
|
||||
下面这些文件不一定需要物理删除,但它们当前仍然在放大 monster / NPC 分轨,必须在统一改造时一起收口。
|
||||
|
||||
| 文件 | 当前问题 | 处理建议 |
|
||||
| --- | --- | --- |
|
||||
| `src/data/scenePresets.ts` | 通过 `monsterIds` 再生 hostile scene npc,并区分 `getSceneHostileNpcs / getSceneFriendlyNpcs` | 保留场景数据文件本身,但删除 `monsterIds` 体系,让敌对角色直接存在于 `npcs` 中。 |
|
||||
| `src/data/customWorldNpcMonsters.ts` | 用单独脚本推导“怪物型 NPC”预设 | 可保留为 hostile visual preset 选择器,但不能再生成第二套实体语义。 |
|
||||
| `src/data/hostileNpcPresets.ts` | 目前既是视觉预设库,也是独立 hostile 流程的数据源 | 降级为 hostile visual/combat preset 库;不再拥有独立实体生命周期。 |
|
||||
| `src/components/HostileNpcAnimator.tsx` | 当前名字和调用语义都在暗示“独立怪物实体” | 可以保留为贴图播放器,但应改为 hostile NPC 的视觉适配组件,而不是独立物种脚本。 |
|
||||
| `src/components/AdventureEntityModal.tsx` | 详情弹窗仍会优先查 monster preset / hostileNpcPreset | 统一读取 NPC 档案;视觉差异只通过 hostile preset 补充。 |
|
||||
| `src/components/SkillEffectPreview.tsx` | 预览器直接使用 `sceneMonsters` 和 `createSceneMonstersFromIds` | 改成统一 hostile NPC 预览态。 |
|
||||
| `src/components/StateFunctionEditor.tsx` | 编辑器里仍然直接造 monster battle preview | 改成 hostile NPC preview。 |
|
||||
| `src/components/preset-editor/SceneNpcPresetPanel.tsx` | 仍然暴露 `monsterPresetId` 字段 | 改成更明确的 hostile visual preset 字段,避免“怪物类型”和“NPC 类型”双语义。 |
|
||||
| `src/hooks/story/npcEncounterActions.ts` | 虽然入口叫 npc,但内部仍然写 `sceneMonsters / sceneHostileNpcs` | 改成统一 hostile NPC 战斗状态字段。 |
|
||||
| `src/hooks/story/choiceActions.ts` | 仍然有 `buildHostileNpcBattleReward` 和 `getResolvedSceneHostileNpcs` 这一层额外概念 | 统一到 hostile NPC 结算工具,不再把“敌对 NPC”和“monster”混称。 |
|
||||
| `src/hooks/useStoryGeneration.ts` | 给 AI/剧情层传入 `sceneMonsters` 或 `sceneHostileNpcs` | 改成统一的 hostile NPC 上下文切片。 |
|
||||
| `src/services/prompt.ts` | 仍然从 `monsterIds` 和 `createSceneMonstersFromIds` 组 prompt | 改成从场景 NPC 列表中筛出 hostile NPC。 |
|
||||
| `src/services/questDirector.ts` | 仍然依赖 `monsterPresetId` 推导当前敌对目标 | 统一改为基于负好感或 hostile 标记的 NPC。 |
|
||||
| `src/services/ai.ts` | 仍然混用 `monsterIds`、sceneNpc 的 hostile 判定 | 与场景统一后改成只读 NPC 列表。 |
|
||||
| `src/services/questTypes.ts` | 仍然把 `hostileNpcIds / monsterIds` 当作 scene 快照字段 | 删除 `monsterIds`,保留 hostile NPC 语义。 |
|
||||
|
||||
## 可保留但必须降级为“素材/配置层”的内容
|
||||
|
||||
下面这些内容不一定要消失,但不能继续作为独立业务链路存在:
|
||||
|
||||
| 文件/内容 | 可以保留的原因 | 必须收口的边界 |
|
||||
| --- | --- | --- |
|
||||
| `src/components/HostileNpcAnimator.tsx` | 怪物贴图是特殊资源,需要专门 sprite sheet 播放器 | 只负责画图,不再决定实体类型、战斗身份、交互入口。 |
|
||||
| `src/data/hostileNpcPresets.ts` | hostile visual/combat preset 仍然有价值 | 只能作为 hostile NPC 的 visual/combat preset 库,不再驱动另一套“monster 实体”。 |
|
||||
| `src/data/hostileNpcOverrides.json` | 资源级 override 仍可继续用 | 不能再配套出独立 hostile 流程。 |
|
||||
| `src/data/monsterOverrides.json` | 如果只是素材映射,可迁移到 hostile visual preset override | 不应继续以 monster 专属命名长期存在。 |
|
||||
| `src/data/customWorldNpcMonsters.ts` | 自定义世界里确实需要从文本匹配 hostile visual preset | 只能产出“NPC 使用哪个 hostile visual preset”,不能产出独立 monster 身份。 |
|
||||
|
||||
## 字段级必须合并的内容
|
||||
|
||||
后续改代码时,至少要把下面这些字段和类型一起收口:
|
||||
|
||||
| 当前字段/类型 | 问题 | 合并方向 |
|
||||
| --- | --- | --- |
|
||||
| `ScenePreset.monsterIds` | 场景里额外保存一份怪物池 | 删除,只保留 `npcs`。 |
|
||||
| `ScenePresetInfo.hostileNpcIds` | 历史遗留双字段 | 直接由 `npcs.filter(initialAffinity < 0 或 hostile)` 推导。 |
|
||||
| `Encounter.monsterPresetId` | 把 hostile NPC 再次物种化 | 改成 hostile visual preset 字段,或并入统一 visualRef。 |
|
||||
| `Encounter.hostileNpcPresetId` | 与 `monsterPresetId` 语义重叠 | 与上面合并为一个字段。 |
|
||||
| `GameState.sceneMonsters` | 把敌对 NPC 单独塞进 monster 容器 | 改成统一 `sceneNpcCombatants` 或等价单一列表。 |
|
||||
| `GameState.sceneHostileNpcs` | 历史兼容层,导致双数据源 | 删除。 |
|
||||
| `SceneHostileNpc / SceneMonster` | 类型名直接固化了分轨 | 改成统一的 hostile NPC / scene combat NPC 类型。 |
|
||||
| `SceneHostileNpcChange / SceneMonsterChange` | 继续复制同一套变更结构 | 合并成统一 NPC scene change。 |
|
||||
| `SceneNpc.monsterPresetId / hostileNpcPresetId` | 同一实体上挂两套 preset 入口 | 收敛为一个 hostile visual/combat preset 字段。 |
|
||||
|
||||
## 本轮最优先的删除顺序
|
||||
|
||||
建议后续真正改代码时,按下面顺序删并,风险最低:
|
||||
|
||||
1. 先删字段入口:`monsterIds / sceneHostileNpcs / hostileNpcPresetId`
|
||||
2. 再删运行时双轨:`src/data/monsters.ts`、`src/data/hostileNpcs.ts`、`src/data/sceneEncounterPreviews.ts`
|
||||
3. 再删战斗双轨:`battlePlan.ts`、`playback.ts` 里的 `monster` actor 与 `sceneMonsters`
|
||||
4. 再删画布双轨:`GameCanvasRuntime.tsx`、`GameCanvasEntityLayer.tsx`、`GameCanvasShared.tsx`
|
||||
5. 最后清编辑器和提示词:`MonsterPresetPanel.tsx`、`MonsterPresetTab.tsx`、`prompt.ts`、`questDirector.ts`
|
||||
|
||||
## 改造后的目标形态
|
||||
|
||||
统一后应只剩下这一套语义:
|
||||
|
||||
- 场景中所有可见角色都放在 `npcs`
|
||||
- 怪物 = `initialAffinity < 0` 或 `hostile = true` 的 NPC
|
||||
- hostile 的视觉差异只来自 hostile visual preset
|
||||
- 战斗中所有敌方单位都属于 hostile NPC combatant
|
||||
- AI、任务、渲染、详情、掉落都只读同一套 NPC 数据
|
||||
|
||||
如果后面代码里还出现下面这些关键词,基本都说明分轨没有删干净:
|
||||
|
||||
- `sceneMonsters`
|
||||
- `sceneHostileNpcs`
|
||||
- `monsterIds`
|
||||
- `hostileNpcPresetId`
|
||||
- `createSceneMonstersFromIds`
|
||||
- `getClosestMonster`
|
||||
- `TurnActor = 'monster'`
|
||||
|
||||
## 这份文档的使用方式
|
||||
|
||||
后续正式开始改造时,建议把文件分成三批执行:
|
||||
|
||||
1. “直接删掉”的入口脚本
|
||||
2. “改名并并回 NPC 主链路”的桥接脚本
|
||||
3. “仅保留素材职责”的 renderer / preset 文件
|
||||
|
||||
不要继续接受“名字叫 NPC,但内部仍然先转成 monster 再跑”的中间态。
|
||||
46
docs/audits/engineering/README.md
Normal file
46
docs/audits/engineering/README.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# 工程优化审查总览
|
||||
|
||||
这一组只保留仍能指导当前 Rust / SpacetimeDB 主线的工程审查入口。早期连续扫描的有效结论已经合并到本 README 的“融合结论”,不再保留逐日旧稿。
|
||||
|
||||
## 当前推荐入口
|
||||
|
||||
1. [SERVER_NODE_FREEZE_AND_DEPRECATION_2026-04-24.md](./SERVER_NODE_FREEZE_AND_DEPRECATION_2026-04-24.md)
|
||||
这一版是旧 Node 后端冻结、第一批物理删除与后续批次边界记录,明确当前工程只保留 Rust / SpacetimeDB 主线入口。
|
||||
2. [ENGINEERING_DEAD_CODE_CLEANUP_BATCH_F_2026-04-21.md](./ENGINEERING_DEAD_CODE_CLEANUP_BATCH_F_2026-04-21.md)
|
||||
这一版是第六批落地记录,聚焦删除无入口 `questDirector`、旧观察文案 helper、一次性硬编码同步脚本,并补齐后端运行时 function catalog 契约覆盖。
|
||||
3. [ENGINEERING_DEAD_CODE_CLEANUP_BATCH_E_2026-04-21.md](./ENGINEERING_DEAD_CODE_CLEANUP_BATCH_E_2026-04-21.md)
|
||||
这一版是第五批落地记录,聚焦旧命名 re-export、空路由骨架、旧发布服务、前端 prompt 镜像与无入口编辑器壳层的物理删除。
|
||||
4. [FRONTEND_LOGIC_BACKEND_MIGRATION_AUDIT_2026-04-21.md](./FRONTEND_LOGIC_BACKEND_MIGRATION_AUDIT_2026-04-21.md)
|
||||
这一版是本轮前端越界逻辑专项审计,专门汇总当前仍应继续迁到 `server-rs` 的运行时、鉴权、生成编排与本地真相残留。
|
||||
5. [ENGINEERING_DEAD_CODE_CLEANUP_BATCH_D_2026-04-21.md](./ENGINEERING_DEAD_CODE_CLEANUP_BATCH_D_2026-04-21.md)
|
||||
这一版是第四批落地记录,聚焦未接入业务的数据生成产物、测试专用 stub 与对应配置残留出清。
|
||||
6. [ENGINEERING_DEAD_CODE_CLEANUP_BATCH_C_2026-04-21.md](./ENGINEERING_DEAD_CODE_CLEANUP_BATCH_C_2026-04-21.md)
|
||||
这一版是第三批落地记录,聚焦鉴权真相收口,先移除前端保存自动登录用户名/密码的本地真相,并明确运行时快照前置写入为什么当前还不能硬砍。
|
||||
7. [ENGINEERING_DEAD_CODE_CLEANUP_BATCH_B_2026-04-21.md](./ENGINEERING_DEAD_CODE_CLEANUP_BATCH_B_2026-04-21.md)
|
||||
这一版是第二批落地记录,聚焦旧主流程壳层、旧 bootstrap 和旧 inventory / forge / equipment flow Hook 的正式出清。
|
||||
8. [ENGINEERING_DEAD_CODE_CLEANUP_BATCH_A_2026-04-21.md](./ENGINEERING_DEAD_CODE_CLEANUP_BATCH_A_2026-04-21.md)
|
||||
这一版是第一批落地记录,聚焦高置信度小型孤岛、prompt 壳子、stub 和无入口 modal 的首轮清理。
|
||||
9. [CURRENT_ENGINEERING_OPTIMIZATION_OPPORTUNITIES_2026-04-20.md](./CURRENT_ENGINEERING_OPTIMIZATION_OPPORTUNITIES_2026-04-20.md)
|
||||
这一版是面向当前仓库状态的优化点盘点,适合直接拿来排优先级和拆执行批次。
|
||||
10. [ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-20.md](./ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-20.md)
|
||||
这一版是对 `2026-04-19` 基线的当前仓库复核,明确哪些问题已经处理、哪些表述需要纠正、热点又迁移到了哪里。
|
||||
11. [ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-19.md](./ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-19.md)
|
||||
这一版保留原始问题快照和执行回填,适合回看“为什么会有这轮清理与边界收口”。
|
||||
## 融合结论
|
||||
|
||||
- 最新专项审计已经把“前端哪些逻辑还该后移到后端”收敛到 6 类:运行时快照、本地 token、本地浏览历史、NPC 委托换单、quest/runtime item 混合编排、浏览器 AI orchestration。
|
||||
- 工程大清洗已经开始进入实际执行阶段,首批高置信度小型孤岛和残留壳子已开始清理。
|
||||
- 第二批已经开始清理旧主流程壳层与旧 flow Hook,当前主工程的“现行入口”和“历史入口”边界正在变得更清楚。
|
||||
- 第三批已经先完成鉴权真相收口的一段,前端不再保存自动登录用户名/密码;运行时快照链仍需先补后端 contract,再继续往前删。
|
||||
- 第四批已经继续收掉未接入业务的数据生成产物、测试专用 stub 与对应脚本/配置残留,主工程里的“假数据主源”进一步减少。
|
||||
- 第五批已经继续收掉旧命名 re-export、空路由骨架、旧发布 service、前端 prompt 镜像与无入口编辑器壳层,主工程里的“假入口”和“假 prompt 主源”进一步减少。
|
||||
- 第六批已经继续收掉无入口 `questDirector`、旧观察文案 helper、一次性硬编码同步脚本,并修复 function catalog 对后端运行时契约的覆盖缺口。
|
||||
- 当前仓库已经完成“旧 dev 插件链路删除、根目录噪音清理、`server-node -> src/**` 反向依赖切断”这批第一阶段任务。
|
||||
- 当前如果想直接判断“今天先优化什么”,优先看 `CURRENT_ENGINEERING_OPTIMIZATION_OPPORTUNITIES_2026-04-20.md`。
|
||||
- 当前的新重点已经进一步收敛到三类:未接线孤岛模块、前端残留的运行时/鉴权真相、热点向 prompt/runtime profile/平台入口壳层迁移。
|
||||
- 早期三轮工程扫描的结论已经聚合为一条长期规则:工程化不能只看目录和拆分动作,必须覆盖真实主链、质量门禁、绿色基线、关键模块豁免和 build warning。
|
||||
- `2026-04-19` 这一轮把问题压实到了四类:仓库噪音、旧 dev 入口残留、前端越界运行时逻辑、巨型热点文件。
|
||||
- `2026-04-20` 这一轮进一步确认:前两类已经阶段性完成,当前真正剩下的是边界尾巴和新热点迁移。
|
||||
- 如果是要看当前清理和边界收口的最新状态,优先看 `ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-20.md`。
|
||||
- 如果是要看“当前可执行的优化点清单”,优先看 `CURRENT_ENGINEERING_OPTIMIZATION_OPPORTUNITIES_2026-04-20.md`。
|
||||
- 如果是要做长期重构方案,从 `2026-04-19`、`2026-04-20` 与当前 dead-code batch 记录开始即可。
|
||||
@@ -0,0 +1,129 @@
|
||||
# server-node 冻结隔离说明(2026-04-24)
|
||||
|
||||
## 1. 当前状态
|
||||
|
||||
`server-node/` 已进入冻结隔离状态,不再作为可运行、可扩展、可引用的后端工程使用。
|
||||
|
||||
冻结原因:项目后端主线已经切到 `server-rs/` 的 Rust + SpacetimeDB 多 crate 方案,继续保留可执行的 `server-node/` 入口会误导后续开发,并增加提示词资产、AI 工作流与运行态逻辑的迁移漂移风险。
|
||||
|
||||
## 2. 冻结边界
|
||||
|
||||
1. 禁止新增任何以 `server-node/` 为目标的运行脚本、开发入口、CI 入口或工程依赖。
|
||||
2. 禁止新增从前端、Rust 后端、脚本或配置主动调用 `server-node/` 的逻辑。
|
||||
3. 禁止在 `server-node/` 内继续新增业务能力;后续能力必须落到 `server-rs/` 对应 crate。
|
||||
4. 历史文档、审计文档、迁移基线中允许保留 `server-node/` 作为旧系统来源说明,但不得把它描述成当前推荐实现。
|
||||
5. 第一批物理删除后,提示词资产与提示词相关工作流继续按迁移核对项追踪,不再恢复旧工程目录。
|
||||
|
||||
## 3. 删除前迁移核对项
|
||||
|
||||
以下资产曾作为删除前核对项。第一批物理删除后,旧实现不再从工作区直接读取;如需继续核对能力缺口,只允许通过历史提交、迁移文档或 `server-rs/` 已迁移实现追溯:
|
||||
|
||||
1. `server-node/src/prompts/customWorldEntityPrompts.ts`:自定义世界实体生成 prompt。
|
||||
2. `server-node/src/prompts/customWorldSceneNpcPrompts.ts`:自定义世界场景 NPC prompt。
|
||||
3. `server-node/src/prompts/questPrompts.ts`:任务意图识别 prompt。
|
||||
4. `server-node/src/prompts/runtimeItemPrompts.ts`:运行时物品意图识别 prompt。
|
||||
5. `server-node/src/prompts/customWorldOrchestratorPrompts.ts`:旧 Custom World JSON 生成与修复 prompt。
|
||||
6. `src/services/ai.ts` 与 `src/prompts/customWorldPrompts.ts` 中仍由前端承载的 AI orchestration / prompt 编排。
|
||||
|
||||
## 4. 工程防线
|
||||
|
||||
1. 第一批物理删除后,根目录 `package.json` 不再保留 `server-node:*`、`dev:node`、`check:server-node-freeze` 等旧入口。
|
||||
2. Vite 与本地开发脚本默认只指向 Rust `api-server`,不再保留 Node/Rust 后端切换开关。
|
||||
3. 历史文档允许保留旧 `server-node` 字样,但新增工程入口、脚本、依赖、运行说明不得再指向旧 Node 后端。
|
||||
4. 若后续需要恢复旧能力,只能迁移到 `server-rs/` 对应 crate 或 Axum facade,不恢复 `server-node/` 工程目录。
|
||||
|
||||
## 5. 后续处理顺序
|
||||
|
||||
1. 继续核对提示词资产与 prompt 工作流是否已完整落到 Rust 主线。
|
||||
2. 继续把前端残留业务编排迁入 `server-rs/`。
|
||||
3. 清理技术索引中容易误导当前入口的 Node / Express 文案。
|
||||
4. 保留历史审计材料,但不得把旧 Node 后端描述为当前推荐实现。
|
||||
|
||||
## 6. 已确认迁移项
|
||||
|
||||
### 6.1 场景幕背景图提示词
|
||||
|
||||
2026-04-25 已把旧 Node 自动资产链路中的场景幕背景图提示词包装迁移到 Rust 主线:
|
||||
|
||||
1. 旧来源:`server-node/src/services/customWorldAgentAutoAssetService.ts` 的 `buildSceneActPrompt(...)`。
|
||||
2. 新主源:`server-rs/crates/api-server/src/custom_world.rs` 的 `build_scene_act_background_image_prompt(...)`。
|
||||
3. 使用位置:`generate_draft_foundation_act_backgrounds(...)` 收集 `sceneChapterBlueprints[].acts[]` 后,先构造幕背景图专用提示词,再调用 `generate_custom_world_scene_image_for_profile(...)`。
|
||||
4. 保留语义:世界名、场景名、幕标题、幕摘要、幕目标、过渡钩子、主角色、辅助角色、世界气质、背景描述,以及“只生成环境背景,不出现角色立绘、站位 UI、对白框、按钮或文字”的约束。
|
||||
5. 迁移边界:`server-node/` 仅作为历史来源说明,不再参与运行;后续调整统一修改 Rust 主源。
|
||||
|
||||
## 7. 第一批安全删除记录(2026-04-25)
|
||||
|
||||
本批次开始把冻结隔离升级为物理删除。执行依据是项目后端主线已固定为 `server-rs/` 的 Rust + SpacetimeDB 多 crate 方案,旧 `server-node/` 不再作为可运行、可扩展、可引用的工程目录保留。
|
||||
|
||||
### 7.1 删除范围
|
||||
|
||||
1. 删除 `server-node/` 目录本体,旧实现只允许通过历史提交、迁移文档和已迁移到 `server-rs/` 的代码追溯。
|
||||
2. 删除旧 Node 后端专用入口:`scripts/dev-node.mjs`、`scripts/server-node-frozen.mjs`、`scripts/check-server-node-freeze.mjs`、`scripts/server-node-freeze-baseline.json`、`scripts/smoke-server-node.ts`、`scripts/smoke-same-origin-stack.ts`、`scripts/m7-api-compare.ts`、`scripts/deploy.sh`、`scripts/update.sh`、`view-llm-logs.ps1`。
|
||||
3. 根目录 `package.json` 删除 `server-node:*`、`dev:node`、`m7:api-compare` 与 `check:server-node-freeze` 等旧入口,并移除 `express`、`@types/express` 依赖。
|
||||
4. `npm run dev` 改为启动 Rust 本地栈;Vite 默认只代理到 Rust `api-server`,不再保留 `GENARRATIVE_BACKEND_STACK` 的 Node/Rust 双栈切换口。
|
||||
5. 清理 `.gitignore` 中只服务 `server-node/` 的忽略规则,并同步 `README.md`、`.env.example`、`server-rs/README.md` 与 `scripts/dev-server/README.md`。
|
||||
|
||||
### 7.2 暂不处理范围
|
||||
|
||||
1. 历史 PRD、审计、迁移基线中的 `server-node` 文案暂时保留为历史记录,不在第一批中大规模改写。
|
||||
2. `backend-rewrite-tasklist/` 中以旧 Node 后端为对照的迁移材料暂时保留,作为后续核对 Rust 主线能力缺口的历史审计输入。
|
||||
3. `src/services/ai.ts` 与 `src/prompts/customWorldPrompts.ts` 的前端残留编排不属于本批 Node 后端删除范围;后续继续按“前端只负责表现,业务逻辑进入 `server-rs/`”单独收口。
|
||||
|
||||
### 7.3 后续批次建议
|
||||
|
||||
1. 技术文档索引中的 Node / Express 后端条目只保留为历史资料,不再作为当前入口或推荐方案。
|
||||
2. 后续如继续整理历史文档,只把仍描述 `Express / PostgreSQL` 为当前目标架构的文字修正为“历史阶段口径”。
|
||||
3. 继续把前端残留业务逻辑迁入 `server-rs`;涉及 SpacetimeDB 的设计、实现、脚本和绑定继续显式使用相关 skill。
|
||||
|
||||
### 7.4 本轮安全核对结果
|
||||
|
||||
2026-04-25 本轮开始分批删除时,已确认第一批工程入口层面满足以下条件:
|
||||
|
||||
1. 工作区根目录下已不存在 `server-node/` 物理目录。
|
||||
2. `scripts/` 下已不存在旧 Node 后端专用运行、冻结、smoke、API 对比脚本。
|
||||
3. 根目录 `package.json` 不再包含 `server-node:*`、`dev:node`、`m7:api-compare` 与 `check:server-node-freeze` 入口。
|
||||
4. `package.json` 与 `package-lock.json` 不再包含 `express`、`@types/express`、`pg`、`postgres` 依赖包。
|
||||
5. `README.md`、`scripts/dev-server/README.md`、`server-rs/README.md`、`vite.config.ts`、`scripts/*.mjs`、`src/`、`packages/` 与 `server-rs/` 未发现仍主动启动或调用 `server-node` 的当前工程入口。
|
||||
|
||||
### 7.5 第二批删除边界
|
||||
|
||||
第二批不再删除可运行工程代码,而是清理“容易误导当前实现口径”的历史文档索引:
|
||||
|
||||
1. 只修正文档中仍把 `server-node`、Express 或 PostgreSQL 描述为当前推荐后端的句子。
|
||||
2. 保留审计、PRD、迁移基线中作为历史事实、旧实现来源、能力对照的 `server-node` 引用。
|
||||
3. 不大规模重写包含中文剧情、需求、审计结论的历史文档,避免把真实历史上下文抹平。
|
||||
4. 若发现某个历史文档仍指导新开发继续写 Node 后端,先把该文档改为“历史阶段口径”,再继续工程处理。
|
||||
|
||||
## 8. 开发命令与脚本复核(2026-04-26)
|
||||
|
||||
本轮按“`server-node/` 已完全移除”的状态复核当前开发入口、脚本和工程配置,确认不再保留旧 Node 后端或 Express 运行路径。
|
||||
|
||||
### 8.1 已复核范围
|
||||
|
||||
1. 根目录 `package.json` 与 `package-lock.json`。
|
||||
2. 根目录 `README.md`、`.env.example`、`.gitignore` 与 `vite.config.ts`。
|
||||
3. `scripts/`、`.github/`、`jenkins/` 与 `server-rs/` 下的已跟踪文本文件。
|
||||
|
||||
### 8.2 复核结论
|
||||
|
||||
1. `package.json` 中不存在 `server-node:*`、`dev:node`、`m7:api-compare`、`check:server-node-freeze` 等旧入口。
|
||||
2. `scripts/` 下不存在 `dev-node.mjs`、`smoke-server-node.ts`、`m7-api-compare.ts`、`smoke-same-origin-stack.ts` 等旧 Node 后端脚本。
|
||||
3. `package.json` 与 `package-lock.json` 中不存在 `express`、`@types/express`、`pg`、`postgres` 依赖。
|
||||
4. 当前开发入口继续固定为 `npm run dev`、`npm run dev:web`、`npm run api-server:maincloud` 与 Rust / SpacetimeDB 相关脚本,不恢复旧 Node 后端切换开关。
|
||||
|
||||
## 9. Caddy 本地服务入口移除(2026-04-26)
|
||||
|
||||
`serve:caddy` 仅服务旧的 dist 本地代理验证链路,不再属于当前 Rust / SpacetimeDB 主开发入口。本轮删除该入口和配套文件,避免开发命令继续暴露第二套本地服务方式。
|
||||
|
||||
### 9.1 删除范围
|
||||
|
||||
1. 根目录 `package.json` 删除 `serve:caddy`。
|
||||
2. 删除 `scripts/run-caddy-dev.mjs`。
|
||||
3. 删除 `tools/Caddyfile.dev`。
|
||||
4. `.env.example` 删除 `CADDY_API_UPSTREAM` 样例变量。
|
||||
|
||||
### 9.2 后续口径
|
||||
|
||||
1. 本地完整联调继续使用 `npm run dev`。
|
||||
2. 单独前端联调继续使用 `npm run dev:web` 并通过 Vite 代理到 Rust `api-server`。
|
||||
3. 生产包预览继续使用 Vite `preview`,不恢复 Caddy 专用开发入口。
|
||||
Reference in New Issue
Block a user