fix(subagent): report resumable children as ready
list_agents called a storage-only continuable child 'complete', inviting parents to poll it for a result that will never appear there. Rename the status to 'ready' — resumable, not terminal — and rewrite the tool description to say a parent is told when a child finishes, so listing is for recall, not polling.
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# 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 .agents/notes/implemented/bug-fix/2026-08-06-list-agents-residency-vocabulary.md
|
||||
2026-08-06-list-agents-residency-vocabulary.md: 01fff958921465909f5cd300dc355fdac6ec0772
|
||||
2026-08-06-list-agents-residency-vocabulary.zh.md: d68b9857de23ccb0b68f0bfafba153fde63303a7
|
||||
@@ -0,0 +1,40 @@
|
||||
# Agent Note: `list_agents` uses `ready` for resumable children
|
||||
|
||||
Status: implemented
|
||||
|
||||
English | [中文](2026-08-06-list-agents-residency-vocabulary.zh.md)
|
||||
|
||||
## Problem
|
||||
|
||||
`list_agents` projected a continuable child's process residency as `running | idle | complete`. `complete` reads as a terminal unit of work with a result somewhere, but the underlying fact says only that no Activation is resident: the conversation is intact, `send_message` can continue it, and nothing about the child's outcome is being claimed. A model that reads `complete` reasonably looks for a result to collect or sends replacement work to a conversation it believes has ended.
|
||||
|
||||
The word is especially misleading alongside [manager-owned settlement delivery](../feature/2026-08-06-manager-owned-subagent-settlement-delivery.md). Completion reaches the parent as a notice; listing exists to recall durable conversations, not to poll for that notice.
|
||||
|
||||
## Decision
|
||||
|
||||
The model-facing projection reports `running | idle | ready`:
|
||||
|
||||
- **`running`** means the resident Agent has an active driver.
|
||||
- **`idle`** means the Agent is resident between turns and may be waiting on agents it started.
|
||||
- **`ready`** means only the durable conversation remains. `send_message` starts the next turn on the same conversation; the status is resumable rather than terminal and does not mean a result is waiting to be collected.
|
||||
|
||||
The tool description states those distinctions and directs the model away from polling: it says the parent is told when a child finishes and that listing is for recalling which children it started. `send_message` remains the authoritative delivery check because either snapshot may race another process or a later message.
|
||||
|
||||
The service layer is unchanged. `SubagentListEntry.activity` retains `'running' | 'inactive'`, which accurately describes corpus residency for consumers such as a UI. The model-facing adapter maps `inactive` to `ready` because that word communicates the action available to the model without inventing an outcome.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
**Keep `complete` and qualify it in the description.** A description saying that `complete` does not mean complete fights the rendered status on every read. The line the model scans must carry the correct distinction itself.
|
||||
|
||||
**Use `active | dormant`.** This removes the useful distinction between a resident Agent that is between turns and a storage-only conversation, and makes the storage-only state sound unavailable. `ready` states the useful fact: the same conversation accepts another turn.
|
||||
|
||||
**Drop the status entirely.** Residency remains useful when a parent decides whether to send more work. Removing it trades one misleading status for no signal.
|
||||
|
||||
**Rename the service activity values.** `running | inactive` is correct at the service layer and has non-model consumers. Renaming it would churn a general contract to fix one adapter's presentation; the [durable catalog note](../feature/2026-07-22-durable-subagent-catalog-and-list-agents.md) continues to own that service vocabulary.
|
||||
|
||||
## Consequences
|
||||
|
||||
- The rendered line uses `<id> [running] — <label>`, `<id> [idle] — <label>`, or `<id> [ready] — <label>`.
|
||||
- The output schema's `status` enum changes with the rendered contract. The generated tool catalog picks up the new description; it renders each tool's `parameters` only and never carried the output schema.
|
||||
- Unit coverage pins all three mappings and the description clauses that direct the model to the settlement notice instead of polling this tool.
|
||||
- The assembled ACP `subagent-list-agents` scenario renders `ready` for a settled, resumable child.
|
||||
@@ -0,0 +1,40 @@
|
||||
# Agent Note: `list_agents` uses `ready` for resumable children
|
||||
|
||||
Status: implemented
|
||||
|
||||
[English](2026-08-06-list-agents-residency-vocabulary.md) | 中文
|
||||
|
||||
## Problem
|
||||
|
||||
`list_agents` 把可继续 child 的进程驻留状态投影为 `running | idle | complete`。`complete` 读起来像一项终态工作,且结果就在某处,但底层事实只表示没有驻留的 Activation:对话完好无损,`send_message` 可以继续它,而且它对 child 的结果不作任何断言。读到 `complete` 的模型会合理地寻找可收集结果,或向一个它以为已经结束的对话发送替代工作。
|
||||
|
||||
这个词与[由管理器负责的结算投递](../feature/2026-08-06-manager-owned-subagent-settlement-delivery.md)同时出现时尤其容易误导。完成会以通知到达 parent;列表用于回忆持久化对话,而不是轮询该通知。
|
||||
|
||||
## Decision
|
||||
|
||||
面向模型的投影报告 `running | idle | ready`:
|
||||
|
||||
- **`running`** 表示驻留 Agent 存在活跃 driver。
|
||||
- **`idle`** 表示 Agent 驻留但处于轮次之间,也可能正在等待它启动的 agent。
|
||||
- **`ready`** 表示只剩下持久化对话。`send_message` 会在同一对话上启动下一轮;该状态表示可恢复而非终态,也不表示有结果等待收集。
|
||||
|
||||
工具描述会陈述这些区别,并引导模型远离轮询:它说明 child 结束时 parent 会收到通知,而列表用于回忆自己启动过哪些 child。由于任一快照都可能与另一进程或后续消息竞态,`send_message` 仍是投递时的权威检查。
|
||||
|
||||
服务层不变。`SubagentListEntry.activity` 保留 `'running' | 'inactive'`,对 UI 等消费方而言,这准确描述了语料驻留状态。面向模型的适配器把 `inactive` 映射为 `ready`,因为这个词表达了模型可执行的操作,而没有虚构结果。
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
**保留 `complete`,并在描述中限定它。** 一段解释 `complete` 不代表完成的描述,每次被读取时都在与渲染状态对抗。模型扫读的那一行必须自身表达正确区别。
|
||||
|
||||
**使用 `active | dormant`。** 这会删除处于轮次之间的驻留 Agent 与仅存于存储的对话之间的有效区别,并让仅存于存储的状态听起来不可用。`ready` 直接表达有用事实:同一对话可以接受下一轮。
|
||||
|
||||
**完全移除状态。** parent 决定是否发送更多工作时,驻留状态依然有用。移除它只是用没有信号替代一个误导性状态。
|
||||
|
||||
**重命名服务活动值。** `running | inactive` 在服务层是正确的,并且有非模型消费方。为了修复一个适配器的呈现而搅动通用契约并不合理;[持久化目录 Agent Note](../feature/2026-07-22-durable-subagent-catalog-and-list-agents.md) 继续拥有该服务词汇。
|
||||
|
||||
## Consequences
|
||||
|
||||
- 渲染行使用 `<id> [running] — <label>`、`<id> [idle] — <label>` 或 `<id> [ready] — <label>`。
|
||||
- 输出 schema 的 `status` 枚举与渲染契约一同变化。生成的工具目录会带上新描述;它只渲染每个工具的 `parameters`,从来不收录输出 schema。
|
||||
- 单元覆盖固定三种映射,以及引导模型等待结算通知而非轮询本工具的描述条款。
|
||||
- 整体组装的 ACP `subagent-list-agents` 场景会为已结算且可恢复的 child 渲染 `ready`。
|
||||
@@ -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 .agents/notes/implemented/feature/2026-07-22-durable-subagent-catalog-and-list-agents.md
|
||||
2026-07-22-durable-subagent-catalog-and-list-agents.md: 61bda2a52f2ea5db0a582fe668643a13b967f091
|
||||
2026-07-22-durable-subagent-catalog-and-list-agents.zh.md: 6b5bff468349df4226aaf76dd7ed7d9ce5c3f33c
|
||||
2026-07-22-durable-subagent-catalog-and-list-agents.md: 51664bc1e211802ef61f47508b9e57fdd099b9e7
|
||||
2026-07-22-durable-subagent-catalog-and-list-agents.zh.md: 79503a30e081abffd45637439ac539d95ae794f0
|
||||
|
||||
@@ -23,7 +23,7 @@ Parent-to-child enumeration is a service capability with consumer-specific proje
|
||||
- report corpus activity separately as `running` or `inactive`, without implying completion or resumability;
|
||||
- return every resulting child in stable `createdAt` ascending, child-id ascending order.
|
||||
|
||||
Every ordinary local start receives a `one-shot` descriptor with an optional caller-owned display label, while the continuation manager persists a labeled `continuable` descriptor containing its additional reconstruction fields. The model-facing delegation tool already owns a short `description` and supplies it for one-shot display; lower-level callers such as workflows need not invent presentation metadata. The model-facing `list_agents` adapter filters the service result to continuable children and refines status through the live Agent registry (`running`/`idle`/`complete`); a UI can consume both modes and choose an id-based fallback for unlabeled one-shot history. Descriptor persistence, by-id lookup, direct-parent authorization, and provider-independent cold resume remain owned by the implemented Activation contract. Listing consumes those facts but cannot weaken them or invent a second descriptor representation.
|
||||
Every ordinary local start receives a `one-shot` descriptor with an optional caller-owned display label, while the continuation manager persists a labeled `continuable` descriptor containing its additional reconstruction fields. The model-facing delegation tool already owns a short `description` and supplies it for one-shot display; lower-level callers such as workflows need not invent presentation metadata. The model-facing `list_agents` adapter filters the service result to continuable children and refines status through the live Agent registry (`running`/`idle`, and [`ready`](../bug-fix/2026-08-06-list-agents-residency-vocabulary.md) for storage-only); a UI can consume both modes and choose an id-based fallback for unlabeled one-shot history. Descriptor persistence, by-id lookup, direct-parent authorization, and provider-independent cold resume remain owned by the implemented Activation contract. Listing consumes those facts but cannot weaken them or invent a second descriptor representation.
|
||||
|
||||
### Enumeration decision
|
||||
|
||||
@@ -52,7 +52,7 @@ If measured scale later requires an index, that index is derived state: session
|
||||
|
||||
A valid descriptor produces one child entry, a per-child inspection failure produces one diagnostic entry, and a candidate without a descriptor produces no entry. `mode` is durable creation policy; `activity` is a process-local corpus snapshot. Activity is neither `AgentStatus`, the manager's internal Activation state, nor a durable outcome, and the result does not expose the internal `createdAt` sorting key. Exact Activation states and durable outcomes such as successful completion, failure, cancellation, and stop reason require a separate durable activation record and are outside this feature.
|
||||
|
||||
The model-facing `list_agents` tool takes one optional `scope: 'children' | 'descendants'` argument, derives the root id from the current execution Agent, and resolves the request through an explicit request-to-spec step (`undefined` → `children`) before either execution or rendering. The resolved `children` scope calls `SubagentService.listChildren(rootSessionId)`, while `descendants` calls `SubagentService.listDescendants(rootSessionId)`. Its internal output projection keeps `id` and `parent` as branded `SessionId` values until the tool JSON boundary. It keeps diagnostics, drops `one-shot` child entries, derives status from the live Agent registry — `running` for an active driver, `idle` for a resident Agent between turns, and `complete` when no live Agent remains — then renders `<id> [<status>] — <label>` or `<id> [diagnostic: <reason>]` in stable catalog order. The `descendants` scope flattens the complete tree from one live-preferred corpus in stable pre-order, traverses ordinary and one-shot intermediates so deeper continuable agents are discovered, revalidates each cold candidate against its enumerated lifecycle, and adds `parentId`/`depth` to every entry. The tool inserts ` parent=<id> depth=<n>` before the label; `parent` is the durable direct-parent session id and may name an omitted ordinary session. For the current caller, only depth-1 child rows are `send_message` candidates, while deeper child rows may be selected for `interrupt_agent` ([interrupt contract](2026-08-06-continuable-subagent-interrupt.md)). Discovery is a hint only — follow-up authority stays exact-direct-parent, and interrupt authority stays with the service's live-lineage check. An empty projection renders `(no subagents)`.
|
||||
The model-facing `list_agents` tool takes one optional `scope: 'children' | 'descendants'` argument, derives the root id from the current execution Agent, and resolves the request through an explicit request-to-spec step (`undefined` → `children`) before either execution or rendering. The resolved `children` scope calls `SubagentService.listChildren(rootSessionId)`, while `descendants` calls `SubagentService.listDescendants(rootSessionId)`. Its internal output projection keeps `id` and `parent` as branded `SessionId` values until the tool JSON boundary. It keeps diagnostics, drops `one-shot` child entries, derives status from the live Agent registry — `running` for an active driver, `idle` for a resident Agent between turns, and `ready` when no live Agent remains — resumable rather than terminal — then renders `<id> [<status>] — <label>` or `<id> [diagnostic: <reason>]` in stable catalog order. The `descendants` scope flattens the complete tree from one live-preferred corpus in stable pre-order, traverses ordinary and one-shot intermediates so deeper continuable agents are discovered, revalidates each cold candidate against its enumerated lifecycle, and adds `parentId`/`depth` to every entry. The tool inserts ` parent=<id> depth=<n>` before the label; `parent` is the durable direct-parent session id and may name an omitted ordinary session. For the current caller, only depth-1 child rows are `send_message` candidates, while deeper child rows may be selected for `interrupt_agent` ([interrupt contract](2026-08-06-continuable-subagent-interrupt.md)). Discovery is a hint only — follow-up authority stays exact-direct-parent, and interrupt authority stays with the service's live-lineage check. An empty projection renders `(no subagents)`.
|
||||
|
||||
In the superseded trace-based path, diagnostics used three fixed reasons. Malformed event surfaces, conflicting headers discovered during an exact child load, a read result whose immutable header differs from the traced candidate or no longer names the requested direct parent, a target that is no longer the located descriptor event, malformed descriptor content, and multiple descriptor events mapped to `corrupt`. An unknown descriptor version mapped to `unsupported`. `SESSION_QUERY_SESSION_NOT_FOUND`, `SESSION_QUERY_EVENT_NOT_FOUND`, and `SESSION_QUERY_PERSISTENCE_FAILED` from a per-child read mapped to `unavailable`. This phase boundary was intentional: a persistence outage during the initial trace failed the operation, while the same outage beginning during candidate reads could produce one identical `unavailable` diagnostic per affected child; the first version neither coalesced those diagnostics nor promoted them to a global failure. A missing descriptor was instead a non-subagent exclusion without a diagnostic. Configuration/window errors and unrecognized failures were not child diagnostics and propagated as operation failures. Each diagnostic identified the child id and reason without exposing model-hidden descriptor content; the candidate was omitted while healthy siblings remained visible. Sessions outside the trace's direct descendants were never read and produced no diagnostic.
|
||||
|
||||
@@ -95,7 +95,7 @@ The first version has no child deletion operation. If later product behavior del
|
||||
- `packages/subagent/subagent/tests/service.spec.ts` pins descriptor v2 parsing for both modes and proves an unlabeled raw start resolves a one-shot descriptor before provider dispatch. `packages/subagent/subagent-inprocess/tests/subagent-inprocess.spec.ts` proves the local driver appends that descriptor inside the initial turn, returns the published id when cancellation lands in the factory-to-run handoff, and keeps result and handle-disposal failures on separate channels. Delegation-tool tests pin propagation of their existing display description and preserve independent result and disposal diagnostics.
|
||||
- `packages/subagent/subagent/tests/list-children.spec.ts` pins the current read path against a real composition of the session store, JSONL persistence, spawn/fork providers, the subagent service, and the projection registry — no query service — keylessly: live-only listing without persistence; loud `SUBAGENT_CONTROL_PROJECTIONS_UNAVAILABLE` and `SUBAGENT_CONTROL_SESSION_STORE_UNAVAILABLE` even with zero children; the three-rung ladder (a live child never inspected, a cold child inspected exactly once, and the cache-hit, absent-key, absent-service, and poisoned-row second-rung cases); last-wins over multiple descriptors; malformed payloads and unknown versions diagnosed as `corrupt`; a failed cold inspection as one `unavailable` diagnostic retried on the next listing; a fork seed's ancestor descriptor listed under that identity; foreign-unit fold failures contained per child as `corrupt` on both the live and cold paths; `createdAt`-then-id ordering without ordinary forks; provider absence without child omission; compacted/uncompacted twins listing identically; a persisted-listing failure failing the whole enumeration; cancellation normalized to stable `CANCELLED`; typed stable error codes; and descendant listing's iterative stable pre-order, traversal through ordinary and one-shot intermediates, positioned diagnostics, lifecycle revalidation, and cancellation. A companion spec (retired together with the query-backed read path) rejected eager evaluation of the optional session-query runtime while importing the ordinary subagent surface.
|
||||
- `packages/subagent/tool-subagent-control/tests/list-agents.spec.ts` pins the `list_agents` schema (one optional `scope` enum), the continuable-only projection that omits a healthy one-shot sibling while preserving diagnostics, registry-derived child/diagnostic/empty text forms, an end-to-end settled-child listing with its durable label, the descendants scope's pre-order parent/depth annotations across a live waiting branch, cancellation forwarding to both scopes, the no-agent rejection, the `agents` load requirement without `sessionQuery`, and HMR disposal.
|
||||
- The keyless ACP snapshot scenario `subagent-list-agents` (examples/acp-agent) fences its second parent turn on a snapshot-only `subagent/end` marker, then executes `list_agents` for real against the subagent service, the projection registry, and JSONL persistence, rendering `<id> [complete] — <label>`.
|
||||
- The keyless ACP snapshot scenario `subagent-list-agents` (examples/acp-agent) fences its second parent turn on a snapshot-only `subagent/end` marker, then executes `list_agents` for real against the subagent service, the projection registry, and JSONL persistence, rendering `<id> [ready] — <label>`.
|
||||
- The keyless snapshot scenario `subagent-diagnostic` (examples/headless-agent) pins the current listing's model-visible diagnostic classification, including a descriptor-less settled child surfacing as a `corrupt` diagnostic.
|
||||
- The keyless ACP snapshot scenario `subagent-published-run-failure` publishes a real one-shot child, injects independent run-result and handle-disposal failures, and preserves both diagnostics in the parent tool result.
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ parent 到 child 的枚举是一项带消费方专用投影的服务功能。`Su
|
||||
- 将语料活动状态单独报告为 `running` 或 `inactive`,但不暗示已完成或可恢复;
|
||||
- 按 `createdAt` 升序、再按 child id 升序稳定返回所有结果 child。
|
||||
|
||||
每次普通的本地启动都会收到带可选、由调用方拥有之显示标签的 `one-shot` 描述符,而继续执行管理器会持久化带标签、包含附加重建字段的 `continuable` 描述符。面向模型的委派工具已经拥有简短 `description`,会将其用于一次性显示;workflow 等底层调用方无需凭空构造展示元数据。面向模型的 `list_agents` 适配器会将服务结果过滤为可继续 child,并通过在线 Agent 注册表细化状态(`running`/`idle`/`complete`);UI 可以消费两种模式,并为无标签的一次性历史选择基于 id 的回退展示。描述符持久化、按 id 查找、直接 parent 鉴权和不依赖提供方的冷恢复仍归已实现的 Activation 约定负责。列表查询消费这些事实,但不能削弱它们,也不能另行发明第二种描述符表示。
|
||||
每次普通的本地启动都会收到带可选、由调用方拥有之显示标签的 `one-shot` 描述符,而继续执行管理器会持久化带标签、包含附加重建字段的 `continuable` 描述符。面向模型的委派工具已经拥有简短 `description`,会将其用于一次性显示;workflow 等底层调用方无需凭空构造展示元数据。面向模型的 `list_agents` 适配器会将服务结果过滤为可继续 child,并通过在线 Agent 注册表细化状态(`running`/`idle`,以及对应仅存于存储的 [`ready`](../bug-fix/2026-08-06-list-agents-residency-vocabulary.md));UI 可以消费两种模式,并为无标签的一次性历史选择基于 id 的回退展示。描述符持久化、按 id 查找、直接 parent 鉴权和不依赖提供方的冷恢复仍归已实现的 Activation 约定负责。列表查询消费这些事实,但不能削弱它们,也不能另行发明第二种描述符表示。
|
||||
|
||||
### 枚举决策
|
||||
|
||||
@@ -52,7 +52,7 @@ subagent 服务将 `sessionQuery` 保持为可选依赖,因此没有该服务
|
||||
|
||||
有效描述符产生一个 child 条目,逐 child 检查失败产生一个 diagnostic 条目,缺少描述符的候选不产生条目。`mode` 是持久化创建策略;`activity` 是进程本地语料快照。活动状态既不是 `AgentStatus`、管理器内部的 Activation 状态,也不是持久化结果,结果不公开内部 `createdAt` 排序键。成功完成、失败、取消和停止原因等精确 Activation 状态与持久化结果需要单独的持久化激活记录,不在本功能范围内。
|
||||
|
||||
面向模型的 `list_agents` 工具接受一个可选的 `scope: 'children' | 'descendants'` 参数,从当前执行 Agent 推导根 id,并在执行或渲染前通过显式的 request-to-spec 步骤解析请求(`undefined` → `children`)。解析后的 `children` scope 调用 `SubagentService.listChildren(rootSessionId)`,`descendants` scope 则调用 `SubagentService.listDescendants(rootSessionId)`。其内部输出投影中的 `id` 与 `parent` 会一直保持为品牌化的 `SessionId` 值,直到工具 JSON 边界。它保留 diagnostic,丢弃 `one-shot` child 条目,状态取自在线 Agent 注册表——driver 活跃为 `running`,驻留但处于轮次之间为 `idle`,没有在线 Agent 时为 `complete`——然后按稳定目录顺序渲染 `<id> [<status>] — <label>` 或 `<id> [diagnostic: <reason>]`。`descendants` scope 从一份实时优先语料按稳定 pre-order 展平完整树,遍历普通与一次性中间节点以发现更深的可继续 agent,依据枚举生命周期重新校验每个冷候选,并为每个条目附加 `parentId`/`depth`。工具会在 label 之前插入 ` parent=<id> depth=<n>`;`parent` 是持久化直接 parent 会话 id,可能指向被省略的普通会话。对于当前调用方,只有 depth-1 child 条目可作为 `send_message` 候选,更深的 child 条目则可供 `interrupt_agent` 选择([中断约定](2026-08-06-continuable-subagent-interrupt.md))。发现结果只是提示——follow-up 权限仍仅属于确切直接 parent,中断权限仍由服务的在线 lineage 检查决定。空投影渲染为 `(no subagents)`。
|
||||
面向模型的 `list_agents` 工具接受一个可选的 `scope: 'children' | 'descendants'` 参数,从当前执行 Agent 推导根 id,并在执行或渲染前通过显式的 request-to-spec 步骤解析请求(`undefined` → `children`)。解析后的 `children` scope 调用 `SubagentService.listChildren(rootSessionId)`,`descendants` scope 则调用 `SubagentService.listDescendants(rootSessionId)`。其内部输出投影中的 `id` 与 `parent` 会一直保持为品牌化的 `SessionId` 值,直到工具 JSON 边界。它保留 diagnostic,丢弃 `one-shot` child 条目,状态取自在线 Agent 注册表——driver 活跃为 `running`,驻留但处于轮次之间为 `idle`,没有在线 Agent 时为 `ready`(可恢复而非终态)——然后按稳定目录顺序渲染 `<id> [<status>] — <label>` 或 `<id> [diagnostic: <reason>]`。`descendants` scope 从一份实时优先语料按稳定 pre-order 展平完整树,遍历普通与一次性中间节点以发现更深的可继续 agent,依据枚举生命周期重新校验每个冷候选,并为每个条目附加 `parentId`/`depth`。工具会在 label 之前插入 ` parent=<id> depth=<n>`;`parent` 是持久化直接 parent 会话 id,可能指向被省略的普通会话。对于当前调用方,只有 depth-1 child 条目可作为 `send_message` 候选,更深的 child 条目则可供 `interrupt_agent` 选择([中断约定](2026-08-06-continuable-subagent-interrupt.md))。发现结果只是提示——follow-up 权限仍仅属于确切直接 parent,中断权限仍由服务的在线 lineage 检查决定。空投影渲染为 `(no subagents)`。
|
||||
|
||||
在已被取代的追踪读路径中,diagnostic 使用三种固定原因。格式错误的事件 surface、精确加载 child 时发现的 header 冲突、读取结果中的不可变 header 与追踪到的候选不一致或不再指向请求的直接 parent、读取目标不再是先前定位的描述符事件、格式错误的描述符内容和多个描述符事件映射为 `corrupt`。未知描述符版本映射为 `unsupported`。逐 child 读取产生的 `SESSION_QUERY_SESSION_NOT_FOUND`、`SESSION_QUERY_EVENT_NOT_FOUND` 和 `SESSION_QUERY_PERSISTENCE_FAILED` 映射为 `unavailable`。这项阶段边界是有意为之:初始追踪期间发生持久化故障会让操作失败,而同一故障如果始于候选读取期间,可能会让每个受影响的 child 分别产生一条相同的 `unavailable` diagnostic;第一版既不合并这些 diagnostic,也不会把它们提升为全局失败。缺少描述符则作为非 subagent 排除,且不产生 diagnostic。配置错误、窗口错误和未识别的失败不属于 child diagnostic,会作为操作失败继续向上传播。每条 diagnostic 都标识 child id 及原因,不暴露对模型隐藏的描述符内容;系统会排除该候选,而其他健康的 sibling 仍然可见。系统绝不会读取不属于追踪结果直接后代的会话,也不会为它们产生 diagnostic。
|
||||
|
||||
@@ -95,7 +95,7 @@ diagnostic 是瞬时查询结果,不属于会话事件或目录状态。推导
|
||||
- `packages/subagent/subagent/tests/service.spec.ts` 固定两种模式下的描述符 v2 解析,并证明无标签的底层启动会在分发给提供方之前解析出一次性描述符。`packages/subagent/subagent-inprocess/tests/subagent-inprocess.spec.ts` 证明本地驱动会在初始轮次内追加该描述符,在取消落入工厂到 run 的交接窗口时返回已发布 id,并让结果与句柄释放失败保留在独立通道中。委派工具测试固定其现有显示说明的传递,并保留相互独立的结果与 dispose diagnostic。
|
||||
- `packages/subagent/subagent/tests/list-children.spec.ts` 针对由会话存储、JSONL 持久化、spawn/fork 提供方、subagent 服务与投影注册表构成的真实组合——不含查询服务——以无密钥方式钉住现行读取路径:无持久化时的仅存活列表;零 children 也响亮报 `SUBAGENT_CONTROL_PROJECTIONS_UNAVAILABLE` 与 `SUBAGENT_CONTROL_SESSION_STORE_UNAVAILABLE`;三级阶梯(存活 child 从不检查、冷 child 恰好检查一次,以及缓存命中、key 缺席、服务缺席、行中毒四个第二级用例);多描述符 last-wins 取末者;载荷格式错误与未知版本诊断为 `corrupt`;冷检查失败成一条 `unavailable` diagnostic 并在下次列表重试;fork seed 中的祖先描述符按该身份列出;外部 unit 折叠失败在存活与冷两条路径上按 child 收纳为 `corrupt`;按 `createdAt` 再按 id 排序且不列普通 fork;提供方缺失时不排除 child;压缩与未压缩的孪生 child 列表结果一致;持久化列表失败使整次枚举失败;取消稳定归一化为 `CANCELLED`;带类型的稳定错误码;以及后代列表的迭代式稳定 pre-order、穿过普通与一次性中间节点、带位置 diagnostic、生命周期复验与取消。一个伴随规格(已随查询式读取路径一起退役)曾在导入普通 subagent surface 时拒绝对可选 session-query 运行时的 eager 求值。
|
||||
- `packages/subagent/tool-subagent-control/tests/list-agents.spec.ts` 固定 `list_agents` 的 schema(一个可选 `scope` 枚举)、只保留可继续 child 且排除健康的一次性 sibling、同时保留 diagnostic 的投影、由注册表推导的 child/diagnostic/空结果文本形式、带持久化 label 的已结束 child 端到端列表、descendants scope 在在线 waiting 分支上的 pre-order parent/depth 注释、两个 scope 的取消信号转发、无调用 agent 时的拒绝、要求 `agents` 但不再注入 `sessionQuery` 的加载约定,以及 HMR dispose。
|
||||
- 无密钥 ACP 快照场景 `subagent-list-agents`(examples/acp-agent)使用仅限快照的 `subagent/end` 标记为第二个 parent 轮次设置边界,随后针对 subagent 服务、投影注册表和 JSONL 持久化真实执行 `list_agents`,渲染 `<id> [complete] — <label>`。
|
||||
- 无密钥 ACP 快照场景 `subagent-list-agents`(examples/acp-agent)使用仅限快照的 `subagent/end` 标记为第二个 parent 轮次设置边界,随后针对 subagent 服务、投影注册表和 JSONL 持久化真实执行 `list_agents`,渲染 `<id> [ready] — <label>`。
|
||||
- 无密钥快照场景 `subagent-diagnostic`(examples/headless-agent)钉住现行列表的模型可见诊断分类,包括无描述符的定局 child 以 `corrupt` diagnostic 出现。
|
||||
- 无密钥 ACP 快照场景 `subagent-published-run-failure` 会发布一个真实的一次性 child,注入相互独立的 run result 与 handle dispose 失败,并在 parent 工具结果中保留两项 diagnostic。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user