Compare commits

...

86 Commits

Author SHA1 Message Date
lhk229 e69865a3b5 修复回归
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 7m15s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 7m22s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 7m22s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 7m45s
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
2026-09-19 00:09:13 +08:00
lhk229 43b7396909 修复资源界面测试并清理退役策划残留
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 5m57s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 5m26s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m10s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 5m21s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m15s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m32s
Project CI / Backend tests (pull_request) Successful in 9m36s
Project CI / Repository checks (pull_request) Successful in 9m13s
Project CI / Frontend tests (pull_request) Successful in 9m42s
Project CI / Native shell tests (pull_request) Successful in 11m55s
Project CI / AI game creator shell web tests (pull_request) Successful in 7m59s
更新资源卡片断言与 Lexical 提示词输入,恢复生成任务异步状态及轮询收尾验证。
删除旧策划别名和不可达错误映射,更新阶段审批注释。
保留旧项目无报错新开 Design 会话并继续的行为。
资源界面修复后完整界面测试 448 通过、17 跳过;审查清理后 Runtime 模型 27 项及 Design Agent 4 项测试通过,类型和配置检查通过。
2026-09-18 11:46:34 +00:00
lhk229 8909b18a15 恢复合并中被回退的 Direct 前端架构
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
恢复主分支的线程事件消费、聊天投影、历史锚点与分页模块。
恢复过程折叠、工具卡片计时以及对应测试和测试桩。
保留策划 V1/V2 退役清理及 Design Agent 总控面板修复。
修正 Direct 验证文档中的测试入口。
验证通过:60 个 Direct 单元测试、69 个相关界面测试、4 个 Design Agent 测试及静态检查。
完整界面测试仍有 8 个资源 UI 测试失败,涉及旧卡片断言和提示词输入方式,本次未修改。
2026-09-18 11:30:56 +00:00
lhk229 5a712910b7 移除策划页面多余的总控状态面板
Design Agent 激活时不再渲染旧总控运行状态面板。
在现有策划会话测试中补充总控状态面板不显示的断言。
2026-09-18 11:22:00 +00:00
lhk229 90b707727c 修正合并后残留的 Direct 旧命令调用
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 7m16s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 7m22s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 7m41s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 7m42s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m57s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m5s
Project CI / Repository checks (pull_request) Failing after 5m23s
Project CI / Frontend tests (pull_request) Failing after 6m37s
Project CI / Native shell tests (pull_request) Successful in 9m25s
Project CI / Backend tests (pull_request) Successful in 9m38s
Project CI / AI game creator shell web tests (pull_request) Failing after 5m23s
删除前端对已移除 Direct 命令的回读

更新回合流类型注释
2026-09-18 09:44:50 +00:00
lhk229 4efaec42ea 清理退役策划测试并更新现状文档
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 6m1s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 6m30s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 6m1s
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
删除旧 hydrate 命令的无效测试桩

将策划 V1/V2 技术方案和共享记忆标记为历史

明确当前策划入口统一使用 Design Agent
2026-09-18 09:00:08 +00:00
lhk229 945b3efa6f 合并最新主分支变更
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
合入 origin/master 的 Direct、资源画布、工具展示和运行时更新
保留策划 Agent V1/V2 退役删除结果
冲突文件继续采用当前分支的策划退役边界
2026-09-18 08:32:03 +00:00
lhk229 bd40ca45f1 合并最新主分支并保留策划退役清理
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
合入 origin/master 的现役 Direct、Mac 随包资源、配置和测试变更
保留策划 Agent V1/V2 退役删除结果
仅在重叠文件保留当前分支的策划解耦代码
不额外处理 master 自身已有缺陷
2026-09-18 08:04:10 +00:00
suzmii 9a21690fe9 Merge pull request '修复 AGC 画布生成、卡片展示与布局交互' (#412) from feat/agc-canvas-acceptance into master
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 5m52s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 5m56s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 4m29s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 5m8s
Project CI / AI game creator shell Rust smoke (push) Successful in 2m7s
Project CI / AI game creator shell Rust crates (push) Successful in 2m27s
Project CI / Frontend tests (push) Successful in 8m33s
Project CI / Repository checks (push) Successful in 10m19s
Project CI / AI game creator shell web tests (push) Successful in 6m51s
Project CI / Backend tests (push) Successful in 18m39s
Project CI / Native shell tests (push) Successful in 20m53s
2026-09-18 15:50:44 +08:00
suzmii deff6319e2 合并主线项目创建目录选择更新
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 6m53s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 6m31s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 7m12s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m5s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m54s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m12s
Project CI / Backend tests (pull_request) Successful in 9m37s
Project CI / Native shell tests (pull_request) Successful in 12m21s
Project CI / Repository checks (pull_request) Successful in 11m10s
Project CI / AI game creator shell web tests (pull_request) Successful in 12m51s
Project CI / Frontend tests (pull_request) Successful in 23m14s
合入 master ee33af7b7 的项目目录选择与模板建项说明。
保留本批画布和对话修复,自动合并无冲突,类型检查通过。
2026-09-18 15:48:10 +08:00
suzmii 2257a78d6b 收口思考等待反馈与紧凑过程样式及失败状态
思考展开时隐藏重复预览并使用灯泡图标,首个响应前显示临时思考提示。
统一分钟内小数和分钟以上整数秒,保持内外过程的紧凑间距与正文层级。
失败工具与分组显示错误色,非零退出码不再误判为成功。
补齐状态、格式、样式和交互回归,本批其余需求留待后续PR。
2026-09-18 15:46:30 +08:00
suzmii a0f6b7c67d 统一思考与执行过程折叠样式及中文耗时
思考展开复用安全Markdown渲染,折叠显示浅色单行纯文本预览与右侧箭头。
共享过程摘要组件,执行过程按真实操作数显示统计并保留各组独立计时。
工具、整轮、生成任务和策划耗时统一为中文时分秒格式。
补齐格式与Markdown回归、更新已有界面断言并验证窄屏键盘操作。
2026-09-18 14:34:10 +08:00
suzmii 21b059bd41 修正工具组独立计时并移除重复整轮耗时
每个工具组只计算自身调用跨度,已完成组立即停止增长与进行中标记。
整轮总耗时仅在回合状态或完成小结显示一次,单工具仍按百毫秒动态更新。
补齐前组已完成后组运行、边界缺失与倒序的回归及浏览器证据。
2026-09-18 13:45:27 +08:00
suzmii 2d90b73b94 合并主线Mac运行资源与发布门禁更新
合入 origin/master b137f1759,保留画布验收与计时返修。
同步主线0.1.67版本及Mac随包资源、插件能力和发布目标检查。
合并双方排障说明,不提交个人依赖锁文件改动。
2026-09-18 13:27:28 +08:00
suzmii cd8f480719 修复生成草稿隔离与回合计时恢复及布局排队
按占位身份隔离生成面板并保存草稿,阻止改变失败请求输入后伪装重试。
保留用户真实发送时间,按既有用户条目身份恢复空运行态回合的终态边界。
修复跨栏目整理队列覆盖及多选拖动预览起点漂移。
补齐六项 review 发现的回归、原生绑定、交叉审查及浏览器验收记录。
2026-09-18 13:25:18 +08:00
suzmii 2ffccb844c 修复对话动态计时与初始消息重复并补齐游戏居中指引
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 5m51s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 5m45s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 5m31s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m3s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m4s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m38s
Project CI / Repository checks (pull_request) Successful in 5m39s
Project CI / Frontend tests (pull_request) Successful in 7m45s
Project CI / Backend tests (pull_request) Successful in 10m3s
Project CI / Native shell tests (pull_request) Successful in 8m54s
Project CI / AI game creator shell web tests (pull_request) Failing after 5m31s
区分整轮总耗时与工具实际阶段时间,以百毫秒刷新一位小数并冻结终态。
修复正式与乐观用户消息到达时初始占位重复,保留真实同文多次发送。
在开发 Agent 系统提示与 Skill 明确禁止 Phaser 和 CSS 双重居中。
补齐原生事件、前端回归与验收文档,保留未完成项和远程 CI 风险。
2026-09-18 12:17:28 +08:00
suzmii 1bd153d7f2 合并主线对话状态与抠图背景色更新
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 4m56s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 6m9s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 5m28s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m33s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m23s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m39s
Project CI / Repository checks (pull_request) Successful in 4m50s
Project CI / Backend tests (pull_request) Successful in 8m38s
Project CI / Frontend tests (pull_request) Successful in 8m2s
Project CI / AI game creator shell web tests (pull_request) Successful in 8m11s
Project CI / Native shell tests (pull_request) Successful in 15m27s
合入 master a2e6f205d,保留远端功能分支已有合并历史。
融合生成选项的参考素材、目标栏目与抠图背景色字段。
保留主线统一线程状态与重试策略,完成前端及原生定向验证。
2026-09-18 10:31:55 +08:00
lhk229 f5a333b839 Merge branch 'master' into feat/agc-canvas-acceptance
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
2026-09-18 01:04:04 +08:00
suzmii 20b1fd63de 合并最新主线抠图链路与开发监听修复
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 6m44s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 6m55s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 7m3s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m9s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m30s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m41s
Project CI / Native shell tests (pull_request) Successful in 15m5s
Project CI / Repository checks (pull_request) Successful in 16m54s
Project CI / Backend tests (pull_request) Successful in 19m49s
Project CI / Frontend tests (pull_request) Successful in 23m33s
Project CI / AI game creator shell web tests (pull_request) Successful in 11m6s
合入master的抠图账本链路、Vite监听边界及窗口测试更新

保留画布占位参考生成、资源展示与批量标签追加功能

合并态通过137项定向测试、AGC类型检查及Rust全目标编译
2026-09-17 22:18:23 +08:00
lhk229 3de9341a9c 合并最新主分支并保留策划退役清理
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 4m30s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 4m44s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m37s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 5m6s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 5m9s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m26s
Project CI / Native shell tests (pull_request) Successful in 19m40s
Project CI / Frontend tests (pull_request) Successful in 21m8s
Project CI / Repository checks (pull_request) Successful in 21m29s
Project CI / Backend tests (pull_request) Successful in 27m41s
Project CI / AI game creator shell web tests (pull_request) Successful in 19m50s
合并 origin/master 的最新功能与测试变更

保留已删除的策划 Agent V1/V2 运行时和旧 GDD 入口

仅解决资源预览类型冲突,不恢复退役策划调用
2026-09-17 14:10:46 +00:00
suzmii 105591bac5 支持画布与资源面板多选素材批量追加标签
复用标签编辑器并冻结整组选中素材,保留原标签与素材类型

原生批量校验后一次保存,覆盖权限、版本冲突与无变化边界

修复保存输入锁和切项目迟到回包,补齐混合选择入口原因

新增前后端回归并记录本地验证及待真实客户端验收事项
2026-09-17 21:51:59 +08:00
suzmii da44d66dc8 明确多选素材批量追加标签的行为合同
限定追加语义、冻结对象、原子保存与类型保留边界

记录已评审里程碑及前后端并行实现计划
2026-09-17 21:12:42 +08:00
suzmii 0a85c4f87e 合并主线资源菜单和引擎预览功能
合入PR410的常用操作收纳与卡片信息类型入口

保留本分支资源名称、文档图标、占位生成与批量移动能力

整合引擎结构摘要与当前图集测试契约
2026-09-17 21:06:15 +08:00
suzmii efce7b102f 对齐主线图集契约与窗口同步测试要求
补齐图集切分声明与工具目录字段边界断言

更新原生HTTP权限守卫及稳定空快照发布次数期望

修正末尾空行并记录CI排查证据,保留待远程验证状态
2026-09-17 21:01:26 +08:00
suzmii db5edc948c 合并最新主分支并修复画布静态检查问题
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 7m19s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 7m30s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 7m28s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 7m41s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m11s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m10s
Project CI / Native shell tests (pull_request) Failing after 4m28s
Project CI / Frontend tests (pull_request) Failing after 5m12s
Project CI / Backend tests (pull_request) Successful in 7m17s
Project CI / Repository checks (pull_request) Failing after 5m43s
Project CI / AI game creator shell web tests (pull_request) Failing after 4m34s
合入master的更新摘要、策划运行边界及图集契约调整

保留画布生成引用占位、资源卡展示与批量布局功能

修正导入顺序、未使用项和稳定回调依赖
2026-09-17 20:15:38 +08:00
suzmii 45c3780bf5 记录画布验收修复的验证证据与待验边界
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
登记自动化回归和独立评审结论

保留真实客户端与付费生成待验项及远程写入确认边界
2026-09-17 19:46:49 +08:00
suzmii 6fcf42e4ac 修 appSurface 生成任务用例的异步排空:等阶段合并、等轮询退出
- 阶段文案与徽标改用 waitFor:本地队列的「排队中。」先于后端记录合并,同步断言在整套连跑时抢跑
- 用例收尾连等两个 poll 周期(2s)并断言账本读计数不再增长,确认这条轮询链在本用例内退出
- 留在线上的轮询醒来会打进下一个用例的 spy(宿主按调用时读 __TAURI__),故排空放在用例内,未动全局 harness
- 未改生产:后台任务跨面板保活保持原样
2026-09-17 19:44:48 +08:00
suzmii e0f9f811b7 生成浮层居中定位与画布安全带高度
补回 transform translateX(-50%):锚点给的是占位卡中心,少了它浮层整体右偏半个面板宽
高度只按画布安全带分配:装得下时挂在卡下面,装不下时与卡顶边对齐盖住占位,不再压成一百多像素
reveal 的面板高度按当前缩放从屏幕 px 折回世界坐标,占位与浮层并集参与可见性
浮层宽度并入可见性并集,靠边卡片不再把浮层切掉一半
新增真实矩形模拟用例(画布高 568)核对浮层高度与落点不越出安全带
2026-09-17 19:35:41 +08:00
suzmii 03b5c1c9f4 补画布生成入口宿主生命周期验收:占位提交、同 operation 重试与成功落点
- 新增测试文件 resourceCanvasGenerationHostLifecycle.test.tsx,渲染真实 ProjectDevelopmentView
- 覆盖音频入口:点工具出占位、提交后占位进入 submitted(后台仍在跑时的中间态)
- 覆盖失败后原请求重试:复用同一 operationId 与幂等键,不会变成新的付费生成
- 覆盖成功后落点:结果卡按占位位置落盘(手动接管),占位随之被撤掉
- 原生命令全部走假实现,不触发任何真实 Provider 调用
2026-09-17 19:20:31 +08:00
suzmii 58992330aa 生成浮层面板 chrome 与画布安全高度修复
浮层复用模态的面板类:边框圆角底色内边距与 header 排布不再缺失
高度上界按真实画布可用底边算(画布高减退底栏安全区与顶边),空间紧时收紧并内部滚动
提交动作行固定在浮层底部,避免长表单把提交按钮顶到底栏下面
新增浮层高度模型测试、结构 CSS 钉子与浮层 chrome 断言
新增宿主级整合用例:图片按正式归类落点并用占位最新位置、音频失败保留与幂等重试
2026-09-17 19:08:34 +08:00
suzmii 2c687b01a4 补齐生成结果分类与占位交互验收合同
明确原生目标分类、音频幂等及画布浮层可见性
2026-09-17 19:08:34 +08:00
suzmii c0e377f479 测试助手同时支持纯文本与引用输入区
appSurface 图集/图标规范入口的提示词仍是 textarea,helper 不能只走 Lexical 编辑器 API
两种字段分别用原生 change 与编辑器 update,读回同样两种口径
补 targetCategory 随任务保存与恢复的断言
2026-09-17 19:01:35 +08:00
suzmii 6001b87215 画布生成按入口栏目落盘目标分类
GUI 生成命令新增可选 targetCategory:generate_local_project_asset 与 start_local_project_asset_generation 经 options 传入完成登记
PlatformArtAssetGenerationOptions 增加 target_category,Agent 与 Direct 路径保持 None,仍按 kind 派生默认分类
新建条目与同 kind 重登记都按显式目标分类写入 manifest 既有 category 字段,不新增字段、不改数据结构
目标分类只接受 GameCreationAppAssetCategory 的六个合法值,version 与 all 等栏目伪值在提交前失败关闭
target_category 刻意不进 standalone 指纹与 durable 请求快照,分类只影响本地 manifest 落点,避免在途账本换槽重复 POST,同任务幂等恢复由调用方继续用同一栏目提交
补用例:kind=image 带 targetCategory=character 落到 character 而不是 unclassified、非法栏目值不产生生成请求、登记入口的显式分类与不传时的原 kind 派生行为
2026-09-17 18:58:53 +08:00
suzmii b08ab6ee66 生成占位可见性、落点与音频提交身份修复
打开生成浮层时把占位与浮层整块带进安全区(避开顶栏底栏),只做最小视口平移不改缩放
落点意图改为按草稿 ID 的 Map,避免并发完成互相覆盖;坐标在落点时刻取占位最新位置
落点 section 改用资源正式归类后的 category,修复图片落待归类、规范落文档时静默跳过
音频与背景音乐提交绑定占位与 operationId:在途时拒绝再次提交,失败保留输入并可同 operation 重试
宿主记录收起浮层时的草稿与音频提交身份,重开占位接着编辑而不是回到空表单
生成任务新增入口栏目 targetCategory 走原生可选入参,前端不据此伪分类
补可见性平移的定向测试
2026-09-17 18:50:29 +08:00
suzmii 7f80012d7f 清理占位重开状态里不再读取的动作 ID
生成浮层的草稿、错误与占位归属统一按 draftId 判等,动作 ID 已无读取方,删掉避免留下死状态
2026-09-17 18:50:29 +08:00
suzmii fbe95591d5 校准布局撤销作用域的行为说明
明确切模式后新操作会替换旧撤销栈但不会跨写布局
2026-09-17 18:31:16 +08:00
suzmii d222aad2ec 参考素材改为提交前预检并补参考链路用例
参考解析前增加纯本地预检:清单归属、受控路径与文件、媒体类型、可解码位图全部通过后才允许产生任何上传副作用,避免第一张参考已上传、第二张坏图才失败
明确拒绝 SVG 等矢量参考,媒体类型或文件扩展名任一命中即拒,本次不做矢量转换,坏图同样在本地失败关闭
asset.upload 门禁提前到预检阶段,显式拒绝该命令的项目连第一个上传凭证都不会签发
预检与实际上传共用同一份本地判据 helper,不新建平行流程,上传侧仍按同一判据重新读取与解码
补参考合同与恢复的账本用例:icon-spec 带用户参考、game-background 规范图加用户参考、图集超限、空白引用写入失败
补提交侧用例:拒绝路径、未登记、非图片、缺失文件、超限、SVG 与坏图,并断言零上传凭证与零生成 POST,反向验证同一张合格参考单独提交确实会签发凭证
补 asset.upload 拒绝用例,以及清单校验与 Direct 身份校验接受用户参考、拒绝用户参考顶替规范引用的覆盖
2026-09-17 18:28:19 +08:00
suzmii 13b28ebbc7 生成占位与卡下独立浮层,修复引用选择被焦点陷阱阻断
工具点击先在当前栏目创建临时占位卡,生成浮层挂在占位下沿;图片、音效、背景音乐入口一致
占位按项目与草稿 ID 归属宿主临时状态:可拖动、提交绑定任务 ID、成功结果落到占位最新位置
删除占位只隐藏展示,关闭浮层不冒充取消后台任务;失败保留占位与输入引用供重试
生成面板改为非模态浮层:ThemedModal 焦点陷阱曾阻断 portal 到 body 的引用选择器,点选不生效
引用选择器定位加顶边钳制,搜索收窄与键盘选择可用;不再越出视口
参考候选与陈旧引用校验排除 SVG(原生解码不支持),其余 image 类型不额外收窄
任务创建处对参考资产 ID 去重;补浮层真实组件整合、占位模型与拖动、参考模型回归测试
2026-09-17 18:22:39 +08:00
suzmii 30648e6b93 画布修复:重算意图各占队列槽、撤销不跨排序模式、整理判据与落盘同源
- 显式整理与「关系图首次就绪」各占一个队列槽,系统重算不再改写用户已按下的那笔整理
- 资源签名同步覆盖排队中的每一笔资源意图,先落盘的那笔不会把后一笔留成过期签名
- 撤销栈按「项目 + 排序模式」隔离:切模式后不会把另一份 sidecar 的坐标写过去
- 整理的「有没有变化」判据与落盘同源,目标栏目还有在途/排队手动落点时也算一次真实变化
- 删除本次改动退役且已无调用方的 resourceBookAllBandLocalPoint 与布局 dragX/dragY
- 补回归:排队中整理不被覆盖、切模式撤销不跨写、在途拖动后整理照常生效、分类变更后拖动按新栏目落盘
2026-09-17 18:18:32 +08:00
suzmii 9dd1052374 明确参考图片格式与上传前整组校验边界
排除不可解码SVG参考并约束上传权限与账号归属判据
2026-09-17 18:18:32 +08:00
suzmii aec9568c39 接通画布生成参考素材的原生链路
新增 referenceAssetIds 原生入参:start_local_project_asset_generation 与 generate_local_project_asset 经 prepare_local_project_asset_generation 统一收口当前项目 manifest 图片素材 id
PlatformArtAssetGenerationOptions 增加 reference_asset_ids,GUI、agent 桥、media 观察与 Direct 运行时构造点显式传空
参考解析固定规范图前置在前、用户参考按给出顺序随后,按远端资源 ID 去重,普通生成总量 5 张、有规范前置 4 张用户参考,图集拒绝额外参考而非静默丢弃
参考素材复用 manifest 到本地文件、图片解码、内容 hash、当前账号 binding 上传的既有通道,历史账号遗留远端 ID 不再复用
retained 阶段与清单校验改为与提交同一套请求合同:icon-spec、ui-prototype、game-background 允许正确引用,art-spritesheet 仍只接受唯一规范引用
修复 Part::file_name 的生命周期错误与 4 处测试构造点少传参考参数
2026-09-17 17:57:53 +08:00
suzmii 0a1f0e0b26 画布布局收口:整理只动当前栏目、多选拖动一笔提交与一次撤销
- 整理画布重排目标栏目内全部素材(含手动坐标与被筛选隐藏的卡),「所有资源」页覆盖全部栏目
- 栏外坐标逐值保留:不再把其他栏目的自动坐标丢给重算,避免被顺带规整成规范槽位
- 手动标记纳入历史快照与相等判定,撤销整理恢复原坐标与原手动标记
- 新增批量坐标写入入口:多选拖动与撤销都只排一笔 CAS、只压一条历史
- 多选拖动按同一位移整批跟随,取消 / 捕获丢失 / 失焦回滚,切项目丢弃进行中的位移
- 补测试:栏外自动坐标保留、all 页整理范围、批量撤销与取消边界
2026-09-17 17:47:11 +08:00
suzmii 5c31ae91ca 返修资源卡完整名悬停入口并收短文档卡注释
- 完整资源名改挂在覆盖整卡、真正命中指针的选中按钮 title 上,名称条自身不再挂悬停不到的 title

- 无障碍名保持原有 aria-label 不变,长名仍是 CSS 单行省略

- 断言改为校验选中按钮 title,并钉住名称条不挂 title

- 文档卡分支注释只写当前行为,去掉旧实现说明
2026-09-17 17:37:48 +08:00
suzmii 3ba6168c6a 同步资源卡名称与画布布局交互产品合同
统一卡面名称和文档图标展示要求

明确当前栏目整理与多选移动的撤销边界
2026-09-17 17:15:38 +08:00
suzmii 2628b83d4b 画布资源卡统一显示正式资源名并简化文档卡卡面
- 资源卡新增卡面名称条,所有类型卡统一显示正式资源 label,长名单行省略、完整名进 title

- 文档卡卡面改为居中图标,不再把正文前几行铺在卡面上,正文只在独立详情浮层读取

- 删除卡面正文摘要的取文本 helper 与行数/长度常量,移除对应 CSS 规则不留墓碑

- 名称条按媒体卡让出右下播放钮位置,替换血缘角标上移避免遮住名称

- 新增资源卡名称与文档卡卡面用例,并同步重命名链路与卡面正文的既有断言
2026-09-17 17:08:42 +08:00
suzmii a7b2b0e23b 画布图片生成支持真实参考图引用
新增参考图模型:候选为当前项目已登记图片,用户参考上限普通生成 5 张、带规范前置 4 张、图集为 0
生成浮层复用资源引用输入组件,提示词里的 @ 引用直接产出当前 manifest 资产 ID 作为参考
生成任务与队列新增 referenceAssetIds,派发时以 referenceAssetIds 交给原生侧解析账号绑定
图集入口不呈现参考选择器,超限在提交前给出原因并挡住提交,不做静默截断
补充参考模型、面板接线与队列派发的定向测试
2026-09-17 16:59:49 +08:00
suzmii ef982fdb78 拆分原生引用与前端生成并行实现边界
使用独立工作树处理原生引用,固定引用资产ID接缝
2026-09-17 16:59:48 +08:00
suzmii 91b65f94ca 确保工作树测试读取本地共享组件源码
补齐共享包测试别名以避免复用依赖指向其他工作树

记录工作树依赖复用的解析检查要求
2026-09-17 16:18:17 +08:00
suzmii 70513cf049 按规范评审固定参考上限并放行实现
普通生成最多五张参考,图集拒绝额外参考

复用现有引用快照并核验恢复校验,明确里程碑验收边界
2026-09-17 16:09:14 +08:00
suzmii 87aed0b765 补齐画布任务身份与引用持久化边界
明确参考图片入参、账号绑定与恢复校验

固定栏目整理撤销、多选范围与素材名称来源
2026-09-17 16:06:57 +08:00
suzmii 733a7015af 明确画布验收修复范围与行为合同
统一生成占位与参考、资源卡展示和布局交互的验收要求

补充单里程碑并行实现计划和独立评审门禁
2026-09-17 16:02:37 +08:00
lhk229 3e3b35713d 合并最新主分支并清理新增策划耦合
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
合入 master 的聊天界面、回合控制及运行时更新
解决七处合并冲突,保持退役策划 V1/V2 链路删除
将新增界面判断连接到 Design Agent 状态并移除旧 GDD 测试依赖
保留现役文档建造指令、回合终止及推理档设置
2026-09-17 02:37:48 +00:00
lhk229 ea34cbdea6 合并远程分支并解决提交历史分叉
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 5m44s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 5m21s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 5m21s
Project CI / Backend tests (pull_request) Failing after 10s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Failing after 5m47s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m50s
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
合并 origin/rm/design-v2 的 master 合并记录
保留本地已合入的 master 更新及策划 Agent 清理成果
合并前后文件树一致,仅统一双方提交历史
2026-09-17 02:29:46 +00:00
lhk229 f957a545bf Merge remote-tracking branch 'origin/master' into rm/design-v2 2026-09-15 15:52:12 +00:00
lhk229 c2064836ce Merge branch 'master' into rm/design-v2
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
2026-09-15 20:59:09 +08:00
lhk229 8e6fb7d078 更新退役GDD样式测试
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 4m31s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 4m35s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m58s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 5m2s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m5s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m15s
Project CI / Frontend tests (pull_request) Successful in 4m35s
Project CI / Repository checks (pull_request) Successful in 4m3s
Project CI / Native shell tests (pull_request) Successful in 7m5s
Project CI / Backend tests (pull_request) Successful in 8m2s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m12s
删除对已移除 GDD 审批弹层选择器的旧断言

保留现役窗口覆盖层样式校验
2026-09-15 08:56:16 +00:00
lhk229 94bd7310a9 更新 Design Agent 运行时说明
移除随包提示词中的旧 project-planning 部署描述

改为当前 Design Agent Runtime 的单 Agent 运行口径
2026-09-15 08:15:15 +00:00
lhk229 1d50f4fef5 清理策划样例路径残留
将通用 file.read 证据测试改用中性 design.md 样例

确保现役代码和测试不再引用旧 Fast GDD 路径
2026-09-15 08:12:32 +00:00
lhk229 23bb0bf131 Merge remote-tracking branch 'origin/master' into rm/design-v2
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 4m39s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 4m27s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m35s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 4m56s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 4m18s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m57s
Project CI / Frontend tests (pull_request) Failing after 3m31s
Project CI / Repository checks (pull_request) Failing after 3m25s
Project CI / Native shell tests (pull_request) Successful in 6m48s
Project CI / AI game creator shell web tests (pull_request) Failing after 3m16s
Project CI / Backend tests (pull_request) Successful in 7m26s
2026-09-15 08:09:21 +00:00
lhk229 758ef5ceec 清理旧Fast GDD命名残留
将通用验收证据和委派测试中的旧 GDD 路径改为中性产物

保留做游戏 Agent 的通用证据回执逻辑
2026-09-15 08:07:12 +00:00
lhk229 ea843641e8 清理退役策划提示词入口
删除 Supervisor playbook 中旧 project-planning 委派说明

保留通用协作与回执规则
2026-09-15 08:04:27 +00:00
lhk229 26d31d73e2 清理退役策划注释残留
移除静态委派验收中的旧 plan.submit_gdd 说明

保持通用委派返工判定语义不变
2026-09-15 08:01:36 +00:00
lhk229 2bce007a0a 收口退役策划运行时分流
移除旧策划 source、plan.submit_gdd 专用卡和相关前端提交分支

保留通用 Supervisor 提交与做游戏 DAG 路由

同步临时计划文档的实际删除边界
2026-09-15 07:58:03 +00:00
lhk229 337cb39340 删除退役策划事件测试
移除 planning-session-v2-stream 订阅注销测试

保留通用 Tauri 事件订阅竞态回归覆盖
2026-09-15 07:43:39 +00:00
lhk229 6d4f7a976f 清理旧策划委派语义
删除 project-planning 的澄清与用户修订跳转说明

保留做游戏 Agent 的静态委派返工语义

更新运行时诊断测试中的旧策划身份夹具
2026-09-15 07:41:25 +00:00
lhk229 12092ceb50 删除策划专用文件与GDD命令
移除旧 Fast GDD 打开命令及 Tauri 注册

删除规划目录和 GDD 投影的专用文件保护分支

保留通用 Agent 控制面与 DirectCodex 文件安全边界
2026-09-15 07:27:30 +00:00
lhk229 bcbf398b65 移除退役策划界面样式
删除旧 GDD 审批卡与策划窄条的孤儿 CSS

更新聊天布局测试以覆盖现役 DirectCodex 选择器

保留设计 Agent 和通用项目工作台表现
2026-09-15 07:05:46 +00:00
lhk229 151c61ad08 清理退役策划测试夹具
删除策划 V2 与批准 GDD 的旧测试数据和调用模拟

保留现役设计 Agent 与 DirectCodex 的界面测试

移除测试中对退役规划命令的断言
2026-09-15 07:00:00 +00:00
lhk229 79b49519b6 删除退役GDD交付入口
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
移除已批准 fast GDD 自动转建游戏流程

清理工作台与首页创建控制器中的旧策划回调

保留 DirectCodex 正常做游戏入口
2026-09-15 06:41:41 +00:00
lhk229 ec2180f281 删除策划V2会话状态链路
移除 App 内策划 V2 会话、GDD 同步与审批状态

删除策划 V2 类型转换模块和退役 GDD 状态类型

保留现役设计 Agent 会话恢复与项目运行时入口
2026-09-15 06:38:29 +00:00
lhk229 341080f42d 收紧退役策划与Supervisor清理边界
明确Supervisor产品运行链路已退役

将做游戏和做素材统一收口到DirectCodex

保留16 Agent DAG仅到编译所需范围
2026-09-15 05:49:54 +00:00
lhk229 45401de57e 解耦设计Agent与策划V2状态
为 Design Agent 增加独立 active、瞬态回复和 reasoning 状态

保留策划 V2 会话自身的状态与消息动画链路

统一项目总控轮询使用两条策划 lane 的合并状态

移除 Design Agent 对旧 planning lane ref 的共享依赖
2026-09-15 05:03:38 +00:00
lhk229 908d248f27 Merge remote-tracking branch 'origin/master' into rm/design-v2
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
2026-09-15 04:49:59 +00:00
lhk229 65598b9886 补充退役策划Agent解耦清理计划
新增退役策划 Agent V1/V2 解耦清理里程碑规范

新增分提交实施计划、修改边界与验收命令

明确不主动清理做游戏 Supervisor 与 16 Agent DAG
2026-09-15 04:49:49 +00:00
lhk229 64ab959d4f 移除退役策划 V2 流式事件订阅
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 3m3s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 2m47s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Failing after 2m48s
Project CI / Backend tests (pull_request) Failing after 16s
Project CI / AI game creator shell Rust smoke (pull_request) Failing after 2m2s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Failing after 2m26s
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / AI game creator shell web tests (pull_request) Failing after 1m7s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 3m33s
Project CI / Native shell tests (pull_request) Failing after 3m17s
Project CI / Frontend tests (pull_request) Successful in 3m42s
删除 planning-session-v2-stream 事件监听与旧实时回复错误处理

保留新版 Design Agent 事件订阅链路
2026-09-15 02:42:03 +00:00
lhk229 9833a53e06 Merge remote-tracking branch 'origin/master' into rm/design-v2
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 3m2s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 3m6s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Failing after 3m7s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Failing after 3m10s
Project CI / AI game creator shell Rust smoke (pull_request) Failing after 1m57s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m39s
Project CI / Native shell tests (pull_request) Failing after 3m35s
Project CI / AI game creator shell web tests (pull_request) Failing after 1m6s
Project CI / Repository checks (pull_request) Successful in 2m49s
Project CI / Frontend tests (pull_request) Successful in 4m4s
Project CI / Backend tests (pull_request) Successful in 7m22s
2026-09-15 02:27:25 +00:00
lhk229 0847b1bb83 Merge remote-tracking branch 'origin/rm/design-v2' into rm/design-v2
Project CI / Repository checks (pull_request) Successful in 2m42s
Project CI / Frontend tests (pull_request) Successful in 3m0s
Project CI / Native shell tests (pull_request) Failing after 3m51s
Project CI / Backend tests (pull_request) Successful in 5m46s
2026-09-14 07:23:48 +00:00
lhk229 8f691d4c8c Merge branch 'master' into rm/design-v2
Project CI / Repository checks (pull_request) Failing after 3m20s
Project CI / Frontend tests (pull_request) Failing after 2m42s
Project CI / Native shell tests (pull_request) Failing after 3m57s
Project CI / Backend tests (pull_request) Successful in 6m23s
2026-09-14 15:22:30 +08:00
lhk229 d3b9f326f0 删除孤立的策划 GDD 模型模块
移除已无调用方的 planning_gdd_model.rs 及模块导出

删除仅依赖退役提交错误类型的无效判定函数
2026-09-14 07:20:13 +00:00
lhk229 7eb2326a76 移除退役策划 V2 运行态刷新入口
Project CI / Repository checks (pull_request) Failing after 2m22s
Project CI / Frontend tests (pull_request) Failing after 3m7s
Project CI / Native shell tests (pull_request) Failing after 3m47s
Project CI / Backend tests (pull_request) Successful in 6m38s
删除旧版策划状态随项目总控运行态刷新的专用 effect

移除仅服务该 effect 的 planningLane 判定模块
2026-09-14 06:30:07 +00:00
lhk229 9fc28790a4 移除退役策划 V2 运行面板参数
删除项目总控运行面板中已无调用方的 GDD 审批状态参数
2026-09-14 06:26:54 +00:00
lhk229 cea45a608d 删除退役策划 V2 前端审批面板
移除旧版 GDD 审批卡和策划运行条组件

项目总控视图仅保留新版 Design Agent 与通用运行面板
2026-09-14 06:23:16 +00:00
lhk229 ee03ade156 Merge remote-tracking branch 'origin/master' into rm/design-v2
Project CI / Repository checks (pull_request) Failing after 3m24s
Project CI / Frontend tests (pull_request) Failing after 3m2s
Project CI / Backend tests (pull_request) Successful in 6m55s
Project CI / Native shell tests (pull_request) Failing after 4m20s
2026-09-14 06:19:46 +00:00
lhk229 4933c6c380 删除退役策划 V2 前端测试契约
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
移除 Plan GDD 审批测试套件及注册入口
2026-09-14 06:15:13 +00:00
lhk229 931f3eae0a 删除退役策划 V2 Rust Runtime
移除 Planning V2 协议模块与 Tauri 命令注册

保留新版 Design Agent、做游戏 Agent 与共享运行时
2026-09-14 06:07:20 +00:00
lhk229 c5f8fa1ef6 清理旧策划 V1 残留注释
删除已失效的 --plan 策划自动应答说明
2026-09-14 05:54:24 +00:00
166 changed files with 18032 additions and 10760 deletions
@@ -957,9 +957,6 @@ async function runInteractiveCargo(cliArguments, setActiveChild) {
return result; return result;
} }
// 立项策划跑 standard 档,`agent.delegate` 这类动作按项目权限策略必须逐个确认,
// 而确认和问询都只从 CLI 的 stdin 读。自主构建档没有这一步,所以只有 --plan 需要
// 一个把「人坐在终端前敲 approve」自动化掉的应答器;判据本身仍然走后端确认命令。
const swarmConfirmationPromptPattern = /输入 approve 或 reject$/u; const swarmConfirmationPromptPattern = /输入 approve 或 reject$/u;
const swarmUserInputPromptPattern = /请选择 1-\d+,或直接输入其他答案:$/u; const swarmUserInputPromptPattern = /请选择 1-\d+,或直接输入其他答案:$/u;
@@ -1590,13 +1590,11 @@ if (!viteConfigSource.includes('allow: [repoRoot]')) {
); );
} }
if ( if (!(
!( tauriConfig.build?.beforeDevCommand?.includes(
tauriConfig.build?.beforeDevCommand?.includes( 'run ai-game-creator-shell:dev-server',
'run ai-game-creator-shell:dev-server', ) || tauriConfig.build?.beforeDevCommand?.includes('run agc:serve')
) || tauriConfig.build?.beforeDevCommand?.includes('run agc:serve') )) {
)
) {
throw new Error( throw new Error(
'AI game creator shell beforeDevCommand must start the selected Vite dev server', 'AI game creator shell beforeDevCommand must start the selected Vite dev server',
); );
@@ -1192,7 +1192,7 @@ async function main() {
function isDirectModuleExecution() { function isDirectModuleExecution() {
return Boolean( return Boolean(
process.argv[1] && process.argv[1] &&
resolve(process.argv[1]) === fileURLToPath(import.meta.url), resolve(process.argv[1]) === fileURLToPath(import.meta.url),
); );
} }
File diff suppressed because one or more lines are too long
@@ -2,8 +2,4 @@
需要等待专业 Agent 时不得调用 respond_to_userRuntime 会通过 delegate/all-join 完成屏障保持同一父 run,取得 readyDelegateReceipts 或 readyIsolatedJoins 后直接整合结果。readyDelegateReceipts 中 contractStatus=evidence-ready 只说明终态、产物和验证等客观证据齐全,你仍须按 acceptanceCriteria 判断语义是否满足;needs-repair 不得当作成功。contractStatus=needs-user-input 时,Runtime 会按原 delivery 逐一发起 user.input_request;每个请求答案收齐后,为对应原 delivery 仅创建一次 continuation 委派,repairOfDelegationId 与 continuationOfDelegationId 都指向该原 delivery,并提交 observation 给出的 questionsSha256、answersSha256Runtime 自动派生稳定 continuation identity,禁止跨 delivery 混用指纹。客观或语义不满足时可以发起一次新 agent.delegate,并把 repairOfDelegationId 指向已认领原 delivery;不得对返工再返工或为同一原 delivery 创建第二个返工。专业结果冲突且无法依据用户目标裁决时,合并问题后用一次 user.input_request 询问用户。只有实现路径、产品取舍或缺失事实会实质改变结果时才调用 user.input_request;项目内可读取事实、权限确认和工具失败不得伪装成用户问题。 需要等待专业 Agent 时不得调用 respond_to_userRuntime 会通过 delegate/all-join 完成屏障保持同一父 run,取得 readyDelegateReceipts 或 readyIsolatedJoins 后直接整合结果。readyDelegateReceipts 中 contractStatus=evidence-ready 只说明终态、产物和验证等客观证据齐全,你仍须按 acceptanceCriteria 判断语义是否满足;needs-repair 不得当作成功。contractStatus=needs-user-input 时,Runtime 会按原 delivery 逐一发起 user.input_request;每个请求答案收齐后,为对应原 delivery 仅创建一次 continuation 委派,repairOfDelegationId 与 continuationOfDelegationId 都指向该原 delivery,并提交 observation 给出的 questionsSha256、answersSha256Runtime 自动派生稳定 continuation identity,禁止跨 delivery 混用指纹。客观或语义不满足时可以发起一次新 agent.delegate,并把 repairOfDelegationId 指向已认领原 delivery;不得对返工再返工或为同一原 delivery 创建第二个返工。专业结果冲突且无法依据用户目标裁决时,合并问题后用一次 user.input_request 询问用户。只有实现路径、产品取舍或缺失事实会实质改变结果时才调用 user.input_request;项目内可读取事实、权限确认和工具失败不得伪装成用户问题。
委派 `project-planning` 时,acceptanceCriteria 只写产物形状、覆盖范围与红线(例如必须交付 `game/fast_gdd.md`、必须原创、必须只定义一个 MVP 闭环),**不得替用户预先裁定产品取舍**。用户没有指定的玩法规则、数值、关卡量级、美术方向和目标人群,一律留给策划子 Agent 按其 3 轮问询预算决定是提问还是按默认建议填写;不要写“未指定的标注为立项假设”“自行假设后继续”这类指令,那会把问询预算作废。平台事实(自包含 Web、desktop/mobile 双视口、keyboard/touch 双输入、本地 HTTP 预览)由 Runtime 固定注入,属于已定事实,不得要求标为待定、建议或开放项。
`project-planning` 的澄清 continuation,必须按 A/B/“需要原型验证”三项合同原样转述;B 是用户确认的 `confirmed/user_option`,不能转成默认建议。若用户后续自由填写推翻已确认决定,保留用户答案原文逐字不改写、不拆分、不搬轮次,并在被推翻决定后注明“已被第 N 轮回答推翻,以后者为准”,在新决定 topic 中写明推翻关系。
只在所有必要回执已认领、manifest 正式任务图已经完成、所有必要返工也已认领、项目副作用已验证且没有待确认动作或待回答请求时给用户最终回复。不要向用户暴露内部 task/event、工具计划、动态 child ID 或调试状态。 只在所有必要回执已认领、manifest 正式任务图已经完成、所有必要返工也已认领、项目副作用已验证且没有待确认动作或待回答请求时给用户最终回复。不要向用户暴露内部 task/event、工具计划、动态 child ID 或调试状态。
@@ -14,6 +14,9 @@ Implement the user's actual game request in the current project as an npm-manage
3. Build with the project's npm script before previewing. The playable entry is the package directory's `dist/index.html`; never report an unbuilt bare-module page as playable. Import assets or configure public assets so all runtime media is included in dist; preview and exports cannot read outside it. 3. Build with the project's npm script before previewing. The playable entry is the package directory's `dist/index.html`; never report an unbuilt bare-module page as playable. Import assets or configure public assets so all runtime media is included in dist; preview and exports cannot read outside it.
4. Build a complete playable loop: visible objective, responsive input, meaningful state changes, success or failure feedback, and a reliable restart path where the game needs one. 4. Build a complete playable loop: visible objective, responsive input, meaningful state changes, success or failure feedback, and a reliable restart path where the game needs one.
5. Fit the active game scene to desktop and mobile viewports without accidental page scrollbars. Reserve deliberate safe space for HUD elements instead of covering interactive content. 5. Fit the active game scene to desktop and mobile viewports without accidental page scrollbars. Reserve deliberate safe space for HUD elements instead of covering interactive content.
- **画布居中只能由一处负责。** 使用 `Phaser.Scale.FIT``autoCenter: Phaser.Scale.CENTER_BOTH` 时,canvas 的直接父容器应使用尺寸明确的普通块布局,不再对同一 canvas 叠加 Grid/Flex 居中、`place-items: center`、自动外边距或居中 transform。Phaser 自动计算的 margin 与 CSS 居中叠加会使竖屏画面向右偏移。
- 若决定由 CSS 居中,则显式使用 `autoCenter: Phaser.Scale.NO_CENTER`,由 CSS 独立完成定位;外围页面可以继续使用 Grid/Flex,限制只针对同一 canvas 的重复定位。
- 出现偏移先检查游戏自身的 CSS 与 Phaser scale 配置,不添加 AGC 预览容器固定偏移补偿。修改布局后重新构建 dist,在桌面、移动及窗口 resize 后检查 canvas 相对游戏父容器居中(误差不超过 1 CSS px)、画面完整且无意外滚动条;不能仅凭 build 成功宣称布局通过。
6. Invoke `taonier-art-assets` for every new game brief that needs visual assets. First reuse suitable registered Taonier art; when the brief's required visual elements are missing or unsuitable, call the reviewed `agc_tools` generation/edit workflow in the same task. After the tool returns, wire its relative paths into the game and verify the rendered result. A game with unused generated assets or placeholder emoji/CSS where requested art should appear is not complete. Load media defensively only for genuinely optional effects, and never relabel a local placeholder as platform art. 6. Invoke `taonier-art-assets` for every new game brief that needs visual assets. First reuse suitable registered Taonier art; when the brief's required visual elements are missing or unsuitable, call the reviewed `agc_tools` generation/edit workflow in the same task. After the tool returns, wire its relative paths into the game and verify the rendered result. A game with unused generated assets or placeholder emoji/CSS where requested art should appear is not complete. Load media defensively only for genuinely optional effects, and never relabel a local placeholder as platform art.
7. Let Phaser own the render loop and input dispatch. Avoid duplicate scenes, stale event listeners, and state that survives restart unintentionally. 7. Let Phaser own the render loop and input dispatch. Avoid duplicate scenes, stale event listeners, and state that survives restart unintentionally.
8. After a meaningful game change, use the browser playtest Skill and fix issues shown by real evidence before reporting completion. 8. After a meaningful game change, use the browser playtest Skill and fix issues shown by real evidence before reporting completion.
@@ -7,5 +7,7 @@
- Score, steps, health, timer, or other core state updates consistently. - Score, steps, health, timer, or other core state updates consistently.
- Restart restores all state and does not duplicate timers, animation loops, or event listeners. - Restart restores all state and does not duplicate timers, animation loops, or event listeners.
- Desktop and mobile layouts keep the core scene visible without accidental document scrolling. - Desktop and mobile layouts keep the core scene visible without accidental document scrolling.
- 画布的缩放与居中由 Phaser 或 CSS 中的一方独立负责。`FIT + CENTER_BOTH` 不与同一 canvas 父容器的 Grid/Flex 居中、自动外边距或居中 transform 叠加;使用 CSS 居中时关闭 Phaser 自动居中(`NO_CENTER`)。
- 在构建后的实际页面检查桌面、移动和 resize:比较 canvas 与游戏父容器的中心,预期居中时水平/垂直误差不超过 1 CSS px,并检查画面没有溢出或意外滚动条。偏移先修游戏 CSS/scale 配置,不用修改 AGC 预览位置掩盖。
- HUD and overlays reserve space and do not cover essential interactive content. - HUD and overlays reserve space and do not cover essential interactive content.
- Requested Taonier art is visibly integrated into the core experience when available. - Requested Taonier art is visibly integrated into the core experience when available.
@@ -1,6 +1,6 @@
{ {
"schemaVersion": "agc-skill-pack.v1", "schemaVersion": "agc-skill-pack.v1",
"version": "2026-08-26.24", "version": "2026-08-26.25",
"skills": [ "skills": [
{ {
"name": "agc-game-production-workflow", "name": "agc-game-production-workflow",
@@ -80,7 +80,7 @@
"agents/openai.yaml", "agents/openai.yaml",
"references/game-quality-checklist.md" "references/game-quality-checklist.md"
], ],
"sha256": "05b5cfbf7a40fd303717491f5cea84ff339a73359c9678b283fd54d2b5c45efd" "sha256": "e122d8f3a6d986b594b95c971754d68197bf7896912fa8267d44a7aa129a57ba"
}, },
{ {
"name": "agc-browser-playtest", "name": "agc-browser-playtest",
@@ -797,6 +797,16 @@ fn direct_thread_visible_item(
direct_thread_event_item(root, item) direct_thread_event_item(root, item)
} }
/// AGC 预写的 canonical 用户条目 id`direct-codex:{clientTurnId}:user`。
///
/// 与 `direct_project_history::is_direct_project_codex_user_item` 的判据同一份口径(前缀 +
/// `:user` 后缀)。回合生命周期事件的 `userItemId` 只能来自这里或已落盘条目自身的 id;
/// clientTurnId 缺失时不猜身份,返回 `None` 让前端按"未知归属"处理。
fn direct_codex_user_item_id_for_client_turn_id(client_turn_id: &str) -> Option<String> {
let client_turn_id = client_turn_id.trim();
(!client_turn_id.is_empty()).then(|| format!("direct-codex:{client_turn_id}:user"))
}
fn direct_codex_command_is_game_verification(command: &str) -> bool { fn direct_codex_command_is_game_verification(command: &str) -> bool {
let command = command.to_ascii_lowercase(); let command = command.to_ascii_lowercase();
command.contains("game.static_smoke") command.contains("game.static_smoke")
@@ -2927,7 +2937,7 @@ impl CodexAppServerConnection {
None => direct_project_local_message_item( None => direct_project_local_message_item(
"user", "user",
current_prompt, current_prompt,
Some(&format!("direct-codex:{client_turn_id}:user")), direct_codex_user_item_id_for_client_turn_id(client_turn_id).as_deref(),
) )
.map_err(platform_llm::LlmError::InvalidRequest)?, .map_err(platform_llm::LlmError::InvalidRequest)?,
}; };
@@ -3046,13 +3056,30 @@ impl CodexAppServerConnection {
}; };
turn_start_guard.armed = false; turn_start_guard.armed = false;
let direct_thread_id = direct_thread_id_for_project(history_root); let direct_thread_id = direct_thread_id_for_project(history_root);
// 回合边界的阶段时间:Turn 上游只有**秒**级 `startedAt` / `completedAt`,秒级截断
// 撑不起前端 0.1 秒粒度的展示,也可能让完成时刻落进该轮用户消息的同一秒、落在真实
// 发送时间之前,被判成无效边界后整轮新回合被吞掉。因此这里只在宿主处理对应阶段时取
// 毫秒钟(与条目侧"没有原生阶段时间就用宿主钟"同一口径),不再读上游秒字段。
let direct_turn_started_at_ms = direct_tool_call_now_ms();
// 本轮开口用户条目的 canonical id:只从已落盘的那条条目上读身份(`id`,工具条目才用
// `call_id`),不在事件侧重造一份。拿不到就留空,让前端按"归属不可证明"处理。
let direct_turn_user_item_id = direct_persisted_user_item
.as_ref()
.and_then(direct_thread_item_identity);
if self.inner.workspace_mode == CodexAppServerWorkspaceMode::DirectProject { if self.inner.workspace_mode == CodexAppServerWorkspaceMode::DirectProject {
append_direct_thread_event(&direct_thread_id, DirectThreadEvent::turn_started()); append_direct_thread_event(
&direct_thread_id,
DirectThreadEvent::turn_started(direct_turn_started_at_ms)
.with_user_item_id(direct_turn_user_item_id.as_deref()),
);
if let Some(user_item) = direct_persisted_user_item.as_ref() { if let Some(user_item) = direct_persisted_user_item.as_ref() {
if let Some(entry_item) = direct_thread_event_item(history_root, user_item) { if let Some(entry_item) = direct_thread_event_item(history_root, user_item) {
// 这里的条目时间可能是启动应答后的观测时间;前端按同一用户条目身份
// 保留更早的真实发送时间,不用此事件时间覆盖它。
let user_item_at = entry_item.at();
append_direct_thread_event( append_direct_thread_event(
&direct_thread_id, &direct_thread_id,
DirectThreadEvent::item_completed(entry_item), DirectThreadEvent::item_completed(entry_item, user_item_at),
); );
} }
} }
@@ -3191,9 +3218,14 @@ impl CodexAppServerConnection {
.map_err(platform_llm::LlmError::InvalidRequest)?; .map_err(platform_llm::LlmError::InvalidRequest)?;
direct_project_history.complete_item(&item); direct_project_history.complete_item(&item);
if let Some(entry_item) = entry_item { if let Some(entry_item) = entry_item {
// `rawResponseItem/completed` 不带阶段时间,宿主处理到这条
// 通知的钟就是该阶段唯一可证明的时间。
append_direct_thread_event( append_direct_thread_event(
&direct_thread_id, &direct_thread_id,
DirectThreadEvent::item_completed(entry_item), DirectThreadEvent::item_completed(
entry_item,
direct_tool_call_now_ms(),
),
); );
} }
} }
@@ -3322,9 +3354,19 @@ impl CodexAppServerConnection {
if let Some(entry_item) = if let Some(entry_item) =
direct_thread_visible_item(history_root, item) direct_thread_visible_item(history_root, item)
{ {
// `item/started` 的通知层带 `startedAtMs`:这是工具真正
// 开始的阶段时间,优先于条目展示时间与宿主钟。
append_direct_thread_event( append_direct_thread_event(
&direct_thread_id, &direct_thread_id,
DirectThreadEvent::item_started(entry_item), DirectThreadEvent::item_started(
entry_item,
direct_thread_item_event_at_ms(
&params,
item,
false,
direct_tool_call_now_ms(),
),
),
); );
} }
} }
@@ -3367,9 +3409,19 @@ impl CodexAppServerConnection {
&& matches!(status, "completed" | "interrupted" | "failed") && matches!(status, "completed" | "interrupted" | "failed")
{ {
terminal_recorded = true; terminal_recorded = true;
// 终态时间:`durationMs` 与宿主记下的毫秒起点都可靠时才派生,
// 否则取宿主处理这条终态的钟;上游秒级 `completedAt` 一律不用。
append_direct_thread_event( append_direct_thread_event(
&direct_thread_id, &direct_thread_id,
DirectThreadEvent::turn_completed(status.to_string()), DirectThreadEvent::turn_completed(
status.to_string(),
direct_thread_turn_completed_at_ms(
turn,
Some(direct_turn_started_at_ms),
direct_tool_call_now_ms(),
),
)
.with_user_item_id(direct_turn_user_item_id.as_deref()),
); );
} }
match status { match status {
@@ -3426,7 +3478,11 @@ impl CodexAppServerConnection {
"failed" "failed"
} }
.to_string(), .to_string(),
), // 这条兜底终态没有对应的 app-server 终态载荷,只能取宿主处理它的钟,
// 不能拿最后一次正文或工具更新时间当回合终点。
direct_tool_call_now_ms(),
)
.with_user_item_id(direct_turn_user_item_id.as_deref()),
); );
} }
let text = match collect_result { let text = match collect_result {
@@ -3624,6 +3680,15 @@ enum DirectCodexTurnCancelTarget {
/// 这时显式释放这条守卫并把可读原因返回给界面。释放条件见 /// 这时显式释放这条守卫并把可读原因返回给界面。释放条件见
/// [`release_stale_direct_taonier_active_invocation`] 的注释;"正在跑的是另一轮"仍然 /// [`release_stale_direct_taonier_active_invocation`] 的注释;"正在跑的是另一轮"仍然
/// 保持原拒绝语义,什么都不释放。 /// 保持原拒绝语义,什么都不释放。
///
/// 兜底终态带 `userItemId`:身份取 `release_stale_direct_taonier_active_invocation` 返回的
/// clientTurnId(客户端回合身份的唯一来源),与正常路径的开口条目 id 同一份 canonical 口径。
/// 拿不到 clientTurnId 就留空——这一轮不会再有原生终态,猜一个身份会让前端把边界盖到别人身上。
fn direct_stale_cancel_turn_completed_event(client_turn_id: &str) -> DirectThreadEvent {
DirectThreadEvent::turn_completed("aborted".to_string(), direct_tool_call_now_ms())
.with_user_item_id(direct_codex_user_item_id_for_client_turn_id(client_turn_id).as_deref())
}
pub(crate) fn cancel_direct_codex_turn_at( pub(crate) fn cancel_direct_codex_turn_at(
root: &Path, root: &Path,
client_turn_id: Option<&str>, client_turn_id: Option<&str>,
@@ -3680,7 +3745,7 @@ pub(crate) fn cancel_direct_codex_turn_at(
// 兜底补一条,否则前端的"最新回合是否在跑"会永远停在运行中。 // 兜底补一条,否则前端的"最新回合是否在跑"会永远停在运行中。
append_direct_thread_event( append_direct_thread_event(
&direct_thread_id_for_project(root), &direct_thread_id_for_project(root),
DirectThreadEvent::turn_completed("aborted".to_string()), direct_stale_cancel_turn_completed_event(&released),
); );
Ok(DirectTurnCancelView { Ok(DirectTurnCancelView {
outcome: DIRECT_TURN_CANCEL_OUTCOME_RELEASED.to_string(), outcome: DIRECT_TURN_CANCEL_OUTCOME_RELEASED.to_string(),
@@ -5006,6 +5071,109 @@ mod tests {
)); ));
} }
/// 阶段时间取自**通知层**字段,形状照抄 codex-cli 0.147 / 0.155 的 v2 协议 schema
/// `item/started` 带 `startedAtMs`、`item/completed` 带 `completedAtMs`(毫秒),
/// `turn/completed` 带 `turn.startedAt` / `turn.completedAt`(秒)与 `turn.durationMs`(毫秒)。
/// 分类函数把 params 原样交给事件级 `at` 的投影函数,所以字段位置必须在这里钉住;
/// 回合边界的秒字段按"不用"锁在这里,避免以后有人再把秒级截断当 0.1 秒精度。
#[test]
fn direct_lifecycle_stage_times_come_from_notification_params() {
let started = serde_json::json!({
"threadId": "thread-1",
"turnId": "turn-1",
"startedAtMs": 1_700_000_000_123u64,
"item": {"id": "call-1", "type": "commandExecution", "command": "ls"},
});
let completed = serde_json::json!({
"threadId": "thread-1",
"turnId": "turn-1",
"completedAtMs": 1_700_000_001_500u64,
"item": {"id": "call-1", "type": "commandExecution", "command": "ls"},
});
for (method, params, expected_at_ms) in [
("item/started", &started, 1_700_000_000_123u64),
("item/completed", &completed, 1_700_000_001_500u64),
] {
let Some(CodexTurnEvent::Item {
completed,
params: event_params,
}) = direct_codex_notification_event(method, params, None, None, "turn-1")
else {
panic!("{method} 必须分类成条目生命周期事件");
};
let item = event_params.get("item").expect("item payload");
assert_eq!(
direct_thread_item_event_at_ms(&event_params, item, completed, 9_999),
expected_at_ms,
"{method} 必须用通知层的阶段时间,而不是宿主钟"
);
}
let terminal = serde_json::json!({
"threadId": "thread-1",
"turn": {
"id": "turn-1",
"items": [],
"status": "completed",
"startedAt": 1_700_000_000i64,
"completedAt": 1_700_000_042i64,
},
});
let Some(CodexTurnEvent::Terminal(params)) =
direct_codex_notification_event("turn/completed", &terminal, None, None, "turn-1")
else {
panic!("turn/completed 必须分类成终态事件");
};
let turn = params.get("turn").unwrap_or(&params);
assert_eq!(
direct_thread_turn_completed_at_ms(turn, Some(1_700_000_000_500), 9_999),
9_999,
"上游只有秒级 completedAt:不采用,取宿主处理终态的毫秒钟"
);
let with_duration = serde_json::json!({
"id": "turn-1",
"items": [],
"status": "completed",
"startedAt": 1_700_000_000i64,
"completedAt": 1_700_000_042i64,
"durationMs": 42_500u64,
});
assert_eq!(
direct_thread_turn_completed_at_ms(&with_duration, Some(1_700_000_000_500), 9_999),
1_700_000_043_000,
"durationMs + 宿主高精度起点才派生结束"
);
}
/// 取消兜底终态也要带开口用户条目身份,且身份只有一个来源:release 返回的 clientTurnId
/// 走与正常路径同一份 canonical 口径;拿不到(空 / 空白)就留空,不猜。
#[test]
fn stale_cancel_terminal_event_keeps_opener_user_item_id_from_client_turn_id() {
let event = direct_stale_cancel_turn_completed_event("turn-0001");
assert_eq!(event.user_item_id(), Some("direct-codex:turn-0001:user"));
assert!(event.at().is_some(), "兜底终态仍要带宿主观测时间");
assert!(matches!(
event,
DirectThreadEvent::TurnCompleted { ref status, .. } if status == "aborted"
));
for missing in ["", " "] {
let event = direct_stale_cancel_turn_completed_event(missing);
assert_eq!(
event.user_item_id(),
None,
"拿不到 clientTurnId 时不得编造开口条目身份"
);
}
// canonical 口径与落盘侧同一份:`direct-codex:{clientTurnId}:user`。
assert_eq!(
direct_codex_user_item_id_for_client_turn_id(" turn-0001 ").as_deref(),
Some("direct-codex:turn-0001:user")
);
assert_eq!(direct_codex_user_item_id_for_client_turn_id(""), None);
}
fn test_llm() -> GameCreatorLlmConfig { fn test_llm() -> GameCreatorLlmConfig {
GameCreatorLlmConfig { GameCreatorLlmConfig {
custom_enabled: false, custom_enabled: false,
@@ -6740,12 +6908,33 @@ done
let consumed = crate::agent::consume_direct_thread(&bootstrap.subscription_id) let consumed = crate::agent::consume_direct_thread(&bootstrap.subscription_id)
.expect("consume events"); .expect("consume events");
// 回合起止必须与开口用户条目同源:前端在「只有锚点 + 历史、运行态为空」的回合里靠这个
// 身份把边界认领给同一条用户条目,缺了它就只能隐藏未知用时。
let lifecycle_user_item_ids = consumed
.events
.iter()
.filter(|event| {
matches!(
event,
DirectThreadEvent::TurnStarted { .. } | DirectThreadEvent::TurnCompleted { .. }
)
})
.map(DirectThreadEvent::user_item_id)
.collect::<Vec<_>>();
assert_eq!(
lifecycle_user_item_ids,
vec![
Some("direct-codex:turn-0001:user"),
Some("direct-codex:turn-0001:user"),
],
"turn.started / turn.completed 都要带本轮开口用户条目的 canonical itemId"
);
let mut user_items = Vec::new(); let mut user_items = Vec::new();
let mut assistant_items = Vec::new(); let mut assistant_items = Vec::new();
for event in &consumed.events { for event in &consumed.events {
let item = match event { let item = match event {
DirectThreadEvent::ItemStarted { item } DirectThreadEvent::ItemStarted { item, .. }
| DirectThreadEvent::ItemCompleted { item } => item, | DirectThreadEvent::ItemCompleted { item, .. } => item,
_ => continue, _ => continue,
}; };
match item { match item {
@@ -1069,15 +1069,10 @@ pub(crate) async fn continue_design_agent_at(
.ok_or("策划 Agent 当前正在工作")?; .ok_or("策划 Agent 当前正在工作")?;
let mut session = match read_design_session(root)? { let mut session = match read_design_session(root)? {
Some(session) => session, Some(session) => session,
None => { None => new_design_session(
if read_planning_session_v2(root)?.is_some() { &project_id,
return Err("此项目包含旧策划会话,请查看原有记录或在新项目开始五阶段策划".into()); &load_game_creator_app_config()?.selected_model_id,
} ),
new_design_session(
&project_id,
&load_game_creator_app_config()?.selected_model_id,
)
}
}; };
if session.project_id != project_id { if session.project_id != project_id {
return Err("策划会话与当前项目不匹配".into()); return Err("策划会话与当前项目不匹配".into());
File diff suppressed because one or more lines are too long
@@ -427,12 +427,16 @@ mod tests {
} }
} }
/// 事件级阶段时间只在重放稳定性用例里逐个指定;其余用例用一个固定值即可,
/// 它们断言的是队列 / 游标语义,不是时间本身。
const FIXED_AT_MS: u64 = 1_000;
fn item_started(item_id: &str) -> DirectThreadEvent { fn item_started(item_id: &str) -> DirectThreadEvent {
DirectThreadEvent::item_started(message(item_id)) DirectThreadEvent::item_started(message(item_id), FIXED_AT_MS)
} }
fn item_completed(item_id: &str) -> DirectThreadEvent { fn item_completed(item_id: &str) -> DirectThreadEvent {
DirectThreadEvent::item_completed(message(item_id)) DirectThreadEvent::item_completed(message(item_id), FIXED_AT_MS)
} }
fn item_delta(item_id: &str) -> DirectThreadEvent { fn item_delta(item_id: &str) -> DirectThreadEvent {
@@ -450,7 +454,7 @@ mod tests {
#[test] #[test]
fn subscribers_have_independent_cursors_on_one_global_queue() { fn subscribers_have_independent_cursors_on_one_global_queue() {
let mut manager = DirectThreadManager::with_limits(100, 100_000); let mut manager = DirectThreadManager::with_limits(100, 100_000);
manager.append("thread-1", DirectThreadEvent::turn_started()); manager.append("thread-1", DirectThreadEvent::turn_started(FIXED_AT_MS));
let first = manager.subscribe("thread-1"); let first = manager.subscribe("thread-1");
let second = manager.subscribe("thread-1"); let second = manager.subscribe("thread-1");
manager.append("thread-1", item_started("item-1")); manager.append("thread-1", item_started("item-1"));
@@ -474,7 +478,7 @@ mod tests {
#[test] #[test]
fn bootstrap_contains_lifecycle_anchor_and_unfinished_events_only() { fn bootstrap_contains_lifecycle_anchor_and_unfinished_events_only() {
let mut manager = DirectThreadManager::with_limits(100, 100_000); let mut manager = DirectThreadManager::with_limits(100, 100_000);
manager.append("thread-1", DirectThreadEvent::turn_started()); manager.append("thread-1", DirectThreadEvent::turn_started(FIXED_AT_MS));
manager.append("thread-1", item_started("item-1")); manager.append("thread-1", item_started("item-1"));
manager.append("thread-1", item_delta("item-1")); manager.append("thread-1", item_delta("item-1"));
manager.append("thread-1", item_completed("item-1")); manager.append("thread-1", item_completed("item-1"));
@@ -484,7 +488,7 @@ mod tests {
assert!(matches!( assert!(matches!(
bootstrap.events.as_slice(), bootstrap.events.as_slice(),
[ [
DirectThreadEvent::TurnStarted {}, DirectThreadEvent::TurnStarted { .. },
DirectThreadEvent::ItemStarted { item, .. }, DirectThreadEvent::ItemStarted { item, .. },
] if item.item_id() == "item-2" ] if item.item_id() == "item-2"
)); ));
@@ -589,15 +593,118 @@ mod tests {
let mut manager = DirectThreadManager::with_limits(100, 100_000); let mut manager = DirectThreadManager::with_limits(100, 100_000);
manager.append( manager.append(
"thread-1", "thread-1",
DirectThreadEvent::turn_completed("completed".to_string()), DirectThreadEvent::turn_completed("completed".to_string(), FIXED_AT_MS),
); );
let bootstrap = manager.subscribe("thread-1"); let bootstrap = manager.subscribe("thread-1");
assert!(matches!( assert!(matches!(
bootstrap.events.as_slice(), bootstrap.events.as_slice(),
[DirectThreadEvent::TurnCompleted { status }] if status == "completed" [DirectThreadEvent::TurnCompleted { status, at, .. }]
if status == "completed" && *at == Some(FIXED_AT_MS)
)); ));
} }
/// 阶段时间必须随事件一起进队列:bootstrap 与重复订阅都拿到**原值**,
/// 重放不得重新取钟(否则每次重连都会把已固定的起止时间改掉)。
#[test]
fn replayed_events_keep_their_original_stage_time() {
let mut manager = DirectThreadManager::with_limits(100, 100_000);
manager.append("thread-1", DirectThreadEvent::turn_started(1_000));
manager.append(
"thread-1",
DirectThreadEvent::item_started(message("item-1"), 2_000),
);
let first = manager.subscribe("thread-1");
assert_eq!(
first
.events
.iter()
.map(DirectThreadEvent::at)
.collect::<Vec<_>>(),
vec![Some(1_000), Some(2_000)]
);
// 第二个订阅看到的是同一份事件,时间不因"又取了一次当前时间"而漂移。
let second = manager.subscribe("thread-1");
assert_eq!(second.events, first.events);
manager.append(
"thread-1",
DirectThreadEvent::item_completed(message("item-1"), 3_000),
);
let completion = manager
.consume(&first.subscription_id)
.expect("consume completion")
.events;
assert_eq!(
completion
.iter()
.map(DirectThreadEvent::at)
.collect::<Vec<_>>(),
vec![Some(3_000)]
);
// 重复消费不产生新事件,也不改写已下发过的时间。
assert!(manager
.consume(&first.subscription_id)
.expect("empty consume")
.events
.is_empty());
assert_eq!(
completion
.iter()
.map(DirectThreadEvent::at)
.collect::<Vec<_>>(),
vec![Some(3_000)]
);
}
/// 生命周期锚点重放时必须带上开口用户条目身份:前端在「只有锚点 + 历史切片、运行态一直空」
/// 的回合里也要能把边界认领给同一条用户条目,而不是按时间戳猜。
#[test]
fn bootstrap_replays_opener_user_item_id() {
let mut manager = DirectThreadManager::with_limits(100, 100_000);
manager.append(
"thread-1",
DirectThreadEvent::turn_started(1_000)
.with_user_item_id(Some("direct-codex:turn-1:user")),
);
let bootstrap = manager.subscribe("thread-1");
assert_eq!(
bootstrap
.events
.iter()
.map(DirectThreadEvent::user_item_id)
.collect::<Vec<_>>(),
vec![Some("direct-codex:turn-1:user")]
);
assert_eq!(bootstrap.events[0].at(), Some(1_000));
// 锚点是独立保存的副本:队列里那条事件被回收之后,新订阅仍拿到同一个身份。
manager
.consume(&bootstrap.subscription_id)
.expect("consume anchor");
manager.append(
"thread-1",
DirectThreadEvent::item_completed(message("item-1"), 2_000),
);
manager.append(
"thread-1",
DirectThreadEvent::turn_completed("completed".to_string(), 3_000)
.with_user_item_id(Some("direct-codex:turn-1:user")),
);
let second = manager.subscribe("thread-1");
assert_eq!(
second
.events
.iter()
.map(DirectThreadEvent::user_item_id)
.collect::<Vec<_>>(),
vec![Some("direct-codex:turn-1:user")],
"起止同源:终态锚点也带同一个开口用户条目身份"
);
assert_eq!(second.events[0].at(), Some(3_000));
}
#[test] #[test]
fn queue_cleanup_only_removes_a_cleanable_prefix() { fn queue_cleanup_only_removes_a_cleanable_prefix() {
let mut manager = DirectThreadManager::with_limits(100, 100_000); let mut manager = DirectThreadManager::with_limits(100, 100_000);
File diff suppressed because it is too large Load Diff
@@ -2391,6 +2391,8 @@ async fn bridge_generate_image(state: &DirectToolBridgeState, arguments: &Value)
slice_mode, slice_mode,
grid_x, grid_x,
grid_y, grid_y,
reference_asset_ids: Vec::new(),
target_category: None,
screen_color, screen_color,
}; };
let _generation_guard = state.image_generation_gate.lock().await; let _generation_guard = state.image_generation_gate.lock().await;
@@ -67,10 +67,11 @@ pub(crate) use canvas_generation::{
generate_platform_art_asset_with_options_at, generate_platform_art_asset_with_options_at,
generate_platform_art_asset_with_required_slices_at, maybe_generate_platform_art_asset_step, generate_platform_art_asset_with_required_slices_at, maybe_generate_platform_art_asset_step,
needs_platform_art_asset_generation, normalize_platform_art_asset_generation_kind, needs_platform_art_asset_generation, normalize_platform_art_asset_generation_kind,
normalize_platform_art_reference_asset_ids, normalize_platform_art_target_category,
platform_art_asset_art_spec, platform_art_asset_output_extension_matches, platform_art_asset_art_spec, platform_art_asset_output_extension_matches,
prepare_platform_art_asset_output_path, project_canvas_asset_media_types, platform_art_runtime_references_match_request_contract, prepare_platform_art_asset_output_path,
role_has_canvas_assets, suggested_canvas_tool_call, PlatformArtAssetGenerationOptions, project_canvas_asset_media_types, role_has_canvas_assets, suggested_canvas_tool_call,
PLATFORM_ART_ASSET_GENERATION_KINDS, PlatformArtAssetGenerationOptions, PLATFORM_ART_ASSET_GENERATION_KINDS,
}; };
#[allow(unused_imports)] #[allow(unused_imports)]
pub(crate) use draft_validation::{ pub(crate) use draft_validation::{
File diff suppressed because it is too large Load Diff
@@ -549,7 +549,7 @@ fn append_agent_runtime_file_read_evidence_ref(
// 给的是**整个三元组**,不是一个碎片。`agent.acceptance_update` 的 evidence 引用 // 给的是**整个三元组**,不是一个碎片。`agent.acceptance_update` 的 evidence 引用
// 要求 {agentId, runId, actionId} 三个字段,回执查找也按三元组整体做 key。早期 // 要求 {agentId, runId, actionId} 三个字段,回执查找也按三元组整体做 key。早期
// 只给 actionId,另外两个靠模型回忆——实测它第一次就把其中一个记错,白吃一次 // 只给 actionId,另外两个靠模型回忆——实测它第一次就把其中一个记错,白吃一次
// 拒绝。反正 `validate_fast_gdd_evidence_identity` 只接受当前根 run 的回执, // 拒绝。验收证据只接受当前根 run 的回执,
// 合法取值唯一,本来就不该让它猜。 // 合法取值唯一,本来就不该让它猜。
observation.summary = format!( observation.summary = format!(
"{} · sourceAgentId={agent_id} · sourceRunId={run_id} · sourceActionId={action_id}", "{} · sourceAgentId={agent_id} · sourceRunId={run_id} · sourceActionId={action_id}",
@@ -919,9 +919,9 @@ mod file_read_source_action_id_tests {
AgentRuntimeToolObservation { AgentRuntimeToolObservation {
tool: "file.read".to_string(), tool: "file.read".to_string(),
status: "ok".to_string(), status: "ok".to_string(),
summary: "已读取 game/fast_gdd.md 第 1-134 行(共 134 行)".to_string(), summary: "已读取 design.md 第 1-134 行(共 134 行)".to_string(),
detail: Some(format!( detail: Some(format!(
"game/fast_gdd.md · sha256={} · lines 1-134 of 134 "design.md · sha256={} · lines 1-134 of 134
第一行内容", 第一行内容",
"a".repeat(64) "a".repeat(64)
)), )),
@@ -954,7 +954,7 @@ mod file_read_source_action_id_tests {
agent_runtime_action_receipt_public_safe_detail_for_test(&root, &observation) agent_runtime_action_receipt_public_safe_detail_for_test(&root, &observation)
.expect("safe detail still parses"); .expect("safe detail still parses");
let value = serde_json::from_str::<serde_json::Value>(&safe_detail).expect("json"); let value = serde_json::from_str::<serde_json::Value>(&safe_detail).expect("json");
assert_eq!(value["path"], "game/fast_gdd.md"); assert_eq!(value["path"], "design.md");
assert_eq!(value["lines"], "1-134 of 134"); assert_eq!(value["lines"], "1-134 of 134");
assert_eq!(value["contentSha256"], "a".repeat(64)); assert_eq!(value["contentSha256"], "a".repeat(64));
} }
@@ -78,12 +78,6 @@ pub(super) fn game_creator_agent_final_reply_error_allows_fallback(error: &str)
matches!(kind.as_str(), "empty-response" | "deserialize") matches!(kind.as_str(), "empty-response" | "deserialize")
} }
/// 这些错误只描述本次 Provider input 或候选 GDD;真正的 session CAS 冲突不在
/// 此列——那说明 durable session 已被推进或损坏,必须 reconcile。
fn plan_submit_error_is_business_rejection(error: &PlanningStorageError) -> bool {
matches!(error.code(), "PLAN_INVALID_REQUEST" | "PLAN_SIZE_LIMIT")
}
const AGENT_RUNTIME_PLAN_UPDATE_IDLE_LIMIT: u32 = 4; const AGENT_RUNTIME_PLAN_UPDATE_IDLE_LIMIT: u32 = 4;
/// 最终回复被收束门禁拦下后 run 会原地续跑重试。多数 blocker 是模型自己能解的 /// 最终回复被收束门禁拦下后 run 会原地续跑重试。多数 blocker 是模型自己能解的
@@ -7,9 +7,6 @@ mod design_session;
mod finalization; mod finalization;
mod json_sidecar; mod json_sidecar;
mod models; mod models;
mod planning_gdd_model;
mod planning_policy_v2;
mod planning_session_v2;
mod provider_control; mod provider_control;
mod provider_retry; mod provider_retry;
mod real_e2e_checkpoint; mod real_e2e_checkpoint;
@@ -24,9 +21,6 @@ pub(crate) use design_session::*;
pub(in crate::agent) use finalization::*; pub(in crate::agent) use finalization::*;
pub(in crate::agent) use json_sidecar::*; pub(in crate::agent) use json_sidecar::*;
pub(in crate::agent) use models::*; pub(in crate::agent) use models::*;
pub(crate) use planning_gdd_model::*;
pub(crate) use planning_policy_v2::*;
pub(crate) use planning_session_v2::*;
pub(in crate::agent) use provider_control::*; pub(in crate::agent) use provider_control::*;
pub(in crate::agent) use provider_retry::*; pub(in crate::agent) use provider_retry::*;
pub(in crate::agent) use real_e2e_checkpoint::*; pub(in crate::agent) use real_e2e_checkpoint::*;
@@ -781,7 +781,7 @@ mod provider_reconciliation_diagnostic_tests {
let directory = tempfile::tempdir().expect("diagnostic directory"); let directory = tempfile::tempdir().expect("diagnostic directory");
let snapshot = AgentRuntimeProviderRequestSnapshot { let snapshot = AgentRuntimeProviderRequestSnapshot {
project_id: "project-1".to_string(), project_id: "project-1".to_string(),
agent_id: "project-planning".to_string(), agent_id: "project-supervisor".to_string(),
task_id: "task-1".to_string(), task_id: "task-1".to_string(),
session_id: "session-1".to_string(), session_id: "session-1".to_string(),
run_id: "run-1".to_string(), run_id: "run-1".to_string(),
@@ -805,7 +805,7 @@ mod provider_reconciliation_diagnostic_tests {
usage: None, usage: None,
tool_calls: vec![platform_llm::LlmToolCall { tool_calls: vec![platform_llm::LlmToolCall {
id: "call-1".to_string(), id: "call-1".to_string(),
name: "runtime_tool_plan_submit_gdd".to_string(), name: "runtime_tool_agent_message".to_string(),
arguments: "{\"path\":\"C:\\\\private\\\\argument\"}".to_string(), arguments: "{\"path\":\"C:\\\\private\\\\argument\"}".to_string(),
}], }],
responses_output: Vec::new(), responses_output: Vec::new(),
@@ -201,39 +201,17 @@ pub(crate) fn observe_agent_runtime_agent_message(
} }
} }
/// 委派 task 末尾那句「你在这条链路上的位置」。三种跳的语义互不相同,共用一句话 /// 委派 task 末尾那句「你在这条链路上的位置」。返工和普通委派的语义不同,单独保留。
/// 就会说谎,所以这里把它显式化。
/// ///
/// - `Repair`:质量返工,`repair_depth` 上限 1,「唯一返工轮」是真的。而且这句话是 /// - `Repair`:质量返工,`repair_depth` 上限 1,「唯一返工轮」是真的。而且这句话是
/// 做游戏链路的**授权信号**——`design-foundation` / `art-director` / /// 做游戏链路的**授权信号**——`design-foundation` / `art-director` /
/// `art-asset-plan` 的角色提示词都把「任务正文明确标识这是带 repairOfDelegationId /// `art-asset-plan` 的角色提示词都把「任务正文明确标识这是带 repairOfDelegationId
/// 的唯一返工轮」当作 `replaceExisting=true` 的唯一许可(见 agent/prompt.rs 的三处 /// 的唯一返工轮」当作 `replaceExisting=true` 的唯一许可(见 agent/prompt.rs 的三处
/// 角色 prompt)。这一支逐字不能动。 /// 角色 prompt)。这一支逐字不能动。
/// - `PlanClarification`:澄清续跑不消耗 `repair_depth`,预算是
/// `static_delegate_clarification_round_limit_at`plan 链路 3 轮)。master 只有一道
/// 平坦的 depth <= 1 门,那时「唯一返工轮」对澄清跳也成立;本仓库改成按谱系分类后
/// 把预算抬到 3,这句话就变成了假天花板——生产实测 4 次澄清续跑全部命中它,命中后
/// 全部直接出稿,没有任何一个 run 走到第 2 轮。
/// - `UserRevision`:用户在审批卡上点「修改 / 退回」后的修订轮。它同样带
/// `repairOfDelegationId`,但 `repair_depth` 防的是 runaway agent,而这一跳每一轮
/// 都由人触发——人本身就是循环边界,所以 `static_delegate_lineage_counters` 早就
/// 把 depth/round 原样继承了。缺的是这句话:走 `Repair` 分支时用户第一次点修改就
/// 会被告知「这是唯一返工轮」,和澄清跳当初那个假天花板是同一个错误。原型对应的是
/// `USER_REVISION_SOFT_LIMIT = 16`,且超过只提示、不拒绝。
/// - `None`:普通委派,不加这一段。 /// - `None`:普通委派,不加这一段。
pub(in crate::agent) enum StaticDelegateHopNote<'a> { pub(in crate::agent) enum StaticDelegateHopNote<'a> {
None, None,
Repair { Repair { original_delegation_id: &'a str },
original_delegation_id: &'a str,
},
UserRevision {
original_delegation_id: &'a str,
},
PlanClarification {
original_delegation_id: &'a str,
rounds_used: u32,
rounds_limit: u32,
},
} }
impl StaticDelegateHopNote<'_> { impl StaticDelegateHopNote<'_> {
@@ -247,32 +225,6 @@ impl StaticDelegateHopNote<'_> {
StaticDelegateHopNote::Repair { StaticDelegateHopNote::Repair {
original_delegation_id, original_delegation_id,
} => format!("\n\n这是对已认领委派 {original_delegation_id} 的唯一返工轮。"), } => format!("\n\n这是对已认领委派 {original_delegation_id} 的唯一返工轮。"),
StaticDelegateHopNote::UserRevision {
original_delegation_id,
} => format!(
"\n\n这是对已认领委派 {original_delegation_id} 的用户修订轮,由用户在审批卡上提出,不是质量返工,不消耗返工深度,也不重置澄清轮次。按任务正文里的用户意见原文修订同一份 GDD 谱系后重新提交;用户看过新稿还可以再次提出修改,这不是最后一轮,不要因此压缩改动或提前收尾。"
),
// 预算用尽:planning_coordinator 出卡时会用
// `current_round >= 3` 直接拒掉第四张卡,所以这里不能再邀请提问,
// 只能要求收稿——语义上等价于原型的 INJ_MUST_DRAFT_ROUNDS。
StaticDelegateHopNote::PlanClarification {
original_delegation_id,
rounds_used,
rounds_limit,
} if rounds_used >= rounds_limit => format!(
"\n\n这是对已认领委派 {original_delegation_id} 的澄清续跑,不是返工轮。已用澄清轮次 {rounds_used}/{rounds_limit},澄清预算已用尽:本轮不得再输出 AGC_NEEDS_USER_INPUT_V1 信封,剩余空白按默认建议补齐并标 default_pending,立即提交 GDD。"
),
// 轮号必须和 planning_coordinator 出卡时的期望一致:那边用
// `validate_exact_plan_clarification_question(.., current_round + 1)`
// current_round 就是本 delivery 的谱系轮次,也就是这里的 rounds_used。
StaticDelegateHopNote::PlanClarification {
original_delegation_id,
rounds_used,
rounds_limit,
} => format!(
"\n\n这是对已认领委派 {original_delegation_id} 的澄清续跑,不是返工轮,不消耗返工深度。已用澄清轮次 {rounds_used}/{rounds_limit}。仍有会实质改变结果的空白且预算未用尽时,可以继续以 AGC_NEEDS_USER_INPUT_V1 信封退出:questions 恰好一题,header 写成「第{next_round}轮·当前要决定:<主题>」,轮号必须是 {next_round},主题写这一轮真正要定的那件事。预算已用尽,或剩余空白能由默认建议覆盖且不影响首个可玩闭环时,立即提交 GDD。",
next_round = rounds_used.saturating_add(1),
),
} }
} }
} }
@@ -1523,122 +1475,3 @@ pub(crate) fn observe_agent_runtime_agent_spawn_isolated(
.map(|value| redact_agent_runtime_project_paths(root, &value, 3_600)), .map(|value| redact_agent_runtime_project_paths(root, &value, 3_600)),
} }
} }
#[cfg(test)]
mod tests {
use super::*;
/// 委派 task 末尾那句话是两条链路的合同,不能共用一份文案。
///
/// 上半条钉做游戏链路:`design-foundation` / `art-director` / `art-asset-plan`
/// 的角色提示词把「任务正文明确标识这是带 repairOfDelegationId 的唯一返工轮」
/// 当作 `replaceExisting=true` 的唯一授权信号,改一个字就会让返工轮拿不到许可。
///
/// 下半条钉立项策划链路:澄清续跑不是返工轮,套用返工文案等于告诉策划子 Agent
/// 「你只剩这一轮」——这正是生产上 4 次澄清续跑之后无一走到第 2 轮的原因。
/// 同时钉住轮号:`planning_coordinator` 出卡时按 `rounds_used + 1` 校验 header
/// 这里写进 task 的必须是同一个数,否则第 2 轮信封会当场被拒。
/// 用户修订轮同样不能套返工文案。
///
/// 「唯一返工轮」防的是 runaway agent,而这一跳由用户在审批卡上亲手点出来——人本身
/// 就是循环边界,`static_delegate_lineage_counters` 早就把 depth/round 原样继承了。
/// 套用返工文案就是告诉策划子 Agent「用户只能改这一次」,和澄清跳当初那个假天花板
/// 是同一个错误。原型对应的是软阈值 16 次、超过只提示不拒绝。
#[test]
fn user_revision_hop_note_is_not_the_repair_round_note() {
let revision = render_static_delegate_task_contract(
"任务",
"project-supervisor",
"run-1",
"delegation-new",
&["交付 game/fast_gdd.md".to_string()],
&["game/fast_gdd.md".to_string()],
StaticDelegateHopNote::UserRevision {
original_delegation_id: "delegation-old",
},
)
.expect("render user revision hop note");
assert!(
!revision.contains("唯一返工轮"),
"用户修订轮不得复用返工文案,否则子 Agent 以为用户只能改这一次:{revision}"
);
assert!(
revision.contains("不消耗返工深度"),
"必须写明它不吃返工额度:{revision}"
);
assert!(
revision.contains("不是最后一轮"),
"必须写明用户还能再改,否则子 Agent 会把多条意见攒到一轮改完:{revision}"
);
}
#[test]
fn plan_clarification_hop_note_is_not_the_repair_round_note() {
let repair = render_static_delegate_task_contract(
"任务",
"project-supervisor",
"run-1",
"delegation-new",
&["交付产物".to_string()],
&["assets/art-spec.png".to_string()],
StaticDelegateHopNote::Repair {
original_delegation_id: "delegation-old",
},
)
.expect("render repair");
assert!(
repair.contains("这是对已认领委派 delegation-old 的唯一返工轮。"),
"返工轮文案是做游戏链路 replaceExisting 的授权信号,必须逐字保留:{repair}"
);
let clarification = render_static_delegate_task_contract(
"任务",
"project-supervisor",
"run-1",
"delegation-new",
&["交付 game/fast_gdd.md".to_string()],
&["game/fast_gdd.md".to_string()],
StaticDelegateHopNote::PlanClarification {
original_delegation_id: "delegation-old",
rounds_used: 1,
rounds_limit: 3,
},
)
.expect("render clarification");
assert!(
!clarification.contains("唯一返工轮"),
"澄清续跑不得复用返工文案,否则策划子 Agent 以为只剩这一轮:{clarification}"
);
assert!(
clarification.contains("已用澄清轮次 1/3"),
"澄清续跑必须写明已用轮次与上限:{clarification}"
);
assert!(
clarification.contains("第2轮·当前要决定:"),
"task 里的轮号必须等于 planning_coordinator 校验 header 时用的 rounds_used + 1{clarification}"
);
let exhausted = render_static_delegate_task_contract(
"任务",
"project-supervisor",
"run-1",
"delegation-new",
&["交付 game/fast_gdd.md".to_string()],
&["game/fast_gdd.md".to_string()],
StaticDelegateHopNote::PlanClarification {
original_delegation_id: "delegation-old",
rounds_used: 3,
rounds_limit: 3,
},
)
.expect("render exhausted clarification");
assert!(
exhausted.contains("澄清预算已用尽"),
"预算用尽时必须要求收稿,出卡侧会直接拒掉第四张卡:{exhausted}"
);
assert!(
!exhausted.contains("第4轮·当前要决定:"),
"预算用尽时不得再给出下一轮 header,那是一张永远递不上去的卡:{exhausted}"
);
}
}
@@ -10,18 +10,6 @@ pub(in crate::agent) fn agent_role_project_path_mutation_block(
if autonomous_relaxed_run_at(root, agent_id, run_id).unwrap_or(false) { if autonomous_relaxed_run_at(root, agent_id, run_id).unwrap_or(false) {
return None; return None;
} }
if is_agent_planning_storage_path(path) || is_plan_fast_gdd_projection_path(path) {
return Some(AgentRuntimeToolObservation {
tool: tool.to_string(),
status: "blocked".to_string(),
summary: if is_agent_planning_storage_path(path) {
"`.agent/planning/**` 只能由立项策划 Runtime 专用存储层写入".to_string()
} else {
"`game/fast_gdd.md` 只能由立项策划 Runtime renderer 写入".to_string()
},
detail: Some(format!("agentId={agent_id} · runId={run_id} · path={path}")),
});
}
match autonomous_owner_artifact_validation_available_for_run_at(root, agent_id, run_id) { match autonomous_owner_artifact_validation_available_for_run_at(root, agent_id, run_id) {
Ok(true) => { Ok(true) => {
let allowed = autonomous_manifest_owner_artifact_paths(agent_id); let allowed = autonomous_manifest_owner_artifact_paths(agent_id);

Some files were not shown because too many files have changed in this diff Show More