Skip to content

Phase 3d: didModifyServices, re-discover every connection, restore discovery (FR-10.5–10.6) #64

Description

@itsniper

Parent: #52

Requirements

  • didModifyServices: mark not ready, park/fail discovery-dependent I/O, re-discover, re-arm subscriptions, surface event (FR-10.5.1).
  • Re-discover on every new connection; never reuse CB service/char refs across connections (FR-10.6.1–10.6.2).
  • Restore: discard catalog, re-discover intended peripherals, re-apply subscription intent; restored link is not ready (FR-10.6.3).
  • Document OS GATT cache / Service Changed 0x2A05 limitation (FR-10.5.3).

Lifecycle interactions (from #51)

  • "Intended peripherals" is now precise. At restore, intent = a rehydrated persisted manual-connect hold (id → reconnectDesired, keyed by restoreIdentifier). Work leases never survive process death, so no other intent source exists at launch.
  • Restored links without a hold must not be discovered. They start the idle timer and are torn down after the global interval (default 5s); running discovery on them wastes radio time and battery (NFR-3.2). Discover only restored peripherals with a rehydrated hold, or those that acquire demand inside the grace window.
  • A hold with reconnectDesired: false still suppresses idle. It rehydrates and keeps the link, so it is in scope for restore discovery even though neither reconnect tier is armed for it.
  • Catalog discard hooks invalidation, not just disconnect. invalidatePeripherals() now runs on .poweredOff in addition to resetting/unsupported/unauthorized, and clears all live CBPeripheral references. Discovery catalogs and readiness must be discarded there; demand is deliberately preserved across the outage, so the relink that follows must re-discover.
  • Re-discovery has one trigger point. Tier-0 OS reconnects, the Tier-1 ladder, the radio-return sweep, and rediscovery-driven relink all converge on the same ensure-linked path. Hook re-discovery to the connection-established transition so no reconnect source is missed.
  • Mock fidelity. Confirm whether CoreBluetoothMock can drive didModifyServices and GATT re-discovery before starting; willRestoreState cannot be synthesized post-init (State-restoration test fidelity: simulate willRestoreState in CoreBluetoothMock (retire actor-boundary-only coverage) #42) and Tier-0 give-up is not simulated (Tier-0 auto-reconnect give-up: replace testInjectDisconnect with mock support + on-device verification #40). File a sibling issue if GATT-change simulation is also missing.

Acceptance criteria

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions