Repository navigation
fix(chat): preserve native work across client resume and identity waits - #7690
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>
…on-lock-20261030 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.1-sol; OpenAI; runtime_reported; reasoning_effort=max
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机 / Motivation
使用原管家会话并依赖定时监控的用户。 服务重启后打开原会话,修改前会把仍在采集的监控误标为服务已重启;修改后保留原 Turn,待它自行完成。 另一个可复现故障是:身份服务读取缓慢时,后台监控长期持有新输入和授权修改共用的锁,用户无法及时发消息或暂停。身份读取等待期间仍可接收输入或修改授权;打开会话也不再终止仍在运行的原监控。 部署后的原服务采用和持续运行需要单独读回,本 PR 不把全部历史业务回复视为完成。 不实现新的账户策略、业务代办或未知失败 Turn 重放。
改动思路 / Approach
身份 IO 是外部观察,授权仍由既有 typed owner 在提交锁内决定;本地 worker 存活直接从原完成事件推导,无需第二套持久状态。 只修复共享输入锁内的身份 IO,以及无模型适配器时仍存活的原 worker 判断;不新增调度器、账户策略或业务重放。
现有 conversation_bindings.input_context 已采用先观察、后提交的顺序,本改动把同一边界用于 native submit、monitor commit、report launch/freeze 和 settlement recovery。观察前先读原请求,观察后在原锁内重读;如果其他请求已经被接收,就读回它,不再次派发。监控仍由原 idle pump 和 Core worker 执行。
| 场景 | 原行为 | 本次行为 |
|---|---|---|
| 身份 IO 等待时有输入或授权更改 | 共用锁被占用 | 原输入和修改可提交;最终授权检查决定是否继续 |
| 原监控无模型适配器时打开会话 | 活跃 Turn 被标记失败 | 仅当原完成事件仍存活时保留同一 Turn |
| worker 已退出、授权已撤销或效果未知 | 原恢复与拒绝路径 | 保持原路径,不把未知失败自动重放 |
该表是 exact head cbab43213ce4a72221e9e34919b3c62eb159237f 的源码解释,执行证据见下方测试;没有另行声明图形渲染验收。
具体改动 / Changes
6 个文件,+336/-90;新增测试 180 行。生产改动复用现有 request/recovery 算法,未增加状态表、CLI、schema、账户选择策略或第二消息消费者。chat_runtime.py 的模块行数上限 2320→2333,明确结算新增的共享生命周期判断;Any=37、dict=0 和默认限制不变。原上限失败保留,不能据此隐藏其他预算失败。
关键代码讲解
_has_live_turn_worker按同一 Session/Turn 的非终态和原完成事件判断本地 worker,缺少模型适配器本身不再被当作死亡证明。既有适配器存在时的 profile 迁移分支保留。resume_session先确认适配器健康或原 worker 存活,再交给既有prepare_managed_session_resume;HTTP 打开历史不会额外创建模型客户端或改写活跃操作。_prepare_submission/submit从原提交逻辑提取一个共享 routine,保留 request/client id、report admission recovery 和 unknown/no-replay 判断,在身份 IO 前后各执行一次,并比较请求身份。_admit在身份观察之后重读 Session 和精确 binding,再复用原bound_context与managed_turn.admittyped owner;排队输入、关闭、撤权和 native lease 仍是提交事实。_commit_poll把身份观察移出共享 fence,提交内仍比较实际采集 scope,pause/re-enable 或 scope 变化不能借用旧观察提交。
依据已发布契约 docs/product/periodic-reports.md,spec_revision 7c6fadd6fe20429468c979eec77ccb1445304dae:native-status-current-authority、native-status-user-priority、native-status-original-worker、native-status-no-unknown-replay 均 implemented,分别由当前授权 race、排队输入 race、三种 resume 入口及原 accepted/recovery 测试覆盖。这些是契约原有要求的审查锚点,不是新协议字段。
对主干的风险 / Risks
最强反例是移出身份 IO 后误用旧授权,或把已退出 worker 永久当成活跃。因此测试在实际 Core File/SQLite 后端阻塞身份读取,同时提交 queue、close、scope 或 pause;要求锁可用、最终拒绝、原 deadline/result hash 不被污染,且没有 native poll 或模型调用。另以原 HTTP resume 路由验证同一活跃 Turn 保留并正常完成,不能只测 helper。
PASS:原实现有 4 个持锁失败和 2 个丢失 active pointer 失败;修复后 16 个 focused case 通过,包含 HTTP/direct/adapter 和扩展 race。71 个 auth/profile/exited-worker 控制、124 个相邻 runtime 控制及 153 个完整 report case 提供补充覆盖;这些较广运行的源码边界在合入新主干时逐文件核对未变,新主干的 launch/report 依赖另做 exact-head 检查。PASS:最终 exact-head 标准 premerge 的 9 个检查全部通过;合入新主干后的 33 个 native 实际入口与 report/clock case 串行全部通过。此前同一 head 与 premerge 并行时有一例超过测试的 15 秒等待;原 Turn 随后在 19.3 秒正常 committed,独立 retained receipt 的 postcondition 为 passed;严格单例复核 13.27 秒通过,未改测试的基线 16.65 秒通过。没有放宽等待窗口或产品断言;这保留为测试等待预算对运行负载敏感的风险,不宣称已定位该波动的全部原因。最初 HTTP fixture 过早关闭其拥有的 controller 造成的失败保留,修正为先等待原 worker 完成,未放宽产品断言。
语义与 CI 对齐
复用既有 Session/Turn、typed authority 和恢复语义,不引入凭错误字符串判断业务结果、隐式授权或新的执行义务。身份准备仍不启用监控;用户 work 仍优先,未知效果仍保留。按当前 Goal policy wait_for_ci=false,未查询、等待远端 CI。本次不会声称已移除所有锁内 IO:native Todo 读取和已有 adapter 初始化的成本仍应按独立证据判断。
我的整体评价 / Verdict
没有发现阻塞性问题。该改动是有用且可回滚的 justified_increment:long_horizon 与 user_experience 均 improved,用户继续使用原会话,无需增加一次配置、确认或手动重放。变更仅涉及原监控、会话恢复及后端拒绝分支,没有修改页面布局或渲染内容;已检查 HTTP resume 调用链。 unverified_scope:变更的渲染内容为 none;部署采用另行验收。保留原请求与 receipt compatibility 有真实已接收操作作为依据;无需新增通用框架或另一套 worker 状态。身份 IO 是外部观察,授权仍由既有 typed owner 在提交锁内决定;本地 worker 存活直接从原完成事件推导,无需第二套持久状态。 只修复共享输入锁内的身份 IO,以及无模型适配器时仍存活的原 worker 判断;不新增调度器、账户策略或业务重放。
部署后的原服务采用和持续运行需要单独读回,本 PR 不把全部历史业务回复视为完成。 整体批准的是 exact head 的这两个已复现故障修复,不代表付费模型质量、全部历史业务回复、所有性能路径或尚未完成的生产安装已经通过。
English verdict: APPROVE cbab432; no blocking finding in the two reproduced native-lifecycle defects, local exact-head validation passed; runtime adoption remains a separate check.
A native steward watch can be running after a service restart before any model adapter is opened. Resuming that conversation treated the missing adapter as a lost server and failed the live work. Provider identity checks also held shared input/binding locks while waiting on IO.
Derive local worker liveness from its existing completion event, preserving the original Turn on resume. Observe provider identity and inspect watch leases outside publication fences, then re-read exact request, binding, Session, queue and recovery identity through the existing typed owner. Existing adapter profile changes and unknown-effect recovery remain intact.
Validation at
cbab43213ce4a72221e9e34919b3c62eb159237f:The existing original pump, HTTP conversation-resume and native report entrypoints are exercised. No screen, configuration, persisted flag, scheduler or account policy is added. The runtime module ceiling records only the necessary 13-line net lifecycle change; other budgets remain unchanged.