Skip to content

refactor(desktop): couple host-service to Electron, drop adoption#4739

Merged
Kitenite merged 2 commits into
mainfrom
electron-host-service-cou
May 20, 2026
Merged

refactor(desktop): couple host-service to Electron, drop adoption#4739
Kitenite merged 2 commits into
mainfrom
electron-host-service-cou

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented May 19, 2026

Summary

Host-service no longer survives Electron. The detach + manifest-adoption machinery was load-bearing back when host-service owned PTYs directly; now that pty-daemon (separate detached lifecycle, supervised by host-service) owns PTY survival, host-service itself has no reason to outlive the app.

  • Coordinator — spawn with `detached: false`. Remove `tryAdopt`, `discoverAll`, `teardownKnownManifests`, `releaseAll`, adopted-liveness timer, and the version-mismatch healing branch. `stop` / `stopAll` / `restart` / `reset` kept; `reset` is still the SIGKILL escape hatch for wedged manifests.
  • Quit path — `before-quit` always SIGTERMs host-services. `runFullQuitCleanup` collapses into `teardownTerminalHost` (v1 only).
  • Parent watchdog — host-service polls `process.ppid` against `HOST_PARENT_PID`. If Electron crashes / force-quits without sending SIGTERM, the child reaps itself within ~2s. CLI-spawned standalone host-services don't set the env var and skip the watchdog.
  • Graceful shutdown — SIGTERM gets a 3s drain, then `closeAllConnections` forces SSE/WS streams (chat completions, file watchers) closed so we don't hang.
  • Manifest — still written by the child so the CLI (`packages/cli`) can find a running service. Desktop coordinator no longer reads it for adoption, only for the `reset` recovery path.
  • Docs and tests updated; `HOST_SERVICE_LIFECYCLE.md` rewritten.

Net: ~390 lines deleted, simpler lifecycle, no orphan host-services.

Test plan

  • `bun run lint` clean
  • `bun run typecheck` clean in apps/desktop
  • All 1959 desktop tests pass
  • Manual: open a chat completion, Cmd+R the window, verify the renderer reconnects to a fresh host-service cleanly
  • Manual: `kill -9` the Electron process while a host-service is running, then `ps aux | grep host-service` ~10s later — should be empty (watchdog reaped it)
  • Manual: run auto-update install, verify new version's host-service starts fresh (no stale-adoption)
  • Manual: CLI `superset status` while desktop running — should still find host-service via manifest

Open in Stage

Summary by cubic

Coupled the desktop host-service to Electron so it starts and stops with the app; removed manifest adoption and simplified quit paths. PTY survival is handled by a detached pty-daemon, keeping terminals intact across restarts.

  • Refactors

    • Spawn host-service attached (detached: false); before-quit calls coordinator.stopAll().
    • Removed adoption code: tryAdopt, discoverAll, teardownKnownManifests, releaseAll, adopted-liveness timer, version-mismatch branch.
    • Deleted unused APIs: hasActiveInstances, listManifests; dropped spawnedByAppVersion from manifest and SUPERSET_APP_VERSION env.
    • Replaced runFullQuitCleanup with teardownTerminalHost (v1 only); dev SIGTERM/SIGINT also stops services.
    • Manifests still written by the child; desktop reads them only for reset. CLI in packages/cli still reads them.
  • Bug Fixes

    • Parent-pid watchdog starts at process boot so the child self-exits even if Electron crashes during startup.
    • Graceful SIGTERM with a 3s drain; closeAllConnections ends SSE/WS so shutdown doesn’t hang.
    • Removes the “wedged adopted service” path and prevents orphan host-service processes.

Written for commit 06aa423. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • Improvements

    • Host services perform graceful shutdown with connection draining and forced-exit fallback for more reliable quits.
    • Host services monitor parent app health and self-exit if the app crashes, preventing orphaned processes.
  • Changes

    • Host-service lifecycle is now owned by the app—services stop on quit and are not re-adopted on restart.
    • Terminal PTYs survive via a separate daemon so open terminals persist after quitting.
    • CLI now consumes service manifests for status/control; manifests are removed on stop.

Review Change Stack

Host-service no longer survives Electron — children spawn attached
(detached: false) and get SIGTERMed via stopAll() on before-quit. A
parent-pid watchdog inside the child handles crash/force-kill paths
where SIGTERM never arrives, so we don't leak orphans.

PTY survival is now owned entirely by pty-daemon (which host-service
supervises with its own detached lifecycle), so coupling host-service
itself loses no user-facing property and removes a large class of
"wedged adopted service" bugs.

Removes tryAdopt/discoverAll/teardownKnownManifests/releaseAll/
adopted-liveness from the coordinator. Manifest writing stays — the
CLI in packages/cli still reads it to find a live host-service.
Adopts a 3s drain window on SIGTERM so in-flight HTTP/SSE/WS finish
or get torn down cleanly.
@capy-ai
Copy link
Copy Markdown

capy-ai Bot commented May 19, 2026

Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 19, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 30615c30-6664-4782-8a00-cc2fd4198692

📥 Commits

Reviewing files that changed from the base of the PR and between 4f9643b and 06aa423.

📒 Files selected for processing (5)
  • apps/desktop/src/main/host-service/env.ts
  • apps/desktop/src/main/host-service/index.ts
  • apps/desktop/src/main/lib/host-service-coordinator.test.ts
  • apps/desktop/src/main/lib/host-service-coordinator.ts
  • apps/desktop/src/main/lib/host-service-manifest.ts
💤 Files with no reviewable changes (2)
  • apps/desktop/src/main/host-service/env.ts
  • apps/desktop/src/main/lib/host-service-manifest.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/desktop/src/main/host-service/index.ts
  • apps/desktop/src/main/lib/host-service-coordinator.ts

📝 Walkthrough

Walkthrough

Host-service lifecycle refactored from manifest-based adoption to direct Electron coupling: Electron SIGTERMs host-services on quit via coordinator.stopAll(); host-service gains guarded shutdown and HOST_PARENT_PID watchdog; manifest shape and coordinator adoption/discovery removed; pty-daemon now owns PTY survivability.

Changes

Host-Service Lifecycle Redesign

Layer / File(s) Summary
Lifecycle Architecture & Design Documentation
apps/desktop/docs/HOST_SERVICE_LIFECYCLE.md, apps/desktop/src/lib/electron-app/factories/app/setup.ts
Architecture and design docs updated to describe host-service as Electron-coupled (stops with app), removal of adoption/release semantics, manifest handling split between CLI and coordinator, and watchdog-based self-exit via HOST_PARENT_PID env variable.
Electron App Quit Flow
apps/desktop/src/main/index.ts
Electron main process updated to call coordinator.stopAll() in before-quit, introduces teardownTerminalHost() for focused terminal-host shutdown, and removes prior discover/adopt surviving services call before tray initialization.
Host-Service Env Schema
apps/desktop/src/main/host-service/env.ts
Removed SUPERSET_APP_VERSION validation from the host-service environment schema.
Host-Service Process Graceful Shutdown & Orphan Watchdog
apps/desktop/src/main/host-service/index.ts
Host-service entry point adds guarded shutdown routine with server drain, forced-exit timeout, SIGTERM/SIGINT handlers, and a watchdog loop that self-exits if Electron parent crashes by checking HOST_PARENT_PID liveness.
Coordinator Tests: Mock Refactoring & Adoption Test Removal
apps/desktop/src/main/lib/host-service-coordinator.test.ts
Test suite refactored with centralized resetMocks() helper, removed listManifests mock wiring and tryAdopt adoption-health tests, updated lifecycle teardown to stopAll(), relaxed some reset assertions, and added a test ensuring reset skips SIGKILL when manifest PID is not alive.
Coordinator Core: Remove Adoption & Adjust Spawn
apps/desktop/src/main/lib/host-service-coordinator.ts
Removes manifest-based adoption validation and liveness timers; deletes public methods releaseAll(), discoverAll(), teardownKnownManifests(); simplifies startWithPreferredPorts to direct spawn; spawn uses detached:false, unconditional child.unref(), and sets HOST_PARENT_PID in child environment.
Host-Service Manifest Shape & Read
apps/desktop/src/main/lib/host-service-manifest.ts
HostServiceManifest no longer contains spawnedByAppVersion; readManifest simplified to strict parse return; listManifests and related directory-listing imports removed.

Sequence Diagram(s)

sequenceDiagram
  participant App as Electron App
  participant Coord as HostServiceCoordinator
  participant HS as Host-Service
  participant PTY as pty-daemon

  App->>Coord: before-quit -> stopAll()
  Coord->>HS: SIGTERM
  HS->>HS: shutdown() (server.close, drain, timeout)
  HS->>PTY: manage/hand off PTYs (pty-daemon detached)
  Note right of HS: HOST_PARENT_PID watchdog may self-exit if parent dies
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • superset-sh/superset#4648: Related host-service adoption/reset logic and manifest/killing flows; touches coordinator and manifest handling.
  • superset-sh/superset#4448: Related changes to host-service-coordinator.test.ts mock setup and module mocking.
  • superset-sh/superset#4499: Related discussion/changes around adoption and spawnedByAppVersion handling in coordinator/manifest code.

Poem

🐰
Once manifests whispered which hosts to keep,
Now Electron holds them close, no secrets deep.
A watchdog hums for orphans in the night,
PTY-daemon guards the terminals' light.
Goodbye, adoption — graceful SIGTERM flight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title directly and specifically describes the main architectural change: coupling host-service to Electron and removing the adoption mechanism, which is the primary goal across all modified files.
Description check ✅ Passed The PR description comprehensively covers all required sections: a detailed summary explaining the changes, related technical context, type of change (refactor), testing plan with multiple verification steps, and additional notes from cubic's auto-generated summary.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch electron-host-service-cou

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@stage-review
Copy link
Copy Markdown

stage-review Bot commented May 19, 2026

Ready to review this PR? Stage has broken it down into 5 individual chapters for you:

Title
1 Simplify host-service manifest and environment schema
2 Implement parent watchdog and graceful shutdown
3 Remove adoption logic from the coordinator
4 Wire simplified quit paths in Electron main
5 Update coordinator tests and documentation
Open in Stage

Chapters generated by Stage for commit 06aa423 on May 19, 2026 11:41pm UTC.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/desktop/docs/HOST_SERVICE_LIFECYCLE.md`:
- Line 7: The fenced diagram block in HOST_SERVICE_LIFECYCLE.md is missing a
language tag which triggers markdownlint MD040; update the opening fenced code
block (the triple-backtick diagram block) to include a language specifier such
as "text" so it becomes a fenced block with a language (e.g., change the opening
``` to ```text) to satisfy the linter and preserve the diagram rendering.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fdb24782-426b-44d3-a0e9-c9169943dbc0

📥 Commits

Reviewing files that changed from the base of the PR and between b634ed5 and 4f9643b.

📒 Files selected for processing (6)
  • apps/desktop/docs/HOST_SERVICE_LIFECYCLE.md
  • apps/desktop/src/lib/electron-app/factories/app/setup.ts
  • apps/desktop/src/main/host-service/index.ts
  • apps/desktop/src/main/index.ts
  • apps/desktop/src/main/lib/host-service-coordinator.test.ts
  • apps/desktop/src/main/lib/host-service-coordinator.ts

Electron main owns app lifecycle, tray, and host-service management. Host-services run as child processes that can outlive the app via manifest-based adoption.
Electron main owns app lifecycle, tray, and host-service management. Host-service runs as a child process **coupled to Electron** — it starts and stops with the app. Terminal sessions (PTYs) survive Electron restarts via a separate `pty-daemon` that host-service supervises on its own detached lifecycle.

```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Specify a language for the fenced diagram block.

Line 7 opens a fenced block without a language, which triggers markdownlint MD040.

Suggested fix
-```
+```text
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 7-7: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/docs/HOST_SERVICE_LIFECYCLE.md` at line 7, The fenced diagram
block in HOST_SERVICE_LIFECYCLE.md is missing a language tag which triggers
markdownlint MD040; update the opening fenced code block (the triple-backtick
diagram block) to include a language specifier such as "text" so it becomes a
fenced block with a language (e.g., change the opening ``` to ```text) to
satisfy the linter and preserve the diagram rendering.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 19, 2026

Greptile Summary

This PR couples host-service lifetime to Electron by switching from detached:true + manifest-adoption to detached:false + a parent-pid watchdog. The adoption machinery (tryAdopt, discoverAll, teardownKnownManifests, releaseAll, liveness timers) is removed entirely, PTY survival is delegated to a separate pty-daemon that host-service supervises, and before-quit now always SIGTERMs children instead of releasing them.

  • Coordinator simplificationstart() is now a direct spawn() call; stop()/stopAll()/restart()/reset() are kept; reset() is still the SIGKILL escape hatch for wedged manifests read off disk.
  • Watchdog — host-service polls process.ppid against HOST_PARENT_PID every 2 s; on orphan detection it triggers the same 3-second graceful-drain path as SIGTERM; CLI-spawned instances skip the watchdog by not setting the env var.
  • Shutdown drainserver.close() + an unref'd 3-second forceExit timer that calls closeAllConnections() handles SSE/WebSocket streams that survive server.close().

Confidence Score: 4/5

Safe to merge. The adoption/release machinery is cleanly removed, the new watchdog and drain path handle all quit scenarios correctly, and stopAll() is now reliably called on every quit path.

The overall refactor is well-structured and the shutdown flows are sound. The one edge case worth addressing is in isParentAlive: catching EPERM and returning false would cause the watchdog to self-terminate even though the Electron parent is still alive. This scenario requires a uid mismatch between parent and child, which is not the designed deployment, but the signal-0 POSIX contract for EPERM makes the silent catch technically incorrect.

apps/desktop/src/main/host-service/index.ts — specifically the isParentAlive EPERM handling in the watchdog.

Important Files Changed

Filename Overview
apps/desktop/src/main/host-service/index.ts Adds graceful SIGTERM drain (3 s) and parent-watchdog (2 s poll); one edge case in EPERM handling in isParentAlive.
apps/desktop/src/main/lib/host-service-coordinator.ts Removes adoption/release machinery; start() now directly spawns; detached:false + HOST_PARENT_PID set correctly; child.unref() now unconditional.
apps/desktop/src/main/index.ts before-quit now always calls stopAll() (synchronous); runFullQuitCleanup collapsed into teardownTerminalHost; discoverAll removed from app startup.
apps/desktop/src/main/lib/host-service-coordinator.test.ts Removes adoption test suite; introduces resetMocks() helper; tests updated to use stopAll() instead of releaseAll().
apps/desktop/src/lib/electron-app/factories/app/setup.ts Comment-only update reflecting new lifecycle (no release/re-adoption).
apps/desktop/docs/HOST_SERVICE_LIFECYCLE.md Docs rewritten to reflect coupled lifecycle, watchdog, and pty-daemon separation.

Sequence Diagram

sequenceDiagram
    participant E as Electron Main
    participant C as HostServiceCoordinator
    participant HS as host-service child
    participant WD as Watchdog in HS

    Note over E,HS: Normal launch
    E->>C: start(orgId, config)
    C->>HS: "spawn detached:false HOST_PARENT_PID=Electron.pid"
    HS-->>C: pollHealthCheck returns Connection
    HS->>WD: setInterval 2s poll ppid

    Note over E,HS: Clean quit
    E->>C: stopAll in before-quit sync
    C->>HS: SIGTERM
    HS->>HS: shutdown SIGTERM server.close
    HS->>HS: forceExit timer 3s unrefed
    HS->>HS: closeAllConnections then process.exit

    Note over E,HS: Force-kill crash
    E--xE: parent exits without SIGTERM
    WD->>WD: ppid changed or ESRCH
    WD->>HS: shutdown parent-exit
    HS->>HS: same 3s drain path
Loading
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
apps/desktop/src/main/host-service/index.ts:139-146
The `catch` block swallows all errors from `process.kill(parentPid, 0)`, including `EPERM`. On POSIX, `EPERM` means the target process **exists** but the caller lacks permission to signal it (e.g. different uid after a privilege drop). Returning `false` in that case would cause the watchdog to call `shutdown("parent-exit")` even though Electron is still alive, killing the host-service spuriously. `ESRCH` (process not found) is the only error that genuinely means "dead parent".

```suggestion
function isParentAlive(parentPid: number): boolean {
	try {
		process.kill(parentPid, 0);
		return process.ppid === parentPid;
	} catch (err) {
		// EPERM means the process exists but we can't signal it — still alive.
		if ((err as NodeJS.ErrnoException).code === "EPERM") {
			return process.ppid === parentPid;
		}
		return false;
	}
}
```

Reviews (1): Last reviewed commit: "refactor(desktop): couple host-service t..." | Re-trigger Greptile

Comment on lines +139 to 146
function isParentAlive(parentPid: number): boolean {
try {
process.kill(parentPid, 0);
return process.ppid === parentPid;
} catch {
return false;
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 The catch block swallows all errors from process.kill(parentPid, 0), including EPERM. On POSIX, EPERM means the target process exists but the caller lacks permission to signal it (e.g. different uid after a privilege drop). Returning false in that case would cause the watchdog to call shutdown("parent-exit") even though Electron is still alive, killing the host-service spuriously. ESRCH (process not found) is the only error that genuinely means "dead parent".

Suggested change
function isParentAlive(parentPid: number): boolean {
try {
process.kill(parentPid, 0);
return process.ppid === parentPid;
} catch {
return false;
}
}
function isParentAlive(parentPid: number): boolean {
try {
process.kill(parentPid, 0);
return process.ppid === parentPid;
} catch (err) {
// EPERM means the process exists but we can't signal it — still alive.
if ((err as NodeJS.ErrnoException).code === "EPERM") {
return process.ppid === parentPid;
}
return false;
}
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/main/host-service/index.ts
Line: 139-146

Comment:
The `catch` block swallows all errors from `process.kill(parentPid, 0)`, including `EPERM`. On POSIX, `EPERM` means the target process **exists** but the caller lacks permission to signal it (e.g. different uid after a privilege drop). Returning `false` in that case would cause the watchdog to call `shutdown("parent-exit")` even though Electron is still alive, killing the host-service spuriously. `ESRCH` (process not found) is the only error that genuinely means "dead parent".

```suggestion
function isParentAlive(parentPid: number): boolean {
	try {
		process.kill(parentPid, 0);
		return process.ppid === parentPid;
	} catch (err) {
		// EPERM means the process exists but we can't signal it — still alive.
		if ((err as NodeJS.ErrnoException).code === "EPERM") {
			return process.ppid === parentPid;
		}
		return false;
	}
}
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 6 files

Re-trigger cubic

- Delete hasActiveInstances() — no callers post-adoption.
- Delete listManifests() from apps/desktop manifest module — only
  callers were the adoption discoverAll/teardownKnownManifests
  paths, both removed.
- Delete spawnedByAppVersion manifest field + SUPERSET_APP_VERSION
  env propagation — only consumer was the version-mismatch adoption
  branch.
- Install parent-pid watchdog at the top of the desktop host-service
  main() so a crash during startup awaits can still reap the child.
@Kitenite Kitenite merged commit 5556aec into main May 20, 2026
10 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch

Thank you for your contribution! 🎉

sazabi Bot pushed a commit that referenced this pull request May 20, 2026
)

* refactor(desktop): couple host-service to Electron, drop adoption

Host-service no longer survives Electron — children spawn attached
(detached: false) and get SIGTERMed via stopAll() on before-quit. A
parent-pid watchdog inside the child handles crash/force-kill paths
where SIGTERM never arrives, so we don't leak orphans.

PTY survival is now owned entirely by pty-daemon (which host-service
supervises with its own detached lifecycle), so coupling host-service
itself loses no user-facing property and removes a large class of
"wedged adopted service" bugs.

Removes tryAdopt/discoverAll/teardownKnownManifests/releaseAll/
adopted-liveness from the coordinator. Manifest writing stays — the
CLI in packages/cli still reads it to find a live host-service.
Adopts a 3s drain window on SIGTERM so in-flight HTTP/SSE/WS finish
or get torn down cleanly.

* chore(desktop): drop dead code from host-service coupling refactor

- Delete hasActiveInstances() — no callers post-adoption.
- Delete listManifests() from apps/desktop manifest module — only
  callers were the adoption discoverAll/teardownKnownManifests
  paths, both removed.
- Delete spawnedByAppVersion manifest field + SUPERSET_APP_VERSION
  env propagation — only consumer was the version-mismatch adoption
  branch.
- Install parent-pid watchdog at the top of the desktop host-service
  main() so a crash during startup awaits can still reap the child.
MocA-Love added a commit to MocA-Love/superset that referenced this pull request May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant