hermes-agent/apps/desktop/electron
Teknium da3a0a852f fix(update): make orphan-backend reap tree-aware + drain Desktop update trees without pre-signalling
Follow-up to #82179 addressing helix4u's review comment
(#82179 issuecomment-5229441571). Three parts:

1. Desktop teardown (salvaged from #77436, @4adwentures): the update
   hand-off's releaseBackendLock() sent SIGTERM to the primary backend
   BEFORE taskkill /T. If the launcher exits first, Windows can no longer
   enumerate its descendants and they survive holding the venv — the
   Electron path that creates the orphan #82179 then has to repair.
   New stopBackendTreesForUpdate() tree-kills the live root first, with
   the behavioral vitest from #77436. The scanner half of #77436 is
   deliberately NOT taken (superseded by #82158's full-cmdline scan).

2. Tree-aware orphan classification: _orphaned_desktop_backend_pids()
   previously refused the whole holder set when any holder had a live
   parent. But the scanner legitimately returns an orphaned serve root
   AND its descendants (the venv trampoline's uv-managed interpreter
   worker — which carries the same backend argv — plus .hermes-runtime
   children). Those have a live parent: the orphan root itself. Now
   holders inside an accepted orphan root's tree fold into that root
   (only roots are returned; taskkill /T reaps descendants), and
   live-parent backends defer to the ancestry check instead of refusing
   outright. Anything outside an orphan tree still refuses.

3. Tests for the mixed shapes: root+managed-runtime child,
   grandchild depth, non-descendant stray alongside an orphan root
   (still refuses), descendant exited mid-classify.

E2E on a real Windows box: spawned a detached backend-shaped orphan
that itself spawned children (3 python descendants); the scanner-shaped
mixed holder set classified to [root], taskkill /T reaped root and all
descendants. The live Desktop backend on the box still classified None
(refusal preserved). The first E2E attempt caught exactly the
trampoline/worker case the mocks missed — the live worker re-execs with
the same backend argv and a live parent — which is what part 2 fixes.

Co-Authored-By: 4adwentures <296413879+4adwentures@users.noreply.github.com>
2026-08-08 20:01:03 -07:00
..
active-runtime-state.test.ts
…
active-runtime-state.ts
…
backend-child.ts
…
backend-command.test.ts
…
backend-command.ts
…
backend-connection-state.test.ts
…
backend-connection-state.ts
…
backend-env.test.ts
…
backend-env.ts
…
backend-health.test.ts
…
backend-health.ts
…
backend-probes.test.ts
…
backend-probes.ts
…
backend-ready.test.ts
…
backend-ready.ts
…
backend-start-failure.test.ts
…
backend-start-failure.ts
…
bootstrap-platform.test.ts
…
bootstrap-platform.ts
…
bootstrap-repair-guard.test.ts
…
bootstrap-repair-guard.ts
…
bootstrap-runner.test.ts
…
bootstrap-runner.ts
…
connection-apply.test.ts
…
connection-apply.ts
…
connection-config.test.ts
…
connection-config.ts
…
crash-forensics.test.ts
…
crash-forensics.ts
…
dashboard-token.test.ts
…
dashboard-token.ts
…
desktop-electron-pin.test.ts
…
desktop-installation.test.ts
…
desktop-installation.ts
…
desktop-uninstall.test.ts
…
desktop-uninstall.ts
…
dev-cdp.test.ts
…
dev-cdp.ts
…
embed-referer.ts
…
entitlements.mac.inherit.plist
…
entitlements.mac.plist
…
event-dedupe.test.ts
…
event-dedupe.ts
…
find-git-bash.test.ts
…
find-git-bash.ts
…
find-in-page.test.ts
…
find-in-page.ts
…
first-run-setup-gate.test.ts
…
first-run-setup-gate.ts
…
first-run-setup-main-process.test.ts
…
fs-read-dir.test.ts
…
fs-read-dir.ts
…
gateway-ws-probe.test.ts
…
gateway-ws-probe.ts
…
git-repo-scan.test.ts
…
git-repo-scan.ts
…
git-review-ops.test.ts
…
git-review-ops.ts
…
git-root.test.ts
…
git-root.ts
…
git-worktree-ops.test.ts
…
git-worktree-ops.ts
…
hardening.test.ts
…
hardening.ts
…
link-title-window.test.ts
…
link-title-window.ts
…
main-window-lifecycle.test.ts
…
main-window-lifecycle.ts
…
main.ts
…
native-auth-decisions.test.ts
…
native-auth-decisions.ts
…
native-oauth-login.test.ts
…
native-oauth-login.ts
…
native-oauth.test.ts
…
native-oauth.ts
…
native-token-store.test.ts
…
native-token-store.ts
…
oauth-net-request.test.ts
…
oauth-net-request.ts
…
power-save.test.ts
…
power-save.ts
…
preload.ts
…
primary-backend-startup.test.ts
…
primary-backend-startup.ts
…
primary-connection-rehome.ts
…
profile-delete-routing.test.ts
…
profile-delete-routing.ts
…
profile-session-routing.test.ts
…
profile-session-routing.ts
…
quick-entry.test.ts
…
quick-entry.ts
…
quit-guard.test.ts
…
quit-guard.ts
…
remote-lifecycle.test.ts
…
remote-lifecycle.ts
…
remote-liveness.test.ts
…
remote-liveness.ts
…
session-windows.test.ts
…
session-windows.ts
…
spawn-helper-perms.test.ts
…
spawn-helper-perms.ts
…
ssh-bootstrap-coordinator.test.ts
…
ssh-bootstrap-coordinator.ts
…
ssh-config.test.ts
…
ssh-config.ts
…
ssh-connection.test.ts
…
ssh-connection.ts
…
stream-throttle.test.ts
…
stream-throttle.ts
…
titlebar-overlay-width.test.ts
…
titlebar-overlay-width.ts
…
update-count.test.ts
…
update-count.ts
…
update-gate.test.ts
…
update-gate.ts
…
update-marker.test.ts
…
update-marker.ts
…
update-rebuild.test.ts
…
update-rebuild.ts
…
update-relaunch.test.ts
…
update-relaunch.ts
…
update-remote.test.ts
…
update-remote.ts
…
updater-process.test.ts
…
updater-process.ts
…
venv-blocker-scan.test.ts
…
venv-blocker-scan.ts
…
vscode-marketplace.test.ts
…
vscode-marketplace.ts
…
wake-indicator-window.ts
…
wake-indicator.test.ts
…
wake-indicator.ts
…
window-below.test.ts
…
window-below.ts
…
window-reveal.test.ts
…
window-reveal.ts
…
window-state.test.ts
…
window-state.ts
…
windows-child-options.test.ts
…
windows-child-options.ts
…
windows-hermes-path.test.ts
…
windows-hermes-path.ts
…
windows-remote-lifecycle.test.ts
…
windows-remote-lifecycle.ts
…
windows-remote-live.test.ts
…
windows-sandbox-fallback.test.ts
…
windows-sandbox-fallback.ts
…
windows-system-ca.test.ts
…
windows-system-ca.ts
…
windows-user-env.test.ts
…
windows-user-env.ts
…
workspace-cwd.test.ts
…
workspace-cwd.ts
…
wsl-clipboard-image.test.ts
…
wsl-clipboard-image.ts
…
wsl-path-bridge.test.ts
…
wsl-path-bridge.ts
…
zoom.test.ts
…
zoom.ts
…