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.
sha256sum-or-shasum selection happens in preflight (macOS ships shasum,
not GNU coreutils) with a clear missing-tool hint; provisioning now waits
for every child and reports each named status before exiting, so a fast
failure can neither hand the EXIT trap a scratch tree that a still-running
install is writing into nor bury the root cause behind a downstream
symptom.
- 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.
AGENTS.md and the Wine Agent Note pair state the run policy: CI owns the
everyday win32 signal; run check:windows-wine only while investigating a
known Windows-related failure, and pre-push selection never includes it.
scripts/wine-windows-gates.sh owns the whole lane — workspace snapshot,
concurrent Node/wineboot/install provisioning, entrypoint resolution, the
vue link, smoke, and the two concurrent blocking gates — so the ci.yml
windows job shrinks to runner provisioning plus one script call, and
pnpm run check:windows-wine runs the identical script locally. The local
path never mutates the working tree, persists the Wine prefix and the
checksum-verified Windows Node zip under .cache/wine-windows/, and falls
back to the cached zip offline. AGENTS.md ceiling 1680 -> 1695 for the
one-line command entry.