Skip to content

docs(rfc): record the Codex provider-routing activation seam - #7642

Closed
xiaoan17 wants to merge 2 commits into
loopx-project:mainfrom
xiaoan17:codex/record-codex-activation-seam
Closed

xiaoan17 wants to merge 2 commits into
loopx-project:mainfrom
xiaoan17:codex/record-codex-activation-seam

Conversation

@xiaoan17

@xiaoan17 xiaoan17 commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Scope

One failing architecture guard on main, and the design decision it was
waiting for.

tests/architecture/test_package_kernel_import_ratchet.py pins every loopx.*
module a co-located package imports. PR #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 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 PR records it.

The decision

loopx.runtime_activation owns the transition of services that are already
installed. Its 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 holds the ingress admission lock and
refuses to continue while a non-terminal Turn is pending. A pending ingress
receipt is not part of that check — the guard reads accepted work through the
Turn state, so a pending loopx_queue or loopx_inbox receipt on its own
does not defer the restart.
tests/test_chat_runtime_activation.py::test_a_pending_ingress_receipt_alone_does_not_defer_the_restart
pins that narrowed boundary.

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 states
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 the English document and its .zh-CN.md mirror carry the same
text.

The RFC's Appendix A records the baseline, the boundary and the remaining
gaps; its decision log records the alternatives that were not taken:

  • restarting the Chat services without the fence,
  • copying the lock and state check into the package,
  • leaving the edge unrecorded.

The pin gains the edge, and its note names the new seam member.

Response to the previous review

The previous review raised one P2: the recorded decision promised that the
guard refuses to continue while "accepted work or ingress is pending", and
that promise does not hold. managed_chat_activation_guard takes the
admission mutex and then reads chat_runtime_activation_state(...), which
enumerates Sessions and Turns and never reads the ingress receipt ledger. A
pending loopx_queue or loopx_inbox receipt alone is admitted.

The English text, the Chinese mirror and Appendix A now state only what the
guard checks — the ingress admission lock and the non-terminal Turn check —
and say explicitly that a pending ingress receipt is not covered. No runtime
policy was widened to fit the old wording; the wording was corrected to the
runtime. The PR description carries the same correction.

Validation

pytest tests/architecture/test_package_kernel_import_ratchet.py            2 passed
pytest tests/test_chat_runtime_activation.py                              27 passed
pytest tests/architecture/test_rfc_status_index.py                        13 passed
python examples/docs-governance-smoke.py                                  ok
python scripts/generate_rfc_status_index.py --check                       clean
scripts/check_rfc_bilingual.py --base origin/main --head HEAD             passed
mkdocs build --strict                                                     built, 0 errors
loopx canary premerge --from-git-diff --git-diff-base origin/main         14 checks, 0 failures, 0 warnings
loopx check --scan-path <changed paths>                                   clean

No production code, schema, wire or default change. The only test added is the
characterization of the guard's real boundary.

@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.

动机 / Motivation

[P2] 新增的 pending ingress 拒绝保证不成立。 当一个 Session 只有待处理的 loopx_queue 或 loopx_inbox 收据、尚无非终态 Turn 时,真实 managed_chat_activation_guard 会放行。英文第 190–191 行和中文第 121 行、附录 A 把这个情况也写成拒绝条件。应把中英文正文、附录和 PR 说明收窄到实际保证;无需为修正文档擅自扩大重启策略。

受影响的是维护 Codex provider-routing 包的开发者:已有的 Chat 服务重启路径需要一个明确允许依赖的内核入口。
此前服务重启已经调用保护栅栏,但架构检查没有登记这条依赖而失败;本 PR 补充设计决定与精确 import pin,使维护者能区分受支持入口和其他私有依赖。
架构检查在本次提交通过;新增文档却把保护范围写成包含 pending ingress,而真实待处理收据会被放行,必须收窄这个保证。
本 PR 不修改服务重启实现,不新增执行权限,不完成分包路线图,也不证明已安装客户端或长程效果已经验收。
支持入口的记录已有价值,但中英文正文、附录与 PR 说明中的 pending ingress 拒绝承诺仍需对齐真实 Turn 栅栏。

评审版本:f471267681526e96e8ab0b81bee843a092d58c02。独立依据为改动前 docs/architecture/rfcs/monorepo-distribution-split-v0.md,spec_revision=b201da8bab305d053866aa0d4516b97ba4a4499e。I2 要求单一内核 owner,I4 要求缺失/关闭一致性,I6 保留安全与权限边界,§5 要求明确记录接缝、禁止任意私有 import。本次依赖记录满足这些边界;不能借新增文字证明自身的额外保护承诺。

改动思路 / Approach

复用现有 loopx.runtime_activation 入口是合理的:包内重启函数已经调用它,这里补上设计决定与架构 pin;复制锁或允许任意内核模块都更差。需要分清两个实际条件:取得 admission mutex 可阻止受保护的新 Turn 在切换窗口内进入;检查 nonterminal_turns 可阻止已有非终态 Turn 被重启。两者都不能推出“已有 pending ingress 收据必然拒绝”。

真实路径是 native_host.restart_guard → managed_chat_activation_guard → chat_runtime_activation_state → 持锁执行已有切换。状态读取器枚举 Session/Turn,不读 ingress 收据账本;ChatIngressStore.create_ingress_receipt 可以独立产生 pending 收据。最小修复是描述这条真实边界,保留待处理收据尚未被该检查覆盖的限制。

具体改动 / Changes

4 个路径、+73/-9:两份 RFC 增加接缝、设计选择与证据说明;架构 fixture 增加一个实际 import;测试仅调整说明,AST 比较逻辑未改。RuntimeActivationDeferred 是异常类型导入,不是另一个执行入口。Ark/JEV 私有依赖仍是积压,MemT 两个原接缝不受替换。

独立验证包括:import ratchet 2 passed;实际 activation 测试 25 passed;离线 native-host client handoff smoke 通过;双语 diff、RFC 状态索引和 docs governance 通过。基线对应源码与 fixture 的缺边失败可以复现,head 的 pin 修复有效。审阅用的基线替身 checkout 并非基线 Git HEAD,已逐路径证明其相关 owner/fixture blob 与 b201da8bab305d053866aa0d4516b97ba4a4499e 完全一致。

另外以真实临时 Session/IngressStore 创建 queue、inbox pending 收据:两者均为 nonterminal_turns=0 且进入 guard;真正 queued Turn 得到 chat_work_pending。所有业务记录读回字节未变。这个反例直接验证新增文档,不以 mock 状态函数替代关键读取器。

对主干的风险 / Risks

阻塞点是公开接缝保证失实,尚未证明发生输入丢失,也不是本 PR 引入的运行时代码回归。已有 activation 和 pin 检查全绿仍允许该反例,因此这些测试不能认证文档所称的全部 pending-ingress 保护。正文两种语言和附录须一起修正,避免下一次集成继续依赖错误前提。

标准 canary premerge --from-git-diff --git-diff-base 9cae3b28939f72fa4aadab5cfe49e19bcbdab372 的 5 个直接检查和 11 个选中检查执行通过;完整门禁仍为 quality_invalid_receipt,因为已记录的 CQR 包含上述失败语义比较和阻塞 finding。保留失败,不能称为完整 premerge 通过。未查询、轮询或等待远端 CI;提交带 DCO trailer。未进行真正的 launchctl、信号发送、共享安装或已安装客户端切换。

我的整体评价 / Verdict

REQUEST_CHANGES。 真实依赖的登记是有用且可逆的增量,新增 promise 必须先符合实际调用方。只需收窄保证,再用 pending queue/inbox 与 queued-Turn 对照读回;不要求扩大到分包发布、另一个解释器或整个父路线图。依赖 pin 的通过也不证明 M4/M5、长期效果或安装验收。

本次检查的 RFC 正文与 import pin 没有布局、主题、首屏或交互改动。未检查已安装客户端视觉与真实服务切换;此处仅评审源码、文档保证与离线夹具。这里的审批结论不授予合并、重启服务或执行新任务的权限。

Reviewer: actor_kind=model_agent; model=gpt-6.1-sol; provider=OpenAI; reasoning_effort=max; declaration_source=runtime_reported.

English verdict: REQUEST_CHANGES

Comment on lines +190 to +191
authority: it takes the ingress lock and refuses to continue while accepted
work or ingress is pending. The import ratchet records that edge as well. This

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] 收窄 pending ingress 的拒绝保证。真实 managed_chat_activation_guard 取得 admission mutex 后只检查 chat_runtime_activation_state(...)["nonterminal_turns"];该状态读取器枚举 Turn,不读取 ingress 收据账本。以真实临时 Session 分别写入 pending loopx_queue / loopx_inbox 收据、保持无非终态 Turn,两者均允许进入 guard;真正 queued Turn 则拒绝并返回 chat_work_pending。因此这里新增的保证以及中文第 121 行、附录 A 的对应文字会让调用方依赖尚不存在的保护。请把两种语言和 PR 说明收窄到非终态 Turn 检查与持有入口互斥锁;这次文档修复不必扩大运行时策略。该反例未证明输入丢失,也不是本 PR 引入的运行时代码变化。

@xiaoan17
xiaoan17 force-pushed the codex/record-codex-activation-seam branch 2 times, most recently from 207f60f to 0dea6bf Compare October 29, 2026 15:04
@mergify

mergify Bot commented Oct 29, 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, @xiaoan17.

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 29, 2026
@xiaoan17
xiaoan17 force-pushed the codex/record-codex-activation-seam branch from 0dea6bf to f74b721 Compare October 29, 2026 15:12
@mergify mergify Bot removed the needs-rebase Mergify: the pull request has merge conflicts with its base branch label Oct 29, 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: actor_kind=model_agent; model=gpt-6.1-sol; provider=OpenAI; reasoning_effort=max; declaration_source=runtime_reported.

APPROVE;没有阻断发现。 复审完整 head f74b721304c4c2c14fdded81b2d2868cfa8ec798,上一版 pending-ingress 保证的 P2 已解决。

动机 / Motivation

受影响的是维护 Codex provider-routing 包的开发者:已有服务重启调用需要一个有明确边界的公开内核接缝。

此前真实重启栅栏已被调用,但 import pin 缺边而失败,上一版文档又错误承诺拒绝所有 pending ingress;本次记录已有依赖,并把保证收窄到真实的非终态 Turn 检查。

当前 pin 检查通过,未登记私有 import 和删除 import 未同步 pin 仍被拒绝;真实 pending queue/inbox 收据允许进入 guard,queued Turn 则拒绝,四个对照的业务记录均未改变。

本 PR 不改变服务重启、权限、默认值或持久格式,不证明实际客户端切换、分包安装或长程净收益。

M0–M5、R0–R4 与未决设计的实际交付和安装资格继续由原分发 RFC 管理;本次只完成现有调用方的接缝记录与边界保护。

改动思路 / Approach

最小且合适的做法是记录已经存在的调用关系,继续复用同一个栅栏;无需在包内复制锁,也无需为修正文档扩大重启策略。实际链路是 native_host.restart_guard → managed_chat_activation_guard → chat_runtime_activation_state。入口互斥锁保护切换窗口,状态读取器枚举 Session/Turn;它没有读取 ingress 收据账本。因此“有非终态 Turn 就拒绝”与“pending ingress 收据单独存在仍放行”可以同时成立。

这是在现有公开接缝中提出一个具名模块的设计决定,不是允许任意包导入内核。当前 base 已包含新的最小/标准运行时组合设计;本提案没有改写它的单一 authority、缺失/关闭语义或未决选项。上一版三个生产 owner 与当前版本的 blob 相同,本轮也重新执行了实际栅栏,而没有继承旧的批准结论。

具体改动 / Changes

关键内容讲解

完整差异为 5 路径、+111/-8:EN/ZH RFC 记录一个已有接缝及备选方案;JSON pin 只增加 loopx.runtime_activation;AST 比较逻辑未改;activation 测试补上 queue/inbox 两种 pending 收据。正文、附录与当前 PR 说明均不再承诺拒绝 pending 收据。RuntimeActivationDeferred 是同模块的异常类型,不是新增执行权限。

独立依据为 改动前的分发 RFC,spec_ref: docs/architecture/rfcs/monorepo-distribution-split-v0.md;spec_revision: 58205c62a16a9e98ab3319ada3bab5aea74b829d。I2 对应既有单一状态/锁 owner;I4 对应原缺失/关闭路径与不新增默认激活;I6 对应未改 schema、隐私和权限。Supported host integration decision 对应这次明确提出的具名接缝及精确 pin,不能把未审阅的新文字用来证明更宽权限。

实际 AST 对照复现了 base 的缺边失败;head 通过。随后在一次性源码副本中增加私有 loopx.control_plane import,检查仍拒绝;删除 activation import 却保留 pin,检查同样拒绝。真实临时 Chat store 的 idle、pending queue、pending inbox 均可进入 guard,queued Turn 返回 chat_work_pending;四组业务 JSON 字节均未改变。这些检查没有启动或停止实际服务。

对主干的风险 / Risks

PASS:42 项 focused tests;changed Python Ruff;RFC 双语 diff、派生索引、docs governance;使用仓库 docs requirements 的 strict MkDocs build。标准 premerge 的 5 个直接检查和 11 个选中检查全通过,精确范围 change-quality 收据有效,公共边界扫描通过。主站构建保留了其他页面既有的 INFO 锚点诊断;它们没有被重标为已修复。

旧反例现已成为准确的限制与可执行保护,不再是虚假的拒绝保证。没有生产代码、启用开关、默认值或持久格式变化。未重新运行整个全仓架构矩阵或实际安装客户端切换;当前结论基于这条具名接缝与相称的风险检查。未查询、轮询或等待远端 CI。

我的整体评价 / Verdict

该增量有明确维护价值:long_horizon improved,仅指后续集成不再依赖错误的入口保护承诺,并继续受到精确 import 约束;未证明实际长程收益。user_experience preserved,既有重启与恢复入口不变,也没有新增用户确认或手工转录步骤。没有重复决策 owner、请求解码器或新公共状态词汇;当前无需扩大重构。

本次仅检查 RFC 正文、pin 和测试,没有布局、主题、首屏或交互实现变化;未做整页视觉检查。实际 App、已安装客户端和平台切换仍未验证。批准结论不授予合并、服务重启或安装权限,远端 head 与原生 closeout/readiness 仍分别读回。

English verdict: APPROVE

At f74b721304c4c2c14fdded81b2d2868cfa8ec798, the narrowed guard contract and exact import seam pass real negative controls and local premerge; installed client switching remains unverified.

xiaoan17 added 2 commits October 30, 2026 00:55
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 recorded decision claimed the guard refuses to continue while accepted
work or ingress is pending. The real guard takes the ingress admission
lock and refuses to continue only while a non-terminal Turn exists; it
reads accepted work through the Turn state and never reads the ingress
receipt ledger, so a pending queue or inbox receipt passes through.

Narrow the English text, the Chinese mirror and Appendix A to the non-
terminal Turn check, and pin the narrowed boundary with a test.

Signed-off-by: xiaoan17 <anbc1224@gmail.com>
@xiaoan17
xiaoan17 force-pushed the codex/record-codex-activation-seam branch from f74b721 to 7c5b252 Compare October 29, 2026 16:56
@mergify

mergify Bot commented Oct 29, 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, @xiaoan17.

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 29, 2026
@xiaoan17

Copy link
Copy Markdown
Contributor Author

这个 PR 已被上游取代,不再以这个形式提交。

上游 #7684 已合并,把同一件事完整做掉了,而且做得更准确:

  • 接缝已记录:第 5 节现在写明 Codex provider-routing host 经由 loopx.extensions.chat_service_guard facade 接入,并说明已接受工作观察、准确服务身份和 ingress lock 仍留在属主那里。
  • pin 已就位:tests/architecture/package_kernel_import_pins.json 里该包唯一被 pin 的 import 就是 loopx.extensions.chat_service_guard,tests/architecture/test_package_kernel_import_ratchet.py 在 main 上通过。

同时这个 PR 的 pin 已经过时且是错的:它记录的是 loopx.runtime_activation,但包代码早已改为只 import loopx.extensions.chat_service_guard。ratchet 同时检查 added 与 removed 两侧,所以这份 pin 会双向失败。

唯一还剩下的独立部分——写明该栅栏实际拒绝什么——已重做并提交在新 PR:
新 PR(分支 codex/record-codex-activation-seam-v2)。

为什么重做而不是直接 rebase 这个分支

原 P2 finding("新增的 pending ingress 拒绝保证不成立")在 main 上依然存在:上游 #7684 的正文没有做那个过宽的承诺,但它也没有说明栅栏实际拒绝什么,读者无法从文档判断 pending ingress 收据是否被覆盖。

新 PR 只做这一件事:

  • 正文(EN/ZH)写明栅栏持有入口准入锁,并在仍有非终态 Turn 时拒绝继续;待处理的入口收据不是 Turn,且栅栏不读取入口收据账本,因此会被放行;queued Turn 以 chat_work_pending 被拒绝。
  • 执行台账(Appendix A)补上这次交付的基线、边界与剩余项。
  • 两个用例钉住边界两侧:只有 pending loopx_queue / loopx_inbox 收据时不推迟重启;有 pending 收据且有 queued Turn 时仍然推迟。

新 PR 不改任何 import、pin、权限、默认值或持久格式,也不重复 #7684 已完成的工作。

@xiaoan17

Copy link
Copy Markdown
Contributor Author

更正:新 PR 是 #7695,不是上面写的 7711。

@xiaoan17

Copy link
Copy Markdown
Contributor Author

已由上游 #7684 取代,剩余的独立部分重做为 #7695。详见上方评论。

@xiaoan17 xiaoan17 closed this Oct 29, 2026
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