Summary
DaemonClient currently uses a request-scoped connection/session model (new Roam session per RPC). This is a bad fit for streaming semantics (subscribe(Tx<DataUpdate>)) and caused flaky/missed update delivery in LSP watcher flows.
What happened
During fixes for LSP multiroot watcher tests, watch_daemon_rebuilds observed frequent stream termination (rx.recv() -> None/Err) and lost update notifications. This manifested as stale diagnostics not clearing after file changes.
Current workaround (temporary)
We added resilience in LSP watcher logic:
- Treat channel receive failures as non-fatal.
- Fall back to polling
version() and publishing when version changes.
This unblocks tests and runtime behavior, but it is a workaround, not the target design.
Why this is bad
- Hides lifecycle bugs behind polling.
- Adds extra RPC churn/noise.
- Keeps streaming behavior less deterministic than it should be.
Upstream dependency
Related upstream issue: bearcove/vox#210
Once roam#210 is fixed (channel/session liveness contract corrected), we should remove the fallback polling and rely on clean stream semantics.
Follow-up plan
- Refactor
DaemonClient to persistent per-project sessions (or dedicated long-lived stream session for subscribe).
- Keep workaround only as a temporary guard.
- Remove workaround ASAP after verifying roam#210 fix in Tracey.
Acceptance criteria
- No per-call reconnect for normal daemon RPC traffic in LSP bridge path.
watch_daemon_rebuilds works from streaming updates without polling fallback.
- LSP watcher tests stay green under default timeout profile.
Summary
DaemonClientcurrently uses a request-scoped connection/session model (new Roam session per RPC). This is a bad fit for streaming semantics (subscribe(Tx<DataUpdate>)) and caused flaky/missed update delivery in LSP watcher flows.What happened
During fixes for LSP multiroot watcher tests,
watch_daemon_rebuildsobserved frequent stream termination (rx.recv() -> None/Err) and lost update notifications. This manifested as stale diagnostics not clearing after file changes.Current workaround (temporary)
We added resilience in LSP watcher logic:
version()and publishing when version changes.This unblocks tests and runtime behavior, but it is a workaround, not the target design.
Why this is bad
Upstream dependency
Related upstream issue: bearcove/vox#210
Once roam#210 is fixed (channel/session liveness contract corrected), we should remove the fallback polling and rely on clean stream semantics.
Follow-up plan
DaemonClientto persistent per-project sessions (or dedicated long-lived stream session forsubscribe).Acceptance criteria
watch_daemon_rebuildsworks from streaming updates without polling fallback.