- subagent-sdk: the default registry name becomes `dsh-sdk` (the bare
`sdk` read ambiguously in configs); READMEs, config catalog, fixture,
and suites follow. The Loader fixture now omits providerName to exercise
the shipped default end to end.
- loader-composition.e2e: two full harness runtimes boot in sequence, so
the default 30s loader-smoke window times out under host load; raise the
subprocess deadline to 120s with matching vitest headroom (the
real-model.e2e precedent).
master already stabilized the raw-mode SIGINT scenario in 65e0ffe03 and
3be090f1d with wider scenario-owned bounds and deliberately delayed child
readiness, so the merge takes master's test implementation. What this branch
keeps is the contract that explains why those bounds are required: the note
paragraph on the settle boundary in PtySendOperation.append, and the
waitForOutput comment recording that raising its deadline alone cannot
recover output the send never collected.
- api: resolve a relative workspace cwd to absolute before the handshake —
the child spawns relative to the parent cwd, but the wire cwd is resolved
again inside the child, so a relative value double-resolved
(worker -> worker/worker).
- api: make the documented handshake retry real — HarnessClient.close() is
permanent, so a failed initialize now reaps the runtime and swaps in a
fresh client; DeepSeekHarness.close() is terminal and stops the respawns.
- api: validate session.event envelopes, assistant/message content, and
session.finished reasons at the wire boundary — a malformed runtime
surfaces as SdkProtocolError instead of type-invalid TurnResult data or a
TypeError out of finalResponse.
- client: a throwing subscribe() filter fails and detaches only its own
subscription (normalized to Error); sibling fan-out and the transport read
loop are undisturbed.
- client: NotificationSubscription.close() drops its queued notifications,
matching its documented contract; runtime-death fail() still leaves
already-delivered items drainable.
- client: subscribe() after close()/runtime death returns a born-failed
subscription so next() rejects instead of parking forever.
- client/transport: bounded requests abandon via AbortSignal — the transport
drops the pending entry at timeout, so repeated bounded calls against a
hung method retain no per-call state.
One test per finding; per-file coverage stays 100% on both packages.
The Agent Note paragraph recorded test-specific timing advice, which
docs/AGENTS.md excludes from implemented notes. The durable half of it —
LocalSendOperation.append drops output after settle, so it survives only in
the scrollback — now documents append itself.