Six one-shot cross-node request verbs in `spt-daemon/src/wan.rs` sent their record, finished their side, subscribed, and then read the reply in an **unbounded** loop whose only non-error exits are a decoded reply and a stream EOF. A peer that ACCEPTS the stream and then neither answers nor finishes it produces neither event, so the caller waits forever — `spt send` with no output and no diagnosis. Pre-existing since `ec360f16`; not a WEBSERVE regression.

## The fix is the carrier, not a budget at the call site

Handing a deadline to the blocking `Whole` carrier is **refused outright** (`ErrorKind::Unsupported`, `REQ-HAZARD-PUMP-IPC-DEADLINE`) because a timeout mid-frame abandons a half-read frame and desyncs the conn. Only `cold_start_pump`'s Split carrier bounds reads — the same discipline the cross-node digest pull already runs on.

The two carriers are **indistinguishable at the call site** (both a `&mut Brain`), and a comment in exactly that position had already failed to stop one wrong wiring. So the requirement is enforced rather than documented: one shared `refuse_unbounded_carrier`, called before any wire I/O, refusing by the verb's own name and naming `cold_start_pump` as the remedy.

## A budget expiry is a distinct outcome

`NoReply` already means the receiver **finished** the stream without a reply frame — an old or refusing node, whose remedy is at that node's version. A peer still **holding** the stream is a wedged or overloaded one, and there is nothing there to upgrade. Reporting the second as the first sends an operator to fix the wrong thing, so each family grows its own expiry variant and its own CLI line.

`request_presence` is the one that could not take a variant, and says so instead of pretending: its outcome type is the WIRE enum, where every variant owes `PresenceReply::of` a token no peer could ever send for a locally-observed silence. It gets `PresenceRequestOutcome { Answered(Presence), PeerSilent }` instead; the published `endpoint list` column still renders `Unknown` — which asserts *nothing* ("nobody could tell"), true of a silent peer — so the flattening happens only at the seam whose vocabulary is published.

## The 14 call sites — which caller could still hand a `Whole` brain to a refusing seam

This is the table that answers the operational question. Every call site of the six verbs, with the
carrier it holds **after** this change; all fourteen are pump-mode, so no caller can reach a refusal
in production or in a rig.

| # | Call site | Carrier |
|---|---|---|
| 1 | `wansend.rs:504` `request_wan` | `cold_start_pump` :382 |
| 2 | `wansend.rs:658` `request_knock` | `cold_start_pump` :638 |
| 3 | `wansend.rs:709` `request_presence` | `cold_start_pump` :691 |
| 4 | `wansend.rs:852` `request_fork` | `cold_start_pump` :832 |
| 5 | `wansend.rs:1785` `request_redeem` | `cold_start_pump` :1767 |
| 6 | `wansend.rs:1860` `request_answer` | `cold_start_pump` :1842 |
| 7 | `twohost.rs:1625` `request_answer` | `ack_brain` :1602 — already pump |
| 8 | `twohost.rs:1757` `request_wan` | `answer_brain` :1737 — `connect_retry_pump` |
| 9 | `twohost.rs:1770` `request_wan` | `answer_brain` :1737 — `connect_retry_pump` |
| 10 | `twohost.rs:2946` `request_redeem` | `redeem_brain` :2918 — already pump |
| 11 | `twohost.rs:2989` `request_wan` | `reply_brain` :2970 — `connect_retry_pump` |
| 12 | `twohost.rs:3230` `request_wan` | `seal_brain` :3207 — `connect_retry_pump` |
| 13 | `twohost.rs:3294` `request_wan` | `done_brain` :3279 — `connect_retry_pump` |
| 14 | `twohost_web.rs:544` `request_wan` | `brain` :521 — `cold_start_pump` |

The rigs got a `connect_retry_pump` **sibling**; `connect_retry` is deliberately untouched, because
the refusal cell needs a blocking carrier to refuse.

## Where the mechanism is installed

A different census, answering a different question — seven refusals, and the seven pump-mode
carrier constructions that satisfy them:

| # | Refusal (`refuse_unbounded_carrier`, before any wire I/O) | Verb named in the refusal |
|---|---|---|
| 1 | `wan.rs:319` `request_wan` | a cross-node message send |
| 2 | `wan.rs:483` `request_fork` | a cross-node fork request |
| 3 | `wan.rs:601` `request_redeem` | a cross-node code redemption |
| 4 | `wan.rs:687` `request_answer` | a cross-node answer receipt |
| 5 | `wan.rs:797` `request_knock` | a cross-node knock |
| 6 | `wan.rs:889` `request_presence` | a cross-node presence probe |
| 7 | `digestlink.rs:221` `request_digest_pull` | (pre-existing; the helper was lifted from here) |

| # | Carrier construction (`Brain::cold_start_pump`) | Path |
|---|---|---|
| 8 | `wansend.rs:382` | message send |
| 9 | `wansend.rs:638` | knock |
| 10 | `wansend.rs:691` | presence probe |
| 11 | `wansend.rs:832` | fork |
| 12 | `wansend.rs:1260` | digest pull (pre-existing) |
| 13 | `wansend.rs:1767` | redeem |
| 14 | `wansend.rs:1842` | answer receipt |

## Commits

| sha | what |
|---|---|
| `168c8622` | the message send: shared refusal helper, `WanRequestOutcome::PeerSilent`, bounded loop, `WAN_PEER_SILENT` |
| `5ca85851` | `WAN_PEER_SILENT` joins the published closed set of WAN failure tags (adapters build blind from that page) |
| `f6eaa935` | the five siblings: fork, redeem, answer, knock, presence — plus their docs, cells and the two walk lists |
| `54259091` | comment-only: each redeem line gets back the doc block and tag that describe it |

## What was measured

Every leg's exit status captured **unpiped**, in its own file, on this branch and again in the gater's own pool at `f6eaa935`:

- `cargo build -p spt -p spt-daemon` — 0, zero warnings
- `cargo test -p spt -p spt-daemon --no-run` — 0 (this is what proves `twohost` / `twohost_web` still compile against the four changed outcome families)
- `cargo test -p spt --bin spt` — 0; the five named cells, including the first-ever execution of `a_silent_peer_is_classified_apart_from_an_unconfirmed_one` (written in `168c8622`, never run: `spt` is a binary crate, so `--lib` finds nothing)
- `cargo test -p spt-daemon --test wan_reply_bound` — 0; 4 passed in 6.5 s, including `every_sibling_verb_ends_a_silent_peers_wait_with_its_own_outcome` (all five verbs against one real, dialable, dispatcher-less broker, each on its own carrier and its own dial) and `every_sibling_verb_refuses_an_unbounded_carrier_by_name`
- `clippy -D warnings` — 0
- `traceable-reqs check` — 0; `REQ-WAN-REPLY-BOUND` `[OK] +doc +impl +unit +int`

The int cells assert the **elapsed** against the budget rather than merely surviving, so a return for some unrelated instant reason cannot pass as the budget firing.

## Docs

`WAN_PEER_SILENT` and `FORK_PEER_SILENT` join the two surfaces that publish a closed set, and the redeem table gains its row with the paragraph beneath it generalised so it is not outrun by its own table. `knock`, `answer` and `presence` publish no such surface anywhere in `docs-site` — no row was invented for them, and the `KNOCK_UNCONFIRMED` gap is being tracked separately rather than quietly filled here.

Closes BigscreenVR/spt-bs-releases#289.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_015SQWGdNjq4sUbTzPQMLEQA
