修复资源编辑分支CI失败
Project CI / Repository checks (pull_request) Successful in 1m28s
Project CI / Frontend tests (pull_request) Successful in 2m54s
Project CI / Backend tests (pull_request) Successful in 3m55s
Project CI / Native shell tests (pull_request) Failing after 10m25s

补齐资源依赖图的 sortMode Hook 依赖
统一后台 Agent 使用专用 Runtime worker,避免默认栈溢出
同步更新 Runtime 技术方案与踩坑记录
This commit is contained in:
2026-08-11 10:16:27 +08:00
parent cf81a71dce
commit 7786fd1efc
5 changed files with 23 additions and 21 deletions
@@ -227,8 +227,8 @@ pub(crate) fn spawn_started_game_creator_agent_background_task_drain_with_lock(
let (first_poll_sender, first_poll_receiver) = std::sync::mpsc::sync_channel(1);
let (runtime_lock_sender, runtime_lock_receiver) = std::sync::mpsc::sync_channel(1);
let worker_name = format!(
"agent-ready-task-{}",
sanitize_agent_runtime_text(&agent_id, 48)
"agent-runtime-worker-{}",
sanitize_agent_runtime_text(&agent_id, 44)
);
if let Err(error) = std::thread::Builder::new()
.name(worker_name)
@@ -252,7 +252,7 @@ pub(crate) fn spawn_started_game_creator_agent_background_task_drain_with_lock(
})
{
return Err((
format!("创建 Agent Runtime child execution worker 失败:{error}"),
format!("创建 Agent Runtime 后台执行 worker 失败:{error}"),
runtime_lock,
));
}
@@ -261,13 +261,13 @@ pub(crate) fn spawn_started_game_creator_agent_background_task_drain_with_lock(
.is_err()
{
return Err((
"Agent Runtime child execution future 未在 2 秒内开始轮询".to_string(),
"Agent Runtime 后台执行 future 未在 2 秒内开始轮询".to_string(),
runtime_lock,
));
}
if let Err(error) = runtime_lock_sender.send(runtime_lock) {
return Err((
"Agent Runtime child execution future 在接管执行锁前已退出".to_string(),
"Agent Runtime 后台执行 future 在接管执行锁前已退出".to_string(),
error.0,
));
}
@@ -506,19 +506,20 @@ pub(in crate::agent) fn start_game_creator_agent_background_task_with_link_in_se
let result =
read_game_creator_agent_runtime_for_session_at(root, &agent_id, Some(&session_id))?;
let root = root.to_path_buf();
let background_agent_id = agent_id.to_string();
let background_task = next_task.task;
tauri::async_runtime::spawn(async move {
let _runtime_lock = runtime_lock;
drain_game_creator_agent_background_tasks(
if let Err((error, _runtime_lock)) =
spawn_started_game_creator_agent_background_task_drain_with_lock(
root,
background_agent_id,
agent_id,
background_task,
state,
state.clone(),
runtime_lock,
)
.await;
});
{
let error = format!("Agent Runtime 后台执行 worker 启动失败:{error}");
let _ = fail_game_creator_agent_runtime_turn_at(root, state, &error);
return Err(error);
}
Ok((result, run_id))
}
@@ -694,6 +694,7 @@ export default function ProjectDevelopmentView({
resourceGraphInputs,
resourceGraphProjectScopeKey,
resourceGraphScopeKey,
sortMode,
]);
const resourceGraphScopeMatches =
@@ -4250,13 +4250,13 @@
- 处理:先以 CAS 单独 commit `queued -> executing`,成功后才调 ToolHost;调用返回后再 commit observation。恢复见到 executing 或 ToolHost 返回 Unknown 时只能进入 reconciliation,不得自动重执行。重复 resume 不得继续增 revision 或重复 event。
- 验证:在“ToolHost 已调用、observation commit 失败”处注入故障,序列化快照并用新 engine 重载;断言重复 resume 后 ToolHost 计数仍为 1,且只有显式 reconcile observation 才恢复 running。
## Runtime pending 恢复不能让大型 async frame 共用默认 worker 栈(2026-08-03
## Runtime 后台执行不能让大型 async frame 共用默认 worker 栈(2026-08-03
- 现象:Supervisor collaboration durable isolated spawn 恢复测试在默认 Tokio worker 栈下稳定 `stack overflow`;单独运行同样失败,提高 `RUST_MIN_STACK` 后通过。
- 原因:不是业务递归。debug 构建中 pending action continuation、后台 task queue 和 Agent 主循环各自形成大型 async poll frame;恢复路径在同一次 poll 调用链直接进入下一层状态机,累计超过 worker 默认栈。
- 处理:整个 pending continuation、它进入的后台主循环,以及完成、取消或失败后 drain 同 Agent 后续队列时,都必须跨越独立 Tokio task 轮询边界,使上层 poll 先退栈后再轮询下一层状态机。传入边界的 future 必须先装箱;若泛型 helper 直接持有大型 future,即使随后 `spawn`,调用方 async frame 仍会把它保留在默认 worker 栈上。边界必须保留结构化取消语义;当前使用 boxed future 与 `JoinSet`,父 continuation 被丢弃时同步 abort 子任务。不得只增大 CI 的 `RUST_MIN_STACK`,否则生产默认栈仍可能崩溃。
- 验证:失败用例必须在未设置 `RUST_MIN_STACK` 时通过;同时覆盖 policy batch 全组、拒绝 pending 后重规划并 drain 下一任务,以及 pending/cancellation 回归,证明恢复不重复生成 isolated spawn、队列继续推进且父任务取消不遗留后台子任务。
- 关联:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_driver/pending_execution.rs`
- 现象:Supervisor collaboration durable isolated spawn 恢复测试或普通 `agent.delegate` 后台委派测试在默认 Tokio worker 栈下稳定 `stack overflow`;单独运行同样失败,提高 `RUST_MIN_STACK` 后通过。
- 原因:不是业务递归。debug 构建中 pending action continuation、后台 task queue 和 Agent 主循环各自形成大型 async poll frame;恢复路径直接进入下一层状态机,或普通后台任务把完整主循环直接放到默认 worker,都会超过默认栈。
- 处理:整个 pending continuation、它进入的后台主循环,以及完成、取消或失败后 drain 同 Agent 后续队列时,都必须跨越独立 Tokio task 轮询边界,使上层 poll 先退栈后再轮询下一层状态机。传入边界的 future 必须先装箱;若泛型 helper 直接持有大型 future,即使随后 `spawn`,调用方 async frame 仍会把它保留在默认 worker 栈上。普通后台任务、静态委派子任务和 manifest ready-task 的首次执行统一复用 16 MiB 专用 Runtime worker,并在 worker 已启动后交接 Agent 任务锁;worker 创建或交接失败要持久化当前 run 失败。pending 边界继续保留结构化取消语义,父 continuation 被丢弃时同步 abort 子任务。不得只增大 CI 的 `RUST_MIN_STACK`,否则生产路径仍可能崩溃。
- 验证:失败用例必须在未设置 `RUST_MIN_STACK` 时通过;同时覆盖普通后台委派、policy batch 全组、拒绝 pending 后重规划并 drain 下一任务,以及 pending/cancellation 回归,证明任务锁只交接一次、恢复不重复生成 isolated spawn、队列继续推进且父任务取消不遗留后台子任务。
- 关联:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_driver/task_start.rs``apps/ai-game-creator-shell/src-tauri/src/agent/runtime_driver/task_queue.rs``apps/ai-game-creator-shell/src-tauri/src/agent/runtime_driver/pending_execution.rs`
## Provider 可扩展不能用一个全局 protocol 枚举代替实例隔离
@@ -825,7 +825,7 @@ game-project/
- 开发模式可通过本地项目文件面板执行 `file.list/read/write/delete`,普通用户界面不暴露文件面板。
- 2026-07-17 起,同一 Runtime 文档的“V1.32 Runtime 强制 Supervisor 协作合同”作为 mixed swarm 可靠性事实源。项目可用 `.agent/collaboration-policy.json` 约束首波 static/isolated 模式、数量和 required static AgentRuntime 在任何 child 副作用前整批校验并把合同指纹固化进 Provider batch v2。当前父 run 一旦形成 delivery/group,正式 `project-supervisor` 默认只负责编排、状态认领和验证,不再直接执行项目 mutation;专业 Agent/isolated child 权限与唯一 Supervisor 最终回复边界保持不变。
- 2026-07-17 V1.32 最终代码已完成独立真实 Provider PASS:首批 mixed batch、三 isolated child、Runner 强杀恢复、专业返工、宿主验证、唯一最终回复与零重复/残留/泄漏同时成立。真实报告计数、隔离重试配置和仍待收敛的 tool-plan repair 成本统一以 Runtime 文档 V1.32 章节与共享决策记录为准。
- 2026-08-03 恢复执行补充约束:整个 pending action continuation、它进入的后台主循环,以及完成、取消或失败后 drain 同 Agent 后续队列时,都必须跨越独立 Tokio task 轮询边界,不能让 pending executor、task queue 与 Agent 主循环的大型 async poll frame 在同一 worker 调用栈连续嵌套。边界输入必须先装箱,避免泛型 helper 在真正 spawn 前仍把大型 future 保留在调用方 async frame;边界同时必须随父 continuation 取消子任务并保持 durable action、batch、run/session 身份及恢复防重语义,当前使用 boxed future 与 `JoinSet` 承担该约束。CI 和生产均使用默认 worker 栈验证,不以提高 `RUST_MIN_STACK` 代替代码边界。
- 2026-08-03 恢复执行补充约束:整个 pending action continuation、它进入的后台主循环,以及完成、取消或失败后 drain 同 Agent 后续队列时,都必须跨越独立 Tokio task 轮询边界,不能让 pending executor、task queue 与 Agent 主循环的大型 async poll frame 在同一 worker 调用栈连续嵌套。边界输入必须先装箱,避免泛型 helper 在真正 spawn 前仍把大型 future 保留在调用方 async frame;边界同时必须随父 continuation 取消子任务并保持 durable action、batch、run/session 身份及恢复防重语义,当前使用 boxed future 与 `JoinSet` 承担该约束。普通后台任务、静态委派子任务和 manifest ready-task 的首次执行统一通过现有 16 MiB 专用 Runtime worker 接管任务锁后轮询,不能把完整 Agent 主循环直接放回默认 Tokio worker;worker 创建或锁交接失败必须把当前 run 持久化为失败。CI 和生产都不得用提高 `RUST_MIN_STACK` 代替这些代码边界。
- 2026-07-18 起,同一 Runtime 文档的“V1.34 动态隔离子 Agent writeScopes 命令绕过封堵”作为 isolated child 的现行能力事实源。在 scope-aware OS sandbox 完成前,动态 child 无条件禁用 `project.verify / project.git_commit / command.exec / command.start / command.stdin / preview.start / agent.delegate / agent.spawn_isolated / project.restore / agent.schedule_ready / canvas.asset_generate / task.create / task.update / blackboard.write` 和全部 MCP;原生工具策略统一显示 `denied`,模板、项目 policy 与用户确认均不能放宽。保留固定只读 `command.run_limited`、同身份 `command.output_read / command.poll / command.terminate`、既有预览的 `preview.validate`,以及严格位于 `writeScopes` 内的 `file.write / file.patch / file.delete / project.patchset`
- V1.34 的新单动作在 confirmation 和 OS launcher 前拒绝;新多 action 原生 batch 只要含一个 denied member 就在独立 pending-action sidecar、confirmation、OS spawn、revision 和任何成员项目副作用前整批 abort,只保留 `aborted / nextActionIndex=0` batch 事实。旧 pending / approval / batch 真正进入执行器时仍重新应用当前 child 边界,旧 executing 未知结果继续进入既有 reconciliation。该安全收紧由恶意 sibling 写入、策略快照、batch、旧 pending 执行器重验和 isolated/mixed/collaboration/provider-batch 回归证明;不因本切片重跑已通过且 isolated mutation 为 0 的 V1.31/V1.32 外部 Provider suite。通用命令只有在后续 scope-aware OS sandbox 对所有后代强制同一 `writeScopes` 并通过独立决策与测试后才可重新评估开放。
- 2026-07-18 起,同一 Runtime 文档的“V1.35 多 ready isolated all-join 原子认领与恢复”作为 `agent.run_status` 同父 run 多 group 认领的现行事实源。Runtime 按 `delegationGroupId` 排序并一次性预取全部 join 锁;任一后续锁忙时保持零 delivery mutation、零 claim sidecar。全锁就绪后,同一 action 的 durable claim journal 按 `prepared -> committed -> observed` 推进;部分 commit 或 Runner 恢复只能复用该 journal 幂等补齐。只认领可完整放入优先 `readyIsolatedJoins` 观察预算的有序前缀,未观察旧 claim 可由后续 action 完整重放,但不创建第二份 isolated claim。每个 claimed delivery 必须由匹配原 action/group 的 journal 覆盖;无 journal 的旧 delivery 每轮只迁移一个原 action,已有 journal 不得扩写或状态倒退,跨 action group 归属冲突失败关闭。成功 observation 写入 pending sidecar 后只能把本轮完整输出的 claim 标记 `observed`,任一未观察或无 journal claim 继续阻断 finalization;每个 group 审计按 `actionId + delegationGroupId` 唯一,并在 Agent DB 锁内修复 torn tail、全量核对后幂等追加。