Stale-GATT recovery and readable-device polling
Candidate: 4c417a58f59c612e06f8a2183fa77c1b81f9b4b4, based on master 4202c4a (includes #297).
- Recovery pending state survives Home Assistant setup retries and replacement coordinators.
- Public native cache eviction precedes bounded bootstrap/reconnect recovery; exact chained BlueZ
GattService1failures are recognized. - Preserves current profile-driven setup, encryption, optional readback, transaction ordering and idle release.
- Owner-requested follow-up restores 30-second polling for readable devices, including short-idle profiles.
Validation: full make check passed (2,366 Python tests; 79 skipped; frontend, browser, generation, lint and typing checks). GitHub Check, Hassfest and HACS passed. Independent recovery and polling reviews approved.
Installed this exact tag through HACS and restarted Home Assistant; both target devices report runtime 7.6.2rc2. Observed three automatic polling/release cycles on each device without issuing refresh commands. Owner changed cupboard brightness to 10% in the Govee app, disconnected the app, and HA learned 10% through automatic polling. Restored cupboard to 5% Candlelight; Dream TV remains on at the owner's request. Cupboard automations restored and verified enabled.
RC1 also qualified ordinary power, RGB, scene, reconnect, multipart preview/cancel, and H6199 music/video/native controls; detailed evidence and readback/restoration qualifications are recorded on PR #249.
Actual stale-cache failure was not reproduced on hardware. Deterministic lifecycle and real ESPHome backend tests establish the recovery mechanics. Public APIs cannot guarantee eviction when ESPHome establishment never returns a client, or eviction of every proxy cache. Polling refreshes supported state after app disconnection; it does not promise simultaneous BLE ownership or complete decoding of every app effect.
ZIP SHA-256: 38edc09e1f3cc423c91dc0a66d68bbc9ecc581c670c8bed16382dbc3149da073 (downloaded checksum verified).