Skip to content

Avoid reparsing completed Chat Turns during App and Lark admission - #8316

Open
loopx-agent wants to merge 3 commits into
mainfrom
codex/lark-queue-terminal-observation-20261108
Open

loopx-agent wants to merge 3 commits into
mainfrom
codex/lark-queue-terminal-observation-20261108

Conversation

@loopx-agent

@loopx-agent loopx-agent commented Nov 7, 2026 •

Copy link
Copy Markdown
Collaborator

Goal And Delivered Outcome

Managed App submission and queued App/Lark admission scanned completed Turn bodies while holding the Session admission fence. Both use the same file observation of unchanged terminal Turns. A matching client ID still resolves the full current request for the existing replay checks. The managed planner still receives current prepared Turns. Bound App and Lark inputs use the same queue.

Target: main. Tested against 8a4d4f9dab17b01d6fe3546936155b4d718fc20d.

Author Declaration

  • Written by: OpenAI Codex.
  • Implemented against the File Chat discovery and managed/queued acceptance contracts in the base above.
Criterion Disposition Symbol / path Validation
Share unchanged terminal observations across managed admission, queued lookup and capacity checks. implemented ChatSessionStore.accept_managed_turn, ChatIngressStore._turn_discovery_rows Failing-before regression in each admission path and read counts below.
Recheck the exact full record for replay and preserve prepared input recovery. implemented Managed acceptance planner and ChatIngressStore.turn_for_client Conflicting request, pending/invalid file, lost acceptance receipt, and original reply regression tests.

Scope And Continuation

This change covers managed and queued admission in the file-backed store. Review and production adoption remain separate stages. The previous Windows run hit the shared loopx_turn_plan output-growth check (11,404 against 9,300). The refreshed head still needs hosted verification.

Validation

  • Tested revision: 33659aeaf5288a00a1c877b1b9eec9f9606426e9. Local validation finished with synthetic and public repository fixtures.
Check kind Result Evidence / limitation
static passed Ruff, standard premerge with 6 direct and 2 selected checks.
regression_parity passed Each baseline opens an unchanged historical body during the next admission. The candidate also returns the latest complete matching response and rejects conflicting App input.
integration passed 792 passed across admission, Session recovery, App HTTP bindings and Lark.
integration failed Additional native Steward managed-host suite: 52 passed and 12 failed. The exact earlier revision reproduces the same failing tests, including the Turn host route rejection.
real_entrypoint passed Ordinary project App HTTP with a fake native model. With 1,120 completed Turn files, warm history body reads 1120 → 0, warm HTTP admission median 454.9 → 397.5 ms, cold median 521.5 → 518.2 ms. A duplicate returned the same Turn and one original user/agent pair.
real_entrypoint passed Lark ingress through file-backed Core with synthetic endpoints. Warm history reads 1120 → 0, cold reads 2240 → 1120. Warm admission median 487.2 → 289.6 ms, with one verified terminal delivery per original source. A separate fixture read back bound App and Lark inputs in the same Session and verified the App took the shared queue.

The paired arms alternate in one process and swap the exact prior method. For App, that method comes from the previous queued fix integrated with the tested base. Cold means an empty discovery observer. The first cold batch measured App 450.4 → 533.2 ms and Lark 397.2 → 491.1 ms. The expanded cold batch measured App 521.5 → 518.2 ms and Lark 591.5 → 512.8 ms. Cold wall times varied between batches. Production tail latency and Windows CI remain separate.

Frontend / Visual Evidence

  • UI impact: none.

Type of Change

  • Bug fix
  • Test update

LoopX Area

  • Host or runtime integration

Shared-authority RFC fixture impact

N/A. File Chat admission only.

Boundary Checklist

  • Public-safe fixture results only.
  • Scoped to managed and queued Turn lookup.
  • No paired RFC changed.
  • UI impact is none.
  • DCO sign-off present.

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, gpt-6.1-sol, OpenAI, runtime_reported, reasoning_effort=max

Request changes conclusion (author-owned PR; GitHub blocks formal self-review)

[P2] 匹配记录的第二次读取失败会重复准入同一请求。 同一 client_turn_id 重试时,File Chat 的发现读取已经匹配原记录。只让随后重新打开该文件的一次 read_text 返回 EIO,已排队和已完成两种状态都从原来复用一个 Turn 变为创建第二个 Turn,并多写一条用户消息。

动机 / Motivation

使用稳定 client_turn_id 重试的 App 和 Lark 私聊队列依赖已接受的请求只创建一个 Turn。 用真实 File ChatStore 对照长历史排队、健康重放和匹配记录的单次 EIO。 热排队减少历史正文读取;正匹配后的读取失败会重复准入。 核对了 3 条变更路径和 File Chat 的调用链。运行时配置与 UI 没有变动。

改动思路 / Approach

复用同一终态观察供重放查找和容量使用;正文、附件、结果仍由真实记录和原重放校验读取。 复用原终态指纹、状态和准入锁,范围合适。首次完整读取已经完成时,第二次打开既增加 I/O,也给请求重放引入失败分支。 问题限定在 File Chat 已知匹配的重试。缓存收益和故障安全分别核验。

具体改动 / Changes

基线为 e58ba30bc949c29ec90c570a8362fb1e7ec9f3be。RFC 定义 client_turn_id、response-loss 重放、不同请求正文的拒绝及现有 File 观察边界。 基线规范

  • 长历史排队。 在相同的 320 条、每条 12 KiB 的已完成历史中,新消息每次排队读取的历史正文从冷路径 640 次降到 320 次,热路径五次均从 320 次降到 0 次。热路径中位数 43.29 → 25.07 ms。健康重试返回原 Turn 和最新响应,同 ID 不同正文仍被拒绝。
  • 重试身份。 同一 client_turn_id 重试时,File Chat 的发现读取已经匹配原记录。只让随后重新打开该文件的一次 read_text 返回 EIO,已排队和已完成两种状态都从原来复用一个 Turn 变为创建第二个 Turn,并多写一条用户消息。

关键代码讲解

旧版直接使用第一次成功读到的整条记录。新版在匹配后总是再次读取,_read_json 将这一轮 EIO 转成空对象,turn_for_client 返回 None,create_queued_turn 于是走分配新 Turn 和写 transcript 的分支。 匹配后重读 · 读错误处理 · 队列准入

对主干的风险 / Risks

前后对照保留了优化收益。已确认命中的请求在第二次 I/O 失败时仍需守住去重,尤其是用户重试已完成消息。

508 项 File Chat、原生 Steward 和 Lark 私聊相关测试通过,另完成长历史和四组同条件重放对照。 Quick premerge 的 6 项直接检查和 2 项选中检查通过。 DCO trailer 已核验。主干在评审期间合入 #8317,变动只涉及研究页面,与本 PR 无重叠,合并树检查通过。 基线第一次读成功,未触发第二次 I/O;当前 head 的第二次 I/O 才触发注入。两次试验都使用实际落盘记录和队列写入。 远端 CI 未取样。

语义与 CI 对齐

沿用现有客户端请求标识和终态集合。验收用例需覆盖已匹配后的暂时读取故障,并断言原请求的存储身份。

我的整体评价 / Verdict

直接使用本次已完整读取的匹配记录。缓存只交付终态元数据时,正匹配后的完整读取失败应返回可重试的不可用结果,阻止重复准入。补齐冷、热、queued 和 completed 的故障用例,并核对健康重试及新请求的长历史读取数。 当前证据限于隔离的 File Core 入口和本地检查。安装后的端到端行为和生产锁尾延迟仍需另行验证。

English verdict: REQUEST_CHANGES. A transient second read of an already-matched request admits a duplicate Turn for both queued and completed records. Keep the long-history optimization and preserve replay identity under I/O failure.

Comment thread loopx/chat_ingress.py
continue
# Replay validation needs the complete current record, including
# the original request body and the latest persisted result.
payload = _read_json(path)

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.

[P2] Preserve a matched request when the full read fails

同一 client_turn_id 重试时,File Chat 的发现读取已经匹配原记录。只让随后重新打开该文件的一次 read_text 返回 EIO,已排队和已完成两种状态都从原来复用一个 Turn 变为创建第二个 Turn,并多写一条用户消息。 旧版直接使用第一次成功读到的整条记录。新版在匹配后总是再次读取,_read_json 将这一轮 EIO 转成空对象,turn_for_client 返回 None,create_queued_turn 于是走分配新 Turn 和写 transcript 的分支。 直接使用本次已完整读取的匹配记录。缓存只交付终态元数据时,正匹配后的完整读取失败应返回可重试的不可用结果,阻止重复准入。补齐冷、热、queued 和 completed 的故障用例,并核对健康重试及新请求的长历史读取数。

…rk-queue-terminal-observation-20261108

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 changed the title Avoid reparsing completed Chat Turns during queue admission Avoid reparsing completed Chat Turns during App and Lark admission Nov 7, 2026

@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, gpt-6.1-sol, OpenAI, runtime_reported, reasoning_effort=max

Request changes conclusion (author-owned PR; GitHub blocks formal self-review)

[P2] 托管准入会在瞬时读故障后重新派发已完成请求。

动机 / Motivation

App 和 Lark 通过稳定的 client_turn_id 重试已接受的输入。重复创建会增加 transcript 并可重复触发上游工作。 用真实 File store 和普通项目 App HTTP 对照长历史排队、托管准入及已匹配后的单次读取故障。 缓存减少历史正文读取。新 head 的排队和托管入口在单次读故障后均可能重复执行。 核对了从当前 main 到新 head 的全部三条路径,也核对了上次评审之后增加的托管分支。改动落在 HTTP 背后的 File 准入。

改动思路 / Approach

排队、容量和托管使用同一 File 观察,原记录仍提供请求正文、附件和响应。控制面负责托管接受与重放决定。 共用已有终态观察器可以缩短准入锁内的历史读取。缓存只存指纹和状态,第二次读取的失败需要保留已确认的匹配身份。 范围合适。相邻整理应收敛两处正匹配后的读取边界,沿用当前 planner 和去重契约。

具体改动 / Changes

基线为 8a4d4f9dab17b01d6fe3546936155b4d718fc20d。RFC 将 client_turn_id 和 Turn 身份作为稳定重试、响应丢失恢复和不同请求正文校验的契约。 基线规范

  • 长历史准入。 同一组 320 条、每条 12 KiB 的终态历史中,五次热准入的历史正文读取在排队和托管入口均从 320 次降为 0 次。冷排队 640→320 次,冷托管保持 320 次。健康重试复用原 Turn 并读回更新后的响应,同 ID 改正文继续被拒绝。
  • 排队重放。 此前的排队问题仍可复现。隔离 File store 对 queued 和 completed 同 ID 重试均写出第二条 Turn,App HTTP 排队路径也再次派发了已完成请求。
  • 托管重放。 通过真实 App HTTP 重试一个已完成的请求,在准入内第二次读取其已匹配记录时注入一次 EIO。基线的排队请求复用原 Turn,托管请求返回 HTTP 400 并能在下一次健康重试复用原 Turn。新 head 的两个入口均返回 HTTP 202 和新 Turn,同 ID 记录 1→2、新增一条用户消息、上游 turn/start 1→2。

关键代码讲解

旧托管入口先把匹配完整记录交给 planner,第二次读失败发生在返回原记录时。新托管入口把这次读取移到 planner 之前,空对象被 continue,matching_turn 留空,已空闲 Session 遂准入新 Turn。排队路径同样把匹配后的空读当作缺失。 托管分支 · 已复现的排队发现

对主干的风险 / Risks

托管 Session 仍有活动 Turn 时,同一故障在两端都只保留一条记录。原 Turn 已完成并释放 Session 后,候选会重新准入。

相关测试基线 770 项、当前 head 772 项通过。另外运行了实际 File 和 HTTP 的故障对照。 Quick premerge 的 6 项直接检查和 2 项选中检查通过。 DCO 和当前主干合并树检查通过。 12 项 native Steward Turn Host 用例在两边报同样的失败,包括 route 拒绝、缺少 status 和验证未提交。受影响的 File Chat HTTP 准入已独立对照。 远端 CI 未取样。

语义与 CI 对齐

沿用原请求身份和终态集合。建议把单次匹配后读故障纳入现有 File 准入回归,并断言上游派发次数。

我的整体评价 / Verdict

让冷路径直接保留本次匹配时已经读取的完整记录。热缓存命中后需要读取完整记录,若暂时读不到,应沿现有可重试错误路径退出准入。用相同故障覆盖排队和托管路径,断言单一 Turn、原 transcript 和派发次数。 证据来自隔离的实际 File Core 和 App HTTP,模型由本地协议替身提供。Lark 相关用例覆盖路由和持久化,线上 Feishu、Windows 和尾延迟未测。

English verdict: REQUEST_CHANGES. A transient read failure after matching a completed request now creates and dispatches a duplicate through both App HTTP paths. Preserve replay identity while retaining the measured warm-read savings.

Comment thread loopx/chat_store.py
# The planner needs live prepared Turns and the full
# current request when its client ID matches.
if existing is None and turn.get("client_turn_id") == client_id:
turn = _read_json(path)

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.

[P2] Preserve a matched managed replay before planning admission

通过真实 App HTTP 重试一个已完成的请求,在准入内第二次读取其已匹配记录时注入一次 EIO。基线的排队请求复用原 Turn,托管请求返回 HTTP 400 并能在下一次健康重试复用原 Turn。新 head 的两个入口均返回 HTTP 202 和新 Turn,同 ID 记录 1→2、新增一条用户消息、上游 turn/start 1→2。 旧托管入口先把匹配完整记录交给 planner,第二次读失败发生在返回原记录时。新托管入口把这次读取移到 planner 之前,空对象被 continue,matching_turn 留空,已空闲 Session 遂准入新 Turn。排队路径同样把匹配后的空读当作缺失。 让冷路径直接保留本次匹配时已经读取的完整记录。热缓存命中后需要读取完整记录,若暂时读不到,应沿现有可重试错误路径退出准入。用相同故障覆盖排队和托管路径,断言单一 Turn、原 transcript 和派发次数。

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