Skip to content

fix(codex): preserve heartbeat cadence across aliased homes - #7230

Open
BigDataDZ wants to merge 1 commit into
mainfrom
codex/codex-home-alias-20261024
Open

BigDataDZ wants to merge 1 commit into
mainfrom
codex/codex-home-alias-20261024

Conversation

@BigDataDZ

Copy link
Copy Markdown
Contributor

Goal And Delivered Outcome

A CODEX_HOME directory alias pointing at the default home makes discovery read one installed heartbeat twice. Cadence projection then mistakes those two reads for conflicting automations and reports an unknown interval.

Deduplicate discovered homes by resolved directory identity at the existing discovery owner, preserving the first selected path and search order. Three normal selection forms now retain the single heartbeat's five-minute cadence. Two genuinely distinct automations on one lane remain ambiguous.

Author Declaration

  • Written by: model_agent (OpenAI Codex), under the author's direction.
  • Implemented against: existing home discovery and installed automation cadence contracts in loopx/codex_app_thread_activity.py at 58e646f7115b167df60442f8766a37ba50fa1a71; reproduced alias defect is the outcome basis. Intended base: main.
  • Criteria: one physical home is discovered once; first-path/order semantics survive; configured, sibling and explicit-list aliases work; real duplicate automation ambiguity is preserved. All implemented at the existing filesystem provider boundary.

Validation

Tested revision: 347133c28ab138f3f6658e9507fbad60f778b9d3. Run state: finished. Inputs: synthetic. Native Windows, CPython 3.12.10, real directory junctions and installed automation fixtures.

  • tests/test_host_thread_activity.py: 72 passed, no skips. All three new public codex_delivery_expectations() regressions failed before the repair and pass afterward. They also assert discovery order and the negative case of two distinct automations.
  • Independent author-side review reran the three junction cases: 3 passed.
  • Broader host/cursor suite: 109 passed, 1 failed. The failure is test_a_new_end_or_rotation_during_read_is_not_reported_as_open[True]: a Windows rotation read returns TURN_OPEN instead of IDLE. Running that exact case with the unchanged provider source from the base SHA reproduces the same failure. It bypasses home discovery and belongs to the existing fix(codex): keep Windows rollout reads from blocking native rotation #7222 Windows shared-reader repair; this PR does not claim the broader suite is green.
  • Ruff, whitespace, semantic advisory, bilingual RFC diff checks and public-boundary scans pass. No shared state vocabulary or new cadence decision owner is introduced.

Scope And Continuation

Complete within alias discovery. This is provider filesystem identity handling in the existing Python adapter; explicit homes= injection, SQLite handling and cadence rules are unchanged. The related refactor pass keeps deduplication at discovery rather than copying it into each consumer.

Frontend/Lark/CLI: the existing read-only cadence projection receives the corrected value; no new operation, configuration or visual surface. POSIX execution, packaged frontend and installed-host validation were not run. Existing #7227 separately wires the host test module into native Windows CI; these source repairs remain independently reviewable. Hosted CI and maintainer review remain pending; no approval or merge is claimed.

Signed-off-by: BigDataDZ <76271875+BigDataDZ@users.noreply.github.com>

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator

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=max

Exact head: 347133c28ab138f3f6658e9507fbad60f778b9d3

动机

使用本机心跳且已保存普通 Codex 聊天配置的用户。 同一 Codex 目录通过别名被扫描两次,单个心跳因此被误判为冲突,周期显示未知。 同一个目录有默认名和别名时,心跳应只读一次,但原先可选、已保存的 profile 仍须能打开同一原生配置。 心跳的五分钟周期确已恢复;但三种别名入口均使一个原来有效的 profile 消失,新建会话在原生适配器启动前报 profile unavailable。 本轮不安装修复、不迁移用户配置、不启动模型,也不把正常心跳投影当作聊天或 Windows 全面验收。

改动思路

物理目录身份去重属于文件读取的正确性规则;已保存 profile 的别名则是独立的用户选择,不能因另一读者去重而消失。当前全局 codex_homes 同时承担两种含义,现有 profile owner 只按保留路径的名字查找,放置边界需要修正。 保留单物理目录一次心跳观察,同时保留所有已支持 profile 名称的发现和解析;无需迁移、删除用户默认值或新建配置协议。

No change leaves cadence ambiguous. Keep physical identity dedup in scan consumers, or make profile discovery/resolution retain alias identities independently. Do not require users to clear/reenter valid settings to accommodate an internal scan. 现有意图已足够,不增加用户确认轮次、配置复制或手动账本。物理来源的读取与用户选择分别归原 owner;本次没有把发现、安装或可用性当成激活、执行、验收或升级授权。这个分支用文字即可说明,未引入未核实图示。

具体改动

规格来源 docs/integrations/session-runtime-control-plane-adapter.md,不可变版本 58e646f7115b167df60442f8766a37ba50fa1a71。ordinary-native-profile-selection 要求已有 native profile 通过原机器配置事务保存并可选择,本头 not_met;existing-session-identity-retained 的既有运行中/精确恢复隔离路径未被修改,相关原 home 用例通过,但不外推全平台或真实模型。

关键代码讲解

  • codex_homes:候选顺序保留,但第82行按 resolve 后的物理身份丢弃其他名字。它是共享发现函数,调用者还包括 profile 设置、普通会话与本机绑定发现;“同一物理目录”不能替代所有这些名字的语义。
  • codex_delivery_expectations:现有 TOML 读者按 Goal、Agent、thread 和 App surface 匹配,重复自动化仍给未知。三种别名入口的单心跳确从未知变为5分钟,第二真实自动化仍未知,暂停后恢复5分钟。
  • codex_profile_home:未改动的 profile owner 按 home.name 匹配已保存名字。默认目录被前面的别名吃掉时,codex 零匹配;默认名先出现时则 codex-alias 零匹配。共享设置表单同样少一个选项,open_session 在真正启动前抛出错误。

完整审查两路径 +57/-1,包括全部生产分支、未修改共享消费者和新增真实后端测试;没有只看最后补丁或继承作者结论。

对主干的风险

[P1] 保留已保存 native profile 的别名解析。 三组实际目录软链接、TOML、SQLite 和机器配置 preview/apply/readback 场景均复现:configured 和 explicit 选 codex、sibling 选 codex-alias,基线可解析并新建原目录会话,本头均报 The selected Codex profile is unavailable or ambiguous,原生启动调用为零。配置和源目录没有丢失,错误来自去重后名称消失。独立正常行为回归是 base 3 passed、head 3 failed;新建会话的适配器在启动处用 stub 截断,失败发生在 stub 之前,不声称启动模型或 live App 已验证。

最小修复是在需要物理去重的观察边界去重,或让 profile 发现/解析独立保留所有受支持别名。不要以要求用户清空或重填原本有效的设置来掩盖回归。新增配置名和跨层迁移都不是必需;保留原单次周期、真实重复未知及已有会话隔离回归。

原四模块本头 137 passed, 5 failed;同输入接回不可变基线 owner 为 134 passed, 8 failed。其中三项新 cadence 回归由红变绿,另五项均在未改动 chat_runtime.py:873 因原 SimpleNamespace fixture 缺 read_only_review 失败,测试身份、位置及异常一致,因果路径与本次 alias 过滤不同,保留为既有检查缺口。它们不是本次 P1 的依据,也没有被声明修好。本地 quick premerge 6直接+2选中检查通过,不能覆盖这些完整调用者反例。作者报告的 Windows 旋转缺口属于另一个 #7222 transport,#7227 URI 修复也不保留 profile 名字;未继承它们的验收。

语义与 CI 对齐

没有新枚举或通用义务,但共享发现结果的名字本身是已有 profile 契约。当前重用 physical Path 身份违反该消费者要求,需要在原 owner 修复并重跑实际保存配置/新会话路径。wait_for_ci=false,本轮没有查询或等待远程 CI。

我的整体评价

存在上述 P1 阻塞,REQUEST_CHANGES。长程影响和用户体验均为 regression:周期读取可用,但已有配置阻止下一次普通会话。架构判断 simplify_now:修复观察去重和逻辑别名选择的边界,无需新框架或用户迁移。 物理目录身份去重属于文件读取的正确性规则;已保存 profile 的别名则是独立的用户选择,不能因另一读者去重而消失。当前全局 codex_homes 同时承担两种含义,现有 profile owner 只按保留路径的名字查找,放置边界需要修正。 保留单物理目录一次心跳观察,同时保留所有已支持 profile 名称的发现和解析;无需迁移、删除用户默认值或新建配置协议。

检查了共享设置 editor 的实际选项和聊天调用链;没有组件、布局、字体或视觉素材改动,视觉构图检查不适用。选项丢失是已复现的功能回归,另列阻塞,不以无布局改动免除。 未独立执行原生Windows junction/旋转、实际已安装App或真实模型;新建会话验证在原生适配器启动处用stub截断,真实配置事务、路径解析与失败前调用完整执行。 已通过、失败及未测试范围分别保留;全树健康、长期效果、实际主机升级与其他 PR 的合入不由本次结论认证。合并仍归维护者,本轮没有合并或安装。

English verdict: REQUEST_CHANGES. Physical-home deduplication fixes cadence but removes valid saved profile aliases from the shared discovery result; all three normal alias forms reproduce failed ordinary conversation opening. Preserve alias-aware profile selection and keep physical deduplication at the appropriate reader boundary.

identities: set[Path] = set()
for candidate in candidates:
if candidate.is_dir() and candidate not in homes:
if candidate.is_dir() and (identity := candidate.resolve()) not in identities:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P1] Preserve selectable native profile aliases when deduplicating physical homes

codex_homes() is also used by codex_profile_options() and codex_profile_home(), which match the surviving path by name. With CODEX_HOME pointing to .codex-alias -> .codex and a saved codex_chat.codex_profile="codex", this filter removes .codex; the settings option disappears and ChatRuntimeController.open_session() raises The selected Codex profile is unavailable or ambiguous before native startup. The inverse occurs for a saved codex-alias with normal sibling discovery. I reproduced configured/sibling/explicit selection through real directory links, persisted machine-config preview/apply/readback, the shared editor and conversation controller: base resolves/opens, this head fails; a separate profile regression is base 3 passed/head 3 failed. Native adapter startup is stubbed after the failing boundary. Keep physical deduplication scoped to store/automation readers, or retain alias-aware profile discovery/resolution, and add these saved-profile cases alongside the cadence and genuine-duplicate controls.

@mergify

mergify Bot commented Oct 24, 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, @BigDataDZ.

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 24, 2026

This branch has not been deployed

No deployments
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.

2 participants