fix(codex): 保留 user 延迟落盘时的 turn 归属 - #1533
Conversation
|
你好,这个 PR 的自动评审群已建好,麻烦点击下面的链接加入飞书群,评审结论会同步在群里(链接一年有效): (本次自动拉群遇到凭证临时故障,没能直接把你拉进群,抱歉;这是自动流程,最终评审结论以维护者审阅为准。) |
|
初步评审意见(自动评审辅助生成,最终以维护者审阅为准): 修 #1503 的方向和 parser 侧改动(把 1.(阻断)非 adopt:非 Lark 输入的 task_started 会冒领 pending 的 Lark 轮
基线(master)上该序列结果正确:web 轮被忽略、lark-A 由自己的 user 记录认领并收到 LARK answer。 2.(阻断)adopt:iTerm 的 task_started 提前认领后,迟到的 user 会 HOL-drop 掉 Lark markadopt 下序列相同:iTerm 轮的 3.(应修)给 id-less 收集中轮次补绑 id 时缺时间序守卫
建议的修法方向(供参考,不限制具体实现)把 task_started 认领做成「可撤销的推测认领」,在指纹 user 落盘前(
测试建议覆盖:非 adopt 非 Lark start 冒领 + 真 Lark 轮不丢、adopt iTerm start + 迟到 user 不误删 Lark mark、回退后下一个真 Lark task_started 能正确认领、claim 后 user 不来直接 abort 的收尾。 再次说明以上为自动评审的初步意见,最终以维护者审阅为准,感谢修复! |
|
补充一点对上一条修法建议的边界要求(仍是初步评审意见,最终以维护者审阅为准): 「佐证完成前的 terminal 先缓冲」必须带明确的释放上界,不能只靠"指纹 user 总会落盘"这个假设——实测
另外建议补的回归用例再加两条:指纹 user 始终不来、terminal 先到达时 Lark mark 被回退且不 settle;回退后缓冲的 foreign terminal 不会在 Lark 话题产出回复。 |
|
再补两条实现精度(仍是初步评审意见,最终以维护者审阅为准):
|
|
续上一条,补一个容易被写漏的实现约束(仍是初步评审意见,最终以维护者审阅为准): 回退推测认领时,除了把 请把这条做成回归断言(而不是只靠代码评审):
|
|
补充上一条「回退」的重置清单:除
清掉 |
|
已按评审意见补齐队列侧守卫:
新增覆盖非 adopt web 输入、adopt iTerm 输入、task_complete/abort 先到、foreign terminal、超时释放、confirmed/unconfirmed lease 重锚和 stale task_started 绑定。 验证:
|
|
增量复审意见(自动评审辅助生成,最终以维护者审阅为准): 回退机制整体实现得很扎实——两轮提的阻断/应修都收掉了:非 adopt 冒领、adopt HOL 误删、确切 id 回退判据、回退四件重置(started / 绑定 id+session / collecting / lease 重锚)、10 分钟佐证超时、id-less 时间序守卫均有实现和回归覆盖;删除变异(去 lease 重锚 / 去 terminal 回退 / 不清 collecting)分别杀 6/1/4 个用例,鉴别力足够;本地 tsc 0、19 个相关套件 707 测试全绿、CI 9/9 绿。 但增量复评发现 1 个 P1:非 adopt 下「指纹不匹配立即回退」对 #1503 的真实时序仍然不生效,建议再收一轮。 问题:AGENTS/scaffolding user 记录会提前触发回退Codex 处理一轮提交时,会把 AGENTS/环境注入作为独立的 按 worker 真实的 1s prune 心跳,#1503 报告人的时序在本版上仍会复现:
(master 基线在同一序列同样失败,所以这不是相对主干的回归;但本 PR 的目标正是 #1503,而报告人明确描述了 task_started 与真实 user 之间写有 AGENTS/env scaffolding、间隔 100s——这个形状下本版没有修好。) 真实 rollout 数据(本机 2011 个会话、1204 对「AGENTS 记录 → botmux_routing 指纹记录」):间隔 p50 0.38s / p90 0.64s / p99 1.16s,37 对 >1s、1 对 >20s(最大 586s)。绝大多数轮因为两条记录间隔不足 1s 而不受影响,但一旦落盘发生停滞(正是本 bug 的触发条件),回退加 20s 普通 lease 就会先于迟到的真实 user 清掉 mark。 建议修法(已做最小原型验证)把「指纹不匹配立即回退」限定在 adopt:
我在现有代码上做了这个一行判定的原型( 一个小提醒(不阻断)10 分钟佐证常量对本机观测 max 587.9s 的余量只有约 2%。维持定值可以,但值得在注释里写明它是按实测 p-max 取的有界上界、而不是协议保证,日后若遇到更长尾可再调。 再次说明以上为自动评审初步意见,最终以维护者审阅为准。 |
|
续上一条增量评审(自动评审辅助生成,最终以维护者审阅为准):上一条建议的「mismatch 回退限定 adopt」单独使用会把最初的误归属问题带回来,这里给出修正后的完整修法,麻烦以此条为准。 为什么单独「限定 adopt」不够非 adopt 推迟 mismatch 回退后,provisional 认领一直绑着先到的 native id;若随后出现另一个确切的 native start(不同 turn_id),现有代码在 id 不等时直接落空(队首已 started,找不到未 start 的轮),新 start 被丢弃;之后指纹 user 的"佐证"只补字段、不换绑,先到那轮的 terminal 再按 id 精确落回 Lark mark → 飞书仍收到错误回复。队列级四版本对照(按 worker 1s prune 心跳):
建议的完整修法(两件,均已在队列上原型验证)
第 2 条不只为竞态服务:真实 rollout 里 Codex 自身会在毫秒级重试/换 native turn——本机 2011 个会话扫到 21 次「不同 turn_id 的 task_started 在终态前重叠」(2026-03~08 均有,两个 id 仅隔 3ms,且第一个 id 永远没有 terminal、完成的是第二个 id)。本版在这种序列上同样会楔成永久执行中(佐证后绑定的是被放弃的旧 id),supersede 一并修掉;另有 45 个会话以未关闭的 start 结束(孤儿),supersede 让真 Lark 轮不再等满 10 分钟。 测试需要同步调整采纳第 1 条后,现有这 3 个用例在非 adopt 下断言的「fingerprint mismatch 后立即 started=false + 重锚」中间态不再成立(原型实测恰为这 3 个变红):
请把断言点从「mismatch user 后」后移到回退真正发生的边沿——绑定 id 的 terminal 到达或distinct native start 到达;并新增:(a) 非 adopt mismatch 不回退、provisional 保留;(b) distinct start supersede(含"旧 id 无终态、新 id 完成"的真实形状);(c) 上一条的 AGENTS 100s 序列。 采用组合修法后,上述四形状全部正确,除上述 3 个待改用例外,本地 18 个相邻套件 612 测试保持全绿。再次说明为自动评审初步意见,最终以维护者审阅为准。 |
|
补充一个严重度定级(自动评审初步意见,最终以维护者审阅为准):上一条表格里的「distinct-native-start supersede」不只是修外部竞态,它同时修掉一条本 PR 相对 master 引入的真实回归,建议按必修看待。 用真实 rollout 序列(2026-03-27 实样,两个 task_started 相隔 3ms:
即该回归由本 PR 引入、并非存量问题。该形状不依赖任何外部并发:Codex 自身重试/换 native turn 就会产生,本机 2011 个会话里 21 次(2026-03~08),另有 45 个会话以未关闭 start 结束。因此上一条建议的两件修法中,第 2 件(provisional 态遇 distinct native start 先回退再重新认领)是恢复 master 既有正确性所必需;第 1 件(mismatch 回退限定 adopt)解决 #1503 的存量缺口。两者建议一并包含,并请用上面 c7→c8 的真实序列加一条回归(master 绿、当前红、修复后绿)。 |
|
再补一个 v3 回归断言的要点(仍是初步评审意见,最终以维护者审阅为准):上一条要求的 c7→c8 换 id 用例,建议用两条 type-ahead 消息构造、并断言两条都被 drain,而不要只断当前轮 settle——因为 stranded 队首的真实危害是 FIFO 挡死后继。 队列级实测(纯 Codex 内部换 id,无任何外部并发):M1/M2 排队,M1 的轮 c7→c8(3ms,c7 无终态,c8 完成),M2 随后正常完成:
机理是不同 id 的 start 在现有 |
|
已按增量评审补齐 v3:非 adopt 模式下,指纹不匹配的 scaffolding 记录不再立即回退;adopt 模式仍保持立即回退并合成本地轮。未佐证的 native ID 遇到不同 同时已同步最新 master,冲突解决保留了主干新增的 native command/CoT 解析和本 PR 的 lifecycle/native turn ID 事件。 验证:
|
|
补充一个 CI 说明(自动评审初步意见,最终以维护者审阅为准):当前唯一的 |
09dae51 to
bf52c9c
Compare
概要
task_started暴露为权威 bridge 生命周期事件,在延迟的response_itemuser 记录超过 20 秒归属 lease 前先保留 pending turn原因
Codex 可能先写入
task_started,再在 AGENTS/环境 scaffolding 后延迟数十秒甚至数分钟写入真实用户记录。若仍按普通 20 秒 attribution lease 处理,pending turn 会被提前清理,后续task_complete无法产生原始turn_terminal,过程卡会一直停在执行中。此外,Codex 可能在没有旧 ID terminal 的情况下以新 native turn ID 重试同一逻辑轮次。若未佐证认领继续绑定旧 ID,已完成的后继轮也会被 FIFO 队首阻塞。
影响面
验证
bun run test -- test/codex-transcript.test.ts test/codex-bridge-queue.test.ts(200 tests)bun run buildgit diff --checkCloses #1503