# M2a task 14: pass the upstream's close on to the client (review follow-up) **Branch:** `m2a` (run `git switch m2a`; `git status --short` must be empty, otherwise stop) **Commit subject:** `Close the client side when the upstream closes, in inferproxy` ## Goal The M2a review found that `inferproxy` only closes towards the client after the client has stopped sending. `loopd`'s HTTP client never stops sending on its own: it keeps its side open until it drops the connection. So when `llama-server` closes, or dies in the middle of an answer, the client is not told; it sits until its own liveness timeout and reports `Stalled` instead of `StreamClosedEarly`, thirty seconds late. A body that runs to the close would hang the same way. Task 02, rule 3, said: "When the server stops sending, the exchange is over: close both." The current code waits for both copy threads to finish instead. This was partly the plan's fault: every test client in `forward.rs` half-closed after sending, so the gap could not show. The new test sends without half-closing. ## Files - Copy (replacing the old one): `crates/inferproxy/tests/forward.rs` - Modify: `crates/inferproxy/src/lib.rs`, `docs/implementer-log.md` ## Required behaviour - When the server-to-client copy ends, for any reason, shut down the client connection (both directions) and the server connection, so that the client's read returns 0 at once and the client-to-server copy thread ends. Do this **after** releasing the open-connection place, as rule 4 of task 02 requires. - Everything else from task 02 still holds, including the half-close when the client stops sending first. ## Steps - [ ] **1. Copy.** `git switch m2a`, then `cp docs/plans/M2a/files/crates/inferproxy/tests/forward.rs crates/inferproxy/tests/` - [ ] **2. See it fail.** `cargo test -p inferproxy --test forward`. Expected: 1 of 7 fails, `the_upstreams_close_reaches_a_client_that_is_still_sending`, with a timeout. - [ ] **3. Fix `lib.rs`.** Run `cargo fmt --all`. - [ ] **4. See it pass.** `cargo test -p inferproxy --test forward`, ten times in a row. Expected: `7 passed` every time. - [ ] **5. Run the gate.** `make gate`. Expected last line: `gate: ok`. - [ ] **6. Log and commit.** `git add crates/inferproxy docs/implementer-log.md && git commit` ## Done when - `cargo test -p inferproxy --test forward` reports 7 passed, ten runs in a row; `make gate` prints `gate: ok`; `cmp crates/inferproxy/tests/forward.rs docs/plans/M2a/files/crates/inferproxy/tests/forward.rs` prints nothing. ## Stop and report if - Passing the new test breaks `forwards_both_ways_and_passes_the_half_close_on`.