A program whose only pending work at the first has-work check is a process.stdin listener exits in ~10 ms with stdin still open — non-deterministically, 40–60% of runs.
Confirmed pre-existing on unmodified 757beace0: a probe binary built there is flaky 7/10. Adding any microtask (Promise.resolve().then(()=>{})) or timer makes it 10/10.
So the loop is emitted correctly and, once entered, holds; the gap is the first-iteration decision. #9407 added stdin_listeners_keep_loop_alive() for the runtime side of the liveness question — that is the predicate a codegen-side fix should consult when deciding whether to enter the loop at all.
claude-code is unaffected (it always has timers pending), which is why #9407's cc acceptance proofs are 5/5 — but any small stdin-driven program, which is the natural shape of a CLI filter, is affected.
Found while fixing #9399/#9400; filed separately because it is neither of those bugs and predates them.
A program whose only pending work at the first has-work check is a
process.stdinlistener exits in ~10 ms with stdin still open — non-deterministically, 40–60% of runs.Confirmed pre-existing on unmodified
757beace0: a probe binary built there is flaky 7/10. Adding any microtask (Promise.resolve().then(()=>{})) or timer makes it 10/10.So the loop is emitted correctly and, once entered, holds; the gap is the first-iteration decision. #9407 added
stdin_listeners_keep_loop_alive()for the runtime side of the liveness question — that is the predicate a codegen-side fix should consult when deciding whether to enter the loop at all.claude-code is unaffected (it always has timers pending), which is why #9407's cc acceptance proofs are 5/5 — but any small stdin-driven program, which is the natural shape of a CLI filter, is affected.
Found while fixing #9399/#9400; filed separately because it is neither of those bugs and predates them.