Repository navigation
fix(codex): resume native quota handoffs after transient holds - #7625
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; GPT-6; OpenAI; self_reported(当前宿主执行归因不可用)
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机 / Motivation
使用已启用原生账号自动接续的 LoopX App、Chat 与 CLI 用户。旧版在额度耗尽且另一个进程暂时占用登录目录时,可能先关闭 App,再把一次 busy 记成永久暂停;新版先检查占用,等待解除后自动重新选择,无需用户手动刷新或换号。恢复临时占用后的自动接续,同时在退出前保护所有已接收的 Chat 任务。本次不做热替换登录、不重放失败任务、不接管未知 CLI 或 VM,也不更改默认授权。合入后仍须把 provider 与 Core 装入实际服务环境、交回唯一观察权并验收自动读取;真实账号的下一次自然耗尽尚未重演。
这是可复现的持续性缺陷:一次临时占用会使之后的轮询仅查看旧状态,额度已经耗尽却一直不能继续。只清零计数会继续无效关闭 App;忽略所有只读文件又会放过真正的认证占用,因此需要同时修正等待语义与退出前检查。
改动思路 / Approach
复用原账号事务与 Core 的同一在途任务锁,比新增重启器或第二份任务状态更小;临时占用属于可继续等待,未知效果仍归原恢复流程。当前 PR 只修复 busy 恢复、只读目录分类和重启前的共享在途任务保护,保留原选择器、凭据 owner 与默认关闭的权限。
调用仍由原设置/API/CLI 进入 NativeAccounts,TypeScript 选择器决定可用目标,Python host 读取真实进程与现有 native owner。所有持久化 intent、手动选择优先级和失败恢复保持原 owner。新的进程快照只是当次核验的派生数据,不是第二份配置。Core 提取原有锁和完整 Turn 读取,provider 在持有同一锁时退出、切换、读回并恢复原服务。没有新增消息消费者或通用杀进程器。
| 触发状态 | 旧版 | 当前提交 |
|---|---|---|
| 临时 busy 后占用解除 | 硬暂停,等待手动检查 | 自动重查并只成功切换一次 |
| 仅只读目录句柄 | 当成认证占用 | 类型和身份核验后排除 |
| 认证文件、缓存 CLI、未知身份 | 阻塞 | 继续阻塞,且先检查再退出 App |
| Chat 已接收但无 active 指针的排队任务 | native 路径未共享原锁 | 完整读取并在退出前等待 |
该表说明源码控制流,不代表真实账号换号执行记录。
具体改动 / Changes
判定依据是合入前的 packages/loopx-codex-provider-routing/NATIVE.md,spec_revision ce4c78088ea464cb31231513882bed6bb6933156,已读用户任务、同实例退出、独立权限及恢复段落;没有用本次新增文档倒推既有要求。
native-auto-continuation:实现。原额度选择与原生 owner 不变,新回归验证多个重建观察器遇 busy 后仍能在释放后选择,后续 ready 不重放。native-client-scope:实现。对数字 FD、只读和 DIR 三项精确核对;普通文件、缺失类型、写句柄、缓存 Codex 继续等待。原账号 owner 会在锁内复核,再次扫描后才变更。native-recovery:实现。原 CAS、凭据事务、恢复 journal 和重开路线保持;未知结果不重放,真正退出拒绝仍硬暂停。旧文档将所有 busy 一并暂停的条款是本次明确披露并验证的有意调整。
关键代码讲解
- NativeAccounts.tick 只让历史
other_clients_busy重新进入观察,正常失败预算和效果未知的 receipt 分支保留。新的 busy 显示 waiting_for_idle,不把临时占用消耗成永久失败。 - NativeHost._home_owners 从同一 lsof 读取 FD、访问方式和类型;排除目录前后仍核对 kernel 进程代际,cached Codex 优先保留。它没有据管理器名称推断 VM 可以重启。
- NativeHost.restart_guard 在退出前排除不可恢复占用,并冻结真实服务 PID、身份和 plist 摘要;新的服务不能继承这次重启集合。缺 Core 或任务状态不可核验时等待,效果体抛出的异常仍交给原恢复路径。
- managed_chat_activation_guard 复用原严格 Turn reader 和 ingress 锁,检查所有显式 runtime,而不依赖页面 Session 汇总。原 update 入口仍报告完整 status/chat 延后列表。
修改共9文件 +352/-121,包括106行回归测试、文档及三个一致的0.12.11版本标记。switch 的大段变化主要是纳入 scoped context 的缩进,凭据写入算法没有复制或替换。
对主干的风险 / Risks
没有阻塞发现。最强反例是测试把“可重启”当成已证明,却遗漏真实排队工作或 loaded manager 路线。验证因此通过公共 NativeHost.switch 使用真实 ChatSessionStore 和文件锁:queued、starting、running、completing、interrupting、非法状态均在退出前停止,原数据字节保持;原 Turn 终结后同一路径到达受锁保护的退出阶段。另有两个真实 launchd 服务的隔离验收,确认旧 PID 退出、新 PID 出现、恢复 journal 清空。
PASS:当前四个相关 suite 共164通过;同输入基线与当前未改路径各149通过。旧版本执行新增反例为4失败,当前通过。三个原 host/client/recovery smoke、10个 TS selector 用例、Ruff、RFC diff 和 standard premerge 全部通过。SKIP:同样三个 native Windows 用例在基线与当前 Darwin 环境均跳过。CI 按 Goal 策略未查询。保留历史:提取 guard 时曾丢失完整延后列表,现已恢复并通过原断言;一次真实 launchd 验收只保留清理回执,原因未捕获,独立重做完整通过,不把旧失败改写成成功。TS 首次复验命令路径写错,已在实际 smoke 路径完成10/10。
权限仍默认关闭;安装、能力发现、页面读取不会开启效果。原149项匹配验证覆盖 disabled、旧配置、手动选择、并发互斥、未知 receipt、强退独立权限以及 Core 更新延后。provider 和 Core 需要在实际运行环境一起采用;独立旧 watcher 需要通过原 manager 退役。真实认证事务没有用生产账号强行演练,VM guest 缓存登录也不在此次证明范围。
语义与 CI 对齐
沿用现有 waiting/native action、Chat Turn 与 owner 边界,没有新增共享状态词汇或 capability id。完整 diff 的 semantic advisory 未发现支持范围内的新词汇载体,但这不是语义等价证明;busy 等待的意图变更由旧版失败与新版恢复反例共同支撑。保留未知效果和受保护占用,不靠删减门禁获得自动继续。
我的整体评价 / Verdict
这是 justified_increment:代码层面的自动恢复缺口已由公共入口、真实系统管理器与回归对照验证;生产安装采用和下一次自然耗尽仍是后续实际验收。long_horizon improved:临时占用释放后不再持续饿死后续工作,未决效果仍不重复。user_experience improved:原授权下新增确认轮数为0,未知状态仍有原恢复出口。
复用原账号事务与 Core 的同一在途任务锁,比新增重启器或第二份任务状态更小;临时占用属于可继续等待,未知效果仍归原恢复流程。当前 PR 只修复 busy 恢复、只读目录分类和重启前的共享在途任务保护,保留原选择器、凭据 owner 与默认关闭的权限。本提交未修改渲染组件、布局或可见字段;检查了现有 Codex 账号设置与 API 消费路径,呈现本身沿用原样。未验证范围:没有新的视觉范围;生产自然耗尽后的换号采用尚未重演。最小后续是安装当前 Core/provider 并独立读回唯一观察器和原服务;不能用绿测试或当前健康账号代替该验收。真实首条 native_unavailable 回执缺少内部诊断,原因仍不确定,不把本次 busy 修复宣称解释所有历史失败。
English verdict: APPROVE b95e42f; no blocking finding. Production adoption and natural-exhaustion verification remain explicit.
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; GPT-6; OpenAI; self_reported(当前宿主执行归因不可用)
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机 / Motivation
使用已启用原生账号自动接续的 LoopX App、Chat 与 CLI 用户。旧版在额度耗尽且另一个进程暂时占用登录目录时,可能先关闭 App,再把一次 busy 记成永久暂停;新版先检查占用,等待解除后自动重新选择,无需用户手动刷新或换号。恢复临时占用后的自动接续,同时在退出前保护所有已接收的 Chat 任务。本次不做热替换登录、不重放失败任务、不接管未知 CLI 或 VM,也不更改默认授权。合入后仍须把 provider 与 Core 装入实际服务环境、交回唯一观察权并验收自动读取;真实账号的下一次自然耗尽尚未重演。
这是可复现的持续性缺陷:一次临时占用会使之后的轮询仅查看旧状态,额度已经耗尽却一直不能继续。只清零计数会继续无效关闭 App;忽略所有只读文件又会放过真正的认证占用,因此需要同时修正等待语义与退出前检查。
改动思路 / Approach
复用原账号事务与 Core 的同一在途任务锁,比新增重启器或第二份任务状态更小;临时占用属于可继续等待,未知效果仍归原恢复流程。当前 PR 只修复 busy 恢复、只读目录分类和重启前的共享在途任务保护,保留原选择器、凭据 owner 与默认关闭的权限。
调用仍由原设置/API/CLI 进入 NativeAccounts,TypeScript 选择器决定可用目标,Python host 读取真实进程与现有 native owner。所有持久化 intent、手动选择优先级和失败恢复保持原 owner。新的进程快照只是当次核验的派生数据,不是第二份配置。Core 提取原有锁和完整 Turn 读取,provider 在持有同一锁时退出、切换、读回并恢复原服务。没有新增消息消费者或通用杀进程器。
| 触发状态 | 旧版 | 当前提交 |
|---|---|---|
| 临时 busy 后占用解除 | 硬暂停,等待手动检查 | 自动重查并只成功切换一次 |
| 仅只读目录句柄 | 当成认证占用 | 类型和身份核验后排除 |
| 认证文件、缓存 CLI、未知身份 | 阻塞 | 继续阻塞,且先检查再退出 App |
| Chat 已接收但无 active 指针的排队任务 | native 路径未共享原锁 | 完整读取并在退出前等待 |
该表说明源码控制流,不代表真实账号换号执行记录。
具体改动 / Changes
判定依据是合入前的 packages/loopx-codex-provider-routing/NATIVE.md,spec_revision ce4c78088ea464cb31231513882bed6bb6933156,已读用户任务、同实例退出、独立权限及恢复段落;没有用本次新增文档倒推既有要求。
native-auto-continuation:实现。原额度选择与原生 owner 不变,新回归验证多个重建观察器遇 busy 后仍能在释放后选择,后续 ready 不重放。native-client-scope:实现。对数字 FD、只读和 DIR 三项精确核对;普通文件、缺失类型、写句柄、缓存 Codex 继续等待。原账号 owner 会在锁内复核,再次扫描后才变更。native-recovery:实现。原 CAS、凭据事务、恢复 journal 和重开路线保持;未知结果不重放,真正退出拒绝仍硬暂停。旧文档将所有 busy 一并暂停的条款是本次明确披露并验证的有意调整。
关键代码讲解
-
NativeAccounts.tick 只让历史
other_clients_busy重新进入观察,正常失败预算和效果未知的 receipt 分支保留。新的 busy 显示 waiting_for_idle,不把临时占用消耗成永久失败。 -
NativeHost._home_owners 从同一 lsof 读取 FD、访问方式和类型;排除目录前后仍核对 kernel 进程代际,cached Codex 优先保留。它没有据管理器名称推断 VM 可以重启。
-
NativeHost.restart_guard 在退出前排除不可恢复占用,并冻结真实服务 PID、身份和 plist 摘要;新的服务不能继承这次重启集合。缺 Core 或任务状态不可核验时等待,效果体抛出的异常仍交给原恢复路径。
-
managed_chat_activation_guard 复用原严格 Turn reader 和 ingress 锁,检查所有显式 runtime,而不依赖页面 Session 汇总。原 update 入口仍报告完整 status/chat 延后列表。
-
native.host 将父进程已经加载的 Core 路径传给同步与 detached 子进程,保留原 PYTHONPATH 其余项,不改全局环境;没有 Core 时不杜撰 owner。真实子进程在工作目录外、禁用 site-packages 的条件下核验相同 Core 与 guard。
修改共9文件 +413/-123,包括149行回归测试、文档及三个一致的0.12.11版本标记。switch 的大段变化主要是纳入 scoped context 的缩进,凭据写入算法没有复制或替换。
对主干的风险 / Risks
没有阻塞发现。最强反例是测试把“可重启”当成已证明,却遗漏真实排队工作或 loaded manager 路线。验证因此通过公共 NativeHost.switch 使用真实 ChatSessionStore 和文件锁:queued、starting、running、completing、interrupting、非法状态均在退出前停止,原数据字节保持;原 Turn 终结后同一路径到达受锁保护的退出阶段。另有两个真实 launchd 服务的隔离验收,确认旧 PID 退出、新 PID 出现、恢复 journal 清空。
PASS:当前四个相关 suite 共167通过;同输入基线及上一 head 的未改路径各149通过,当前167全量继续覆盖这些相同断言。旧版本执行新增反例为4失败,当前通过。三个原 host/client/recovery smoke、10个 TS selector 用例、Ruff、RFC diff 和 standard premerge 全部通过。SKIP:同样三个 native Windows 用例在基线与当前 Darwin 环境均跳过。CI 按 Goal 策略未查询。保留历史:提取 guard 时曾丢失完整延后列表,现已恢复并通过原断言;一次真实 launchd 验收只保留清理回执,原因未捕获,独立重做完整通过,不把旧失败改写成成功。TS 首次复验命令路径写错,已在实际 smoke 路径完成10/10。
相对上一 head 的重审还发现父进程 sys.path 可导入而子进程不可导入的缺口;新提交补充默认 host 启动环境。前一候选执行这两个真实子进程用例均失败,当前三个加载/缺失场景通过;最终全套167通过。其余149个匹配基线用例的函数体未改变,最初164通过和旧审批保留为历史,不继承为新 head 的结论。
权限仍默认关闭;安装、能力发现、页面读取不会开启效果。原149项匹配验证覆盖 disabled、旧配置、手动选择、并发互斥、未知 receipt、强退独立权限以及 Core 更新延后。provider 和 Core 需要在实际运行环境一起采用;独立旧 watcher 需要通过原 manager 退役。真实认证事务没有用生产账号强行演练,VM guest 缓存登录也不在此次证明范围。
语义与 CI 对齐
沿用现有 waiting/native action、Chat Turn 与 owner 边界,没有新增共享状态词汇或 capability id。完整 diff 的 semantic advisory 未发现支持范围内的新词汇载体,但这不是语义等价证明;busy 等待的意图变更由旧版失败与新版恢复反例共同支撑。保留未知效果和受保护占用,不靠删减门禁获得自动继续。
我的整体评价 / Verdict
这是 justified_increment:代码层面的自动恢复缺口已由公共入口、真实系统管理器与回归对照验证;生产安装采用和下一次自然耗尽仍是后续实际验收。long_horizon improved:临时占用释放后不再持续饿死后续工作,未决效果仍不重复。user_experience improved:原授权下新增确认轮数为0,未知状态仍有原恢复出口。
复用原账号事务与 Core 的同一在途任务锁,比新增重启器或第二份任务状态更小;临时占用属于可继续等待,未知效果仍归原恢复流程。当前 PR 只修复 busy 恢复、只读目录分类和重启前的共享在途任务保护,保留原选择器、凭据 owner 与默认关闭的权限。本提交未修改渲染组件、布局或可见字段;检查了现有 Codex 账号设置与 API 消费路径,呈现本身沿用原样。未验证范围:没有新的视觉范围;生产自然耗尽后的换号采用尚未重演。最小后续是安装当前 Core/provider 并独立读回唯一观察器和原服务;不能用绿测试或当前健康账号代替该验收。真实首条 native_unavailable 回执缺少内部诊断,原因仍不确定,不把本次 busy 修复宣称解释所有历史失败。
English verdict: APPROVE 0389d69; no blocking finding. Production adoption and natural-exhaustion verification remain explicit.
The package import ratchet fails on main. PR loopx-project#7625 added from loopx.runtime_activation import managed_chat_activation_guard, RuntimeActivationDeferred to packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_host.py, and the pin that records every `loopx.*` module a co-located package imports does not carry that edge: AssertionError: co-located packages gained imports of loopx internals: {'loopx-codex-provider-routing': ['loopx.runtime_activation']} The pin's own note says a new edge needs a recorded design decision, and the monorepo-distribution-split RFC Section 5 holds that decision. This records it. `loopx.runtime_activation` owns the transition of services that are already installed. `managed_chat_activation_guard` holds the accepted-Chat-work fence and the ingress lock while a managed client restarts, and the Codex provider routing package uses it, and no other entry point of that module, to fence accepted Chat work before it restarts the Chat services it manages. The guard grants no work authority: it takes the ingress lock and refuses to continue while accepted work or ingress is pending. Section 5 now names that module as the third public module in the supported host integration seam, beside MemT's facade and `loopx.file_lock`, and says that the seam does not widen: a package still may not import the executor or another kernel-private module, and the pinned Ark/JEV edges stay migration debt. Both mirrors carry the same text. The RFC's Appendix A records the baseline, the boundary and the remaining gaps, and its decision log records the alternatives: restarting the Chat services without the fence, copying the lock and state check into the package, or leaving the edge unrecorded. The pin gains the edge and its note names the new seam member. No production code, schema, wire or default change. Validation: the import ratchet passes; the RFC bilingual diff check, the RFC status index check and the docs governance smoke pass; mkdocs --strict builds the docs site and both developer books. Signed-off-by: xiaoan17 <anbc1224@gmail.com>
The package import ratchet fails on main. PR loopx-project#7625 added from loopx.runtime_activation import managed_chat_activation_guard, RuntimeActivationDeferred to packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_host.py, and the pin that records every `loopx.*` module a co-located package imports does not carry that edge: AssertionError: co-located packages gained imports of loopx internals: {'loopx-codex-provider-routing': ['loopx.runtime_activation']} The pin's own note says a new edge needs a recorded design decision, and the monorepo-distribution-split RFC Section 5 holds that decision. This records it. `loopx.runtime_activation` owns the transition of services that are already installed. `managed_chat_activation_guard` holds the accepted-Chat-work fence and the ingress lock while a managed client restarts, and the Codex provider routing package uses it, and no other entry point of that module, to fence accepted Chat work before it restarts the Chat services it manages. The guard grants no work authority: it takes the ingress lock and refuses to continue while accepted work or ingress is pending. Section 5 now names that module as the third public module in the supported host integration seam, beside MemT's facade and `loopx.file_lock`, and says that the seam does not widen: a package still may not import the executor or another kernel-private module, and the pinned Ark/JEV edges stay migration debt. Both mirrors carry the same text. The RFC's Appendix A records the baseline, the boundary and the remaining gaps, and its decision log records the alternatives: restarting the Chat services without the fence, copying the lock and state check into the package, or leaving the edge unrecorded. The pin gains the edge and its note names the new seam member. No production code, schema, wire or default change. Validation: the import ratchet passes; the RFC bilingual diff check, the RFC status index check and the docs governance smoke pass; mkdocs --strict builds the docs site and both developer books. Signed-off-by: xiaoan17 <anbc1224@gmail.com>
The package import ratchet fails on main. PR loopx-project#7625 added from loopx.runtime_activation import managed_chat_activation_guard, RuntimeActivationDeferred to packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_host.py, and the pin that records every `loopx.*` module a co-located package imports does not carry that edge: AssertionError: co-located packages gained imports of loopx internals: {'loopx-codex-provider-routing': ['loopx.runtime_activation']} The pin's own note says a new edge needs a recorded design decision, and the monorepo-distribution-split RFC Section 5 holds that decision. This records it. `loopx.runtime_activation` owns the transition of services that are already installed. `managed_chat_activation_guard` holds the accepted-Chat-work fence and the ingress lock while a managed client restarts, and the Codex provider routing package uses it, and no other entry point of that module, to fence accepted Chat work before it restarts the Chat services it manages. The guard grants no work authority: it takes the ingress lock and refuses to continue while accepted work or ingress is pending. Section 5 now names that module as the third public module in the supported host integration seam, beside MemT's facade and `loopx.file_lock`, and says that the seam does not widen: a package still may not import the executor or another kernel-private module, and the pinned Ark/JEV edges stay migration debt. Both mirrors carry the same text. The RFC's Appendix A records the baseline, the boundary and the remaining gaps, and its decision log records the alternatives: restarting the Chat services without the fence, copying the lock and state check into the package, or leaving the edge unrecorded. The pin gains the edge and its note names the new seam member. No production code, schema, wire or default change. Validation: the import ratchet passes; the RFC bilingual diff check, the RFC status index check and the docs governance smoke pass; mkdocs --strict builds the docs site and both developer books. Signed-off-by: xiaoan17 <anbc1224@gmail.com>
The package import ratchet fails on main. PR loopx-project#7625 added from loopx.runtime_activation import managed_chat_activation_guard, RuntimeActivationDeferred to packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_host.py, and the pin that records every `loopx.*` module a co-located package imports does not carry that edge: AssertionError: co-located packages gained imports of loopx internals: {'loopx-codex-provider-routing': ['loopx.runtime_activation']} The pin's own note says a new edge needs a recorded design decision, and the monorepo-distribution-split RFC Section 5 holds that decision. This records it. `loopx.runtime_activation` owns the transition of services that are already installed. `managed_chat_activation_guard` holds the accepted-Chat-work fence and the ingress lock while a managed client restarts, and the Codex provider routing package uses it, and no other entry point of that module, to fence accepted Chat work before it restarts the Chat services it manages. The guard grants no work authority: it takes the ingress lock and refuses to continue while accepted work or ingress is pending. Section 5 now names that module as the third public module in the supported host integration seam, beside MemT's facade and `loopx.file_lock`, and says that the seam does not widen: a package still may not import the executor or another kernel-private module, and the pinned Ark/JEV edges stay migration debt. Both mirrors carry the same text. The RFC's Appendix A records the baseline, the boundary and the remaining gaps, and its decision log records the alternatives: restarting the Chat services without the fence, copying the lock and state check into the package, or leaving the edge unrecorded. The pin gains the edge and its note names the new seam member. No production code, schema, wire or default change. Validation: the import ratchet passes; the RFC bilingual diff check, the RFC status index check and the docs governance smoke pass; mkdocs --strict builds the docs site and both developer books. Signed-off-by: xiaoan17 <anbc1224@gmail.com>
The package import ratchet fails on main. PR loopx-project#7625 added from loopx.runtime_activation import managed_chat_activation_guard, RuntimeActivationDeferred to packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_host.py, and the pin that records every `loopx.*` module a co-located package imports does not carry that edge: AssertionError: co-located packages gained imports of loopx internals: {'loopx-codex-provider-routing': ['loopx.runtime_activation']} The pin's own note says a new edge needs a recorded design decision, and the monorepo-distribution-split RFC Section 5 holds that decision. This records it. `loopx.runtime_activation` owns the transition of services that are already installed. `managed_chat_activation_guard` holds the accepted-Chat-work fence and the ingress lock while a managed client restarts, and the Codex provider routing package uses it, and no other entry point of that module, to fence accepted Chat work before it restarts the Chat services it manages. The guard grants no work authority: it takes the ingress lock and refuses to continue while accepted work or ingress is pending. Section 5 now names that module as the third public module in the supported host integration seam, beside MemT's facade and `loopx.file_lock`, and says that the seam does not widen: a package still may not import the executor or another kernel-private module, and the pinned Ark/JEV edges stay migration debt. Both mirrors carry the same text. The RFC's Appendix A records the baseline, the boundary and the remaining gaps, and its decision log records the alternatives: restarting the Chat services without the fence, copying the lock and state check into the package, or leaving the edge unrecorded. The pin gains the edge and its note names the new seam member. No production code, schema, wire or default change. Validation: the import ratchet passes; the RFC bilingual diff check, the RFC status index check and the docs governance smoke pass; mkdocs --strict builds the docs site and both developer books. Signed-off-by: xiaoan17 <anbc1224@gmail.com>
The package import ratchet fails on main. PR loopx-project#7625 added from loopx.runtime_activation import managed_chat_activation_guard, RuntimeActivationDeferred to packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_host.py, and the pin that records every `loopx.*` module a co-located package imports does not carry that edge: AssertionError: co-located packages gained imports of loopx internals: {'loopx-codex-provider-routing': ['loopx.runtime_activation']} The pin's own note says a new edge needs a recorded design decision, and the monorepo-distribution-split RFC Section 5 holds that decision. This records it. `loopx.runtime_activation` owns the transition of services that are already installed. `managed_chat_activation_guard` holds the accepted-Chat-work fence and the ingress lock while a managed client restarts, and the Codex provider routing package uses it, and no other entry point of that module, to fence accepted Chat work before it restarts the Chat services it manages. The guard grants no work authority: it takes the ingress lock and refuses to continue while accepted work or ingress is pending. Section 5 now names that module as the third public module in the supported host integration seam, beside MemT's facade and `loopx.file_lock`, and says that the seam does not widen: a package still may not import the executor or another kernel-private module, and the pinned Ark/JEV edges stay migration debt. Both mirrors carry the same text. The RFC's Appendix A records the baseline, the boundary and the remaining gaps, and its decision log records the alternatives: restarting the Chat services without the fence, copying the lock and state check into the package, or leaving the edge unrecorded. The pin gains the edge and its note names the new seam member. No production code, schema, wire or default change. Validation: the import ratchet passes; the RFC bilingual diff check, the RFC status index check and the docs governance smoke pass; mkdocs --strict builds the docs site and both developer books. Signed-off-by: xiaoan17 <anbc1224@gmail.com>
The package import ratchet fails on main. PR loopx-project#7625 added from loopx.runtime_activation import managed_chat_activation_guard, RuntimeActivationDeferred to packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_host.py, and the pin that records every `loopx.*` module a co-located package imports does not carry that edge: AssertionError: co-located packages gained imports of loopx internals: {'loopx-codex-provider-routing': ['loopx.runtime_activation']} The pin's own note says a new edge needs a recorded design decision, and the monorepo-distribution-split RFC Section 5 holds that decision. This records it. `loopx.runtime_activation` owns the transition of services that are already installed. `managed_chat_activation_guard` holds the accepted-Chat-work fence and the ingress lock while a managed client restarts, and the Codex provider routing package uses it, and no other entry point of that module, to fence accepted Chat work before it restarts the Chat services it manages. The guard grants no work authority: it takes the ingress lock and refuses to continue while accepted work or ingress is pending. Section 5 now names that module as the third public module in the supported host integration seam, beside MemT's facade and `loopx.file_lock`, and says that the seam does not widen: a package still may not import the executor or another kernel-private module, and the pinned Ark/JEV edges stay migration debt. Both mirrors carry the same text. The RFC's Appendix A records the baseline, the boundary and the remaining gaps, and its decision log records the alternatives: restarting the Chat services without the fence, copying the lock and state check into the package, or leaving the edge unrecorded. The pin gains the edge and its note names the new seam member. No production code, schema, wire or default change. Validation: the import ratchet passes; the RFC bilingual diff check, the RFC status index check and the docs governance smoke pass; mkdocs --strict builds the docs site and both developer books. Signed-off-by: xiaoan17 <anbc1224@gmail.com>
The package import ratchet fails on main. PR loopx-project#7625 added from loopx.runtime_activation import managed_chat_activation_guard, RuntimeActivationDeferred to packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_host.py, and the pin that records every `loopx.*` module a co-located package imports does not carry that edge: AssertionError: co-located packages gained imports of loopx internals: {'loopx-codex-provider-routing': ['loopx.runtime_activation']} The pin's own note says a new edge needs a recorded design decision, and the monorepo-distribution-split RFC Section 5 holds that decision. This records it. `loopx.runtime_activation` owns the transition of services that are already installed. `managed_chat_activation_guard` holds the accepted-Chat-work fence and the ingress lock while a managed client restarts, and the Codex provider routing package uses it, and no other entry point of that module, to fence accepted Chat work before it restarts the Chat services it manages. The guard grants no work authority: it takes the ingress lock and refuses to continue while accepted work or ingress is pending. Section 5 now names that module as the third public module in the supported host integration seam, beside MemT's facade and `loopx.file_lock`, and says that the seam does not widen: a package still may not import the executor or another kernel-private module, and the pinned Ark/JEV edges stay migration debt. Both mirrors carry the same text. The RFC's Appendix A records the baseline, the boundary and the remaining gaps, and its decision log records the alternatives: restarting the Chat services without the fence, copying the lock and state check into the package, or leaving the edge unrecorded. The pin gains the edge and its note names the new seam member. No production code, schema, wire or default change. Validation: the import ratchet passes; the RFC bilingual diff check, the RFC status index check and the docs governance smoke pass; mkdocs --strict builds the docs site and both developer books. Signed-off-by: xiaoan17 <anbc1224@gmail.com>
The package import ratchet fails on main. PR loopx-project#7625 added from loopx.runtime_activation import managed_chat_activation_guard, RuntimeActivationDeferred to packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_host.py, and the pin that records every `loopx.*` module a co-located package imports does not carry that edge: AssertionError: co-located packages gained imports of loopx internals: {'loopx-codex-provider-routing': ['loopx.runtime_activation']} The pin's own note says a new edge needs a recorded design decision, and the monorepo-distribution-split RFC Section 5 holds that decision. This records it. `loopx.runtime_activation` owns the transition of services that are already installed. `managed_chat_activation_guard` holds the accepted-Chat-work fence and the ingress lock while a managed client restarts, and the Codex provider routing package uses it, and no other entry point of that module, to fence accepted Chat work before it restarts the Chat services it manages. The guard grants no work authority: it takes the ingress lock and refuses to continue while accepted work or ingress is pending. Section 5 now names that module as the third public module in the supported host integration seam, beside MemT's facade and `loopx.file_lock`, and says that the seam does not widen: a package still may not import the executor or another kernel-private module, and the pinned Ark/JEV edges stay migration debt. Both mirrors carry the same text. The RFC's Appendix A records the baseline, the boundary and the remaining gaps, and its decision log records the alternatives: restarting the Chat services without the fence, copying the lock and state check into the package, or leaving the edge unrecorded. The pin gains the edge and its note names the new seam member. No production code, schema, wire or default change. Validation: the import ratchet passes; the RFC bilingual diff check, the RFC status index check and the docs governance smoke pass; mkdocs --strict builds the docs site and both developer books. Signed-off-by: xiaoan17 <anbc1224@gmail.com>
An exhausted native Codex account could remain permanently paused after a transient client hold. The host also treated read-only directory handles as credential consumers and could quit the App before discovering a blocker.
Recheck legacy busy pauses automatically, keep those waits outside the hard-failure budget, and preflight typed owners before App quit. Only verified read-only directory descriptors are exempted; cached Codex clients and auth-file handles remain holds. Discovered Chat services now share the existing accepted-work reader and ingress lock through account readback and restoration. Archive/private bootstraps also pass their already loaded Core import root to native workers, including detached handoffs, so service protection does not depend on the current directory or another installation. Existing explicit restart/force permissions, native account transactions, identity checks and unknown-effect recovery remain authoritative.
Validation: 167 focused tests passed (3 platform/fixture skips); the old base fails four ownership/retry regressions, and the first candidate fails two isolated worker-import regressions. Native host/client/recovery smokes, TypeScript selector tests, Ruff, bilingual diff check and standard risk-based premerge passed. A credential-free Darwin drill used two real launchd services and verified fresh replacement PIDs and empty recovery. No real login was switched for testing. The first generic native-unavailable incident has no diagnostic detail sufficient to identify its internal cause.