Summary
A TUI starting during managed-daemon replacement should survive the handoff. If its initial transport disappears, startup should rediscover the winning registration and retry instead of exiting with a raw transport error.
Current state
The original incident produced seven live service candidates because concurrent starts raced through registration. V2 now elects one service process with a channel-scoped file lock (dd842f9; related PR #35826), so the many-candidate race described in the original report is no longer the current architecture.
The remaining client-side requirement is still valid: a startup transport can disappear during intentional daemon replacement. Event-stream reconnect already rediscovers the managed service, but initial TUI hydration/API requests can fail before that recovery path owns startup.
Expected behavior
- Fresh startup may replace a healthy version-mismatched daemon according to service policy.
- Concurrent service candidates elect one owner.
- A TUI whose startup transport disappears rediscovers the current registration and retries bounded initial hydration.
- The user does not need to launch OpenCode a second time.
- Explicit
--server failures remain loud; only managed-service startup uses rediscovery.
Acceptance criteria
- Reproduce a daemon handoff between transport discovery and initial TUI hydration.
- The first TUI invocation rediscoveries the winning managed daemon and completes startup.
- Retry is bounded and does not create restart authority beyond ordinary
Service.start policy.
- Multiple concurrent clients converge on the elected daemon.
- Tests cover transport loss before the event stream connects and during initial hydration.
Original observation
Observed on macOS while upgrading 0.0.0-next-15078 to 0.0.0-next-15081: the first TUI exited with a transport error and a second invocation succeeded after registration stabilized.
Discussion: https://slack.com/archives/C0BE69AHCQP/p1783527674019519
Summary
A TUI starting during managed-daemon replacement should survive the handoff. If its initial transport disappears, startup should rediscover the winning registration and retry instead of exiting with a raw transport error.
Current state
The original incident produced seven live service candidates because concurrent starts raced through registration. V2 now elects one service process with a channel-scoped file lock (
dd842f9; related PR #35826), so the many-candidate race described in the original report is no longer the current architecture.The remaining client-side requirement is still valid: a startup transport can disappear during intentional daemon replacement. Event-stream reconnect already rediscovers the managed service, but initial TUI hydration/API requests can fail before that recovery path owns startup.
Expected behavior
--serverfailures remain loud; only managed-service startup uses rediscovery.Acceptance criteria
Service.startpolicy.Original observation
Observed on macOS while upgrading
0.0.0-next-15078to0.0.0-next-15081: the first TUI exited with a transport error and a second invocation succeeded after registration stabilized.Discussion: https://slack.com/archives/C0BE69AHCQP/p1783527674019519