fix(agent): 超预算待处理事项先于会话终态写入
e15「超预算」偶发失败(全量 ci 负载下 decision.agent_run_id 仍是上一次运行)是产品竞态,不是测试等待不足: finalize 先把 agent_run 写成 budget_exceeded,之后才 upsert 同根因的超预算待处理事项(和任务行)。 观察者(测试、会话页、待处理中心)在两次写入之间看到终态时,事项还指向上一次运行。 改为先写待处理事项与任务行,最后写会话终态:看到 budget_exceeded 时事项已指向这次运行。 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
12bc4664b6
commit
c9c6505d71
1 file changed
+26
-23
@@ -315,18 +315,20 @@ export async function finalize(
|
||||
content_hash: sha(JSON.stringify({ runId, report })),
|
||||
})
|
||||
.execute();
|
||||
await ctx.db
|
||||
.updateTable("agent_run")
|
||||
.set({
|
||||
status,
|
||||
summary: summary.slice(0, 4000),
|
||||
...(status === "waiting" ? {} : { finished_at: new Date() }),
|
||||
...(res.status === "failed"
|
||||
? { error: JSON.stringify({ reason: res.reason, budget: res.budget, message: res.message }) }
|
||||
: {}),
|
||||
})
|
||||
.where("id", "=", runId)
|
||||
.execute();
|
||||
if (status === "budget_exceeded") {
|
||||
// 同根因(同一待处理事项 / 同一定时巡检 / 同一目标模板)超预算合并到已有事项,不重复新建。
|
||||
// 先写事项再写终态:观察者看到 budget_exceeded 时,事项已指向这次运行(之前顺序相反,
|
||||
// 负载下读到终态时事项还指向上一次运行,e15 偶发失败)
|
||||
await writeDecision(ctx, {
|
||||
kind: "other",
|
||||
title: "智能体运行超出预算",
|
||||
summary: res.message ?? "超出预算",
|
||||
subjectId: runId,
|
||||
dedupeKey: await budgetDedupeKey(ctx, run),
|
||||
evidence: { runId, runIds: [runId], budget: res.budget, message: res.message, goal: run.goal },
|
||||
});
|
||||
}
|
||||
// 任务行同样先于会话终态写:看到会话终态时任务页已是同一结论
|
||||
if (run.task_id) {
|
||||
const taskStatus =
|
||||
status === "cancelled"
|
||||
@@ -349,17 +351,18 @@ export async function finalize(
|
||||
.where("id", "=", run.task_id)
|
||||
.execute();
|
||||
}
|
||||
if (status === "budget_exceeded") {
|
||||
// 同根因(同一待处理事项 / 同一定时巡检 / 同一目标模板)超预算合并到已有事项,不重复新建
|
||||
await writeDecision(ctx, {
|
||||
kind: "other",
|
||||
title: "智能体运行超出预算",
|
||||
summary: res.message ?? "超出预算",
|
||||
subjectId: runId,
|
||||
dedupeKey: await budgetDedupeKey(ctx, run),
|
||||
evidence: { runId, runIds: [runId], budget: res.budget, message: res.message, goal: run.goal },
|
||||
});
|
||||
}
|
||||
await ctx.db
|
||||
.updateTable("agent_run")
|
||||
.set({
|
||||
status,
|
||||
summary: summary.slice(0, 4000),
|
||||
...(status === "waiting" ? {} : { finished_at: new Date() }),
|
||||
...(res.status === "failed"
|
||||
? { error: JSON.stringify({ reason: res.reason, budget: res.budget, message: res.message }) }
|
||||
: {}),
|
||||
})
|
||||
.where("id", "=", runId)
|
||||
.execute();
|
||||
// 后台调查:结论回写待处理事项,交还人工(仍可被新证据重新唤醒)
|
||||
if (run.dedupe_key?.startsWith("investigate:")) {
|
||||
const decisionId = run.dedupe_key.slice("investigate:".length);
|
||||
|
||||
Reference in new issue
Block a user