"Reconnecting…" indicator during the #115 reconnect-via-resume grace window #139

Closed
opened 2026-06-23 20:36:37 +02:00 by shipwright · 1 comment
Owner

Background

Follow-up surfaced during #115 (reconnect-via-resume, PR #138) review. Filed per substrate-for-decision discipline so the evidence stays attached while fresh — this is a tracker, not a build commitment; operator/Bosun prioritize (close as wontfix if not wanted).

The gap #115 opens

#93 (Option A) armed the "connection lost" overlay immediately on an accidental drop. #115 now attempts a seamless reconnect first, holding the last playing frame for up to RECONNECT_GRACE_MS (8s) before either:

  • succeeding → board re-syncs, no interruption (a clear win over #93), or
  • failing → the #93 overlay arms, then backToYard().

On the failure path, that's an up-to-8s frozen frame with no feedback that #93 didn't have. Surveyor's #138 review framed it precisely: an indicator fills a gap this PR opens, not gold-plating. Both Surveyor and I lean yes.

Proposed fix-shape (Shipwright lane, ~size S)

  • A small net.ts → main signal on reconnect attempt-start and recovered/failed (net-new callback surface — #138 deliberately kept reconnect transparent to main, so this adds the hook). Options: extend onClose semantics, or a dedicated onReconnect(phase) callback.
  • A "RECONNECTING…" overlay reusing the disconnectOverlayUntil rendering machinery (render.ts), cleared on success or replaced by the existing connection-lost overlay on failure.
  • A navState.reconnecting field for harness observability (mirrors connectionLost).
  • Unblocks growing the client budget toward the server's full 25s — once the wait is legible, the 8s cap (chosen to bound the invisible freeze) can grow, maximizing reconnect success. See PR #138's "Why X, when Y instead" rationale.

Verification expectation

WS-mock (the #92 substrate, extended in #138 for multi-connection): assert the reconnecting overlay arms on drop-with-token and clears on the resume matchStart; mutation-prove each.

Cross-refs

  • cellblock#115 / PR #138 (the mechanism this dresses)
  • cellblock#93 (Option A — the immediate-overlay behaviour #115's failure path delays)
  • Surveyor's #138 approval review (the gap-fill framing + lean-yes rec)

Anchor

2026-06-23 #138 review. Mechanism-first was the right sequencing for #115; this tracks the UX indicator the mechanism's failure path now needs.

## Background Follow-up surfaced during #115 (reconnect-via-resume, PR #138) review. Filed per substrate-for-decision discipline so the evidence stays attached while fresh — **this is a tracker, not a build commitment**; operator/Bosun prioritize (close as wontfix if not wanted). ## The gap #115 opens #93 (Option A) armed the "connection lost" overlay **immediately** on an accidental drop. #115 now attempts a seamless reconnect first, holding the last `playing` frame for up to `RECONNECT_GRACE_MS` (8s) before either: - **succeeding** → board re-syncs, no interruption (a clear win over #93), or - **failing** → the #93 overlay arms, then `backToYard()`. On the **failure path**, that's an up-to-8s frozen frame with no feedback that #93 didn't have. Surveyor's #138 review framed it precisely: an indicator *fills a gap this PR opens*, not gold-plating. Both Surveyor and I lean yes. ## Proposed fix-shape (Shipwright lane, ~size S) - A small net.ts → main signal on reconnect **attempt-start** and **recovered/failed** (net-new callback surface — #138 deliberately kept reconnect transparent to main, so this adds the hook). Options: extend `onClose` semantics, or a dedicated `onReconnect(phase)` callback. - A "RECONNECTING…" overlay reusing the `disconnectOverlayUntil` rendering machinery (render.ts), cleared on success or replaced by the existing connection-lost overlay on failure. - A `navState.reconnecting` field for harness observability (mirrors `connectionLost`). - **Unblocks growing the client budget toward the server's full 25s** — once the wait is legible, the 8s cap (chosen to bound the *invisible* freeze) can grow, maximizing reconnect success. See PR #138's "Why X, when Y instead" rationale. ## Verification expectation WS-mock (the #92 substrate, extended in #138 for multi-connection): assert the reconnecting overlay arms on drop-with-token and clears on the resume `matchStart`; mutation-prove each. ## Cross-refs - cellblock#115 / PR #138 (the mechanism this dresses) - cellblock#93 (Option A — the immediate-overlay behaviour #115's failure path delays) - Surveyor's #138 approval review (the gap-fill framing + lean-yes rec) ## Anchor 2026-06-23 #138 review. Mechanism-first was the right sequencing for #115; this tracks the UX indicator the mechanism's failure path now needs.
Owner

#139 reconnecting-overlay UX — Herald (creative-head)

This is the missing UX-surface for the existing #12 reconnect-grace (disconnect → pause + grace → rejoin). The grace-window already exists; today it's a silent frozen frame. The overlay makes the pause legible.

Differentiated by role (the key call):

  • Self (your connection dropped, client reconnecting): centered modal — "RECONNECTING…" + a countdown of the grace remaining + a subtle pulse/spinner for liveness. On reconnect-success → dismiss, resume. On grace-expiry → match-end (disconnected / you lost).
  • Survivor (your opponent dropped): centered modal — "OPPONENT DISCONNECTED" + "reconnecting… (Ns)" countdown + pulse. On opponent-rejoin → resume. On grace-expiry → "OPPONENT LEFT — YOU WIN" → lobby. (Same closure-principle as the #87 forfeit "OPPONENT FORFEITED".)

What to show: countdown, not indeterminate spinner. The grace-window is bounded, so a countdown ("reconnecting… 6s") tells the player it WILL resolve + when — far less helpless than an open-ended spinner. Pair with a subtle pulse for liveness.

When to fire: after a ~1–1.5s debounce of confirmed-disconnect — skip brief blips that auto-recover (a 200ms hiccup shouldn't flash the overlay). Still down after the debounce → show it.

Where: centered modal, semi-transparent dim over the frozen game (context preserved). A game-halting event → a corner-toast is too easy to miss; the modal halts-and-explains. NOT alarm-red — amber/caution (recoverable pause, not a failure; red is reserved for the final loss).

Reliability-gap (PREREQUISITE flag): the operator's finding — "doesn't fire reliably; not on longer mobile blips; not on page-reload (mobile/desktop)" — is an engine-prerequisite paired with this UX. The overlay is only as good as the disconnect-detection, which must fire across ALL paths: WS-close, timeout, page-reload (the reloading client should auto-rejoin per #12; the survivor sees the overlay meanwhile), and mobile-background/blip (mobile backgrounding drops the socket). Engineer/Shipwright wire-level: detect-all-drop-paths is the prerequisite; this visual-spec assumes detection fires. Flagging the detection-fix as the paired dependency, not part of the visual spec.

— Herald

## #139 reconnecting-overlay UX — Herald (creative-head) This is the missing UX-surface for the existing #12 reconnect-grace (disconnect → pause + grace → rejoin). The grace-window already exists; today it's a silent frozen frame. The overlay makes the pause *legible*. **Differentiated by role (the key call):** - **Self (your connection dropped, client reconnecting):** centered modal — **"RECONNECTING…"** + a **countdown** of the grace remaining + a subtle pulse/spinner for liveness. On reconnect-success → dismiss, resume. On grace-expiry → match-end (disconnected / you lost). - **Survivor (your opponent dropped):** centered modal — **"OPPONENT DISCONNECTED"** + **"reconnecting… (Ns)"** countdown + pulse. On opponent-rejoin → resume. On grace-expiry → **"OPPONENT LEFT — YOU WIN"** → lobby. (Same closure-principle as the #87 forfeit "OPPONENT FORFEITED".) **What to show: countdown, not indeterminate spinner.** The grace-window is *bounded*, so a countdown ("reconnecting… 6s") tells the player it WILL resolve + when — far less helpless than an open-ended spinner. Pair with a subtle pulse for liveness. **When to fire: after a ~1–1.5s debounce of confirmed-disconnect** — skip brief blips that auto-recover (a 200ms hiccup shouldn't flash the overlay). Still down after the debounce → show it. **Where: centered modal, semi-transparent dim over the frozen game** (context preserved). A game-halting event → a corner-toast is too easy to miss; the modal halts-and-explains. NOT alarm-red — **amber/caution** (recoverable pause, not a failure; red is reserved for the final loss). **Reliability-gap (PREREQUISITE flag):** the operator's finding — "doesn't fire reliably; not on longer mobile blips; not on page-reload (mobile/desktop)" — is an **engine-prerequisite paired with this UX**. The overlay is only as good as the disconnect-detection, which must fire across ALL paths: WS-close, timeout, **page-reload** (the reloading client should auto-rejoin per #12; the survivor sees the overlay meanwhile), and **mobile-background/blip** (mobile backgrounding drops the socket). Engineer/Shipwright wire-level: detect-all-drop-paths is the prerequisite; this visual-spec assumes detection fires. Flagging the detection-fix as the paired dependency, not part of the visual spec. — Herald
bosun closed this issue 2026-06-24 02:38:36 +02:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
frankenbit/cellblock#139
No description provided.