Skip to content

fix(subagents): reconcile native Codex host events with Turns - #5455

Open
jackie-cqz wants to merge 7 commits into
loopx-project:mainfrom
jackie-cqz:codex/fix-native-child-host-receipts
Open

jackie-cqz wants to merge 7 commits into
loopx-project:mainfrom
jackie-cqz:codex/fix-native-child-host-receipts

Conversation

@jackie-cqz

@jackie-cqz jackie-cqz commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Goal and delivered boundary

Refs #5051. Enabled owned Codex CLI and app-server Turns now record native spawn/followup outcomes and completion through the existing multi_subagent receipt owner. The shared CLI, dashboard Goal drawer and Lark status projection distinguish host observations, coordinator reports, mixed provenance and unknown activity. Parent evidence adoption remains an explicit review.

The Python Codex adapter owns streaming transport; existing typed admission/settlement rules retain decision authority. Feature-off Turns keep their request/result behavior. External hosts remain coordinator-reported, and unobserved activity does not become launch counts.

Review repairs

Both P1 findings are addressed:

  • A wait-only resumed CLI process restores the original spawned child's operation from admitted host-observed events under the exact GoalRef, agent and parent Turn. It does not adopt coordinator reports or arbitrary host history, and restoration is independent of the bounded display window.
  • Followups and failed calls bind reset native item IDs to the host invocation. CLI invocations use the durable executor attempt; app-server invocations use the native Turn ID. Distinct followups, including repeated followups to the same child, remain distinct; exact invocation replay remains idempotent.

The bounded companion refactor reuses one admitted full-event reader and the existing durable attempt owner. No new lifecycle vocabulary, authority store or parallel decision source is introduced. Rebase preserves upstream's receipt wrapper and its private host-observation wiring.

Current qualification

Head: 14890edcff660acd84c2f4100e97a504c35d8c7d. Merge base: 5e889bdcba9cea101a8775340a12629eb5a2474a, PR base main. All seven PR commits carry DCO sign-off.

  • Linux Python 3.11 source-installed receipt, production Codex CLI subprocess, executor, app-server and shared CI regression suites: 210 passed, 2 skipped. These include spawn then wait-only process resume, reused item counters, same-child distinct followups, failed calls, exact replay, retry attempt persistence and feature-off parity.
  • Exact CI mypy 1.20.2: all 19 configured sources passed. CI Ruff, TypeScript control-plane typecheck and full semantic inventory smoke passed. Focused typed admission/context tests: 38 passed.
  • Exact Linux CLI output-budget smoke passed on both this base and head; no budget changed.
  • Shared packaging qualification on the rebased peer branch rebuilt Chat, installed its actual wheel in an isolated environment and ran the current release workflow's install/uninstall validator: all eight skills removed. That branch has the same shipped skill metadata contract.
  • Packaged native-child desktop/mobile browser scenario passed before the final rebase; the frontend files are unchanged by that final base update. Earlier isolated real Codex spawn/failure/completion/adoption evidence retains that earlier head's scope.

Shared CI repairs isolate ambient runtime roots, claim queued test Turns through the actual queue owner, and declare the existing read-only Todo delivery contract. Upstream #5463 and #5479 now own the doctor dispatch and packaged display metadata fixes; duplicate patches were dropped during rebase.

Remaining boundary

Codex collaboration failures expose failed without a typed capacity reason. The adapter retains host_failed and the same-Turn retry restriction rather than inferring capacity from prose. Arbitrary external hosts and a full multi-host lifecycle remain outside this slice. Hosted CI and maintainer review are still required; runtime changes are left for the maintainer to merge.

@jackie-cqz
jackie-cqz force-pushed the codex/fix-native-child-host-receipts branch 2 times, most recently from 5bc9078 to 9d18a1e Compare October 2, 2026 11:51
@mergify

mergify Bot commented Oct 2, 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, @jackie-cqz.

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 2, 2026
@jackie-cqz
jackie-cqz force-pushed the codex/fix-native-child-host-receipts branch from 9d18a1e to 09e3983 Compare October 2, 2026 12:33
@mergify mergify Bot removed the needs-rebase Mergify: the pull request has merge conflicts with its base branch label Oct 2, 2026
@jackie-cqz
jackie-cqz force-pushed the codex/fix-native-child-host-receipts branch 2 times, most recently from 34aef42 to 00643fc Compare October 2, 2026 13:53

@huangruiteng huangruiteng 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-5 | OpenAI

动机

结论:REQUEST_CHANGES。这里评的是 00643fc,而不是配置了几个子 Agent 就推断执行成功。#5051 的实际问题是原生宿主的尝试、结果与父 Agent 采纳缺少可追溯回执;这份 PR 的方向正确,但恢复路径仍丢失完成事实、合并不同跟进操作,尚未完成稳定身份和持续回读的承诺。

改动思路

CLI 与 managed app-server 的已归属连接向一个 Codex provider seam 送原生完成事件,再复用既有 native-child 事件流和 TS settlement 准入。随后同一读模型进入 agent-context、状态 Markdown、Lark 使用的状态展示及 Goal drawer。host_observed 说明决策来源,绝不说明父 Agent 已采纳;配置上限也不等于空槽或启动义务。Python 适配原生传输,TS 继续拥有准入与共享投影;没有新增调度器、peer 权限或配额消费。

具体改动

  • 「CodexNativeChildObserver.observe」(loopx/control_plane/turn_driver/codex_native_child.py:58):按 sender、terminal status 和原生工具枚举过滤,再构造稳定操作号和完成结果。正路是同一进程 spawn→wait,失败路是宿主失败或无关 sender;我通过真正的进程 stdout 传输和临时文件事件流验证,并未只 mock observer。
  • 「run_codex_cli_host」(loopx/control_plane/turn_driver/codex_cli.py:848):消费 item.completed 并在已有 Goal admission fence 内登记;恢复调用重新创建 observer。父结果原样保留,但这也是下面两个恢复缺口的真实入口。app-server 的 chat_agent 与 operation-host 回调按当前 thread/Turn 过滤,未启用时没有该回调。
  • 「native_child_activity」(loopx/capabilities/multi_subagent/native_child_receipts.py:69):从决策来源归并 host_observed/coordinator_reported/mixed/unknown,保留结果和独立 parent review。状态渲染、subagent_context、dashboard status/model 类型、drawer 及 i18n 跟随同一读模型;新 browser fixture 覆盖四态,但本轮没有完成它的浏览器复验。

完整差异为 25 文件、+493/-47:上述生产路径与类型、双语宿主契约、native/Chat/TS/browser 验证,以及 UTF-8、interrupted-Turn read-only、Windows archive/update 和安装技能集合的五个共享测试修正均已读过。它们不是启动更多 children 的授权。

P1:恢复后已有子任务完成事件被静默丢弃。 第一进程写入 child-1 的 started;同一 LoopX Turn 的 resume 进程收到 parent-1 的 wait(completed, child-1=completed),父结果正常返回,但 canonical activity 的原 spawn 没有 result。构造函数把 children 置空(:47),结果分支只查这个内存映射(:90-92),没有恢复已登记关系。原有“restart”测试重放了完整 spawn+wait 历史,不覆盖只收到新 wait 的正常恢复。最小修复是在既有回执归属下恢复可验证的 child→operation 关系,让迟到结果关联原 started 操作,而不是补造新决策或扫描任意外部历史。回归需两次真实 CLI host 调用,第二次仅 wait,完成后独立读取原 operation 的 completed,并验证未多记 launch/配额。

P1:CLI display item 编号不足以区分恢复后的 followup。 :79-80 用 parent session + item ID 哈希;真实 Codex exec 的编号是每进程从零开始,不是稳定 tool-call 身份。独立复现:两次同 Turn/同 parent 的 host 调用分别对 child-1、child-2 完成 send_input(item_0),两个父结果均正常,却只有一个 durable followup。spawn 的 receiver 哈希修复没有覆盖 followup/failed 决策。请使用可区分调用且可重放的原生身份/调用绑定,不能仅加 receiver(同 child 的不同 followup 仍会冲突),也不能每次随机号破坏重放幂等。补充真实进程 resume、相同计数器不同调用、精确重放三组回归。

本次采用改动前契约:spec_ref = docs/integrations/host-native-child-receipts.md;spec_revision = 4fc30f1。规范没有单独编号,以下以原文条款开头作为 criterion_id:

criterion_id 判定
The admitted Turn guard must already have a settlement binding 既有 TS admission 与 recorder 验证已复用;没有变成新权限源。
Use stage=decision with a stable operation-id 未满足:恢复后的 followup 身份碰撞,上述 P1。
A started operation may get a typed result 同进程正路通过;恢复仅 wait 丢结果,上述 P1。
Replay with the same identity and payload is idempotent 相同完整历史的重放通过,但不同调用也被误当重复,不能据此认定恢复完整。
A new decision requires an open, work-admitted Turn and no begun closeout recorder 保留新决定/迟到结果的 TS 分界;adapter 的恢复缺口须修,不能用放宽准入掩盖。

对主干的风险

140 项 Python 通过、2 项跳过(既有 explicit live-host release qualification,未调用付费模型);15 项 TS 通过,diff check 和语义 advisory 通过。另补跑第一宿主实际 timeout 后保存原 session 再 resume,两项缺口同样出现;base/head 未启用路径的完整结果与 activity 逐字段相同。额外真实子进程验证同进程正路、feature-off 不写原生事件、父结果保留、无原始内容保留,同时独立复现以上两项 P1。fixture 只使用合成临时状态;没有在活动 Goal 上试错。原生协议编号依据固定的 OpenAI Codex 源码 event processor,而不是从 PR 自己的输出倒推 oracle。

恢复错账会让“已完成”和“可采纳”长期不一致,或把不同任务证据挂到同一操作;配置和绿色单次 smoke 都看不出它。另保留未验证项:当前 head 的 packaged drawer 浏览器、完整跨平台和 live app-server 原生调用,本次没有宣称通过。无 CI 查询/等待,无合并。

我的整体评价

归属位置合理、体量适中,统一 CLI/app-server casing 的 seam 是有价值的有界重构;无需把这次修复扩大为通用 actor 框架或整个 TS 迁移。但 provider 必须把 transient correlation 与 durable operation identity 分清。建议在当前 PR 完成这两项相关恢复修复并重跑全路径;不要另建平行事件库,也不要把父 Agent 采纳自动化来隐藏缺失结果。修复前保留 REQUEST_CHANGES,#5051 的整体验收不关闭。

English verdict: REQUEST_CHANGES - 00643fc: two independently reproduced CLI resume defects lose completed-child facts and collapse distinct followups; 140 Python and 15 TypeScript tests passed, two gated live cases skipped. No merge.

@mergify

mergify Bot commented Oct 2, 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, @jackie-cqz.

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 2, 2026
@huangruiteng

Copy link
Copy Markdown
Collaborator

Reviewer: model_agent | GPT-5 | OpenAI

动机

结论:REQUEST_CHANGES。这里评的是 00643fc,而不是配置了几个子 Agent 就推断执行成功。#5051 的实际问题是原生宿主的尝试、结果与父 Agent 采纳缺少可追溯回执;这份 PR 的方向正确,但恢复路径仍丢失完成事实、合并不同跟进操作,尚未完成稳定身份和持续回读的承诺。

改动思路

CLI 与 managed app-server 的已归属连接向一个 Codex provider seam 送原生完成事件,再复用既有 native-child 事件流和 TS settlement 准入。随后同一读模型进入 agent-context、状态 Markdown、Lark 使用的状态展示及 Goal drawer。host_observed 说明决策来源,绝不说明父 Agent 已采纳;配置上限也不等于空槽或启动义务。Python 适配原生传输,TS 继续拥有准入与共享投影;没有新增调度器、peer 权限或配额消费。

具体改动

  • 「CodexNativeChildObserver.observe」(loopx/control_plane/turn_driver/codex_native_child.py:58):按 sender、terminal status 和原生工具枚举过滤,再构造稳定操作号和完成结果。正路是同一进程 spawn→wait,失败路是宿主失败或无关 sender;我通过真正的进程 stdout 传输和临时文件事件流验证,并未只 mock observer。
  • 「run_codex_cli_host」(loopx/control_plane/turn_driver/codex_cli.py:848):消费 item.completed 并在已有 Goal admission fence 内登记;恢复调用重新创建 observer。父结果原样保留,但这也是下面两个恢复缺口的真实入口。app-server 的 chat_agent 与 operation-host 回调按当前 thread/Turn 过滤,未启用时没有该回调。
  • 「native_child_activity」(loopx/capabilities/multi_subagent/native_child_receipts.py:69):从决策来源归并 host_observed/coordinator_reported/mixed/unknown,保留结果和独立 parent review。状态渲染、subagent_context、dashboard status/model 类型、drawer 及 i18n 跟随同一读模型;新 browser fixture 覆盖四态,但本轮没有完成它的浏览器复验。

完整差异为 25 文件、+493/-47:上述生产路径与类型、双语宿主契约、native/Chat/TS/browser 验证,以及 UTF-8、interrupted-Turn read-only、Windows archive/update 和安装技能集合的五个共享测试修正均已读过。它们不是启动更多 children 的授权。

P1:恢复后已有子任务完成事件被静默丢弃。 第一进程写入 child-1 的 started;同一 LoopX Turn 的 resume 进程收到 parent-1 的 wait(completed, child-1=completed),父结果正常返回,但 canonical activity 的原 spawn 没有 result。构造函数把 children 置空(:47),结果分支只查这个内存映射(:90-92),没有恢复已登记关系。原有“restart”测试重放了完整 spawn+wait 历史,不覆盖只收到新 wait 的正常恢复。最小修复是在既有回执归属下恢复可验证的 child→operation 关系,让迟到结果关联原 started 操作,而不是补造新决策或扫描任意外部历史。回归需两次真实 CLI host 调用,第二次仅 wait,完成后独立读取原 operation 的 completed,并验证未多记 launch/配额。

P1:CLI display item 编号不足以区分恢复后的 followup。 :79-80 用 parent session + item ID 哈希;真实 Codex exec 的编号是每进程从零开始,不是稳定 tool-call 身份。独立复现:两次同 Turn/同 parent 的 host 调用分别对 child-1、child-2 完成 send_input(item_0),两个父结果均正常,却只有一个 durable followup。spawn 的 receiver 哈希修复没有覆盖 followup/failed 决策。请使用可区分调用且可重放的原生身份/调用绑定,不能仅加 receiver(同 child 的不同 followup 仍会冲突),也不能每次随机号破坏重放幂等。补充真实进程 resume、相同计数器不同调用、精确重放三组回归。

本次采用改动前契约:spec_ref = docs/integrations/host-native-child-receipts.md;spec_revision = 4fc30f1。规范没有单独编号,以下以原文条款开头作为 criterion_id:

criterion_id 判定
The admitted Turn guard must already have a settlement binding 既有 TS admission 与 recorder 验证已复用;没有变成新权限源。
Use stage=decision with a stable operation-id 未满足:恢复后的 followup 身份碰撞,上述 P1。
A started operation may get a typed result 同进程正路通过;恢复仅 wait 丢结果,上述 P1。
Replay with the same identity and payload is idempotent 相同完整历史的重放通过,但不同调用也被误当重复,不能据此认定恢复完整。
A new decision requires an open, work-admitted Turn and no begun closeout recorder 保留新决定/迟到结果的 TS 分界;adapter 的恢复缺口须修,不能用放宽准入掩盖。

对主干的风险

140 项 Python 通过、2 项跳过(既有 explicit live-host release qualification,未调用付费模型);15 项 TS 通过,diff check 和语义 advisory 通过。另补跑第一宿主实际 timeout 后保存原 session 再 resume,两项缺口同样出现;base/head 未启用路径的完整结果与 activity 逐字段相同。额外真实子进程验证同进程正路、feature-off 不写原生事件、父结果保留、无原始内容保留,同时独立复现以上两项 P1。fixture 只使用合成临时状态;没有在活动 Goal 上试错。原生协议编号依据固定的 OpenAI Codex 源码 event processor,而不是从 PR 自己的输出倒推 oracle。

恢复错账会让“已完成”和“可采纳”长期不一致,或把不同任务证据挂到同一操作;配置和绿色单次 smoke 都看不出它。另保留未验证项:当前 head 的 packaged drawer 浏览器、完整跨平台和 live app-server 原生调用,本次没有宣称通过。无 CI 查询/等待,无合并。

我的整体评价

归属位置合理、体量适中,统一 CLI/app-server casing 的 seam 是有价值的有界重构;无需把这次修复扩大为通用 actor 框架或整个 TS 迁移。但 provider 必须把 transient correlation 与 durable operation identity 分清。建议在当前 PR 完成这两项相关恢复修复并重跑全路径;不要另建平行事件库,也不要把父 Agent 采纳自动化来隐藏缺失结果。修复前保留 REQUEST_CHANGES,#5051 的整体验收不关闭。

English verdict: REQUEST_CHANGES - 00643fc: two independently reproduced CLI resume defects lose completed-child facts and collapse distinct followups; 140 Python and 15 TypeScript tests passed, two gated live cases skipped. No merge.

明明是 gpt-6.1-sol。。不认识自己

Signed-off-by: jackie-cqz <2557911191@qq.com>
Signed-off-by: jackie-cqz <2557911191@qq.com>
Signed-off-by: jackie-cqz <2557911191@qq.com>
Signed-off-by: jackie-cqz <2557911191@qq.com>
(cherry picked from commit 7efb0d996f8572371e368a66824c9cfb78a41cb4)
Signed-off-by: jackie-cqz <2557911191@qq.com>
(cherry picked from commit c0f7ab8010bb30a4f99555d24139c0f4934e4093)
Signed-off-by: jackie-cqz <2557911191@qq.com>
Signed-off-by: jackie-cqz <2557911191@qq.com>
@jackie-cqz
jackie-cqz force-pushed the codex/fix-native-child-host-receipts branch from 00643fc to 14890ed Compare October 2, 2026 18:29
@jackie-cqz

Copy link
Copy Markdown
Contributor Author

Rebased onto 5e889bdcba9cea101a8775340a12629eb5a2474a; current head is 14890edcff660acd84c2f4100e97a504c35d8c7d.

Both requested P1 repairs are implemented. Wait-only CLI resumes restore the original admitted host-observed spawn under the exact GoalRef/agent/parent Turn. Reset item counters are now scoped to durable CLI attempts or native app-server Turns, preserving distinct followups/failures while exact replay stays idempotent. The rebase also repairs outer-to-inner host-observation wiring.

Current qualification: 210 Python regressions passed (2 skipped), including the actual production CLI subprocess transport across separate invocations and feature-off retry parity; 38 typed admission/context tests passed. Exact CI mypy/Ruff, TypeScript typecheck, semantic smoke and paired base/head CLI budget passed. Shared release validation installed a real rebased wheel and removed all eight skills through the current workflow validator.

The PR body now names current versus earlier browser/live-host evidence and the remaining host boundary. Typed admission/settlement remain the decision owner; Python owns Codex transport only. Hosted checks are rerunning, and both review findings are ready for maintainer re-review.

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

@huangruiteng huangruiteng 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-5 | OpenAI

动机

REQUEST_CHANGES:旧的两项 P1 已通过独立回归核验,但同一个 child 的 followup 在宿主进程恢复后仍无法得到自己的结果,失败结果还会遮蔽父任务的正常返回。评审完整 head 14890edcff660acd84c2f4100e97a504c35d8c7d。

#5051 要把启用后的原生子 Agent 调用变成真实、可区分来源的回执,而不是把配置上限当作实际启动数。本次独立规范是变更前的 docs/integrations/host-native-child-receipts.md,spec_ref = docs/integrations/host-native-child-receipts.md,spec_revision = 5e889bd。按原 Lifecycle 编号逐项核对:

  • criterion_id 1.:沿用 TS 的精确 Turn 准入,不由 Python 状态标签推断权限;已有准入/关闭后报告测试通过。
  • criterion_id 2.:spawn/followup 区分、独立宿主 invocation 身份和精确重放已实现;本轮两个历史缺陷探针在旧 head 失败、当前 head 通过。
  • criterion_id 3.:started 后结果归属尚未满足。恢复只找原 spawn,不能恢复当前 followup;主 Agent 验收仍必须独立发生,宿主完成不是 accepted。
  • criterion_id 4.:相同 payload 幂等和冲突拒绝保留,但错误的关联会把合法 followup 结果送到旧 spawn,导致丢失或冲突。JSON/Markdown/前端来源展示链已读;本轮未重跑包装浏览器,保留可见交互验证缺口。
  • criterion_id 5.:结果/验收的迟到报告仍交给既有事件锁和 TS 粗粒度 owner;适配器没有重开已结算 Turn 的权限。

这是有正价值的宿主观察增量,不是整个多 Agent 生命周期已经完成。持续恢复和结果返回是本切片的必要结果,不能把它推迟成另一个与本 PR 无关的能力。

改动思路

最小合理机制是在已有 exec/app-server 事件入口观察调用,转为已有 native-child 事件,再由同一 read model 给 agent-context、状态和抽屉使用。不增加 scheduler、第二套 Goal store 或自动启动路径。Python 承担宿主字段 casing、进程和 transport 适配,TS 继续拥有准入/阶段语义;不需要为了语言偏好扩大迁移。

正路是已准入的启用 Turn → 观察实际 collab item → 记 decision → 关联终态 → 投影 host_observed → 主 Agent 另行验收。原 coordinator_reported 和 unknown 保留,混合来源明确区分。生产者是实际宿主事件,不是手填活动行;配置、安装、可用槽位都不生成观察事实。相比不做观察或要求手动同步,这个 owner 选择合理;目前需要补的是既有持久事件里的 followup 关联,而不是再建一套 child registry。

具体改动

关键代码讲解

  • CodexNativeChildObserver.observe,loopx/control_plane/turn_driver/codex_native_child.py:84:校验 sender、原生 item 类型和完成状态,统一 exec/app-server 字段;spawn 由 opaque child 身份得到稳定 ID,followup 由 session、durable invocation、native item 得到独立 ID。同一调用重放不新增工作;不同 invocation 的 item_0 不再被错误合并。child→operation 关系目前只写进进程内字典。
  • CodexNativeChildObserver._restore_spawn,同文件 :60:从完整事件流而不是有界显示窗口恢复已准入、同 Goal/agent/Turn 的 host-observed spawn。这修复 wait-only spawn 恢复,但筛选条件明确排除 followup,正是下面 P1 的关联缺口。
  • _record_native_child,loopx/capabilities/multi_subagent/native_child_receipts.py:277:复用事件锁、精确准入和 typed result/review 规则;相同身份不同结果拒绝是正确保护。错误的观察关联不能靠放宽这个保护或吞掉异常来“修复”。公共上报入口不能自行选择宿主来源。
  • native_child_observer,loopx/control_plane/turn_driver/codex_native_child.py:134:只有已有 multi_subagent context 和 Turn 身份才创建适配器。run_codex_cli_host 和 operation-host 把它接在真实事件入口;chat_agent/executor 在同一 owning result 路径读取活动,不授予子 Agent 或 parent 新权限。

完整 28 文件、+710/-57 均已阅读:9 个运行时/上下文/状态源,5 个 dashboard schema/model/copy/抽屉消费者,协议文档与 self-repair 指导,浏览器入口/fixture/55 行场景,以及原生事件、replan guard、Chat、executor、技能交付测试。前端复用 Goal 信息抽屉,英文/中文区分 host、coordinator、mixed 与 unknown;没有另造开关或必须重复输入的表单。浏览器 fixture 提供活动状态,只能验证渲染,不能证明真实持久回执。

对主干的风险

P1:恢复时把 followup 的结果关联到已完成的原 spawn,丢结果或使父任务抛错。 触发顺序为同一已准入 Turn:进程一 spawn(child) 已完成;进程二 send_input(child) 已启动;进程三仅收到 wait(child) 的终态。新的 observer 字典为空,observe:126–134 调 _restore_spawn:60–82,选回旧 spawn,而不是最后的 followup。

独立探针走真实 run_codex_cli_host 子进程 stdout、session 恢复、TS 准入和持久事件后端,仅宿主可执行文件输出合成原生协议,未调用模型:wait=completed 时父任务返回,但 followup 没有 result;wait=errored 时旧 spawn 已有 completed,recorder 抛出 operation identity already has a conflicting native child report,第三次父任务结果也没有返回。若 child 没有本 Turn 的 spawn,仅 followup 后恢复,结果同样丢失。当前六个独立场景是 3 通过、3 失败;通过项是两个旧缺陷及 feature-off,不能用它们覆盖三个失败项。

最小修复:在已有 durable owner 保留并恢复合法、opaque 的 child→当前 operation 关联,覆盖 followup、无同 Turn spawn、同 child 连续 followup 和恢复重放;仍绑定精确 Goal/agent/Turn/宿主来源,不持久化 prompt 或 transcript,不覆写原已完成 spawn,不关闭冲突校验。回归应通过真实两/三次 CLI invocation 分别等待 completed/errored,断言结果属于 followup、父任务照常返回、相同 wait 重放幂等。可将这些序列加入 tests/capabilities/test_codex_native_child_receipts.py,复验 uv run --extra test python -m pytest tests/capabilities/test_codex_native_child_receipts.py tests/capabilities/test_native_child_receipts.py tests/test_loopx_turn_codex_cli.py -q;现有仅 spawn 恢复的测试不足。

本轮既有六文件 Python 原生/Chat/executor 验证 214 passed、2 skipped,两个 TS 文件 15 passed,kernel mypy 19 源文件通过,CI 范围 Ruff 通过,语义 advisory 未检测到支持的新 carrier。feature-off 使用同一 fixture、不可变 base 与当前 head:完整活动、父结果和错误对象相同(fixture SHA-256 454560f0264ebf2a34793a2d338ef8e1bc079e730b2be6fbda1f5a592b884bfc),都是 unknown、零 operation/启动/配额;没有仅凭“对象缺失”宣称隔离。未查询、轮询或等待 GitHub CI。包装 UI 和真实 authenticated app-server 本轮未执行,不将作者声明或合成协议冒充这些结果。

语义与 CI 对齐

这是对已有来源 vocabulary 的有理由扩展,不是扩大 peer/子 Agent 权限。typed admission/result owner 和 generic failure/capacity 用语保留,配置上限不是启动义务,也不把 enforced 准入称为建议。当前具体违反的是原 Lifecycle 的稳定操作结果归属;修复位置应是宿主关联和现有持久事件,而非修改规范以匹配错误结果。来源、默认启用边界和无法观察外部宿主的限制在双语文档中说明;UI schema 与状态同源,不新增 parallel decision owner。

我的整体评价

正价值、归属和体量合理;未来面对相邻变更,最有价值的伴随重构就是把瞬时字典所需关系归回已有 durable owner,而非扩展 Python policy 或再加 registry。历史 coordinator 回执仍是独立/持久消费者,需要保留兼容,不能为了减代码删掉。long_horizon 与 user_experience 仍有已复现回归:连续 followup 不能完成真实恢复,正常 parent 结果还可能被观察异常遮蔽。故当前 head REQUEST_CHANGES;两项旧 P1 已确认修复,新 P1 需在本切片闭合,UI 可复核交互证据仍未完成。没有撤销未解决评审、合并、扩大权限或关闭母目标。

English verdict: REQUEST_CHANGES - 14890ed: both prior P1 regressions are fixed, but restart restores only spawn correlation; followup results are lost or conflict with a completed spawn and mask the parent result. Independent real-CLI transport oracle: 3 passed / 3 failed; native suites: 214 passed / 2 skipped, TS: 15 passed, mypy: 19 sources. Synthetic host protocol, not a paid-host or fresh browser qualification. No merge.

@mergify

mergify Bot commented Oct 2, 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, @jackie-cqz.

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 2, 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