重构策划agent,接入新工作流+harness #322
Reference in New Issue
Block a user
Delete Branch "design_agent_refactor"
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?
代码审查(branch
design_agent_refactorvsmaster)本 PR 用策划 Agent 运行时替换 Planning V2:阶段工作流、工作区工具、Responses 原生
output[]history replay,并抽出项目写锁分类和官方路由 AGC 模型选择。核心循环、崩溃/不确定工具恢复、工作区路径隔离、platform-llm回放整体连贯,测试覆盖也不差。合并前建议先修 4 个 bug:前端 retry / 阶段审批的 turn-id 与流式清理、
write_file静默空覆盖、顾问阶段工作区导轨错位。其余为建议项。统计:4 bug / 5 suggestion / 1 nit。下面按严重程度列,行内评论已挂到对应 diff。
Bug
App.tsx):前端 retry 换了新clientTurnId,后端DesignInput::Retry不begin_design_turn,事件仍带原session.turn.id,被前端丢掉,崩溃恢复/last-error 重试看不到 token 流和工具进度。App.tsx):decide_design_phase绕过executeDesignAgentTurn,finally不清planningV2TransientReply,批准后会在已持久化消息下残留重复气泡。write_file静默空覆盖(design_tools.rs):content缺失或非字符串时unwrap_or_default()写空文件却返回「已写入」。DesignWorkspacePanel.tsx):PHASES只有五段创作阶段,consultant的findIndex为 -1,rail 把概念设计标成当前。Suggestion
common-tail.md要求submit_phase_for_approval,顾问阶段又追加consultant-tail.md说不要提交,运行时也会拒绝,两段 tail 在 live system prompt 里互相打架。design_debug默认开启,把完整 history(含用户文本和 encrypted reasoning)写进{project}/.debug/design-agent/。ask_clarification文档写 2–4 个选项,执行器接受任意长度(含 0)。platform-llm把output_item.added与.done共用路径后,非function_call缺output_index会打挂整条流,影响非策划 Agent 的 Responses 调用方。Nit
ensure_design_session未使用且硬编码 model"quality",与selected_model_id不一致。核心 runtime / 回放 / 写锁分类可以合;前端 turn 身份、审批流、以及
write_file契约建议修完再合。[suggestion]
design_debug默认常开,把完整会话写进用户项目每次 provider attempt 都会把完整
session.history(以及后续 rawresponses_output)经后台线程try_send到{project}/.debug/design-agent/*.json。这是整段策划对话,含用户文本和 encrypted reasoning,背压只有 16 条 drop queue。建议:用 debug flag / build profile 门控,写到 app 私有诊断目录(对齐 provider-reconciliation dump),并排除出项目分享/导出。
[bug]
write_file对缺失/非字符串content静默空覆盖content用Value::as_str().unwrap_or_default()。字段缺失或是 object/array/number 时会写成空文件,却返回「已写入 {path}」。已有工作区文档会被空字节覆盖,模型还以为成功。建议:要求
content必须是 JSON string;缺失或非字符串返回Err。只有模型明确传""时才允许截断。[suggestion] consultant 阶段 system prompt 自相矛盾
每个阶段(含 consultant)都会追加
common-tail.md,要求必须调用submit_phase_for_approval。consultant 随后又追加consultant-tail.md,说没有下一阶段、不要提交。运行时也会拒绝 consultant submit(design_session.rs)。两段 tail 同时出现在 live system prompt 里。建议:
current_phase == "consultant"时跳过common_tail(或其中的审批句)。[suggestion]
ask_clarification的 options 契约与 schema 不一致tools.json写 options 为 2–4 项,执行器却接受缺失/空/Vec任意长度,并仍设置pending_clarification。0 选项卡片只剩 textarea;1 或 10 选项原样展示。除了第一个 wait 之后跳过剩余工具,没有「每 turn 一次澄清」的硬校验。建议:options 不在 2–4 就拒绝(或改 schema 允许纯自由文本)。空 options 若是有意的 fallback,描述里就不要写 2–4。
[suggestion] consultant 阶段 system prompt 自相矛盾
这个根本无所谓
[suggestion] 新注释在复述改动史,而不是短 invariant
这几处(以及约 1503 行、
write_lock.rs:443、project_gates.rs:1825)引用 Issue #318、叙述「原本零等待」和为什么挪到spawn_blocking。读的人需要的是类型/exhausted_projectionAPI 看不出来的契约,而不是设计史。建议:类型系统看不出的 WHY 留一行(例如 Windows
ACCESS_DENIEDvs UnixEACCES)。Issue 编号 /「原本零等待」叙述可以删。[nit]
ensure_design_session未使用,且硬编码 model"quality"若以后有人从 command path 调用,会和
continue_design_agent_at使用的selected_model_id不一致。建议:删掉,或接收真实 model id 并接到 command 路径。
[bug] Retry 会丢掉流式事件
这里用
designAgentTurnRef.current.clientTurnId过滤design-agent-update。Retry 会生成新的clientTurnId并写入 ref,但后端DesignInput::Retry不调用begin_design_turn,事件继续带session.turn.id(原 message id)。结果:崩溃恢复 / last-error 重试看不到 token 流和工具进度,直到 invoke 返回。也不能直接复用原 id:
design_command_replayed会拒绝用{type:"retry"}对上已存的{type:"message"}。建议:Retry 时先把
session.turn.id更新成新 command id 再发事件,或事件一律带当前 command id。前端测试应覆盖 retry 事件能匹配 in-flight command。[bug] 阶段审批绕过
executeDesignAgentTurn,不清 transientonDesignApprove自己invoke('decide_design_phase')。批准会启动下一阶段(LLM + tools),流式写入planningV2TransientReply,但这条路径不像executeDesignAgentTurn的finally(约 942 行)那样清理 transient。ProjectSupervisorView在 turn 结束后仍渲染{!directCodex && transientReply},最后一块 stream / tool 行会作为重复助手气泡留在已持久化消息下面。这是每次批准阶段后的 happy path。建议:
decide_design_phase走同一套 turn helper(设designAgentTurnRef、busy,并在finally清planningV2TransientReply),或至少在 apply/catch 后清掉。[bug] 顾问阶段导轨回落到「概念设计」
PHASES只有五段创作阶段。TDD 批准后currentPhase是consultant,findIndex为-1,Math.max(0, -1)变成0,rail 把概念设计标成当前、没有任何阶段标完成。DesignAgentSurface已有顾问文案,工作区 header 则回退到原始 id。建议:rail 纳入
consultant(或单独的「五段已完成」态),未知/consultant不要当 index 0。[suggestion] 非 function_call 的
output_item.added缺output_index会打挂整条流以前
response.output_item.added会忽略非function_callitem。现在与.done共用路径,任何 item 类型都要求output_index。兼容网关若对 message/reasoning 的output_item.added不带该字段,会 Deserialize/槽位失败并中断整条流,包括非策划 Agent 的 Responses 调用方。官方 OpenAI 带这个字段;这是平台级行为变化。建议:
function_call继续 fail-closed(回放需要)。其它 item 类型缺output_index时忽略该事件,不要失败整条流。复审补充:顾问态「做成游戏」没有切到 DirectProject
上次四个 bug(Retry 流式身份、审批 transient、
write_file空覆盖、顾问导轨)看起来都还在。这条是新问题。顾问态点「做成游戏」会写
.agent/runtime-mode.json、把工作台外壳切成游戏布局,并重挂 supervisor。但传给App的planningStartMode仍是startMode === 'planning',没有跟外壳一样用agentRuntimeMode === 'design'门控。startMode不会变,结果:App以策划模式重挂,directCodexProductRuntime被关掉。hydrate_design_agent_session因 sidecar 已是game返回null,策划会话被藏起来。useDesignAgentSurface仍为真,游戏工作台侧栏继续渲染空的策划控件(阶段回落到「概念设计」)。executeDesignAgentTurn;continue_design_agent_session不读 runtime-mode,顾问 Agent 继续跑。和提交说明「切换同项目 DirectProject、不自动发首轮」对不上。
8528c5ffc只压住了首轮 prompt,没有把App切进 Direct Codex。建议:
ProjectSupervisor的planningStartMode与外壳用同一条件:agentRuntimeMode === 'design' && startMode === 'planning'。continue_design_agent_session/decide_design_phase在active_runtime == "game"时直接拒绝,不要只挡 hydrate。continue_design_agent_session。[bug]
continue_design_agent_session不读 runtime-modehydrate_design_agent_session在active_runtime == "game"时返回None,但这条续轮入口没有同样的检查。做成游戏之后前端如果仍误走策划 turn(当前WorkspaceLauncher就会),顾问 Agent 会继续跑。decide_design_phase_at同样没挡。建议两处在active_runtime == "game"时直接拒绝,不要只挡 hydrate。[bug] 顾问态「做成游戏」只换了外壳,对话仍停在策划 Agent
上面工作台外壳的
planningStartMode已经用agentRuntimeMode === 'design' && startMode === 'planning'门控(约 352 行)。点「做成游戏」后agentRuntimeMode变成game,外壳切到游戏工作台。这里传给
App的仍是startMode === 'planning'。startMode不会变,所以重挂后的App仍是策划模式:directCodexProductRuntime关着,hydrate 因 sidecar=game返回空,useDesignAgentSurface仍为真,侧栏变成空的策划控件(阶段回落到概念设计),发消息继续走executeDesignAgentTurn。建议与外壳用同一条件:
agentRuntimeMode === 'design' && startMode === 'planning'。评审结论:Request changes
问题清单:1 阻塞 / 4 重要 / 7 建议 / 6 细节。每条给出「位置 — 问题 — 影响 — 建议」。
一、阻塞(Blocking)
B1 首页「做方案」新建项目后,首轮消息不会进入策划 Agent
apps/ai-game-creator-shell/src/features/app-shell/WorkspaceLauncher.tsx:61-63、:88-93、:385-388;配合apps/ai-game-creator-shell/src/App.tsx:270、:6444-6497agentRuntimeMode初值恒为'game',仅在 render 之后的 effect 中跟随currentProjectContext同步,因此项目上下文出现的第一帧planningStartMode为false。此时ProjectSupervisor先以游戏 lane 挂载,App.tsx:6444-6497的自动首轮 effect(directCodexProductRuntime为真时不 return)把首轮 prompt 发给 Direct Codex;随后 lane 切到'design'触发重挂,但首轮 claim 记录在跨实例共享的initialSupervisorMessageClaimsByPage中,已被前一实例消耗,重挂后的策划实例不再发送首轮。continue_design_agent_session从未被调用,新策划链路在真实入口上不可用(用户会看到策划工作台打开但 Agent 不工作,或项目被 Direct Codex 抢跑)。routes 做方案 false/true creation to the design agent、keeps 做方案 first turn on Supervisor without a Direct attachment sidecar、surfaces the planning clarification card after 做方案 creates the project from home(CI job 7182/7183/7185,本机npx vitest run apps/ai-game-creator-shell/tests/appSurface.test.ts复现4 failed | 386 passed (390))。invoke调用序列出现chat_with_game_creator_direct_codex,而continue_design_agent_session一次都没有出现。:385-388临时改为仅按currentProjectContext.startMode === 'planning'派生后,4 个用例全部转绿(诊断改动已还原)。planningLaneActive = currentProjectContext?.startMode === 'planning' && runtimeOverride !== 'game'(runtimeOverride仅在用户点「做成游戏」时置为'game');无论采用哪种写法,都要保证 lane 切换时首轮 claim 不被上一个 lane 消耗(例如把 claim 归属到projectPath + lane,或在 lane 切换时重置)。二、重要(Major)
M1 顾问阶段同时收到“必须提交审批”和“不需要提交审批”
apps/ai-game-creator-shell/src-tauri/design-agent/phase-context/common-tail.md:6、phase-context/consultant-tail.md:4;执行侧src-tauri/src/agent/runtime_protocol/design_session.rs:284-286common-tail.md每个阶段都会追加(design_tools.rs:159-161),其中要求“必需产物完成后必须提交阶段审批”;顾问阶段再追加的consultant-tail.md明确“顾问阶段没有下一层,也不需要提交阶段审批”。同一份 live system prompt 内两条相反指令并存,而运行期submit_design_phase_for_approval在consultant会直接报 “顾问态不提交阶段审批”。common-tail.md增加“顾问阶段除外”,或顾问阶段不再追加common-tail.md。M2
resources/skills/tdd.md是五册串联,且含与本阶段冲突的红线(需确认是否原型基线)src-tauri/design-agent/resources/skills/tdd.md:1,100,275,459,641,748,红线出现在:259(同族:453、:626);登记于resources/catalog.json(skills.tdd为 tdd 阶段唯一注入资源):259一带是概念层红线“出现具体数值、按键、界面即删”,而 tdd 阶段的目标恰恰是产出数值、配表与字段字典。M3 会话 history 无上限 + 64MB sidecar 上限会让会话永久写不进去
src-tauri/src/agent/runtime_protocol/design_session.rs:13、:102-111;写入侧src-tauri/src/agent/runtime_protocol/json_sidecar.rs:122-135;调用点src-tauri/src/agent/design_runtime.rs:250-254DesignSession.history会累积全部 Responses 原生 output 与工具结果,每个 checkpoint 全量序列化;DESIGN_SESSION_MAX_BYTES超限时直接返回“超过 64MiB 上限”,没有任何裁剪、压缩或降级路径。M4
resources/SKILL.md是原型方案残留,会随安装包发布src-tauri/design-agent/resources/SKILL.md:1,5,9-13;打包映射src-tauri/tauri.conf.json:34-36ask_user/finish(summary)这类生产工具集中不存在的工具;附录 A 五册在文件内重复两次,且与resources/skills/*.md逐行重复。我核对了design_tools.rs的读取逻辑(只读system-prompt.md/tools.json/resources/catalog.json/phase-context/*),确认它没有任何运行期调用方。三、建议(Minor)
S1 dev 启动脚本默认把完整 history 写入用户项目
apps/ai-game-creator-shell/scripts/start-tauri-dev.mjs:109-115;写入侧src-tauri/src/agent/design_runtime.rs:465-492GENARRATIVE_AGC_DESIGN_DEBUG=1,design_debug会把session.history(含用户文本与reasoning.encrypted_content)写到{project}/.debug/design-agent/*.json。方案文档只承诺.debug是“可删除、不阻塞”的旁路,但默认开启意味着本地开发必然写入真实项目目录。S2
App.tsx中一批策划工作区接线没有 UI 出口src/App.tsx:572-578、:11663-11665、:11740-11760、:912-960(refreshDesignWorkspace);消费侧src/features/project-workspace/DesignAgentSurface.tsx:38-46designWorkspaceFiles/designPreviewPath/designPreviewText/onDesignOpenFile/onDesignClosePreview一路传下去,但DesignAgentSurface既不解构也不渲染这些 props(文件浏览实际由左栏DesignWorkspacePanel承担)。list_design_workspace,结果无人使用;同时留下“这套接线到底该不该存在”的维护歧义。S3 注入文档引用的“配套文件”在资源包内不存在
resources/skills/concept.md:7-8(另有top_design.md、architecture.md、systems.md、tdd.md同族引用);模块层resources/modules/system-types/06_战斗与敌人/SKILL.md:5-6模板_概念设计.md、例子_星露谷_概念设计.md、例子_星露谷_分析.md等名称,包内真实文件是templates/concept-design.md、exemplars/stardew-concept.md、templates/stardew-analysis.md;模块层还写着“与总纲..\SKILL.md配套”“本目录例子_星露谷_系统设计_S06战斗.md”,两者都不存在(总纲实为resources/skills/systems.md,范例实为exemplars/stardew-s06-combat.md)。list_resources拿到逻辑 ID,而tools.json明确要求“不要猜测物理路径”,两者相加会诱发必然失败的read_file。S4 速览卡存在两套互相矛盾的结构
phase-context/overview-card.md:1(正文 10 节)与resources/exemplars/overview-card.md:3,54phase-context/overview-card.md为准收敛范例表述。S5
tools.json声明与执行器行为有偏差src-tauri/design-agent/tools.json:4,5,7,11,12;执行侧design_runtime.rs:284-302、design_tools.rs:11,206-208,279-283,468-475,554-585ask_clarification声明“选项数 2-4”“每轮最多一次”,实际无任何校验(0/1/5+ 都可,UI 直接按数组渲染);search_text200 条命中被静默截断;patch_file文件不存在时返回Ok("局部修改失败:文件不存在"),design_tool_line会把它渲染成看起来成功的“局部修改:path”;list_dir.path声明必填而运行期默认为.;read_resource描述里的“未实现占位文档”在包内不存在。S6 策划回合没有取消入口与预算约束
src-tauri/src/agent/design_runtime.rs:693-718(run_design_loop)S7 官方 router 模型来源变更是跨模块影响,需要说明与后端确认
src-tauri/src/config.rs:96、:207-215OFFICIAL_LLM_ROUTER_MODEL = "gpt-6-astra",官方 router 路径改用llm.model(AGC 模型目录 ID,例如quality)并新增x-genarrative-client: agc头。api-server 侧已有该头解析(非本 PR 新增),但这条改动影响所有走官方 router 的 Agent,不只是策划。四、细节(Nit)
DesignWorkspacePanel.tsx:330-334:Math.max(0, PHASES.findIndex(...))会把未知阶段静默显示成“概念设计”,建议显式处理未知值。DesignAgentSurface.tsx:48:view === null(尚未 hydrate)时也把阶段兜底成concept并渲染“概念设计”,实际会话可能已在tdd;建议无 view 时先显示加载态。DesignWorkspacePanel.tsx:345,402,452:出现“Agent 产生的策划文档会显示在这里。”“文档会在这里按普通 Markdown 方式预览。”等功能说明文案,与AGENTS.md“UI 面板中不要默认写功能说明、规则描述或开发解释文案”冲突。design_tools.rs:130-133:注入资源缺失/为空时静默continue,没有任何诊断记录,与方案文档第 176 行“只记录诊断并继续请求 Provider”不符。resources/catalog.json:47 条summary为同一句模板文案,list_resources的“简介”无区分度,Agent 只能靠标题猜内容。skill-pack:check只覆盖 Codex skill 包,策划资源包的“目录 / 登记表 / 注入阶段”一致性没有检查;本次我逐条核对了 52 条登记(无重复 ID、path 全部大小写精确存在、无未登记文件、无空文件),建议补一个轻量脚本把它固化下来。五、已核对通过的部分
npm run check:encoding(4394 文件)、git diff --check、两个 manifest 的cargo fmt --all -- --check均通过。Repository checks中的npm run lint全链通过(脚本按序执行到了测试步骤),CIBackend tests通过(含platform-llm新增的原生回放用例)。design_runtime.rs:162-171)、审批 transient 清理(App.tsx:11700-11715)、write_file空覆盖(design_tools.rs:255-264)、顾问阶段导轨(DesignWorkspacePanel.tsx:16-23);ensure_design_session遗留也已清理。platform-llm的 Responses 原生回放在实现上很干净:responses_input/responses_output只在原生模式生效(store=false+include=reasoning.encrypted_content),legacy 路径不受影响,neutral adapter 与validate_for_transport都做了拒绝;流式增量按output_index累积、completed 仅在有非空output[]时覆盖,用例覆盖到位。normalize_relative_path拒绝绝对路径 /../ 反斜杠,resolve_local_project_path逐段拒绝符号链接与 Windows reparse point,删除与遍历跳过链接,项目写锁 + 活跃锁 + 错误脱敏一致沿用。六、合并前建议
@@ -111,1 +112,3 @@env: withAgcDevEndpointEnv(endpoint),env: {...withAgcDevEndpointEnv(endpoint),[AGC_DESIGN_DEBUG_ENV]: '1',S1(建议):dev 下硬编码开启设计调试,会把含用户文本与
reasoning.encrypted_content的完整 history 写进{project}/.debug/design-agent/*.json。建议改为显式 opt-in。@@ -0,0 +1,4 @@顾问阶段不需要继续自主推动项目或主动安排下一步;遵照用户的具体指示行动。根据用户指示回答问题、读取相关文档、修改工作区文件,并说明改动可能影响的已有产物。涉及方向性变化或多个可行方案时,先向用户说明影响并等待用户决定;不要替用户做决定。顾问阶段没有下一层,也不需要提交阶段审批。M1(重要):本行与
phase-context/common-tail.md:6的“必须提交阶段审批”在同一份 live system prompt 内互相矛盾(common-tail.md每个阶段都会追加),运行期还会硬拒绝(design_session.rs:284)。建议二选一:common-tail增加“顾问阶段除外”,或顾问阶段不再追加common-tail。@@ -0,0 +256,4 @@## 七、红线(只有三条)1. 不冒充用户决定:用户没说的方向标"待确认",正文不写死。2. 不越层:出现具体数值、按键、界面即删。M2(重要):该文件实为五册串联(833 行 / 52KB,
catalog.json中 tdd 阶段唯一注入资源),本行一带是概念层“出现具体数值、按键、界面即删”红线,与 tdd 阶段必须产出数值、配表与字段字典的目标冲突,且每轮多注入约 2 万 token。请确认是否为原型基线;若否,建议只保留 TDD 总册段。@@ -11435,2 +11660,4 @@onPlanGddDecision={decidePlanGdd}planningLane={planningV2Active}designView={useDesignAgentSurface ? designAgentView : null}designFiles={designWorkspaceFiles}S2(建议):
designFiles/designPreviewPath/designPreviewText/onDesignOpenFile/onDesignClosePreview在DesignAgentSurface.tsx:38-46中并未被解构使用(文件浏览实际由左栏DesignWorkspacePanel承担),属死接线,且每轮事件会多打一次list_design_workspace。建议删除或真正接通。@@ -350,3 +385,2 @@currentProjectContext.startMode === 'planning'}planningStartMode={planningStartMode}playRequest={playRequest}B1(阻塞):策划 lane 判定依赖渲染后才同步的
agentRuntimeMode(初值恒为game),首帧planningStartMode为 false,导致ProjectSupervisor先以游戏 lane 挂载并消耗掉首轮 claim。详见评审正文 B1(含调用序列实测与验证)。建议改为渲染期派生(startMode === 'planning' && runtimeOverride !== 'game'),并保证 lane 切换时首轮 claim 不被上一 lane 消耗。代码审查意见
整体结构清晰:会话崩溃恢复(executing 标记 + 检查点重放)、命令幂等、路径安全复用既有
resolve_local_project_path/normalize_relative_path护栏、工具白名单与 tools.json 一一对应、契约侧responses_input在 neutral adapter 有明确拒绝兜底,测试覆盖也比较到位。以下问题按严重度排序:需要修复
1.
App.tsx审批回调缺少项目切换防护(中)executeDesignAgentTurn的.then/.catch里都有localProjectPathRef.current !== nextProjectPath的检查,但onDesignApprove的decide_design_phase回调没有:applyDesignView会写setMessages、savedConversationProjectPathRef、latestMessagesRef等会话级状态。真实场景:用户点「批准」后审批请求在途(审批通过会触发下一轮完整 Agent 循环,可能耗时几十秒),此时切到另一个项目,旧项目的 DesignView 会被套用到新项目的对话状态上,且savedConversationProjectPathRef被写成旧项目路径,后续会话保存归属错乱。建议补上与executeDesignAgentTurn一致的 ref 检查。2.
upsert_responses_output_item对上游 slot 无上界保护(低-中)server-rs/crates/platform-llm/src/lib.rs:output_index来自上游 SSE 事件,属不可信输入。AGC 支持用户自配 OpenAI-compatible endpoint,一个异常/恶意的 provider 发output_index: 2^40会让resize尝试巨额分配直接 abort 进程。建议加一个合理上限(如 slot > 1024 时按错误事件处理或忽略)。建议修复
3.
ask_clarification同轮重复调用会静默覆盖(低)tools.json 里写了「每轮最多调用一次」,但
execute_design_tool未兜底:同一批次里模型连续调两次ask_clarification,第二次会直接覆盖session.pending_clarification,而第一次的function_call_output已经告诉模型「waiting_for_user + 第一个问题」。结果模型以为用户在回答第一个问题,用户看到的卡却是第二个,后续Clarification输入按request_id匹配的是第二个问题,上下文错位。建议第二次调用返回错误(如「当前已有待回答的澄清」),与submit_phase_for_approval的幂等返回已有请求保持一致。4. 策划项目会话损坏后无法打开项目(低)
项目打开链路里
hydrateDesignAgentSession抛错且planningStartMode为真时直接throw,整个打开流程中止。read_design_session的 schema 校验失败(如 64MB 超限写入中断留下的半截文件、手改过的 session.json)会把项目彻底锁死,UI 没有恢复入口。建议 hydrate 失败时降级为「会话损坏,可重新开始策划会话」,而不是阻断项目打开。5. 会话历史无界增长(风险项,可不本 PR 处理)
session.history每轮累积完整原生 output(含 reasoning encrypted_content、function_call_output的完整文件内容),commands只增不减。两个后果:长会话(尤其 consultant 阶段反复迭代)token 上下文最终会爆;session.json 超过 64MB 上限后checkpoint_design每次写盘都失败,回合卡死在错误态。建议记入后续事项:历史压缩或 commands 淘汰策略。提示性意见
6.
planningV2Reasoning是死状态:design_event里reasoning_text恒为None,前端setPlanningV2Reasoning永远不会被触发,且resetTerminalPlanningConversation也没有清它。既然是「预留」,建议要么接上 reasoning 增量事件,要么先不加这段状态和designReasoning展示,避免后续接线的以为已通。7. 调试开关默认开:
start-tauri-dev.mjs里GENARRATIVE_AGC_DESIGN_DEBUG除非显式设为'0'否则一律按'1'注入,dev 下默认出现「快速准备做成游戏测试」按钮并写.debugdump。如果是有意的 opt-out 设计建议在文档里写一句;否则建议改成显式'1'才开。8. UI 说明文案:
DesignWorkspacePanel头部的「Agent 产生的策划文档会显示在这里。」和 project-development 里的「持续协作推进设计」属于 AGENTS.md「UI 面板中不要默认写功能说明、规则描述」约束覆盖的文案,建议移除(空态引导文案可保留)。9.
search_text空 query:"".contains恒真,空 query 会把工作区每行都当命中直到 200 上限。建议在 executor 里拒掉空query。这个问题描述的风险在抽象上成立,但对当前生产代码来说,实际链路已经有 Runtime 兜底,不会出现同一批次第二次
ask_clarification覆盖第一次的问题。当前处理顺序是:
process_design_batch每次只取一个工具调用;第一次
ask_clarification执行后写入session.pending_clarification;随后计算:
因为已经进入等待状态,剩余调用会被标记为:
pending_batch被清空,当前回合停止。所以即使 Provider 在同一批 Responses 输出中返回多个
ask_clarification:execute_design_tool;pending_clarification;需要区分两点:
execute_design_tool本身没有“已有澄清请求时拒绝覆盖”的独立保护;process_design_batch串行收束,并在第一个等待工具后停止剩余调用。因此这条审查意见更准确的结论是:工具函数局部缺少防御,但当前批处理 Runtime 已经提供了有效门禁,描述中的实际错位场景在现有链路不会发生。
如果要进一步增强,可以在
ask_clarification分支再加一个极小的保险判断:但它主要是防止未来新增其他调用路径,当前不属于必须修复的生产 bug。