fix(cloud): retry restored port panes after machine refresh

Merged
AU
10d ago
+298-19

Summary

After relaunch, a Cloud browser pane on a forwarded VM port (e.g. http://10.107.80.1:3400/) stayed on "Cloud session unavailable" and the sidebar showed Ports 0, even though the server was running.

Root cause: the restored pane is staged in pendingRestoredProjections until a port scan publishes its port:N resource, but CloudPortDiscovery.mayScan only allowed scans after an explicit Ports request. Every post-restart scan logged cloud.portScan.begin requested=false and returned nothing, so the staged pane never resolved.

  • A live or staged forwarded-port pane is now standing scan demand (hasProjectedPortPanes), so the first scan after the link connects publishes the port and the staged pane configures itself.
  • Restored panes show "Reconnecting to Cloud…" until the route configures. They drop to the Reload card only when a settled scan misses the port (settleRestoredPortPanes) or a 30 s deadline (injected clock) passes. Reload returns to the reconnecting state immediately.
  • Providers rehydrated for restored machines keep the saved private address when the status read omits one.
  • Removed a synthetic port upsert that only covered live projections and never ran for staged ones.

Validation

  • Tagged build pr-17232-cloud-restore-retry-v25, relaunched with the reporter's saved layout: cloud.portScan.result ports=3400 then cloud.desktop.proxy.ready port=3400, and the restored pane rendered the page.
  • New CloudDesktopAccessTests cases cover the restore deadline, settled miss, Reload flip, and deadline cancellation on configure (CI run https://github.com/manaflow-ai/cmux/actions/runs/37298537520).
  • verify-local.py --only swift-syntax --swift-changed, git diff --check.

— unregistered

🤖 Generated with Claude Code