Closed general

Wake-from-sleep self-heal: auto-clear the 'Cannot reconnect' dialog by reloading ONLY the VS Code pane, only when provably required

John Lauer · 8d ago ·closed by John Lauer

Type: Feature (design agreed with John 2026-08-02; proven manually the same morning)

Symptom today: close the laptop lid overnight; on wake the VS Code pane shows the workbench's terminal modal, "Cannot reconnect. Please reload the window." It sits there until the user clicks Reload Window by hand. HD, a desktop app that can know the machine just resumed, does nothing.

Proof this is deterministically healable (live, 2026-08-02): after an overnight sleep, /workspace/health reported fully healthy (distro running, code-server 200, editor_will_load true) while the dialog was still up. One click of the dialog's own Reload Window button reconnected instantly, restored the Claude tabs with their conversations, and activated the freshly staged adom-vscode 1.1.13. So when the backend is healthy and that dialog is showing, reload is guaranteed-correct and the ONLY remaining action (the workbench has permanently given up retrying by the time it shows this modal).

Design (wake-heal cascade):

  1. Detect resume without Win32 plumbing: a 10s wall-clock tick task; if SystemTime jumped >90s between ticks, the machine slept (HD's own #7 logs prove the process freezes through sleep, heartbeat 26150s -> 26160s across 13 wall-clock hours). Optionally add WM_POWERBROADCAST later; the gap detector alone is sufficient and cross-platform.
  2. Heal the backend first: poll the existing /workspace/health logic (in-process, NOT wsl.exe-spammed) with backoff up to ~2 min; the existing supervisor restart paths cover an unhealthy distro/code-server.
  3. Only then look at the pane: CDP-eval the workbench frame (the /eval-in "workbench" target infra already exists) for the terminal reconnect dialog (.monaco-dialog-box containing "Cannot reconnect").
  4. Dialog present + backend healthy -> reload ONLY the VS Code pane (emit an event; PanelVisualStudioCode resets the iframe behind the 0.1.303 editor-cover splash). Never the HD window, never other tabs; the Wiki pane etc. are untouched. This honors "reload is a last resort": the terminal dialog IS the proof that nothing less works.
  5. No dialog -> do nothing (short sleeps where the workbench reconnected on its own).
  6. Toast "Workspace reconnected after sleep" so the heal is visible but not modal.

Explicitly rejected: auto-reloading on every wake (reload without checking is the annoying thing we are replacing); wiring anything through wsl.exe (hd-prefer-adom-vscode); touching the whole window.

Ship note: needs a laptop build slot (running HD is currently a dirty build owned by another thread; coordinate before hd_stop).

3 Replies

John Lauer · 8d ago

Design amendment (John, 2026-08-02): detection uses the REAL Win32 power APIs, not a homegrown clock-gap heuristic. "You're a desktop app... if you try to reimplement that you'll just create more bugs for us to stamp out." Correct. Step 1 is replaced with:

  • A hidden message-only window (own thread, isolated from Tauri's window proc) receiving WM_POWERBROADCAST, registered via RegisterSuspendResumeNotification so delivery is correct on Modern Standby laptops (lid-close on modern hardware is S0 idle, not S3).
  • PBT_APMSUSPEND -> log + timestamp; flush anything worth flushing.
  • PBT_APMRESUMEAUTOMATIC (machine woke, user absent) -> run the heal cascade silently.
  • PBT_APMRESUMESUSPEND (user-triggered wake) -> heal cascade + the reconnect toast.
  • CallNtPowerInformation(LastSleepTime/LastWakeTime) -> exact sleep duration for the log line, no bookkeeping of our own.
  • Optional richness, same registration surface: GUID_LIDSWITCH_STATE_CHANGE (lid open/close), GUID_ACDC_POWER_SOURCE (battery vs AC), GUID_CONSOLE_DISPLAY_STATE, and WTSRegisterSessionNotification (lock/unlock) so the pane reload can complete BEFORE the user unlocks and never be seen at all.

Steps 2-6 (backend-health-first, dialog check, pane-only reload as provable last resort, do-nothing path, toast) unchanged.

John Lauer · 8d ago

SHIPPED and verified on John's laptop, 2026-08-02 evening (commits d06c9fa9 + b0a5e097 + c04edb11).

What went in:

  • Detection: Win32 power notifications (RegisterSuspendResumeNotification + WM_POWERBROADCAST on a hidden message-only window). Distinguishes user vs automatic wake and reports sleep duration.
  • Heal cascade, gated on Settings > Behavior > "wake heal" (default ON, per the earlier toggle requirement): patient health poll -> code-server systemd restart -> HCS-wedge detection with a targeted distro terminate (the full wsl --shutdown stays a manual escalation in v1) -> Adom session token re-stamp (tmpfs wipes on every distro restart) -> 45s workbench self-reconnect grace -> pane-only reload via the existing reload-vscode-iframe event, and only when the reconnect dialog is provably stuck.
  • Debug UI (John's spec): indicator right of the lightbulb (moon = slept, spinning sync = healing, sunrise = done, red = failed) plus an info icon whose tooltip live-streams every cascade step with timestamps. Visibility = Settings > Behavior > "wake indicator", default OFF fleet-wide; John's is ON for the debugging window.
  • Test rig: POST /wake/simulate runs the full cascade without sleeping the machine; GET /wake/status serves the same state the tooltip renders.

Verified tonight: simulate ran the cascade end-to-end in ~40s (detected -> backend healthy -> token re-stamped -> workbench healthy, no reload needed -> done), and the indicator + spinner rendered in the header during the run.

The cascade encodes the ladder from the SAME DAY's two real incidents (morning: stale reconnect dialog over a healthy backend; evening: dead code-server + HCS-wedged WSL needing terminate + shutdown). Remaining to validate: a REAL overnight sleep with the watcher armed - that is the coming days' debugging plan, tooltip narrating each step.

John Lauer · 7d ago

Closing as SHIPPED and validated (2026-08-02 evening through 2026-08-03).

Since the SHIPPED reply below, the feature grew the full debug surface John specced and then some: a REAL 2.5-minute sleep test passed end to end (dual resume events deduped, workspace verified in 18s); the header indicator + live tooltip are photographically verified; Settings gained a Wake section with the heal toggle, indicator toggle, and a linger slider (default 60s); a "Preview wake indicator" button plays a scripted fake wake with a countdown and Hide-now narrated in the Settings window; the indicator's linger now actually expires via a 1s ticker (a real bug found during preview work: recency was computed once and never re-evaluated, which would have kept the indicator up forever after real wakes too); and the whole feature is documented for every user's in-workspace agent via the new hd-wake-repair skill in adom/hd-bootstrap (0.2.35+).

Remaining: the overnight-sleep validation happens naturally over the coming nights with John's indicator ON. If a real overnight wake misbehaves, that gets a fresh, specific issue rather than reopening this one.

Log in to reply.