# M2 第六波状态 日期:2026-07-28 ## 基线 本轮从已推送的 `integration/v1@1f935a3` 开始,目标是把真实模型回合从“能调用” 收敛为“可停止、可超时、失败不产生半轮、玩家能安全恢复”,并准备一套可在真实 Windows 开发机重复执行的桌面冒烟流程。 ## 已完成 ### 可取消的原子回合 - 新增一次性 `TurnControl`,取消、90 秒截止时间与 SQLite 提交竞争同一个原子边界。 - Tauri 在调度后台回合前同步登记 `actionId`,消除“提交后立刻停止”找不到回合的窗口。 - 停止命令不等待故事操作锁;提交已经赢得边界时,原提交结果仍是唯一权威,界面会明确 告知完整回合已安全写入。 - LAPP 请求运行在隔离的原生请求线程;同步 Vault 解析卡住时,取消或超时仍能及时返回, reducer 与 SQLite 不会收到半轮结果。 - 中断后的 LAPP executor 会先发布退休状态,Tauri 在向界面返回前重建 provider;同一 `TurnRequest` 与 `actionId` 可进行一次安全重试。 - 故事回合与连接测试共享原生调用单飞闸门。旧 Vault/HTTP 调用真正退出前不会再启动 新的原生模型调用,避免连续取消累积后台线程。 ### 错误恢复与连接测试 - 后端只根据 LAPP 稳定错误码和 HTTP 状态分类配置错误、凭据不可用、限流、供应商拒绝、 网络不可用、超时与无效响应;供应商正文不会进入 `TurnFailure` 或玩家界面。 - 界面只对后端标记为可重试的失败显示一次“重试本轮”,并复用原请求和动作 ID。 - 新增“测试当前连接”。Tauri 命令不接受 provider/model 参数,只读取当前已应用设置, 因而不能被前端用于探测任意模型。 - 连接测试在独立线程执行,受 35 秒外层超时与单飞保护;返回值只包含 provider/model 标识、成功状态和稳定诊断码,不包含凭据或供应商响应正文。 - 连接成功只证明最小聊天请求可用;隐藏判定工具调用仍需在真实故事回合中验证。 ### Windows 开发机冒烟 - 新增 `scripts/windows-smoke.ps1`,检查干净且已跟踪远端的 `integration/v1`、Rust 1.96 MSVC host、Node 24、精确 pnpm、锁文件一致性,以及相邻 `lapp-rs` 的来源、 固定提交与干净工作树。 - 脚本依次执行全量 `pnpm verify` 和 `pnpm tauri build --no-bundle`;只有全部通过后 才可选启动桌面窗口。 - `-Launch` 强制使用 Windows 临时目录下的显式隔离存档路径。应用会 canonicalize 路径并拒绝相对路径、临时目录根和链接逃逸;脚本不会删除该目录,便于重启恢复验证。 - `-Demo` 先验证窗口、SQLite 恢复、终局与双线路隔离;默认 LAPP 模式再验证 profile、 Vault、最小连接和一轮真实工具调用。 完整操作见 [`docs/windows-developer-smoke.md`](../windows-developer-smoke.md)。 ## 验证结果 - Rust 1.96 `cargo fmt --check` 通过。 - 119 项核心 Rust 测试通过:Domain 5、Engine 21、Runtime 61、Store 32。 - Tauri 后端 **18** 项测试通过,包括取消前置竞态、provider 退休后同动作重试、 连接单飞、隔离存档路径和既有文件数据库纵切。 - 核心与 Tauri Clippy `-D warnings` 通过,Tauri 全 target 类型检查通过。 - 25 份契约 Schema、TypeScript DTO 与 Rust 源哈希一致,Schema 清单本身也受检查。 - TypeScript 严格检查、29 项 Web 测试和 Vite 生产构建通过。 Tauri 检查和后端测试在当前 Linux Work 环境继续使用空的 GUI 链接占位库;它们证明 Rust/Tauri 代码、宏和测试能够编译执行,不等同于真实 WebView2 窗口或 Windows 二进制。 PowerShell 脚本也尚未在本环境解析执行。 ## 明确限制 - 固定版 `lapp-rs@5ba3c659…` 的流事件只有文本增量、结束与用量,不包含工具调用片段, 且流式 API 不返回最终 `ChatResponse`。因此本轮实现的是可取消的非流式可信回合; 在 LAPP 增加可验证的工具调用流与最终响应前,不能安全地把隐藏检定/TurnPlan 改成 真正流式提交。 - Rust 无法强杀正在执行的 Windows 原生 Vault 调用。单飞闸门会阻止新的调用,应用与 SQLite 仍能及时结束本轮;若原生调用永久不返回,后续模型调用需等待或重启应用。 - 某些供应商可能已在取消生效前接收请求,因此“未写入故事”不等于绝对不会产生一次 供应商计费。消除这一点需要 `lapp-rs` 提供可取消、分阶段的凭据解析与请求 API。 ## 尚待真实 PC 关闭 1. 在 Windows 上实际执行脚本,确认完整验证与 `tauri build --no-bundle`。 2. 使用隔离存档启动 Demo 窗口,完成两次重启、终局与双线路隔离。 3. 使用真实 LAPP profile/Vault 运行最小连接测试及至少一轮隐藏判定工具调用。 4. 记录 Windows 版本、架构、被测提交和首个失败点;不得回传凭据、profile、数据库或 完整供应商响应。