合并远端 0.1.11 基线并保留本地 AGC 全流程改动
Project CI / Repository checks (push) Successful in 3m49s
Project CI / Frontend tests (push) Successful in 4m54s
Project CI / Backend tests (push) Successful in 8m50s
Project CI / Native shell tests (push) Failing after 12m12s

This commit is contained in:
Git Hooks Test
2026-08-28 20:56:03 +08:00
406 changed files with 13136 additions and 4965 deletions
@@ -556,7 +556,7 @@ V1.11 把命令安全边界从“固定 program + argv 规则 + 隔离环境变
- `command.exec` 与 `command.start` 必须继续共用唯一 `ProjectCommandLaunchSpec`,`project.verify` 必须调用同一 sandbox launcher。真实 executable / argv 在该层包装为受信任系统 bubblewrap;一次性 Tokio child、PTY child wrapper、npm 验证脚本和全部后代不能有绕过该包装的生产 spawn 路径。
- bubblewrap 只允许从固定系统候选路径解析,文件必须是普通可执行文件且不能被当前普通用户写入。缺失、权限异常、namespace setup 失败或挂载失败都返回 `sandbox-unavailable` / preflight 失败;不得尝试裸 `unshare`、代理断网或无沙箱宿主执行作为 fallback。
- sandbox 使用独立 user / mount / pid / ipc / uts / cgroup / network namespace,禁用嵌套 user namespace,并启用 parent-death 收束。系统 executable / dynamic runtime 和明确工具链缓存只读挂载;规范项目根以原绝对路径读写挂载,cwd 仍必须是无 symlink / reparse point 的项目内目录。
- 项目根挂载后覆盖控制目录:`.git / .agents / .codex / .hermes` 存在时按原路径只读挂载;`.agent` 使用不可读写的空 mount 覆盖,命令不能看到 Runtime sidecar、会话、审计或配置。项目内指向外部的 symlink 因目标未挂载而不可访问。
- 项目根挂载后覆盖控制目录:`.git / .agents / .codex` 存在时按原路径只读挂载;`.agent` 使用不可读写的空 mount 覆盖,命令不能看到 Runtime sidecar、会话、审计或配置。项目内指向外部的 symlink 因目标未挂载而不可访问。
- HOME / USERPROFILE / TMP / Cargo / npm cache 使用 sandbox 内私有临时目录。允许只读复用不含凭据的工具链 source cache,但外部工具链环境根必须 canonicalize 后再次校验为与变量类型匹配的窄叶目录;`RUSTUP_HOME=$HOME`、`.rustup -> $HOME` 和其它宽用户目录必须失败关闭。不得挂载整个用户 HOME、AppData、SSH、云凭据、Cookie 或 Runtime 配置目录。
- 网络 namespace 默认无外部网络,HTTP(S) / ALL proxy 与离线包管理器变量只作为纵深防御。`networkAccess` 首版固定 `disabled`,模型输入不能开启;需要联网必须作为未来独立 approval escalation 设计,不能复用普通 confirm 偷渡。
@@ -572,7 +572,7 @@ V1.11 把命令安全边界从“固定 program + argv 规则 + 隔离环境变
- namespace canary 与项目 mount preflight 失败时,必须在 revision / processId 推进前返回稳定的 sandbox unavailable / setup 错误并保持项目命令未执行。当前 preflight 与随后真实 bwrap launch 是两次独立启动:真实 launch 若在目标 exec 前发生第二次 setup 失败,目标程序不会绕过沙箱执行,但尚无可信 exec-ready 握手证明失败阶段,revision 可能已经推进并按普通命令失败收束。这是 V1.11 已知残余,后续必须用 launcher 握手把“沙箱已建立且目标已 exec”与“仅准备采用沙箱”分开,不能把当前行为描述为原子保证。
- command log、terminal receipt、Agent DB 和 process record 至少记录固定 `sandboxMode=workspace-write / networkAccess=disabled / sandboxBackend=bubblewrap / sandboxProfileVersion=workspace-v1` 安全元数据,不记录 host mount source、用户 HOME、bwrap 完整 argv 或本地工具链路径。process record 使用 schema v2 持久化 launch 当时的四项元数据,poll / stdin / terminate 和旧 boot reconciliation 必须从 record / live session 读取,不能按当前平台静态猜测;旧 v1 record 只能迁移为 `legacy-unknown`。纯 preflight 失败记录 `unavailable / not-established`,不得谎报 bubblewrap 已建立。
- 确定性真实进程测试必须证明:项目内构建 / 测试 / Git 读取成功;项目外普通文件读取与写入失败;`.git / .agent / .agents / .codex / .hermes` 写入失败;网络默认不可达;shell 子进程继承同一边界;bwrap 不可用时项目命令零执行且失败关闭。`command.start` 还必须让 PTY 后代实际执行 `setsid + chdir` 后的项目外读取、控制目录写入和原始 socket 负例,并断言 process record 与每段专用审计的四项 sandbox metadata。
- 确定性真实进程测试必须证明:项目内构建 / 测试 / Git 读取成功;项目外普通文件读取与写入失败;`.git / .agent / .agents / .codex` 写入失败;网络默认不可达;shell 子进程继承同一边界;bwrap 不可用时项目命令零执行且失败关闭。`command.start` 还必须让 PTY 后代实际执行 `setsid + chdir` 后的项目外读取、控制目录写入和原始 socket 负例,并断言 process record 与每段专用审计的四项 sandbox metadata。
- deb / rpm 发布包声明 `bubblewrap` 宿主依赖;AppImage 不携带 bubblewrap sidecar,发布页和安装检查必须明确要求受支持版本的系统 `/usr/bin/bwrap` 或 `/bin/bwrap`。缺失时命令工具安全失败关闭,但该 AppImage 不算具备可用的通用开发能力。
- 真实 Provider disposable E2E 不给固定 program、文件名或工具顺序,要求模型自行发现项目技术栈,运行构建、测试和 Git 检查,并用结构化审计证明所有命令都在 workspace-write / network-disabled 下执行。上述门禁通过前不得宣称 V1.11 完成。
@@ -986,7 +986,7 @@ V1.24 修正仓库启动上下文把 `AGENTS.md` 与 README/CONTEXT 一律描述
V1.25 在 V1.24 仓库启动上下文上增加项目内 Skill catalog,但不把 Skill 正文预加载到每轮 prompt。目标是对齐 Codex 的 progressive disclosure:模型始终只看到用于触发判断的 `name / description / entryPath / contentSha256`,任务真实命中后再通过现有 `file.read` 获取 `SKILL.md` 正文,并只按正文导航读取必要 reference。Skill 是项目工作流知识,不是新工具、权限包或可执行插件。
- 发现根固定为项目内 `.codex/skills/<skill-name>/SKILL.md` 与兼容目录 `.agents/skills/<skill-name>/SKILL.md`,只接受这两个根下的直接子目录入口,不递归把 reference 中的其它 `SKILL.md` 当独立 Skill。本仓库既有规范以 `.codex/skills` 为准;同名且两处都合法时 `.codex` 胜出,删除高优先级入口后 `.agents` 才可接管。V1.25 不扫描 AppData、用户主目录、全局 Codex/Hermes 安装目录、Git submodule 外部路径或网络 marketplace。
- 发现根固定为项目内 `.codex/skills/<skill-name>/SKILL.md` 与兼容目录 `.agents/skills/<skill-name>/SKILL.md`,只接受这两个根下的直接子目录入口,不递归把 reference 中的其它 `SKILL.md` 当独立 Skill。本仓库既有规范以 `.codex/skills` 为准;同名且两处都合法时 `.codex` 胜出,删除高优先级入口后 `.agents` 才可接管。V1.25 不扫描 AppData、用户主目录、全局 Codex 安装目录、Git submodule 外部路径或网络 marketplace。
- `skill-name` 必须与目录名和 YAML frontmatter `name` 完全一致,使用 1-64 个 ASCII 小写字母、数字或单连字符,首尾必须是字母或数字;frontmatter 必须位于文件开头并提供非空字符串 `name / description`。YAML 使用结构化 parser;未知字段不产生 Runtime 能力。描述清洗凭据和绝对路径、折叠为单行并限制 2048 bytes。
- 单个 `SKILL.md` 最大 128 KiB,catalog 最多 64 项,prompt 中 Skill metadata section 最大 4 KiB。超限、解析失败、符号链接、路径不规范或读取失败的入口不进入 catalog;预算或读取导致的省略必须使 repository context 标记 `truncated=true`,不能把部分 YAML 当有效 metadata。
- 仓库启动上下文升级为 `repository-startup-context-v3`,新增有界 `skills` 列表。fingerprint 覆盖 active Skill 的规范入口路径、来源根、清洗后 name/description、清洗后完整文件 SHA-256 和截断状态;Skill 正文、metadata、优先级或入口增删发生变化时,任何受 repository context gate 保护的旧 pending action 都必须先形成 drift blocker,再在同一 run 重规划。shadowed 的低优先级同名入口不影响 active 语义。
@@ -1482,6 +1482,8 @@ npm run ai-game-creator-shell:agent-runtime:supervisor-swarm-final-reply-transie
V1.43 不放宽 V1.41 的文本型 `game-creator-provider-handoff.v1`,而是为 `requestKind=tool-plan` 增加独立私有账本 `.agent/runtime/tool-plan-handoffs/<agentKey>/<runKey>.json`,schema 固定为 `game-creator-tool-plan-handoff.v1`。同一 Agent/run 账本按 `(loopIteration, repairAttempt)` 单调保存已成功的 `repair-0..N` Provider 响应,每条绑定完整 retry identity、实际物理 `providerRequestId`、真实 request slot/attempt、Provider/model、去除 thinking 后的响应、thinking 归一化哈希/计数、完整 function call envelope、usage、响应指纹和创建时间。账本使用既有 `0600`、原子替换、父目录同步、`.previous` 恢复和写后完整回读;未知字段、乱序/缺口、重复 slot 冲突、超限、危险可执行路径、密钥或配置痕迹一律失败关闭。
当成功响应因 handoff 校验失败而进入 `needs-reconciliation` 时,Runtime 额外在应用私有数据目录的 `diagnostics/provider-reconciliation/<projectHash>/<requestHash>.json` 写入一次本地诊断。该诊断只服务人工排障,不参与恢复、重试或业务状态判断,可保留本次 Provider 响应、tool call arguments 和原始校验错误;项目 `.agent`、Agent DB、公共 event、CLI 与报告只保留安全摘要及该私有诊断的相对引用。诊断文件限制为 1 MiB,使用原子写入;应用配置目录不可用或诊断写入失败时,不改变既有 fail-closed reconciliation 语义。
### 提交、重放与所有权
- 每个 tool-plan 物理请求的顺序固定为:Provider 成功 -> tool-plan handoff 追加并回读 -> 同一实际 requestId lifecycle `completed` -> 解析/格式修复或动作预检。function arguments 只存在于私有 handoff 与后续 pending/action batch。protocol/repair 公共审计共同保存 `agentId/taskId/sessionId/runId/source/loopIteration/repairAttempt/requestSlot/responseFingerprint/providerRequestIdSha256/protocol`;protocol 只额外保存 `functionCallCount/callIdSha256s/functionNames/responseIdSha256/responseIdChars` 和既有 normalization 字段,其中 function names 必须由 catalog 绑定;repair 只额外保存 attempt/maxAttempts、协议错误/preview 哈希与字符数及 `callIdSha256/functionNameSha256`。公共 task、event、Agent DB、CLI 和报告不得保存原始 callId/callIds/responseId/providerRequestId。两类审计都在 Agent DB append 锁内按完整 Agent/task/Session/run/source/slot 身份做全历史 compare-and-append,不能以受限尾部读取替代幂等。
@@ -210,6 +210,7 @@ Supervisor 认领该回执后,由父 run 自己为每个原 delivery 逐一创
- 进程与节点:External Runner 按“有效 Agent LLM 凭据/Responses 路由 + `projectId/agentId/sessionId/runId`”隔离长期 `codex app-server --stdio`,即每个权威节点 run 直接持有自己的 Codex CLI 子进程与 ephemeral thread,每次完整权威请求映射 turn。同一节点 turn 串行,节点之间进程级隔离;单节点连接失败不得使其它节点同时失去终态。Codex thread 不写 durable recovery;节点完成、重启、retry、handoff 和 finalization 仍只认 AGC 账本。
- LLM 配置:`apiKind` 始终只接受 `openai_responses`;非空 Key 转换为 app-server model provider,base URL 生效,Key 仅走专用环境变量;空 Key 只桥接用户 Codex `auth.json`,不继承环境 `CODEX_API_KEY`。设置面板在 app-server 模式继续显示并保存 model、effort、stream、全局/逐 Agent Key 与路由配置;`openai_chat / anthropic` 明确提示切 `provider`,不得悄悄忽略。`stream=true` 接入 app-server 文本 delta;`webSearchEnabled=true` 只允许 DirectProject 经客户端审核的 `agc_web_search` 使用,不得启用 Codex 原生 webSearch 或任意网络。
- 安全与取消:临时 cwd、隔离 `CODEX_HOME` 与 OS HOME、read-only、network off、never approval,并在启动前关闭 web/multi-agent/shell/browser/plugin/image 等原生能力;取消从 turn-start pending 阶段就跟踪且只 interrupt 当前 turn。已发送 turn 后连接断开或终态丢失进入 reconciliation,只关闭当前节点进程且不重放同一 request slot;明确 failed/interrupted 不按 transport 重试。
- remote-control 认证边界:没有 ChatGPT `auth.json` 的 API Key / provider-proxy app-server 在启动时设置 Codex 内部环境变量 `CODEX_INTERNAL_APP_SERVER_REMOTE_CONTROL_DISABLED=1`,让 remote-control 以 `desired_state=Disabled` 启动,避免上游进入 1Hz 认证重试;不再依赖需要 ChatGPT 登录态的 `remoteControl/disable` RPC。只有实际桥接 ChatGPT 登录态的 AuthBridge 保持 remote-control 可用。API Key 子进程同时使用 `RUST_LOG=warn` 收敛剩余预期噪音,不伪造 `auth.json` 或静默继续。
- 资源与退出:app-server pool 按实际凭据快照/base URL/API kind/CLI 版本和节点 run 身份隔离并做有界 LRU;空 AppData Key 必须读取同一份有界 `auth.json` 字节来生成池指纹并桥接隔离登录态,继承的 `CODEX_API_KEY` 始终移除,node thread 也只淘汰 inactive LRU。Runner 正常、强制和 watchdog 退出都显式关池,Linux child 绑定 parent-death signal,防止强杀 Runner 后遗留带凭据孤儿进程。stdout NDJSON 与 stderr 无换行记录均有硬上限;stderr 原文不写入诊断,只记录固定分类、总字节数、SHA-256 和可取得的退出状态。
- 旧配置迁移:既有 AppData 若没有 `agentMode`,只有全局和逐 Agent 路由均为 `openai_responses` 时迁移到 `codex_app_server`;存在 `openai_chat / anthropic` 时显式保留 `provider`,避免打开项目自动恢复时把所有节点批量写成 `invalid-config`。用户确认端点支持 Responses 后,可在设置中显式切换并保留原 model/base URL/API Key。
- 验收:fake JSON-RPC fixture、三态 UI/config、配置指纹、unknown-terminal 零重放、旧两种模式回归和显式 ignored 真实 smoke 全部通过后,才可视为模式切换完成。
@@ -221,7 +222,7 @@ Supervisor 认领该回执后,由父 run 自己为每个原 delivery 逐一创
- 状态询问、解释和不冲突补充默认继续当前 Provider;明确停止、改向或会让在途方案过期时才允许请求中断。判定失败时继续任务,并在下一安全边界消费消息,不得把失败等同于需要中断。
- UI 通过持久 conversation 展示关联回复,刷新后仍可见;返回的 `assistantReply / interruptDecision / decisionReason` 只用于本次命令结果与诊断,不形成第二个会话或第二个 Run。
V1.11 的受保护仓库控制目录同时包含 `.git / .agent / .agents / .codex / .hermes`;其中 `.agent` 对项目命令隐藏,其余控制目录只读。
V1.11 的受保护仓库控制目录同时包含 `.git / .agent / .agents / .codex`;其中 `.agent` 对项目命令隐藏,其余控制目录只读。
2026-08-04 起,Runtime 的公共工具规划指令、Supervisor 协作编排 playbook、条件 overlay 和编译期静态 Agent 节点目录统一由版本化 Prompt Bundle 驱动,位于 `apps/ai-game-creator-shell/src-tauri/prompts/runtime/`。`manifest.json` 是 section 路径、组合顺序、平台 / Editor 变体、role overlay、Provider 协作 fragment,以及 Supervisor 与六组专业 Agent 静态目录的单一来源;role overlay 只允许 `rootSourceKind` 强类型语义 selector,构建期拒绝未知 kind,运行期把权威 source 常量映射为生成 kind。`build.rs` 同时监听 Bundle 每一级目录、manifest 和已登记 section,保证任意嵌套目录新增孤立 Markdown 都会触发增量构建,并以失败关闭方式校验 schema、引用、路径 / symlink、孤立 Markdown、selector、节点身份、旧 alias 和生成标识符,再生成 `'static + Copy` Rust 定义并编译进发布二进制。公共 runtime system header 保持身份中立;生成的 Supervisor planning composition 必须复用 `supervisorChat.identity`。每个 section 只能属于 runtime composition、Supervisor composition、chat 字段、platform variant、visual variant、role overlay 或 Provider fragment 中一个语义所有者;唯一例外是同一 identity section 由 Supervisor planning 与 `supervisorChat.identity` 显式复用,从而同时阻断 Supervisor 指令外泄和动态 variant 与静态 composition 的重复注入。专业节点 taskId / group / role 还必须在构建期与 `shared-contracts::new_game_creation_app_seed_tasks()` 强一致,防止身份合同、静态目录和正式 seed DAG 漂移。Bundle 承载公共指令、隔离 Agent 合同、平台差异、角色选择、并行委派、all-join、视觉返工、claim gate,Supervisor 共享核心身份、interaction / final-reply 专属合同及其组合,以及首批协作、delivery 收敛、manifest wait、试玩后续委派等 repair 自然语言合同;background planning 在 system composition 复用核心身份,所有 user context 都不再重复注入 Supervisor 身份合同正文。`agent_runtime_native_executable_tools()` 仍是原生可执行工具的权威源列表,同时供 Prompt 工具目录与 native capability registry 使用,MCP 工具只从当前请求的动态 catalog 暴露。最终 Provider 请求必须通过生成的 section、composition、overlay 与 provider fragment API 构建,禁止恢复直接 `include_str!("prompts/runtime/...")`、在 Provider 或 `prompt.rs` 源码中复制协作 graph 文案,或依赖自然语言精确 `.replace()` 注入工具合同、平台规则或角色规则。Bundle 不是完整可执行 graph:正式 DAG 依赖边、权限、沙箱、委派容量、持久 all-join 状态机、完成门和身份校验仍由 Rust、`shared-contracts` 与经校验的 `.agent/collaboration-policy.json` 强制执行,不允许通过 Skill、外部配置或任意运行时 Prompt 覆盖绕过。
@@ -239,7 +240,7 @@ Prompt 静态门禁必须断言上述 Bundle section 当前定义的权威语义
2026-07-14 V1.10 真实 `gpt-5.5` 验收:`process-session` 在无工具配方任务中完成 start / 3 次连续 cursor poll / stdin / terminate,41 条 task、75 条 event、63 条 Agent DB、8 条 receipt、4 套确认生命周期和唯一 completed / assistant,fixture launch 为 1,终态 PID / 端口、重放、重复与公共正文 / 密钥 / 诱饵泄漏均为 0。独立 Runner 强杀套件形成 21 条 task、34 条 event、36 条 Agent DB,新 boot 保持原 run / session,只产生 1 条 reconciliation,launch 仍为 1、PID reconnect / final / assistant / 重放 / 泄漏均为 0;两个 disposable 项目均已清理。
2026-07-14 起,同一文档的“V1.11 OS 强制工作区沙箱与通用项目命令”替代 V1.2 / V1.10 在 Linux 上的固定 program / 严格 argv 白名单边界。`command.exec / command.start` 继续接受结构化 `program + args + cwd`、沿用 confirm policy、durable action、revision、verification、输出和进程会话协议;`project.verify` 也必须复用同一 launcher,不能保留平行的宿主 npm spawn。Linux 只在受信任系统 bubblewrap 创建的 workspace-write sandbox 内启动真实命令:项目根可写,`.git / .agents / .codex / .hermes` 只读,`.agent` 不可见且不可写,项目外普通用户文件不挂载,网络 namespace 默认隔离,所有后代继承相同边界。program 只接受无路径分隔符的裸可执行名并从受信任 PATH 解析,argv 只保留数量、长度和控制字符硬限制;允许 `bash -lc`、Git、构建器、测试器和项目脚本在沙箱内自行工作。外部工具链环境根必须 canonicalize 后校验为窄工具链目录,禁止把整个 HOME 或其符号链接目标挂入沙箱。bubblewrap 缺失、不可执行或 setup 失败必须在项目命令执行前失败关闭,不允许退回宿主全权限。process record v2 与命令审计持久化真实 launch metadata,失败不能按平台静态冒充已建立沙箱。共享 `os-workspace-sandbox` capability 只标记 Linux;Windows 首版继续使用原固定白名单、隔离环境和 Job Object,不能宣称已达到同等 OS sandbox。deb / rpm 声明 bubblewrap 依赖,AppImage 依赖宿主预装且缺失时功能失败关闭;approval 与 sandbox 仍是两层独立门禁。
2026-07-14 起,同一文档的“V1.11 OS 强制工作区沙箱与通用项目命令”替代 V1.2 / V1.10 在 Linux 上的固定 program / 严格 argv 白名单边界。`command.exec / command.start` 继续接受结构化 `program + args + cwd`、沿用 confirm policy、durable action、revision、verification、输出和进程会话协议;`project.verify` 也必须复用同一 launcher,不能保留平行的宿主 npm spawn。Linux 只在受信任系统 bubblewrap 创建的 workspace-write sandbox 内启动真实命令:项目根可写,`.git / .agents / .codex` 只读,`.agent` 不可见且不可写,项目外普通用户文件不挂载,网络 namespace 默认隔离,所有后代继承相同边界。program 只接受无路径分隔符的裸可执行名并从受信任 PATH 解析,argv 只保留数量、长度和控制字符硬限制;允许 `bash -lc`、Git、构建器、测试器和项目脚本在沙箱内自行工作。外部工具链环境根必须 canonicalize 后校验为窄工具链目录,禁止把整个 HOME 或其符号链接目标挂入沙箱。bubblewrap 缺失、不可执行或 setup 失败必须在项目命令执行前失败关闭,不允许退回宿主全权限。process record v2 与命令审计持久化真实 launch metadata,失败不能按平台静态冒充已建立沙箱。共享 `os-workspace-sandbox` capability 只标记 Linux;Windows 首版继续使用原固定白名单、隔离环境和 Job Object,不能宣称已达到同等 OS sandbox。deb / rpm 声明 bubblewrap 依赖,AppImage 依赖宿主预装且缺失时功能失败关闭;approval 与 sandbox 仍是两层独立门禁。
2026-07-14 V1.11.1 第一切片:`command.exec / project.verify` 已共用受信任 trampoline launcher。bwrap 的 `child-pid` 只推进 child-created,`--block-fd` 放行后仍须收到 `SANDBOX_READY`;Runtime 完成 revision / verification durable callback 后才发送 `COMMIT_EXEC`,收到 `EXEC_ESTABLISHED` 后才计算业务 timeout。当前不把这套 stdin 私有控制通道用于 PTY;`command.start` 与 process record v3 仍是下一切片,相关链路完成前 V1.11.1 保持进行中。
@@ -1177,7 +1178,7 @@ game-project/
## 2026-08-20 Direct Codex 审核 Skill Pack 与受控工具内核
- 普通项目对话只由一个 project-bound Codex app-server thread 执行。客户端系统提示词只放最小工程合同、当前游戏源码有界快照、项目 prompts 和审核 Skill 索引;不再批量读取项目 `.codex/.agents/.hermes` Skill 正文,也不恢复 Supervisor、专业 Agent 或 harness。
- 普通项目对话只由一个 project-bound Codex app-server thread 执行。客户端系统提示词只放最小工程合同、当前游戏源码有界快照、项目 prompts 和审核 Skill 索引;不再批量读取项目 `.codex/.agents` Skill 正文,也不恢复 Supervisor、专业 Agent 或 harness。
- 首页恢复“做游戏 / 做素材 / 做方案”三个创作类型,默认“做游戏”。该选择与设置页的 Agent Runtime 模式无关;每次首页提交仍只自动创建一个新项目并进入项目工作台。用户正文原样进入项目对话,`game|art|doc` 仅作为受限结构化首轮上下文传给同一 Codex thread,不拼接“初始意图”文案、不产生首页对话、不切换 Provider 或恢复旧 Runtime 编排。
- `agc-skill-pack.v1` 只包含项目结构、陶泥儿美术、Web 游戏实现、真实浏览器试玩、客户端资源投影五项 Skill。清单记录用途、触发条件、所需工具、版本和内容 SHA-256;审核文本按 UTF-8 读取并将 CRLF 规范为 LF 后计算指纹和安装,避免混合换行造成 Windows / Linux 构建结果漂移,语义内容变化时必须同步重算对应清单指纹并提升版本。同步统一运行 `npm run agc:skill-pack:sync`,只读校验由 AGC `typecheck` 和 release build 自动执行,发现漂移时直接列出 Skill 与实际摘要,不让失配内容进入构建产物。客户端把审核文件安装到隔离目录后通过 app-server `skills/extraRoots/set + skills/list` 注册并复核,完整正文由 Codex 原生 Skill 机制按意图加载,一层引用只能经 `agc_read_skill_resource` 读取清单内 Markdown。引用路径按平台无关规则拒绝反斜杠、盘符、UNC、绝对路径和 `..`,不能依赖当前宿主的 `std::path` 语义判断其它平台路径。
- DirectProject 只连接客户端内置的 `agc_tools` STDIO MCP,工具固定为审核引用读取、标准陶泥儿美术准备、已登记资源有界查询、视频 / 角色动画 / 音效 / BGM 的 create-or-derive 语义生成、已登记图片去背景和 desktop/mobile 浏览器试玩。MCP 进程只做协议;真实浏览器与付费 External v1 调用通过随机 loopback 地址回到客户端主进程,因此不复制 GUI 登录态、开发者 Key、项目路径、revision、operation 或幂等键到模型上下文。已登记工具固定自动批准,但付费资源工具仍由客户端绑定稳定回合身份、限制单回合请求数、串行执行并优先恢复匹配账本;通用 shell、Codex 原生 webSearch、任意网络、多 Agent、插件和外部 MCP 继续关闭。`codex_app_server` 模式要求 `llm.webSearchEnabled=false`。
@@ -173,7 +173,7 @@ D9/D10 描述的「manifest ready-task 调度器在 Supervisor 下游启动策
| hydrate read-model schema | `plan-gdd-state-view.v1` |
| GDD 状态 | `draft \| ready_for_approval \| revision_requested \| approved \| rejected \| superseded` |
| 单项决定状态 | `confirmed \| default_pending \| prototype_pending` |
| 回答来源 | `user_option \| user_freeform \| default` |
| 回答来源 | `user_option \| user_freeform \| user_revision \| default` |
| 审计 recordType | `agent.runtime.plan.gdd_decided` |
| planning typed 指纹文本 | `sha256-serde-json-v2:<64 位小写十六进制>` |
| 现役 action/profile binding digest | `<64 位小写十六进制>`,无前缀 |
@@ -402,7 +402,7 @@ Runtime 注入并强校验以下精确结构:
- **轮次计数与上限**:本轮是第几轮由委派链上的 `clarification_round` 派生值决定(沿 `repair_of_delegation_id` 上溯推断,见第 23.5 节),上限 3;不再由 session 自行累加 `roundsUsed`。session 仍是 decisions 数组与 GDD 草稿内容的权威,但**不再是轮次状态机的权威**。
> **随之而来的合同影响 —— 2026-08-13 已全部收口。** 第 3 节注册表的 `plan-decision-checkpoint.v1` 与 request kind、第 8.6 节 `plan-session.v1` 的 `activeQuestion` / `roundsUsed` / `supersededCheckpointHandoffs`、第 9 节的 checkpoint domain 与 `supersededCheckpointProviderRequestIds`、第 12 节的 checkpoint stale 状态机、第 14 节与 activeQuestion 相关的恢复行,均已随本节重写一并删除或改写;第 9.1 节 golden vector 已按新 identity 重新生成(3857 bytes,`a59856de7e…`)。
- 用户明确输入优先于 Agent 默认;默认建议必须标为 `default_pending`,手感、节奏、镜头、可读性或重玩差异等需要验证的结论标为 `prototype_pending`。
- 用户明确输入优先于 Agent 默认;默认建议必须标为 `default_pending`,手感、节奏、镜头、可读性或重玩差异等需要验证的结论标为 `prototype_pending`。审批阶段的用户修改意见使用 `answerSource=user_revision`、`round=0`;Runtime 仅在 session 带 revise/reject 的 `lastDecisionRef` 时接受该来源。
- session revision 1 由 Runtime 先写入固定 `initial-request` 决定:topic=`初始需求`、state=`confirmed`、answerSource=`user_freeform`、round=0、answerSummary 精确等于规范化后的 1~400 scalar 初始用户需求。Provider 不能改写或省略这条来源记录;超过上限的初始输入先要求用户收束,不能截断。
### 5.2 决策卡
@@ -663,7 +663,7 @@ Provider 只能提交设计内容,不能提交或覆盖任何 Runtime 身份
该 input 及所有嵌套类型都使用 `deny_unknown_fields`;`game.platformFacts`、任意 `basis`、`projectId/gddId/version/submissionId/approvalRequestId`、action/run/session identity、时间与任何 fingerprint 一旦出现在 Provider input 中即返回 `PLAN_INVALID_REQUEST`。Runtime 在发出本轮 Provider request 前把当前 `sessionRevision/sessionFingerprint` 绑定进内部执行上下文,在项目锁内验证该 CAS 后,才把 project、GDD、版本、durable action、source/profile、session/run、时间、固定 `platformFacts`、全部 `basis:null` 与 fingerprint 注入 `plan-gdd.v1`。字段数量和文本限制按第 8.3 节对应 durable 字段执行。
input 中必须逐项包含并精确等于 source session 的全部 `decisionsSummary` 和 `prototypeValidationItems`,不得改变决定的 id/topic/state/answerSource/round/answerSummary,也不得改变原型项正文或顺序;每个已提问决定因此具有可验证的 1~3 轮来源。额外 decision 只允许是未提问默认:`default_pending + default + round=0`,且不能为它伪造 prototype item。唯一允许的 `confirmed + user_freeform + round=0` 是 Runtime 创建的固定 `initial-request`,其 answerSummary 精确等于初始用户需求。直接出稿因此可以合法使用 `roundsUsed=0`,但仍至少提交该初始 decision。
input 是当前 GDD 的完整快照,不要求与 source session 的 `decisionsSummary` 和 `prototypeValidationItems` 逐项相等。审批修订可用 `user_revision + round=0` 修改、删除或新增决定;未涉及内容由 Agent 以当前 GDD 为基线保持不变。Runtime 仍校验决定结构、原型项双射、`initial-request` 首项、身份和 CAS。payload 出现 `answerSource=user_revision` 时,当前 session 的 `lastDecisionRef.action` 必须是 `revise` 或 `reject`;首次提交、澄清续跑和没有待处理用户修订的普通质量返工返回 `PLAN_INVALID_REQUEST`。用户修订周期内的质量返工可以继续携带 `user_revision`,但其 planning child 必须直接继承当前 session 的 `latestDelegationId`,不得从旧 delivery 另起分支。该闸只作用于新版本 create,同 `submissionId` replay 不重判。唯一固定的 `confirmed + user_freeform + round=0` 是 Runtime 创建的 `initial-request`。
### 8.3 `plan-gdd.v1`
@@ -1152,15 +1152,7 @@ GDD handler 只能从已验证 batch binding 复制 `sourceSessionRevision/sourc
4. Provider transient failure/物理中断但 session、context 和 request slot 未变时,才沿用同一 base ID 的 attempt 派生规则。已知 retryable transport/upstream failure 先把旧 attempt durable 闭合为 `failed`;Runner/进程恢复只有在 boot/owner/lease 证据证明旧物理请求不再存活且无 handoff/batch 时,才闭合为 `interrupted`。旧终态写入、同步并回读成功后,才能创建 attempt N+1 的新 `started`;不能原地复用同一 providerRequestId,也不能让两个 started attempt 并存。无法证明旧请求已终止时进入 recovery required,不自动重发。每个 attempt 始终有独立 `started → completed|failed|interrupted` lifecycle。
5. 除第 1~2 项明确允许的同 binding `started + ready batch` 崩溃组合,以及上文 delivery 问题落盘/答案绑定的已消费证明外,binding 缺失/损坏、lifecycle 与 batch 不一致、同 revision 下 requestContextFingerprint 漂移、session 不是合法 successor,或 batch 已进入执行/等待状态时返回 `PLAN_NEEDS_RECONCILIATION`。此路径不自动删除、不补默认 binding、不重绑、不重试。
严格 submit input 被 Runtime 以 `PLAN_INVALID_REQUEST`、`PLAN_SESSION_DECISIONS_MISMATCH`(2026-08-21 补,见下)或由该输入导出的候选 GDD `PLAN_SIZE_LIMIT` 拒绝时,当前策划子 run 最多产生 **5 次** `plan.submit_gdd / rejected` observation:前 4 次关闭原 sole-action batch 后可在同一 run 续跑,让 Provider 根据最后一条 observation 修正;第 5 次仍须先完整落盘 rejected observation,再把该 run 终态失败,**不得**请求第 6 次 Provider tool-plan。该分类只针对本次 Provider input / 候选 GDD;读取既有不可变 GDD 或 receipt 时出现同名大小上限、既有 lineage 已达版本上限,或任何其它 durable authority 异常,一律是 `PLAN_NEEDS_RECONCILIATION`,不得消耗 Provider 重试额度。计数是 Runtime state 的 durable、每个 child run 独立的字段,进程重启不能清零;只有新建的策划 child run 才从 0 开始。它不依赖前端、Prompt 文字或 Provider 自报,且普通工具 observation 不计入。
**(2026-08-21)台账逐项比对失败从 `PLAN_SESSION_CAS_CONFLICT` 拆出为 `PLAN_SESSION_DECISIONS_MISMATCH`,并纳入上述可重试分类。** 第 8.2 节「input 必须逐项包含并精确等于 source session 的 `decisionsSummary` 与 `prototypeValidationItems`」这条校验(实现为 `planning_submit.rs` 的 `session_decisions_match_input`)原先与三条真 CAS 判据(`sessionRevision` 溢出、session 已被其它动作推进、Runtime source revision/fingerprint 无效)共用一个错误码,因此被 `plan_submit_error_is_business_rejection` 漏掉,一次不匹配即 `needs-reconciliation` 硬阻断整个策划子 Agent。
两者性质本就不同,按本节自己的判据即可区分:真 CAS 说明 **durable 权威**已变或已坏,重交同一份 input 不可能成功;台账不匹配时权威完好,错的是**本次 Provider input**——策划子 Agent 把决策摘要抄漏、抄错,或多追加了一条非 `default_pending` 决定。后者正是本节划归「本次 Provider input / 候选 GDD」的那一类。
**不变量未放松**:不匹配照样拒绝、照样不产生任何事实,只是拒绝的后果从「叫人核对」变成「回灌 rejected observation 让 Provider 改稿」,仍受同一个 5 次 durable 预算约束,第 5 次照常终态失败。伪造用户确认(追加 `confirmed + user_option`)等第 8.2 节禁止的写法一条都没有变得可行。
**触发这次拆分的实测**:策划子 Agent 连续三次 submit 撞形状层(`PLAN_INVALID_REQUEST`),每次都按回灌的理由改对一部分——机制运转正常;第四次形状终于合法,随即撞上台账比对这一支,直接 `needs-reconciliation`,整条链路零产物收场。即**越接近提交成功越容易撞上不给重试的门**,这与「5 次预算让 Provider 自行收敛」的设计意图直接冲突。
严格 submit input 被 Runtime 以 `PLAN_INVALID_REQUEST` 或由该输入导出的候选 GDD `PLAN_SIZE_LIMIT` 拒绝时,当前策划子 run 最多产生 **5 次** `plan.submit_gdd / rejected` observation:前 4 次关闭原 sole-action batch 后可在同一 run 续跑,让 Provider 根据最后一条 observation 修正;第 5 次仍须先完整落盘 rejected observation,再把该 run 终态失败,**不得**请求第 6 次 Provider tool-plan。该分类只针对本次 Provider input / 候选 GDD;读取既有不可变 GDD 或 receipt 时出现同名大小上限、既有 lineage 已达版本上限,或任何其它 durable authority 异常,一律是 `PLAN_NEEDS_RECONCILIATION`,不得消耗 Provider 重试额度。计数是 Runtime state 的 durable、每个 child run 独立的字段,进程重启不能清零;只有新建的策划 child run 才从 0 开始。它不依赖前端、Prompt 文字或 Provider 自报,且普通工具 observation 不计入。
第 2 项的自动前滚必须与 session successor、batch supersede/cleanup 和 replacement request 的 started 写入都在项目锁内按幂等步骤恢复;任一断点重启后只能继续相同步骤。这样合法 steer 能确定性替换旧输出,而身份污染不会被“自动恢复”掩盖。
@@ -1169,7 +1161,7 @@ GDD handler 只能从已验证 batch binding 复制 `sourceSessionRevision/sourc
main loop 不能把 submit 当成普通 action dispatch:在 durable action identity 建立后、生成普通 command ID 或进入 action executor 前,必须进入 `plan.submit_gdd` 专用分支。该分支重验 exact plan identity,执行下列提交与投影。**(2026-08-14 按 M1B-2 实现边界收口)** 本包只负责校验、定版、写不可变 GDD、重建 index、渲染 `game/fast_gdd.md`、安装 session successor 并终止策划子 run;**不创建 `.agent/planning/pending.json` / `gdd-approval` planning pending,不创建审批卡,也不把 Supervisor 或策划子 run 投影为审批等待**。`gdd-approval` pending 与 Supervisor 等待态属于 `M1C-1`,还要受第 13.0 节 `M1C-2a` 验收取证门约束。原 submit 在进入专用分支前已经建立的 generic `game-creator-pending-action.v5` standalone pending 与 `game-creator-provider-action-batch.v4` action batch 必须原样保留,作为后续 receipt/terminal observation 的同 action 恢复锚点;GDD create 成功不等于该 action 已 observed。
1. 解析第 8.2 节 strict input;在项目锁内重读 project identity、策划子 run 与委派根身份、Provider request 所绑定的 session CAS、canonical GDD 链及原 submit 的 generic v5 standalone pending / v4 batch anchors。不信任 Provider payload 中不存在也不允许出现的版本、时间、平台事实或身份;M1B-2 不读取或创建尚未实现的 approval receipt / planning pending。
2. 验证文本上限、轮次、决定状态和 prototype item 一一对应;`decisions` 必须先逐项等于 source session 的完整决定前缀,前缀之后只允许追加 `state=default_pending + answerSource=default + round=0` 的未提问默认决定,任何伪造为用户已确认的额外决定都按 session CAS 冲突拒绝。Runtime 注入固定 platformFacts 和所有 `basis:null`,以当前 durable actionId/裸 action fingerprint 作为 submission identity。
2. 验证文本上限、轮次、决定状态和 prototype item 一一对应;`decisions` 按本次完整 GDD 快照校验,不与旧 session 内容逐项比较。`round=0` 的非首项决定只能是 `answerSource=default`(默认建议)或 `answerSource=user_revision`(审批修改),分别对应允许的状态集合。`user_revision` 还要求当前 session 已有 `lastDecisionRef.action ∈ {revise, reject}`;没有该引用时不得把未确认项标成审批修改。已有 session 创建新的 planning child 时,`repairOfDelegationId` 必须精确等于旧 session 的 `latestDelegationId`;这条 continuation 游标约束在 Provider 请求前生效,防止旧 delivery 重新成为当前分支。Runtime 注入固定 platformFacts 和所有 `basis:null`,以当前 durable actionId/裸 action fingerprint 作为 submission identity。
3. M1B-2 尚无 receipt writer:只要已有任一 GDD,新的不同 submissionId 就返回 `PLAN_PENDING_GDD_EXISTS`;同 submissionId 只允许按历史 binding replay。`M1C-1` 接入有效 approve/revise/reject receipt 后,才把边界扩为“最新版本已有 receipt 才允许下一版本”。
4. 当前 M1B-2 的首次版本固定为 1;未来版本仍只能取最后一个连续有效版本加一,范围 1~128,不允许缺号或扫描任意文件补号。
5. 新提交由 Runtime 生成并冻结 `approvalRequestId/createdAtUtc`,填充全部 durable identity、source session binding 和时间,计算 GDD fingerprint,以第 10.1 节算法 create-only 发布 `gdd.v{N}.json`。同 submissionId replay 必须先找到并严格读取既有 GDD,复用其中 Runtime 生成的版本、request/time 与 identity 后再比较,不能用新时间制造假冲突。
@@ -1449,7 +1441,6 @@ type PlanGddError = {
| 'PLAN_UNSUPPORTED_KNOWLEDGE_BASIS'
| 'PLAN_CORRUPT_AUTHORITY'
| 'PLAN_SESSION_CAS_CONFLICT'
| 'PLAN_SESSION_DECISIONS_MISMATCH'
| 'PLAN_SESSION_RECOVERY_REQUIRED'
| 'PLAN_NEEDS_RECONCILIATION'
| 'PLAN_DURABILITY_FAILED'
@@ -1,8 +1,8 @@
# 【技术说明】AGC 接第三方 Provider 的兼容性缺陷
- 首次记录:2026-08-19
- 最新核对:2026-08-25,当前实现仍保留本文所述 Provider 分发约束
- 结论:**这不是单一策划链路的问题**。各创作流程共用同一套 Provider 分发;第三方端点必须满足当前 `agentMode`、`apiKind` 和工具调用协议约束。缺陷 4 已修复,其余限制仍按本文处理。
- 最新核对:2026-08-27,当前实现仍保留本文所述 Provider 分发约束
- 结论:**这不是单一策划链路的问题**。各创作流程共用同一套 Provider 分发;第三方端点必须满足当前 `agentMode`、`apiKind` 和工具调用协议约束。缺陷 4 已修复;`llm.stream=true` 时 Provider tool-plan 现在按配置发送流式请求并在后端聚合完整响应,前端展示合同不变。其余限制仍按本文处理。
---
@@ -14,6 +14,7 @@
| 2 | `codex_app_server` 模式把第三方端点喂给 codex | apiKind≠openai_responses 时秒挂;否则 413 + 工具误用,180 秒超时后留下待核对的孤儿请求 | 模式前提未被约束 |
| 3 | `provider` 模式下 `tool_choice=required` 与 DeepSeek 思考模式互斥 | 首个 tool-plan 请求 400,整个 runtime 起不来 | 参数空间缺一个值 |
| 4 | 普通 action 批次带 plan update 时,两条预检规则互斥 | 「更新计划 + 委派专业 Agent」同一轮返回就报「批次成员身份或顺序不匹配」 | **本分支回归**(已修) |
| 5 | `llm.stream` 只记录配置,不驱动 Provider tool-plan 传输 | 要求 `stream=true` 的网关第一发 tool-plan 得到 HTTP 400,整轮不可用 | 传输配置失效(已修) |
缺陷 1~3 叠加的结果:**当前代码里没有任何一组配置能让 DeepSeek 跑起来**。缺陷 4 与 provider 无关,换成 `gpt-5.6-terra` 打通 LLM 链路后才暴露出来。
@@ -291,3 +292,26 @@ let expected_member_plan_update = batch
- DeepSeek 网关 413 的具体阈值,以及 `provider` 模式下 AGC 自组的请求体是否也会触顶。
---
## 9. 缺陷 5:`llm.stream` 未作用于 Provider tool-plan(已修)
### 现象
`agentMode=provider`、`llm.stream=true` 时,审计与重试指纹记录 `stream=true`,但首个 tool-plan 仍调用 `LlmClient::run()`,请求体实际为 `stream=false`。只接受流式请求的 OpenAI 兼容网关返回 HTTP 400 `Stream must be set to true`;由于这是本地请求构造错误,重试同一请求无法恢复。
### 修复边界
Provider 的持久化重试分发与常规重试分发统一按 `llm.stream` 选择 `stream_run()` / `run()`。`stream_run()` 负责聚合文本、工具调用与终态,tool-plan 仍在响应完整后按现有协议解析、校验和交接;不把半截 tool-call 参数发布给前端,也不改变最终回复的 response-stream 合同。
### 回归
- `response_stream_uses_distinct_streamed_final_reply_for_responses_and_chat`:覆盖 Responses / Chat 两种 wire 的 tool-plan 与 final-reply 请求均发送 `stream=true`。
- `response_stream_disabled_keeps_direct_planning_reply_to_one_request`:覆盖 `llm.stream=false` 时 tool-plan 仍发送 `stream=false` 且保持单请求直接收束。
- `background_agent_runtime_executes_streamed_native_function_tool_plan`:覆盖 Anthropic tool-use 分片在 Shell Runtime 中聚合为原生工具动作,并完成 tool-plan 协议审计与动作执行。
- `platform-llm` 既有 Chat / Responses 流式工具调用聚合用例继续覆盖分片工具参数装配。
### 升级边界
升级前遗留的 durable retry sidecar 若是在旧实现(审计记录 `stream=true`、实际发送 `stream=false`)期间创建,升级恢复后会按当前配置真实发送流式请求。该行为修正了配置与 wire 行为的一致性,但不保证与升级前已发出的失败请求字节一致;排查跨版本恢复时以 raw failure log 的请求快照为准。
---