# M4:story action 与 gameplay reducer 任务清单 ## 0. 当前执行基线 本阶段与当前仓库里的 RPG 入口与运行时主链重构直接对应,统一以以下文档为准: 1. [../docs/technical/RPG_ENTRY_RUNTIME_CHAIN_REFACTOR_EXECUTION_PLAN_2026-04-21.md](../docs/technical/RPG_ENTRY_RUNTIME_CHAIN_REFACTOR_EXECUTION_PLAN_2026-04-21.md) 2. [../docs/technical/FRONTEND_TO_BACKEND_MIGRATION_EXECUTION_PLAN_2026-04-21.md](../docs/technical/FRONTEND_TO_BACKEND_MIGRATION_EXECUTION_PLAN_2026-04-21.md) 3. [../docs/technical/M4_RPG_RUNTIME_STORY_SPACETIMEDB_BASELINE_2026-04-21.md](../docs/technical/M4_RPG_RUNTIME_STORY_SPACETIMEDB_BASELINE_2026-04-21.md) 当前任务清单只维护 Axum / SpacetimeDB 重写侧的后端迁移项,不再把旧 `GameShell / runtimeRoutes.ts / storyActionService.ts` 命名视为新架构目标。 ### 当前进展(`2026-04-22`) 本阶段首轮已先把 `server-rs` 从“只有 `module-story` 占位目录”推进到“SpacetimeDB 侧 story 会话基座真实可编译”: 1. 已新增 `server-rs/crates/module-story` 真实 crate。 2. 已冻结 `story_session / story_event` 的首版领域类型、状态枚举和字段校验 helper。 3. 已在 `server-rs/crates/spacetime-module` 中新增 `story_session`、`story_event` 两张表。 4. 已新增 `begin_story_session`、`continue_story` 两个 reducer,形成最小会话事件链。 5. 已新增 `begin_story_session_and_return`、`continue_story_and_return` 两个 procedure,形成可同步返回快照的最小 story session contract。 6. 已重新执行 `spacetime generate`,把 `story_session / story_event` Rust bindings 刷入 `spacetime-client/src/module_bindings`。 7. 已在 `server-rs/crates/spacetime-client` 中新增 `begin_story_session(...)`、`continue_story(...)` facade。 8. 已在 `server-rs/crates/api-server` 中新增: - `POST /api/story/sessions` - `POST /api/story/sessions/continue` 9. 已执行 `cargo check -p module-story -p spacetime-module -p spacetime-client -p api-server` 并通过。 6. 已新增 `docs/technical/M4_MODULE_COMBAT_SPACETIMEDB_BASELINE_2026-04-21.md`,冻结 `battle_state` 与 `resolve_combat_action` 的首版字段与规则口径。 7. 已新增 `server-rs/crates/module-runtime-item` 真实 crate。 8. 已冻结 `treasure_record` 的首版领域类型、完整奖励物品快照和字段校验规则。 9. 已在 `server-rs/crates/spacetime-module` 中新增 `treasure_record` 表。 10. 已新增 `resolve_treasure_interaction` reducer 与 `resolve_treasure_interaction_and_return` procedure,并把宝箱奖励同步写入 `inventory_slot`。 11. 已新增 `docs/technical/M4_RPG_RUNTIME_INVENTORY_SPACETIMEDB_BASELINE_2026-04-21.md`,冻结 `inventory_slot` 与 `apply_inventory_mutation` 的首版字段与规则口径。 12. 已新增 `server-rs/crates/module-inventory` 真实 crate。 13. 已在 `server-rs/crates/spacetime-module` 中新增 `inventory_slot` 表。 14. 已新增 `apply_inventory_mutation` reducer,形成最小背包主链。 15. 已新增 `docs/technical/M4_MODULE_NPC_SPACETIMEDB_BASELINE_2026-04-21.md`,冻结 `npc_state`、`resolve_npc_social_action` 与 `resolve_npc_interaction` 的首版字段与交互口径。 16. 已新增 `server-rs/crates/module-npc` 真实 crate。 17. 已在 `server-rs/crates/spacetime-module` 中新增 `npc_state` 表。 18. 已新增 `upsert_npc_state`、`resolve_npc_social_action`、`resolve_npc_interaction` 及对应 procedure。 19. 已新增 `docs/technical/M4_MODULE_NPC_COMBAT_ORCHESTRATION_BASELINE_2026-04-21.md`,冻结 `npc_fight / npc_spar` 到 `battle_state` 的最小联合编排口径。 20. 已在 `server-rs/crates/spacetime-module` 中新增 `resolve_npc_battle_interaction_and_return` procedure,把 NPC 开战交互与 battle 初始化写入串到同一事务。 15. 已新增 `docs/technical/M4_MODULE_PROGRESSION_SPACETIMEDB_BASELINE_2026-04-21.md`,冻结 `player_progression / chapter_progression` 的首版字段、成长曲线与章节预算口径。 16. 已新增 `server-rs/crates/module-progression` 真实 crate。 17. 已在 `server-rs/crates/spacetime-module` 中新增 `player_progression`、`chapter_progression` 两张表。 18. 已新增 `get_player_progression_or_default`、`grant_player_progression_experience`、`upsert_chapter_progression`、`apply_chapter_progression_ledger_entry` 及对应 procedure。 19. 已新增 `docs/technical/M4_RPG_RUNTIME_QUEST_SPACETIMEDB_BASELINE_2026-04-21.md`,冻结 `quest_record / quest_log / apply_quest_signal` 的首版字段、日志口径与交付状态流转规则。 20. 已新增 `server-rs/crates/module-quest` 真实 crate。 21. 已在 `server-rs/crates/spacetime-module` 中新增 `quest_record`、`quest_log` 两张表。 22. 已新增 `accept_quest`、`apply_quest_signal`、`acknowledge_quest_completion`、`turn_in_quest` reducer,形成最小任务闭环。 23. 已执行 `cargo test -p module-quest`、`cargo check -p spacetime-module`、`cargo check -p api-server` 与全量 `cargo check` 并通过。 24. 已新增 `docs/technical/M4_PROGRESSION_QUEST_COMBAT_INTEGRATION_2026-04-21.md`,冻结任务交付与战斗胜利到成长系统的联动口径。 25. 已把 `turn_in_quest` 接到 `player_progression / chapter_progression` 的最小经验写入。 26. 已把 `resolve_combat_action(Victory)` 接到 `player_progression / chapter_progression` 的最小经验写入。 27. 已把 `turn_in_quest.reward.items` 接到 `inventory_slot` 发物链,形成任务交付的最小物品奖励闭环。 28. 已新增 `docs/technical/M4_RPG_RUNTIME_STORY_SESSION_STATE_QUERY_DESIGN_2026-04-22.md`,冻结最小 `story state` 查询切片,只开放 `storySession + storyEvents` 真相态查询。 29. 已在 `server-rs/crates/api-server` 中挂出 `GET /api/story/sessions/:storySessionId/state`,通过 `spacetime-client.get_story_session_state(...)` 读取 `SpacetimeDB procedure` 返回的会话快照与事件流。 30. 已新增 `docs/technical/M4_COMBAT_REWARD_INVENTORY_INTEGRATION_2026-04-22.md`,冻结 `battle_state.reward_items` 与 `resolve_combat_action(Victory)` 发物到 `inventory_slot` 的最小联动口径。 31. 已新增 `docs/technical/M4_MODULE_COMBAT_STATE_QUERY_DESIGN_2026-04-22.md`,冻结最小 `battle state` 查询切片,只开放单个 `battleState` 真相态查询。 32. 已在 `server-rs/crates/spacetime-module` 中新增 `get_battle_state` procedure,按 `battle_state_id` 返回当前战斗快照。 33. 已在 `server-rs/crates/spacetime-client` 中新增 `get_battle_state(...)` facade,供 Axum 同步读取 battle 真相态。 34. 已在 `server-rs/crates/api-server` 中挂出 `GET /api/story/battles/:battleStateId`,通过 `spacetime-client.get_battle_state(...)` 返回单战斗快照。 35. 已在 `server-rs/crates/spacetime-client` 中新增 `resolve_npc_battle_interaction(...)` facade,把 `resolve_npc_battle_interaction_and_return` procedure 映射为稳定 Rust record,供 Axum 直接消费。 36. 已在 `server-rs/crates/api-server` 中挂出 `POST /api/story/npc/battle`,当前只接受 `npc_fight / npc_spar`,同步返回 `npcInteraction + battleState`。 37. 已执行 `cargo check -p spacetime-client -p api-server` 并通过,完成 `module-npc -> spacetime-client -> api-server` 的最小 NPC 开战同步返回链闭环。 38. 已重新执行 `spacetime generate --no-config --lang rust --out-dir D:\\Genarrative\\server-rs\\crates\\spacetime-client\\src\\module_bindings --module-path D:\\Genarrative\\server-rs\\crates\\spacetime-module --include-private --yes`,把 `get_battle_state`、`battle_state.reward_items` 与 `custom_world_agent_session` 相关 bindings 刷入 `spacetime-client/src/module_bindings`。 39. 已把 `server-rs/crates/spacetime-client/src/lib.rs` 中原本占位返回错误的 `get_battle_state(...)` 改成真实 procedure 调用,当前 battle query 已不再停留在 facade stub。 40. 已再次执行 `cargo check -p spacetime-client --manifest-path D:\\Genarrative\\server-rs\\Cargo.toml` 与 `cargo check -p api-server --manifest-path D:\\Genarrative\\server-rs\\Cargo.toml`,当前 battle/story 新链路在编译层已恢复通过。 41. 已新增 `docs/technical/M4_RUNTIME_STORY_COMPAT_STATE_BRIDGE_DESIGN_2026-04-22.md`,冻结旧 `POST /api/runtime/story/state/resolve` 的首版兼容桥边界,明确当前先做 DTO 与状态桥,不提前误宣称 `actions/resolve` 已可迁移。 42. 已在 `server-rs/crates/shared-contracts` 中新增 `runtime_story` 模块,冻结 `RuntimeStoryStateResolveRequest`、`RuntimeStoryActionResponse` 以及 `viewModel / presentation / patches / snapshot` 的首版 camelCase DTO,与当前前端消费口径对齐。 当前验证边界补充: 1. `story_sessions` / `story_battles` 的二进制测试目标在当前机器上编译耗时很长,已有多轮回归尝试,但还没有在单次时窗内收敛到最终断言结果。 2. `npm run check:encoding` 已启动到 `node scripts/check-encoding.mjs`,但当前尚未在单次时窗内跑完,不能标记为已完成。 3. 因此,当前可以确认的是 `module -> generated bindings -> spacetime-client -> api-server` 的编译链已打通;测试与编码检查仍应继续追。 当前这轮仍未扩到 `resolve_story_action`、`sync_runtime_snapshot_projection`、旧 `/api/runtime/story/*` 兼容接口和前端实际 runtime story API 切换,这些继续保留在后续 `M4` 工作项中。 ## 1. SpacetimeDB gameplay 表 - [x] 设计 `story_session` - [x] 设计 `story_event` - [x] 设计 `npc_state` - [x] 设计 `quest_record` - [x] 设计 `inventory_slot` - [x] 设计 `treasure_record` - [x] 设计 `battle_state` - [x] 设计 `player_progression` - [x] 设计 `chapter_progression` ## 2. 核心 reducer - [ ] 设计 `resolve_story_action` - [x] 设计 `continue_story` - [x] 设计 `begin_story_session` - [ ] 设计 `sync_runtime_snapshot_projection` - [x] 设计 `apply_quest_signal` - [x] 设计 `apply_inventory_mutation` - [x] 设计 `resolve_npc_interaction` - [x] 设计 `resolve_treasure_interaction` - [x] 设计 `resolve_combat_action` - [x] 设计 `update_progression_state` ## 3. 当前主链模块落位 - [ ] 迁移 `rpg-entry` 配套后端入口能力 - [ ] 迁移 `rpg-profile` 资料域 - [ ] 迁移 `rpg-runtime-story` - [x] 迁移 `combat` - [ ] 迁移 `inventory` - [ ] 迁移 `npc` - [x] 迁移 `progression` - [x] 迁移 `quest` - [x] 迁移 `runtime-item` - [ ] 迁移 runtime snapshot 归一化、view model compiler 与状态同步规则 ## 4. 兼容接口 - [ ] 兼容 `POST /api/runtime/story/actions/resolve` - [ ] 兼容 `GET /api/runtime/story/state/:sessionId` - [ ] 兼容 `POST /api/runtime/story/state/resolve` - [ ] 兼容 `POST /api/runtime/story/initial` - [ ] 兼容 `POST /api/runtime/story/continue` 补充说明: 1. 当前已落地的是新的 Rust facade: - `POST /api/story/sessions` - `POST /api/story/sessions/continue` - `GET /api/story/sessions/:storySessionId/state` - `GET /api/story/battles/:battleStateId` - `POST /api/story/npc/battle` 2. 其中前 3 个接口是 `story session` 真相链路,后 2 个接口是 battle / NPC 开战真相链路,都不等价于旧 Node 的 LLM `runtime/story/*` 兼容接口。 3. 当前新增的 `story state` 查询只返回 `storySession + storyEvents`,还没有兼容旧 `RuntimeStoryActionResponse`、`currentStory`、`availableOptions`。 4. 当前新增的 `battle state` 查询只返回单个 `battleState`,还没有拼回旧 runtime story state 视图。 5. 在 `resolve_story_action / story state` contract 未冻结前,不应误勾选旧兼容接口。 ## 5. ViewModel 兼容 - [ ] 兼容当前 `RuntimeStoryActionResponse` - [ ] 兼容当前 `RuntimeStoryOptionView` - [ ] 兼容当前 `interaction` 元数据 - [ ] 兼容当前 battle / toast / patch 响应结构 - [ ] 兼容当前 `currentStory` 回填逻辑 ## 6. 阶段验收 - [ ] 当前前端 story 选项点击后可走新后端闭环 - [ ] NPC / quest / treasure / combat 主循环行为不回退 - [ ] `story state` 恢复链可用 - [ ] 后端边界与当前 `rpgEntry -> rpgSession -> rpgRuntime -> rpgRuntimeStory -> rpgProfile` 口径一致 - [ ] 旧 Node 版 story route 回归用例完成平移