## Request Addresses BigscreenVR/spt-bs-releases#293: a pump-mode Brain could enter an unbounded reply wait through read_event(), preventing the round from returning and the supervisor from recovering. Candidate: **9d71871905766e293322eb94ed0748d04d7aba75**. Supersedes d79831d1 and its cancelled CI run 34419667991. ## Change - Delete Brain::read_event; migrate all Rust callers, including tests, to read_event_until with an explicit deadline. - Reply waits compute the deadline after send and before the loop. Unrelated frames cannot renew it. peek_first_line remains a reply wait. - The nine serve_*_feed loops and attach serve loop use explicit `let deadline: Option = None`, with comments distinguishing subscriber lifetime from a call budget. Any future silence bound belongs per read, not per call. - Whole carriers retain io_timeout=None and their existing blocking semantics; no unsupported timeout is manufactured. - Add REQ-BRAIN-READ-BOUNDED-PER-CALL (doc/impl/int), including the stream-loop distinction, and real-IPC retirement regressions. - Reword the initial migration commit from wip(brain) to refactor(brain), retaining its body and Co-authored by trailer. ## Evidence - RED witnessed by hertz on de5a44bc: `cargo test -p spt-daemon --test pumpdeadline pump_terminal_retire -- --test-threads=1 --nocapture`: 0 passed, 2 failed at independent 3-second cutoffs; 6.01s execution. - GREEN rerun at 9d718719: `cargo check --workspace --all-targets --keep-going` passed; `cargo test -p spt-daemon --test pumpdeadline -- --test-threads=1 --nocapture` passed 5/5, 0 ignored/filtered, 2.21s execution. The complete target includes both retirement cells, missing broker reply, silent peer reply classification, and bounded image query. - `traceable-reqs check --json` at 9d718719: 893 requirements complete, zero findings. - Revised static half GREEN at 9d718719 independently from hertz and doyle. Hertz checked HEAD before and after: zero read_event calls/declarations across all Rust including tests; all nine named feed bodies and attach serve loop have explicit None and no call_deadline(); peek_first_line and Brain send-ack, stream-list, and retirement waits retain their hoisted reply deadlines. Deployah's independent rebind is pending. No permanent source-text test or nominal unit-stage claim. - PR CI runs the unchanged unit SET on Windows and Linux: `cargo build -p spt --bin translate_proof_fixture`, then `cargo nextest run --workspace -E 'kind(lib) + kind(bin)'`. This is separate from the explicit pumpdeadline target above; replacement CI results are pending, not claimed green. ## Feed lifetime: constructor and call-path proof Production feed servers do not receive the pump-mode client. dispatch::worker takes broker_name, constructs its own Brain via dispatch::connect, which calls Brain::cold_start (Whole/io_timeout=None), and passes that client to its family-specific serve loops. pump/mod.rs has no feed-server calls. In addition to that constructor fact, this candidate explicitly sets None in the nine feed loops and attach serve loop: a future caller supplying a finite-budget carrier cannot accidentally impose a total feed lifetime. peek_first_line intentionally retains call_deadline() because it waits for one reply, not a subscriber lifetime. This is source-path and budget-placement evidence; the short runtime tests are not offered as long-lived-feed proof. ## Assembly and limits - Assemble #289 (code PR #208) before #293. This lane includes the per-call request_wan correction; preserve the deadline outside its reply loop when integrating the overlap. - pump/mod.rs is unchanged. The two regression sites are integration cells in tests/pumpdeadline.rs, not modifications to pump/mod.rs. - Not established: which unbounded method parked the observed instance, why the broker stopped replying, or that 0.68.0 introduced the old unbounded API. This lane closes the unbounded-wait recovery hole, not the deferred broker root-cause question. - No golden run or production restart initiated by this PR.