cmux NEXT: Home says the daemon is too old only once it answers so (no flash while connecting)
In a restore launch, Home showed "Conversations need a newer cmux daemon." from 2012 to 2339 ms after process start, while the Chief owner was still connecting. It's the third finding of the launch recording in #23680. Leo: show nothing, or the snapshot, until the daemon actually answers with an old version.
Cause: ChiefConversationOwner.supports is connection != nil && …, so "still connecting" and "too old" were the same false. On top of that, HomeHostView added the placeholder label visible before its availability stream ran.
Change:
ChiefConversationOwner.refusalkeeps the handshake's refusal (DaemonCompatibility(refusal:): missing capabilities, another protocol, another app). It stays nil while connecting, after a timeout or a closed socket, and once connected.- A retry that times out after a refusal keeps the refusal.
HomeService.isRefusedreads it.HomeHostViewstarts with the label hidden and shows it only for a refusal or a migration notice. While connecting, the pane shows its fill (or the launch image) and nothing else.
Test: HomeDaemonNoticeTests. While the owner is connecting, or after a timeout, the notice is hidden. After a missingCapabilities refusal it shows, and a later timeout keeps it up.
Red, then green: the first commit adds the test and the owner state without the view change, so the test fails on it. The second commit is the fix.
Test fix after adoption (1632cbf4d32, 7c46910a1c6): the first version of the test looked for the notice among NSTextFields, but Home's notice is a ChromeLabel, so it never saw it (the connecting checks passed without looking, and its red came only from the refusal check, which could never pass). A failing #expect that captured the view also crashed the test process on the fleet (Swift Testing reflected a null NSPasteboard). The lookup now reads ChromeLabel text and the checks read plain booleans.
Observed / Not run
- Observed:
cmux-ci run ... suite Packages/macOS/CmuxNext HomeDaemonNoticeTestsat 1632cbf4d32: both tests pass. At 7c46910a1c6 (before the lookup fix) the refusal test failed with only hiddenNSTextFields found.cmux-ci compile-check --apppassed at 1632cbf4d32. - Not run: the fixed test against the pre-fix view (label visible while connecting); by reading,
noTooOldNoticeWhileTheOwnerIsStillConnectingfails there, since the label starts visible with this text.
What visibly changes: during launch, Home no longer flashes the too-old daemon notice; it shows only when the daemon really refused.
No capture: this removes a notice that flashed for ~330 ms while the daemon was connecting at launch; a capture tour shows the settled Home, which looks the same before and after. HomeDaemonNoticeTests pins when the notice shows.
Agent session: huge-blue
🤖 Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Fixes Home flashing a "Conversations need a newer cmux daemon" notice while the Chief conversation owner is still connecting. Home now shows the notice only once the daemon actually answers with a refusal, and keeps it hidden on timeouts or closed sockets.
ChiefConversationOwner.refusalkeeps the handshake's refusal, stays nil while connecting and after a timeout or closed socket, and clears as soon as a newer daemon's handshake succeeds so the notice takes down at once.HomeHostViewstarts with the label hidden and shows it only for a refusal or a migration notice.HomeDaemonNoticeTestspins the behavior, reports failures instead of crashing the test process, and finds the notice whether it is aChromeLabelor anNSTextField.