markConnected skipped onReconnect on the very first successful connect
(hasConnected=false branch), but an earlier failed attempt could have
already fired onDisconnect -> isConnected=false. Consumer state stayed
stuck at false forever. Fire onReconnect in that case too.
Repro: launch app while opencode sidecar is still warming up so the
first WS attempt fails. Second attempt succeeds but isConnected stays
false; user sees "Connection lost" toast on every send.