Skip to content

fix(runtime): wait for launchd job removal before service handoff - #8159

Merged
loopx-agent merged 1 commit into
mainfrom
codex/managed-service-handoff-20261106
Nov 6, 2026
Merged

loopx-agent merged 1 commit into
mainfrom
codex/managed-service-handoff-20261106

Conversation

@loopx-agent

Copy link
Copy Markdown
Collaborator

macOS 的 launchctl bootout 可能在旧 job 完全移除前返回。更新器紧接着加载同名新服务会失败,失败后的回滚也会遇到相同竞争。现在由现有 macOS 服务管理适配器有界等待 job 确认移除,再继续原交接;前向切换、回滚和中断恢复共用这一检查。未知查询错误或超时保留失败,原 Chat 准入围栏、活动工作保护、身份校验和恢复日志继续生效。

验证:三个相邻 Python 测试文件 139 项通过、4 项按原条件跳过;新增异步卸载场景在原主干上两项失败,在修复后通过。构建 Chat bundle 后另跑真实 launchd、Core、HTTP 和空隔离工作区验证,切换及失败回滚通过,连续三次核验未重复重启服务。源码与测试的公开边界扫描通过;全局检查另报两个既有 Goal 的 authority 未迁移错误,不属于本变更。真实用户的服务采用和旧消息补答须在安装后独立核验。

Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Reviewer: model_agent; GPT-6 family; OpenAI; self_reported.

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

动机 / Motivation

在 macOS 上升级或恢复已有 LoopX 工作区的用户会遇到这一问题。旧 job 尚未卸载完就加载新服务,切换失败后还可能无法恢复原服务;新路径先核实 job 离场,再继续交接。让原服务管理器安全采用新 Core,并保留活动请求和失败恢复。本次只修服务交接,不代替真实 Bot 消息验收,也不改变账号或请求权限。安装后的原服务采用和历史问题补答仍需独立验收。这次要修的不是模型答复内容,而是已安装的修复无法可靠进入在线服务的一个实际原因。只增加固定休眠不能证明旧服务已经离场,重复加载也会把同一个竞争带入失败恢复。

改动思路 / Approach

这是现有 macOS 服务适配器的 IO 完成条件,留在该 owner 内即可;不新增服务、策略或持久状态。当前 PR 仅等待原 job 移除,并把这一检查接入前向切换、回滚和中断恢复。原来的入口、目标可执行文件资格、实际管理器来源、Chat 准入围栏和私有交接日志继续负责权限与恢复。新增检查仅在原流程已经决定交接之后读取同一标签;返回113才视为已不存在,其他错误或期限到达仍是失败。用表格概括本 head 的差异即可,无需另造状态图:

场景 base 本 head
bootout 返回但 job 仍在 直接 bootstrap,可能失败 先确认 job 移除
新服务启动失败 恢复也会撞上异步卸载 同一检查保护恢复
原服务身份已匹配或存在活动请求 复用或拒绝切换 保留原行为

具体改动 / Changes

关键代码讲解

  1. _wait_unloaded 用 launchctl print 核对原标签,最多等待五秒;未知查询错误不会被当成“服务已不存在”。该函数只观察管理器,不发送第二条停止或业务请求。
  2. _align_managed_runtime 在已成功 bootout、已记录 stopped 后等待,之后才加载候选;回滚也在恢复原配置和加载前确认离场。这样等待本身失败时仍保留真实已停止服务的恢复责任。
  3. _recover_alignment 把相同条件用于中断日志恢复,沿原标签、启动参数和数据路由核验,保持一个恢复 owner。

规范依据为 apps/desktop/loopx-control-plane/README.md,固定 revision 54e26effd9cc958179b9fe555d50ba22d13538a6 的服务交接段落。INGRESS:仍先保护全部已接受工作,busy Chat 用例验证无停止/写入。ROUTE:保留注册表、数据、账号和参数,原 retarget/custom-route 用例及真实管理器验证。READBACK:两个 HTTP 服务仍需匹配目标身份,连续三次核验未改变 PID。ROLLBACK:启动失败恢复原配置、中断保留日志并可接续,异步回滚和原中断测试覆盖。以上均为本次映射的规范条目,未把部署后的业务补答算成已验收。

对主干的风险 / Risks

没有发现阻断性问题。最强反例是同步 mock 在 bootout 时立即删 job,使前向和回滚都假绿。本次加入“返回成功但标签再保留两个查询周期”的对抗场景,同一测试在 base 两项失败,在本 head 通过;另有严格未知返回码和期限拒绝。原有135项控制在 base 通过,本 head 三个相邻文件139项通过、4项按原环境条件跳过。

真实 launchd、Core、HTTP 和隔离空工作区测试在构建 Chat bundle、关闭测试上报后于当前 head 另行通过,覆盖原服务恢复、目标采用和三次无重复重启。首次新 checkout 缺少 bundle 的失败记录保留,构建是仓库原验收前提;未以延长期限或删除断言消掉失败。Python 编译、RFC 双语差分和 diff hygiene 通过,两个变更文件的公开边界扫描通过。全局检查另报两个 Goal 的 canonical authority 不可用,作为不属于本次服务交接验证的诊断保留,没有替它们迁移状态。CI 按本 Goal 配置不查询、不等待。

语义与 CI 对齐

这是本机服务适配器的完成条件修复,复用原 activation 错误和恢复日志,没有新协议、指令、账号权限或默认模型策略。五秒确认仍可能保守拒绝极慢卸载;真实原 Bot 的服务采用、旧问题正文和渠道读回不能由隔离测试替代。

我的整体评价 / Verdict

对长期可靠性和用户体验的判断都是 improved:后续正常升级及中断恢复共同使用同一个服务离场检查,避免要求用户反复触发更新。完整变化是20行生产代码与57行新增测试,现有 OS owner 足以承担;未引入兼容分支、持久字段或另一控制器。这个有用的有界修复可以合入,但安装后的原服务身份及逐条业务回复仍开放,不能据此宣称旧消息全部处理完成。

English verdict: APPROVE — head e5acc77; no blocking finding. Native handoff/rollback, base counterfactual and existing controls pass; original Bot delivery remains post-install acceptance.

@loopx-agent
loopx-agent merged commit 927d0b3 into main Nov 6, 2026
5 of 6 checks passed
@loopx-agent
loopx-agent deleted the codex/managed-service-handoff-20261106 branch November 6, 2026 02:12
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