The updater's relaunch of the macOS shell died twice (#115332) with
EXC_BAD_ACCESS inside AppKit's key-equivalent routing: a keystroke landed on
the freshly launched app, AppKit asked the application menu's delegate to
populate, and Electron's delegate crashed because no window existed yet.
main.ts installed our menu inside app.whenReady() before createWindow(), and
Electron installs its own default menu even earlier — at
`will-finish-launching` — whenever the app has not called
Menu.setApplicationMenu before that event. On macOS a later
Menu.setApplicationMenu(null) never removes an installed NSMenu, so the
suppression has to run at module scope.
Now: Menu.setApplicationMenu(null) at module scope suppresses Electron's
default menu, and installApplicationMenuAfterFirstWindow() (new pure helper,
DI-tested) creates the first BrowserWindow and only then installs the real
menu on macOS. Windows/Linux keep shipping without an application menu.
Not live-run on macOS: no macOS runner is available here; the ordering is
proven by the helper's vitest cases and by code-path reading of Electron
40.10.2's lib/browser/init.ts + default-menu.ts.