feat(app): persist demo turns through Tauri
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
# M1/M2 第二并行波次状态
|
||||
|
||||
日期:2026-07-28
|
||||
集成分支:`integration/v1`
|
||||
起始基线:`fa8bd0d`
|
||||
|
||||
## 本波次目标
|
||||
|
||||
从第一波静态契约和内存测试缝继续接通:
|
||||
|
||||
- `RuntimeState → PlayerView` 脱敏投影;
|
||||
- 与内存实现同语义的 SQLite StoryStore;
|
||||
- 持久化单轮 Turn Engine;
|
||||
- Tauri `submit_turn` 与浏览器/Tauri 双模式前端桥接;
|
||||
- “天亮前一定回来”许诺纵切的首次端到端提交与恢复。
|
||||
|
||||
开发时使用 1 个集成人和 3 个独立 worktree。游戏运行时仍是单模型架构,
|
||||
没有引入导演 Agent。
|
||||
|
||||
## 已集成
|
||||
|
||||
### PlayerView 投影
|
||||
|
||||
- `project_player_view` 是 `RuntimeState` 到玩家可见状态的唯一纯投影。
|
||||
- 仅显示玩家当前持有且存在公开 `ItemSpec` 的物品。
|
||||
- 仅显示 `observer == player` 的知识。
|
||||
- 仅显示玩家参与、已接受或已结束的许诺。
|
||||
- 六维关系只映射为五档区间,不暴露精确数值。
|
||||
- 判定、NPC 物品、隐藏事实、内部规则和 NPC-only 许诺不进入视图。
|
||||
- 关系更新时间沿当前 lineage 查找最近一次 `nana → player` 变化,不受其他关系边影响。
|
||||
|
||||
### SQLite StoryStore
|
||||
|
||||
- `nodes`、`materialized_states`、`branch_heads` 三表初始化。
|
||||
- `append_node` 使用 `IMMEDIATE` 单事务。
|
||||
- 父节点、单根、节点唯一、stale head 与新分支语义和内存实现保持一致。
|
||||
- 支持按分支恢复状态、按 ID 读取节点和按节点读取物化状态。
|
||||
- 写入与恢复均重新计算 `state_hash`。
|
||||
- 节点 JSON 会与 SQLite 中的 story、node、branch、parent 结构列交叉校验。
|
||||
- 有效 JSON 的静默损坏、结构列漂移和无效 JSON 都会被拒绝。
|
||||
|
||||
### 持久化 Turn Engine
|
||||
|
||||
模型侧只能返回内部 `TurnPlan`:
|
||||
|
||||
```text
|
||||
validate request
|
||||
→ load branch state
|
||||
→ stale check
|
||||
→ provider plan
|
||||
→ reducer
|
||||
→ state hash
|
||||
→ atomic append
|
||||
→ infallible PlayerView projection
|
||||
→ TurnResult
|
||||
```
|
||||
|
||||
- 模型不能直接构造最终 `PlayerView`。
|
||||
- reducer、provider、store 和序列化错误都在提交前返回。
|
||||
- projector 被定义为不可失败的防御性纯边界,消除“已提交但整轮报失败”的窗口。
|
||||
- 提交身份由已落库状态覆盖,不信任 projector 提供的 story/node/branch。
|
||||
- 上游、规则和存储错误转换为稳定、脱敏的 `TurnFailure`。
|
||||
|
||||
### Tauri 纵切
|
||||
|
||||
- 首次启动在应用数据目录创建 SQLite 数据库并播种根节点。
|
||||
- 启动时严格区分全新数据库、缺分支数据库和损坏数据库。
|
||||
- `get_demo_player_view` 从已保存状态、当前节点和 lineage 重新投影。
|
||||
- `submit_turn` 走真实 Turn Engine 与 SQLite,而不是静态 `PlayerView`。
|
||||
- 许诺“天亮前一定回来”会创建 accepted Promise、提高 hope、保存节点并返回脱敏视图。
|
||||
- 重新打开文件数据库后恢复同一节点、许诺、关系档位和当前线路历史。
|
||||
- 浏览器开发模式仍保留确定性 adapter;Tauri 模式通过同一前端 API 调用命令。
|
||||
|
||||
## 安全修正
|
||||
|
||||
交叉审查额外修正了以下问题:
|
||||
|
||||
- NPC 与 NPC 之间的许诺不会通过许诺侧栏或历史标签泄漏。
|
||||
- NPC-only 关系变化不会触发玩家关系“最近更新”提示。
|
||||
- 历史 lineage 损坏在启动恢复时会作为存档错误上报,不伪装成正常短历史。
|
||||
- 节点 ID 使用 story、branch、action 的稳定哈希,避免字符清洗和跨分支碰撞。
|
||||
- Tauri 错误保留 `retryable`,前端能读取结构化错误对象的 message。
|
||||
|
||||
## 已通过验证
|
||||
|
||||
```text
|
||||
canonical JSON fixtures parse
|
||||
|
||||
node scripts/verify-contracts.mjs
|
||||
15 schemas and TypeScript DTO source hash verified
|
||||
|
||||
vue-tsc --noEmit
|
||||
|
||||
vitest run
|
||||
4 test files passed
|
||||
12 tests passed
|
||||
|
||||
vite build
|
||||
production build succeeded
|
||||
|
||||
SQLite schema smoke
|
||||
branch_heads, materialized_states, nodes created in memory
|
||||
```
|
||||
|
||||
当前源码共声明 55 项 Rust 单元/集成测试,覆盖 reducer、投影、内存/SQLite
|
||||
存储、Turn Engine 和 Tauri 纵切。
|
||||
|
||||
## 尚未关闭
|
||||
|
||||
当前 Work 环境仍没有 `cargo`、`rustc` 和 `rustfmt`,因此 55 项 Rust 测试、
|
||||
Tauri 宏展开、rusqlite 编译与桌面启动尚未实际验证。必须在 Rust 1.96 环境执行:
|
||||
|
||||
```text
|
||||
cargo fmt --all -- --check
|
||||
cargo clippy --workspace --all-targets -- -D warnings
|
||||
cargo test --workspace
|
||||
cargo run -p nana-contracts -- --check
|
||||
pnpm tauri dev
|
||||
```
|
||||
|
||||
在这些命令通过前,不把 M0/M1 标记为完成。
|
||||
|
||||
## 已知的下一阶段缺口
|
||||
|
||||
- Tauri provider 目前是确定性的娜娜纵切,不是真实 LAPP 模型调用。
|
||||
- 动态 suggestions 和完整 scene/expression/pose 快照尚未进入持久化节点;真实
|
||||
provider 接入前必须冻结 presentation snapshot 契约。
|
||||
- 回溯面板尚未调用创建分支命令。
|
||||
- SQLite 尚未加入 schema migration 版本和多实例 busy timeout。
|
||||
|
||||
## 下一波次
|
||||
|
||||
1. 在 Rust 1.96 环境关闭首次编译、格式、Clippy 与 Tauri 启动门。
|
||||
2. 冻结可恢复的 presentation snapshot,避免动态建议和视觉状态在重启后漂移。
|
||||
3. 用 `lapp-rs` 接入真实非流式 TurnPlan provider,并继续保留 Fake Provider CI。
|
||||
4. 接入上下文编译与类型化工具循环,确保整轮只有一次提交。
|
||||
5. 为回溯面板增加“从这里继续”命令,验证旧分支保留和新分支状态隔离。
|
||||
Reference in New Issue
Block a user