24 KiB
24 KiB
M4:story action 与 gameplay reducer 任务清单
0. 当前执行基线
本阶段与当前仓库里的 RPG 入口与运行时主链重构直接对应,统一以以下文档为准:
- ../docs/technical/RPG_ENTRY_RUNTIME_CHAIN_REFACTOR_EXECUTION_PLAN_2026-04-21.md
- ../docs/technical/FRONTEND_TO_BACKEND_MIGRATION_EXECUTION_PLAN_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 会话基座真实可编译”:
- 已新增
server-rs/crates/module-story真实 crate。 - 已冻结
story_session / story_event的首版领域类型、状态枚举和字段校验 helper。 - 已在
server-rs/crates/spacetime-module中新增story_session、story_event两张表。 - 已新增
begin_story_session、continue_story两个 reducer,形成最小会话事件链。 - 已新增
begin_story_session_and_return、continue_story_and_return两个 procedure,形成可同步返回快照的最小 story session contract。 - 已重新执行
spacetime generate,把story_session / story_eventRust bindings 刷入spacetime-client/src/module_bindings。 - 已在
server-rs/crates/spacetime-client中新增begin_story_session(...)、continue_story(...)facade。 - 已在
server-rs/crates/api-server中新增:POST /api/story/sessionsPOST /api/story/sessions/continue
- 已执行
cargo check -p module-story -p spacetime-module -p spacetime-client -p api-server并通过。 - 已新增
docs/technical/M4_MODULE_COMBAT_SPACETIMEDB_BASELINE_2026-04-21.md,冻结battle_state与resolve_combat_action的首版字段与规则口径。 - 已新增
server-rs/crates/module-runtime-item真实 crate。 - 已冻结 runtime item 侧奖励快照与物品写回基线,为后续奖励链并入 inventory / quest / combat 提供统一底层能力。
- 已在
server-rs/crates/spacetime-module中补齐 runtime item / inventory / quest / combat 所需的奖励落表与回写依赖。 - 当前 M4 runtime story compat bridge 已明确移除旧
treasure_*遭遇动作概念,不再把宝箱遭遇视作本阶段 runtime story 主链目标。 - 已新增
docs/technical/M4_RPG_RUNTIME_INVENTORY_SPACETIMEDB_BASELINE_2026-04-21.md,冻结inventory_slot与apply_inventory_mutation的首版字段与规则口径。 - 已新增
server-rs/crates/module-inventory真实 crate。 - 已在
server-rs/crates/spacetime-module中新增inventory_slot表。 - 已新增
apply_inventory_mutationreducer,形成最小背包主链。 - 已新增
docs/technical/M4_MODULE_NPC_SPACETIMEDB_BASELINE_2026-04-21.md,冻结npc_state、resolve_npc_social_action与resolve_npc_interaction的首版字段与交互口径。 - 已新增
server-rs/crates/module-npc真实 crate。 - 已在
server-rs/crates/spacetime-module中新增npc_state表。 - 已新增
upsert_npc_state、resolve_npc_social_action、resolve_npc_interaction及对应 procedure。 - 已新增
docs/technical/M4_MODULE_NPC_COMBAT_ORCHESTRATION_BASELINE_2026-04-21.md,冻结npc_fight / npc_spar到battle_state的最小联合编排口径。 - 已在
server-rs/crates/spacetime-module中新增resolve_npc_battle_interaction_and_returnprocedure,把 NPC 开战交互与 battle 初始化写入串到同一事务。 - 已新增
docs/technical/M4_MODULE_PROGRESSION_SPACETIMEDB_BASELINE_2026-04-21.md,冻结player_progression / chapter_progression的首版字段、成长曲线与章节预算口径。 - 已新增
server-rs/crates/module-progression真实 crate。 - 已在
server-rs/crates/spacetime-module中新增player_progression、chapter_progression两张表。 - 已新增
get_player_progression_or_default、grant_player_progression_experience、upsert_chapter_progression、apply_chapter_progression_ledger_entry及对应 procedure。 - 已新增
docs/technical/M4_RPG_RUNTIME_QUEST_SPACETIMEDB_BASELINE_2026-04-21.md,冻结quest_record / quest_log / apply_quest_signal的首版字段、日志口径与交付状态流转规则。 - 已新增
server-rs/crates/module-quest真实 crate。 - 已在
server-rs/crates/spacetime-module中新增quest_record、quest_log两张表。 - 已新增
accept_quest、apply_quest_signal、acknowledge_quest_completion、turn_in_questreducer,形成最小任务闭环。 - 已执行
cargo test -p module-quest、cargo check -p spacetime-module、cargo check -p api-server与全量cargo check并通过。 - 已新增
docs/technical/M4_PROGRESSION_QUEST_COMBAT_INTEGRATION_2026-04-21.md,冻结任务交付与战斗胜利到成长系统的联动口径。 - 已把
turn_in_quest接到player_progression / chapter_progression的最小经验写入。 - 已把
resolve_combat_action(Victory)接到player_progression / chapter_progression的最小经验写入。 - 已把
turn_in_quest.reward.items接到inventory_slot发物链,形成任务交付的最小物品奖励闭环。 - 已新增
docs/technical/M4_RPG_RUNTIME_STORY_SESSION_STATE_QUERY_DESIGN_2026-04-22.md,冻结最小story state查询切片,只开放storySession + storyEvents真相态查询。 - 已在
server-rs/crates/api-server中挂出GET /api/story/sessions/:storySessionId/state,通过spacetime-client.get_story_session_state(...)读取SpacetimeDB procedure返回的会话快照与事件流。 - 已新增
docs/technical/M4_COMBAT_REWARD_INVENTORY_INTEGRATION_2026-04-22.md,冻结battle_state.reward_items与resolve_combat_action(Victory)发物到inventory_slot的最小联动口径。 - 已新增
docs/technical/M4_MODULE_COMBAT_STATE_QUERY_DESIGN_2026-04-22.md,冻结最小battle state查询切片,只开放单个battleState真相态查询。 - 已在
server-rs/crates/spacetime-module中新增get_battle_stateprocedure,按battle_state_id返回当前战斗快照。 - 已在
server-rs/crates/spacetime-client中新增get_battle_state(...)facade,供 Axum 同步读取 battle 真相态。 - 已在
server-rs/crates/api-server中挂出GET /api/story/battles/:battleStateId,通过spacetime-client.get_battle_state(...)返回单战斗快照。 - 已在
server-rs/crates/spacetime-client中新增resolve_npc_battle_interaction(...)facade,把resolve_npc_battle_interaction_and_returnprocedure 映射为稳定 Rust record,供 Axum 直接消费。 - 已在
server-rs/crates/api-server中挂出POST /api/story/npc/battle,当前只接受npc_fight / npc_spar,同步返回npcInteraction + battleState。 - 已执行
cargo check -p spacetime-client -p api-server并通过,完成module-npc -> spacetime-client -> api-server的最小 NPC 开战同步返回链闭环。 - 已重新执行
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。 - 已把
server-rs/crates/spacetime-client/src/lib.rs中原本占位返回错误的get_battle_state(...)改成真实 procedure 调用,当前 battle query 已不再停留在 facade stub。 - 已再次执行
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 新链路在编译层已恢复通过。 - 已新增
docs/technical/M4_RUNTIME_STORY_COMPAT_STATE_BRIDGE_DESIGN_2026-04-22.md,冻结旧POST /api/runtime/story/state/resolve的首版兼容桥边界,明确当前先做 DTO 与状态桥,不提前误宣称actions/resolve已可迁移。 - 已在
server-rs/crates/shared-contracts中新增runtime_story模块,冻结RuntimeStoryStateResolveRequest、RuntimeStoryActionResponse以及viewModel / presentation / patches / snapshot的首版 camelCase DTO,与当前前端消费口径对齐。 - 已恢复并重建
server-rs/crates/api-server/src/runtime_story.rs,把上一轮误删留下的中间态收口回可编译实现。 - 已在 Rust
api-server侧挂出旧 runtime story 兼容接口:
POST /api/runtime/story/state/resolveGET /api/runtime/story/state/:sessionIdPOST /api/runtime/story/actions/resolvePOST /api/runtime/story/initialPOST /api/runtime/story/continue
state/resolve与actions/resolve已统一复用runtime_save的 SpacetimeDB 快照持久化链:
- 请求带
snapshot时先写入runtime_snapshot - 请求不带
snapshot时从持久化runtime_snapshot读取 - 无可用快照时返回
409
actions/resolve已补齐当前前端主链需要的确定性兼容动作闭环,覆盖:
story_continue_adventurestory_opening_camp_dialoguecamp_travel_home_sceneidle_call_outidle_explore_forwardidle_observe_signsidle_rest_focusidle_travel_next_scenenpc_preview_talknpc_chatnpc_helpnpc_leavenpc_fightnpc_sparnpc_recruitbattle_attack_basicbattle_use_skillbattle_all_in_crushbattle_escape_breakoutbattle_feint_stepbattle_finisher_windowbattle_guard_breakbattle_probe_pressurebattle_recover_breathinventory_useequipment_equipnpc_tradenpc_gift
actions/resolve已补clientVersion与gameState.runtimeActionVersion的冲突校验、动作后版本自增、storyHistory追加和 snapshot 回写。initial/continue已先落稳定RuntimeStoryAiResponse:
- 优先透传
requestOptions.availableOptions / optionCatalog - 未配置 LLM 时走确定性 fallback 文本
- 已配置
platform-llm时可做文本增强,但不阻塞接口可用性
actions/resolve已开始迁移 Node 动作后 LLM 增强分支的最小闭环:
npc_chat / story_opening_camp_dialogue在配置platform-llm时会尝试生成对话态storyText- NPC 对话增强回包会对齐 Node 旧
displayMode = dialogue + deferredOptions结构,先只展示“继续推进冒险” battle victory / spar_complete / escaped在配置platform-llm时会尝试生成结果叙事,但不改既有规则结算- LLM 不可用或生成失败时自动回退到确定性
resultText / currentStory
- 已执行
cargo test -p shared-contracts、cargo check -p api-server、cargo test -p api-server runtime_story并通过,当前 runtime story 兼容链在 Rust 侧已恢复到可编译、可测试状态。 - 已补 Rust 侧 route boundary 回归:
runtime_story_routes_resolve_through_rust_route_boundaryruntime_story_action_resolve_rejects_client_version_conflictruntime_story_npc_help_is_one_shot_and_restores_resourcesruntime_story_npc_recruit_requires_threshold_and_release_target_when_party_full
- 已把兼容桥里的关键 NPC 行为继续对齐到 Node 旧主链:
npc_chat好感增长改为max(2, 6 - chattedCount),首聊可从46 -> 52npc_help改为一次性援手,成功时恢复10 HP / 8 Mana且关系+4npc_recruit改为要求affinity >= 60,队伍满员时必须透传releaseNpcId
- 已补测试环境专用的 runtime snapshot 内存兜底,仅在
#[cfg(test)]下生效,用于在未启动本地 SpacetimeDB 时稳定回归PUT /api/runtime/save/snapshot -> GET /api/runtime/story/state -> POST /api/runtime/story/actions/resolve这条 Rust 边界链。 - 已把 quest compat 主循环补到 Rust
runtime story兼容桥:
npc_chat_quest_offer_viewnpc_chat_quest_offer_replacenpc_chat_quest_offer_abandonnpc_quest_acceptnpc_quest_turn_in
- 已把 quest offer 对话态的
currentStory.npcChatState.pendingQuestOffer与前端面板依赖的runtimePayload.npcChatQuestOfferAction一并回填到 Rust compat 回包,保证现有 quest 面板入口不回退。 - 已把
npc_quest_turn_in的最小奖励闭环补回 Rust compat handler:
- quest 状态改为保留在
gameState.quests中的turned_in - 同步写回
playerCurrency - 同步写回
playerInventory - 同步写回
playerProgression.totalXp / level / xpToNextLevel / lastGrantedSource - 同步写回 NPC
affinity
- 已新增 quest compat Rust 回归:
runtime_story_quest_offer_replace_updates_pending_offer_and_payloadruntime_story_quest_offer_abandon_clears_pending_offer_and_restores_chat_optionsruntime_story_quest_accept_writes_quest_runtime_stats_and_followup_storyruntime_story_quest_turn_in_marks_quest_rewards_and_affinity
- 已再次执行
cargo test -p api-server runtime_story、cargo check -p api-server与node scripts/check-encoding.mjs并通过,当前 quest compat 已恢复到可编译、可回归状态。 - 已继续把 Task6 旧 inventory / NPC inventory compat 主链补回 Rust
runtime story兼容桥:
equipment_equipequipment_unequipforge_craftforge_dismantleforge_reforgenpc_tradenpc_gift
- 已把 NPC 交互态 fallback option compiler 对齐到 Node 旧顺序,当前会按条件输出:
npc_chatnpc_helpnpc_sparnpc_fightnpc_tradenpc_giftnpc_quest_accept / npc_quest_turn_innpc_recruitnpc_leave
- 已新增 Rust compat 回归:
runtime_story_state_compiler_builds_active_npc_options_with_trade_gift_and_help_lockruntime_story_equipment_equip_updates_loadout_and_build_toastruntime_story_equipment_unequip_returns_item_to_inventory_and_resets_loadoutruntime_story_forge_craft_consumes_materials_and_currencyruntime_story_forge_dismantle_replaces_item_with_material_outputsruntime_story_forge_reforge_upgrades_item_and_consumes_costruntime_story_npc_trade_buy_updates_currency_inventory_and_stockruntime_story_state_compiler_bootstraps_trade_inventory_for_role_npcruntime_story_npc_trade_buy_bootstraps_missing_npc_stateruntime_story_npc_gift_updates_affinity_inventory_and_patchruntime_story_route_boundary_persists_equipment_equip_snapshot_updates
- 当前 Rust compat bridge 已补入口级 NPC 状态预处理:即使快照里的
npcStates为空,纯商贩型 NPC 也会在state/get与actions/resolve前自动初始化基础关系态、stanceProfile / relationState / tradeStockSignature与最小 trade stock。 - 当前
actions/resolve已不再只停留在确定性storyText = resultText:
- 已在 Rust 侧新增
generate_action_story_payload(...) - 已对齐 Node 旧分支的最小范围
npc_chat / story_opening_camp_dialogue / terminal combat outcome - 当前仍未迁移 Node 那套完整 orchestrator 选项重排,只先保留既有 fallback options
- 当前
cargo test -p api-server runtime_story已提升到 30 条回归通过。 - 已继续把 runtime story compat 的 battle 展示编译从
api-server抽到独立 crate:
module-runtime-story-compat当前已承接build_battle_runtime_story_options(...)、restore_player_resource(...)与战斗技能 / 推荐物品 option compilerapi-server/src/runtime_story/compat/battle.rs已删除presentation.rs与npc_actions.rs当前统一直接复用 crate 导出的 battle helper
- 已继续把 runtime story option 的基础 DTO 编译从
api-server抽到独立 crate:
module-runtime-story-compat/src/options.rs当前已承接build_static_runtime_story_option(...)、build_disabled_runtime_story_option(...)、build_runtime_story_option_from_story_option(...)、build_story_option_from_runtime_option(...)api-server/src/runtime_story/compat/presentation.rs已删除这批本地重复实现,当前只保留更贴近 NPC / quest / view-model 组装的逻辑
- 已继续把 runtime story view-model 编译从
api-server抽到独立 crate:
module-runtime-story-compat/src/view_model.rs当前已承接build_runtime_story_view_model(...)、build_runtime_story_encounter(...)、build_runtime_story_companions(...)resolve_current_encounter_npc_state(...)已统一由 crate 导出,api-server的presentation.rs与game_state.rs不再保留本地副本
- 已停止继续拆分 runtime story 文件与模块,当前 M4 收尾改为加速 Node -> Rust 切流验证:
npm run dev:rust/npm run dev:rust:sh会启动 Rustapi-server、SpacetimeDB 与 Vite,并设置GENARRATIVE_BACKEND_STACK=rust- ../vite.config.ts 已补
/api/story代理,Rust 栈下/api/runtime/*与/api/story/*均会走GENARRATIVE_RUNTIME_SERVER_TARGET - 当前 M4 的切流目标以“旧 runtime story 兼容接口 + 新 story/battle 查询切片可由 Rust 承接”为准,不再把继续拆 crate 作为本阶段阻塞项
当前验证边界补充:
story_sessions/story_battles的二进制测试目标在当前机器上编译耗时仍然较长,还没有把更大范围的 story/battle 回归全部收拢到单次时窗内。node scripts/check-encoding.mjs已再次执行并通过,当前本轮涉及的中文文件编码未被写坏。- 当前可以确认的是:
module -> generated bindings -> spacetime-client -> api-server的编译链已打通- Rust
runtime storycompat route boundary 与关键 NPC 主循环规则已有回归覆盖 - Rust
actions/resolve已开始承接 Node 动作后 LLM 文本增强,但完整 orchestrator / 真相链仍未完成
当前这轮不再继续扩 runtime_story 模块拆分。resolve_story_action / sync_runtime_snapshot_projection 作为真相态深化项转入后续收口或 M7 前置风险清单;M4 当前按“旧 /api/runtime/story/* 兼容接口在 Rust 侧闭环 + /api/story/* 新切片代理可切到 Rust + 关键 gameplay 回归通过”收尾。
1. SpacetimeDB gameplay 表
- 设计
story_session - 设计
story_event - 设计
npc_state - 设计
quest_record - 设计
inventory_slot - 设计 runtime item 奖励快照基线
- 设计
battle_state - 设计
player_progression - 设计
chapter_progression
2. 核心 reducer
- 设计
resolve_story_action(转入真相态深化,不阻塞 M4 兼容切流收尾) - 设计
continue_story - 设计
begin_story_session - 设计
sync_runtime_snapshot_projection(转入真相态深化,不阻塞 M4 兼容切流收尾) - 设计
apply_quest_signal - 设计
apply_inventory_mutation - 设计
resolve_npc_interaction - 设计 runtime item 奖励回写基线
- 设计
resolve_combat_action - 设计
update_progression_state
3. 当前主链模块落位
- 迁移
rpg-entry配套后端入口能力 - 迁移
rpg-profile资料域 - 迁移
rpg-runtime-story - 迁移
combat - 迁移
inventory - 迁移
npc - 迁移
progression - 迁移
quest - 迁移
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
补充说明:
- 当前已落地的是两类 Rust facade:
- 新真相态接口:
POST /api/story/sessionsPOST /api/story/sessions/continueGET /api/story/sessions/:storySessionId/stateGET /api/story/battles/:battleStateIdPOST /api/story/npc/battle- 旧 runtime story 兼容接口:
POST /api/runtime/story/state/resolveGET /api/runtime/story/state/:sessionIdPOST /api/runtime/story/actions/resolvePOST /api/runtime/story/initialPOST /api/runtime/story/continue
- 其中新真相态接口仍是
story session / battle / NPC 开战的底层切片;旧runtime/story/*则是复用runtime_snapshot的兼容桥,不等价于最终真相态实现。 - 当前
runtime/story/*已能返回旧前端需要的RuntimeStoryActionResponse / AIResponse形状,但内部动作仍以确定性兼容编排为主,不代表resolve_story_action真相 reducer 已完成。 - 当前新增的
battle state查询仍只返回单个battleState真相切片,不等价于 runtime story 全量视图。 - 后续
M4仍需把兼容桥逐步替换成真正的 story action / snapshot projection 真相链。
5. ViewModel 兼容
- 兼容当前
RuntimeStoryActionResponse - 兼容当前
RuntimeStoryOptionView - 兼容当前
interaction元数据 - 兼容当前 battle / toast / patch 响应结构
- 兼容当前
currentStory回填逻辑
6. 阶段验收
- 当前前端 story 选项点击后可走新后端闭环
- NPC / quest / combat 主循环行为不回退
story state恢复链可用- 后端边界与当前
rpgEntry -> rpgSession -> rpgRuntime -> rpgRuntimeStory -> rpgProfile口径一致 - 旧 Node 版 story route 回归用例完成平移
阶段验收补充说明:
当前前端 story 选项点击后可走新后端闭环当前按 Rustapi-server的真实边界回归判定已满足:PUT /api/runtime/save/snapshotGET /api/runtime/story/state/runtime-mainPOST /api/runtime/story/actions/resolve但这不等于“生产默认流量已经切到 Rust”。
story state 恢复链可用当前指:- 请求带
snapshot时可先写后读 - 请求不带
snapshot时可从已持久化runtime_snapshot恢复
- 请求带
旧 Node 版 story route 回归用例完成平移当前指:- 已平移 Node 的
rpg runtime story routes resolve through the new route boundary - 已补
clientVersion冲突回归 - 已把
npc_chat的46 -> 52Node 旧语义对齐进 Rust compat handler
- 已平移 Node 的
NPC / quest / combat 主循环行为不回退当前按 Rust compat 回归口径已可勾选:
- 当前 runtime story compat bridge 已明确移除
treasure_*遭遇动作,不再把 treasure 视作本阶段 runtime story 主循环的一部分。 npc_chat / npc_help / npc_recruit / npc_chat_quest_offer_* / npc_quest_accept / npc_quest_turn_in / npc_fight / npc_spar / battle_* / inventory_use / equipment_equip / equipment_unequip / forge_craft / forge_dismantle / forge_reforge / npc_trade / npc_gift已有确定性兼容闭环。- 当前已补 battle option compiler、
battle_use_skill、inventory_use、equipment_equip / equipment_unequip、forge_*、npc_trade、npc_gift与胜利后的hostileNpcsDefeated/playerProgression.lastGrantedSource = hostile_npc写回。 - 当前已补 NPC 交互态入口预处理:纯商贩型 NPC 即使没有预填
npcStates.*.inventory,也会在 compat bridge 内自动恢复可交易库存与基础关系态,不再依赖 Node 侧预热。 - 更大范围 Node 回归与真相态 reducer 替换不再作为 M4 阻塞项,转入 M7 切流前回归矩阵。
后端边界与当前 rpgEntry -> ...当前按 Rust 代理与路由覆盖可勾选:- 前端真实调用链已对齐
/api/runtime/story/* - Rust 栈已覆盖
/api/runtime/*与/api/story/*代理目标 npm run dev:rust是本地 Rust 切流入口,M7 再做远端灰度与回退验证
- 前端真实调用链已对齐