Thanks, Kevin. That was a helpful explanation of the reasoning, and I tried exactly what you suggested.
What I implemented
AutoReconnect disabled entirely. connect() is called without CBConnectPeripheralOptionEnableAutoReconnect.
On disconnect: stopScan(). About 3 s before the peripheral's known advertising time, a fresh scanForPeripherals(withServices:) (service UUID filter, no duplicates).
On discovery: connect() immediately. If not connected ~10 s after the expected advertising time: cancel the pending connect, stopScan(), repeat at the next minute.
watchOS 26.6 (23U67), active HKWorkoutSession, Bluetooth logging profile installed. bluetoothd reported the app as background-running during reconnection.
Log lines below are trimmed, identifiers replaced by placeholders, times are local.
Result 1: Timed scanning works, but offers no apparent reception advantage
The peripheral's advertising time stayed stable within 0.1 s across all disconnects, so the scan windows were correctly positioned. bluetoothd performed passive scanning with a 30 ms window every 300 ms:
[LE.Scan] Starting passive scan (300.00ms/30.00ms) with duplicate filter enabled
For comparison, each pending connect() uses LE Extended Create Connection with 30/30 ms for the first ~6 s, then 300/30 ms. Thus, after the initial connection phase, both approaches use the same nominal scan interval/window.
When a scan window missed the peripheral, no advertising report from it appeared in the controller logs.
Result 2: The reduced reconnection range also applies to explicit scan + connect
All five link losses were supervision timeouts on connections established without AutoReconnect.
At the fifth disconnect, bluetoothd's disconnection history contained:
11:56:14.778 [LE.Connection] reason 708 time:2026-10-09 11:34:37.574
11:56:14.778 [LE.Connection] reason 708 time:2026-10-09 11:45:00.505
11:56:14.778 [LE.Connection] reason 708 time:2026-10-09 11:49:07.382
11:56:14.778 [LE.Connection] reason 708 time:2026-10-09 11:52:22.903
11:56:14.778 [LE.Connection] reason 708 time:2026-10-09 11:56:14.772
The crucial finding is that the reconnection restriction is applied even after a successful explicit scan discovery.
The app discovered the peripheral at -76 dBm and called connect() ~30 ms later:
11:57:24.374 [LE.Scan] Matched UUID <service> for device "<peripheral>"
11:57:24.406 [XPC] Received XPC message "CBMsgIdConnectPeripheral" from session "<app>-central"
11:57:24.406 [App] Connecting device "<peripheral>" for session "<app>-central" with options (connect:0 disconnect:0 notify:0 delay:0 ...)
11:57:24.406 [App] Device <peripheral> classicPaired 0, lePaired 0, discoveredViaLeScan 1
11:57:24.408 [LE.Connection] updateLeConnectionRSSIThresholdState for <peripheral> from 0 to 1
11:57:24.408 [LE.Connection] device "<peripheral>" ... filter accept list options: conn_cmpt_option=0, minRSSI=-70, PHYs=0
That connection never completed. Earlier in the same session, before the restriction engaged, connections at -86 and -94 dBm had succeeded.
Toggling Bluetooth off/on immediately cleared the state. The next connection, at -74 dBm, completed within 40 ms:
11:57:52.301 [Core] Powering off chipset
11:57:56.285 [Core] Powering on chipset
11:58:24.401 [LE.Connection] statedump: LeConnectionRSSIThresholdState History: 0 entries
Result 3: The restriction uses a 20,864-second counting window
On every connection attempt, bluetoothd logs:
getNumDisconnectionsBySignalQuality for <peripheral> over time window 20864.000000 count N
This corresponds to 5 h 47 min 44 s, and the same window value appears in our sysdiagnoses from September 29, September 30, and October 9.
On October 9, the count reached 5 at 11:57:24.408, precisely when updateLeConnectionRSSIThresholdState changed from 0 to 1.
We also observed the restriction clearing without user intervention: on September 29 it was active at 10:14, but at the next connection attempt at 18:02 the count was 0 and the threshold state returned to 0.
We haven't observed an individual disconnect aging out at exactly 20,864 seconds, but the logged window and observed expiration are consistent.
Interestingly, WWDC22 describes a rolling 24-hour window. We don't know whether this is a different mechanism or whether the implementation has changed.
Result 4: User interaction does not reset the restriction
In earlier runs with AutoReconnect enabled, the same restriction survived:
Bringing the app to the foreground and interacting with it
Navigating between views
Returning to the Home Screen and reopening the app
Ending and restarting the workout
Force-quitting and relaunching the app
Only toggling Bluetooth (or Airplane Mode with Bluetooth disabled) cleared it immediately. Otherwise, the restriction eventually expired.
Our own cancelPeripheralConnection disconnects (reason 722) did not contribute to the counter; supervision timeouts (reason 708) did.
This appears inconsistent with WWDC22 session 10135, which states that the reduced-reconnection-range limits are reset whenever the user interacts with the app.
Questions
Is this restriction intended to apply during an active HKWorkoutSession? As you explained, throttling Bluetooth activity provides little benefit while the app is already executing. Here, bluetoothd reports the app as background-running, and it explicitly initiates connect() immediately after discovering the peripheral.
Is there any supported way to avoid, detect, or reset this restriction? WWDC22 describes the mechanism in the context of Background BLE connections, with a rolling 24-hour window and a reset on user interaction. Our observations differ on all three points. Is this the same mechanism, or a different restriction?
Is this expected behavior or a watchOS bug? In particular, should the failure of the documented user-interaction reset be treated as a bug?
I have already filed Feedback Assistant report FB25101044, referencing DTS case 22079163 and including an earlier sysdiagnose captured with Apple's Bluetooth logging profile.
I also have the newer October 9 sysdiagnose documenting the explicit scan/connect experiment described above, including the threshold activation and Bluetooth reset. I can provide that through Feedback Assistant or DTS if useful.
Thanks again.