Exit codes
Rune propagates the child's exact exit code. Tools speak through codes, and a runner that collapses them to 0 and 1 destroys the only signal a CI job has.
The table
Ctrl+C
The interrupt reaches every process attached to the terminal, including Rune and the child. Rune records the signal and keeps waiting. It never exits before the child does.
What Rune reports is therefore the child's own outcome:
This matches npm run. A build script that catches the interrupt and finishes writing its output
is a success, and treating it as a failure would be wrong.
Two collisions worth knowing
Rune's own errors exit 1, and so do many children. A config error and a failing test suite are
indistinguishable by code alone. The distinguishing signal is stderr: Rune's own failures always
write a diagnostic there and produce no output on stdout. npm and just accept the same collision.
The timeout code is 124, matching GNU timeout. A child that exits 124 on its own is
indistinguishable by code. Rune prints the reason to stderr when it is the one that decided:
Wide statuses on Windows
A Windows exit status uses all 32 bits, and Ctrl+C reports 0xC000013A. Rune passes it through
unchanged rather than truncating it to a byte. Truncation would turn "the user pressed Ctrl+C" into
"the script failed with 58", which a CI job would then act on.
Signal deaths on POSIX
128 + n is the shell convention, and it is what $? shows after a signal death.
Windows has no POSIX signals, and an exit status there carries none.
Checking in CI
Nothing needs unwrapping. A job that branched on npm run test's code branches on the same values
after the switch to Rune.