Every external command in Sources now runs through swift-subprocess instead of Foundation.Process. Three call sites read their pipes only after waitUntilExit, so any child writing more than the 64 KB pipe buffer would deadlock; git config --get-all and launchctl print can both exceed it. Two more blocked a cooperative thread from inside an async function. swift-subprocess drains both streams concurrently, so these cases disappear instead of being worked around. A new test reads a blob larger than the pipe buffer through GitCommandRunner.live, which had no direct test before and is where the deadlock would have surfaced.
Behavior is otherwise unchanged. Foundation.Process makes each child a process group leader and swift-subprocess does not, so the call sites set PlatformOptions.processGroupID = 0; without it the pager cannot claim the terminal foreground through tcsetpgrp. The pager still ignores SIGPIPE before writing and still tolerates a reader that quits early, now by inspecting SubprocessError instead of walking NSUnderlyingErrorKey. Collected output requires an explicit limit, so Git and launchctl reads cap at 8 MiB and git format-patch output at 128 MiB; both were previously unbounded.
One difference is worth recording: when a Task is cancelled, swift-subprocess terminates the child, while Foundation.Process left it running. No migrated call site runs under runCLIStreamingCommand, so nothing in the CLI relied on the old behavior.
Timeouts and cancellation propagation are deliberately left out so this change stays a mechanism swap. Tools/ManualSiteGenerator and the test helpers keep using Foundation.Process: they already read before waiting or redirect to temporary files, so they carry none of the defects above.