Commit 772d6cd
committed
fix(presets): three Linux preset-launch bugs (leak, intermittence, phantom prompt)
Three races that only manifested on the `#[cfg(unix)]` daemon-backed
spawn path — Windows uses in-process spawn and was unaffected.
1. Prompt leak. The daemon spawn's "synthesize a relaunch command
from in-memory original_command" branch fired on every fresh
preset launch, racing apply_preset's own write_command_when_ready.
Both wrote the command; the second landed in the just-started
agent's input box. New `should_synthesize_agent_relaunch` gate
restricts synthesis to genuine relaunches (disk meta or captured
agent UUID), so fresh preset launches get exactly one write from
apply_preset.
2. Intermittent launch. With the synthesis duplicate removed,
apply_preset's writer-poll thread was the only path firing the
command — and its 5s budget was shared between Phase 1 (writer
ready) and Phase 2 (shell quiet). Slow daemon spawns (cold
pty_daemon, SSH-tunnelled remote) sometimes starved Phase 1, the
thread timed out before the writer appeared, and the click did
nothing. Split into independent budgets: 15s for Phase 1, 5s for
Phase 2.
3. Phantom prompt (command typed but not submitted). `DaemonWriter::
write` is fire-and-forget — each call spawns its own Tokio task
that round-trips a separate Write RPC. Writing command bytes and
the CR terminator in two `write_all` calls let the daemon receive
them out of order: CR first submitted an empty line and redrew
the prompt, then the command bytes landed at the new prompt with
no terminator. New `build_pty_command_payload` concatenates
command + CR into one buffer so a single write_all is one Tokio
spawn is one daemon RPC — atomic at the master fd.
Close-app/reopen Claude-resume flow is untouched: that path goes
through `resolve_resume_command` (disk_meta + adapter pair), not the
synthesis fallback this commit gates.
Tests pin all three regressions: should_synthesize_agent_relaunch
truth table (4 cases), test_slow_writer_then_quiet_detected (writer
lands at 7s, command still gets written), and
write_command_to_pty_uses_single_write_call (exactly one Write::write
syscall, breaks loudly if anyone refactors back to two).1 parent 872582b commit 772d6cd
2 files changed
Lines changed: 446 additions & 62 deletions
0 commit comments