Goal
Deliver ReliaBLE's headline reliability promise: automatic reconnection with exponential backoff for dropped connections, plus the connection-stability status updates that report reconnection progress.
Addresses:
- FR-1.2 — Ensure automatic reconnection attempts with exponential backoff for failed connections.
- FR-1.3.1 — Provide status updates on connection stability (extends the
.reconnecting story established by the connection lifecycle work).
High-level summary
When a connected peripheral drops unexpectedly (or an initial connection fails transiently), ReliaBLE should automatically attempt to reconnect using exponential backoff (with jitter and a configurable cap / max-attempt policy via ReliaBLEConfig), rather than requiring the integrating app to manually retry. Reconnection progress (.reconnecting, attempt count, next-retry timing) should surface through the same connection-state stream introduced upstream so apps can reflect stability in their UI.
Blocked by
Sketch of scope
- Backoff policy (base delay, multiplier, max delay, max attempts, jitter) configurable via
ReliaBLEConfig.
- Distinguish app-initiated disconnects (no auto-reconnect) from unexpected drops (auto-reconnect).
- Emit
.reconnecting / attempt metadata on the connection-state stream.
- Cancel/stop reconnection on explicit disconnect or when the app opts out.
- Mock-driven tests covering backoff scheduling, give-up after max attempts, and successful recovery.
Acceptance criteria
- Unexpected disconnects trigger automatic reconnection with exponential backoff.
- Backoff parameters are configurable; sane defaults provided.
- Reconnection status is observable via the connection-state stream.
- Explicit disconnects do not trigger reconnection.
- Mock-driven tests cover the backoff and recovery paths (no real radio).
References
Demo app (ship alongside this work)
Auto-reconnect is ReliaBLE's headline feature, so the Demo's job is to make exponential backoff observable — a user should be able to pull a device out of range and watch the reconnection ladder. Builds on the Demo connection-state plumbing added in #36.
Scope (Demo)
- Surface reconnection progress — when the connection-state stream emits
.reconnecting, show attempt count and next-retry timing in the device-detail view, and optionally a small status badge on the device-list row.
- Expose backoff config — add a section to
SettingsView to tweak the ReliaBLEConfig backoff parameters (base delay, multiplier, max delay, max attempts, jitter) so the behavior can be exercised live.
- Demonstrate the disconnect semantics — visibly distinguish an app-initiated disconnect (settles to
.disconnected, no auto-reconnect) from an unexpected drop (enters .reconnecting). This is the manual acceptance check for "explicit disconnects do not trigger reconnection."
Acceptance criteria (Demo)
.reconnecting state (with attempt count / next-retry timing) is visible in the Demo UI.
- Backoff parameters are adjustable from
SettingsView and take effect.
- The Demo makes the explicit-disconnect vs. unexpected-drop distinction visually clear.
References (Demo)
Goal
Deliver ReliaBLE's headline reliability promise: automatic reconnection with exponential backoff for dropped connections, plus the connection-stability status updates that report reconnection progress.
Addresses:
.reconnectingstory established by the connection lifecycle work).High-level summary
When a connected peripheral drops unexpectedly (or an initial connection fails transiently), ReliaBLE should automatically attempt to reconnect using exponential backoff (with jitter and a configurable cap / max-attempt policy via
ReliaBLEConfig), rather than requiring the integrating app to manually retry. Reconnection progress (.reconnecting, attempt count, next-retry timing) should surface through the same connection-state stream introduced upstream so apps can reflect stability in their UI.Blocked by
ConnectionStatemodel to emit reconnection status, and hooks into the disconnect/fail delegate paths established there.Sketch of scope
ReliaBLEConfig..reconnecting/ attempt metadata on the connection-state stream.Acceptance criteria
References
AGENTS.md(@BluetoothActor, mock harness,ReliaBLEConfig)Demo app (ship alongside this work)
Auto-reconnect is ReliaBLE's headline feature, so the Demo's job is to make exponential backoff observable — a user should be able to pull a device out of range and watch the reconnection ladder. Builds on the Demo connection-state plumbing added in #36.
Scope (Demo)
.reconnecting, show attempt count and next-retry timing in the device-detail view, and optionally a small status badge on the device-list row.SettingsViewto tweak theReliaBLEConfigbackoff parameters (base delay, multiplier, max delay, max attempts, jitter) so the behavior can be exercised live..disconnected, no auto-reconnect) from an unexpected drop (enters.reconnecting). This is the manual acceptance check for "explicit disconnects do not trigger reconnection."Acceptance criteria (Demo)
.reconnectingstate (with attempt count / next-retry timing) is visible in the Demo UI.SettingsViewand take effect.References (Demo)
Demo/CLAUDE.md— Demo conventions and required build tooling; read first.Demo/ReliaBLE Demo/ReliaBLE Demo/Settings/SettingsView.swift— backoff config UI.