Skip to content

fix(codex): 保留 user 延迟落盘时的 turn 归属 - #1533

Merged
deepcoldy merged 1 commit into
deepcoldy:masterfrom
kunshanyep-beep:fix/codex-late-user-terminal
Sep 29, 2026
Merged

deepcoldy merged 1 commit into
deepcoldy:masterfrom
kunshanyep-beep:fix/codex-late-user-terminal

Conversation

@kunshanyep-beep

@kunshanyep-beep kunshanyep-beep commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

概要

  • 将 Codex task_started 暴露为权威 bridge 生命周期事件,在延迟的 response_item user 记录超过 20 秒归属 lease 前先保留 pending turn
  • 将 task-start 认领保持为可撤销的推测状态,直到匹配的用户指纹记录完成佐证
  • 非 adopt 模式下,AGENTS/环境 scaffolding 等不匹配 user 记录不再立即回退;释放仍受精确 terminal、distinct native start 和 10 分钟佐证上界约束
  • adopt 模式继续在不匹配 user 到达时回退推测认领并合成本地轮
  • 当 Codex 放弃一个 native turn ID 并立刻换 ID 重试时,由新 start supersede 未佐证认领并重新认领同一队首
  • 在 terminal/abort 事件中保留 native turn ID,确保终态只路由到精确匹配的轮次

原因

Codex 可能先写入 task_started,再在 AGENTS/环境 scaffolding 后延迟数十秒甚至数分钟写入真实用户记录。若仍按普通 20 秒 attribution lease 处理,pending turn 会被提前清理,后续 task_complete 无法产生原始 turn_terminal,过程卡会一直停在执行中。

此外,Codex 可能在没有旧 ID terminal 的情况下以新 native turn ID 重试同一逻辑轮次。若未佐证认领继续绑定旧 ID,已完成的后继轮也会被 FIFO 队首阻塞。

影响面

  • 仅影响 Codex structured transcript / bridge queue 的轮次归属
  • 覆盖非 adopt、adopt、本地输入、type-ahead 与 terminal/abort 路由
  • 未修改其它 CLI 的 transcript 或 bridge 实现

验证

  • bun run test -- test/codex-transcript.test.ts test/codex-bridge-queue.test.ts(200 tests)
  • 12 个相关 lifecycle/transcript 测试文件(503 tests)
  • bun run build
  • git diff --check

Closes #1503

@deepcoldy

Copy link
Copy Markdown
Owner

你好,这个 PR 的自动评审群已建好,麻烦点击下面的链接加入飞书群,评审结论会同步在群里(链接一年有效):
https://applink.larkoffice.com/client/chat/chatter/add_by_link?link_token=741jd2aa-f064-4c7c-9cf3-d921a139d817

(本次自动拉群遇到凭证临时故障,没能直接把你拉进群,抱歉;这是自动流程,最终评审结论以维护者审阅为准。)

@deepcoldy

Copy link
Copy Markdown
Owner

初步评审意见(自动评审辅助生成,最终以维护者审阅为准):

修 #1503 的方向和 parser 侧改动(把 task_started 解析为权威生命周期边沿、terminal 携带 turn_id)都认可,本机数据也支持这个修复的价值:1210 个 Lark 轮里 task_started → 对应指纹 user 记录的延迟 p50≈1.5s / p90≈19.4s / p95≈27.8s,约 7.5%(90 轮)超过 20s 归属 lease。但队列侧「认领队首」目前没有指纹归属校验,引入了两类真实的跨轮次误归属,建议补守卫后再合。

1.(阻断)非 adopt:非 Lark 输入的 task_started 会冒领 pending 的 Lark 轮

turn_started 分支只按 !started + 5s 新鲜窗认领队首,而认领发生在 user 记录落盘之前,指纹还来不及参与。非 adopt 下,owner 从 web 终端手输、或 /compact 等 passthrough(走 raw_input/deliverRawInput,不建 bridge mark)与一条 Lark 消息竞态时,前者的原生轮会把 Lark mark 认走。队列级最小复现(相对 mark 时刻):

  1. mark('lark-A', 'LARK prompt', 10000)
  2. web/passthrough 轮先提交:task_started(T-WEB) @10100 → lark-A 被置 started
  3. user 'WEB prompt' @10200(非 adopt 不合成 local 轮,指纹不匹配被缓冲)
  4. task_complete(T-WEB, 'WEB answer') @12000 → 按 id 精确关到 lark-A → 飞书在 lark-A 下收到 "WEB answer"
  5. 真正在 type-ahead 里排队的 Lark 轮随后 user 'LARK prompt' @12500、task_complete(T-LARK, 'LARK answer') @14000 时,队列里已无对应 turn,LARK answer 丢失。

基线(master)上该序列结果正确:web 轮被忽略、lark-A 由自己的 user 记录认领并收到 LARK answer。

2.(阻断)adopt:iTerm 的 task_started 提前认领后,迟到的 user 会 HOL-drop 掉 Lark mark

adopt 下序列相同:iTerm 轮的 task_started 先认领队首,迟到的 iTerm user 记录在「佐证」分支指纹不匹配后继续下走,willSynthLocal 命中 HOL-drop,把已认领的 Lark mark 直接删掉;随后真正的 Lark 轮只能以新合成的本地轮收尾,lark-A 不再 settle。基线行为是 iTerm user 先到 → 合成 local 轮插在未 start 的 Lark mark 之前,两者互不干扰,是对的。

3.(应修)给 id-less 收集中轮次补绑 id 时缺时间序守卫

turn_started 的 active-collecting 分支对「靠 user 记录先 started、尚无 sourceTurnId」的轮次会无条件补绑 id(codex 的 user 事件本身不带 turn_id,这其实是常态而非罕见)。一旦绑错(自身 task_started 因 attach/rollout 轮换/时钟偏差漏吃,随后吃到别的轮次或跨 session 的 start),targetForNativeEvent 的 fallback 会因 fallback.sourceTurnId 已存在直接返回 null,该轮真实 terminal 被丢弃;而 started 轮永不被 pre-start prune,进程不重启就永久 blocking(过程卡停在执行中,正是 #1503 的症状形状)。建议至少加上与 targetForNativeEvent 一致的 transcriptStartTimeMs 时序条件。

建议的修法方向(供参考,不限制具体实现)

把 task_started 认领做成「可撤销的推测认领」,在指纹 user 落盘前(transcriptStartTimeMs 未设)保持可回退:

  • 指纹 user 到达且匹配 → 现状的佐证路径;
  • 指纹 user 不匹配 → 回退认领(恢复 unstarted、重锚 attribution lease、清 collecting),让该 user 重走既有路径:非 adopt 忽略/缓冲,adopt 合成 local 轮并保持插在 Lark mark 之前——基线语义由此恢复;
  • 佐证完成前到达的 terminal(task_complete/turn_aborted)不直接关闭 Lark mark,先缓冲,待指纹落盘后再决定归属(codex transcript 里 user 记录先于 terminal,这是有界的);
  • 若整轮只有 start + abort、user 始终不来,按既有 ambiguous/超时路径处理,不污染 Lark 轮;
  • active-collecting 分支补时间序守卫(第 3 点)。

测试建议覆盖:非 adopt 非 Lark start 冒领 + 真 Lark 轮不丢、adopt iTerm start + 迟到 user 不误删 Lark mark、回退后下一个真 Lark task_started 能正确认领、claim 后 user 不来直接 abort 的收尾。

再次说明以上为自动评审的初步意见,最终以维护者审阅为准,感谢修复!

@deepcoldy

Copy link
Copy Markdown
Owner

补充一点对上一条修法建议的边界要求(仍是初步评审意见,最终以维护者审阅为准):

「佐证完成前的 terminal 先缓冲」必须带明确的释放上界,不能只靠"指纹 user 总会落盘"这个假设——实测 task_started → 指纹 user 的延迟长尾可达数百秒,且 rollout 轮换/写入失败时该记录可能永远不来。若缓冲无界,等于把本 issue 的"过程卡停在执行中"从「user 迟到」原样搬到「terminal 被缓冲」。建议释放路径至少覆盖两种形状:

  1. 该 native turn 的 terminal(task_complete/turn_aborted)到达时,指纹 user 仍未匹配:这是该轮已结束的硬证据,不应再无限等待。应回退推测认领(Lark mark 恢复 unstarted、重锚 attribution lease、清 collecting),terminal 不允许关闭/settle 这个 Lark mark——非 adopt 下该 terminal 按既有 unmatched 路径丢弃(它不是 Lark 轮的产出),adopt 下交给本地轮路径;被回退的 Lark mark 仍由现有 20s lease prune / 后续真 task_started 重新认领。
  2. task_started 认领后既无指纹 user、也无 terminal(CLI 僵死/记录缺失):回退后的 Lark mark 必须重新受现有 attribution lease 约束,即推测认领不能让一个未经指纹证实的轮永久豁免 pre-start prune;需要保留 lease 计时或在认领时另设一个有界的"佐证等待"超时。

另外建议补的回归用例再加两条:指纹 user 始终不来、terminal 先到达时 Lark mark 被回退且不 settle;回退后缓冲的 foreign terminal 不会在 Lark 话题产出回复。

@deepcoldy

Copy link
Copy Markdown
Owner

再补两条实现精度(仍是初步评审意见,最终以维护者审阅为准):

  1. 形状 1 的回退触发必须按绑定时记录的那个 native turn id 判定:只有当 terminal 的 sourceTurnId 与推测认领已绑定的 sourceTurnId 相同(且 session 兼容)才触发回退;不能写成「推测态期间收到任意 terminal 就回退」——一条陈旧/重放的、属于其它轮的 terminal 不能把还活着的推测认领误回退。这与现有 targetForNativeEvent 的精确 id 路由是同一把尺子(已关闭轮的重放仍由现有 closed-turn 墓碑 / seen 去重在入口先行拦截,二者不冲突)。

  2. 请显式补一条反向形状的回归:绑定 id 的 task_started 之后指纹 user 始终缺失、但该 id 的 terminal 正常落盘 → 回退推测认领,该 terminal 按 id 路由不到任何 started 轮、Lark 侧零产出(与既有 unmatched terminal 语义一致);若 type-ahead 里还排着真正的 Lark 轮,其后续 task_started 仍应能正常认领队首。这条与「foreign terminal 冒领」在 id 层面不可区分,必须用测试钉死「不产出」,不能依赖实现巧合。

@deepcoldy

Copy link
Copy Markdown
Owner

续上一条,补一个容易被写漏的实现约束(仍是初步评审意见,最终以维护者审阅为准):

回退推测认领时,除了把 started 翻回 false,必须重新锚定 lease——把 unconfirmedAttributionStartedAtMs(若曾确认则 submitConfirmedAtMs)重写为当前时间,并清掉已绑定的 sourceTurnId/sourceSessionId。原因是推测认领在 turn_started 分支里会把 unconfirmedAttributionStartedAtMs 清成 undefined;如果回退只翻 started=false,pruneExpiredPreStartHeads 会在 leaseStartedAtMs === undefined 处直接 break——该 mark 既不会被 prune,又作为未 start 的 FIFO 队首挡住后续所有已完成轮次的 drainEmittable,变成永久僵尸队首(比 #1503 还糟:连 20s lease 的存量兜底都没了)。

请把这条做成回归断言(而不是只靠代码评审):

  1. mark → task_started 推测认领 → 指纹 user 不匹配触发回退;
  2. 时间推进超过 attribution grace(20s);
  3. 断言该 mark 能被 pruneExpiredPreStartHeads 清掉、队列不残留;
  4. 反向变异:删掉重锚那一行,该用例必须转红。

@deepcoldy

Copy link
Copy Markdown
Owner

补充上一条「回退」的重置清单:除 started=false、清绑定的 sourceTurnId/sourceSessionId、重锚 lease 外,还必须把 collecting 指针清空(当它指向被回退的轮时)。否则回退后、mark 被 prune 前的窗口内,后续 terminal 会经 targetForNativeEvent 误落到这个未 start 的 mark 上——已在现有队列上实测两种形状:

  • 无 id terminal(共享队列的其它 producer):命中 if (!ev.sourceTurnId) return this.collecting,foreign final 直接写入;
  • 带外来 id 的 terminal:exact 匹配因轮未 start 落空后,fallback 到无 id 的 stale collecting 同样写入。

清掉 collecting 后两种 foreign terminal 均不落该 mark。回归断言请加一条:回退后灌入 foreign terminal(无 id 和外来 id 各一),被回退轮的 finalText 必须保持 undefined。至此回退的完整重置为四件:started、绑定 id/session、collecting、lease 锚点。

@kunshanyep-beep

Copy link
Copy Markdown
Contributor Author

已按评审意见补齐队列侧守卫:

  • task_started 现在只做可撤销的推测认领;指纹 user 匹配后才转为已佐证状态
  • 新鲜但不匹配的 user 会完整回退 started、native id/session、collecting,并重锚 confirmed/unconfirmed lease
  • 只有相同 native turn id 且 session 兼容的 terminal 才触发回退;terminal 不会 settle Lark mark
  • 推测认领增加 10 分钟佐证上界,超时回退后继续受原有 attribution lease 约束
  • id-less collecting turn 补充 transcriptStartTimeMs 时间序守卫
  • foreign/no-id terminal 在回退窗口内不会写入该 mark

新增覆盖非 adopt web 输入、adopt iTerm 输入、task_complete/abort 先到、foreign terminal、超时释放、confirmed/unconfirmed lease 重锚和 stale task_started 绑定。

验证:

  • focused transcript/queue suites: 183 tests
  • related lifecycle suites: 153 tests
  • bun run build
  • git diff --check

@deepcoldy

Copy link
Copy Markdown
Owner

增量复审意见(自动评审辅助生成,最终以维护者审阅为准):

回退机制整体实现得很扎实——两轮提的阻断/应修都收掉了:非 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/环境注入作为独立的 role:user input_text 记录写在真实用户消息之前(同属这一轮 native turn,内容如 # AGENTS.md instructions ...)。当前实现里,推测认领中的轮次只要收到一条新鲜但指纹不匹配的 user 记录就立即回退;而在非 adopt 会话中,不匹配的 user 记录并不能开启一个竞争轮(本地轮合成是关闭的),所以它不能证明这次 task_started 认领错了。

按 worker 真实的 1s prune 心跳,#1503 报告人的时序在本版上仍会复现:

  1. mark('A','prompt') t=0;task_started(TA) t=0.1s → 推测认领;
  2. AGENTS 注入记录 t=0.5s(指纹不匹配)→ 立即回退,lease 重锚到 0.5s;
  3. ticker 在 t≈20.5s prune 掉 unstarted 的 A;
  4. 真实指纹 user t=100s、task_complete(TA) t=144s 到达时队列已空 → terminal 丢失、过程卡仍停在执行中。

(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:

  • 非 adopt:不匹配的新鲜 user 记录维持推测认领,照旧进 unmatched 缓冲;释放只走已实现的两条有界路径——绑定 id 的 terminal 到达(web/passthrough 竞争轮照样在它完成时被精确回退,R1 终局不变)或 10 分钟佐证超时;
  • adopt:不匹配的新鲜 user 会合成真实竞争本地轮,保持现在的立即回退 + synth local。

我在现有代码上做了这个一行判定的原型(if (!collectingTooOld && this.localTurnsEnabled) rollback…):上面 100s 序列探针转绿;adopt 合成、abort-only、双排队串行、cot 归属、你们已有的 R1/R2 终局断言全部仍成立;受影响的只有 3 个用例里「foreign user 后立即 started=false」的中间态断言(回退时机从 user 不匹配推迟到该 native 轮 terminal),把断言点后移即可;另建议把那两个「不匹配即重锚 lease」的用例相应改成「terminal/超时后重锚」。

一个小提醒(不阻断)

10 分钟佐证常量对本机观测 max 587.9s 的余量只有约 2%。维持定值可以,但值得在注释里写明它是按实测 p-max 取的有界上界、而不是协议保证,日后若遇到更长尾可再调。

再次说明以上为自动评审初步意见,最终以维护者审阅为准。

@deepcoldy

Copy link
Copy Markdown
Owner

续上一条增量评审(自动评审辅助生成,最终以维护者审阅为准):上一条建议的「mismatch 回退限定 adopt」单独使用会把最初的误归属问题带回来,这里给出修正后的完整修法,麻烦以此条为准。

为什么单独「限定 adopt」不够

非 adopt 推迟 mismatch 回退后,provisional 认领一直绑着先到的 native id;若随后出现另一个确切的 native start(不同 turn_id),现有代码在 id 不等时直接落空(队首已 started,找不到未 start 的轮),新 start 被丢弃;之后指纹 user 的"佐证"只补字段、不换绑,先到那轮的 terminal 再按 id 精确落回 Lark mark → 飞书仍收到错误回复。队列级四版本对照(按 worker 1s prune 心跳):

形状 master 本版 v2 仅 adopt 限定 adopt 限定 + 下方 supersede
AGENTS 早到、指纹 user 迟到 100s(#1503) 丢 丢 ✅ ✅
web 轮完整跑完后 Lark 轮才 start(串行) 错/丢 ✅ ✅ ✅
两个 native start 交错(先到轮的 terminal 后到) 发错回复 ✅ 发错回复 ✅
先到 start 无 user 无终态,真 Lark 轮完成 — 卡 10min 卡 10min ✅

建议的完整修法(两件,均已在队列上原型验证)

  1. mismatch user 的立即回退限定在 adopt(上一条):非 adopt 下不匹配 user 不构成竞争轮证据,provisional 继续等。
  2. 新增 distinct-native-start supersede(所有模式生效):turn_started 分支里,当 active 已绑定不同 sourceTurnId、且 active 仍处 provisional(transcriptStartTimeMs 未设)时,先调用已实现的 rollbackProvisionalTaskStart(active),然后继续走下面的认领(回退后队首恢复 unstarted,会被同一个新 start 重新认领,天然复用现有 tooOld/5s 新鲜窗);已完成指纹佐证(非 provisional)的轮不参与,保持现状。

第 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 个变红):

  • rolls back a foreign task_started claim so the real Lark turn still settles
  • re-anchors the lease after a fingerprint mismatch and lets the mark expire
  • re-anchors the confirmed lease when a provisional claim rolls back

请把断言点从「mismatch user 后」后移到回退真正发生的边沿——绑定 id 的 terminal 到达或distinct native start 到达;并新增:(a) 非 adopt mismatch 不回退、provisional 保留;(b) distinct start supersede(含"旧 id 无终态、新 id 完成"的真实形状);(c) 上一条的 AGENTS 100s 序列。

采用组合修法后,上述四形状全部正确,除上述 3 个待改用例外,本地 18 个相邻套件 612 测试保持全绿。再次说明为自动评审初步意见,最终以维护者审阅为准。

@deepcoldy

Copy link
Copy Markdown
Owner

补充一个严重度定级(自动评审初步意见,最终以维护者审阅为准):上一条表格里的「distinct-native-start supersede」不只是修外部竞态,它同时修掉一条本 PR 相对 master 引入的真实回归,建议按必修看待。

用真实 rollout 序列(2026-03-27 实样,两个 task_started 相隔 3ms:c7@…507 → c8@…510,c7 全文件无终态,唯一 task_complete 属于 c8)直接喂队列:

  • master:✅ 正确 settle(master 不消费 task_started,指纹 user 正常认领、c8 的 terminal 正常收尾);
  • 本 PR 第一提交 648f6f5:❌ 楔住(无条件认领绑死被放弃的 c7,c8 terminal 按 id 路由不上);
  • 当前 v2:❌ 仍楔住(佐证后依旧绑 c7,unresolved=1,过程卡永久执行中)。

即该回归由本 PR 引入、并非存量问题。该形状不依赖任何外部并发:Codex 自身重试/换 native turn 就会产生,本机 2011 个会话里 21 次(2026-03~08),另有 45 个会话以未关闭 start 结束。因此上一条建议的两件修法中,第 2 件(provisional 态遇 distinct native start 先回退再重新认领)是恢复 master 既有正确性所必需;第 1 件(mismatch 回退限定 adopt)解决 #1503 的存量缺口。两者建议一并包含,并请用上面 c7→c8 的真实序列加一条回归(master 绿、当前红、修复后绿)。

@deepcoldy

Copy link
Copy Markdown
Owner

再补一个 v3 回归断言的要点(仍是初步评审意见,最终以维护者审阅为准):上一条要求的 c7→c8 换 id 用例,建议用两条 type-ahead 消息构造、并断言两条都被 drain,而不要只断当前轮 settle——因为 stranded 队首的真实危害是 FIFO 挡死后继。

队列级实测(纯 Codex 内部换 id,无任何外部并发):M1/M2 排队,M1 的轮 c7→c8(3ms,c7 无终态,c8 完成),M2 随后正常完成:

  • master:drain = [M1:ONE, M2:TWO];
  • 当前 v2:drain = []——M1 绑死 c7 卡在队首(provisional),M2 虽已 started 且有 final 却发不出来;
  • 采用上一条两件修法后:drain = [M1:ONE, M2:TWO]。

机理是不同 id 的 start 在现有 turn_started 分支 id 不等时落空后,会 fall-through 误认领下一个未 started 的排队轮,后续指纹/终态连环错位。真实数据支持它会打到后继:21 次 abandoned-start 的后继 id 21/21 都有 terminal(后继轮确实完成),其中 18/21 后继 start 之后还有新的 user turn(后面还排着更多轮)。所以该用例请断言 drainEmittable() 按序产出 M1、M2 两条,且队列清空;只断 M1 settle 挡不住这个 FIFO 回归。

@kunshanyep-beep

Copy link
Copy Markdown
Contributor Author

已按增量评审补齐 v3:非 adopt 模式下,指纹不匹配的 scaffolding 记录不再立即回退;adopt 模式仍保持立即回退并合成本地轮。未佐证的 native ID 遇到不同 task_started 时会被 supersede,并由新 ID 重新认领同一队首。新增了 100 秒 scaffolding 延迟和 c7→c8 双 type-ahead 顺序 drain 回归。

同时已同步最新 master,冲突解决保留了主干新增的 native command/CoT 解析和本 PR 的 lifecycle/native turn ID 事件。

验证:

  • parser/queue:200 tests
  • 相关 12 个 lifecycle/transcript 套件:503 tests
  • bun run build
  • git diff --check

@deepcoldy

Copy link
Copy Markdown
Owner

补充一个 CI 说明(自动评审初步意见,最终以维护者审阅为准):当前唯一的 bun-test 红腿与本 PR 无关——失败是 test/sandbox.test.ts 两条 EACCES ... rm .../sbx-tmux-*,而本分支的合并基线尚未包含主干上的 sandbox 非 root 清理修复(#1552,合入 9687979,同时改了 src/adapters/backend/sandbox.ts 与该测试)。最新 master tip 的 bun-test 为绿;在已包含 #1552 的基线上本地用 bun 跑 test/sandbox.test.ts 37/37 通过,与本 PR 改动的四个文件零交集。rebase(或合并)最新 master 后该腿即可转绿,不需要为本 PR 改代码。

@deepcoldy
deepcoldy force-pushed the fix/codex-late-user-terminal branch from 09dae51 to bf52c9c Compare September 29, 2026 07:36
@deepcoldy
deepcoldy merged commit 706142a into deepcoldy:master Sep 29, 2026
17 of 18 checks passed
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.

bug(codex): transcript user 延迟超过归属期限后丢失 terminal,过程卡停在执行中

2 participants