docs(subagent): qualify startup cleanup outcomes

This commit is contained in:
pku-xht committed 2026-08-21 07:29:12 +08:00
1 parent ca7ccac27f
commit 75b8eb08ba
10 files changed
+16 -15

No files matched your search

@@ -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-06-22-acp-subagent-backend.md
2026-06-22-acp-subagent-backend.md: 2a93329b5f21e98c3f49c17f62997e07aed3c72d
2026-06-22-acp-subagent-backend.zh.md: 5be06a47558466f547591eb0fd19d6be11ccfecf
2026-06-22-acp-subagent-backend.md: 85129ec6a5b1c5607ef3a89e6ebaf6cbfb29e7c9
2026-06-22-acp-subagent-backend.zh.md: ed0b3488a91782cc1249f65e95935e2f7c00e9c3
@@ -30,7 +30,7 @@ The child's working directory is an explicit resolution, never the harness proce
### StopReason mapping
ACP `StopReason` → harness `SubagentStopReason`: `end_turn`→`completed`, `max_tokens`→`max-tokens`, `refusal`→`refusal`, `cancelled`→`aborted`, `max_turn_requests`→`error` (no clean equivalent — the task did not finish), unknown→`error`. A spawn/transport/RPC failure resolves `error` (or `aborted` if a cancel was requested); `result` never rejects on a child-level failure, per the seam contract. Non-completed and lifecycle failures add only the bounded provider stage, coarse category, closed permission decision, and observed process facts defined by the [out-of-process diagnostics decision](2026-08-21-out-of-process-subagent-minimal-diagnostics.md); raw ACP errors and stderr remain Host-only.
ACP `StopReason` → harness `SubagentStopReason`: `end_turn`→`completed`, `max_tokens`→`max-tokens`, `refusal`→`refusal`, `cancelled`→`aborted`, `max_turn_requests`→`error` (no clean equivalent — the task did not finish), unknown→`error`. Spawn, initialize, and session-creation failures reject `start()` before publication after provider-owned cleanup; prompt/RPC/transport failures after publication settle `result` as `error` (or `aborted` after local cancellation), and `result` never rejects on a child-level failure. Non-completed and lifecycle failures add only the bounded provider stage, coarse category, closed permission decision, and observed process facts defined by the [out-of-process diagnostics decision](2026-08-21-out-of-process-subagent-minimal-diagnostics.md); raw ACP errors and stderr remain Host-only.
### Security: scrubbed child environment
@@ -30,7 +30,7 @@ subagent seam([seam Agent Note](2026-06-21-subagent-capability-seam.zh.md))
### StopReason 映射
ACP `StopReason` → harness `SubagentStopReason`:`end_turn`→`completed`、`max_tokens`→`max-tokens`、`refusal`→`refusal`、`cancelled`→`aborted`、`max_turn_requests`→`error`(无对等语义,任务未完成)、未知→`error`。spawn/传输/RPC 失败时,结果为 `error`(如果已请求取消则为 `aborted`);按 seam 约定,`result` 在子 agent 级别失败时从不 reject。非完成结果与生命周期失败只会附加[进程外诊断决策](2026-08-21-out-of-process-subagent-minimal-diagnostics.zh.md)定义的有界 provider stage、粗粒度 category、闭集权限决定和已观测进程事实;原始 ACP 错误与 stderr 仍只留在 Host。
ACP `StopReason` → harness `SubagentStopReason`:`end_turn`→`completed`、`max_tokens`→`max-tokens`、`refusal`→`refusal`、`cancelled`→`aborted`、`max_turn_requests`→`error`(无对等语义,任务未完成)、未知→`error`。spawn、initialize 与会话创建失败会在提供方自有清理后、发布前拒绝 `start()`;发布后的 prompt/RPC/传输失败会把 `result` 确定为 `error`(本地取消后为 `aborted`),而 `result` 在子 agent 级别失败时绝不 reject。非完成结果与生命周期失败只会附加[进程外诊断决策](2026-08-21-out-of-process-subagent-minimal-diagnostics.zh.md)定义的有界 provider stage、粗粒度 category、闭集权限决定和已观测进程事实;原始 ACP 错误与 stderr 仍只留在 Host。
### 安全:清洗子进程环境
@@ -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-08-21-out-of-process-subagent-minimal-diagnostics.md
2026-08-21-out-of-process-subagent-minimal-diagnostics.md: 86a8ed5f5ce38af9792aa8961c939098b79647e3
2026-08-21-out-of-process-subagent-minimal-diagnostics.zh.md: f8a885ec6b36e28474683857eefe6d399d047857
2026-08-21-out-of-process-subagent-minimal-diagnostics.md: d7797eda4c6b31851918eeb9bb764deac3222b9e
2026-08-21-out-of-process-subagent-minimal-diagnostics.zh.md: 527c29f41120ace1374486dabffd00534a962e7f
@@ -61,7 +61,7 @@ During initialize or session run, `SdkProtocolError` and JSON-RPC error response
| Diagnostic bytes and presentation | `dsh-subagent`, foreground tool, and Job runtime | The same bounded text stays separate from assistant output in foreground and one-shot background modes |
| Raw failure | Child runtime, Error cause chain, and Host logger | Available for Host diagnosis only, never copied into the parent model result |
Startup publishes no run until the provider's handshake completes. A startup failure rolls the private child back to quiescence before rejecting with safe facts. A published run settles its result without rejection, and `dispose()` independently reports safe teardown or shutdown facts while still using the backend's existing process cleanup ladder.
Startup publishes no run until the provider's handshake completes. Successful startup cleanup rolls the private child back to quiescence before rejection; cleanup failure instead preserves ordered safe startup and teardown/shutdown facts without claiming process exit. A published run settles its result without rejection, and `dispose()` independently reports safe teardown or shutdown facts while still using the backend's existing process cleanup ladder.
## Verification
@@ -61,7 +61,7 @@ Subagent failure (provider: <provider>; stage: <stage>; category: <category>; st
| 诊断字节与呈现 | `dsh-subagent`、前台工具与 Job 运行时 | 前台和一次性后台模式都把同一份有界文本与 assistant 输出分开 |
| 原始失败 | 子运行时、Error cause 链与 Host logger | 只供 Host 排障,绝不复制进父模型结果 |
启动只有在提供方握手完成后才发布运行。启动失败会先把私有子进程回滚到完全停稳,再以安全事实拒绝。已发布运行的结果不会拒绝,而 `dispose()` 会独立报告安全 teardown 或 shutdown 事实,并继续使用后端既有的进程清理阶梯。
启动只有在提供方握手完成后才发布运行。启动清理成功时,私有子进程会先回滚到完全停稳再拒绝;清理失败时,则保留有序的安全启动与 teardown/shutdown 事实,但不会宣称进程已经退出。已发布运行的结果不会拒绝,而 `dispose()` 会独立报告安全 teardown 或 shutdown 事实,并继续使用后端既有的进程清理阶梯。
## Verification
@@ -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-dsh-sdk/README.md
README.md: 19c9e04bc0a947439dbbba3a9a1fa033c9310542
README.zh.md: 9a1e285f9561fae8cb6349b9467894d86ac45cdf
README.md: fbdcc2e95eb97df2f3c58c9b61dce99691ceda41
README.zh.md: 2b8c818fe4296fb6777617cd954b9172eba07d54
+1 -1
View File
@@ -6,7 +6,7 @@ The SDK provider runs each subagent as a complete DeepSeek Harness runtime in a
## Start and ownership
`start(request)` resolves the child's working directory, spawns the runtime through `DeepSeekHarness`, and completes the `initialize` handshake (with the configured `provider`/`model` route and optional `maxTokens` output cap) before it fulfills. Fulfillment therefore means the child runtime is ready and ownership has transferred to the caller. A spawn, handshake, or pre-publication cancellation failure rejects only after the subprocess has been reaped; a working-directory resolution failure rejects before anything is spawned. Non-cancellation rejections expose only fixed provider, stage, and category facts in their Error message; the original SDK failure remains on the internal cause chain and in Host diagnostics.
`start(request)` resolves the child's working directory, spawns the runtime through `DeepSeekHarness`, and completes the `initialize` handshake (with the configured `provider`/`model` route and optional `maxTokens` output cap) before it fulfills. Fulfillment therefore means the child runtime is ready and ownership has transferred to the caller. A spawn, handshake, or pre-publication cancellation failure ordinarily rejects after the subprocess is reaped; when cleanup itself rejects, the ordered safe initialize/shutdown facts preserve both failures without claiming process exit. A working-directory resolution failure rejects before anything is spawned. Non-cancellation rejections expose only fixed provider, stage, and category facts in their Error message; the original SDK failure remains on the internal cause chain and in Host diagnostics.
The working directory resolves exactly like the ACP backend, through the seam's shared out-of-process helpers ([`dsh-subagent`](../subagent/README.md)): the configured `cwd` override when set (validated once at load), else the delegating parent session's cwd — never the server process's own cwd. The resolved path becomes the child process cwd and the workspace cwd of its SDK session.
@@ -6,7 +6,7 @@ SDK 提供方会在全新的子进程中把每个 subagent 作为完整的 DeepS
## 启动与所有权
`start(request)` 先解析子进程工作目录,通过 `DeepSeekHarness` spawn 运行时,并在履行前完成 `initialize` 握手(携带配置的 `provider`/`model` 路由及可选的 `maxTokens` 输出上限)。因此,履行意味着子运行时已就绪、所有权已移交给调用方。spawn、握手或发布前取消失败时,只会在子进程被回收后拒绝;工作目录解析失败则会在尚未 spawn 任何内容时拒绝。非取消拒绝的 Error 消息只公开固定的 provider、stage 与 category 事实;原始 SDK 失败仍保留在内部 cause 链和 Host 诊断中。
`start(request)` 先解析子进程工作目录,通过 `DeepSeekHarness` spawn 运行时,并在履行前完成 `initialize` 握手(携带配置的 `provider`/`model` 路由及可选的 `maxTokens` 输出上限)。因此,履行意味着子运行时已就绪、所有权已移交给调用方。spawn、握手或发布前取消失败通常会在子进程被回收后拒绝;若清理自身也拒绝,有序的安全 initialize/shutdown 事实会保留两项失败,但不会宣称进程已经退出。工作目录解析失败则会在尚未 spawn 任何内容时拒绝。非取消拒绝的 Error 消息只公开固定的 provider、stage 与 category 事实;原始 SDK 失败仍保留在内部 cause 链和 Host 诊断中。
工作目录的解析与 ACP 后端完全一致,并使用 seam 共享的进程外辅助工具([`dsh-subagent`](../subagent/README.zh.md)):设置了 `cwd` 覆盖值时使用该值(加载时校验一次),否则使用发起委派的父会话 cwd,绝不使用服务器进程自身的 cwd。解析出的路径同时成为子进程 cwd 和其 SDK 会话的工作区 cwd。
@@ -207,9 +207,10 @@ function sdkStartupFailure(spec: SdkRunSpec, error: unknown): Error {
/**
* Start and publish one SDK runtime child after its `initialize` handshake.
* Child failures resolve through the run result; startup and shutdown failures
* reject with fixed safe facts after process reap, retaining original causes
* for Host observation. Disposal shuts the runtime down and reaps it.
* Child failures resolve through the run result. Startup rejects with fixed
* safe facts after SDK-owned cleanup; successful cleanup proves process reap,
* while cleanup failure preserves both causes without claiming quiescence.
* Disposal shuts the runtime down and reaps it.
* @param request - the start request; its signal is the cancellation channel.
* @param spec - the resolved spawn spec: command/args/cwd, the child's
* provider/model route, env, timeouts, and the optional error sink.