AGC Direct 回合:一条原生命令挂死后把写通道锁死到回合结束(direct-execution-draining) #529
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
背景
AGC 的 Direct 回合有一套宿主执行账本(租约 + 预算 + 封口),任何"新副作用"必须先
admit拿到租约才能写文件 / 跑命令 / 发起付费调用。当前实时观测到:一条原生命令挂死 → 租约永不结算 → 整轮所有写入被 100% 拒绝 → 交付根本无法开始。这不是模型不肯干活,也不是构建/环境问题。现象(2026-09-29 真实回合,可复核)
项目
gameagent-cfc64e7f81114787819ae39c10cbc2c2,用户诉求是"做一个飞鸟(Flappy Bird 风格)竖版飞行躲避游戏"。clientTurnId=783175b6-007f-4017-9dc4-f49431e5176d,账本createdAtMs=1790671041149taonier_prepare_game_art失败(2m07s):spritesheet 请求 4 片、只识别到 2 片 → 已由 #525 跟踪agc_generate_image全部成功并登记"…\WindowsApps\Microsoft.PowerShell_7.6.6.0_x64__8wekyb3d8bbwe\pwsh.exe" -Command "node -e \"…PNG 透明度探测…\"";tool-callcall_01_Jy0Q2FXDFOD5YBcJYRcc3886,status=running直到回合结束(5m40s 无终态、无任何输出)agc_remove_background×2 失败:remote-terminal-failed: 资源编辑生成失败(远端task-2b69dd51677e890e53e04bd8052504a0/task-cd6ce6758adbfdbe143cb24c6d9b1d98,请求到失败仅 3 秒;账本落phase=remote-failed、terminalFailureCode=remote-generation-failed)agc_write_file/agc_apply_patch+ 1 次agc_remove_background全部被拒,同一句话:direct-execution-draining: 当前批次正在收束,请等待在途操作结束Codex app-server 已退出;exitStatus=unknown;stderrClass=nonempty;stderrBytes=1944;stderrSha256=758997fa88ed53ba2745c3e94276b0885c3bd916675bdddfe8a965e5c9f36548;账本落phase=interrupted、active=[]结果:
game/game.js仍是 351 B 占位("还没有生成游戏…"),npm run build、双端视觉、generic-v1试玩三项验收全部无法执行;交付合同 4 项passed:false。证据路径
%APPDATA%\world.genarrative.ai-game-creator\projects\gameagent-cfc64e7f\.agent\conversations\tool-calls.jsonl(挂死命令原文、13 次拒绝原文、逐条 startedAt/updatedAt).agent\runtime\errors\error-1790671518931262000-4.json(draining 归类,metadata.tool=agc_apply_patch).agent\resource-edits\operations\{2c08714d-4e6d-4acc-9337-43a09cb8f0eb,6d9ae085-8f39-4b99-8c07-2e43fde9fda4}.json(远端失败终态)%APPDATA%\world.genarrative.ai-game-creator\direct-executions\1519caa29489b16ecaab01bbaf39adbbcc49d8e14aadb145978fb07724876cc5\f1eaefb90fb6a3fcd6972af4a45dccfe43e0d36e8a9560b05f61f9a84a1cc97d.json(账本终态)%APPDATA%\world.genarrative.ai-game-creator\diagnostics\application.log(16:47:59 连接终止行)根因
finish_lease命中(!passed && kind != Write)→phase = Draining(agent/direct_execution.rs:1153-1157)。agc_remove_background属EffectKind::Paid(agent/direct_tool_bridge.rs:2717-2718),两次失败即完成这一步。item/completed(拿到 exitCode)才finish_lease;这条命令走的是 codex 原生统一执行入口(常驻会话,二进制里可见Identifier of the running unified exec session.、"Bytes to write to stdin…"),只要会话不结束就永远停在running,active一直非空。admit_with_key里phase == Draining && !active.is_empty()→ 直接返回direct-execution-draining,写 / 补丁 / 付费 / 验证一律进不来(agent/direct_execution.rs:1055-1067)。只读工具不取租约,于是表现成"只读正常、写入全废"。MAX_ACTIVE=64只管容量(:14,1043);tick_locked只比总预算(:925-938,执行 900s / 整轮 1800s)。唯一出路是等整轮 30 分钟Exhausted,或模型自己放弃——本轮是后者。已在本机验证的机制:Windows 上
pwsh -NoProfile -Command -(脚本来自 stdin)在 stdin 保持打开时无限挂住(实测 >12s 不返回);命令串里用的是 POSIX 风格\"转义去嵌pwsh -Command "node -e \"…\"",在 PowerShell 语义下不成立,shell 一旦等 stdin 就再也不会结束。为什么现在没解(可观测性缺口)
write_stdin收尾。agc_*)里没有任何"停掉在途命令/放弃本批次"的动作。class/bytes/sha256,1944 B 内容不落盘,事后无法定性它为什么退出。拟改动(分三步,先落失败用例再改实现)
P0-a 租约墙钟兜底(宿主侧)
timeout_ms,缺省 3–5 分钟);到期由宿主主动按"失败 +needsReconciliation"结算该租约并落证据,不再让它继续拦新副作用。phase允许回到 Working,后续EffectKind::Write可受理;未成功结算的事实必须写进 evidence,不能静默当成功。P0-b 拒绝文案带出阻塞方
direct-execution-draining必须带上阻塞项的kind / tool / 会话或 item id / 已运行时长,并给出可执行解法(向该会话写入收尾、或显式放弃本批次)。P1 Draining 作用域收窄
Write不被无关的长Execute租约拦住,或提供一个显式的"放弃批次"动作让模型自救。P2 stderr 留证
.agent/runtime/errors/,供事后定性。验收判据
apps/ai-game-creator-shell/scripts/direct-execution-production-fixture.mjs增加例如native-hung,并加进scripts/run-agc-direct-execution-fixture.mjs默认用例表;现有 11 例completed/passes/mcp/mcp-write/native/native-resources/patch/deadline/native-session/restart/running必须继续全绿):agc_write_file能被受理;needsReconciliation事实,且账本没有把该轮记成成功。direct_execution/tests.rs增"挂死租约不永久拦写",且既有parallel_validation_shares_one_batch_and_failure_drains_before_repair、sealing_blocks_new_writes_and_requires_drain_and_process_proof不得被放松。npm run check:agc-direct-execution-fixture、npm run check:encoding、git diff --check。非目标
关联
drain()把模型报的 failed 改写成 interrupted、app-server 关闭原因可观测、阶段回归断言)——修的是终态与文案,不是"长租约永久拦写"I will solve this