Repository navigation
fix(chat): retain steward admission across executor publication - #8614
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>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent GPT-6, OpenAI (self_reported)
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机 / Motivation
管家私聊的本人在执行器切换过程中发送普通消息。 旧主干在收到并核过该消息后把端点发布当成永久拒绝,用户要重新发送。当前头在原会话中完成同一条消息,原消息下只出现一次终答。 隔离 Lark/Core 入口已验证一次接收、一次执行和一次原消息回传。 本次覆盖新消息入场、当前授权和原会话关闭。历史失败回放、交办执行和真实服务部署遵循既有流程。 真实服务采用和下一条自然消息的最终回传及耗时仍需独立验收。
改动思路 / Approach
把过期端点的处理放在既有入场锁内,可以复用当前绑定、原会话和原请求,范围变动继续由 Core 拒绝。 仅处理同一私聊管家授权下的端点发布间隙,保持原入场及回传 owner。 原 Lark transport 将实际原消息交给 Core。Core 入场锁内核对绑定记录,只有授权字段全等且端点发生一次允许的切换时才保留唯一原 Session。之后通过原 Core 来源复核与 delivery-scope fence,沿现有队列入场。单靠放宽绑定相等条件会放过旧会话关闭,首头反例实际产生了同通道第二个 Session。
具体改动 / Changes
固定规格为 docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md @ 43b4699ccf2a2a11456f46b82da7102173e65e86。原授权复核和原会话关闭由入场层落地,原消息回传仍由既有 Lark worker 完成。
关键代码讲解
resolve_external_admission_source合并首次来源核验和变更后的再次核验。首次沿现有来源输入,竞争分支将同一原 Session 带给 Core,当前 scope 和原上下文均可据同一绑定核查。ensure_external_admission_scope在已确认绑定唯一变化为端点时从原通道读唯一可续 Session,先保存原请求的准备态及 Session,再进行可失败的 provider IO。二次发布或身份变化结束本次入场。ChatExternalConversations._admit_prepared沿用原 client identity 和已有 Close 保护。相同原请求反复对账不新建 Turn,不重复发送。回归用真实 transport/Core/Store 与合成 provider,检查关闭、旧历史以及原回传。
对主干的风险 / Risks
撤权、Goal 范围变化、第二次发布及关闭原 Session 均为零新 Turn。隔离中断后关闭同一 Session,旧 worker 继续读到同一拒绝。 相同的 11 个既有用例在固定主干与当前头均通过,覆盖双锁内核源、撤权、群聊、其他 App、Stop 和原暂挂。 标准 canary 为 6 直检加 2 选中检查通过,周边 Python 628 项与 TypeScript 63 项通过。周边三项失败及定时报表三项失败在精确主干与当前头成对复现,分别落在 discovery 读异常与 registry 激活 fixture。整仓本地运行在首头中途停止。Goal 采用本地验证,远端 CI 未查询。原服务采用和生产时延需独立验证。
语义与 CI 对齐
复用现有 prepared 响应码及原会话关闭约定。首次误拒和首头替换会话均保留反例,当前检查确认无新状态、额度或部署语义。
我的整体评价 / Verdict
当前精确头无阻断发现。把过期端点的处理放在既有入场锁内,可以复用当前绑定、原会话和原请求,范围变动继续由 Core 拒绝。 仅处理同一私聊管家授权下的端点发布间隙,保持原入场及回传 owner。 这保留了异常后继续核验原请求的能力,已授权时少一次用户重新发起。变更位于 Core 入场锁及消息日志,已检查 Lark 回传接口和原终答格式。 真实原服务采用和时延待验。真实服务采用、自然原消息和整仓 CI 未核验。三条宽测失败及三条定时报表失败在固定主干与当前头复现。
English verdict: APPROVE at fb6ea1d603915eaf1382a58f1c1bfac3fb0dce17. Matched Lark/Core fixtures verify original-session delivery and denial after Close. Live adoption and merge readiness remain open.
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 GPT-6, OpenAI (self_reported)
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机 / Motivation
受影响的是在执行器发布期间发送普通私聊的管家用户。 执行器发布可能发生在首次飞书读取和 Core 入场之间,原主干会拒绝已授权的消息。上一评审头在原消息暂不可读或正文被修改时都返回 durably_accepted。 执行器未变化的普通私聊只读一次正文。切换分支追加一次同原消息读取。 第二次飞书读取暂时不可用时,保留原请求和 Session,零新 Turn。原 worker 读回同一正文后,执行一次,原消息下独立读回一次终答。 第二次读取发现正文已改,原请求拒绝,零新 Turn,原会话历史与回传记录保持原样。 本次改动覆盖原消息入场、来源复核与原会话回传。原交办执行和历史请求另有既有流程。 线上采用、下一条自然消息的原路回传和时延尚待验。精确头周边三条失败在同一主干以相同签名复现,整仓运行未完成。
改动思路 / Approach
Core 保持原请求和授权,飞书适配器核验原消息内容,现有 worker 恢复原准备态。 当前改动限于同一已授权原私聊管家的执行器采用窗口。 Core 先在现有请求下固定原 Session,随后按新绑定复核。第一次读取已有飞书端的原来源与正文,收到新的执行器后才重取同一个消息 ID。当前来源可读且相同才允许进入原队列。
具体改动 / Changes
固定规格是 docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md @ 43b4699。
- 原授权复核和原会话关闭由 resolve_external_admission_source、ensure_external_admission_scope 及原队列约束处理。撤权、范围变化、再次发布、关闭及中断后关闭均维持零新 Turn。
- 原消息回传沿用 LarkPrivateConversations.reconcile_request。复现检查了原 Session、请求 ID、一次执行和原消息下的最终回传。
- 切换后复核原消息由 steward_source_preflight 调用现有 _source_message,核对消息类型、正文或附件描述、创建时间与回复关系。上一评审头 fb6ea1d 在缺失和已修改用例均错误受理。新头的同输入覆盖暂挂恢复、正文已变拒绝及普通路径单次读取。
对主干的风险 / Risks
精确头通过 12 个重点 Python 用例、671 个周边 Python 用例、63 个 TypeScript 用例,以及标准 canary 的 6 项直检和 10 项选中检查。Ruff、mypy、RFC 双语与公开边界检查通过。周边三项失败在同一主干复现相同签名,涉及 discovery 读异常与 registry 激活夹具。上一评审头整仓运行中途停止。Goal 使用本地验证,远端 CI 未查询。
飞书回传验证使用真实适配器、Core 和原 worker,飞书及 native provider 由夹具模拟。单次读取的回归用例验证了普通路径的调用次数,线上端到端耗时另行测量。
我的整体评价 / Verdict
当前整条 PR 的精确头无阻断发现。修复处理了同授权的执行器切换,保留原会话与原消息的恢复路径。附加读取仅发生在切换时。线上采用与自然消息时延仍需独立验收。
English verdict: APPROVE at 43bd8bd. Exact-head Lark/Core fixtures verify original-session recovery, rejection of changed input and one source read for ordinary admission. Live adoption and natural-message timing remain unverified.
Goal And Delivered Outcome
A Steward message can reach the delivery-scope fence just as the same owner binding publishes its adopted executor. The previous admission path records a permanent rejection before a Turn exists. The exact main revision returns
command_rejectedin the new synthetic Lark fixture.The same message now records the original Session before revalidating its current source once. A Close during that revalidation ends the request with zero Turns and preserves the original Session. The first PR head admitted that same input into a replacement Session. The passing fixture checks one Turn in the original Session, one terminal reply verified against the original message, and an idempotent subsequent delivery pass. A follow-up review reproduced a gap in source verification on the former PR head. When the original message became unavailable or its body changed at publication, that head still admitted the earlier body. The Lark adapter now rereads the same provider message when Core observes an executor change. A missing source keeps the prepared request for the existing worker. Changed content produces a rejection with zero new Turns.
Author Declaration
43b4699ccf2a2a11456f46b82da7102173e65e86ensure_external_admission_scopeandChatExternalConversations._admit_preparedresolve_external_admission_sourceand the existing delivery-scope fence| Verify the original provider message after an executor change | implemented |
steward_source_preflight| Missing source holds the original request until it is readable, edited source rejects, and ordinary input uses one read |Scope And Continuation
The refresh applies to an ordinary private owner Steward message during an Antigravity/Codex endpoint change. The binding record must otherwise match. The current source, channel, context, and pinned Session must verify. A stable ordinary path uses one message read. The existing prepared-request state retains the original Session across interrupted verification. Commands, frozen Agent targets, prior requests, and existing delivery rules follow their current contracts. Managed service adoption and live traffic verification are separate acceptance steps.
Validation
43bd8bd8c009cfe5afe2caa00c71534390b158abregression_paritypassedreal_entrypointpassedunitpassedstaticpassedunitfailedreal_backendnot_runFrontend / Visual Evidence
UI impact is none.
Type of Change
LoopX Area
Checklist