fix(reward-memory): recover pending TS projections without repeating work - #5232
Conversation
…work Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
审阅 head:2b7b0cbeeb6f6dc667064b4925ef2e049f0d8cb3。未发现阻塞本次有界修复的问题;不把源码验证等同于安装采用、跨进程恢复或记忆实际效果。
动机
已有 query-ready API 在 provider/应用完成后遇到 TS 投影异常,会保留部分回执,却丢失待确认产物;相同请求只能一直 incomplete,重新判断还可能增加模型调用。该缺口已在不可变基线复现,不是为了增加一个新的记忆服务。本 PR 是有价值的独立增量:恢复同进程内已经完成的工作,不宣称完成更大的记忆闭环。
改动思路
复用原 SDK、配置与 TS owner,在调用方完整私有 result 中暂存原始 SDK 观察和产物。重试先过既有请求摘要,再仅调用原 TS 投影,由它重新核验应用、产物和经验归因;没有把经验正文或判断规则复制到 Python。doing nothing 虽然仍可继续独立研究,但已付费的结果会被遗失;只有公开回执又无法重建产物。当前私有快照比新增缓存、恢复协议或第二决策服务更小。
具体改动
关键代码讲解
- 私有 pending 快照 保存原 SDK 状态、累计遥测、两类回执和产物;可选字段默认 None,旧调用方式不变,它不成为新的持久权威。
- 共享恢复入口 只经过既有 TS RPC。成功后按 TS 的 preserve_base_output 选择产物并清除 pending;故障返回同一基线结果,不调用 provider/applier。
- 精确重放 保留关闭时的早退和原请求 fence;配置、问题、范围、产物变化不能挪用旧结果。首次 hook 完成后先保留私有快照,再请求投影。
- 语义判断 区分“恢复已尝试判断的投影”和“第一次判断”。无效归因恢复也不能顺便再调用模型;后续显式 assessment 仍可纠正不完整 SDK 证据,无需重新召回。
全 diff 为生产 54+/12-、测试 213+、双语文档 24+。13 个新回归覆盖交付/判断恢复、持续异常、精确身份拒绝、错误归因和产物快照;复用原测试 fixture,没有新 smoke 家族或临时 probe 入库。文档说明所有私有字段不得进入通用前端/飞书,并保留 EOF/重启不能恢复的边界。
对主干的风险
最强反例是“投影恢复偷偷再次执行模型”或“无效回执被升级”。额外 invalid-assessment 负例曾直接报 second model judgment,已修复;两 corpus 的累计调用/过滤计数、原交付链和非法归因拒绝均验证。关闭路径仍 None、零 TS/provider 调用;配置未变化,原 Dashboard 配置与双语契约已检查,无新增前端资产。Lark 保持状态入口,不声称所有用户入口已打通。
同一 fixture 经真实 SDK→TS 入口在 base/head 对照,15 个正常/拒绝场景的完整公开 packet、产物和调用计数摘要完全一致:b3722cf8adac81a6f41860a4f6b90f8dbb08913232f36b8b586f7d271d9e328c。唯一刻意变化是恢复场景由 incomplete 到 context_delivered,provider/交付 callback 均保持一次。旧基线 42 项通过,新恢复场景先红后绿;exact head 的组合 Python 167 项、原 TS 10 项及前端契约通过。5 项直接检查和 17 项预合并检查全部通过,没有放宽预算。
语义与 CI 对齐
复用既有状态和单一 TS owner,不新增公共词表或 actor/授权语义。正式 mypy(19 文件)、TS typecheck、Ruff、编译和语义/公开边界检查通过。额外 follow-imports=skip 类型探针两处 no-any-return 在不可变 base/head 的原 RPC/callback 返回位置均复现,单独披露,不伪称通过。首次预合并缺 TypeScript 依赖已按锁文件安装后消除,未修改依赖清单或门槛。按本 Goal 的 wait_for_ci=false,未查询、轮询或等待 GitHub CI。
我的整体评价
APPROVE 这一有界修复。长程连续性改善在于已完成结果可恢复且不重复工作;用户体验改善在于使用原入口、原配置获得诚实回执,而非额外手工同步。简化已体现在共用恢复 helper 和原 TS owner,未为了 TS 偏好扩大语言重写。真实 provider/model 效果、跨进程恢复、通用前端/Lark 回传及安装采用仍需独立证据;它们不被本次合成验收冒充完成。需要 Core maintainer 合并后再走受控升级,本自评审不提供合并权限。
English verdict: APPROVE - 2b7b0cb; bounded private SDK-result recovery reuses the existing TS owner without repeated provider/judgment work. Matched base/head observations, 167 Python tests, 10 TS tests and exact-head premerge pass; persistence, utility and installation remain out of scope.
Summary / 摘要
Fix caller-retained Reward Memory results that become permanently incomplete when the provider/application has already finished but the existing TS result projection fails.
修复 Reward Memory 调用方保留结果的恢复缺口:provider/应用已经执行,TS 结果投影暂时失败后,相同请求只能永久返回 incomplete,待确认产物也无法恢复。
reward_memory.decision.project; assessment first recovers delivery, or returns the already-attempted semantic projection without another callback—even for invalid attribution.私有快照保留原 SDK 观察和产物;精确请求重放只重试原 TS 投影。assessment 先恢复交付,已尝试的语义判断不因投影恢复而重复调用,即使归因无效;后续显式判断仍可纠正不完整证据。TS 继续持有准入/完成语义,Python 仅适配和保留既有私有值,不新增持久化、开关、循环或授权。
Validation / 验证
ee9dad81b14c6d15d32b95851b5d38fcc485e732: existing 42 decision tests pass; the first four new projection-recovery cases fail before the fix.mypy --follow-imports=skip decision.pyreports two unchangedno-any-returnerrors, independently reproduced at the immutable source base; the official repository mypy gate passes.npm ci --ignore-scripts; no manifest/lockfile change or budget increase.原基线的 42 项决策测试通过,新增前四个恢复场景先红后绿;额外负例确认并修复了无效归因恢复时的重复 callback。137 项相关 Python 测试、10 项原 TS 测试、30 项配置测试及原前端契约检查通过;Ruff、编译、正式 mypy 和 TS 类型检查通过。额外跳过导入的严格 mypy 检查两处原有错误已在独立基线复现,不伪称通过。
User paths, boundaries and rollback / 产品入口、边界与回滚
The changed entry points are
run_reward_memory_decision(..., previous_result=result)andassess_reward_memory_decision(result, ...). Reuse the caller's complete private result and stable application/artifact identity. Onlypublic_packetis displayable.The existing Dashboard configuration fields (
config_path,enabled_agents) and their configuration owner are unchanged, so no new control or packaged frontend asset is needed. Existing configuration and bilingual frontend contracts were checked. Lark remains status-only; universal frontend/Lark consumption, cross-process restore and memory utility are not delivered here. All provider/model test inputs are synthetic; this is not financial-effect evidence.本次改变两个既有调用入口的恢复行为;必须保留完整私有结果和稳定应用/产物身份,只展示 public_packet。Dashboard 原配置字段及 owner 未变,无新增控件或前端资产;原配置和双语前端契约已检查。Lark 保持状态投影,不宣称通用端到端回传、跨进程恢复或实际记忆收益。本地验收使用合成 provider/callback,不代表金融效果。
Rollback to the original optional automatic-recall hook, or disable through the existing configuration owner. Ordinary research remains fail-open. No query/lesson/model rationale or pending output is sent to TS, generic UI or Lark.
Scope / 范围
One bounded implementation commit: existing private adapter, focused regression tests and bilingual contract documentation. Reused the existing TS projection and test fixtures rather than adding a second decision service or a new smoke family. Local state, provider data, credentials and generated logs are excluded. Maintainer review/merge and qualified installation remain separate; no unmerged installation is performed.