Skip to content

fix(native-accounts): await acknowledged service unload - #7358

Merged
loopx-agent merged 1 commit into
mainfrom
codex/native-auth-unload-wait-20261026
Oct 26, 2026
Merged

loopx-agent merged 1 commit into
mainfrom
codex/native-auth-unload-wait-20261026

Conversation

@loopx-agent

Copy link
Copy Markdown
Collaborator

launchd can acknowledge bootout while the service is still exiting. The native account coordinator previously treated that transient registration as a failed pause, restored the source client and aborted an otherwise valid handoff.

Wait up to five seconds for actual unload, retaining the existing recovery intent and refusing the credential transaction if the job remains loaded. No ownership, consent, force-quit, quota-freshness or account-selection rule changes. Provider manifests advance to 0.12.7 and the operator contract describes this bounded wait.

Validation: the delayed-unload full-switch counterexample fails on 0.12.6 and passes here; the never-unloaded negative case preserves recovery and performs no transaction. All five provider Python smokes (22 operator tests), ten TypeScript policy tests, Ruff/compile and committed premerge gates passed. The credential-free real macOS launchd fixture also restarts both discovered services to fresh PIDs with one synthetic account transaction. A real production credential swap remains outside that fixture.

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; model=GPT-6; provider=OpenAI; self_reported

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

动机

已经允许自动换号并重启客户端的用户,会在后台服务异步退出时遇到这个问题。例如系统已经接受停止 Chat 服务,服务却还短暂显示为退出中;旧路径立即报暂停失败并中止换号,新路径等待真实卸载后再继续。延迟卸载的完整切换用例现在只执行一次账号事务并恢复服务;永不卸载的用例仍拒绝换号并保留恢复意图。本次仅修正停止确认与实际卸载之间的时序,不改变账号选择、授权范围或强退权限,也不重放业务。生产真实凭据切换与未知虚拟机归属仍由既有维护任务继续验收;隔离进程实测不等于生产业务恢复。

改动思路

这个等待属于原有 native host 的服务 IO 确认步骤;复用已有恢复意图和账号事务,不增加调度器、状态库、许可或策略开关。当前 PR 一次交付卸载等待、超时拒绝、回归和 0.12.7 文档清单;后续按原安装路径采用同一构建。单次确认不足以区分“正常退出中”和“停止失败”;固定休眠则可能既等待过长又不足。这里让原暂停 owner 读取真实 job 状态,在卸载后继续现有内核身份退出核验和原生事务;一直未卸载就保留同一恢复意图并报告失败。原有额度新鲜度及手工选择 fence 仍在凭据变更前重验,不因多等几次就放宽。

具体改动

五个文件 +48/-4。生产改动集中在暂停服务后的小段确认循环;其他内容是两个反例、NATIVE.md 说明及版本统一到 0.12.7。没有新增字段、服务、CLI、独立观察器或数据 owner。smoke 虽包含较多身份/恢复分支,但共享同一原生 handoff fixture,新增的两例专门保护确认与真实退出的差别,没有把整个文件合并成另一套算法。

关键代码讲解

  • pause_chat_agents(packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_host.py:479):Wait between acknowledged stop and actual unload; retain bounded failure。
  • _chat_loaded(packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_host.py:530):Read the real launchd job state using the existing bounded transport。
  • switch(packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_host.py:599):Keep account transaction after full pause and native idle; restore through finally。

规范依据:packages/loopx-codex-provider-routing/NATIVE.md,不可变基线 de349dd。以下是既有合同条款的评审映射:

  • NATIVE-IDLE:implemented;完整 native 回归和本次异步退出/永不退出反例覆盖。
  • NATIVE-CONSENT:implemented;完整 native 回归和本次异步退出/永不退出反例覆盖。
  • NATIVE-OWNERSHIP:implemented;完整 native 回归和本次异步退出/永不退出反例覆盖。
  • NATIVE-RECOVERY:implemented;完整 native 回归和本次异步退出/永不退出反例覆盖。
  • NATIVE-TRANSACTION:implemented;完整 native 回归和本次异步退出/永不退出反例覆盖。

对主干的风险

最强反例是等待被误当许可:永不退出的 job 也继续换号。新增 stuck-unload 用例确认超时后凭据事务为零、原恢复记录仍在;延迟两个状态读取的完整 switch 用例则从 0.12.6 的失败转为一次切换及正确恢复。两者都走实际暂停/事务编排,没有让 mock 直接提供已成功换号结论。隔离 macOS launchd 也再次完成两服务停启和新 PID 读回,但账号 owner 是模拟的。五秒是卸载轮询窗口,底层 launchctl 仍有原有独立 IPC 超时;这不是整个换号旅程的五秒承诺。

五项 Python package smoke、其中 22 项 operator 测试、十项 TypeScript 策略测试、Ruff、编译及精确提交 premerge 通过。premerge 没有选中包 smoke,因此另行执行完整包检查。禁用重启、其他 home、未知 CLI、PID 复用、手工选择、强退 opt-in 和恢复失败的原分支均保留通过。按当前 Goal 配置未查询或等待远端 CI。

语义与 CI 对齐

沿用既有暂停、恢复及原生账号事务语义,只修正操作确认与真实状态之间的时序。没有迁移、默认开启、权限扩大或第二套状态。相关 #7356 是本次基线;#7355 的服务名问题已被该基线覆盖;邻近 #7357 修改只读对话指引,未触及此 owner。

我的整体评价

未发现阻塞问题,结论 APPROVE,属于同一原生切换目标的 justified_increment。正常退出不再无谓消耗失败预算,有利于持续运行和使用体验;没有新增必需的人机确认。检查 packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_host.py 与 NATIVE.md,本次没有页面渲染改动,visual_review 不适用,未验证展示范围为 none。这个等待属于原有 native host 的服务 IO 确认步骤;复用已有恢复意图和账号事务,不增加调度器、状态库、许可或策略开关。当前 PR 一次交付卸载等待、超时拒绝、回归和 0.12.7 文档清单;后续按原安装路径采用同一构建。剩余的生产自然换号、安装采用和不可见虚拟机状态不由测试结果代替。完整评审 head 为 dd90108。

English verdict: APPROVE — dd90108. Bounded actual-unload confirmation fixes a reproduced asynchronous-stop failure without expanding authority. Delayed and never-unloaded counterexamples, full package/policy checks and isolated real launchd restart passed; production credential cutover remains separate.

@loopx-agent
loopx-agent merged commit 56cedb4 into main Oct 26, 2026
21 of 26 checks passed
@loopx-agent
loopx-agent deleted the codex/native-auth-unload-wait-20261026 branch October 26, 2026 04:37
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