e5527d0201
Review 07 P7 (High): reads walked every reference of every device serially with no backoff, so a dead device cost Timeout per tag per poll (50 tags x 2 s = 100 s) and starved every healthy device long enough to trip the comms-loss watchdog against a reachable one. - ReadAsync buckets references by device and reads up to 8 devices concurrently; each device's tags are still read in order. - Each device has a ConnectionBackoff (1 s doubling to 30 s). Two consecutive comms faults mark it down: the rest of that pass and every later pass fail fast with BadCommunicationError and touch no wire until the window expires or any answer (data path or probe) resets it. One timing-out tag does not blacken its answering siblings. - Cold connects are single-flight per device (ConnectGate), replacing the per-key creation locks; a cached handle never touches the gate. - A status/exception proving the device ANSWERED with a deterministic refusal (not found, not allowed, out of bounds, type/size mismatch) is per-tag Bad, keeps its handle, warns once per tag and advances LastSuccessfulRead instead of evicting and degrading. Writes classify the same way. - Health is written once per read: Degraded if any device faulted, Healthy if anything read Good, LastSuccessfulRead advanced when any device answered. Adds an env-gated ab_server case with a blackholed sibling device. Refs #738 Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT