# M4 RPG Runtime Quest SpacetimeDB 基座记录(2026-04-21) 更新时间:`2026-04-21` ## 0. 文档目标 本文件只记录一件事: **把 `module-quest` 从“只有 README 占位”推进到“SpacetimeDB 侧已有最小可编译任务运行时基座”的真实落地结果。** 本轮只落任务主状态、任务日志与最小 reducer,并补上任务交付到成长表、背包表的最小联动;不扩到完整奖励结算、Axum facade、前端任务面板或 story action 全量迁移。 --- ## 1. 本轮落地范围 本轮按 `AI_NATIVE_QUEST_SYSTEM_PRD_2026-04-02.md`、`AI_NATIVE_TASK_DRIVEN_GOAL_EXPERIENCE_PRD_2026-04-07.md` 与 `SPACETIMEDB_AXUM_OSS_BACKEND_REWRITE_DESIGN_2026-04-20.md` 的交叉口径,只落实下面 5 件事: 1. 新增 `server-rs/crates/module-quest/` 真实 crate,而不是继续停留在 README 占位。 2. 在 `module-quest` 中冻结 `QuestRecord`、`QuestStep`、`QuestReward`、`QuestProgressSignal` 的首版 Rust 领域类型与校验/归一化 helper。 3. 在 `server-rs/crates/spacetime-module/` 中新增 `quest_record`、`quest_log` 两张表。 4. 在 `spacetime-module` 中新增 `accept_quest`、`apply_quest_signal`、`acknowledge_quest_completion`、`turn_in_quest` 四个 reducer。 5. 用 `module-story` 同口径方式,把任务推进固定成“主记录 + 日志追加”的最小可编译基座。 6. 把 `turn_in_quest.reward.items` 显式映射为 `InventoryMutation::GrantItem`,在任务交付时同步写入 `inventory_slot`。 --- ## 2. 本轮新增的真实工程落点 ### 2.1 新增 crate 1. `server-rs/crates/module-quest/Cargo.toml` 2. `server-rs/crates/module-quest/src/lib.rs` ### 2.2 workspace 与主工程聚合 1. `server-rs/Cargo.toml` - 已把 `crates/module-quest` 纳入 workspace members 2. `server-rs/crates/spacetime-module/Cargo.toml` - 已接入 `module-quest` 依赖 3. `server-rs/crates/spacetime-module/src/lib.rs` - 已接入 `module-quest` 类型 - 已新增 `quest_record` - 已新增 `quest_log` - 已新增 `accept_quest` - 已新增 `apply_quest_signal` - 已新增 `acknowledge_quest_completion` - 已新增 `turn_in_quest` --- ## 3. 当前冻结的数据口径 ### 3.1 `quest_record` 当前首版字段冻结为: 1. `quest_id` 2. `runtime_session_id` 3. `story_session_id` 4. `actor_user_id` 5. `issuer_npc_id` 6. `issuer_npc_name` 7. `scene_id` 8. `chapter_id` 9. `act_id` 10. `thread_id` 11. `contract_id` 12. `title` 13. `description` 14. `summary` 15. `objective` 16. `progress` 17. `status` 18. `completion_notified` 19. `reward` 20. `reward_text` 21. `narrative_binding` 22. `steps` 23. `active_step_id` 24. `visible_stage` 25. `hidden_flags` 26. `discovered_fact_ids` 27. `related_carrier_ids` 28. `consequence_ids` 29. `created_at` 30. `updated_at` 31. `completed_at` 32. `turned_in_at` 当前策略: 1. `quest_record` 保持 private 真相表口径。 2. 当前仍沿用“一个任务一条主记录”的最小可编译策略,不在本轮拆 `quest_step` 独立表。 3. `objective / progress / active_step_id / status` 统一由 `steps` 归一化导出,避免旧接口和新真相源在同一条记录里出现漂移。 ### 3.2 `quest_log` 当前首版字段冻结为: 1. `log_id` 2. `quest_id` 3. `runtime_session_id` 4. `actor_user_id` 5. `event_kind` 6. `status_after` 7. `signal_kind` 8. `signal` 9. `step_id` 10. `step_progress` 11. `created_at` 当前策略: 1. `quest_log` 先作为 private 结构化日志表,不提前做 public event table。 2. 当前只承接 `Accepted / Progressed / Completed / CompletionAcknowledged / TurnedIn` 五类事件。 3. 后续若要接前端实时提示,再决定是否补 event table 或投影表,而不是现在先塞 UI 专用字段。 --- ## 4. 当前 reducer 口径 ### 4.1 `accept_quest` 当前负责: 1. 校验 `QuestRecordInput` 2. 拒绝重复 `quest_id` 3. 写入 `quest_record` 4. 追加一条 `Accepted` 日志 ### 4.2 `apply_quest_signal` 当前负责: 1. 校验 `QuestSignalApplyInput` 2. 校验目标 `quest_record` 必须存在 3. 只对当前 active step 应用任务信号 4. 在命中信号时推进 step progress、刷新 `objective / active_step_id / progress / status` 5. 命中且未完成时追加 `Progressed` 6. 最后一条 step 完成时追加 `Completed` 补充约束: 1. 已经 `Completed / ReadyToTurnIn / TurnedIn / Failed / Expired` 的任务不会被重复推进。 2. 信号未命中当前 active step 时,本轮 reducer 允许静默 no-op,保持幂等。 ### 4.3 `acknowledge_quest_completion` 当前负责: 1. 把 `completion_notified` 标为 `true` 2. 追加一条 `CompletionAcknowledged` 日志 ### 4.4 `turn_in_quest` 当前负责: 1. 校验任务已处于 `Completed / ReadyToTurnIn` 2. 固定所有 step progress 为完成态 3. 把任务状态切到 `TurnedIn` 4. 补齐 `turned_in_at` 5. 追加一条 `TurnedIn` 日志 6. 若存在 `reward.items`,同步发放到 `inventory_slot` 7. 若存在 `reward.items`,同步发放到 `inventory_slot` 8. 若 `reward.experience > 0`,同步发放 `player_progression` 经验 9. 若存在已初始化的 `chapter_progression`,同步累计章节任务经验账本 --- ## 5. 当前刻意未做 本轮明确没有扩到以下范围: 1. 还没有落任务奖励的货币、好感、情报统一发放 reducer 2. 还没有接 `runtime_snapshot` projection / sync 3. 还没有接 `story_session`、`npc_state` 的更多跨域联动 4. 还没有新增 Axum 的 runtime quest facade 5. 还没有把 `server-node` 现有 quest API 切到 `server-rs` 6. 还没有把 Goal Director、章节目标 handoff、前端任务 UI 切到 SpacetimeDB 真相源 也就是说,本轮只是把 `module-quest` 的 SpacetimeDB 任务基座立起来,不宣称已经完成任务系统迁移。 --- ## 6. 验证要求 本轮工程变更完成后,至少执行下面两类验证: 1. `npm run check:encoding` 2. `cargo test -p module-quest` 3. `cargo check -p spacetime-module` --- ## 7. 下一步建议 按当前节奏,后续应继续按下面顺序推进: 1. 先把 `quest_record` 与 `runtime_snapshot` 的投影边界补清。 2. 再把 `resolve_story_action` 内的 quest signal 分发迁到 `apply_quest_signal`。 3. 再把 `turn_in_quest` 与 `npc affinity / currency / intel projection` 的奖励结算接成显式 reducer。 4. 再把 quest reward item 的映射 helper 上提到独立领域 crate,减少 `spacetime-module` 聚合层重复转换。 5. 最后再接 Axum facade、兼容 DTO 与前端任务主链。