Files
nana-story/tasks/plan.md

287 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Implementation Plan: Wave 7 本地 Windows 闭环
## Overview
`integration/v1@23672e857bfa854930b0c8ab8aca316a95ba5d09` 继续开发。先关闭真实
Windows 基线暴露出的可重复性问题,再补齐真实模型的当前分支连续上下文与超预算检查点,
随后实现“风险预检 → 玩家确认 → 隐藏检定失败 → 可推骰 / 可重新生成”的纵向切片。
每个阶段都必须保持回合原子提交、分支隔离和 `PlayerView` 脱敏边界。
## Architecture Decisions
- 继续使用 `integration/v1`,不在本地另起一套重建工程。
- `lapp-rs` 保持相邻 path dependency,并固定到 `5ba3c659…`
- 契约源码哈希统一按 LF 规范化;同时用 `.gitattributes` 固定文本文件换行,避免
Windows `core.autocrlf=true` 产生假漂移。
- 模型上下文固定为“系统约束 → 稳定资源 → 当前分支检查点 / 原始历史 → 本轮动态尾部”,
提升前缀缓存命中;兄弟分支内容不得进入上下文。
- 压缩检查点是可丢弃缓存,不是事实来源;删除检查点不得改变 `RuntimeState`
- 风险提示是“不落节点的预检结果”,只有玩家确认后才进入现有隐藏判定与原子提交链。
- `Regenerate` 复用原行动的判定记录;`PushCheck` 是带明确后果的新行动和新节点。
- 在重新生成 / 推骰语义闭环前,不扩大到内容包导入、TTS、生图或第二完整角色。
## Dependency Graph
```text
Windows 可重复契约门禁
└─ 精确 Node/pnpm + Rust/MSVC 工具链
└─ Wave 6 全量基线
└─ 当前分支连续上下文
└─ 超预算检查点压缩
└─ 风险预检契约
├─ Runtime / Store 语义
└─ Tauri 窄命令
└─ Vue 确认、推骰、重新生成界面
└─ Windows Demo + LAPP 冒烟
```
## Task 1: 修复跨平台契约哈希
**Description:** 消除 Windows CRLF checkout 对契约源码哈希的影响,同时固定未来 checkout
的文本换行。
**Acceptance criteria:**
- [x] 干净 Windows checkout 上 `node scripts/verify-contracts.mjs` 通过。
- [x] Rust 生成器对 LF 与 CRLF 输入计算相同源码哈希。
- [x] Linux 既有 `.source.sha256` 不发生无意义变化。
**Verification:**
- [x] `node scripts/verify-contracts.mjs`
- [x] `cargo test -p nana-contracts`
- [x] `cargo run -p nana-contracts -- --check`
- [x] `git diff --check`
**Dependencies:** None
**Files likely touched:**
- `.gitattributes`
- `scripts/verify-contracts.mjs`
- `crates/nana-contracts/src/main.rs`
**Estimated scope:** Medium
## Task 2: 恢复锁定的本地工具链
**Description:** 让 Windows 开发机满足仓库已声明的精确依赖,不修改项目依赖版本。
**Acceptance criteria:**
- [x] Node.js 24+ 与 pnpm 10.29.2 可用。
- [x] Rust 1.96.0、rustfmt、clippy、MSVC Build Tools、Windows SDK 可用。
- [x] 相邻 `lapp-rs` 位于固定提交且工作树干净。
**Verification:**
- [x] `node --version`
- [x] `pnpm --version`
- [x] `rustc --version`
- [x] `cargo clippy --version`
- [x] `git -C ..\lapp-rs rev-parse HEAD`
**Dependencies:** Task 1 可并行
**Files likely touched:** None(仅本机工具链与依赖目录)
**Estimated scope:** Medium
## Task 3: 关闭 Wave 6 Windows 机械门禁
**Description:** 在真实 Windows 目标上重新验证既有 119 项核心 Rust、18 项 Tauri、
29 项 Web 测试和无 bundle 桌面编译。
**Acceptance criteria:**
- [x] 依赖安装使用锁文件且不修改锁文件。
- [x] `pnpm verify` 等价的 Web / Rust / 契约门禁全绿。
- [x] `pnpm tauri build --no-bundle` 成功。
**Verification:**
- [ ] `powershell.exe -NoProfile -File .\scripts\windows-smoke.ps1 -InstallDependencies`
**Dependencies:** Tasks 1-2
**Files likely touched:** None
**Estimated scope:** Small
## Checkpoint: Windows 基线
- [x] 工作树只包含已审阅的 Wave 7 变更。
- [x] 契约、Web、Rust、Tauri 门禁均可重复。
- [x] 记录首个无法自动关闭的环境阻塞。
## Task 4: 恢复当前分支连续上下文
**Description:** Store 提供按 `parent_id` 追溯的祖先链;Runtime 将稳定资源、当前分支
历史和本轮输入按固定顺序编译给 LAPP,解决真实模型第二轮起失忆的问题。
**Acceptance criteria:**
- [x] 第三轮模型输入包含根到当前节点的前两轮玩家输入和演出节拍。
- [x] 分叉后只包含本分支祖先,兄弟分支文本和隐藏状态不泄漏。
- [x] 系统约束、角色卡和 Persona 在连续回合中保持逐字节稳定,本轮输入位于尾部。
- [x] 精确骰点、目标值、状态 delta、NPC 隐藏物品和未触发世界书不进入上下文。
**Verification:**
- [x] Store 祖先链测试覆盖分叉共享祖先。
- [x] Runtime 捕获模型输入的三轮与兄弟分支隔离测试。
- [x] 既有 PlayerView / 上下文泄密 canary 通过。
**Dependencies:** Checkpoint: Windows 基线
**Files likely touched:**
- `crates/nana-store/src/lib.rs`
- `crates/nana-runtime/src/context.rs`
- `crates/nana-runtime/src/lib.rs`
- `crates/nana-runtime/src/lapp_provider.rs`
- `src-tauri/src/lib.rs`
**Estimated scope:** Medium
## Task 5: 增加超预算分支检查点
**Description:** 根据模型上下文窗口预算保留“最近祖先检查点 + 检查点后原始节点 + 本轮
输入”;超预算时使用同一 LAPP 模型压缩旧段,并把检查点作为当前节点的非权威缓存。
**Acceptance criteria:**
- [ ] 500 节点分支恢复不扫描无关分支并保持在输入预算内。
- [ ] 检查点只继承自当前祖先链,来源哈希不符时拒绝使用。
- [ ] 删除检查点后 `RuntimeState`、分支头和 `PlayerView` 不变。
- [ ] 压缩取消、超时或畸形输出不创建节点、不移动分支头。
**Verification:**
- [ ] SQLite v2 → v3 无损迁移测试。
- [ ] 预算边界、检查点继承、来源哈希和删除重建测试。
- [ ] 压缩调用复用既有取消控制与原生单飞闸门。
**Dependencies:** Task 4
**Files likely touched:**
- `crates/nana-domain/src/lib.rs`
- `crates/nana-store/src/lib.rs`
- `crates/nana-runtime/src/context.rs`
- `crates/nana-runtime/src/lapp_provider.rs`
- `src-tauri/src/lib.rs`
**Estimated scope:** MediumCore 与 Runtime 可在内部契约冻结后并行)
## Checkpoint: 连续上下文
- [ ] 三轮真实上下文连续。
- [ ] 兄弟分支隔离。
- [ ] 稳定前缀可缓存。
- [ ] 500 节点与超预算检查点测试通过。
## Task 6: 增加不落节点的风险预检契约
**Description:** 高风险玩家行动先返回脱敏风险描述和确认令牌,不调用隐藏判定、不推进
状态、不创建故事节点。
**Acceptance criteria:**
- [ ] 普通行动仍沿用现有单次提交路径。
- [ ] 高风险行动首次提交只返回玩家可理解的风险提示。
- [ ] 预检结果不包含骰点、目标值、NPC 隐藏信息或精确关系数值。
**Verification:**
- [ ] Domain / Runtime 契约测试。
- [ ] Tauri 命令测试证明预检不写 SQLite。
- [ ] PlayerView 泄密 canary 继续通过。
**Dependencies:** Checkpoint: 连续上下文
**Files likely touched:**
- `crates/nana-domain/src/lib.rs`
- `crates/nana-runtime/src/`
- `src-tauri/src/lib.rs`
- `contracts/`
**Estimated scope:** Medium
## Task 7: 完成确认、推骰与重新生成纵切
**Description:** 把现有 `Regenerate` / `PushCheck` 领域语义接到 Tauri 与 Vue,让玩家在失败
后选择承担结果、推骰或重新生成叙述。
**Acceptance criteria:**
- [ ] 确认风险后只产生一个完整节点。
- [ ] `Regenerate` 复用原判定,不允许刷骰。
- [ ] `PushCheck` 明示后果并创建新行动、新判定和新节点。
- [ ] 回溯后两条线路的判定、物品、许诺和关系互不污染。
**Verification:**
- [ ] Runtime / Store 端到端测试。
- [ ] Tauri 命令测试。
- [ ] Vue 交互测试覆盖确认、取消、推骰、重新生成。
- [ ] 完整 `pnpm verify`
**Dependencies:** Task 6
**Files likely touched:**
- `crates/nana-runtime/src/adjudication.rs`
- `crates/nana-store/src/lib.rs`
- `src-tauri/src/lib.rs`
- `src/app/`
- `src/App.vue`
**Estimated scope:** Medium(按契约、后端、前端三个小提交交付)
## Checkpoint: 可玩纵切
- [ ] 风险提示先于隐藏检定。
- [ ] 失败、推骰、重新生成的语义可被玩家区分。
- [ ] 取消、超时和畸形响应仍不产生半轮。
- [ ] Demo 与真实 LAPP 各完成一次隐藏判定。
## Task 8: Windows 桌面冒烟与交付
**Description:** 启动隔离存档的 Demo 窗口,验证两次重启、终局、回溯与双线路隔离;随后
执行真实 LAPP 最小连接及隐藏判定。
**Acceptance criteria:**
- [ ] Demo 窗口启动并正常退出。
- [ ] 两次重启恢复、终局和双线路隔离通过。
- [ ] 真实 LAPP 连接测试及一轮工具调用通过,日志无凭据。
**Verification:**
- [ ] `scripts/windows-smoke.ps1 -Launch -Demo`
- [ ] `scripts/windows-smoke.ps1 -Launch`
**Dependencies:** Task 7
**Files likely touched:** 仅状态报告;若冒烟发现缺陷则另建小任务。
**Estimated scope:** Medium
## Risks and Mitigations
| Risk | Impact | Mitigation |
|---|---|---|
| Gitea SSH 2222 被本机代理拦截 | 无法自动 fetch/push | 本地开发不依赖 fetch;提交前使用用户终端 SSH 或短期 HTTPS 凭据 |
| Rust/MSVC 未安装 | 无法关闭 Tauri 门禁 | 先完成纯文本跨平台修复;工具链作为显式环境任务 |
| 精确 pnpm 下载不稳定 | Web 验证延迟 | 保留锁文件;优先使用 Corepack 官方包并重试,不升级项目版本 |
| 祖先链错误按 branch_id 过滤 | 分叉后丢失共享历史 | 只按 parent_id 追溯并做兄弟分支隔离测试 |
| 压缩摘要被误当事实 | 删除缓存后剧情状态变化 | 检查点保持非权威,状态仍只由根状态 + delta 重建 |
| 风险预检变成第二套状态机 | 原子性回归 | 预检只产生短期确认数据,唯一 reducer / SQLite 提交路径不变 |
| 重新生成可刷骰 | 破坏公平性 | 判定绑定原 action/check;只有 PushCheck 创建新判定 |
## Open Questions
- 无产品阻塞问题。Rust/MSVC 安装若需要管理员交互,将在 Task 2 单独请求用户操作。