feat(subagent): make final reports the continuable return contract

A continuable child could finish without giving its parent a usable
result: the report tool was described as optional and its default
delivery stayed quiet. Install the child-scoped report obligation (tool
description plus the tool:report prompt section), default reportDelivery
to wakeup, bind shipped subagent_fork delegations to one-shot so fork
keeps its prefix reuse, and extend the ACP snapshot harness to pin child
system prompts alongside child tool schemas.
This commit is contained in:
Hypatia May
2026-08-11 11:50:39 +08:00
parent 6d3cabf295
commit 76cf6cbd0b
79 changed files with 916 additions and 326 deletions
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/subagent/subagent-fork/README.md
README.md: 55475aee7841e91960de79887dfe9bf37afdf9da
README.zh.md: 379218970c406162309659277a4fcb2da885d9ea
README.md: 2bd72058ab7d112f8f317a33842fc4d95b719017
README.zh.md: 40f9e34c5a8ae8c74de2ae0c9e4676866f0bd083
+2 -1
View File
@@ -39,7 +39,7 @@ Forking duplicates retained completed history into separate child requests; the
#### KV Cache effect
The child may reuse the inherited byte-identical prefix under the same provider and model. Persona, tool-filter, generated-SDK, or route changes may invalidate reuse before inherited history; later child history is append-only.
The child may reuse the inherited byte-identical prefix under the same provider and model. Persona, tool-filter, generated-SDK, or route changes may invalidate reuse before inherited history; later child history is append-only. Shipped compositions therefore bind this provider to `backgroundMode: one-shot`, because a continuable child additionally carries the child-scoped `report` tool and its prompt section — deltas that precede the inherited history and so invalidate all of it ([the fork-one-shot Agent Note](../../../.agents/notes/implemented/architecture/2026-08-10-fork-children-stay-one-shot.md)).
### Parent tool result, indirectly
@@ -58,3 +58,4 @@ Append-only; newly visible content follows the reusable request prefix and does
## Known Limitations and Deferred Work
- **The seed is a one-time snapshot** — the child sees the parent's completed turns as of the fork and nothing the parent logs afterwards; there is no live context sharing.
- **No shipped composition creates a continuable fork child** — `prepareContinuable` remains implemented and the seam accepts it, but every shipped `cordis.yml` sets `backgroundMode: one-shot` on the fork delegation tool, so the provider's continuable path has no production caller. Reopening it requires the child's system prompt and tool schemas to match the parent's byte for byte, which the [`report` return channel](../tool-subagent-report/README.md) currently prevents. Rationale and the reintroduction condition: [the fork-one-shot Agent Note](../../../.agents/notes/implemented/architecture/2026-08-10-fork-children-stay-one-shot.md).
+2 -1
View File
@@ -39,7 +39,7 @@ fork 会把保留的已完成历史复制到独立的子 agent 请求中;随
#### KV Cache 影响
在提供方和模型相同的前提下,子 agent 可以复用继承的逐字节相同前缀。persona、工具过滤、生成 SDK 或路由变化可能在继承历史之前使复用失效;后续子 agent 历史仅追加。
在提供方和模型相同的前提下,子 agent 可以复用继承的逐字节相同前缀。persona、工具过滤、生成 SDK 或路由变化可能在继承历史之前使复用失效;后续子 agent 历史仅追加。因此随附组合把本提供方绑定为 `backgroundMode: one-shot`:可继续子 agent 还会额外携带作用域局部的 `report` 工具及其提示词 section,而这些增量位于继承历史之前,会使继承历史整体失效(见 [fork 保持 one-shot 的 Agent Note](../../../.agents/notes/implemented/architecture/2026-08-10-fork-children-stay-one-shot.md))。
### 父 agent 工具结果(间接)
@@ -58,3 +58,4 @@ fork 会把保留的已完成历史复制到独立的子 agent 请求中;随
## 已知限制与暂缓事项
- **初始内容是一次性快照**:子 agent 只能看到 fork 时父 agent 已完成的轮次,看不到父 agent 此后记录的任何内容;不会实时共享上下文。
- **没有任何随附组合会创建可继续的 fork 子 agent**`prepareContinuable` 仍然实现完好,seam 也接受它,但每份随附的 `cordis.yml` 都在 fork 委派工具上设置 `backgroundMode: one-shot`,因此该提供方的可继续路径没有生产调用方。重新开放它需要子 agent 的系统提示词与工具 schema 与父 agent 逐字节一致,而这一点目前被 [`report` 返回通道](../tool-subagent-report/README.md)阻止。理由与重新开放条件见 [fork 保持 one-shot 的 Agent Note](../../../.agents/notes/implemented/architecture/2026-08-10-fork-children-stay-one-shot.md)。
@@ -74,6 +74,12 @@ class ForkProvider implements SubagentProvider {
})
}
// TODO(fork-continuable-prefix-reuse): no shipped composition calls this —
// they bind fork to `backgroundMode: one-shot` because a continuable child's
// `report` tool and prompt section precede the inherited history, defeating
// the prefix reuse a fork exists for. Reopening needs a byte-identical child
// system prompt and tool schemas; see issue #2124 and
// .agents/notes/implemented/architecture/2026-08-10-fork-children-stay-one-shot.md.
prepareContinuable(request: ContinuableCreateRequest): Promise<ContinuableCreateSpec> {
// The fork prefix is captured ONCE, at creation: it becomes part of the
// child's own durable transcript, so a later cold resume replays that