The stdin/stdout claim now engages only in a normal process: the sys
stream backed by its real descriptor and fds 0-2 all open, which makes
it impossible for the private wire duplicates to land in the standard
range. Anything else - replaced streams, an incomplete descriptor
table, a failed dup - is served in place exactly as v1 was, and a
second concurrent stdio_server() raises RuntimeError instead of
contending for the streams.
This replaces the previous hardening (the dup-above-standard-range
loop, stderr-merge detection, and nested transports serving into the
diversion) with guards, and removes the migration entry: no working
code changes behavior, so there is nothing to migrate. Comments and
docstrings trimmed throughout the diff.
While serving on the process's real stdout, stdio_server now moves the
protocol pipe to a private descriptor and points fd 1 - and, on
Windows, the standard output handle - at stderr, restoring it when the
transport exits. A stray print() in handler code or a child process
writing to its inherited stdout lands in the client's log instead of
corrupting the JSON-RPC stream. The null device stands in when stderr
is unusable or, on POSIX, is detected as merged into stdout (2>&1).
The stdin claim generalizes into the shared _claim_fd mechanism: one
lock-guarded sentinel table covers both descriptors, private wire
duplicates are forced above the standard descriptor range so a process
started with a standard descriptor closed cannot hand the wire out as
its "stderr", and a failed claim degrades to serving the sys stream's
buffer in place exactly as v1 did.
Docs now describe the guarded behavior with its remaining gaps (output
flushed before serving begins, injected streams, merged stderr on
Windows), and the transport:stdio:stream-purity divergence narrows
accordingly.