diff --git a/backend-rewrite-tasklist/01_M0_M2_FOUNDATION_AND_AUTH.md b/backend-rewrite-tasklist/01_M0_M2_FOUNDATION_AND_AUTH.md index e3fef59f..35865c61 100644 --- a/backend-rewrite-tasklist/01_M0_M2_FOUNDATION_AND_AUTH.md +++ b/backend-rewrite-tasklist/01_M0_M2_FOUNDATION_AND_AUTH.md @@ -8,7 +8,8 @@ 交付物:[M0_CAPABILITY_SURFACE_BASELINE_2026-04-20.md](./M0_CAPABILITY_SURFACE_BASELINE_2026-04-20.md) - [x] 整理当前后端 96 条路由并生成一份“旧接口 -> 新实现”映射表 交付物:[M0_ROUTE_MIGRATION_MATRIX_2026-04-20.md](./M0_ROUTE_MIGRATION_MATRIX_2026-04-20.md) -- [ ] 整理当前 12 个内部模块并锁定迁移归属 +- [x] 整理当前 12 个内部模块并锁定迁移归属 + 交付物:[M0_MODULE_MIGRATION_BASELINE_2026-04-20.md](./M0_MODULE_MIGRATION_BASELINE_2026-04-20.md) - [ ] 整理当前所有 SSE 接口与事件格式 - [ ] 整理当前所有 `/generated-*` 静态资源前缀 - [ ] 整理当前前端直接依赖的响应头、envelope、错误格式 diff --git a/backend-rewrite-tasklist/M0_MODULE_MIGRATION_BASELINE_2026-04-20.md b/backend-rewrite-tasklist/M0_MODULE_MIGRATION_BASELINE_2026-04-20.md new file mode 100644 index 00000000..92d895c0 --- /dev/null +++ b/backend-rewrite-tasklist/M0_MODULE_MIGRATION_BASELINE_2026-04-20.md @@ -0,0 +1,276 @@ +# M0:内部模块迁移归属基线 + +日期:`2026-04-20` + +依据来源: + +- [../docs/technical/NODE_BACKEND_MODULE_AND_API_INDEX.md](../docs/technical/NODE_BACKEND_MODULE_AND_API_INDEX.md) +- [../server-node/manifests/backend-capability-index.json](../server-node/manifests/backend-capability-index.json) +- [../docs/technical/SPACETIMEDB_AXUM_OSS_BACKEND_REWRITE_DESIGN_2026-04-20.md](../docs/technical/SPACETIMEDB_AXUM_OSS_BACKEND_REWRITE_DESIGN_2026-04-20.md) + +## 1. 文档目的 + +这份文档用于完成 `M0` 的第三条任务: + +- 整理当前 `12` 个内部模块并锁定迁移归属 + +这里的“迁移归属”不是简单把旧目录名照搬到 Rust,而是要求后续重写必须先明确: + +1. 每个旧模块在新架构中的主归属 crate。 +2. 每个旧模块是否需要拆成“SpacetimeDB 状态层 + Axum/application 编排层”。 +3. 每个旧模块的状态真相应该进入 `SpacetimeDB`、`OSS` 还是开发态本地文件适配。 +4. 每个旧模块优先落在哪个迁移阶段,避免后续任务拆分时反复改口径。 + +补充边界: + +1. 本文只覆盖当前 `server-node/src/modules/*` 下的 `12` 个内部模块。 +2. `auth`、`health` 虽然属于后端能力面,但不在这 `12` 个内部模块目录里,因此不在本文表内。 + +## 2. 冻结结论 + +当前 Node 后端的正式内部模块固定为以下 `12` 个: + +| 模块 ID | 中文名称 | 当前目录 | 关联路由数 | 当前对外暴露面 | 重写后主归属 | 重写后次归属 | 目标迁移阶段 | +| --- | --- | --- | --- | --- | --- | --- | --- | +| `ai` | AI 编排模块 | `server-node/src/modules/ai` | `23` | `runtime-main` | `application + llm-service` | `contracts + api-server SSE facade` | `M4`、`M5`、`M6` | +| `assets` | 资产工具模块 | `server-node/src/modules/assets` | `18` | `assets` | `application::assets + oss-service` | `spacetime-module::asset_metadata` | `M6` | +| `combat` | 战斗结算模块 | `server-node/src/modules/combat` | `1` | `runtime-story-action` | `spacetime-module::gameplay::combat` | `domain::combat` | `M4` | +| `custom-world` | 自定义世界运行时模块 | `server-node/src/modules/custom-world` | `26` | `runtime-main` | `spacetime-module::custom_world + application::custom_world` | `llm-service + oss-service` | `M5` | +| `editor` | 编辑器资源模块 | `server-node/src/modules/editor` | `3` | `editor` | `api-server::editor + application::editor` | `oss-service`、开发态本地文件适配 | `M6` | +| `inventory` | 背包与物品变更模块 | `server-node/src/modules/inventory` | `1` | `runtime-story-action` | `spacetime-module::gameplay::inventory` | `domain::inventory` | `M4` | +| `npc` | NPC 交互模块 | `server-node/src/modules/npc` | `6` | `runtime-story-action`、`runtime-main` | `spacetime-module::gameplay::npc` | `application::npc_dialogue + llm-service` | `M4`、`M5` | +| `progression` | 成长与关卡进程模块 | `server-node/src/modules/progression` | `3` | `runtime-story-action`、`runtime-main` | `spacetime-module::gameplay::progression` | `domain::progression` | `M3`、`M4` | +| `quest` | 任务运行时模块 | `server-node/src/modules/quest` | `4` | `runtime-main`、`runtime-story-action` | `spacetime-module::gameplay::quest` | `application::quest_drafting + llm-service` | `M3`、`M4` | +| `runtime` | 运行时状态基座模块 | `server-node/src/modules/runtime` | `32` | `runtime-main`、`runtime-story-action` | `spacetime-module::runtime` | `application::runtime_facade` | `M3` | +| `runtime-item` | 运行时物品模块 | `server-node/src/modules/runtime-item` | `2` | `runtime-main`、`runtime-story-action` | `spacetime-module::gameplay::runtime_item` | `application::item_intent + llm-service` | `M4` | +| `story` | 故事会话模块 | `server-node/src/modules/story` | `10` | `runtime-main`、`runtime-story-action` | `spacetime-module::gameplay::story` | `application::story_facade + api-server SSE facade` | `M4` | + +冻结总数: + +1. 内部模块目录:`12` +2. 关联路由数最多的模块:`runtime`,共 `32` 条 +3. 纯外部副作用导向模块:`ai`、`assets`、`editor` +4. 纯状态规则导向模块:`combat`、`inventory` +5. 需要“状态层 + 编排层”双落位的混合模块:`custom-world`、`npc`、`quest`、`runtime-item`、`story` + +## 3. 锁定迁移归属规则 + +后续所有重写实现,必须先遵守以下归属规则: + +1. 纯运行时状态、纯规则计算、纯领域变更,优先进入 `spacetime-module/` 与 `domain/`,不能继续把真相留在 Axum 内存或 Node 风格 service。 +2. 外部模型调用、OSS 上传、短信、微信、本地文件读写,统一放在 `application/ + api-server/ + infra service`,不能塞进 SpacetimeDB reducer。 +3. 任何当前“一个模块同时做状态和副作用”的能力,在新架构里都必须拆成: + - `SpacetimeDB`:状态真相与读模型 + - `Axum/application`:外部编排、SSE、对象上传、三方调用 +4. `public/generated-*` 不再是任何模块的真相源;未来只能作为兼容访问前缀或 CDN 映射。 +5. 不允许把旧模块简单合并成一个“大 runtime service”;必须保留可对照的领域边界。 + +## 4. 模块迁移矩阵 + +| 当前模块 | 当前职责摘要 | 新状态真相源 | 新外部副作用归属 | 迁移后必须落位 | +| --- | --- | --- | --- | --- | +| `ai` | prompt 编排、聊天/剧情/世界生成组织 | `SpacetimeDB` 只存任务和结果引用,不存编排过程真相 | `llm-service` | 只能留在 Axum/application 侧,禁止直接进 reducer。 | +| `assets` | 生成、发布、缓存、Qwen 精灵表 | `asset_job`、`asset_object`、`asset_manifest` 等表 | `oss-service` + 外部媒体模型 | 二进制进 OSS,任务与引用进 SpacetimeDB。 | +| `combat` | 战斗结算、数值变化 | `battle_state`、`story_event` | 无 | 作为纯 reducer 规则模块落到 gameplay。 | +| `custom-world` | 世界资料、问答流、Agent 草稿与编译 | `custom_world_*` 系列表 | `llm-service`、`oss-service` | 世界状态在 SpacetimeDB,编译/生成在 Axum。 | +| `editor` | 编辑器 JSON 读写、图标枚举 | 开发态本地文件;线上对象元数据可入 SpacetimeDB | Axum 本地文件适配或 OSS | 第一阶段保留 Axum 工具面,不迁到前端。 | +| `inventory` | 背包变更、物品副作用、NPC 背包交互 | `inventory_slot`、`story_event` | 无 | 归入 story action 对应 reducer。 | +| `npc` | 互动规则、关系变化、招募/对话语义 | `npc_state`、`story_event` | `application::npc_dialogue + llm-service` | 状态归 SpacetimeDB,台词生成归 Axum。 | +| `progression` | 等级、章节、敌对 scaling、benchmark | `player_progression`、`chapter_progression` | 无 | 作为 runtime / story 公共领域模块进入 SpacetimeDB。 | +| `quest` | 任务意图、日志、进度变化 | `quest_record`、`story_event` | `application::quest_drafting + llm-service` | 任务状态归 SpacetimeDB,生成型任务草案归 Axum。 | +| `runtime` | 快照、设置、资料页、状态归一化 | `runtime_snapshot`、`runtime_setting`、`profile_*` | 无 | 作为新后端最先迁移的状态基座模块。 | +| `runtime-item` | 物品意图、奖励解析、宝藏逻辑 | `treasure_record`、`inventory_slot`、`story_event` | `application::item_intent + llm-service` | 奖励结算归 reducer,意图生成归 Axum。 | +| `story` | 会话状态、动作分发、主循环 | `story_session`、`story_event` | `application::story_facade + SSE` | 主循环状态归 SpacetimeDB,流式输出由 Axum 兼容。 | + +## 5. 各模块冻结要求 + +### 5.1 `ai` + +当前定位: + +1. 负责剧情、多轮聊天、自定义世界等 prompt 编排。 +2. 自身不负责持久化,但会被多条 runtime 路由反复调用。 + +重写后的冻结要求: + +1. 主归属固定为 `application + llm-service`,不是 `spacetime-module`。 +2. 后续如果需要记录 AI 阶段状态,只能把任务状态或结果引用写入 SpacetimeDB,不把供应商 SDK 与 prompt 执行放进 reducer。 +3. 与 `story`、`custom-world`、`runtime-item`、`quest` 的关系固定为“它们产生命令,`ai` 负责外部生成”。 + +### 5.2 `assets` + +当前定位: + +1. 负责角色形象、动作、Qwen 精灵表生成。 +2. 负责发布到 `public/generated-*` 与局部 manifest。 + +重写后的冻结要求: + +1. 二进制对象一律进入 `OSS`。 +2. 主归属固定为 `application::assets + oss-service`。 +3. 资产任务状态、对象引用关系、发布绑定关系必须进入 `spacetime-module::asset_metadata`。 +4. 后续不允许继续以本地 `public/generated-*` 是否存在文件作为业务真相。 + +### 5.3 `combat` + +当前定位: + +1. 提供 story action 里的战斗型结算。 +2. 本质是纯规则计算。 + +重写后的冻结要求: + +1. 主归属固定为 `spacetime-module::gameplay::combat`。 +2. 不单独拥有 HTTP 路由,也不直接依赖外部 IO。 +3. 后续实现必须保持纯规则、可测试、可被 `resolve_story_action` reducer 复用。 + +### 5.4 `custom-world` + +当前定位: + +1. 负责 creator intent、world profile、传统问答流、Agent 运行时类型。 +2. 同时牵涉世界编译、资产生成和公开画廊。 + +重写后的冻结要求: + +1. 这是标准的双落位模块: + - `SpacetimeDB` 保存会话、草稿、作品、画廊、Agent 状态。 + - `Axum/application` 负责编译、SSE、外部 LLM 与资产生成编排。 +2. 传统问答流和 Agent 流必须拆表,不能继续长期混成一个大 JSON 会话体。 +3. 对外仍然要兼容当前 `/api/custom-world/*` 与 `/api/runtime/custom-world/*` 访问习惯。 + +### 5.5 `editor` + +当前定位: + +1. 读写编辑器资源 JSON。 +2. 枚举工作区 `public/Icons` 图标资源。 + +重写后的冻结要求: + +1. 第一阶段主归属固定为 `api-server::editor + application::editor`。 +2. 开发态允许继续读写本地文件,线上态再逐步对象化。 +3. 不允许把编辑器写盘逻辑迁到前端浏览器侧。 +4. 仍必须保留 `EDITOR_API_ENABLED` 开关门禁。 + +### 5.6 `inventory` + +当前定位: + +1. 负责背包变更、赠礼、NPC 背包交互等副作用。 +2. 当前主要被 story action 调用。 + +重写后的冻结要求: + +1. 主归属固定为 `spacetime-module::gameplay::inventory`。 +2. 与 `story`、`runtime-item` 的交互必须通过 reducer 协调,不能回到“多个 service 各自改 JSON”。 +3. 后续如需对外展示背包读模型,优先通过 view 暴露,不新增独立真相副本。 + +### 5.7 `npc` + +当前定位: + +1. 负责 NPC 关系、招募、交互规则与场景 NPC 语义。 +2. 同时参与 runtime 聊天流和 story action 结算。 + +重写后的冻结要求: + +1. 状态真相固定在 `spacetime-module::gameplay::npc`。 +2. LLM 对话、招募话术、流式文本输出固定由 `application::npc_dialogue + llm-service` 处理。 +3. 不允许把 NPC 状态又分散回聊天 session store、本地缓存或前端临时状态。 + +### 5.8 `progression` + +当前定位: + +1. 负责角色成长、章节推进、敌对强度等规则。 +2. 同时影响 snapshot hydrate 与 story action 结算。 + +重写后的冻结要求: + +1. 主归属固定为 `spacetime-module::gameplay::progression`。 +2. 仍保持纯规则、纯领域建模,不承接外部 IO。 +3. 作为 `runtime` 与 `story` 的公共领域组件,不能被重新塞回单一路由 handler。 + +### 5.9 `quest` + +当前定位: + +1. 负责任务语义、任务日志、任务进度信号。 +2. 既参与 AI 草案生成,也参与 story action 结算。 + +重写后的冻结要求: + +1. 任务主状态固定进入 `spacetime-module::gameplay::quest`。 +2. AI 生成的任务候选与草案编排固定由 `application::quest_drafting + llm-service` 承担。 +3. 前端兼容接口仍走 `/api/runtime/quests/*` 或 story action 聚合,不新增前端直连任务状态写入口。 + +### 5.10 `runtime` + +当前定位: + +1. 是当前运行时快照、设置、资料页、状态归一化的基座模块。 +2. 路由覆盖最广,是 Node 版后端迁移的第一主战场。 + +重写后的冻结要求: + +1. 主归属固定为 `spacetime-module::runtime`。 +2. `runtime_snapshot`、`runtime_setting`、`profile_*` 等读写模型优先在 `M3` 完成迁移。 +3. Axum 只保留兼容 facade,不再继续让快照真相停留在 PostgreSQL 风格 repository。 + +### 5.11 `runtime-item` + +当前定位: + +1. 负责运行时物品意图、奖励、宝藏解析与剧情指纹。 +2. 同时受到 AI 生成与 story action 结算驱动。 + +重写后的冻结要求: + +1. 奖励、掉落、宝藏等状态变化固定进入 `spacetime-module::gameplay::runtime_item`。 +2. 物品意图生成固定由 `application::item_intent + llm-service` 承接。 +3. 物品领域不能再拆成“部分在 story、部分在 route、部分在前端”的临时实现。 + +### 5.12 `story` + +当前定位: + +1. 负责运行时故事会话、动作分发与 state 恢复。 +2. 当前既暴露 REST,也暴露与聊天/继续剧情相关的流式体验。 + +重写后的冻结要求: + +1. 主归属固定为 `spacetime-module::gameplay::story`。 +2. SSE 输出与兼容 DTO 拼装固定由 `application::story_facade + api-server SSE facade` 负责。 +3. `storyAction.resolve` 的跨模块联动必须以 `story` 为编排入口,但不再由单个 Node service 直接改整包 JSON。 + +## 6. 本轮冻结后的硬约束 + +后续迁移中,不允许出现以下情况: + +1. 把 `ai`、`assets`、`editor` 直接放进 SpacetimeDB reducer 执行三方网络或文件系统 IO。 +2. 把 `combat`、`inventory`、`progression` 重新做成只存在于 Axum handler 内部的计算 helper。 +3. 把 `custom-world`、`story`、`npc` 这类混合模块继续保留为“单大对象 JSON + 单大 service 写回”模式。 +4. 把 `runtime` 当成一个兜底垃圾桶,把其他领域模块重新并回去。 +5. 在没有对应 Axum facade 的前提下,让前端第一阶段直接依赖 SpacetimeDB 原生写接口。 + +## 7. 本任务完成定义 + +当以下条件成立时,这条任务视为完成: + +1. 当前 `12` 个内部模块已经有正式书面冻结清单。 +2. 每个模块都已明确: + - 当前目录 + - 关联路由数 + - 对外暴露面 + - 重写后主归属 + - 重写后次归属 + - 目标迁移阶段 +3. 后续拆 `server-rs/` crate、建 SpacetimeDB bounded context、排 M3~M6 任务时,可以直接引用本文,不再靠口头记忆。 + +## 8. 后续直接依赖这份基线的任务 + +1. 设计 `server-rs/` workspace 与 crate 边界 +2. 设计 SpacetimeDB `runtime / gameplay / custom_world / asset_metadata` 表分层 +3. 设计 story action reducer 的跨模块协作边界 +4. 设计 custom world / assets / editor 的 Axum facade diff --git a/backend-rewrite-tasklist/README.md b/backend-rewrite-tasklist/README.md index 4ffd3ee2..61cd66c9 100644 --- a/backend-rewrite-tasklist/README.md +++ b/backend-rewrite-tasklist/README.md @@ -16,6 +16,7 @@ - [07_CROSS_CUTTING_AND_ACCEPTANCE.md](./07_CROSS_CUTTING_AND_ACCEPTANCE.md):横向专项、执行顺序与最终验收清单。 - [M0_CAPABILITY_SURFACE_BASELINE_2026-04-20.md](./M0_CAPABILITY_SURFACE_BASELINE_2026-04-20.md):当前 Node 后端 `6` 个挂载面的冻结基线,用于后续接口映射、模块迁移与验收对照。 - [M0_ROUTE_MIGRATION_MATRIX_2026-04-20.md](./M0_ROUTE_MIGRATION_MATRIX_2026-04-20.md):当前 `96` 条后端路由的“旧接口 -> 新实现”迁移矩阵,用于 Axum 路由树和 application service 落位。 +- [M0_MODULE_MIGRATION_BASELINE_2026-04-20.md](./M0_MODULE_MIGRATION_BASELINE_2026-04-20.md):当前 `12` 个内部模块的迁移归属基线,用于锁定 Rust crate、SpacetimeDB bounded context 与 Axum/application 分工。 ## 维护规则