From 7dc36c2632dd5edce678f0ae52438067a4572c27 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 23 Sep 2026 09:03:37 -0700 Subject: [PATCH] fix(ios): let a legacy untagged Mac row take pushed presence routes performPushedRouteSyncBatch has looked up the stored row by the exact pairing id (device + presence tag) since 5aedb51ea2. A row paired before instance tags existed is untagged, and presence always reports a tag, so the lookup never found it. applyPushedRoutes was handed nil and never wrote. Its untagged branch, reconnectRouteAuthority(pairedMacInstanceTag: nil), which lets a legacy row adopt its device's sole route-advertising build, had become unreachable. A legacy Mac that moved stopped getting fresh routes over presence. Fall back to the device's untagged row when there is no exact tagged match. applyPushedRoutes still requires the presence instance to be the device's only route-advertising build, and the upsert is still conditioned on the row's own (nil) tag, so a Mac with two builds online is not written. presenceRoutesForHiddenDuplicateRefreshOnlyTheEmittingRow covers this. On main it awaits pairedStore.waitUntilUpsertCount(1) forever, which is what hangs the serial CmuxMobileShell package run until the job timeout. Co-Authored-By: Claude Opus 5.5 --- .../MobileShellComposite+PresenceRouteSync.swift | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite+PresenceRouteSync.swift b/Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite+PresenceRouteSync.swift index b88d383e5d39..7d2299dbe5b6 100644 --- a/Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite+PresenceRouteSync.swift +++ b/Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite+PresenceRouteSync.swift @@ -190,9 +190,17 @@ extension MobileShellComposite { macDeviceID: instance.deviceId, instanceTag: instance.tag ) + // An untagged legacy row adopts its device's sole + // route-advertising build; `applyPushedRoutes` checks that + // this instance is that build before writing. + let legacyPairingID = MobilePairedMac.pairingID( + macDeviceID: instance.deviceId, + instanceTag: nil + ) if await self.applyPushedRoutes( from: instance, - pairedMac: pairedMacsByPairingID[pairingID], + pairedMac: pairedMacsByPairingID[pairingID] + ?? pairedMacsByPairingID[legacyPairingID], scope: scope ) { persistedRoutes = true