Repository navigation
fix(chat): recover interrupted queued input publication - #6895
loopx-agent wants to merge 4 commits into
Conversation
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
left a comment
There was a problem hiding this comment.
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.
A crash after saving a queued Turn could leave its user message or
turn.queuedevent 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 base45d742088a3f7896a0a008761f68d2437398bcd1(#6896):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.