Skip to content

fix(chat): recover interrupted queued input publication - #6895

Open
loopx-agent wants to merge 4 commits into
mainfrom
codex/fix-queued-turn-recovery-20261019
Open

loopx-agent wants to merge 4 commits into
mainfrom
codex/fix-queued-turn-recovery-20261019

Conversation

@loopx-agent

@loopx-agent loopx-agent commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

A crash after saving a queued Turn could leave its user message or turn.queued event missing. Retrying returned the original Turn without completing publication; another process could also claim it before the input was published.

恢复复用原 Turn 的完整正文、图片、来源与客户端身份。相同请求重试和首次领取补齐中断的输入发布;冲突、重复输入及无法确认的残缺记录保持拒绝。Session 的进程间锁覆盖发布,防止提前领取;已有排队事件证明发布完成时,不重读后续执行历史。

普通 Chat 的 prepared managed acceptance 仍由已有 typed acceptance owner 恢复,保留原消息 ID 和展示文本。队列模式重试只复用该接纳回执,不代写内部执行文本或排队事件;尚未完成接纳的 Turn 不能被普通队列领取。正常请求经原接纳入口恢复后,只执行一次。此检查同时修正了本提案先前版本会破坏 managed acceptance 的回归。

输入 IO 收拢到已有 ChatIngressStore,保留 ChatSessionStore 接口及队列常量导出;主存储模块减少 109 行,没有提高上限。来源、撤销、权限、容量、过期和执行准入继续使用原 owners,没有新增配置、队列或框架。

启动恢复用例现在在第二次启动前,直接检查父进程持有的原 Popen 句柄已退出并回收,替代子进程通过数字 PID 猜测清理状态。原 3 秒超时、一次重试、原请求和线程身份、单次执行及拒绝路径保持不变。故意跳过 Session.close 时,新检查在第二次启动前失败,原来的子进程仍存活,随后仅由测试清理。

Validation at bd4891e736402ed0816f95f878215c3a5d22e1bd, integrated base 45d742088a3f7896a0a008761f68d2437398bcd1 (#6896):

  • 564 source tests pass in one final run, covering queued input, active Turns, ordinary-project HTTP, bindings, native steward, manager model adoption, native Inbox, Chat Agent and Lark. They exercise isolated real stores and synthetic native/provider protocols. Managed acceptance retains the original message, null Goal, native thread and one execution.
  • 41 integration tests and both startup stages pass in a fresh installed wheel. All 720/682 imported LoopX modules come from the wheel, with no source fallback. Eight runtime file hashes match this head; the final commit only changes the copied startup test fixture. This qualifies packaged backend behavior, not live provider use or production installation.
  • Dashboard TypeScript typecheck, 45 native conversation-binding/Inbox transaction tests, Ruff on all four PR paths and all 17 configured strict-mypy targets pass.
  • The exact-head standard premerge passes all six direct checks and both selected canaries. Accepted main fix(chat): recover unfinished Bot requests automatically #6896 removes the duplicate Inbox read transport, bringing maintained semantic twins to 43/43. This PR changes no semantic budget or module ceiling.
  • The skipped-cleanup negative experiment fails at the owned-process check before another child can spawn. No startup timeout or retry allowance was increased. The earlier 89/1 and initial integrated 563/1 initialize failures remain failed observations; their production root cause is unproven. The earlier 304/1 Core-setup batch is also retained as historical evidence, not relabeled passing by these runs.

The exact-scope change-quality receipt verifies valid. Main subsequently advanced through history readback and Lark settings changes outside these four paths; the evidence above names the integrated revision actually tested. This completed proposal remains open for independent review. It is not merged or installed and does not qualify project-recipient permissions, live receiver adoption or the complete original-route collaboration journey.

Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

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

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

完整审阅当前 bd4891e736402ed0816f95f878215c3a5d22e1bd:四个文件 +565/-129,比较基线 45d742088a3f7896a0a008761f68d2437398bcd1。未发现阻塞性代码问题;本结论覆盖本切片,不替代合并资格或安装授权。

动机

向已有 Chat 会话提交后续输入、并在中断后重试或等待排队执行的用户与调用方。 Turn 已落盘但消息或排队事件尚未发布时,旧版重试只返回原 Turn;新版复用保存的完整输入补齐发布,领取必须等发布完成。 在受控 IO 中断、存储重开和实际 HTTP 恢复中,原 Turn 的输入与排队事件各保留一次,既有接纳与撤销边界不被替换。 不新增会话、队列、权限或配置,不认证真实模型使用、完整项目协作交付或生产安装。

独立规格来自不可变基线的 New Goal authority 原 Session/Turn 恢复契约,在 diff 前读取。original-input-and-turn、same-acceptance-owner、identity-conflict-stops、publication-before-claim、recovery-is-not-execution 分别约束原输入、接纳归属、冲突停止、发布顺序及证据边界;作者用例与测试数量不能自证这些要求。

改动思路

输入发布与领取顺序是既有 ingress IO 边界的正确性约束;managed acceptance 的决策仍归原 typed owner。 本 PR 仅恢复原排队输入及其首次领取,保留旧接口,不新增执行或受众权限策略。

已有 ingress、Session 锁、原请求记录和 typed acceptance 已足够。此处把排队输入 IO 收到现有 ChatIngressStore,用同一个进程间 Session fence 覆盖落盘与发布;重试和首次领取共用恢复函数。只增加锁不能修复已经保存的残缺输入,只在重试补写又不能保护直接领取,因此两条入口须一起修。正常完成的首条排队事件是既有发布标记,避免每次健康领取扫描全部后续历史;不新增状态机、存储协议、配置或队列。

触发 旧版 当前 head
Turn 保存后、消息/事件发布前中断 返回原 Turn,但输入仍缺失或可先被领取 在原 fence 内补齐保存的输入后再领取
未完成的 managed acceptance 属于原 typed owner 仍由原 owner 完成;队列重试不换消息身份,领取拒绝抢先执行
已有发布标记及后续残缺输出 输入已经发布 不把后续执行日志误判为输入缺失

具体改动

关键代码讲解:

  • create_queued_turn:保留 client identity、正文、图片、origin、原 Turn 与容量/TTL;同请求校验在修复前,跨进程 fence 保持到输入和事件发布结束。
  • _recover_queued_turn_input:优先识别已有发布标记;未发布时严格读日志,匹配完整原输入,歧义或损坏明确拒绝。它使用保存的请求,不能让重试文本替换原文。
  • claim_next_queued_turn:既有来源和 Goal 实例校验先执行,补齐输入后才写 claim/active;prepared managed capsule 只能回原接纳入口恢复。
  • _read_jsonl:严格模式只供恢复校验;其他调用方仍使用原默认宽松读取,未引入新的全局拒绝策略。
  • codex_startup:启动夹具核父进程持有的真实 Popen 已退出并回收,不再让子进程猜数字 PID。原三秒超时、一次重试及正常请求/线程/拒绝断言都保留。

独立 File-backed 存储实验在四个 IO 中断位置分别走原请求重试和首次领取,共八格:旧版仅两格已完成发布的情况满足完整输入,其余六格缺消息或排队事件;当前八格均保留原 Turn,正文和事件各一次。两版正常 managed acceptance 的不同展示文本都保持原样,排除了“全部拒绝”的假通过。完整相关源码套件 91 passed,覆盖 prepared owner、冲突/损坏日志、跨进程阻挡、实际 HTTP 来源撤销和原线程完成。

对主干的风险

实际安装到独立 wheel 环境后,排队/managed HTTP/两段启动恢复相关 46 passed、31 deselected;检查了 709 个 LoopX 模块全部来自 wheel,两个生产文件哈希与本 head 一致。底层文件日志、HTTP server 与 stdio 子进程是真实路径,模型协议与故障注入是合成边界,没有调用真实模型或操作活跃 Goal。首次 wheel 构建正确拒绝上个分支留下的旧 Chat assets;重建当前 Chat bundle 后重新构建与安装成功,原失败记录保留。

当前标准 premerge 6 direct + 2 selected canaries 全过,含语义 43/43、双语 diff、compile 与模块上限;四个路径 Ruff 通过,无 manual hold。未查询或等待 CI。没有独立重跑作者完整 564 项、跳过 cleanup 的独立负控或真实模型/生产安装,不把它们写成本次证据。已跑的测试覆盖两段真实 stdio startup cleanup 及原超时/一次重试。

我的整体评价

APPROVE,goal_achieved(仅原排队输入恢复切片)。 新行为解决可复现的输入丢失窗口,且原请求、managed 接纳、来源撤销与正常历史读取边界有正反证据。将 IO 收拢到已有 ingress 并保留原常量导出,是有当前调用方的同域简化;无需再建事务框架或新模块。恢复的长期意义仅指请求连续性与重复执行防护,用户路径维持原输入和原会话,不增加意图填写或确认轮次;模型质量、完整成本收益及更大协作旅程仍未知。

English verdict: APPROVE — bd4891e736402ed0816f95f878215c3a5d22e1bd against immutable 45d742088a3f7896a0a008761f68d2437398bcd1. Full four-file review; independent real-store counterfactual improves 2/8 to 8/8 complete original publications, with committed managed display preserved. 91 source tests and 46 installed-wheel tests pass; all 709 imported LoopX modules are wheel-owned and both changed runtime hashes match. Standard premerge 6 direct + 2 canaries and four-path Ruff pass. Native protocol/fault fixtures are synthetic; no CI consultation, live model, production installation, merge or authority claim.

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.

1 participant