android / android (pull_request) Failing after 18s
ci / docs-site (pull_request) Successful in 1m7s
ci / web (pull_request) Successful in 1m9s
apple / swift (pull_request) Successful in 1m15s
apple / screenshots (pull_request) Skipped
ci / rust-arm64 (pull_request) Successful in 1m45s
ci / rust (pull_request) Successful in 6m9s
Unplug a pad mid-session and plug it back in, and roughly half the time it never rumbles again for the rest of the session. The removal arm restarted the pad's rumble sequence counter. The client's reorder gate does not restart: `rumble_last_seq` lives for the whole QUIC connection and has no reset path, so it still holds whatever the pad reached before the unplug. Restarting the host counter therefore hands the client a seq it has already seen, and its wrapping half-space compare drops every envelope until the counter climbs back past the stored value — up to 128 sends. Since the counter only advances on a level change or a ~120 ms renewal while a level is non-zero, that spans many separate rumble events, so it reads as a flaky controller rather than a clean outage. Whether it bites is decided by how much the pad rumbled beforehand, which is why it looks intermittent: a pad that never rumbled before the re-plug has `None` on the client side and always heals. The counter now survives, matching the sibling pad-state gate — whose comment eleven lines above already explains that a re-plug must arrive with a still- newer seq to be accepted. The three clears that actually end the stale lease move into `clear_pad_feedback`, whose signature deliberately has no seq parameter so the arm cannot regress by editing. Covered by a regression test that drives the real wire encoder and the real client gate, and asserts the pre-fix behaviour is genuinely rejected across the whole forward window, so it cannot pass vacuously. Found by the 2026-08-03 force-feedback sweep (B1/T5 — see the backlog in punktfunk-planning design/haptics-sweep-2026-08-03.md).