广告 schema 也得允许两个数组传 null,否则继承分支走不到
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / Backend tests (pull_request) Failing after 9s
Project CI / Frontend tests (pull_request) Successful in 4m45s
Project CI / Native shell tests (pull_request) Successful in 15m17s

上一提交让 Runtime 在返工/续跑时继承 acceptanceCriteria 与 expectedArtifacts,
但广告给模型的 agent.delegate schema 把它们写死成 `"type": "array"` +
minItems 1。模型根本没法传 null,只能继续手抄,继承分支一次都没走到。

无头验证实测:改动前后每条 continuation 都固定先失败 2 次
(verify-farm-2 共 4 次,verify-farm-3 共 6 次),完全没有变化。我上一轮
汇报「0 次」是错的——当时截断了 inspect 输出,没看到那一段就下了结论。

两个字段的 type 改成 ["array", "null"],各自带上说明;工具描述补一句
「返工与澄清续跑一起传 null 由 Runtime 继承」。测试同时钉住描述文案和
schema 的 null 可空性。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-24 02:50:50 +00:00
parent f7644ff5c5
commit 9ad22bf4ae
@@ -1475,7 +1475,7 @@ fn runtime_tool_description(tool: &str) -> &'static str {
"blackboard.write" => "向项目级共享黑板追加稳定结论。",
"agent.message" => "向一个目标 Agent 写入定向上下文消息。",
"agent.delegate" => {
"用持久验收合同把边界清晰的后台任务委派给另一个 Agent;返工时 repairOfDelegationId 指向原 deliveryrunId 必须为 null。"
"用持久验收合同把边界清晰的后台任务委派给另一个 Agent;返工时 repairOfDelegationId 指向原 deliveryrunId 必须为 nullacceptanceCriteria 与 expectedArtifacts 一起传 null 由 Runtime 从原 delivery 继承"
}
"agent.spawn_isolated" => "创建最多三个写范围互不重叠的隔离子 Agent。",
"agent.goal_contract" => {
@@ -1722,8 +1722,8 @@ fn runtime_tool_input_schema(tool: &str) -> Value {
"properties": {
"agentId": { "type": "string", "minLength": 1 },
"task": { "type": "string", "minLength": 1, "maxLength": 2400 },
"acceptanceCriteria": { "type": "array", "minItems": 1, "maxItems": 8, "items": { "type": "string", "minLength": 1, "maxLength": 240 } },
"expectedArtifacts": { "type": "array", "maxItems": 16, "items": { "type": "string", "minLength": 1, "maxLength": 240 } },
"acceptanceCriteria": { "type": ["array", "null"], "minItems": 1, "maxItems": 8, "items": { "type": "string", "minLength": 1, "maxLength": 240 }, "description": "初次委派必填。带 repairOfDelegationId 的返工或澄清续跑传 nullRuntime 会从原 delivery 继承权威合同,手抄一遍不增加任何信息,抄错会被直接拒收。" },
"expectedArtifacts": { "type": ["array", "null"], "maxItems": 16, "items": { "type": "string", "minLength": 1, "maxLength": 240 }, "description": "与 acceptanceCriteria 同进同出:初次委派必填,返工与澄清续跑一起传 null 由 Runtime 继承。" },
"repairOfDelegationId": { "type": ["string", "null"] },
"runId": { "type": ["string", "null"] },
"continuationOfDelegationId": { "type": ["string", "null"] },
@@ -2214,6 +2214,22 @@ mod tests {
assert!(description.contains("repairOfDelegationId 指向原 delivery"));
assert!(description.contains("runId 必须为 null"));
// 广告给模型的 schema 一度把这两个数组写死成非空数组,模型于是根本无法
// 传 null,只能手抄——实测每条 continuation 固定先失败 2 次才抄对。
assert!(
description.contains("acceptanceCriteria 与 expectedArtifacts 一起传 null"),
"{description}"
);
let schema = runtime_tool_input_schema("agent.delegate");
for field in ["acceptanceCriteria", "expectedArtifacts"] {
let types = schema["properties"][field]["type"]
.as_array()
.unwrap_or_else(|| panic!("{field} 必须允许 null"));
assert!(
types.iter().any(|value| value == "null"),
"{field} 的广告 schema 必须允许 null,否则 Runtime 侧的继承分支永远走不到"
);
}
}
/// plan 根 Supervisor 只广告 7 个原生工具 + 2 个协议控制。全量注册表里其余