Repository navigation
fix(chat): keep recovery discovery free of provider identity IO - #6907
Conversation
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; effort=max; active_turn_verified=false
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机
受影响的是私聊 Bot 的用户:旧失败请求较多、身份接口变慢时,其他原消息的回复也要等待扫描。一次历史失败的发现会等待网络身份核验;多条旧记录串行累积,原 Bot 的回传被整轮扫描拖住。修改后先用本地规范状态发现候选,再在真正受理时核验权限和来源。发现阶段不再调用 provider 身份接口,原有执行与回传门禁继续生效。本 PR 不放宽执行资格、授权、原生失败凭证或业务完成条件,不新增消费者、模型调用或调度。线上整轮扫描与剩余原消息的自动回传仍需在部署后独立验收;单条发现计时不能代表整体回复 SLA。此前合成身份接口很快,功能测试通过也无法暴露这种共享等待;这次用相同的真实只读输入分离了发现成本与执行授权。
改动思路
保留原扫描器和 TypeScript 候选规划器,只把发现阶段的输入换成本地已启用绑定。候选是“值得继续核验”的提示,之后仍由原 worker 在原请求与来源 fence 内核验当前 App、本人、grant、原消息和原生失败清单,再决定是否预留与排队。直接缓存已核验权限会引入过期授权;另起 worker 或复制筛选规则会增加第二套拥有者,均不如在既有边界去掉不必要 IO。
发现是派生的队列提示;当前权限与确切来源仍由原受理拥有者在产生效果前重新核验。本 PR 只去除共享发现循环中的网络身份 IO,不优化或绕过实际受理和发送前的核验。本地绑定变旧只可能产生多余提示,实际受理必须重新拒绝失效权限,不能把提示解释为已获得执行许可。
具体改动
独立规范依据是 docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md,修订 d4bb60c98c01ab840c5f971e3ca06e778b94a129,已先读修改前的现有 worker 与失败续办约定。canonical-worker 仍使用原扫描器、规划器和队列;fresh-admission-authority 保留实际受理前的全部当前身份与来源/原生凭证核验;original-result-integrity 不改变原失败、原消息和业务完成判定。三项在当前提交实现;新增双语段落只解释边界,不被用作自证规范。
关键代码讲解
_context_recovery_plan新增私有输入选择参数,发现时读取本地已启用绑定,缺失或禁用即没有候选;实际操作仍默认调用原有bindings.resolve。两条输入进入同一个 typed 规划器,没有复刻执行策略。context_recovery_candidate是唯一开启发现模式的调用点,仍只返回既有候选布尔值,不保存状态、不提供原生/来源核验凭证,也不排队执行。recover_failed_request不开启发现模式。原请求锁、来源 fence、当前权限、确切原生失败与原消息核验仍在预留、入队之前。新反例让身份变为不可用,确认它在读取原消息前就拒绝,原 Turn 和消息数不变。
四个文件59增/4删,其中生产代码14增/4删、测试36行、双语说明9行。没有新增兼容状态、快照缓存、CLI、角色或调度,保留一份规范状态和一个执行决定拥有者。
对主干的风险
最强风险是把本地启用状态误当当前许可,尤其是在发现后权限失效时。本次只改变内部提示的可得性:旧实现身份超时会把提示压成 false;新实现可以先给出 true,但实际受理仍须重新核验并拒绝。新增用例明确区分这两个结果,不能仅凭候选字段证明任何工作完成。缺失、禁用或已关闭会话继续保留原来的拒绝路径。
73项相关源测试和31项安装包测试通过;完整当前提交另有6个直接检查、11个仓库检查通过,Ruff与配置的17文件 mypy 通过。安装包关键生产模块与源码逐字节相同。不可变基线的两个可用发现用例会触发禁止 provider IO 的断言,另两个缺失/关闭路径保持通过;早期预计失败数量包含已关闭会话,已按实际证据修正并保留原记录,没有改变断言。既有15个扫描器场景继续覆盖授权撤回、来源变化、原生效果、原生 Goal、上下文版本和中断恢复。
同一克隆输入、解释器与规划器的三次普通发现计时为:修改前30.014、16.381、11.211秒,修改后0.0859、0.0211、0.0195秒。首次身份超时返回 false 的记录完整保留;另一次独立墙钟采样把主要等待定位在身份子进程。没有把采样耗时冒充基线,也不推断子进程 CPU、总体回复时延或 p95。按当前矩阵不查询或等待 GitHub CI。
语义与 CI 对齐
继续复用 candidate/eligible 的既有区别,发现是派生提示、受理是经核验的效果边界;私有 discovery_only 不能由 HTTP 提交为权限。词汇检查和语义 canary 通过,没有新增全局状态或义务协议。
我的整体评价
未发现阻塞项,结论 APPROVE,范围为 0d470c8201d0661b7c8612d8e9589d9472759fe1。长期执行(long_horizon)改善在于历史失败不再把共享发现串成网络等待;用户体验(user_experience)改善在于其他原消息可更及时进入既有回传流程,同时失效身份仍不能执行。这是一项完整且适度的发现层增量,不靠第二套策略或维护者手工代办。真实安装后整轮发现和 provider 回传仍须继续验收;实际受理和发送仍可能受身份服务延迟影响,不宣称本次已满足整个 Bot SLA。
English verdict: APPROVE for 0d470c8201d0661b7c8612d8e9589d9472759fe1. The existing typed candidate planner now uses local canonical input during discovery, while actual admission retains fresh authority, source and native proof. Controlled timings and source/package guards support the bounded fix; live full-scan/reply latency remains separate.
Recovery discovery called fresh provider identity verification for each historical failure before the reply worker could use the scan result. A slow or unavailable identity read therefore delayed unrelated Bot replies and cleanup.
Use the local enabled binding with the same typed Core candidate planner during discovery. This remains a provisional queue hint: actual admission still resolves current App/owner/grant, exact original source and native failure proof under the existing fences before enqueue. No model, message, scheduler or permission policy is added.
Validation: 73 relevant source tests pass, including a provider-IO-forbidden discovery test and unavailable-authority admission rejection. One unchanged private read-only fixture took 11.2–30.0 seconds before and 0.019–0.086 seconds after across three ordinary samples; one earlier identity timeout is retained. A separate wall-time profile locates the wait in identity subprocess IO. This is discovery evidence, not an end-to-end latency/p95 claim. The installed wheel passed 31 targeted cases (42 deselected), and the exact-head gate passed 6 direct and 11 selected checks. Raw profiles and inputs remain private; live adoption is a separate acceptance step.