acpmux: typing to a paused peer's chat wakes it before the send
Leo (2026-11-03):
Cuz the meme/dream is / You only resume when you absolutely need to / But when is that?
The model sometimes sees a delay and you sometimes see it after sending but it evens out to not much at all just a tiny bit of extra time that you mostly perceive as "thinking" / But it's all still responsive on the ui side
What changes
A chat on a peer whose link is down already asked that peer's route to wake a paused machine. It did so only when a message was refused (session/prompt, Peer::wake, ACPMUX_PEER_WAKE, as with the Freestyle pool slot's cloud-vm-up nc). So a paused machine began to resume after the person pressed Send.
Now a client's sign that a person is writing to that chat wakes it too:
_acpmux/typingwithon: true.forward_inneranswers typing itself (presence stays this daemon's own), so the wake happens there.- a non-blank
_acpmux/composer_set
_acpmux/draft_set is deliberately not a wake: the pane saves the chat it leaves unchanged when it switches away, and that is no one writing.
The resume runs while they type, so most of it is done by the time the message goes.
Unchanged:
- Typing off, a cleared draft and a peer daemon's forward still only want the link back, or ask nothing, as before.
- Background reconnects still never wake a machine (HQ#5074: passive reads never wake one).
- A draft that is never sent costs one resume. The machine's idle pause takes it back.
This is the "predictive resume" half of the policy in the owning research issue. The issue has the measurements, the transcript replay and the rest of the policy. Claude's stdio announces a tool_call only once its input is complete: p50 lead 0 s over 431k replayed calls. So the earliest usable signal for a turn's first resume is the person's typing. Within a turn it is the model's message_start.
Performance
Resume latency the person sees after Send, for a paused peer. "Before" is the measured path through the cmux app on production Freestyle. The person's typing time runs in parallel with the resume.
| metric | before | after | delta | harness |
|---|---|---|---|---|
| resume started, relative to Send | at Send (refused prompt) | at the first keystroke | resume starts one typing-time earlier | unit test typing_to_a_down_peers_chat_wakes_it_before_the_send |
resume call through the app, Freestyle small (8 cycles) | 0.22–0.6 s typical, 20.5 s outlier | hidden behind typing when typing takes longer than the resume | about −0.5 s per first message after a pause | guest 100 ms timestamp log, HQ research issue |
| user-perceived added latency per turn on active lane-days (281 days, replay, R = 1 s) | p95 0.4 s once a turn runs | unchanged within a turn | 0 | replay days.py, HQ research issue |
No timer, observer or loop is added. The wake mark is the existing WAKE_FOR window, which lapses by itself.
Tests
server::peer_forward::tests::typing_to_a_down_peers_chat_wakes_it_before_the_send, new.only_a_message_asks_a_down_peers_route_to_wake_it, updated for the newparamsargument.
cmux-ci test -- cargo test -p acpmux --lib -- peer_forward: 8 passed at bfb8cc7ec (fast checks run 41726599751). Rerun with clippy at the fixed head below.
🤖 Generated with Claude Code
Agent session: agent session