cli: cover the bridge's stdout-loss path #232

Merged
natsukium merged 1 commit from issue-166 into main 2026-09-08 21:56:47 +09:00
Owner

The golden felis bridge conversations cover the clean terminal, the failing terminal before the first item, cancel, and daemon loss, but stdout loss is not among them — and it cannot be: the channel that would carry a correlated error is the one that failed, so the bridge publishes nothing and there is no transcript to diff. This lands it as a plain assertion test beside the goldens rather than extending the fixture format with a reader-closing directive.

The bridge harness gains close_stdout (dropping the read end is the only way to fail a child's stdout from outside) and an exit path that leaves stdin open, so a status can only come from the bridge's own decision. The new test serves one reply, parks the daemon mid-verb so a second operation is genuinely in flight, closes the read end, and asserts exit 1, that the served reply is all stdout ever carried, and that stderr stays human-only. Removing the close_stdout call makes it hang and fail, so it is not vacuous. The pre-existing stdout_failure_stops_the_bridge_without_waiting_for_stdin_eof case moves onto the same harness and gains the stderr assertion it previously discarded with Stdio::null().

Test-only; no documented behavior changes, so no doc or CHANGELOG cascade.

Fixes #166

The golden `felis bridge` conversations cover the clean terminal, the failing terminal before the first item, cancel, and daemon loss, but stdout loss is not among them — and it cannot be: the channel that would carry a correlated error is the one that failed, so the bridge publishes nothing and there is no transcript to diff. This lands it as a plain assertion test beside the goldens rather than extending the fixture format with a reader-closing directive. The bridge harness gains `close_stdout` (dropping the read end is the only way to fail a child's stdout from outside) and an exit path that leaves stdin open, so a status can only come from the bridge's own decision. The new test serves one reply, parks the daemon mid-verb so a second operation is genuinely in flight, closes the read end, and asserts exit `1`, that the served reply is all stdout ever carried, and that stderr stays human-only. Removing the `close_stdout` call makes it hang and fail, so it is not vacuous. The pre-existing `stdout_failure_stops_the_bridge_without_waiting_for_stdin_eof` case moves onto the same harness and gains the stderr assertion it previously discarded with `Stdio::null()`. Test-only; no documented behavior changes, so no doc or CHANGELOG cascade. Fixes #166
cli: pin the bridge's stdout loss under an in-flight operation
All checks were successful
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
bench / Criterion regression gate (pull_request) Successful in 2m4s
darwin / detect relevant changes (pull_request) Successful in 3s
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 50s
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m10s
pr / nix flake check (pull_request) Successful in 30s
pr / cargo build / clippy / test / deny (pull_request) Successful in 1m46s
pr / wire schema is compatible with the base (pull_request) Successful in 8s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 54s
pr / publish felis (x86_64-linux) (pull_request) Has been skipped
windows / detect relevant changes (pull_request) Successful in 3s
windows / windows docs-only no-op (pull_request) Has been skipped
windows / cargo nextest (Windows) (pull_request) Successful in 4m32s
windows / frontend smoke (Windows) (pull_request) Successful in 2m1s
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been skipped
windows / cargo clippy (Windows cross) (pull_request) Successful in 14s
e390789ee5
The golden bridge conversations cover every terminal path, but a stdout
loss has no terminal: the channel that would carry a correlated error is
the one that failed, so the bridge stops every operation and exits 1 with
nothing on stdout. That shape cannot be diffed as a transcript, so it is
a plain assertion test rather than a fixture directive for closing the
reader.

The existing coverage closed the reader before the bridge had written
anything and ignored stderr. Closing it while the daemon is parked mid-
verb puts a real operation in flight at the moment stdout dies, and
capturing stderr pins that the failure stays human-only there instead of
leaking a protocol object onto the one channel still open.

Assisted-by: Claude Code
natsukium deleted branch issue-166 2026-09-08 21:56:47 +09:00
Sign in to join this conversation.
No description provided.