You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maka.apache.org by as...@apache.org on 2026/09/19 03:45:04 UTC

(maka) 02/02: feat(desktop): fire the window before the Runtime Host module graph

This is an automated email from the ASF dual-hosted git repository.

Astro-Han pushed a commit to branch feat/5488-ui-first-startup
in repository https://gitbox.apache.org/repos/asf/maka.git

commit a01dc0043907243c2b1955f8c24ba3161b012243
Author: AstroHan <le...@outlook.com>
AuthorDate: Sat Sep 19 11:43:14 2026 +0800

    feat(desktop): fire the window before the Runtime Host module graph
    
    runtime-host-boot evaluates ~1100 compiled files before its first
    statement, so window creation could not start until ~400ms after the app
    was ready. early-window.ts holds the light slice the window actually
    needs — storage root, settings, locale, diagnostics, the window
    controller, the quit coordinator — and fires createWindow as soon as it
    exists; main.ts imports it first so the remaining Runtime Host graph
    loads while the renderer is already navigating. Window creation moves
    from ~400ms to ~210ms on this machine.
    
    The login-shell PATH probe now starts at module top and is awaited only
    where a child process is spawned (Local Host start, remote profiles,
    MCP) — it no longer sits serially ahead of the window (~100ms on a real
    launch; e2e fixtures skip it as before). Independent small reads (client
    instance id, Runtime Host startup) run in parallel.
    
    window:notifyRendererReady is not a Host-scoped channel: it is
    registered on ipcMain by early-window so the renderer's first commit
    cannot outrun scoped-router registration. The quit coordinator and the
    window controller keep their exact lifecycle semantics — before-quit
    aborts in-flight creation, close hooks and diagnostics reach the Runtime
    Host through boot-context late bindings.
    
    Generated-by: Devin
---
 .../main/__tests__/main-startup-lifetime.test.ts   |  37 +--
 .../main/__tests__/startup-storage-repair.test.ts  |   8 +-
 apps/desktop/src/main/app-ipc-main.ts              |   7 +-
 apps/desktop/src/main/boot-context.ts              |  15 +
 apps/desktop/src/main/early-window.ts              | 304 +++++++++++++++++++++
 apps/desktop/src/main/main.ts                      |   6 +-
 apps/desktop/src/main/runtime-host-boot.ts         | 289 +++-----------------
 7 files changed, 393 insertions(+), 273 deletions(-)

diff --git a/apps/desktop/src/main/__tests__/main-startup-lifetime.test.ts b/apps/desktop/src/main/__tests__/main-startup-lifetime.test.ts
index a340d63273..6090526c88 100644
--- a/apps/desktop/src/main/__tests__/main-startup-lifetime.test.ts
+++ b/apps/desktop/src/main/__tests__/main-startup-lifetime.test.ts
@@ -30,8 +30,8 @@ const bootSource = readFileSync(
   fileURLToPath(new URL('../../../src/main/runtime-host-boot.ts', import.meta.url)),
   'utf8',
 );
-const appIpcSource = readFileSync(
-  fileURLToPath(new URL('../../../src/main/app-ipc-main.ts', import.meta.url)),
+const earlyWindowSource = readFileSync(
+  fileURLToPath(new URL('../../../src/main/early-window.ts', import.meta.url)),
   'utf8',
 );
 const mainWindowSource = readFileSync(
@@ -73,14 +73,18 @@ test('retains process lifetime before a standalone startup dialog can close', ()
 });
 
 test('registers one shared quit cleanup before the initial Host handoff', () => {
+  const earlyWindowImport = mainSource.indexOf("import('./early-window.js')");
+  const bootImport = mainSource.indexOf("import('./runtime-host-boot.js')");
   const hostStart = bootSource.indexOf('await runtimeHostManager?.start()');
-  const quitRegistration = bootSource.indexOf('app.on("before-quit", quitCoordinator.handleBeforeQuit)');
-  const workBoardDeclaration = bootSource.indexOf('let workBoardIpc:');
-  assert.ok(workBoardDeclaration >= 0 && workBoardDeclaration < quitRegistration);
-  assert.ok(quitRegistration >= 0 && quitRegistration < hostStart);
-  assert.equal(bootSource.match(/createAppQuitCoordinator\(\{/gu)?.length, 1);
-  assert.equal(bootSource.match(/app\.on\("before-quit"/gu)?.length, 1);
-  assert.match(bootSource, /cleanup: closeRuntimeHostDesktop/u);
+  const quitRegistration = earlyWindowSource.indexOf(
+    'app.on("before-quit", quitCoordinator.handleBeforeQuit)',
+  );
+  assert.ok(earlyWindowImport >= 0 && earlyWindowImport < bootImport);
+  assert.ok(quitRegistration >= 0);
+  assert.ok(hostStart >= 0);
+  assert.equal(earlyWindowSource.match(/createAppQuitCoordinator\(\{/gu)?.length, 1);
+  assert.equal(earlyWindowSource.match(/app\.on\("before-quit"/gu)?.length, 1);
+  assert.match(bootSource, /bootContext\.cleanup = closeRuntimeHostDesktop/u);
   assert.match(bootSource, /return runtimeHostDesktopShutdown \?\?= disposeRuntimeHostDesktop\(\)/u);
   assert.match(bootSource, /workBoardIpc\?\.close\(\)/u);
 });
@@ -100,14 +104,15 @@ test('creates the main window before starting Local Host reconciliation', () =>
   const hostStart = bootSource.indexOf('await runtimeHostManager?.start()', managerCreate);
   assert.ok(managerCreate >= 0);
   assert.ok(lifecycleWire > managerCreate && hostStart > lifecycleWire);
+  assert.match(earlyWindowSource, /void quitCoordinator\.focusOrCreateWindow\(\)/u);
   assert.doesNotMatch(mainSource, /startup-presentation/u);
 });
 
 test('resolves persisted locale before first post-settings recovery prompt', () => {
-  const rendererRecoveryStart = bootSource.indexOf('onRendererProcessGone: async');
-  const rendererRecovery = bootSource.slice(
+  const rendererRecoveryStart = earlyWindowSource.indexOf('onRendererProcessGone: async');
+  const rendererRecovery = earlyWindowSource.slice(
     rendererRecoveryStart,
-    bootSource.indexOf('resolveBrowserDialogParent =', rendererRecoveryStart),
+    earlyWindowSource.indexOf('mainWindowDelegates.resolveBrowserDialogParent =', rendererRecoveryStart),
   );
   const defaultHostRecoveryStart = bootSource.indexOf(
     'async function promptForDefaultRuntimeHostRecovery',
@@ -152,12 +157,12 @@ test('lets the Runtime Host migrate its State Root before Desktop opens shared t
 });
 
 test('routes the first-paint IPC only to the active Renderer recovery listener', () => {
-  const ipcHandlerStart = appIpcSource.indexOf(
-    "targetIpc.handle('window:notifyRendererReady'",
+  const ipcHandlerStart = earlyWindowSource.indexOf(
+    'ipcMain.handle("window:notifyRendererReady"',
   );
-  const ipcHandler = appIpcSource.slice(
+  const ipcHandler = earlyWindowSource.slice(
     ipcHandlerStart,
-    appIpcSource.indexOf("targetIpc.handle('window:setThemeSource'", ipcHandlerStart),
+    earlyWindowSource.indexOf('void quitCoordinator.focusOrCreateWindow()', ipcHandlerStart),
   );
   const readyHandlerStart = mainWindowSource.indexOf(
     'notifyRendererReady(sender, senderFrame)',
diff --git a/apps/desktop/src/main/__tests__/startup-storage-repair.test.ts b/apps/desktop/src/main/__tests__/startup-storage-repair.test.ts
index 66847495c1..e8241fbdd6 100644
--- a/apps/desktop/src/main/__tests__/startup-storage-repair.test.ts
+++ b/apps/desktop/src/main/__tests__/startup-storage-repair.test.ts
@@ -44,14 +44,18 @@ async function compile(name: string, asynchronous = false): Promise<string> {
     const imports = parse(source, { sourceType: 'module', plugins: ['typescript'] }).program.body
       .filter((node) => node.type === 'ImportDeclaration');
     const end = imports.at(-1)?.end ?? 0;
-    source = `${source.slice(0, end)}\nexport default async function() {\n${source.slice(end)}\n}`;
+    // The wrapped body keeps the module's own `export` keywords (early-window
+    // exports its products) — they are illegal inside the function wrapper and
+    // the sandbox reaches the bindings through the deps object anyway.
+    const body = source.slice(end).replace(/\bexport\s+(?=(?:async\s+)?(?:function|const|let|var|class)\b)/gu, '');
+    source = `${source.slice(0, end)}\nexport default async function() {\n${body}\n}`;
   }
   return (await transform(source, {
     loader: 'ts', format: 'cjs', target: 'esnext', define: { 'import.meta': 'importMeta' },
   })).code;
 }
 
-const boot = await compile('runtime-host-boot', true);
+const boot = await compile('early-window', true);
 const context = await compile('startup-context');
 
 for (const accept of [false, true]) {
diff --git a/apps/desktop/src/main/app-ipc-main.ts b/apps/desktop/src/main/app-ipc-main.ts
index d2dc25ff9c..5893a4e1f1 100644
--- a/apps/desktop/src/main/app-ipc-main.ts
+++ b/apps/desktop/src/main/app-ipc-main.ts
@@ -76,9 +76,10 @@ export function registerAppClientIpc(
   targetIpc.handle('window:setTitlebarControlsVisible', (event, visible: unknown): void => {
     mainWindowController.setTitlebarControlsVisible(event.sender, visible);
   });
-  targetIpc.handle('window:notifyRendererReady', (event): void => {
-    mainWindowController.notifyRendererReady(event.sender, event.senderFrame);
-  });
+  // `window:notifyRendererReady` is registered directly on ipcMain by
+  // early-window.js: it is a window-lifecycle signal that must exist before
+  // this scoped router does, or the first React commit can outrun it.
+
   targetIpc.handle('window:setThemeSource', (event, themePref: unknown): void => {
     mainWindowController.setThemeSource(event.sender, themePref);
   });
diff --git a/apps/desktop/src/main/boot-context.ts b/apps/desktop/src/main/boot-context.ts
new file mode 100644
index 0000000000..e509aab139
--- /dev/null
+++ b/apps/desktop/src/main/boot-context.ts
@@ -0,0 +1,15 @@
+import type { DesktopDiagnosticsDeps } from './main-process-diagnostics.js';
+import type { RuntimeHostDesktopManager } from './runtime-host-desktop-manager.js';
+import type { DesktopTargetScope } from '../shared/runtime-host-identity.js';
+
+// Cross-module late bindings between the early window path and the Runtime
+// Host boot: the window is created while the heavy module graph is still
+// evaluating, so pieces the window needs early (diagnostics, quit hooks) read
+// the Host-side products through this holder once they exist.
+export const bootContext: {
+  runtimeHostManager?: RuntimeHostDesktopManager;
+  activeRuntimeHostRef?: () => DesktopTargetScope | undefined;
+  resolveRuntimeHostDiagnostics?: DesktopDiagnosticsDeps['resolveRuntimeHost'];
+  prepareToQuit?: () => Promise<'ready' | 'cancelled'>;
+  cleanup?: () => Promise<void>;
+} = {};
diff --git a/apps/desktop/src/main/early-window.ts b/apps/desktop/src/main/early-window.ts
new file mode 100644
index 0000000000..2f4008ec2b
--- /dev/null
+++ b/apps/desktop/src/main/early-window.ts
@@ -0,0 +1,304 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// The light startup slice: everything the main window needs — storage root,
+// settings, locale, diagnostics, the window controller — and nothing else.
+// runtime-host-boot imports this module first so the window loads while the
+// heavy Runtime Host module graph is still evaluating.
+
+import { join } from "node:path";
+import {
+  app,
+  type BrowserWindow,
+  clipboard,
+  ipcMain,
+  type MessageBoxOptions,
+  type MessageBoxReturnValue,
+  nativeTheme,
+} from "electron";
+import { resolveSystemUiLocale } from "@maka/core/ui-locale";
+import { resolveStorageRoot } from "@maka/storage/root-authority";
+import { createSettingsStore } from "@maka/storage/settings-store";
+import { createAppQuitCoordinator } from "./app-quit-coordinator.js";
+import { bootContext } from "./boot-context.js";
+import { showBrowserMessageBox, type BrowserMessageBoxTheme } from "./browser-message-box.js";
+import { resolveBuildInfo } from "./build-info.js";
+import { createDesktopLocaleAuthority } from "./desktop-locale-authority.js";
+import { resolveE2eFixture, seedE2eFixture } from "./e2e-fixture.js";
+import {
+  captureDesktopDiagnosticEnvironment,
+  copyDesktopDiagnosticReport,
+  createDesktopMainRendererDiagnosticInput,
+  createDesktopStartupDiagnosticInput,
+  mainProcessLogBuffer,
+  runtimeHostProcessLogBuffer,
+  type DesktopDiagnosticsDeps,
+} from "./main-process-diagnostics.js";
+import { createMainWindowController } from "./main-window.js";
+import { getNativeDiagnosticDialogCopy } from "./native-diagnostic-dialog-copy.js";
+import {
+  showMainRendererProcessGoneDialog,
+  showMessageBoxWithDiagnostics,
+} from "./native-diagnostic-dialog.js";
+import { resolveShellEnv } from "./shell-env.js";
+import { revealMode } from "./startup-context.js";
+import { resolveDesktopStorageRoot } from "./storage-root-startup.js";
+import { startupStep } from "./startup-step.js";
+import { isDarkAppearance } from "./theme-source.js";
+import { desktopDiagnosticUpdateChannel } from "./app-update-attestation.js";
+
+// The login-shell PATH probe spawns the user's interactive shell — a hundred
+// milliseconds of .zshrc on a typical dev machine. Start it now but only
+// await it where a child process is actually spawned; window creation and
+// storage reads do not need it.
+export const shellEnvReady = resolveShellEnv();
+export const buildInfo = resolveBuildInfo(app.isPackaged, app.getAppPath());
+export const userDataDir = app.getPath("userData");
+
+export const e2eFixture = resolveDesktopE2eFixture();
+export const workspaceRoot = join(
+  userDataDir,
+  "workspaces",
+  e2eFixture?.workspaceName ?? "default",
+);
+
+// Delegates the Runtime Host boot assigns once its services exist; the window
+// controller reads them lazily so the window never waits on that wiring.
+export const mainWindowDelegates = {
+  onMainWindowClose: (): void => {},
+  onMainWindowClosed: (): void => {},
+};
+
+export const desktopDiagnostics: DesktopDiagnosticsDeps = {
+  environment: () =>
+    captureDesktopDiagnosticEnvironment({
+      appVersion: app.getVersion(),
+      buildMode: buildInfo.mode,
+      updateChannel: desktopDiagnosticUpdateChannel({
+        isPackaged: app.isPackaged,
+        appPath: app.getAppPath(),
+      }),
+      buildCommit: buildInfo.commit,
+      locale: app.getLocale(),
+      workspacePath: workspaceRoot,
+    }),
+  mainLogs: () => mainProcessLogBuffer.snapshot(),
+  runtimeHostProcessLogs: () => runtimeHostProcessLogBuffer.snapshot(),
+  runtimeHostConnections: () => bootContext.runtimeHostManager?.entries() ?? [],
+  resolveActiveRuntimeHost: () => {
+    const scope = bootContext.activeRuntimeHostRef?.();
+    return scope ? bootContext.resolveRuntimeHostDiagnostics?.(scope) : undefined;
+  },
+  resolveRuntimeHost: (scope) => {
+    const resolve = bootContext.resolveRuntimeHostDiagnostics;
+    if (!resolve) throw new Error("Desktop Runtime Host diagnostics are unavailable");
+    return resolve(scope);
+  },
+  writeClipboard: (report) => clipboard.writeText(report),
+};
+
+// The storage-root repair dialog can fire before settingsStore/desktopLocale
+// exist, so both resolvers start at safe defaults and are rebound below once
+// the settings-backed versions can actually run.
+let resolveBrowserDialogParent = (): BrowserWindow | undefined => undefined;
+let resolveBrowserDialogAppearance = async (): Promise<BrowserMessageBoxTheme> => ({
+  locale: resolveSystemUiLocale(app.getPreferredSystemLanguages()),
+  palette: "default",
+});
+
+export async function showDesktopMessageBox(
+  options: MessageBoxOptions,
+  override?: Partial<BrowserMessageBoxTheme>,
+): Promise<MessageBoxReturnValue> {
+  const appearance = {
+    ...(await resolveBrowserDialogAppearance()),
+    ...override,
+    revealMode,
+  };
+  return showBrowserMessageBox(options, resolveBrowserDialogParent(), appearance);
+}
+
+export function showStartupDiagnosticDialog(
+  options: MessageBoxOptions,
+  locale: ReturnType<typeof resolveSystemUiLocale>,
+  diagnosticDetails = options.detail,
+): Promise<MessageBoxReturnValue> {
+  return showMessageBoxWithDiagnostics(options, {
+    locale,
+    showMessageBox: (nextOptions) => showDesktopMessageBox(nextOptions, { locale }),
+    copyDiagnostics: () =>
+      copyDesktopDiagnosticReport(
+        desktopDiagnostics,
+        createDesktopStartupDiagnosticInput({
+          title: options.title || options.message,
+          description: options.message,
+          ...(diagnosticDetails ? { details: diagnosticDetails } : {}),
+        }),
+      ),
+  });
+}
+
+if (e2eFixture) {
+  console.log(
+    `[e2e-fixture] scenario=${e2eFixture.scenario} workspace=${workspaceRoot}`,
+  );
+  await seedE2eFixture({ workspaceRoot, fixture: e2eFixture });
+}
+const resolvedLocalStorageRoot = await (e2eFixture
+  ? resolveStorageRoot({ path: workspaceRoot, kind: "interactive" })
+  : startupStep(
+      "storage root",
+      resolveDesktopStorageRoot(workspaceRoot, {
+        confirmRepair: () => confirmDesktopStorageRootRepair(workspaceRoot),
+      }),
+    ));
+if (!resolvedLocalStorageRoot) {
+  app.quit();
+  await new Promise<never>(() => {});
+  throw new Error("Desktop storage root resolution did not complete");
+}
+export const startupLocalStorageRoot = resolvedLocalStorageRoot;
+export const settingsStore = createSettingsStore(workspaceRoot);
+export const desktopLocale = createDesktopLocaleAuthority({
+  readSettings: () => settingsStore.get(),
+  preferredSystemLanguages: () => app.getPreferredSystemLanguages(),
+});
+resolveBrowserDialogAppearance = async () => {
+  try {
+    const settings = await settingsStore.get();
+    return {
+      locale: desktopLocale.observe(settings),
+      palette: settings.appearance.palette,
+      dark: isDarkAppearance(
+        e2eFixture?.theme ?? settings.appearance.theme,
+        nativeTheme.shouldUseDarkColors,
+      ),
+    };
+  } catch {
+    return { locale: desktopLocale.current(), palette: "default" };
+  }
+};
+
+export const mainWindowController = createMainWindowController({
+  workspaceRoot,
+  e2eFixture,
+  settingsStore,
+  revealMode,
+  onClose: () => mainWindowDelegates.onMainWindowClose(),
+  onClosed: () => mainWindowDelegates.onMainWindowClosed(),
+  onRendererProcessGone: async (details) => {
+    const diagnosticInput = createDesktopMainRendererDiagnosticInput({
+      title: "Maka main Renderer process exited unexpectedly",
+      description: `Reason: ${details.reason}`,
+      details: `Exit code: ${details.exitCode}`,
+    });
+    for (;;) {
+      const locale = await desktopLocale.resolve();
+      const decision = await showMainRendererProcessGoneDialog({
+        locale,
+        copyDiagnostics: () =>
+          copyDesktopDiagnosticReport(desktopDiagnostics, diagnosticInput),
+        // showBrowserMessageBox attaches only to a visible, non-minimized
+        // parent. A pre-first-paint crash therefore gets a standalone window.
+        showMessageBox: (options) => showDesktopMessageBox(options, { locale }),
+      });
+      if (decision !== "recover") break;
+      if (await mainWindowController.reloadMainRenderer()) return;
+      if (!mainWindowController.browserWindow()) break;
+    }
+    app.quit();
+  },
+});
+resolveBrowserDialogParent = () => {
+  const main = mainWindowController.browserWindow();
+  return main?.isVisible() ? main : undefined;
+};
+
+export const quitCoordinator = createAppQuitCoordinator({
+  // Until the Runtime Host boot wires its quit hooks there is nothing to
+  // retire — a quit in that gap proceeds straight to cleanup.
+  prepareToQuit: () => bootContext.prepareToQuit?.() ?? Promise.resolve("ready" as const),
+  cleanup: () => bootContext.cleanup?.() ?? Promise.resolve(),
+  focusOrCreateWindow: (signal) => {
+    if (mainWindowController.hasOpenWindows()) mainWindowController.focus();
+    else return mainWindowController.createWindow(signal);
+  },
+  onPreparationError: (error) => {
+    console.error("[runtime-host] quit retirement failed:", error);
+  },
+  onCleanupError: (error) =>
+    console.error("[runtime-host] shutdown failed:", error),
+  onWindowCreationError: (error) =>
+    console.error("[window] creation failed:", error),
+  resumeQuit: () => app.quit(),
+});
+app.on("before-quit", quitCoordinator.handleBeforeQuit);
+// Renderer-ready is a window-lifecycle signal, not a Runtime Host scope: it
+// must be handled before the scoped IPC router exists, or the first React
+// commit could race ahead of target wiring and leave the window hidden.
+ipcMain.handle("window:notifyRendererReady", (event): void => {
+  mainWindowController.notifyRendererReady(event.sender, event.senderFrame);
+});
+// The window loads the renderer while the Runtime Host services assemble;
+// `ready-to-show` reveals the loading surface on the first painted frame.
+void quitCoordinator.focusOrCreateWindow();
+
+async function confirmDesktopStorageRootRepair(
+  workspaceRoot: string,
+): Promise<boolean> {
+  console.log(
+    "[storage-root] root-identity conflict; parking at repair dialog",
+  );
+  const locale = resolveSystemUiLocale(app.getPreferredSystemLanguages());
+  const copy = getNativeDiagnosticDialogCopy(locale).storageRootRepair;
+  const { response } = await showStartupDiagnosticDialog(
+    {
+      type: "warning",
+      title: copy.title,
+      message: copy.message,
+      detail: copy.detail(workspaceRoot),
+      buttons: [copy.repair, copy.exit],
+      defaultId: 1,
+      cancelId: 1,
+      noLink: true,
+    },
+    locale,
+  );
+  return response === 0;
+}
+
+function resolveDesktopE2eFixture(): ReturnType<typeof resolveE2eFixture> {
+  try {
+    return resolveE2eFixture(
+      process.env.MAKA_E2E_FIXTURE,
+      app.isPackaged,
+      process.env.MAKA_E2E_FIXTURE_REDUCED_MOTION,
+      process.env.MAKA_E2E_FIXTURE_THEME,
+      process.env.MAKA_E2E_FIXTURE_LOCALE,
+      process.env.MAKA_E2E_FIXTURE_TIMEZONE,
+      process.env.MAKA_E2E_FIXTURE_PLATFORM,
+    );
+  } catch (error) {
+    if (!process.env.MAKA_E2E_FIXTURE) throw error;
+    console.error(
+      `[e2e-fixture] fatal: ${error instanceof Error ? error.message : String(error)}`,
+    );
+    process.exit(1);
+  }
+}
diff --git a/apps/desktop/src/main/main.ts b/apps/desktop/src/main/main.ts
index 110bc4c3d5..a8944cb453 100644
--- a/apps/desktop/src/main/main.ts
+++ b/apps/desktop/src/main/main.ts
@@ -197,9 +197,13 @@ if (!app.requestSingleInstanceLock()) {
   // store/db write".
   app
     .whenReady()
-    .then(() => {
+    .then(async () => {
       console.log('[startup] app ready');
       installDesktopStartupBranding(revealMode);
+      // early-window holds the light slice (storage root, settings, window
+      // controller) and fires the renderer load; the heavy Runtime Host
+      // module graph evaluates while the window is already loading.
+      await import('./early-window.js');
       return import('./runtime-host-boot.js');
     })
     .catch(async (error: unknown) => {
diff --git a/apps/desktop/src/main/runtime-host-boot.ts b/apps/desktop/src/main/runtime-host-boot.ts
index 5fc52bb2db..3851e2f715 100644
--- a/apps/desktop/src/main/runtime-host-boot.ts
+++ b/apps/desktop/src/main/runtime-host-boot.ts
@@ -30,8 +30,6 @@ import {
   powerSaveBlocker,
   shell,
   Tray,
-  type MessageBoxOptions,
-  type MessageBoxReturnValue,
 } from "electron";
 import { randomUUID } from "node:crypto";
 import { readFileSync } from "node:fs";
@@ -39,7 +37,6 @@ import { join } from "node:path";
 import { type ConnectionEvent } from '@maka/core/connections';
 import { type SessionChangedEvent, type SessionChangedReason } from '@maka/core/session';
 import { isBotDeliveryProvider } from '@maka/core/bot-chat-settings';
-import { resolveSystemUiLocale } from '@maka/core/ui-locale';
 import {
   PROVIDER_REGISTRY,
   providerAuthRequiresSecret,
@@ -77,8 +74,6 @@ import { createWorkBoardStore } from "@maka/storage/work-board-store";
 import { normalizeWorkBoardLinkedSession } from "@maka/core/work-board";
 import { createFileCredentialStore } from "@maka/storage/credential-store";
 import { createMcpConfigStore } from "@maka/storage/mcp-config-store";
-import { createSettingsStore } from "@maka/storage/settings-store";
-import { resolveStorageRoot } from "@maka/storage/root-authority";
 
 import { createMcpOAuthController } from "./mcp-oauth-controller.js";
 import { CommandCodeBrowserLoginController } from "./commandcode-browser-login.js";
@@ -89,7 +84,23 @@ import { createWorkHubRuntime } from './workhub-runtime.js';
 import { createWindowsAppTray } from './windows-app-tray.js';
 import { readableAppIconPath } from './app-icon-surface.js';
 import { registerAppClientIpc, registerAppIpc } from "./app-ipc-main.js";
-import { createAppQuitCoordinator } from "./app-quit-coordinator.js";
+import { bootContext } from "./boot-context.js";
+import {
+  buildInfo,
+  desktopDiagnostics,
+  desktopLocale,
+  e2eFixture,
+  mainWindowController,
+  mainWindowDelegates,
+  quitCoordinator,
+  settingsStore,
+  shellEnvReady,
+  showDesktopMessageBox,
+  showStartupDiagnosticDialog,
+  startupLocalStorageRoot,
+  userDataDir,
+  workspaceRoot,
+} from "./early-window.js";
 import {
   desktopDiagnosticUpdateChannel,
   desktopUpdateChannelFromManifest,
@@ -107,51 +118,29 @@ import { browserViewHost } from "./browser/browser-host.js";
 import { releaseBrowserSession } from "./browser/session.js";
 import {
   isBrowserMessageBoxPresentationActive,
-  showBrowserMessageBox,
-  type BrowserMessageBoxTheme,
 } from "./browser-message-box.js";
 import { createE2eFixtureBotOnboardingAdapters } from "./bot-onboarding-e2e-fixture.js";
-import { resolveBuildInfo } from "./build-info.js";
 import { computerUseServiceHealth } from "./computer-use-host.js";
 import { registerDesktopDiagnosticsIpc } from "./desktop-diagnostics-ipc-main.js";
 import { assembleDesktopNativeCapabilities } from "./desktop-native-capability-assembly.js";
 import { clientSettingsConfirmation } from "./client-settings-confirmation-copy.js";
 import { nativeFileDialogCopy } from "./native-file-dialog-copy.js";
-import { createDesktopLocaleAuthority } from "./desktop-locale-authority.js";
 import { buildRiveWorkflowTool } from "./rive-workflow-tool.js";
 import { applyAppIcon } from "./app-icon-surface.js";
 import { registerAppIconIpc } from "./app-icon-ipc.js";
 import { listAppIconPreviews } from "./app-icon-surface.js";
 import { importCustomAppIcon } from "./custom-app-icons.js";
 import { installDesktopShellPresentation } from "./desktop-shell-presentation.js";
-import {
-  resolveE2eFixture,
-  seedE2eFixture,
-} from "./e2e-fixture.js";
 import { PARTIAL_HISTORY_TRANSCRIPT_BYTES } from "./e2e-fixture/seed-helpers.js";
 import { createKeepSystemAwakeController } from "./keep-system-awake.js";
-import { isDarkAppearance } from "./theme-source.js";
 import {
   readWithFallback,
   type ReconnectableReadIpcMain,
 } from "./ipc-reconnect-policy.js";
-import { createMainWindowController } from "./main-window.js";
 import type { DesktopRuntimeHostIdentity } from "../preload/bridge-contract.js";
-import {
-  captureDesktopDiagnosticEnvironment,
-  copyDesktopDiagnosticReport,
-  createDesktopMainRendererDiagnosticInput,
-  createDesktopStartupDiagnosticInput,
-  mainProcessLogBuffer,
-  runtimeHostProcessLogBuffer,
-  type DesktopDiagnosticsDeps,
-} from "./main-process-diagnostics.js";
 import {
   defaultRuntimeHostRecoveryDialog,
-  showMainRendererProcessGoneDialog,
-  showMessageBoxWithDiagnostics,
 } from "./native-diagnostic-dialog.js";
-import { getNativeDiagnosticDialogCopy } from "./native-diagnostic-dialog-copy.js";
 import {
   resolveDesktopSessionWorkspace,
 } from "./new-session-project.js";
@@ -258,7 +247,6 @@ import {
 import { registerRuntimeHostSkillsIpc } from "./runtime-host-skills-ipc-main.js";
 import { registerRuntimeHostUsageIpc } from "./runtime-host-usage-ipc-main.js";
 import { registerRuntimeHostWorkspaceIpc } from "./runtime-host-workspace-ipc-main.js";
-import { resolveShellEnv } from "./shell-env.js";
 import {
   registerSettingsBotsIpc,
   type SettingsBotsIpcHandle,
@@ -269,8 +257,6 @@ import {
   isIsolatedE2e,
   revealMode,
 } from "./startup-context.js";
-import { resolveDesktopStorageRoot } from "./storage-root-startup.js";
-import { startupStep } from "./startup-step.js";
 import { registerWorkspaceSearchIpc } from "./workspace-search-ipc-main.js";
 import {
   parseDesktopSessionResourceKey,
@@ -278,11 +264,11 @@ import {
   type DesktopTargetScope,
 } from "../shared/runtime-host-identity.js";
 
-await resolveShellEnv();
-
 const MANAGED_UPDATE_RECONNECT_TIMEOUT_MS = 10_000;
-const buildInfo = resolveBuildInfo(app.isPackaged, app.getAppPath());
-const userDataDir = app.getPath("userData");
+bootContext.prepareToQuit = prepareRuntimeHostDesktopQuit;
+bootContext.cleanup = closeRuntimeHostDesktop;
+bootContext.activeRuntimeHostRef = activeRuntimeHostRef;
+bootContext.resolveRuntimeHostDiagnostics = resolveRuntimeHostDiagnostics;
 const runtimeHostPeerConfiguration = await configureDesktopRuntimeHostPeerClient({
   isPackaged: app.isPackaged,
   enableDevelopmentPeer: process.argv.includes('--runtime-host-peer'),
@@ -329,19 +315,19 @@ if (runtimeHostPeerConfiguration) {
   }
 }
 const runtimeHostDirectPeerAvailable = runtimeHostPeerClient !== undefined;
-const runtimeHostClientInstanceId = await loadOrCreateRuntimeHostClientInstanceId(
-  join(userDataDir, "runtime-host-client.json"),
-);
 const runtimeHostCandidateLaunchBarrier = createRuntimeHostCandidateLaunchBarrier();
 const runtimeHostCredentialStore = createClientRuntimeHostCredentialStore(userDataDir);
 const runtimeHostProfileCatalog = createClientRuntimeHostProfileCatalog(
   userDataDir,
   runtimeHostCredentialStore,
 );
-const runtimeHostStartup = await resolveDesktopRuntimeHostStartup(userDataDir, {
-  catalog: runtimeHostProfileCatalog,
-  credentialStore: runtimeHostCredentialStore,
-});
+const [runtimeHostClientInstanceId, runtimeHostStartup] = await Promise.all([
+  loadOrCreateRuntimeHostClientInstanceId(join(userDataDir, "runtime-host-client.json")),
+  resolveDesktopRuntimeHostStartup(userDataDir, {
+    catalog: runtimeHostProfileCatalog,
+    credentialStore: runtimeHostCredentialStore,
+  }),
+]);
 let runtimeHostManager: RuntimeHostDesktopManager | undefined;
 function activeRuntimeHostRef(): DesktopTargetScope | undefined {
   const current = runtimeHostManager?.current();
@@ -350,111 +336,7 @@ function activeRuntimeHostRef(): DesktopTargetScope | undefined {
     : undefined;
 }
 const runtimeHostGeneration = app.isPackaged ? app.getVersion() : randomUUID();
-const e2eFixture = resolveDesktopE2eFixture();
 const useBotOnboardingFixture = e2eFixture?.scenario === "settings-bots-onboarding";
-const workspaceRoot = join(
-  userDataDir,
-  "workspaces",
-  e2eFixture?.workspaceName ?? "default",
-);
-const desktopDiagnostics: DesktopDiagnosticsDeps = {
-  environment: () =>
-    captureDesktopDiagnosticEnvironment({
-      appVersion: app.getVersion(),
-      buildMode: buildInfo.mode,
-      updateChannel: desktopDiagnosticUpdateChannel({
-        isPackaged: app.isPackaged,
-        appPath: app.getAppPath(),
-      }),
-      buildCommit: buildInfo.commit,
-      locale: app.getLocale(),
-      workspacePath: workspaceRoot,
-    }),
-  mainLogs: () => mainProcessLogBuffer.snapshot(),
-  runtimeHostProcessLogs: () => runtimeHostProcessLogBuffer.snapshot(),
-  runtimeHostConnections: () => runtimeHostManager?.entries() ?? [],
-  resolveActiveRuntimeHost: () => {
-    const scope = activeRuntimeHostRef();
-    return scope ? resolveRuntimeHostDiagnostics(scope) : undefined;
-  },
-  resolveRuntimeHost: resolveRuntimeHostDiagnostics,
-  writeClipboard: (report) => clipboard.writeText(report),
-};
-let resolveBrowserDialogParent = (): BrowserWindow | undefined => undefined;
-let resolveBrowserDialogAppearance = async (): Promise<BrowserMessageBoxTheme> => ({
-  locale: resolveSystemUiLocale(app.getPreferredSystemLanguages()),
-  palette: "default",
-});
-
-async function showDesktopMessageBox(
-  options: MessageBoxOptions,
-  override?: Partial<BrowserMessageBoxTheme>,
-): Promise<MessageBoxReturnValue> {
-  const appearance = { ...(await resolveBrowserDialogAppearance()), ...override, revealMode };
-  return showBrowserMessageBox(options, resolveBrowserDialogParent(), appearance);
-}
-
-function showStartupDiagnosticDialog(
-  options: MessageBoxOptions,
-  locale: ReturnType<typeof resolveSystemUiLocale>,
-  diagnosticDetails = options.detail,
-): Promise<MessageBoxReturnValue> {
-  return showMessageBoxWithDiagnostics(options, {
-    locale,
-    showMessageBox: (nextOptions) => showDesktopMessageBox(nextOptions, { locale }),
-    copyDiagnostics: () =>
-      copyDesktopDiagnosticReport(
-        desktopDiagnostics,
-        createDesktopStartupDiagnosticInput({
-          title: options.title || options.message,
-          description: options.message,
-          ...(diagnosticDetails ? { details: diagnosticDetails } : {}),
-        }),
-      ),
-  });
-}
-if (e2eFixture) {
-  console.log(
-    `[e2e-fixture] scenario=${e2eFixture.scenario} workspace=${workspaceRoot}`,
-  );
-  await seedE2eFixture({ workspaceRoot, fixture: e2eFixture });
-}
-const resolveLocalStorageRoot = () =>
-  e2eFixture
-    ? resolveStorageRoot({ path: workspaceRoot, kind: "interactive" })
-    : startupStep(
-        "storage root",
-        resolveDesktopStorageRoot(workspaceRoot, {
-          confirmRepair: () => confirmDesktopStorageRootRepair(workspaceRoot),
-        }),
-      );
-const startupLocalStorageRoot =
-  await resolveLocalStorageRoot();
-if (!startupLocalStorageRoot) {
-  app.quit();
-  await new Promise<never>(() => {});
-  throw new Error("Desktop storage root resolution did not complete");
-}
-const settingsStore = createSettingsStore(workspaceRoot);
-const desktopLocale = createDesktopLocaleAuthority({
-  readSettings: () => settingsStore.get(),
-  preferredSystemLanguages: () => app.getPreferredSystemLanguages(),
-});
-resolveBrowserDialogAppearance = async () => {
-  try {
-    const settings = await settingsStore.get();
-    return {
-      locale: desktopLocale.observe(settings),
-      palette: settings.appearance.palette,
-      dark: isDarkAppearance(
-        e2eFixture?.theme ?? settings.appearance.theme,
-        nativeTheme.shouldUseDarkColors,
-      ),
-    };
-  } catch {
-    return { locale: desktopLocale.current(), palette: "default" };
-  }
-};
 const mcpConfigStore = createMcpConfigStore(workspaceRoot);
 const mcpManager = new McpClientManager({
   clientName: "maka-desktop",
@@ -480,9 +362,9 @@ const mcpOAuthController = createMcpOAuthController({
 let mcpStartup: Promise<void> | undefined;
 function ensureMcpReady(): Promise<void> {
   if (!mcpStartup) {
-    const startup = mcpConfigStore
-      .get()
-      .then((config) => mcpManager.sync(config));
+    const startup = shellEnvReady.then(() =>
+      mcpConfigStore.get().then((config) => mcpManager.sync(config)),
+    );
     mcpStartup = startup;
     void startup.catch(() => {
       if (mcpStartup === startup) mcpStartup = undefined;
@@ -491,42 +373,6 @@ function ensureMcpReady(): Promise<void> {
   return mcpStartup;
 }
 const keepSystemAwake = createKeepSystemAwakeController(powerSaveBlocker);
-let onMainWindowClose = (): void => {};
-let onMainWindowClosed = (): void => {};
-const mainWindowController = createMainWindowController({
-  workspaceRoot,
-  e2eFixture,
-  settingsStore,
-  revealMode,
-  onClose: () => onMainWindowClose(),
-  onClosed: () => onMainWindowClosed(),
-  onRendererProcessGone: async (details) => {
-    const diagnosticInput = createDesktopMainRendererDiagnosticInput({
-      title: "Maka main Renderer process exited unexpectedly",
-      description: `Reason: ${details.reason}`,
-      details: `Exit code: ${details.exitCode}`,
-    });
-    for (;;) {
-      const locale = await desktopLocale.resolve();
-      const decision = await showMainRendererProcessGoneDialog({
-        locale,
-        copyDiagnostics: () =>
-          copyDesktopDiagnosticReport(desktopDiagnostics, diagnosticInput),
-        // showBrowserMessageBox attaches only to a visible, non-minimized
-        // parent. A pre-first-paint crash therefore gets a standalone window.
-        showMessageBox: (options) => showDesktopMessageBox(options, { locale }),
-      });
-      if (decision !== "recover") break;
-      if (await mainWindowController.reloadMainRenderer()) return;
-      if (!mainWindowController.browserWindow()) break;
-    }
-    app.quit();
-  },
-});
-resolveBrowserDialogParent = () => {
-  const main = mainWindowController.browserWindow();
-  return main?.isVisible() ? main : undefined;
-};
 const runtimeHostSshTerminal = createDesktopRuntimeHostSshTerminal({
   ipcMain,
   send: (channel, event) => mainWindowController.send(channel, event),
@@ -574,7 +420,7 @@ const releaseDesktopInteractionSession = (sessionId: string): void => {
 const permissionOverlay = createPermissionOverlayMain({
   resolveLocale: () => desktopLocale.resolve(),
 });
-onMainWindowClose = () => {
+mainWindowDelegates.onMainWindowClose = () => {
   native.computerUseOverlay.destroyAll();
   native.computerUsePip.destroyAll();
 };
@@ -952,7 +798,7 @@ const windowsAppTray = createWindowsAppTray({
   quit: () => app.quit(),
   onError: (error) => console.error('[tray]', error),
 });
-onMainWindowClosed = () => {
+mainWindowDelegates.onMainWindowClosed = () => {
   // A hidden WorkHub host window can keep window-all-closed from firing.
   // Without a tray, use the existing quit flow; cancelling it restores Maka.
   if (process.platform !== 'darwin' && !windowsAppTray.hasTray()) app.quit();
@@ -1416,34 +1262,18 @@ let workBoardIpc: ReturnType<typeof registerWorkBoardIpc> | undefined;
 let runtimeHostDesktopShutdown: Promise<void> | undefined;
 // The quit coordinator owns cleanup for every later stage, including a Host
 // handoff cancelled while the main window is still loading.
-const quitCoordinator = createAppQuitCoordinator({
-  prepareToQuit: prepareRuntimeHostDesktopQuit,
-  cleanup: closeRuntimeHostDesktop,
-  focusOrCreateWindow: (signal) => {
-    if (!runtimeHostManager) return;
-    if (mainWindowController.hasOpenWindows()) mainWindowController.focus();
-    else return mainWindowController.createWindow(signal);
-  },
-  onPreparationError: (error) => {
-    console.error("[runtime-host] quit retirement failed:", error);
-  },
-  onCleanupError: (error) =>
-    console.error("[runtime-host] shutdown failed:", error),
-  onWindowCreationError: (error) =>
-    console.error("[window] creation failed:", error),
-  resumeQuit: () => app.quit(),
-});
-app.on("before-quit", quitCoordinator.handleBeforeQuit);
 // The manager registers its IPC router on construction; starting the Local
 // Host is a background reconciliation, not a prerequisite for the window.
 runtimeHostManager = createLocalRuntimeHostManager();
+bootContext.runtimeHostManager = runtimeHostManager;
 runtimeHostManager.setDefaultProfile(runtimeHostStartup.preferences.defaultProfileId);
 wireLifecycle();
 sessionLocal.wake();
 windowsAppTray.start();
 // Remote profiles do not depend on the Local Host: a handoff parked on a
-// user decision must not hold their activation for the whole session.
-void runtimeHostProfileService.startEnabledProfiles();
+// user decision must not hold their activation for the whole session. Remote
+// transports spawn SSH/relay children, so they still wait on the shell PATH.
+void shellEnvReady.then(() => runtimeHostProfileService.startEnabledProfiles());
 // Runtime Host is the only schema-migration authority for its State Root.
 // Work Board remains a Desktop-owned table, but it opens only while a ready
 // Host has verified the schema — including a Local Host that only becomes
@@ -1484,6 +1314,7 @@ const registerDesktopWorkBoard = (): void => {
   }
 };
 void (async () => {
+  await shellEnvReady;
   await runtimeHostManager?.start();
   registerDesktopWorkBoard();
   await guestSessionMountService.start().catch((error: unknown) => {
@@ -2246,50 +2077,6 @@ function wakePeerRecoveryAfterResume(): void {
   runtimeHostManager?.wakePeerRecovery();
 }
 
-function resolveDesktopE2eFixture(): ReturnType<typeof resolveE2eFixture> {
-  try {
-    return resolveE2eFixture(
-      process.env.MAKA_E2E_FIXTURE,
-      app.isPackaged,
-      process.env.MAKA_E2E_FIXTURE_REDUCED_MOTION,
-      process.env.MAKA_E2E_FIXTURE_THEME,
-      process.env.MAKA_E2E_FIXTURE_LOCALE,
-      process.env.MAKA_E2E_FIXTURE_TIMEZONE,
-      process.env.MAKA_E2E_FIXTURE_PLATFORM,
-    );
-  } catch (error) {
-    if (!process.env.MAKA_E2E_FIXTURE) throw error;
-    console.error(
-      `[e2e-fixture] fatal: ${error instanceof Error ? error.message : String(error)}`,
-    );
-    process.exit(1);
-  }
-}
-
-async function confirmDesktopStorageRootRepair(
-  workspaceRoot: string,
-): Promise<boolean> {
-  console.log(
-    "[storage-root] root-identity conflict; parking at repair dialog",
-  );
-  const locale = resolveSystemUiLocale(app.getPreferredSystemLanguages());
-  const copy = getNativeDiagnosticDialogCopy(locale).storageRootRepair;
-  const { response } = await showStartupDiagnosticDialog(
-    {
-      type: "warning",
-      title: copy.title,
-      message: copy.message,
-      detail: copy.detail(workspaceRoot),
-      buttons: [copy.repair, copy.exit],
-      defaultId: 1,
-      cancelId: 1,
-      noLink: true,
-    },
-    locale,
-  );
-  return response === 0;
-}
-
 async function promptForDefaultRuntimeHostRecovery(input: {
   readonly profileId: string;
   readonly profileName: string;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org