diff --git a/docs/architecture/010-commander-claude-bridge.md b/docs/architecture/010-commander-claude-bridge.md index 9de1cf5..57beecb 100644 --- a/docs/architecture/010-commander-claude-bridge.md +++ b/docs/architecture/010-commander-claude-bridge.md @@ -159,11 +159,20 @@ to `unknown`. Every listener, timer, and abort handler is removed on every settle path. A forced settlement also destroys the local stdout and stderr pipe ends, and stdout or stderr read errors are contained until the child close path reports -the provider-neutral outcome. The function resolves exactly one frozen record -on every validation, spawn, I/O, timeout, cancellation, overflow, termination, -and close path. It never rejects. Catches wrap only defined operational -failures, so a programmer defect still surfaces as a defect rather than being -laundered into a failure code. +the provider-neutral outcome. For the defined operational results the transport +represents as exchange outcomes — validation, spawn, I/O, timeout, +cancellation, overflow, termination, and close — the function resolves exactly +one frozen record. Nothing outside that handled set is promised to resolve. It +rejects deliberately, rather than reporting an outcome, when mandatory +post-spawn child-dispatch hardening cannot be established: the transport runs +its bounded, platform-qualified termination procedure, destroys the local +stdout and stderr ends, clears the child's listeners, re-arms the spawn-failure +absorber over the cleared handle, and then rejects. The local stdin end is left +as it is, and termination stays a request rather than a completion guarantee. +That rejection is not `SPAWN_FAILED` and is not an exchange outcome at all. +Catches wrap only defined operational failures, so a programmer or +security-boundary defect still surfaces as a defect rather than being laundered +into a failure code. ## Termination is qualified, and the limit is disclosed diff --git a/src/adapters/process-transport.ts b/src/adapters/process-transport.ts index 40b7919..7c4c054 100644 --- a/src/adapters/process-transport.ts +++ b/src/adapters/process-transport.ts @@ -599,12 +599,21 @@ async function terminate( /** * Run one process exchange. * - * **Total.** Resolves to exactly one frozen {@link AgentExchange} on every - * validation, spawn, I/O, timeout, cancellation, overflow, termination, and - * close path. It never rejects and never throws by design. Catches are placed - * only around defined operational failures — `spawn`, `kill`, a broken stdin - * pipe, a hostile `AbortSignal` getter — so a programmer defect still surfaces - * as a defect rather than being laundered into a failure code. + * **Defined operational results.** For the defined operational results this + * transport represents as exchange outcomes — validation, spawn, I/O, + * timeout, cancellation, overflow, termination, and close — resolves to + * exactly one frozen {@link AgentExchange}. Nothing outside that handled set + * is promised to resolve. Deliberate fail-closed rejection: when mandatory + * post-spawn child-dispatch hardening cannot be established, the transport + * runs its bounded, platform-qualified termination procedure, destroys the + * local stdout and stderr ends, clears the child's listeners, re-arms the + * spawn-failure absorber over the cleared handle, and then rejects. The local + * stdin end is left as it is, and termination stays a request rather than a + * completion guarantee. That rejection is not `SPAWN_FAILED` and is not an + * `AgentExchange` outcome at all. Catches are placed only around defined + * operational failures — `spawn`, `kill`, a broken stdin pipe, a hostile + * `AbortSignal` getter — so a programmer or security-boundary defect still + * surfaces as a defect rather than being laundered into a failure code. * * **Deterministic precedence.** Every detected terminal cause is compared with * `TERMINAL_CAUSE_PRECEDENCE`; callback arrival order cannot demote a stronger