Skip to content

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

Open
BigDataDZ wants to merge 3 commits into
mainfrom
codex/codex-home-alias-20261024
Open

BigDataDZ wants to merge 3 commits into
mainfrom
codex/codex-home-alias-20261024

Conversation

@BigDataDZ

@BigDataDZ BigDataDZ commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Problem and result

An aliased Codex home made the installed-heartbeat reader count one automation twice and omit its cadence. The first repair deduplicated global discovery by physical identity, which hid logical profile names and broke ordinary conversation creation for existing saved profiles.

Keep global codex_homes() discovery's baseline logical names and ordering. Deduplicate physical stores only in the existing installed-automation reader, including explicit homes= inputs. This preserves profile selection while scanning each physical heartbeat store once. Two genuine automations remain ambiguous; pausing the duplicate restores the five-minute cadence.

Author Declaration

Written by: model_agent (OpenAI Codex), under the author's direction. Basis: demonstrated alias cadence defect and the published P1 saved-profile counterexample. Intended base: main; implementation baseline 58e646f7115b167df60442f8766a37ba50fa1a71.

Owner: provider filesystem reads in loopx/codex_app_thread_activity.py. Existing typed cadence and profile rules are unchanged. No new capability, configuration migration, protocol vocabulary or parallel decision owner. The bounded future-facing correction moves physical deduplication to its actual consumer, preserving the shared discovery contract.

Validation

Tested integration revision: 1ede00501b0b4b34b7da1e4e10a5b14c93ec174d. Latest-main parent: 59464f9741fe177381743eadaaffebbb54e5472e. The only merge conflict was adjacent discovery docstring lines; both alias and relative-home explanations are retained. Run state: finished. Inputs: synthetic. Native Windows / CPython 3.12.10; real disposable directory junctions.

  • Three configuration/editor/conversation regressions: original parent discovery 3 passed, original PR discovery 3 failed, repaired discovery 3 passed. Real preview/apply/readback, editor options, ordinary open_session and persisted session identity are exercised; only final native adapter launch is stubbed. Native config bytes and machine configuration remain unchanged after session creation.
  • Previous pre-integration owner/consumer suites: 129 passed, 25 skipped. Skips are Unix-peer cases on Windows. Independent author-side review reran both changed suites: 88 passed, no skips; no actionable blocker. A fixture's missing read_only_review=False field is corrected without changing production guards.
  • Cadence regressions cover configured, sibling and explicit aliases, first-path order, single manifest read, explicit reader inputs, real duplicate ambiguity and recovery after pausing the duplicate.
  • Fresh integrated four-module run: 167 passed, 32 skipped, 1 failed. The failure is the Windows rotation case test_a_new_end_or_rotation_during_read_is_not_reported_as_open[True]; replaying the exact case with the immutable latest-main activity module also fails identically. Its owning repair remains fix(codex): keep Windows rollout reads from blocking native rotation #7222; this PR does not bundle that transport change or claim a green expanded suite.
  • Fresh integrated profile/activity modules: 91 passed, no skips.
  • Ruff, whitespace, semantic advisory, bilingual RFC diff check and public-boundary inspection pass. The advisory detected no supported new vocabulary carriers; its static coverage is limited.
  • Companion machine-settings suites: 9 passed, 12 skipped, 6 failed. The same six periodic-report failures occur with immutable parent discovery; the selected interpreter lacks timezone data for Asia/Shanghai. No dependency installation was attempted.
  • Full-repository execution remains unqualified: collection stops at unavailable Windows fcntl in a benchmark test. No full-tree pass is claimed.

Scope and continuation

The P1 profile regression is addressed within the existing provider owner. Frontend: existing profile editor and new-conversation backend journey are covered; packaged browser interaction and live native adapter execution remain untested. Lark/CLI interfaces are unchanged. No live user store, Goal, model turn, OS upgrade or merge is involved.

POSIX, installed-host qualification, current-head CI and maintainer re-review remain outstanding. The branch now integrates the fetched latest main and retains only three PR-owned changed paths against it. The previous design's discovery-level deduplication is superseded by the consumer-local repair.

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.

Comment thread loopx/codex_app_thread_activity.py Outdated
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
Signed-off-by: BigDataDZ <76271875+BigDataDZ@users.noreply.github.com>
@BigDataDZ

Copy link
Copy Markdown
Contributor Author

Addressed the P1 profile-alias regression in 78b266ec8471f179be5b382bc0d0cec90067e89c.

The previous global physical-home deduplication removed logical profile names used by saved configuration and ordinary conversation startup. Global discovery now preserves baseline logical names/order; physical deduplication is owned solely by the installed-automation reader, including explicit homes= inputs. No configuration reset or migration is required.

Three real Windows junction journeys cover configuration preview/apply/readback, editor options and ordinary open_session: parent discovery 3 passed, original PR discovery 3 failed, repaired discovery 3 passed. Only final native adapter launch is stubbed. Existing native config bytes and saved configuration remain unchanged. Genuine duplicate automations still yield unknown cadence; pausing one restores the interval.

Four owner/consumer suites: 129 passed, 25 skipped. Independent author-side review found no blocker and ran the two changed suites: 88 passed; a fresh primary-agent rerun also passed all 88. Ruff, whitespace, advisory semantic scan and bilingual RFC checks pass. The existing fake adapter now explicitly supplies read_only_review=False; production guards are unchanged.

Known limits remain explicit: companion settings tests have six periodic-report timezone failures identical with parent discovery (missing timezone data); full-suite collection stops at Windows-unavailable fcntl. No full-tree, packaged UI or live Codex execution pass is claimed.

The PR body now reflects the corrected ownership and current evidence. Ready for maintainer re-review on this head; no approval or self-merge claimed.

@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

动机

使用已保存 Codex profile 的用户,以及查看自动化是否按周期交付的工作区使用者。

同一 Codex 目录通过别名出现时,旧扫描把一条自动化算成两条,周期显示未知;本次希望只读取一次物理目录,同时保留用户已保存的 profile 名称。

已验证符号链接场景恢复五分钟周期,三种 profile 入口均能创建并读回会话;大小写别名仍显示未知,扫描中失效的别名还会中断整个投影。

范围是本地只读发现与周期投影,不改变自动化调度、账号、凭据、配额、原生会话归属或模型执行。

剩余缺口:大小写别名与扫描期间的目录失效仍需作者在当前读取器内修复;这不是要求完成整个原生运行时路线图。

改动思路

本次复审覆盖完整 head 78b266ec8471f179be5b382bc0d0cec90067e89c,从原始基线 58e646f7115b167df60442f8766a37ba50fa1a71 比较,而非只复验上一个 P1。全局 codex_homes 恢复逻辑名称,保存的 profile 继续由原有机器配置、编辑器与会话控制器解释;物理目录去重移到 _installed_automation_intervals。周期只是读取原生 TOML 后的状态投影,不应成为调度或权限的第二个决策者。真正两条自动化仍应显示未知,暂停冲突项后才恢复原周期。

把物理目录去重留在周期读取器、保留全局逻辑名称,职责划分正确且成本很小;需要修正的是文件系统身份和单目录异常边界。本 PR 只交付现有原生目录读取器的兼容性修复,不引入调度策略、持久化状态或新配置。 这项同域简化已经落实,不需要增加配置、持久化日志或通用抽象。下面用文字说明调用链,未使用需要额外渲染验证的图。

具体改动

三文件净变更 +162/-2:生产代码增加读取器局部去重,测试增加三种普通 profile 入口、显式 homes、真实冲突与暂停恢复;测试原生 stub 补齐现有 read_only_review 字段。没有安装脚本、权限或模型策略变化。

依据先读的 docs/integrations/session-runtime-control-plane-adapter.md,固定规范版本 58e646f7115b167df60442f8766a37ba50fa1a71:ordinary-native-profile-selection 已实现;配置、同级目录和显式 homes 三条完整路径均能创建、持久化并读回正确的 profile/home。existing-session-identity-retained 在本次触及范围内保持:原生配置、机器配置与已归档 SQLite 线程没有被重写;现有会话归属路径不变。

关键代码讲解

  • codex_homes:61:保留已存在目录的不同名称和优先顺序。它同时服务配置编辑器、profile 解析和普通新会话,不能因为共享物理目录就删除一个名称。
  • _installed_automation_intervals:312:读取 ACTIVE heartbeat 清单,再按 Goal、agent 和绑定线程归组。新增 home.resolve() 集合能合并符号链接,但不是所有文件系统上的物理身份,且解析异常位于已有文件读取保护之外。
  • codex_delivery_expectations:368:非 App 请求直接返回;App 请求复用上述读取器。结果交给原有 attach_host_delivery_windows,其 provider 调用先于所有行赋值,因此目录解析异常会波及同一响应中的健康行。

对主干的风险

[P2] 用文件系统身份识别同一目录。 在实际大小写不敏感文件系统上设置 CODEX_HOME=.CODEX,默认路径为 .codex。两者 samefile() 为真且设备号、inode 相同,但 resolve() 后 Path 仍不相等。普通发现与显式 homes 均把唯一清单读两次,五分钟周期仍变成未知。原始基线也有此问题,这是原任务尚未修复的分支,并非声称新引入回归。最小修复是在当前读取器内使用真实目录身份;不要再次全局删除 profile 名称。

[P2] 把目录解析失败限制在单个来源。 使用真实发现得到有效目录列表后,在读取间隙将一个别名改成循环链接。同一合成输入下,基线的生产 attach_host_delivery_windows 返回健康行 fresh、周期5和无关行 unknown;当前 head 在第333行抛 RuntimeError,所有行的窗口都尚未赋值。事件由发现边界的调度包装器确定性触发,实际路径解析和清单读取没有伪造;未声称已执行 HTTP 服务器或发生过真实用户事故。最小修复是捕获单目录身份解析错误并继续健康来源,下一次正常读取能够恢复。

复审建议的回归用例为上述实际大小写别名和发现后失效场景,再运行 uv run --extra test python -m pytest tests/test_host_thread_activity.py tests/test_chat_codex_defaults.py -q。现有四个 owner 测试文件输出563 passed;其中 pytest 内部退出码未单独记录,所以决定性依据采用另有退出码的三臂完整源码对照。基线三种 profile 成功,前一个 PR head 三种失败,本 head 三种成功;真实第二自动化仍未知,暂停后恢复5,错误 Goal 不匹配,归档线程仍归档。

本地标准 canary premerge 六项直接检查、两项 catalog 检查和 Ruff 均退出0。没有查询、轮询或等待 GitHub CI,也没有把旧 Goal 质量失败、人工合并约束或作者 Windows 结果改写为本次通过。

语义与 CI 对齐

没有新增枚举、协议词汇或通用义务;沿用现有 home、scope 和 expectation。但新增路径解析影响了既有只读投影的来源隔离,语义结论为 violated,证据正是上述健康来源被异常中断;语义扫描通过不能替代此反例。最新主干的原生 URI/path 修复与队列内其他 Codex 改动不修复当前读取器的身份和异常边界。合并冲突状态是独立集成条件,不是本评审的问题依据。

我的整体评价

REQUEST_CHANGES。 上一个普通 profile 选择 P1 已独立验证修复;当前实现复用了正确 owner,规模适当,持久化兼容性应保留,不需要再做语言迁移或新框架。符号链接场景已取得可用增量,但尚不能把“每个物理目录只读一次”和来源失败隔离判为交付完成。长程状态观察与用户体验仍有回归风险,最低重审证据是两项新反例通过后重新验证原有 profile、冲突和暂停恢复路径。

视觉评审不适用:本次只改变 Python 发现/投影和测试,没有渲染布局变化。未验证范围:Windows/junction、已安装 App、实际模型启动及完整 HTTP 服务器;配置编辑器数据、真实文件系统、SQLite、控制器持久化和生产投影已按上述边界检查。此结论不授权合并或撤销旧评审讨论。

English verdict: REQUEST_CHANGES — 78b266e. The saved-profile regression is fixed in three source-pinned ordinary-entry comparisons. Two P2 issues remain: case-insensitive aliases still duplicate one physical store, and a discovered alias becoming unresolvable aborts the entire delivery-window projection. Local standard premerge and Ruff pass; no CI was consulted and no merge or review-dismissal authority is implied.

for home in codex_homes() if homes is None else homes:
# Discovery retains logical profile names; read each physical store only
# once here so an alias cannot masquerade as a second installed heartbeat.
identity = home.resolve()

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.

[P2] Deduplicate actual filesystem identity. On a case-insensitive filesystem, configured .CODEX and default .codex can be samefile() with the same device/inode while their resolved Path values differ. I reproduced both ordinary discovery and explicit homes counting one manifest twice and returning no cadence. This is a remaining original defect, not an introduced baseline regression. Keep logical profiles intact and deduplicate filesystem identity only in this reader; add a real case-alias regression.

for home in codex_homes() if homes is None else homes:
# Discovery retains logical profile names; read each physical store only
# once here so an alias cannot masquerade as a second installed heartbeat.
identity = home.resolve()

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.

[P2] Contain home-resolution failures per source. After real discovery returns a valid alias, retargeting it to a loop before this read raises RuntimeError here, outside the per-file handler. Through ordinary codex_delivery_expectations and production attach_host_delivery_windows, the baseline returns the healthy five-minute lane and an unknown unrelated lane; this head aborts before assigning any windows. Deterministically schedule the filesystem retarget after discovery and assert healthy sources survive; handle resolution failure locally without guessing an unavailable lane healthy.

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

Copy link
Copy Markdown
Contributor Author

Resolved the main-branch merge conflict at signed integration head 1ede00501b0b4b34b7da1e4e10a5b14c93ec174d, merging fetched main 59464f9741fe177381743eadaaffebbb54e5472e without rewriting prior commits. Only adjacent docstring explanations conflicted; both logical profile preservation and relative-home semantics are retained. The PR delta against that main remains the same three owned paths.

Fresh integrated validation:

  • Profile and activity suites: 91 passed, no skips, including the newly integrated relative-home cases and all alias/profile regressions.
  • Four-module expansion: 167 passed, 32 skipped, 1 failed. The sole failure is test_a_new_end_or_rotation_during_read_is_not_reported_as_open[True]. A process-local replay using the complete immutable latest-main activity module reproduces the identical failure; the existing Windows reader/ReplaceFileW repair remains fix(codex): keep Windows rollout reads from blocking native rotation #7222. No failure is hidden or weakened.
  • Ruff, staged whitespace, bilingual RFC check and semantic advisory pass. No supported new vocabulary carriers were found; the advisory has its documented static limits.

PR body is updated for this exact head. New hosted CI and maintainer re-review remain required; prior review evidence is not treated as approval of the integration head. No self-merge or live-host changes.

@mergify mergify Bot removed the needs-rebase Mergify: the pull request has merge conflicts with its base branch label Oct 25, 2026

@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

动机

使用已保存 Codex profile 的用户,以及查看自动化是否按周期交付的工作区使用者。

同一 Codex 目录通过别名出现时,旧扫描把一条自动化算成两条,周期显示未知;本次希望只读取一次物理目录,同时保留用户已保存的 profile 名称。

已验证符号链接场景恢复五分钟周期,三种 profile 入口均能创建并读回会话;大小写别名仍显示未知,扫描中失效的别名还会中断整个投影。

范围是本地只读发现与周期投影,不改变自动化调度、账号、凭据、配额、原生会话归属或模型执行。

剩余缺口:大小写别名与扫描期间的目录失效仍需作者在当前读取器内修复;这不是要求完成整个原生运行时路线图。

改动思路

本次集成复审覆盖完整 head 1ede00501b0b4b34b7da1e4e10a5b14c93ec174d,从本次实际 merge base 59464f9741fe177381743eadaaffebbb54e5472e 比较,而非只复验上一个 P1。全局 codex_homes 恢复逻辑名称,保存的 profile 继续由原有机器配置、编辑器与会话控制器解释;物理目录去重移到 _installed_automation_intervals。周期只是读取原生 TOML 后的状态投影,不应成为调度或权限的第二个决策者。真正两条自动化仍应显示未知,暂停冲突项后才恢复原周期。

把物理目录去重留在周期读取器、保留全局逻辑名称,职责划分正确且成本很小;需要修正的是文件系统身份和单目录异常边界。本 PR 只交付现有原生目录读取器的兼容性修复,不引入调度策略、持久化状态或新配置。 这项同域简化已经落实,不需要增加配置、持久化日志或通用抽象。下面用文字说明调用链,未使用需要额外渲染验证的图。

本次相对上一评审的变化仅是合入主干与相邻发现注释整合;新增的相对目录测试来自主干。完整 base→head 仍是下述三个 PR 路径。两项既有 P2 未在该集成头修复,下面均按当前完整源码重新复现,不继承旧判定。

具体改动

三文件净变更 +162/-2:生产代码增加读取器局部去重,测试增加三种普通 profile 入口、显式 homes、真实冲突与暂停恢复;测试原生 stub 补齐现有 read_only_review 字段。没有安装脚本、权限或模型策略变化。

依据先读的 docs/integrations/session-runtime-control-plane-adapter.md,固定规范版本 59464f9741fe177381743eadaaffebbb54e5472e:ordinary-native-profile-selection 已实现;配置、同级目录和显式 homes 三条完整路径均能创建、持久化并读回正确的 profile/home。existing-session-identity-retained 在本次触及范围内保持:原生配置、机器配置与已归档 SQLite 线程没有被重写;现有会话归属路径不变。

关键代码讲解

  • codex_homes:61:保留已存在目录的不同名称和优先顺序。它同时服务配置编辑器、profile 解析和普通新会话,不能因为共享物理目录就删除一个名称。
  • _installed_automation_intervals:315:读取 ACTIVE heartbeat 清单,再按 Goal、agent 和绑定线程归组。新增 home.resolve() 集合能合并符号链接,但不是所有文件系统上的物理身份,且解析异常位于已有文件读取保护之外。
  • codex_delivery_expectations:371:非 App 请求直接返回;App 请求复用上述读取器。结果交给原有 attach_host_delivery_windows,其 provider 调用先于所有行赋值,因此目录解析异常会波及同一响应中的健康行。

对主干的风险

[P2] 用文件系统身份识别同一目录。 在实际大小写不敏感文件系统上设置 CODEX_HOME=.CODEX,默认路径为 .codex。两者 samefile() 为真且设备号、inode 相同,但 resolve() 后 Path 仍不相等。普通发现与显式 homes 均把唯一清单读两次,五分钟周期仍变成未知。原始基线也有此问题,这是原任务尚未修复的分支,并非声称新引入回归。最小修复是在当前读取器内使用真实目录身份;不要再次全局删除 profile 名称。

[P2] 把目录解析失败限制在单个来源。 使用真实发现得到有效目录列表后,在读取间隙将一个别名改成循环链接。同一合成输入下,基线的生产 attach_host_delivery_windows 返回健康行 fresh、周期5和无关行 unknown;当前 head 在第336行抛 RuntimeError,所有行的窗口都尚未赋值。事件由发现边界的调度包装器确定性触发,实际路径解析和清单读取没有伪造;未声称已执行 HTTP 服务器或发生过真实用户事故。最小修复是捕获单目录身份解析错误并继续健康来源,下一次正常读取能够恢复。

复审建议的回归用例为上述实际大小写别名和发现后失效场景,再运行 uv run --extra test python -m pytest tests/test_host_thread_activity.py tests/test_chat_codex_defaults.py -q。本轮四个 owner 测试文件为 566 passed,完整进程退出码0;另在不可变 base、当前 head 和旧347完整源码上重跑独立三臂配置/会话对照。基线三种 profile 成功,前一个 PR head 三种失败,本 head 三种成功;真实第二自动化仍未知,暂停后恢复5,错误 Goal 不匹配,归档线程仍归档。

本地标准 canary premerge 六项直接检查、两项 catalog 检查和 Ruff 均退出0。没有查询、轮询或等待 GitHub CI,也没有把旧 Goal 质量失败、人工合并约束或作者 Windows 结果改写为本次通过。

语义与 CI 对齐

没有新增枚举、协议词汇或通用义务;沿用现有 home、scope 和 expectation。但新增路径解析影响了既有只读投影的来源隔离,语义结论为 violated,证据正是上述健康来源被异常中断;语义扫描通过不能替代此反例。最新主干的原生 URI/path 修复与队列内其他 Codex 改动不修复当前读取器的身份和异常边界。合并冲突状态是独立集成条件,不是本评审的问题依据。

我的整体评价

REQUEST_CHANGES。 上一个普通 profile 选择 P1 已独立验证修复;当前实现复用了正确 owner,规模适当,持久化兼容性应保留,不需要再做语言迁移或新框架。符号链接场景已取得可用增量,但尚不能把“每个物理目录只读一次”和来源失败隔离判为交付完成。长程状态观察与用户体验仍有回归风险,最低重审证据是两项新反例通过后重新验证原有 profile、冲突和暂停恢复路径。

视觉评审不适用:本次只改变 Python 发现/投影和测试,没有渲染布局变化。未验证范围:Windows/junction、已安装 App、实际模型启动及完整 HTTP 服务器;配置编辑器数据、真实文件系统、SQLite、控制器持久化和生产投影已按上述边界检查。此结论不授权合并或撤销旧评审讨论。

English verdict: REQUEST_CHANGES — 1ede005. The saved-profile regression is fixed in three source-pinned ordinary-entry comparisons. Two P2 issues remain: case-insensitive aliases still duplicate one physical store, and a discovered alias becoming unresolvable aborts the entire delivery-window projection. Local standard premerge and Ruff pass; no CI was consulted and no merge or review-dismissal authority is implied.

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants