听娜娜讲故事
nana-story 是一个本地优先、纯 BYOK 的 AI 对话游戏。V1 聚焦一段可回溯、可分支、状态可重放的单角色纵切。
当前阶段
M0 契约基线已建立;M1 状态、投影与持久化主链已经接通;M2 已具备可取消的真实模型 回合,以及面向长分支的上下文检查点与滚动压缩主链。Windows 原生构建基线已经建立, 真实在线 LAPP 与视觉验收仍待关闭。
目前包括:
- Tauri 2 + Vue 3 + TypeScript 工程;
- Rust workspace 与模块所有权边界;
- Rust 领域类型作为契约唯一事实来源;
- 生成的 JSON Schema 与 TypeScript DTO;
- canonical
PlayerViewfixture; - 最小娜娜内容包;
- 原子化状态 reducer,覆盖关系、许诺、知识、持有物、时钟与判定;
- 保持同一语义的内存与 SQLite StoryStore,支持事务追加、恢复和回溯分叉;
- SQLite schema v3,以及从 schema v1 / v2 的无损迁移、旧库完整性校验、WAL、 busy timeout 与未来版本拒绝;
- 写入与恢复时的状态哈希校验;
RuntimeState → PlayerView脱敏投影与隐藏信息 canary 测试;TurnPlan → reducer → SQLite → PlayerView单轮提交链;- 随故事节点持久化并恢复 scene、expression、pose、beats 与 suggestions;
- 确定性的场景上下文编译器,按固定顺序筛选角色卡、Persona、世界书、剧情事件与可见记忆;
- 缓存友好的 prompt schema v3:稳定资源前缀、当前分支检查点 / 原文尾部和动态本轮 内容各自分区;模型上下文窗口、输出上限、工具续调用与安全余量统一进入预算;
- 长分支超过预算时,由当前选中的同一个 LAPP 模型通过严格的摘要工具滚动压缩;摘要 只接受当前分支的玩家安全叙事投影,始终是可删除、可重建的非权威缓存;
- 检查点通过稳定前缀与叙事来源 SHA-256 校验,只能沿当前祖先链继承;损坏、过期或 来自兄弟分支的缓存不会参与提示词;
- 新检查点先作为待提交结果保留,最终与普通节点或重生成节点在同一存储事务中提交; 取消、超时、陈旧线路或无效输出不会留下半轮节点或孤立检查点;
- 可继续的模型回复会在提交前按同一模型预算验证其“下一轮最新原文”占用;即使输出 符合静态 Schema,只要会让后续回合永久无法编排,就不会写入线路;
- 内存与 SQLite 后端均覆盖 500 节点祖先链读取和检查点查找,不再沿用界面层的 200 节点深度限制;
- 引擎掌控的类型化隐藏检定循环,模型只收到定性结果,不能指定或读取骰点、难度与精确数值;
- 基于
lapp-rs原生工具消息的 LAPP TurnPlan provider 与严格输出校验; - 从任意当前线路历史节点创建真实持久化分支,旧线路与新线路保持隔离;
- 列出、重命名、切换故事线路,并在关闭应用后恢复最后活动线路;
- 应用内选择 LAPP profile 中声明了聊天与工具调用能力的模型,凭据仍只由 LAPP Vault 即时解析;
- 应用内测试当前已应用模型的最小连接,不接收任意模型目标,也不返回供应商正文;
- 回合支持停止生成与 90 秒应用截止时间;取消、超时或无效输出都不能产生半轮节点;
- 缺凭据、配置错误、限流、供应商拒绝与网络不可用使用脱敏错误分类,并只允许一次 明确的安全重试;
- 可完整游玩的“天亮之前”纵切:接受许诺、隐藏搜索、获得车票、进入隧道、天亮前 归来并结算许诺;
- Turn 请求/结果校验、Fake Provider 与确定性世界书触发;
- 可交互的主演出屏、持有物/线索/许诺、关系与回溯面板。
浏览器模式继续使用确定性的本地 Turn adapter,方便无桌面壳开发;Tauri
模式已经通过 submit_turn 使用 SQLite 自动保存和恢复,并通过 fork_branch
创建持久化分支。线路选择和名称也保存在同一 SQLite 存档中。桌面端默认使用真实
LAPP provider;只有显式设置
NANA_STORY_PROVIDER=demo 时才启用确定性的娜娜纵切实现。
应用内“设置”只选择 LAPP profile 已有模型,不读取、保存或回显 API Key。若 profile
缺失,或没有声明 chat 与 tool-call 能力的启用模型,界面会明确显示不可用。
Rust 1.96 下的 workspace 共 215 项测试通过:Contracts 1、Domain 5、Engine 21、
Runtime 106、Store 65、Tauri 17;全 workspace Clippy、25 份契约 Schema 检查、
TypeScript 检查、29 项 Web 测试与生产构建均已通过。Windows 原生构建基线与复现
步骤见 docs/windows-developer-smoke.md,本轮
不据此宣称真实在线 LAPP 或窗口视觉验收已经完成。
开发
要求:
- Node.js 24+
- pnpm 10.29.2
- Rust 1.96
- 与本仓库同级的
lapp-rs,固定到lapp-rs.lock中的提交
workspace/
├─ lapp-rs/
└─ nana-story/
pnpm install
pnpm verify
pnpm tauri dev
不配置 LAPP、仅运行确定性纵切时:
NANA_STORY_PROVIDER=demo pnpm tauri dev
只验证前端和已提交契约时可运行:
pnpm verify:web
边界
- 模型供应商协议与凭据处理属于
lapp-rs。 - 前端只接收
PlayerView,不会得到完整RuntimeState。 - V1 不使用向量记忆库、导演 Agent 或多个完整角色。
- 模型与前端都不能直接修改运行时状态。