新增Direct回合跨页面生命周期规范并固定快照失败重试3次
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 5m13s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 5m19s
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 5m33s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 5m45s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m33s
Project CI / AI game creator shell Rust crates (push) Successful in 2m57s
Project CI / Frontend tests (push) Successful in 4m7s
Project CI / Repository checks (push) Successful in 3m15s
Project CI / Native shell tests (push) Successful in 6m49s
Project CI / Backend tests (push) Successful in 7m55s
Project CI / AI game creator shell web tests (push) Successful in 2m52s

新增《Direct回合跨页面生命周期与运行中项目可见性》里程碑与实施计划,约定离开项目页面不终止回合、重新进入需恢复忙碌态与进度并以快照 sequence 续接
主规范补充 Direct 回合跨页面行为合同、左上角运行中项目面板契约与验收标准
读取活动回合快照失败改为最多重试 3 次,3 次全部失败才向用户告知失败原因,且不得改写成业务、权限或审批结论
This commit is contained in:
2026-09-15 15:54:16 +08:00
parent d9151219ab
commit 3dfb8056d0
3 changed files with 135 additions and 0 deletions
@@ -1379,3 +1379,52 @@ DirectProject 使用 `approvalPolicy=never`,避免每次原生调用再经过
## 2026-09-14 新游戏策划到真实美术接入的连续交付
DirectProject 在收到完整游戏策划或游戏制作请求后,必须把视觉素材作为同一交付链路处理:先读取当前项目已登记资源;策划案包含角色、对象、背景、特效、界面或其它视觉实体且现有资源不满足时,Codex 必须在同一游戏实现任务中调用审核的 `agc_tools` 生图或编辑工具,读取返回的资源身份与相对路径,把真实产物接入游戏源码,再构建并验证实际渲染。生成了素材但源码仍使用 emoji、CSS 形状或临时占位图替代策划要求的视觉元素,不能报告游戏完成。只有策划明确不需要视觉素材,或现有已登记素材完全满足需求时,才允许跳过生图;图片生成、处理、登记和接入不因用户没有重复输入“生图”而降级为可选建议。
## 2026-09-15 Direct 回合跨页面生命周期与运行中项目可见性
DirectProject 的陶泥儿智能创作回合属于**项目**,不属于页面。离开项目界面(切到首页或其它项目)不终止在跑的回合:回合继续持有身份锁、继续调用 Provider 与工具、继续写入项目。因此"界面里看不到进度"不等于"回合结束",更不等于"权限被拒绝"。壳层必须让这条事实对用户可见、可续接、可等待。
### 目标
- 重新进入同一个项目时,前端必须得知"该项目有一轮 Direct 回合仍在跑",恢复"正在处理"状态与最近一次进度,并阻止发起第二条付费回合。
- 壳层左上角提供"正在运行的项目"面板:列出当前确有在跑 Direct 回合的项目(显示名 + 状态 + 已运行时长),可点击进入对应项目。
- 流经 `projectRuntimeVisibleError` 的真实错误不得被投影成与真相无关的说明:回合仍在运行不能被说成权限/审批问题;项目写锁 ACL 拒绝不能被说成审批配置;写锁争用不能被吞成无信息的通用失败。
### 非目标
- 本轮不新增取消入口:离开页面即取消的语义不在范围内。
- 不改变 Direct 回合的身份锁排他性、项目写锁语义、计费与幂等身份。
- 不引入跨进程或持久化的回合账本:面板与重连都只基于当前 GUI 进程内的活动回合注册表;应用退出后不恢复"正在运行"显示。
- 不新增跨端契约:新命令是 Tauri 本地命令,不进 `packages/shared` / `shared-contracts` / OpenAPI。
### 参与入口、状态与跨模块边界
- 回合身份由 Rust 的 Direct 回合身份锁持有,注册表键是 canonicalize 后的项目根;一个项目同时最多一条 Direct 回合。
- 回合进度的事实源是 Direct 回合更新事件发射器(status / activity / sequence / updatedAt)。同一次发射必须同时投影到活动回合注册表,面板与重连读的是这份投影,不允许前端各自维护第二份"谁在跑"的真相。
- 只读快照经单一命令下发给前端;前端只做表现与临时 UI 状态,不据此写业务状态、不据此改项目文件。
- 终态(completed / failed)后回合离开注册表,面板对应行随之消失;本特性不提供历史运行记录。
### 行为合同
1. 活动回合快照字段固定为:`projectPath``projectName``turnId``status``accepted` / `running` / `streaming` / `finalizing` / `completed` / `failed`)、`activity`(可空)、`startedAt``updatedAt``sequence`,全部为毫秒级时间戳或稳定标识。`projectName` 在回合进入时从项目清单读取一次,读不到或为空时回退为项目目录名,读取失败不得阻断回合。
2. 重新进入项目:快照命中该项目时,前端必须恢复"正在处理"状态与最近一次进度文案;必须以该回合的 `sequence` 作为事件续接基线,使后续进度继续生效;回合结束前不允许发起第二条 Direct 回合;回合结束不得重复追加助手消息(沿用既有回合幂等身份)。
3. 快照未命中:按"当前没有在跑的回合"处理。读取失败按下面的重试合同处理,两者都不得阻断发送、不得清空既有状态、不得把查询失败显示成业务失败。
4. 同一项目并发第二条回合仍由身份锁拒绝,前端按稳定前缀 `direct-codex-turn-already-running:` 收口为"仍在处理这个项目的上一条需求,请稍候"。
5. 面板按 `startedAt` 升序展示,显示名直接用快照的 `projectName`(不在面板里另发起清单读取);空列表时不渲染面板外壳,不留空白占位。
6. 面板与重连都不得展示内部诊断(Provider 指纹、token、绝对路径以外的内部细节按既有项目路径展示口径处理)。
### 失败与边界
- 读取活动回合快照(含面板刷新)遇到错误时**最多重试 3 次**:同一查询、有界间隔,期间任意一次成功即按成功处理,不向用户显示失败;**3 次全部失败后**才把失败原因告诉用户。失败文案只说明"读取正在运行的项目失败",不得改写成业务失败、权限或审批结论,也不得据此判定"没有在跑的回合"。重试次数固定为 3,不得无限重试、不得并发放大请求。
- 回合在进行中时项目被删除或改名:面板行按快照里的项目路径展示,点击后按既有打开项目失败口径处理,不在面板内发明新文案。
- 同一 GUI 进程里不同项目的回合互不影响;身份锁的跨进程排他语义不变。
### 验收标准与证据
- Rust 定向用例覆盖:进入后可从快照读到自己的项目与回合身份;进度更新反映 `status`/`activity`/`sequence`/`updatedAt`;终态后离开快照;多项目并存互不覆盖;既有身份锁排他与残留回收用例不变。
- 前端模型层用例覆盖:`direct-codex-turn-already-running:` 与历史同义中文正文都归一到"仍在处理",真正的 `项目权限策略拒绝执行:<command>` 仍保留审批提示。
- 前端 App 级用例覆盖:重新进入有在跑回合的项目后处于忙碌态且无法提交第二条回合;回合结束后恢复可发送;无在跑回合的项目不受影响。
- 面板用例覆盖:排序、显示名回退、空态不渲染、点击进入项目。
- 重试用例覆盖:前两次失败、第三次成功时不产生用户可见失败;连续 3 次失败后出现一次带失败原因的提示,且不阻断发送、不清空既有状态。
- 门禁:AGC typecheck、`appSurface` 全量、模型层定向 vitest、Rust 壳定向 `cargo test``npm run check:encoding``git diff --check`
- 真实 Provider 长回合与真实跨项目并发的运行时证据若未取得,必须在交付记录里显式列为未验证项。