ddf2c014f1
withTimeout wrapped a blocking process.waitFor() that coroutine cancellation can't interrupt, so a hung process hung the stage until it exited on its own; and destroyForcibly() killed only the direct child, leaving sh -c grandchildren (the real npm/tsc) as orphans. Use process.waitFor(timeout, MILLISECONDS) for an on-the-clock deadline, and kill via toHandle().descendants() + the parent.