A backend that keeps running while its install is deleted or replaced
underneath it still answers /health and /system/info from memory — the
launcher's version check passed and the UI attached to a process that
500s every DB-touching route (raw errors without CORS headers, so the
webview reports access-control failures). The attach path now requires a
DB-touching probe (/profiles) to return an actual 200 status line, and
replaces the squatter otherwise — the status line is parsed explicitly
because the raw HTTP helper previously returned 500 bodies as Ok.
desktop-prod/desktop-fresh now terminate our own running processes
(bundle, dev binary, app-scoped port-3900 listener) before wiping, which
is how the zombie was produced.
Co-authored-by: mergetest <test@local>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>