发布独立游戏聊天0.1.1并强化试玩验收

新增只能打开游戏聊天页的0.1.1独立release构建配置。
内置Runner启动、诊断日志、Windows后台进程与退出收束。
修复自动预览启动、同页版本刷新和结构化验收状态展示。
强化试玩协议、窗口末端采样与固定失败识别,允许正常输赢但拒绝无法推进。
完善旧验收回执自愈和当前场景指纹完成门。
补齐Rust、前端、真实Chrome回归测试及项目文档。
This commit is contained in:
2026-07-31 13:32:07 +08:00
parent 216407d93e
commit dcd8901246
56 changed files with 6891 additions and 364 deletions
@@ -59,6 +59,34 @@ AI 游戏创作独立客户端常用短命令:
npm run agc
```
需要构建只能打开“游戏运行 + 聊天”页面的独立 release 包时使用:
```bash
npm run agc:build:game-chat-release
```
该命令启用 Rust `game-chat-release` feature,并配合编译期前端入口锁定生成独立 NSIS 包。当前专用 release 版本为 `0.1.1`;产物的 `productName` 为 `Genarrative Game Chat`,`identifier` 为 `world.genarrative.ai-game-creator.game-chat`,安装身份和 AppData 不与普通 AI 游戏创作客户端混用。独立包直接渲染本地 `GameChatReleaseApp`,绕过平台 `AuthenticatedClient`,进入本地项目工作台不依赖 `api-server`;普通 `npm run agc`、`npm run agc:dev`、debug game-chat 和 `npm run agc:build` 继续走既有认证入口与配置。
game-chat 的用户可见 preview 必须由 Tauri 客户端 `PreviewRegistry` 持有。External Runner 和 Tauri 的 registry、server 句柄与 running 状态是进程内资源,不得互相推断或把 Runner 验证用 server 直接交给 iframe。当前 accepted Supervisor 父 run 下真实 `preview-playtest` scheduler child 首次给出结构化成功证据、且其 revision 精确等于项目当前 revision 后,客户端才消费一次性授权并启动一个 Tauri preview server,随后自动显示 iframe;`preview.start` 必须携带 `expectedRevision`,Tauri 在取得项目写锁后再次原子比对。same-run steer 授权必须记录授权前 revision / validation cursor 和唯一 generation ID,旧证据、旧 policy await 或旧 start 返回均不能清除新授权。同一 run 的更高 validated revision 只刷新原 iframe,不能重复 `preview.start` 或新增 server,相同 / 更低 revision 不刷新;同 revision 的最新失败证据必须关闭该 revision 的可玩判定。preview HTTP 的 HTML、脚本、样式、资源和错误响应都必须返回 `Cache-Control: no-store`。没有 Tauri 用户预览时,顶部状态必须显示“预览未启动”,不能只写“未启动”。
`generic-v1` 的真实试玩必须从 `ready` 且正整数 level 开始;start 推进到 `playing` 后,必须先持续观察 2 秒并取得至少 8 个实际样本,期间保持 `playing`,以确认玩家获得正常操作机会;随后点击唯一可见、启用且真实可交互的 `data-playtest-id="primary-action"`,由该控件触发真实主要玩法操作,并以 sequence 相对点击前严格推进证明操作已被接受。操作被接受前进入 `won | lost` 代表玩家没有获得正常操作机会,必须失败;操作被接受后的单次 `lost` 是合法结局,但不能成为所有受控尝试的唯一结果。若主要操作后仍为 `playing`,则继续观察 3 秒并取得至少 12 个实际样本;`won` 可提前证明非失败推进。之后 restart 必须推进 sequence、恢复到 `ready | playing`,并持续观察 3 秒、取得至少 12 个实际样本;若首轮结果为 `lost`,重开稳定后必须再执行一次必要的 start、2 秒 / 8 样本操作机会和真实 primary-action,第二次必须进入或保持 `playing`(再观察 3 秒 / 12 样本且不得转为 `lost`)或进入 `won`。两次受控尝试都固定 `lost` 代表无法正常推进的恶性 bug,必须失败。各观察窗口内 sequence 不得回退,restart 窗口只能保持 `ready | playing`。样本数和观察时长必须同时满足,窗口末端必须强制再读取一次有效状态,不能靠前段样本数提前通过。selector、时长、样本门槛、终态边界、非失败推进、窗口末端覆盖、required assertions 和 sequence 规则都属于 scenario fingerprint。旧 fingerprint 回执在读取和 plan liveness 检查时按 stale missing 处理,让同一 run 可重新 `preview.validate`;身份、digest、路径或内容完整性篡改仍失败关闭,最终完成门仍须现场重算当前 fingerprint 并严格拒绝旧证据。
进度展示只把结构化 `preview.validate` 的 `passed=true && playtestPassed=true` 认作试玩通过,不从 `summary` 的 `:ok` 推断结论。`image.inspect status=ok` 只表示工具成功;`passed=null` 或缺少结构化布尔结论时显示中性“截图分析完成”,不得显示绿色通过。
真实 Chrome 回归必须用同一前缀同时覆盖尚未接受 `primary-action` 就瞬时进入 `lost` 的 FAIL、两次受控尝试都固定 `lost` 的 FAIL,以及首轮合法 `lost` 后重开并在第二轮证明非失败推进的 PASS:
```bash
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml real_chrome_generic_playtest_ --features game-chat-release -- --ignored --nocapture --test-threads=1
```
修改 game-chat release flavor 后,至少执行壳配置门禁、AppSurface game-chat 定向测试、前端类型检查、AppData / 诊断日志 / release flavor 相关 Rust 定向测试、`npm run check:encoding` 和 `git diff --check`。打包 smoke 必须确认:安装信息和产物版本为 `0.1.1`;无参数启动直接进入且只能停留在 game-chat 页面;停止或断开 `api-server` 后本地工作台仍能打开;普通 dev / release 与 debug game-chat 仍走原认证入口;独立 AppData 生效。预览 smoke 应先让当前 run 成功验证 revision N,确认 Tauri registry 启动一个 server 且 iframe 自动出现;在 validate 后、start 取得锁前推进项目 revision,必须确认原子 `expectedRevision` 门禁拒绝启动且授权保留等待新证据;再验证 revision N+1,确认 server 进程和 loopback origin 不变、iframe 显示新版本且响应为 `no-store`。same-run steer 还要覆盖旧验证不消费新授权、旧异步 attempt 不清新 generation;Runner registry 单独 running、失败 / 相同 / 更低 revision 均不能触发用户预览或重复刷新,停止后顶部显示“预览未启动”。独立包退出时必须通过 `runner.shutdown_for_client_exit` 先进入 draining 再结束本 boot,保留 durable sidecar 供下次 reconciliation,不把中断任务写成 completed;Windows Runner 必须 `CREATE_SUSPENDED -> AssignProcessToJobObject -> ResumeThread`,分配或恢复失败时 kill + wait,客户端持有 kill-on-close Job 兜底,关闭主窗口后 Runner、MCP、command、ConPTY 及其后代都应消失。普通 dev / release 和 CLI 继续使用 `runner.shutdown_if_idle`。
Windows release 的非交互后台命令统一使用 `CREATE_NO_WINDOW`,包括 `command.exec / project.verify`、STDIO MCP、Repository Context Git、`git.inspect / project.git_commit` 和 `taskkill` 清理命令;需要进程组终止时再叠加 `CREATE_NEW_PROCESS_GROUP`,不要使用 `DETACHED_PROCESS`。smoke 时应在实际任务运行期间观察无额外控制台窗口,并在关闭客户端后核对整棵后台进程树为零,再重启确认 reconciliation 可继续。
Provider 失败回归必须同时检查等待态和耗尽态:用本地 mock 503 证明 Runtime 从 durable retry record 显示精确 HTTP 状态、真实 `nextAttempt/maxRetries` 和退避秒数;最后一次重试仍失败时,状态卡与持久 conversation 只显示安全中文摘要。测试正文应包含诱饵 Provider URL/query、API Key 和 Windows / Unix 绝对路径,并断言这些正文、内部 fingerprint / chars 与 `[redacted ...]` 占位符均未进入用户可见消息;不能只验证状态卡而漏掉 `SupervisorChatOnlyView` 直接渲染的 conversation。
Windows 安装包还必须覆盖 AppData 与诊断失败路径:新建目录的 owner 必须等于进程 `TokenUser` SID 且 DACL 仅允许当前用户;历史 foreign-owner 目录应先拒绝任何 reparse / junction / symlink,再原子重命名为同级唯一 `.owner-mismatch-backup-*` 并重建安全目录,旧配置不得覆盖。Windows 新建 Runner lock、endpoint temp、project-owner diagnostic temp 与 real-E2E 私有文件的 owner 可能仍是 token 默认 owner `Administrators`;只允许本进程 `create_new` 后仍持有不共享独占句柄、且句柄确认普通 / 非 reparse / 单链接的对象在写入或原子安装前初始化为 `TokenUser`,失败时清理该新文件。既有 durable 文件读取、活锁、access denied、硬链接或非固定 lock 路径不得删除、接管或截断。`startup.log` 与 `agent-runner.log` 达到 256 KiB 时只保留一份 `.previous.log`,并扫描 API Key、Authorization、AppData 和其它绝对路径零泄漏;AppData 不可写时 `startup.log` 应回退系统 TEMP 的 `Genarrative-Game-Chat-Diagnostics`,故意注入 `.setup()` / `.build()` 初始化失败时必须出现带诊断日志位置的 Windows 对话框;`.setup()` 发生在 `app.run` 阶段,错误对话框必须由 setup 失败路径直接触发,不能只处理 `.build()` 返回值。Runner 子进程已退出时父进程应立即报告,不得继续等待完整启动期限。
开发侧需要无 UI 验收某个单 Agent 的完整 Runtime 时使用:
```bash