Skip to content

fix(macos): preserve independent execution and Chat Codex homes - #5626

Merged
loopx-agent merged 2 commits into
mainfrom
codex/launchagent-independent-codex-homes-20261005
Oct 5, 2026
Merged

loopx-agent merged 2 commits into
mainfrom
codex/launchagent-independent-codex-homes-20261005

Conversation

@loopx-agent

@loopx-agent loopx-agent commented Oct 4, 2026 •

Copy link
Copy Markdown
Collaborator

A macOS Chat service may resume workers from an execution CODEX_HOME different from its Chat app-server home. Previously selecting LOOPX_CHAT_CODEX_HOME overwrote both values, so existing worker profiles no longer matched. The installer now persists them independently, preserves omitted values on upgrade/restart, and keeps session-profile refusal in force.

Latest main is incorporated with a signed normal merge. Its selected-distribution interpreter, custom registry, workspace arguments, and runtime-identity checks remain; no force-push or parallel launcher is introduced.

Specification And Acceptance

Basis: the existing PR's independent service-home repair and managed home ownership / upgrade preservation, read at the unchanged main revision before repair.

Criterion Disposition Evidence
Preserve installed home bindings, including old shell-export plists implemented Real installer/zsh child: omitted restart, changed Chat only, legacy decoder, paths with spaces/metacharacters
Keep Chat capture and worker session profile fencing distinct implemented Real Chat consumer and worker digest: wrong execution home refused, restoring original home accepted
Changing a setting neither migrates sessions nor copies auth implemented Existing runtime/store/profile owners remain unchanged; bilingual docs disclose scope
Keep current registry/workspace/interpreter/runtime-identity protections implemented Extended durable wrapper smoke transports both homes with custom registry and two workspace arguments; inherited rejection checks retained
Real launchd/Bot interrupted recovery and two-cycle R2/S4 execution deferred Existing program acceptance remains open; no live account, worker or model exercised

Scope And Continuation

Three files: the existing host installer, its durable smoke, and the integration contract. One resolver serves both existing settings. Old plist decoding remains because supported upgrades still call it; removing Python adapters is not a reason to lose that recovery path. This repair is complete within this scope; broader host qualification remains with the existing R2/S4 owner. No frontend operation or authority provider is added; this does not qualify canonical SQLite as the release default.

Validation

Tested head: e82c394f5d69255226aa4dc6c1feee4078e95e1f; base: 03794d7b0edb323a52c8aec05c9be24c27f4f5cc. Finished; synthetic/public fixtures.

  • uv run --extra test python examples/macos-dashboard-launchagent-status-smoke.py passed, including actual generated zsh wrapper, literal workspace arguments, invalid-home refusal and inherited retention/registry/identity checks.
  • 12 fixed scenarios per immutable base/head, repeated with a noneditable wheel: four distinct-home failures reproduce on base and pass on head; default/Chat-only/same-home/legacy child output and status bytes match. Wrong-home refusal and restoration remain independent oracles. launchctl, HTTP and model hosts are fixtures.
  • uv run --extra test python -m pytest tests/test_chat_codex_home.py tests/test_chat_agent.py tests/test_loopx_turn_executor.py tests/test_local_delegation.py -q: 201 passed. The installed wheel's Chat/home suite: 57 passed, imported from site-packages outside the checkout.
  • Official current-source Chat build, wheel build, control-plane typecheck, scoped Ruff, shell syntax, semantic advisory and diff hygiene passed. Generated assets, lockfile and private evidence are excluded.
  • Native exact-scope quality and risk-based premerge results are recorded in the exact-head review. CI is not queried under the resolved review policy. Live launchd/model/Bot and long-running qualification are not run.

UI impact: none; existing installer settings are repaired, with no new product screen. Runtime merge remains maintainer-owned.

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.1-sol; OpenAI; runtime_reported; reasoning_effort=xhigh

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Exact head: 5626@7c0393ec0d2f3e246cc0282df6f5bade705cd6b6. Base: 2f68e3b835c3bfc0e3718373cdb6c72eea99291e.

动机

在 macOS 上让聊天服务与长期 worker 使用不同既有 Codex 目录的操作者。 基线安装或重启会把聊天目录同时写成执行目录,使 worker 的原会话 profile 检查失败;当前版本分别保留两项设置,升级未指定执行目录时无需重输原目录。 真实安装脚本、生成的 zsh 包装器和既有目录消费者对照证明分离配置可传递、重启保留且恢复原目录后 profile 检查通过。 本次不迁移会话、不复制凭据、不新增 Agent 权限,也不声明实际 launchd 登录恢复、真实模型多轮续跑或长期吞吐已验收。 实际登录服务恢复、Bot 发起 worker 续跑及两轮独立验收仍由已有运行时资格路径完成。

改动思路

聊天服务使用的 Codex 目录与执行 worker 使用的目录,都是操作者已经选择的宿主配置。旧安装器把聊天选择写到两个变量,破坏 worker 的既有 profile;本次在原解码器上增加变量和首次安装 fallback 参数,分别读取、保留和传递两项选择。沿用原 XML/shell 转义和旧 plist 读取,继续由既有会话 owner 判断能否恢复,没有新增权限或决定源。只查看配置字符串不够,因此我执行了真实安装脚本及其生成的 zsh 子进程,再检查实际 Chat 目录消费者和原 worker 的 profile digest。launchctl、curl 与上游模型边界为 fixture,未声称真实登录服务通过。

具体改动

完整三文件 +62/-10:安装器 +14/-9、已有 smoke +34/-1、双语集成文档 +14。默认安装无需增加参数;同时指定两项现有变量可分离目录,重启未指定执行目录时保留已安装值。显式改变执行目录只改变服务配置,原会话的 profile 围栏仍适用。

关键代码讲解

  • resolve_codex_home(scripts/macos-dashboard-launchagent.sh:213):明确变量优先,其次读取已安装字段或旧 shell export,最后采用首次安装 fallback;只用 shlex 解码旧命令,不执行旧命令,拒绝相对目录。
  • write_plists(同文件:250,调用:279–281):先解析两个目录再写 plist;分别生成 CODEX_HOME 与 LOOPX_CHAT_CODEX_HOME 的环境和值,原状态服务参数和写 API opt-in 分支保持不变。
  • smoke main(examples/macos-dashboard-launchagent-status-smoke.py):加入不同目录、含空格路径、无参数重启、真实 wrapper child 和无覆盖拒绝;沿用临时 HOME/fake launchctl,补充已有回归而非新建演示框架。

规范按 同一份已接受集成契约 docs/integrations/session-runtime-control-plane-adapter.md @ 2f68e3b835c3bfc0e3718373cdb6c72eea99291e 判断;不以本 PR 新增文档自行证明规范:

  • Managed Codex home ownership (implemented):implemented,独立目录传输、原会话 profile 保留及错目录拒绝已核验。
  • including older shell-export plists:implemented,旧 shell-only 输入在两版保持相同 child 行为,损坏 plist 拒绝并保留字节。
  • changing this variable is not a session-migration command:implemented,主动换执行目录不能恢复原绑定;恢复原目录后 profile 检查通过,没有复制或迁移会话。
  • interrupted task recovery rate:deferred,实际登录/Bot 发起 worker、两轮独立验收及重复计算指标仍属已有 R2/S4 运行时资格,不把本次桥接烟测算成全部完成。

对主干的风险

同一输入经冻结基线和当前 head 各执行12个场景,共24个观测。四个不同目录场景——初次选择、无参数重启、仅改 Chat、仅改执行端——基线均导致原预期 worker profile 拒绝,当前均传递正确目录。普通默认、Chat-only 首装、相同目录及旧 shell-only 四组的完整 child 结果相同;有效样本的 status plist 字节相同。额外反向核验显示:主动选择其他执行目录仍拒绝原 worker 绑定,恢复原目录接受,未把 transport 修复变成身份绕过。相对执行目录和损坏 plist 在 head 均在替换前拒绝。

110项相关 pytest 通过,LaunchAgent smoke、当前 Chat bundle 构建/校验、Ruff、bash -n、diff hygiene、开发 advisory 后的完整 semantic-vocabulary smoke 通过。按完整三文件运行风险 premerge:4个直接检查及18项选中检查通过,1项既有 maintainability advisory 保留;基线完整源快照和当前 head 的完整归一化报告相等,均为未改的 goal_topic_runtime.py any_count56超过49。该债务不能称为已修,也不扩大本 PR 来调整 ceiling。首次测试有5项因 worktree 中上一版构建包的 source manifest 过期而失败;生成当前 head 包后原110项通过,未放宽断言/预算。构建另有现存 npm 依赖告警;本 PR 没改 lockfile/依赖,不宣称全库安全扫描完成。

本修改没有新增 optional capability;现有 write API 开关仍按原 smoke 的开/关路径执行,状态 plist 对照保持相同,不影响 Goal quota、claim/lease 或注册 Agent。Frontend/Lark 配置 owner 未改变,原 CLI 安装入口仍可操作,不需要新 UI 开关。相关 #5543 也修改同一安装器的解释器、registry 和 workspace transport;集成时要保留两组修复,当前没有宣称两 PR 已组合验证。实际 launchd、真实模型或 Bot 新 dispatch、安装升级及长期 throughput 未执行;无 CI 查询/轮询/等待,也未更改活跃服务或账户。

我的整体评价

APPROVE,无当前阻塞 finding。delivery 为 justified_increment:long_horizon 与 user_experience 在本次受影响路径均 improved,证据是正确目录跨重启保留和原身份围栏拒绝/恢复,而非 PR 数或测试数。它减少了已复现的“升级后 worker 换错目录、需要人恢复”的中断成本;速度或长期产出提升仍是预期,未给出未经测量的百分比。62行新增对应完整有界修复,参数化原解码器已做邻域简化;旧持久化 plist 是真实消费者,保留单一解码路径合理,另加通用框架或无关 TS 重写没有当前价值。语义复用现有变量和身份 owner,局部路径解析不创建共享 vocabulary。控制面/运行时变更由维护者合并,APPROVE 和原生 ready 都不授予自合并权。

English verdict: APPROVE - 5626@7c0393ec0d2f3e246cc0282df6f5bade705cd6b6; independent execution/Chat homes survive installation and restart, original profile rejection/recovery remains intact. 12 paired installer cases,110 related tests, LaunchAgent smoke and bounded risk checks pass; inherited maintainability advisory retained. Actual launchd/model continuity and sustained efficiency remain unqualified; no CI consulted; maintainer merge required.

@mergify

mergify Bot commented Oct 5, 2026

Copy link
Copy Markdown

This pull request has merge conflicts with main and cannot be merged
until they are resolved. Please rebase or merge the base branch, @loopx-agent.

Choose the remote for the base repository, not an out-of-date fork.
For a fork clone, first inspect git remote -v; upstream must point
to https://github.com/loopx-project/loopx.git. If it is absent, add it
with git remote add upstream https://github.com/loopx-project/loopx.git.
Then run:

git fetch upstream
git rebase upstream/main
# Resolve each conflict, git add the resolved files, then git rebase --continue.
git push --force-with-lease origin HEAD

For a same-repository clone whose origin points to
https://github.com/loopx-project/loopx.git, use origin instead of
upstream for fetch/rebase. If you prefer merging the base, use
git merge <base-remote>/main and push normally.

Keep the DCO Signed-off-by trailer on every commit when you rebase.
https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase Mergify: the pull request has merge conflicts with its base branch label Oct 5, 2026
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.1-sol; provider=OpenAI; declaration_source=runtime_reported; reasoning_effort=xhigh

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

动机

在 macOS 登录服务中沿用已有 worker 会话、同时给聊天端选择另一配置目录的用户。 升级或只修改聊天目录时,旧安装器会把 worker 的执行目录一起改掉,原会话配置检查因此拒绝恢复;修复后两端分别保留各自目录,重启不需要重新输入已知配置。 真实安装器、生成的 zsh 子进程和独立安装包已验证:不同目录可保存、重启和恢复,错误执行目录仍被拒绝,恢复原目录后检查通过。

此 PR 修复主干冲突与服务配置传递;真实 launchd、Bot/付费模型和两轮完整工作恢复仍未测,R2/S4 与 SQLite 默认/升级及 Python 退役的完整验收继续保持开放。

改动思路

复用现有 macOS 安装器、plist 解码和 shell/XML quoting,以及 Chat 目录捕获与 worker session profile(会话配置身份)检查。一个既有 resolver 分别读取聊天与执行设置,再由同一个 writer 生成持久字段与子进程 export;用户的独立目录选择无法从另一端推导,因此不是多写一份需要手工同步的状态。遗漏执行选择时读当前服务记录,新安装才采用聊天目录。旧 shell-only plist 仍有真实升级调用方,继续只解码而不执行其内容。

普通 install/restart 仍走原入口。先解析目录、registry、工作区和当前 runtime identity,再写服务描述;子进程接收原有自定义 registry 与工作区参数。实际 profile 检查的 owner 未移动,也没有新调度器、Python eligibility owner、credential copy 或会话迁移。选择错误 execution home 时保留拒绝,按原目录修正才能恢复;这样验证的是有用恢复,非仅新增 blocker。

具体改动

当前精确 head e82c394f5d69255226aa4dc6c1feee4078e95e1f,固定 main 基线 03794d7b0edb323a52c8aec05c9be24c27f4f5cc。原 head 7c0393ec0d2f3e246cc0282df6f5bade705cd6b6 已有评审,但不继承其批准;本轮正常 merge main、解决两个安装器/测试冲突,保留当前 interpreter、registry、workspace 与 runtime identity 边界。完整当前 PR 三文件69+/11-,远端 whole diff 与已验证本地 diff 的路径、hunk 和内容相同,只有 index hash 显示长度不同;GitHub patch 格式只展示原普通提交,不能代表 merge 冲突解决后的最终内容。

依据为 docs/integrations/session-runtime-control-plane-adapter.md,固定 revision 03794d7b0edb323a52c8aec05c9be24c27f4f5cc:接受前的相同规范。Managed Codex home ownership implemented:Chat 捕获与 session mismatch 仍在原 owner 强制;including older shell-export plists implemented:独立绑定、遗漏重启和旧 shell upgrade 由真实安装器验证;changing this variable is not a session-migration command implemented:错误 execution home 拒绝旧 worker,原目录恢复接受,未更改 session/store/auth;interrupted task recovery rate deferred:实际服务与两轮 R2/S4 仍由既有验收承担,不用合成 host 或测试数关闭它。

关键代码讲解

  • resolve_codex_home(scripts/macos-dashboard-launchagent.sh:279)从显式变量、已安装 exact field 或旧 export 取该目录;旧 descriptor 用 shlex 解码,拒绝相对路径,返回展开后的绝对路径。复用一个解析 owner,没有两个平行 resolver。
  • write_plists(scripts/macos-dashboard-launchagent.sh:316)分别解析 LOOPX_CHAT_CODEX_HOME 与 CODEX_HOME,生成独立 export/EnvironmentVariables;保留 main 的 console-script interpreter、custom registry、workspace 参数及写前 runtime identity 校验。服务配置选择没有授予执行其它会话的权限。
  • 既有 durable smoke 更新了错误的“Chat 总是覆盖 execution”预期,实际执行生成的 zsh wrapper,断言两个 home、自定义 registry、带空格/命令替换字符的工作区参数完整到达子进程,且未执行命令替换。相对 execution home 和 malformed plist 保持写前拒绝;docs 以双语披露默认改变和非迁移边界。

对主干的风险

没有当前阻塞发现。最强反例是“plist 字符串正确,真正的子进程却丢失 registry/workspace 或仍覆盖原 worker home”。固定12场景逐项经过真实安装器、zsh、Chat capture 和 worker digest/fence;四个独立 home 场景在 main 都拒绝原配置,在 head 都接受。默认、仅 Chat、新建相同 home、旧 shell 的完整 child 观察和 status plist 字节保持一致;新增 Chat plist 的 execution 字段是明确披露的持久变化,没有把整个 plist 假称 byte parity。改到错误 execution home 仍拒绝原绑定,恢复原目录后接受;invalid input 不覆盖原服务。

同组验证在 noneditable wheel 重复,子进程从 site-packages 导入真实消费者,不靠源码目录遮蔽。201项源码 Chat/home/Turn/delegation 回归、57项 wheel Chat/home 测试、官方当前 Chat/wheel 构建、tsc、scoped Ruff、bash syntax 和 diff 检查通过。原生 CQ cqr_e131d9c13d36d568487a 对此 exact scope pass;canary premerge 4direct/19selected、零 blocking failures/manual holds,使用选定 worktree Python。没有查远端 CI。

一项 ratchet 仍红,保留为原生 inherited advisory:不可变 base 与 head 的完整 JSON 除根目录外完全相同,包含 goal_topic_runtime.py Any 56>49、quota handler statements 96>90、goal_boundary decision points 63>60,未修改这些文件、ceiling 或断言。最初未带 tracked census 的 archive 漏掉债务,未当作 baseline 证明;随后用同一 Git tree 的独立私有 index,才逐项复现失败。早期 CQ 结果因字段预算/引用范围被拒绝,修正序列化后才获当前有效 receipt,拒绝结果没有当成功记账。

launchctl、HTTP/upstream model 是 fixture;没有改动真实 LaunchAgents、账户、Bot 或现有 worker。并发 installer 与真实长期 R2/S4 仍未测,未新增并发保证。已有 store、session migration/rollback 和旧 plist 读取能力继续保留;恢复依赖正确原目录,不靠删除 profile fence 或复制凭据。三个公开路径及 review 文本不含私有状态、日志或本机路径。回滚可 revert 此代码,不重写历史会话。

语义与 CI 对齐

这是披露的既有 installer 默认修复,无新增 feature-off capability;配置字段的可用性不等于授权。现有 provider environment vocabulary 与 typed session identity owner 被复用,没有新通用 actor lifecycle。absolute/plist/profile 拒绝是 machine-enforced,文档是纠正与范围说明,未把硬准入说成建议。通用 Goal/Turn obligation 没有混入 Codex 产品词。

changed advisory 在 full semantic-vocabulary checker 之前执行,两者均完成;空 advisory 不覆盖动态 construction。formal scanner 自己保留未证明的 producer 与跨 runtime 边界,不被当作全局语义等价证明。关闭/普通路径用完整 consumer/status parity 和负例补充,而非 green CI 或符号计数。

我的整体评价

APPROVE,justified_increment:long_horizon improved,遗漏重启和目录更改不再使既有会话走错配置;user_experience improved,保存已知独立选择、错误输入可纠正,没有新增操作页面或额外确认。完整真实服务、SQLite 默认升级、Python 退役及 Goal 均未据此收尾。

Future-facing pass 已应用:复用单一 resolver,保留实际旧 descriptor 解码与 session fence,扩展现有真实 wrapper 测试而非平行测试框架。代码规模与这个可复现恢复问题相称。最新 host 记录提供 Reviewer 来源,active_turn_verified=true 只描述该观察,不证明 backend weights 或赋予权限。运行时变更仍由维护者合并;作者 COMMENTED 结论不是 GitHub 独立批准,也不是 merge authority。

English verdict: APPROVE - e82c394; real installer/zsh and source/noneditable-wheel consumers preserve independent homes and main registry/workspace transport, with wrong-profile refusal/restoration intact. 201 source and57 wheel cases, paired12-case observations and native4/19 gates cover this bounded repair; independently reproduced baseline ratchet debt and live R2/S4 gaps remain explicit.

@loopx-agent
loopx-agent merged commit 59eb5d5 into main Oct 5, 2026
18 of 24 checks passed
@loopx-agent
loopx-agent deleted the codex/launchagent-independent-codex-homes-20261005 branch October 5, 2026 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-rebase Mergify: the pull request has merge conflicts with its base branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant