Rework of the salvaged #59942 hook so it fixes the whole #52339 class without
regressing what the Desktop updater already gets right:
- macOS only. The Windows arm rmtree'd a possibly-running NSIS install
(partial deletion under a lock) and windows.ps1 already owns that swap;
Linux packages stay with their package manager.
- No re-sign. The rebuilt release/ bundle already carries the stable local
signing identity from _desktop_macos_relaunchable_fixup; a deep `codesign -s -`
on the installed copy replaced it with a fresh ad-hoc cdhash and reset every
TCC grant. ditto preserves the signature, so nothing is signed here.
- Running bundles are reported, not swapped: Electron loads app.asar and helper
apps lazily, so renaming the bundle away and deleting the old tree crashes
the live app. The detached updater waits for exit; a terminal `hermes update`
with the app open now prints what to do instead.
- Failures are printed as warnings; the old `Path | None` return read every
failure as "Desktop app up to date".
- The refresh also runs on the "build stamp current" path, so a stale
/Applications copy left by an earlier update heals on the next `hermes update`
even when there is nothing to rebuild.
- Core is host-independent (_install_rebuilt_macos_bundles takes paths as data);
the two invariant tests run on every OS instead of `skipif(darwin)` tests that
ran nowhere.
Covers the Desktop-button path too: posix.sh runs `hermes update`, so an app
running from apps/desktop/release/ now refreshes the /Applications copy Finder
launches (the Discord report: new shell right after the update, old shell on
the next Dock launch).