Repository navigation
fix(explore): retain latest findings when timestamps tie - #7889
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.
1) 问题定义(为什么改、要解决什么)
- 修复
build_explore_result_projection在多条 Explore finding 共享同一整秒时间戳(last_updated_at相同)且执行逆序排序(reverse=True)时,Python 稳定排序保留了旧创建顺序而非最新追加顺序,导致finding_limit截断时丢弃最新结论的问题。
2) 改动摘要(按模块分组)
- 同秒时间戳按追加序号破平 (
loopx/capabilities/explore/result_log.py):在build_explore_result_projection中先对folded_findings按(chronology_key(item["last_updated_at"]), item["_recorded_order"])执行reverse=True排序,再投影_finding_view(event),确保同秒追加或更新的结论按最新写入优先保留,且不篡改原始证据时间戳。 - 回归测试 (
tests/control_plane/test_explore_measurement_feedback.py):新增同秒多次写入与原地更新的截断顺序测试及 File/SQLite CLI 端到端顺序断言。
3) 逐点审阅结论(架构、语义、正确性、测试、风险)
- 正确性:利用已有的
_recorded_order单调序号在不污染底层事件时钟的前提下消除了整秒精度碰撞导致的逆序反转。
4) 建议修改项(分 P0/P1/P2,带文件路径和行号)
- 无阻塞项。
5) 最终结论(Verdict)
Approved — ready to merge once CI completes (exact head a3a2d39fa87acf451d6c5e46576b76d590cd0a9a verified).
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)
精确 head:a3a2d39fa87acf451d6c5e46576b76d590cd0a9a;base:867615e2c3aa2a32516a71d46f11a20d6fcb3289。未发现阻塞项;结论依据本轮独立 source/CLI/反例验证,未查询或等待 CI。
动机 / Motivation
在 Explore 中连续记录或修正发现、随后依赖默认三条结果继续工作的 Agent 与用户。
同一秒写入四条 finding 后,旧视图保留最早三条,把最后一条挤出窗口;修正一条旧 finding 时,窗口也可能继续混入较旧记录。后续工作容易遗漏刚获得的观察。
当前 head 在相同时间键内按既有 append ordinal 排序,再生成 finding view 和应用数量限制;同一固定来源的新记录与 correction 均进入预期窗口,原始记录和跨时间顺序保持。
范围限于同 chronology key 的结果窗口与其分页;评分、计量值、planner/authority、已存记录和实际模型采用均保持各自原边界。本轮不启动模型、评测或修改冻结实验。
改动思路 / Approach
问题出在同秒结果先被转成 view、再由稳定排序保留旧创建次序;数量限制随后把新观察挤掉。现有 fold 已给出最新 append ordinal,在同一个 canonical projector 中排序即可修复;无需新增持久字段、改时钟或复制到各 consumer。
保留现有 chronology 主键、history、measurement 与 typed page owner,只在相同时间键内补既有 ordinal;更大的排序或语言迁移不属于本 PR。
无操作会留下可复现的证据窗口缺陷;人为增加时间或让每个 reader 自行修正会增加证据与维护成本。本实现继续用 Python 现有日志投影适配器,mode、task eligibility、measurement 与 page revision 由原 typed owner 处理。修正窗口能支持后续工作看见当前证据,实际采用与收益另行观察。
具体改动 / Changes
完整两文件 +44/-4,production 为既有 projector +7/-4,测试在现有模块增加37行。规范:loopx/capabilities/explore/README.md,不可变 spec_revision 为 867615e2c3aa2a32516a71d46f11a20d6fcb3289;本轮将近期结果/修正、source history 和 revision-bound page 条款映射为 recent-window、source-history、page-recovery,三项 implemented。measurement 的“latest recorded”仍按既有 append-order 比较;本 PR 保留普通结果跨不同时间键的 chronology 规则。
关键代码讲解
build_explore_result_projection对folded_findings使用(chronology_key, _recorded_order)的降序,随后调用 view builder,最后按 finding limit 截断;新规则仅用于相同 chronology key。_fold_by_result_id本来就从 source append 顺序派生 ordinal,并保留 first time、最新版本及 update_count;这里复用已有事实,未增加持久字段或改变 source。_finding_view的输出与 measurement attribution validation 保持原有字段。turn_context.py仍先读取完整来源,再交给既有 TypeScript owner 做 task/refutation 优先级、分页与 source revision 校验。
对主干的风险 / Risks
我用同一份固定 source JSON 分别经过不可变 base 和当前 production projector。对 tagged 与 measured finding,base 的前三条是旧 0,1,2,head 为 3,2,1;同秒修正0后,head 为 0,3,2。不同时间的旧 append 仍排在后面,foreign Goal、limit=0 与 source/history 不变控制均保留。十个检查中 base 有八个不满足期望,head 全部满足,代表同一排序缺陷的多种控制,不是八个独立缺陷。
还把这两份实际 projection 送入未改的 native typed page owner:page revision 确实不同,拿旧 revision 续读会拒绝;从新首页恢复后,第二页可读到遗漏的0,Explore off 仍返回 graph=null。PASS:五个完整相关 Python 模块 141 passed,含真实 File/SQLite CLI;Explore context 16 TS passed,覆盖 off、task isolation、refutation 与分页。PASS:本地 standard premerge 6 direct + 5 canaries,Ruff。最初 TS 命令误用未声明的 tsx loader,在测试执行前失败;改用仓库 Node24 native strip-types 入口后通过,失败记录保留。CI 保持 UNVERIFIED。
作者提供的“main + #7874@f8 + 本修复”六项 comparison 通过,属于另一组组合来源;本轮未将其用作本 PR 独立资格,也未把 #7874 原 head 的历史失败改成通过。当前批准由上述独立 standalone 证据支撑。
我的整体评价 / Verdict
此有界缺陷修复为 goal_achieved;long_horizon 与 user_experience 均 improved:同秒新增观察与 correction 可以进入后续默认窗口,读者可沿现有 revision recovery 完成读取,无额外确认轮次。代码比例合适,复用既有 ordinal 是本次已应用的局部简化;无需扩大成新的排序框架或语言迁移。semantic vocabulary 沿用现有 owner。完整两文件 diff 修改 result projection 排序和回归测试;既有结果 consumer 的布局、控件、文案与图形页面未改。Dashboard 实际视觉呈现、模型采用和长期效果未在本轮验证。正式 GitHub approval、thread closeout 和 merge authority 保持独立。
English verdict: APPROVE — a3a2d39fa87acf451d6c5e46576b76d590cd0a9a fixes tied-time finding windows using the existing append ordinal while preserving source history, scope and page recovery.
当多个 Explore finding 在同一秒写入时,默认前三条结果可能保留最早创建的 finding,挤掉较新的结果。source writer 使用整秒时间,原排序在时间相同时保留了 fold 的创建顺序;更新旧 finding 也会遇到同样的问题。
本 PR 在现有 canonical result projection 中,按原 chronology key 排序后,用既有的最新 append ordinal 处理相同 key,再应用结果数量限制。新 finding 和同秒 correction 因此进入最新结果窗口。原始时间、append history、计量数值、source digest 字段和不同时间之间的排序规则保持原值;不增加存储字段或第二个排序 owner。Python 改动留在既有日志投影适配器,复用其已有 ordinal。
验证:固定同秒的 manual measurement / writeback-result 回归在修复前均失败;修复后相关 Python 81 项通过,其中包含真实 File/SQLite CLI 写入与默认结果窗口读回。TS turn-context 16 项通过,覆盖 Explore off、分页来源、任务隔离与 refutation 优先级。Ruff、diff、RFC 双语检查及 premerge 的5项 canary和6项直接检查通过。首次 premerge 因未安装 TypeScript 开发依赖失败,补齐锁定依赖后通过,失败记录保留。没有查询 CI。
这也定位了 #7874 保留的分页断言问题。以当前 main 加 #7874 的
f8fc621022a285cb8ee152647932161c3ff90e56、再加本次单文件修复组成的本地验证源,原 File/SQLite comparison CLI 6 项全部通过;原断言保留。#7874 的作者分支/head 未改动。这是组合验证,不能把旧 head 的失败改记为通过。风险限于同 chronology key 结果的显示次序与由此生成的分页 revision;旧页使用现有来源变更恢复路径重新读取。评分、任务选择、authority、日志和实验运行语义没有新增变更。提案以 main 为 base,待独立 exact-head review。