Problem
PR #1112 (fix(transport): unblock read_messages when the CLI dies but stream stays open) has a fix that contradicts the P1 prediction. The code path raises ProcessError only on nonzero returncode, but for clean exit the teardown path is not triggered.
Impact
- The grace window of 2s is a guess - production CLIs routinely buffer >2s of stdout (model streaming output)
- On a non-orphan death with slow streaming, this fix will spuriously close the stream
- The "failing-first" test is theatre - tests assert the watcher's
aclose() call (test's own) which proves nothing
What was audited
MCE audit Tcas1112 (2026-07-19) caught 3 HIGH attacks via F-C:
- The grace window is a guess, not a guarantee - production CLIs routinely buffer >2s of stdout
- The "failing-first" test is theatre - tests assert that the watcher's aclose() call raises from the test's own call
- P1 (read_messages unblocks when CLI dies, p=0.85) is contradicted by the code itself - when the process exits 0, the code path raises ProcessError only on nonzero returncode
Recommended fix
- The author should:
a. Handle the clean exit case explicitly (not just nonzero returncode)
b. Increase the grace window OR make it configurable
c. Write failing-first tests that simulate real CLI death scenarios
Cross-references
Problem
PR #1112 (fix(transport): unblock read_messages when the CLI dies but stream stays open) has a fix that contradicts the P1 prediction. The code path raises
ProcessErroronly on nonzero returncode, but for clean exit the teardown path is not triggered.Impact
aclose()call (test's own) which proves nothingWhat was audited
MCE audit Tcas1112 (2026-07-19) caught 3 HIGH attacks via F-C:
Recommended fix
a. Handle the clean exit case explicitly (not just nonzero returncode)
b. Increase the grace window OR make it configurable
c. Write failing-first tests that simulate real CLI death scenarios
Cross-references