Skip to content

bug(desktop): explicit Quit Maka leaves the local Runtime Host holding the State Root writer #3703

Description

@M4n5ter
English

What happened

Explicitly quitting Maka Desktop can leave the Desktop-owned ephemeral Runtime Host alive when durable residency exists. The surviving Host continues to hold the sole State Root writer, so a later Desktop generation or compatibility epoch cannot start against that root. Waiting does not converge while recurring durable work keeps the old Host resident; the current workaround is to identify and terminate the process manually.

Expected behavior: a full Quit Maka action is maintenance authorization for the Desktop-owned local ephemeral Host. It should retire that exact Host and release the writer before Desktop completes a clean exit. Closing only one Surface must remain distinct and must not stop a shared or operator-owned Host.

This is the urgent local Desktop slice of #3231.

How to reproduce

  1. Start Desktop with its local ephemeral Runtime Host.
  2. Create durable residency, such as an active recurring Scheduled Task.
  3. Explicitly quit Desktop without manually terminating the Host.
  4. Confirm that the Host remains alive and still owns the State Root writer.
  5. Start a later Desktop generation or compatibility epoch against the same State Root.
  6. Observe that Runtime Host election / State Root writer acquisition cannot complete. If the conflict UI is reached, Wait cannot converge while recurring residency remains.
  7. Terminate the surviving Host manually and observe that startup completes.

Environment

Logs, screenshots, or additional context

Reproduction evidence

The macOS reproduction recorded:

  • surviving Host: PPID 1 while retaining the State Root writer;
  • stale Electron singleton owner PID gone while SingletonSocket remained;
  • runtime.sqlite / runtime.sqlite-wal still open;
  • the next Desktop launch blocked in Runtime Host election / writer acquisition;
  • terminating the surviving Host allowed startup to complete immediately.

#3231 contains a Windows reproduction where an active Scheduled Task kept the epoch 24 Host resident and the epoch 25 Desktop could offer only Wait or Cancel Startup.

Verified current implementation

  • before-quit runs closeRuntimeHostDesktop.
  • closeRuntimeHostDesktop calls runtimeHostManager.close().
  • RuntimeHostDesktopManager.close() closes reconnect lifecycles and Client resources, but does not request retirement of the owned local Host.
  • The only Desktop path that currently invokes authenticated host.upgrade.prepare and waits for the exact adopted Host PID to exit is prepareForUpdate.

Durable residency therefore turns explicit Desktop quit into Surface-only disconnection at the Runtime Host boundary.

Why #3348 did not fix this

#3348 explicitly left normal-quit Host survival untouched. Its proposed registration/PID residue sweep was removed after review because PID termination could not be bound atomically to the authenticated Host; the PR closed with no functional fix. This issue must not revive registration-only PID killing.

Required behavior

When Electron is performing an explicit full application quit:

  • treat the action as maintenance authorization for the Desktop-owned local ephemeral Host;
  • stop candidate launches and bind retirement to the exact adopted Host identity/epoch;
  • fence new admission, preserve durable intent, and settle or explicitly interrupt active execution under [Tracking] Runtime Host maintenance and single-writer retirement #3231;
  • wait until the Host releases Domain resources and the sole State Root writer before completing application exit;
  • leave local service-mode Hosts and managed remote Hosts running;
  • report a truthful, bounded failure instead of silently claiming clean quit if safe retirement cannot complete.

Window-only close and full Quit Maka must have explicit, tested product semantics on each platform.

Acceptance criteria

  • Native Quit Maka / Cmd+Q / an equivalent explicit full-quit path retires the exact Desktop-owned ephemeral Host even when a Scheduled Task, Goal, or Automation holds durable residency.
  • Desktop does not finish clean shutdown until writer release is observed, or reports an actionable retirement failure.
  • Starting Maka again against the same State Root does not require manual process termination.
  • Durable schedules and continuation intent recover when Maka starts again; no background Host work runs while Maka is fully stopped.
  • In-flight work is recovered from a supported durable checkpoint or recorded as explicitly interrupted; unresolved external effects remain result_unknown.
  • Managed remote and local service-mode Hosts are not retired by Desktop quit.
  • Tests cover idle and durable-resident local Hosts, active execution, retirement failure, and platform-specific window-close/full-quit mapping.

Architecture boundaries

Two Draft PRs cover complementary parts of one larger lifecycle problem:

#3254 is not limited to takeover of a “truly idle” incompatible Host: it records a real epoch-24 takeover while a scheduled-task residency existed. That capability is legacy-dependent because the current Host kernel's generation-takeover path requires #isTrueIdle(). The system therefore lacks a stable, forward-compatible management contract for every incompatible durable-resident Host.

Neither Draft PR defines the final lifecycle authority. The target architecture is one local Host reconciliation system with one lifecycle owner, one artifact identity, one epoch fence, and one transition state machine shared by Desktop, installed CLI, and TUI presentation adapters.

Non-goals

Part of #3231.

AI assistance disclosure

Codex assisted with investigation and drafting. The evidence covers the #3348 outcome, #3254 behavior, and the main quit/retirement paths.

简体中文

发生了什么

存在 durable residency 时,用户明确退出 Maka Desktop 后,Desktop 自己拥有的 ephemeral Runtime Host 可能仍然存活。该 Host 会继续持有唯一的 State Root writer,导致后续 Desktop generation 或 compatibility epoch 无法针对同一 State Root 启动。只要 recurring durable work 继续保持 Host 常驻,等待就不会自行收敛;当前 workaround 是由用户定位并手工终止该进程。

预期行为:完整的退出 Maka应当构成对 Desktop 所拥有本地 ephemeral Host 的维护授权。Desktop 应让该精确 Host 安全退场并释放 writer,然后才能完成 clean exit。只关闭一个 Surface 必须保持不同语义,不能停止共享或由 operator 管理的 Host。

这是 #3231 中紧急的本地 Desktop 切片。

如何复现

  1. 启动 Desktop 及其本地 ephemeral Runtime Host。
  2. 创建 durable residency,例如启用一个 recurring Scheduled Task。
  3. 明确退出 Desktop,但不要手工终止 Host。
  4. 确认 Host 仍然存活,并继续持有 State Root writer。
  5. 使用后续 Desktop generation 或 compatibility epoch 针对同一个 State Root 启动。
  6. 观察 Runtime Host election / State Root writer acquisition 无法完成。即使进入 conflict UI,只要 recurring residency 仍存在,等待也不会收敛。
  7. 手工终止残留 Host,观察 Desktop 随即完成启动。

环境

日志、截图或补充上下文

复现证据

macOS 复现记录包括:

  • 残留 Host 的 PPID 1,且仍持有 State Root writer;
  • Electron singleton owner PID 已消失,但 SingletonSocket 仍存在;
  • runtime.sqlite / runtime.sqlite-wal 仍保持打开;
  • 下一次 Desktop 启动阻塞在 Runtime Host election / writer acquisition;
  • 手工终止残留 Host 后,启动立即完成。

#3231 还包含 Windows 复现:active Scheduled Task 使 epoch 24 Host 保持常驻,epoch 25 Desktop 只能提供等待取消启动

已核查的当前实现

  • before-quit 调用 closeRuntimeHostDesktop
  • closeRuntimeHostDesktop 调用 runtimeHostManager.close()
  • RuntimeHostDesktopManager.close() 只关闭 reconnect lifecycle 和 Client resource,不会请求所拥有本地 Host 退场。
  • 当前 Desktop 中,只有 prepareForUpdate 会调用已认证的 host.upgrade.prepare,并等待精确的 adopted Host PID 退出。

因此,durable residency 会让明确的 Desktop 退出在 Runtime Host 边界上退化成只断开 Surface。

为什么 #3348 没有修复该问题

#3348 明确没有改变 normal-quit Host survival。评审发现其 registration/PID residue sweep 无法将 PID kill 与已认证 Host 原子绑定,因此删除了该方案;PR 关闭时没有留下功能修复。本 issue 不能重新引入只根据 registration/PID 杀进程的方案。

必需行为

Electron 执行明确的完整应用退出时:

  • 将该操作视为对 Desktop-owned local ephemeral Host 的维护授权;
  • 停止 candidate launch,并将 retirement 绑定到精确的 adopted Host identity/epoch;
  • [Tracking] Runtime Host maintenance and single-writer retirement #3231 停止新 admission、保存 durable intent,并收敛或明确中断 active execution;
  • 等待 Host 释放 Domain resource 和唯一 State Root writer 后,再完成应用退出;
  • 不停止 local service-mode Host 和 managed remote Host;
  • 无法安全完成 retirement 时,报告真实且有界的失败,不能静默声称 clean quit。

每个平台都必须明确并测试“只关闭窗口”和完整退出 Maka的产品语义。

验收标准

  • 原生退出 MakaCmd+Q 或等价 full-quit 路径,即使存在 Scheduled Task、Goal 或 Automation durable residency,也会让精确的 Desktop-owned ephemeral Host 退场。
  • Desktop 只有观察到 writer release 后才能完成 clean shutdown;否则必须报告可操作的 retirement failure。
  • 再次针对同一 State Root 启动 Maka 时,不需要用户手工终止进程。
  • Durable schedule 与 continuation intent 在 Maka 再次启动后恢复;Maka 完全停止期间不运行后台 Host work。
  • In-flight work 从受支持的 durable checkpoint 恢复,或被明确记录为 interrupted;无法确认的 external effect 保持 result_unknown
  • Desktop 退出不会让 managed remote 或 local service-mode Host 退场。
  • 测试覆盖 idle 与 durable-resident local Host、active execution、retirement failure,以及各平台 window-close/full-quit 映射。

架构边界

两个 Draft PR 分别覆盖同一个更大生命周期问题的互补部分:

#3254 并不限于接管“真正空闲”的不兼容 Host:它记录了 epoch 24 Host 仍有 scheduled-task residency 时的真实 takeover。该能力依赖 legacy Host 行为,因为当前 Host kernel 的 generation-takeover 路径要求 #isTrueIdle()。因此,系统仍缺少一套适用于所有未来不兼容且 durable-resident Host 的稳定管理契约。

两个 Draft PR 都没有定义最终 lifecycle authority。目标架构是一套本地 Host reconciliation 系统:由一个 lifecycle owner、一种 artifact identity、一道 epoch fence 和一个 transition state machine 统一支撑 Desktop、installed CLI 与 TUI presentation adapter。

非目标

属于 #3231

AI 辅助声明

Codex 协助了调查与起草。证据覆盖 #3348 的最终结果、#3254 的行为,以及 main 的退出和 retirement 路径。

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions