Problem
pty_run (added in #198 to regression-test the tty branch of cmd_unregister) fails when
the invoking shell's stdin is not a terminal — which is the normal case inside an agent
harness, a CI step, or any piped invocation:
script: tcgetattr/ioctl: Operation not supported on socket
Observed 2026-09-14: 3 failures in radio_lifecycle.bats's #198 pty tests during a local
full-suite run under an agent worker. They pass in isolation (61/61), pass on a clean
re-run (1013/1013), and CI is green on both runners — so it is intermittent, environment-
dependent, and not a product defect.
Why it's worth fixing rather than tolerating
A flaky test in the suite that verifies radio is corrosive in a specific way: it trains
whoever runs it to discount red. Today a worker correctly diagnosed it as pre-existing and
out of scope — the next one may instead spend a round chasing it, or worse, learn to
re-run until green. That habit is exactly what would have hidden #203.
BSD script (macOS) and util-linux script (Linux) both want a real tty on stdin to
allocate the pty. The helper already handles the syntax difference between the two; it
does not handle the precondition that stdin be a terminal.
Fix options
- Give
script a tty on stdin — < /dev/tty where available, so the helper doesn't
depend on inheriting one.
- Skip with a reason when no pty can be allocated.
bats' skip is honest and keeps
the suite green in harnesses that genuinely cannot provide one; CI (which can) still
exercises the branch, so coverage isn't lost where it matters.
- Both — prefer a real pty, skip explicitly when one is unobtainable.
(3) is the shape that keeps the signal and drops the noise. A silent skip would be worse
than the flake, so whichever path is taken the reason must be printed.
Acceptance
Notes
Found by the #191 worker during an intermediate full-suite run; correctly scoped out of
that PR since it touches neither pty_run nor radio_lifecycle.bats. Pre-existing
fragility introduced with #198, not a regression from #203/#191.
Problem
pty_run(added in #198 to regression-test the tty branch ofcmd_unregister) fails whenthe invoking shell's stdin is not a terminal — which is the normal case inside an agent
harness, a CI step, or any piped invocation:
Observed 2026-09-14: 3 failures in
radio_lifecycle.bats's #198 pty tests during a localfull-suite run under an agent worker. They pass in isolation (61/61), pass on a clean
re-run (1013/1013), and CI is green on both runners — so it is intermittent, environment-
dependent, and not a product defect.
Why it's worth fixing rather than tolerating
A flaky test in the suite that verifies radio is corrosive in a specific way: it trains
whoever runs it to discount red. Today a worker correctly diagnosed it as pre-existing and
out of scope — the next one may instead spend a round chasing it, or worse, learn to
re-run until green. That habit is exactly what would have hidden #203.
BSD
script(macOS) and util-linuxscript(Linux) both want a real tty on stdin toallocate the pty. The helper already handles the syntax difference between the two; it
does not handle the precondition that stdin be a terminal.
Fix options
scripta tty on stdin —< /dev/ttywhere available, so the helper doesn'tdepend on inheriting one.
bats'skipis honest and keepsthe suite green in harnesses that genuinely cannot provide one; CI (which can) still
exercises the branch, so coverage isn't lost where it matters.
(3) is the shape that keeps the signal and drops the noise. A silent skip would be worse
than the flake, so whichever path is taken the reason must be printed.
Acceptance
including both CI runners — not skipped away everywhere.
Notes
Found by the #191 worker during an intermediate full-suite run; correctly scoped out of
that PR since it touches neither
pty_runnorradio_lifecycle.bats. Pre-existingfragility introduced with #198, not a regression from #203/#191.