This commit is contained in:
2026-04-28 20:25:37 +08:00
parent f0471a4f8d
commit 0f013b6eee
45 changed files with 1117 additions and 1047 deletions

View File

@@ -20,7 +20,7 @@
- [RPG_RUNTIME_DIRECT_DRAFT_PROFILE_AUDIT_2026-04-25.md](./RPG_RUNTIME_DIRECT_DRAFT_PROFILE_AUDIT_2026-04-25.md)RPG 运行时进入世界时改为直读 Agent session 草稿 profile 的链路检查。
- [RPG_WORLD_DRAFT_EDIT_AUTOSAVE_OVERRIDE_AUDIT_2026-04-28.md](./RPG_WORLD_DRAFT_EDIT_AUTOSAVE_OVERRIDE_AUDIT_2026-04-28.md)RPG 世界草稿结果页编辑后被旧设定覆盖的前端本地态、session 真相源与自动保存链路审计。
- [engineering/RPG_FRONTEND_SCRIPT_BACKEND_MIGRATION_AUDIT_2026-04-28.md](./engineering/RPG_FRONTEND_SCRIPT_BACKEND_MIGRATION_AUDIT_2026-04-28.md)RPG 前端脚本中仍应迁到 `server-rs` / SpacetimeDB 的开局、快照、story engine、战斗、NPC/背包规则与创作残留后门审计。
- [engineering/RPG_FRONTEND_SCRIPT_BACKEND_MIGRATION_COMPLETION_CHECK_2026-04-28.md](./engineering/RPG_FRONTEND_SCRIPT_BACKEND_MIGRATION_COMPLETION_CHECK_2026-04-28.md)RPG 前端脚本后端迁移完成度复核,标明已完成项、已收口的结果页保存 normalize以及仍需收尾的 `camp_travel_home_scene` 前端专用旅行分支
- [engineering/RPG_FRONTEND_SCRIPT_BACKEND_MIGRATION_COMPLETION_CHECK_2026-04-28.md](./engineering/RPG_FRONTEND_SCRIPT_BACKEND_MIGRATION_COMPLETION_CHECK_2026-04-28.md)RPG 前端脚本后端迁移完成度复核,标明开局、快照、story engine / prompt context、`camp_travel_home_scene`、战斗、NPC、背包/锻造、结果页保存 normalize 与角色资产 prompt 主链均已收口
- [engineering/ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-20.md](./engineering/ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-20.md):对 `2026-04-19` 工程清理审计的当前仓库复核,区分已完成项、仍存边界问题和新的热点迁移。
- [engineering/ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-19.md](./engineering/ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-19.md):未引用垃圾、旧入口残留、前后端双份真相与后端迁移项的专项审计。

View File

@@ -13,7 +13,7 @@
4. [RPG_FRONTEND_SCRIPT_BACKEND_MIGRATION_AUDIT_2026-04-28.md](./RPG_FRONTEND_SCRIPT_BACKEND_MIGRATION_AUDIT_2026-04-28.md)
这一版专项扫描 `src/` 下 RPG 开头脚本明确运行时开局、快照、story engine、战斗后处理、NPC/背包规则和创作链残留后门中应迁到 `server-rs` 的逻辑。
5. [RPG_FRONTEND_SCRIPT_BACKEND_MIGRATION_COMPLETION_CHECK_2026-04-28.md](./RPG_FRONTEND_SCRIPT_BACKEND_MIGRATION_COMPLETION_CHECK_2026-04-28.md)
这一版复核 RPG 前端脚本后端迁移完成度确认开局、快照、存档、NPC、背包/锻造、结果页保存前 normalize 与角色资产 prompt 主链已收口,同时标出 `camp_travel_home_scene` 前端专用旅行分支仍未完全迁完
这一版复核 RPG 前端脚本后端迁移完成度,确认开局、快照、存档、story engine / prompt context、`camp_travel_home_scene`NPC、背包/锻造、战斗后处理、结果页保存前 normalize 与角色资产 prompt 主链已收口。
6. [FRONTEND_LOGIC_BACKEND_MIGRATION_AUDIT_2026-04-21.md](./FRONTEND_LOGIC_BACKEND_MIGRATION_AUDIT_2026-04-21.md)
这一版是本轮前端越界逻辑专项审计,专门汇总当前仍应继续迁到 `server-rs` 的运行时、鉴权、生成编排与本地真相残留。
7. [ENGINEERING_DEAD_CODE_CLEANUP_BATCH_D_2026-04-21.md](./ENGINEERING_DEAD_CODE_CLEANUP_BATCH_D_2026-04-21.md)

View File

@@ -4,18 +4,18 @@
本次按 `RPG_FRONTEND_SCRIPT_BACKEND_MIGRATION_AUDIT_2026-04-28.md` 中列出的应迁后端项逐项检查当前代码。
结论:**应迁移项尚未全部迁移完成。**
结论:**应迁移项全部迁移完成。**
当前状态:
1. `已完成`9 项。
2. `部分完成`1 项。
1. `已完成`10 项。
2. `部分完成`0 项。
3. `未发现完全未启动`0 项。
本轮重新核查的变化:
1. 上次残留的 `RPG 创作结果页` 保存前 profile normalize 已完成后端化。
2. 新发现 `camp_travel_home_scene`登记为服务端 runtime function id但正式点击仍会被前端专用旅行分支提前拦截并本地拼装场景迁移状态
2. `camp_travel_home_scene`完成后端收口:正式点击统一走 `/api/runtime/story/actions/resolve`目标场景、encounter preview、`scenesTraveled` 与快照持久化由 `server-rs` 裁决
## 2. 核验口径
@@ -43,7 +43,7 @@
| `P0` 运行时开局 `GameState` 装配 | 已完成 | 正式开局状态由 `server-rs/crates/api-server/src/runtime_story/compat/bootstrap.rs` 创建并持久化;前端 `useRpgSessionBootstrap.ts` 只保留选择页占位态和 `beginRpgRuntimeStorySession(...)` 调用。 |
| `P0` runtime story 网关客户端快照解析/补丁 | 已完成 | `rpgRuntimeStoryGateway.ts` 不再有 `buildRuntimeSnapshotRequest` / `bridgeServer*Snapshot``rpgRuntimeStoryClient.ts` 读取 `/state/:sessionId`,动作提交 `/actions/resolve`,不再上传完整 `snapshot.gameState/currentStory`。 |
| `P0` 自动保存整份运行时快照 | 已完成 | `useRpgSessionPersistence.ts` / `rpgSnapshotClient.ts` 保存链路只提交 `sessionId/bottomTab` checkpoint`runtime_save.rs` 从服务端已有快照刷新 checkpoint并测试拒绝旧式完整快照上传。 |
| `P0` story engine / chapter / world mutation / prompt context 编排 | 部分完成 | 后端已有 `project_story_engine_after_action(...)``build_runtime_story_prompt_context(...)``/story/initial``/story/continue``sessionId` 时只从服务端 snapshot 投影 world / character / history / prompt context`camp_travel_home_scene` 已是服务端 function id前端仍先走本地 `runCampTravelHomeChoice(...)` 拼装场景迁移、encounter preview runtimeStats。 |
| `P0` story engine / chapter / world mutation / prompt context 编排 | 完成 | 后端已有 `project_story_engine_after_action(...)``build_runtime_story_prompt_context(...)``/story/initial``/story/continue``sessionId` 时只从服务端 snapshot 投影 world / character / history / prompt context`camp_travel_home_scene` 正式点击也已统一进入后端 resolver不再由前端拼装场景迁移、encounter preview runtimeStats。 |
| `P0` 战斗胜负后处理、死亡复活、战斗后章节推进 | 已完成 | `battle_* / inventory_use` 正式点击统一走 `runServerRuntimeChoiceAction(...)` 与后端 `/actions/resolve``storyChoiceContinuation.ts` 对战斗 / 逃脱 / 物品动作加硬保护,不再裁决掉落、任务推进、死亡复活或战后 story`postBattleFlow.ts` 正式状态构造函数已删除。 |
| `P1` NPC 交易/送礼价格数量库存校验 | 已完成 | 前端 `npcInteraction.ts` 已改为消费 `runtimeNpcInteraction` view 并只提交 `{ mode, itemId, quantity }`;后端 `npc_actions.rs` / `npc_support.rs` 负责价格、库存、货币、赠礼好感和原子更新。 |
| `P1` 背包/装备/锻造可用性与配方视图 | 已完成 | 前端 `inventoryActions.ts` 读取 `loadRpgRuntimeInventoryView(...)`,根据后端 action/view 提交;后端 `view_model.rs` / `forge.rs` 生成背包、装备槽、配方、`canCraft/enabled/reason`。 |
@@ -51,9 +51,9 @@
| `P1` 创作结果页保存与 Agent session/result preview 真相优先级 | 已完成 | 后端已提供 `GET /api/runtime/custom-world/agent/sessions/:sessionId/result-view`,统一 `targetStage/profileSource/canAutosaveLibrary/canSyncResultProfile`,前端不再直接读取 `legacyResultProfile`;保存前 canonicalize 已迁到 `server-rs``normalizeRpgEntryAgentBackedProfile(...)` 现在只透传兼容旧导入。 |
| `P1` 角色资产工坊默认 prompt 与缓存合并规则 | 已完成 | 默认 prompt、legacy prompt 过滤、逐动作缓存合并已在 `server-rs/crates/api-server/src/prompt/rpg/role_asset_studio.rs`;前端 modal 只调用 workflow API、保存用户草稿和发起生成/发布。 |
## 4. 仍未完成的具体收尾点
## 4. 完成的具体收尾点
### 4.1 story engine / prompt context 主链已完成,但 `camp_travel_home_scene` 仍残留前端正式分支
### 4.1 story engine / prompt context 主链 `camp_travel_home_scene` 已完成后端收口
当前后端已经处理动作结算后的确定性 story projector
@@ -83,17 +83,25 @@
4. `npm run test -- src/services/ai.test.ts src/hooks/rpg-runtime-story/storyRequestCoordinator.test.ts src/hooks/rpg-runtime-story/useRpgRuntimeStoryController.test.tsx` 覆盖前端 story / chat 请求在 session 模式下只发送轻量 payload。
5. `npm run test -- src/hooks/rpg-runtime-story/sessionActions.test.ts src/hooks/rpg-runtime-story/choiceActions.test.ts src/hooks/rpg-runtime-story/npcEncounterActions.test.ts` 覆盖前端旧 UI 分支不再回写后端拥有的 `storyEngineMemory`
重新核查新增残留
本轮收尾
1. `packages/shared/src/contracts/rpgRuntimeStoryAction.ts` 已把 `camp_travel_home_scene` 纳入 `TASK5_RUNTIME_FUNCTION_IDS` / `SERVER_RUNTIME_FUNCTION_IDS`
2. `server-rs/crates/api-server/src/runtime_story/compat.rs` 已有 `camp_travel_home_scene` resolver 分支,但当前只清理 encounter并未承接前端旧分支里的目标场景、encounter preview 与完整离营故事提交
3. `src/hooks/rpg-runtime-story/choiceActions.ts` 仍在 `isRpgRuntimeServerFunctionId(...)` 之前判断 `isCampTravelHomeOption(...)`,并调用 `runCampTravelHomeChoice(...)`
4. `src/hooks/rpg-runtime-story/storyChoiceRuntime.ts` `runCampTravelHomeChoice(...)` 会在浏览器中决定目标场景、清理战斗/遭遇、递增 `scenesTraveled`、构造 encounter preview并通过 `commitGeneratedStateWithEncounterEntry(...)` 写入后续故事
2. `server-rs/crates/api-server/src/runtime_story/compat.rs` `camp_travel_home_scene` resolver 已承接前端旧分支的正式状态职责:解析目标场景、写入 `currentScenePreset`、清理战斗/遭遇残留、递增 `scenesTraveled`、生成 encounter preview并让后续故事和持久化继续走后端 snapshot 主链
3. 目标场景解析以后端为准:优先接收兼容 payload 中的 `targetSceneId`,其次使用内置角色主场景映射,自定义世界按角色与 landmark 绑定解析,再回退到当前场景前向连接或首个冒险场景
4. `src/hooks/rpg-runtime-story/choiceActions.ts` 不再调用 `runCampTravelHomeChoice(...)``camp_travel_home_scene` 即使命中旧展示 helper也会按服务端 function id 统一进入 `runServerRuntimeChoiceAction(...)`
5. `src/hooks/rpg-runtime-story/storyChoiceRuntime.ts` 已删除 `runCampTravelHomeChoice(...)`,前端不再保留正式场景迁移构造函数。
影响
已消除风险
1. 这条链不是纯动画表现,而是正式场景迁移、运行时统计、遭遇预览和后续故事提交
2. 它已经具备服务端 function id 身份,却没有统一走 `/api/runtime/story/actions/resolve`,因此仍不满足“前端只提交 action后端返回 hydrated snapshot”的边界。
1. `camp_travel_home_scene` 不再由浏览器决定目标场景、运行时统计或 encounter preview
2. 正式离营状态已经满足“前端只提交 action后端返回 hydrated snapshot”的边界。
本轮验收补充:
1. `cargo test -p api-server runtime_story_route_boundary_camp_travel_home_scene_is_server_owned --manifest-path server-rs\Cargo.toml` 覆盖点击后 hydrated snapshot 进入角色主场景、生成 encounter preview、递增 `scenesTraveled` 并持久化。
2. `cargo test -p api-server runtime_story --manifest-path server-rs\Cargo.toml` 覆盖 runtime story 相关后端回归。
3. `npm run test -- src/hooks/rpg-runtime-story/choiceActions.test.ts` 覆盖 `camp_travel_home_scene` 只调用后端 resolver不触发旧本地旅行分支。
4. `npm run test -- src/hooks/rpg-runtime-story/storyChoiceRuntime.test.ts src/services/rpg-runtime/rpgRuntimeStoryClient.test.ts` 覆盖服务端 runtime choice presentation 与 story client 轻量 payload。
### 4.2 本地战斗 continuation 已收口到后端
@@ -156,14 +164,14 @@
4. 角色资产工坊 modal 中的 prompt 输入框与缓存保存:这是用户正在编辑的 UI 草稿,默认 prompt 和合并规则已由后端 workflow 输出。
5. `playServerBattlePresentation(...)`:只播放临时动画态,最终 `GameState/currentStory` 仍以服务端 snapshot 为准。
## 6. 下一步建议
## 6. 后续建议
推荐按风险顺序继续
本轮核验范围内的应迁项已经收口。后续建议转为质量维护
1. `camp_travel_home_scene` 点击链统一改为 `runServerRuntimeChoiceAction(...)` / `/api/runtime/story/actions/resolve`
2. 扩展 `server-rs/crates/api-server/src/runtime_story/compat.rs` 中的 `camp_travel_home_scene` resolver让目标场景、encounter preview、`scenesTraveled`、故事提交和快照持久化全部由后端完成
3. 补齐前端测试,锁定 `camp_travel_home_scene` 不再调用 `runCampTravelHomeChoice(...)`;补齐后端 route 级测试,覆盖离营后 hydrated snapshot 字段
1. 继续把 function catalog / 旧文档里“本地规则结算”的历史描述逐批改成当前后端归属,避免误导后续开发
2. 新增 runtime function 时先补后端 resolver / view / contract再让前端接展示入口保持“前端不造正式状态”的边界
3. 对仍保留的前端本地 continuation 只允许处理非服务端 function id凡进入 `SERVER_RUNTIME_FUNCTION_IDS` 的动作都应有 route 级测试
## 7. 一句话结论
**当前迁移已经完成开局、快照、存档、story engine / prompt context 主链、NPC、背包/锻造、战斗后处理、profile 生成、创作结果页 normalize 和角色资产 prompt 主链;但 `camp_travel_home_scene` 仍由前端专用分支拼装正式场景迁移状态,所以不能判定“应迁移项已全部迁移完成”**
**当前迁移已经完成开局、快照、存档、story engine / prompt context 主链、`camp_travel_home_scene` 离营迁移、NPC、背包/锻造、战斗后处理、profile 生成、创作结果页 normalize 和角色资产 prompt 主链;本核验范围内不再保留前端正式状态裁决残留**

View File

@@ -74,7 +74,7 @@
新系统必须满足:
1. 可解释:玩家能理解“为什么这个角色擅长这个”“为什么这个 NPC 会喜欢这种行为”“为什么这个怪物在这个世界里是这种威胁”。
2. 可生成:自定义世界可以稳定生成新属性名称与定义
2. 可生成:自定义世界可以稳定生成新属性名称。
3. 可校验AI 输出不能直接裸写进运行时,必须经过本地验证。
4. 可复用:同一套属性 schema 能进入角色、怪物、技能、Build、物品、对话 prompt。
5. 可迁移:能从当前四维属性 / 标签 / 怪物 preset 平滑过渡。
@@ -165,12 +165,6 @@ type WorldAttributeSchema = {
slots: Array<{
slotId: string;
name: string;
definition: string;
positiveSignals: string[];
negativeSignals: string[];
combatUseText: string;
socialUseText: string;
explorationUseText: string;
}>;
};
```
@@ -178,12 +172,9 @@ type WorldAttributeSchema = {
### 关键原则
1. `slotId` 是稳定技术标识,例如 `axis_a` ~ `axis_f`
2. `name` 是世界内真实显示名称,例如武侠里可能不是“力量”,而是“骨势”“身法”
3. `definition` 必须描述角色本质倾向,而不是派生战斗数值
4. 每个属性都必须能解释:
- 战斗中的体现
- 对话中的体现
- 探索中的体现
2. 本世界六维名称在创作、提示词输出、解析后保存的数据中只保留 `name`;其他定义、信号和用途说明字段不再进入 schema
3. `name` 是世界内真实显示名称,例如武侠里可能不是“力量”,而是“骨势”“身法”
4. 六个名称需要能支撑战斗、对话、探索的叙事理解,但这些说明由下游运行时按场景生成,不写入 schema。
### 禁止项
@@ -247,16 +238,9 @@ type AttributeSchemaGenerationInput = {
```ts
type AttributeSchemaGenerationOutput = {
schemaName: string;
slots: Array<{
slotId: string;
name: string;
definition: string;
positiveSignals: string[];
negativeSignals: string[];
combatUseText: string;
socialUseText: string;
explorationUseText: string;
}>;
};
```
@@ -267,13 +251,9 @@ AI 输出后必须通过本地校验:
1. 属性数量必须等于 6。
2. `name` 需唯一,长度建议 `2~4` 个中文字符。
3. `definition` 不得出现“提升攻击 / 提升防御力 / 提升生命值”这类派生描述
4. 每个属性都必须同时具备:
- 一个战斗说明
- 一个社交说明
- 一个探索说明
5. 任意两条属性定义关键词重叠度不能过高。
6. 若校验失败:
3. `name` 不得出现“生命 / 法力 / 护甲 / 攻击 / 防御 / 力量 / 敏捷 / 智力 / 精神”这类旧四维或派生资源词
4. 任意两个属性名称不能重复,也不能只做同义换皮。
5. 若校验失败:
- 预设世界回退到固化 schema
- 自定义世界回退到模板世界 schema并记录失败日志
@@ -283,25 +263,25 @@ AI 输出后必须通过本地校验:
### 武侠世界示例
| 属性名 | 定义 |
| 槽位 | 属性名 |
| --- | --- |
| 骨势 | 扛压、顶冲、硬吃风险也不退的势头 |
| 身法 | 腾挪、抢位、换线、把握出手节奏的能力 |
| 眼脉 | 看破破绽、拆招、识局、看穿人心的能力 |
| 心焰 | 决断、压迫、胆气、在局面中立住自身意志的能力 |
| 尘缘 | 与人事、情面、承诺、牵引关系打交道的能力 |
| 玄息 | 调息、稳态、久战、把自身维持在可用状态的能力 |
| axis_a | 骨势 |
| axis_b | 身法 |
| axis_c | 眼脉 |
| axis_d | 心焰 |
| axis_e | 尘缘 |
| axis_f | 玄息 |
### 仙侠世界示例
| 属性名 | 定义 |
| 槽位 | 属性名 |
| --- | --- |
| 道骨 | 承载道压与高强度冲击的底子 |
| 灵行 | 位移、御空、转场、抢占天时地利的能力 |
| 识海 | 解析禁制、洞察因果、识破虚实的能力 |
| 心契 | 与他者、器物、灵兽、誓约建立共鸣的能力 |
| 劫纹 | 在高危变化中强行推进、改写局势的能力 |
| 玄息 | 循环灵息、稳住心神、让自身持续在线的能力 |
| axis_a | 道骨 |
| axis_b | 灵行 |
| axis_c | 识海 |
| axis_d | 心契 |
| axis_e | 劫纹 |
| axis_f | 玄息 |
关键点:
@@ -692,10 +672,8 @@ AI 不可以直接生成:
```ts
type PromptAttributeSummary = {
schemaName: string;
slots: Array<{
name: string;
definition: string;
}>;
actorTopAttributes: string[];
targetTopAttributes?: string[];
@@ -726,12 +704,6 @@ export type AttributeVector = Record<string, number>;
export interface WorldAttributeSlot {
slotId: string;
name: string;
definition: string;
positiveSignals: string[];
negativeSignals: string[];
combatUseText: string;
socialUseText: string;
explorationUseText: string;
}
export interface WorldAttributeSchema {
@@ -1017,8 +989,8 @@ behaviorVectors: Array<{
对策:
1. 增加本地定义重叠校验
2. 强制每个属性都写战斗 / 社交 / 探索三种说明
1. 增加本地名称重复、旧词和同义换皮校验
2. 提示词要求六个名称覆盖不同叙事气质,避免全部落在同一种行动倾向上
3. 首版预设世界采用固化 schema不在运行时漂移
### 风险 2过度抽象策划难以配置
@@ -1029,8 +1001,8 @@ behaviorVectors: Array<{
对策:
1. 每个属性附带定义、正反信号、示例行为
2. 编辑器永远显示 `name + definition`
1. 编辑器只显示并编辑六个属性名称
2. 解释文本由技能 / 标签 / 物品等下游按具体场景生成
3. 所有技能 / 标签 / 物品的属性向量都显示人类可读解释
### 风险 3旧系统迁移期间双轨并存混乱

View File

@@ -112,7 +112,7 @@
- `npc_help`
脚本:`src/data/functionCatalog/npc/npcHelp.ts`
说明:向 NPC 寻求补给、回复或支援的 function。奖励由本地规则稳定计算,避免帮助收益被模型临场漂移。
说明:向 NPC 寻求补给、回复或支援的 function。正式奖励、资源变化与 one-shot 状态由后端 runtime action resolver 稳定计算,避免帮助收益被模型临场漂移。
- `npc_chat`
脚本:`src/data/functionCatalog/npc/npcChat.ts`
@@ -140,7 +140,7 @@
- `npc_quest_accept`
脚本:`src/data/functionCatalog/npc/npcQuestAccept.ts`
说明:正式接下 NPC 委托的 function。它把本地生成的任务写入 quest log并让剧情承接“玩家已经答应处理这件事”。
说明:正式接下 NPC 委托的 function。它把后端 pending quest offer 写入 quest log并让剧情承接“玩家已经答应处理这件事”。
- `npc_quest_turn_in`
脚本:`src/data/functionCatalog/npc/npcQuestTurnIn.ts`
@@ -172,7 +172,7 @@
- `camp_travel_home_scene`
脚本:`src/data/functionCatalog/flow/campTravelHomeScene.ts`
说明:营地开场或同伴交流结束后,正式前往角色主场景的流程项。它负责定制化场景迁移和状态清理,不属于普通 state function
说明:营地开场或同伴交流结束后,正式前往角色主场景的流程项。前端脚本只保留按钮与视觉元信息目标场景、状态清理、encounter preview、`scenesTraveled` 与快照持久化由后端 runtime action resolver 负责
- `story_opening_camp_dialogue`
脚本:`src/data/functionCatalog/flow/storyOpeningCampDialogue.ts`
@@ -182,7 +182,7 @@
- `inventory_use`
脚本:`src/data/functionCatalog/panel/inventoryUse.ts`
说明:在背包面板里使用药品、灵力物或 build buff 物品的 function。它先由本地规则结算资源变化,再把结果记入故事历史
说明:在背包面板里使用药品、灵力物或 build buff 物品的 function。前端只提交物品动作资源变化、数量扣减、build buff 与故事历史由后端 resolver 写入
- `equipment_equip`
脚本:`src/data/functionCatalog/panel/equipmentEquip.ts`
@@ -190,7 +190,7 @@
- `equipment_unequip`
脚本:`src/data/functionCatalog/panel/equipmentUnequip.ts`
说明:从装备槽位卸下物品的 function。它确保卸装结果由本地规则严格处理,不会破坏背包数量和 loadout 一致性。
说明:从装备槽位卸下物品的 function。后端 resolver 负责卸装结果、背包数量和 loadout 一致性。
- `forge_craft`
脚本:`src/data/functionCatalog/panel/forgeCraft.ts`
@@ -198,7 +198,7 @@
- `forge_dismantle`
脚本:`src/data/functionCatalog/panel/forgeDismantle.ts`
说明:在锻造面板中拆解物品回收材料的 function。拆解产出由本地锻造规则控制,避免与物品设计脱节。
说明:在锻造面板中拆解物品回收材料的 function。拆解产出由后端锻造 resolver 控制,避免与物品设计脱节。
- `forge_reforge`
脚本:`src/data/functionCatalog/panel/forgeReforge.ts`

View File

@@ -6,44 +6,36 @@
统一角色属性系统把一个世界中“角色能力如何被理解”收口到 `CustomWorldProfile.attributeSchema.slots`。这六个 slot 是世界级设定,不是单个角色自己的六个字段。
当前结果页世界页可以展示角色维度,但编辑世界信息时只能修改世界名称、概述、基调、目标等文本,尚不能手动修订六个维度本身的信息
当前结果页世界页可以展示角色维度。旧方案曾允许编辑维度定义、正负信号和战斗/社交/探索用途,但这些字段会让创作和提示词下游过早背负规则说明。本轮收缩为只允许修订六个维度名称
## 2. 本次目标
在“编辑世界信息”独立面板中允许用户编辑六个角色维度的信息
在“编辑基本设定”独立面板中允许用户编辑六个角色维度名称
1. 修改 `attributeSchema.slots` 中每个维度的 `name``definition``positiveSignals``negativeSignals``combatUseText``socialUseText``explorationUseText`
1. 修改 `attributeSchema.slots` 中每个维度的 `name`
2. 不在可扮演角色或场景角色编辑器中新增单角色六维数值编辑。
3. 保存时同步更新 `profile.attributeSchema`
4.`profile.ownedSettingLayers.ruleProfile.attributeSchema` 存在,同步写入同一份 schema避免世界档案和设定层出现双源漂移。
5. 前端只负责编辑结构化文本,不新增属性结算逻辑。
5. 前端只负责编辑名称,不新增属性结算逻辑,也不再保存维度说明、正负信号和用途文本
## 3. 交互设计
入口位置:
- 世界页点击“世界概述”里的编辑按钮
- 打开现有“编辑世界信息”面板
- 世界页点击“基本设定”里的编辑按钮
- 打开现有“编辑基本设定”面板
- 在基础世界文本字段下方增加“角色维度”区块
每个维度展示并允许编辑
- 维度名称
- 定义
- 正向信号
- 负向信号
- 战斗体现
- 社交体现
- 探索体现
正向信号与负向信号使用逗号、中文逗号或换行拆分成数组。
每个维度展示并允许编辑“维度名称”。
## 4. 数据落点
保存路径:
- `profile.attributeSchema.slots[n]`
- `profile.ownedSettingLayers.ruleProfile.attributeSchema.slots[n]`,仅当 `ownedSettingLayers` 已存在时同步
- `profile.attributeSchema.slots[n].name`
- `profile.ownedSettingLayers.ruleProfile.attributeSchema.slots[n].name`,仅当 `ownedSettingLayers` 已存在时同步
系统仍保留 `slotId` 作为稳定键,解析旧草稿时会丢弃旧 `definition``positiveSignals``negativeSignals``combatUseText``socialUseText``explorationUseText` 字段。
不修改:
@@ -52,7 +44,7 @@
## 5. 验收
1. 世界信息面板能看到六个角色维度。
2. 修改任一维度名称、定义、信号或三类用途说明后,保存到 `profile.attributeSchema.slots`
1. 基本设定面板能看到六个角色维度名称
2. 修改任一维度名称后,保存到 `profile.attributeSchema.slots`,且不会写回旧说明字段
3. 编辑角色自身时不出现单角色六维数值输入区。
4. UI 仍读取当前世界 schema不回退写死旧四维文案。

View File

@@ -162,3 +162,29 @@
5. `npm run test -- src/services/ai.test.ts src/hooks/rpg-runtime-story/storyRequestCoordinator.test.ts src/hooks/rpg-runtime-story/useRpgRuntimeStoryController.test.tsx`
6. `npm run test -- src/hooks/rpg-runtime-story/sessionActions.test.ts src/hooks/rpg-runtime-story/choiceActions.test.ts src/hooks/rpg-runtime-story/npcEncounterActions.test.ts`
7. `npx eslint src/hooks/rpg-runtime-story/sessionActions.ts src/hooks/rpg-runtime-story/sessionActions.test.ts src/hooks/rpg-runtime-story/useRpgRuntimeNpcInteraction.ts src/hooks/rpg-runtime-story/choiceActions.ts src/hooks/rpg-runtime-story/choiceActions.test.ts --max-warnings 0`
### 4.6 `camp_travel_home_scene` 后端收尾
本轮继续收口完成度核验中最后一个残留点:`camp_travel_home_scene` 不能再被前端 `runCampTravelHomeChoice(...)` 提前拦截并本地拼装正式状态。
落地规则:
1. 前端点击 `camp_travel_home_scene` 后统一进入 `runServerRuntimeChoiceAction(...)`,只提交 `sessionId / clientVersion / functionId / optionText / runtimePayload`
2. `server-rs/crates/api-server/src/runtime_story/compat.rs` 负责解析离营目标场景:
- 优先使用 action payload 中的 `targetSceneId`
- 内置世界按 `playerCharacter.id + worldType` 映射到角色主场景。
- 自定义世界优先找玩家角色在 `landmarks[].sceneNpcIds` 中绑定的地点,否则使用当前营地的 `forwardSceneId / connectedSceneIds` 或第一个 landmark。
3. 后端 resolver 写入完整离营状态:
- `currentScenePreset`
- `currentEncounter / sceneHostileNpcs / npcInteractionActive / inBattle`
- `runtimeStats.scenesTraveled`
- `playerX / playerFacing / animationState / playerActionMode / scrollWorld`
- `lastObserveSigns* / currentBattle* / spar* / activeCombatEffects`
4. 后端在目标场景上生成确定性的 encounter preview内置场景至少带一个可交互 NPC自定义场景复用 `build_custom_scene_preset(...)` 中的 NPC 投影。
5. 后端保存 `storyHistory``currentStory`,随后继续走 `project_story_engine_after_action(...)` 和持久化快照。
6. 前端保留 `camp_travel_home_scene` 作为 function id 与展示用 helper但不再保留正式状态构造函数。
验证新增:
1. 后端 route 测试覆盖 `camp_travel_home_scene` 点击后 hydrated snapshot 已进入角色主场景、生成 encounter preview、递增 `scenesTraveled` 并持久化。
2. 前端 `choiceActions.test.ts` 覆盖 `camp_travel_home_scene` 即使命中旧 helper 判定,也只调用 `runServerRuntimeChoiceAction(...)`

View File

@@ -7,7 +7,7 @@ RPG Agent 生成世界草稿时,前端会把 `draftProfile` 归一化成 `Cust
## 落地约束
- `draftProfile.attributeSchema` 是世界草稿真相源的一部分,必须随 foundation draft 一起生成并保存。
- 六维固定使用 `axis_a``axis_f` 六个槽位,但 `schemaName`每个槽位 `name` 和说明必须贴合本次世界设定
- 六维固定使用 `axis_a``axis_f` 六个系统槽位,但创作、提示词输出、解析后保存的数据只保留每个槽位 `name``slotId` 由系统补齐用于数值映射,不要求模型理解或生成额外说明字段
- 维度名不得沿用通用旧词:生命、法力、护甲、攻击、防御、力量、敏捷、智力、精神。
- 若模型遗漏或结构不合规,后端必须生成中文兜底属性体系,不能让前端只靠固定模板补齐。
- 世界页面的“世界”页签必须展示当前 `attributeSchema.slots` 的六个名称,作为玩家进入世界前可见的规则信号。
@@ -25,7 +25,7 @@ RPG Agent 生成世界草稿时,前端会把 `draftProfile` 归一化成 `Cust
3. `server-rs/crates/api-server/src/custom_world_foundation_draft.rs`
- `normalize_framework_shape()` 归一化 `attributeSchema`
- `build_foundation_draft_profile_from_framework()` 将归一化后的 `attributeSchema` 写入 `draftProfile`
- 新增兜底生成器,基于世界名、基调、目标、冲突和种子文本生成六个中文维度。
- 新增兜底生成器,基于世界名、基调、目标、冲突和种子文本生成六个中文维度名称
4. `src/components/CustomWorldEntityCatalog.tsx`
- 在世界页签增加“角色维度”区域,直接渲染 `profile.attributeSchema.slots` 的六个名称。
@@ -33,5 +33,5 @@ RPG Agent 生成世界草稿时,前端会把 `draftProfile` 归一化成 `Cust
## 验收
- 新生成的 RPG 世界草稿 JSON 顶层包含 `attributeSchema.slots.length === 6`
- 结果页/世界页展示六个自定义维度名,而非固定的力量、敏捷、智力、精神。
- 结果页/世界页展示六个自定义维度名,而非固定的力量、敏捷、智力、精神;页面不展示维度说明、正负信号或用途说明
- 缺失或非法模型输出会被后端兜底为合法中文六维。