Repository navigation
fix(benchmark): resume verified interrupted hosts without rewinding state - #8208
Conversation
…winding state Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
…doff Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
…tion 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; OpenAI / gpt-6-astra; reasoning effort: ultra; declaration: runtime_reported.
Reviewed exact head: 8633d29ef8a58d9089ef522ca6c3a110d11d36ba against main contract baseline 22b0f6c25a0450a66bd93f05954808dc0a5800ed.
动机 / Motivation
在有限预算内运行原生 Agent、需要从中断现场接续的 benchmark 操作者。这里的实际问题是:进程因本段预算到期而中断,最新代码、SQLite 和原会话仍在;旧路径一直保留未决 Host,新路径核对这些原始状态后追加一段接续记录。
已验证的原会话可以进入下一次正常调度,原状态和中断记录保留,重复请求不会重新发放同一段时间。这不是 Goal 完成、评分器恢复、额外预算授权或任意跨容器搬迁,也不自动解除未结算的 replan。真实模型是否采用交接内容、续跑后的有效评分和完整研究状态验收仍需由实验接收端另行核验。
验收来源是变更前的 benchmark/README.md,不是本 PR 新增说明自行证明自己。对应四项边界:preserved-state-and-session 保留原状态和会话;current-admission-and-stops 复用当前准入与 Stop;bound-phase-recovery 不在重试时补发同段时间;research-and-native-authority 仍由原研究恢复、评分器接收端独立验收。
改动思路 / Approach
进程与 Docker 观察留在 provider,原生历史分页复用现有 reader,Goal、停止和语义结算继续由原 owner 决定。本 PR 只交付已证中断的原地传输接续与可选内容交接;评分器、预算授权和未结算 replan 都不由它代办。
下表对应上述精确 head 的实际入口。关键变化是先证明原 Host 的中断,再回到原来的调度流程,而不是把失败记录清掉。
| 输入情况 | 旧行为 | 本次行为 |
|---|---|---|
| 已调用的原生 Turn 因预算中断,原状态和稳定历史完整 | 保持原 Host 未决 | 核对身份、状态和原生历史后,追加有固定截止的新 phase;下一 wake 仍走原准入 |
| 未调用模型就遇预算停止 | 已支持新 phase | 保留原行为;可选交接内容也完整绑定到该 phase |
| 状态不符、仍有进程、当前 Stop 或未结算 replan | 保持停止/未决 | 继续保持;不把传输恢复视为语义完成 |
| 同一 phase 重试 | 保留原截止与记录 | 还校验交接内容不可变;合法后续预算段可以绑定新的交接内容 |
具体改动 / Changes
关键代码讲解
prepare_stopped_recovery从已停止 Docker 容器生成源码、工作区、SQLite/WAL、会话和调度记录的清单。它不会启动模型或评分。最终版同时约束默认 Docker hostname,并由接收端读取内核 UTS hostname 核对,避免把全部字节复制到另一个容器后误当原地续跑。read_interrupted_host组合原 wake、当前 Goal/session/profile、进程退出或停止容器证明。信息缺失与不匹配保持原记录,不能退化成删除 pending 的捷径。它仅核对当次传输;当前 Stop、lease 与 replan 的原所有者仍决定后续工作。native_interrupted_turn使用完整分页历史并重复读回,核验同一会话、工作目录、中断末尾和时间窗口。共享 reader 仍保留“完成 checkpoint 必须指向已完成 cursor”的旧限制;不能把这条新通路拿去放宽普通 checkpoint。resume_state_file锁定原状态与现有 phase,从实际最新前驱追加新记录。原阶段、会话、replan 历史和 Todo 都保留;同一恢复段不能换截止或换交接内容。新阶段进入后仍走普通 worker。recovery_handoff复用现有只传内容的 handoff owner。文件须满足精确摘要、普通文件与大小约束;FIFO 会立即拒绝。phase 绑定的内容只在同会话成功回执前继续提供,未知结果不能假装已交付。
独立审查中实际复现并修好了三类关键反例:早期版本接受“复制全部原始字节到另一 namespace”;把任意 *-shm 文件都排除导致普通候选变化漏检;已存在的 pre-dispatch 分支接受交接文件后却没有持久化。最终版分别约束原 namespace、仅排除确属 SQLite 的索引 SHM,并让两条 phase 创建路径都保留交接内容。此外复核了 FIFO 不阻塞、同段输入不可变及合法后续段可换交接内容。
验证覆盖不是只测 helper:同一独立夹具在不可变 main 基线与本 head 上运行真实 SQLite Goal、external scheduler 和子进程。基线保留未决,head 追加 phase 后的实际 argv 复用原 session,原 Goal/前驱字节不变。生产 heartbeat_body 也通过真实 CLI 独立验证了有/无交接内容的差异;实际模型派发用合成 native 进程,不冒称付费模型采用。
最终两文件增量的聚焦组 24/24 通过;Linux 实际 Docker 的停止源、同容器消费/重放和跨容器完整复制拒绝 17/17 通过。此前较宽组的产品案例通过;私有夹具曾漏导入 pytest,补齐后以最终聚焦组执行完整原断言,未放宽断言。旧基线相关检查为 64 通过、14 个可选 Docker 跳过;原 PR 宽组为 192 通过、15 个可选 Docker 跳过。中间版宽组 216 通过、15 个可选跳过,另有上述夹具错误;最终增量只改 scheduler 与其测试,对应已重新验证。每个旧失败和修复回执均保留,不能只挑后来成功的一次。
对主干的风险 / Risks
主要风险在错误地把“进程结束”当成“效果已经结算”,以及把别的现场误认为原现场。当前代码坚持读取原始状态、完整原生历史和当前准入,错误或不完整证据保持未决;started、unknown、returned 的未结算 replan 都有保留 hold 且不重复派发的反例。原生读回只调用历史接口,不调用模型或重放工具。
默认边界也需要明确:新 dispatch 增加被动 attempt UUID 与进程观察,这是已披露的回执元数据变化,不能声称所有默认字节完全不变;实际恢复仍须显式 continuation,交接内容还须显式绑定原 phase。没有新增全局提示、planner、Goal 状态或评分机会。关闭恢复/不提供 brief 时,原 worker 选择和普通 heartbeat 内容保持原义。
Docker hostname 校验能防止意外跨 worker 复用,但不是对拥有 Docker/UTS 配置权限的可信操作者的密码学认证。真实模型理解、研究完整性和后续评分收益没有在本评审验证;HTTP 评分器恢复也不是本 PR 的能力。
CI 的 kernel-static-checks 在 tests/control_plane/test_goal_create_completion.py:184 报 F841。对不可变基线 22b0f6c25a0450a66bd93f05954808dc0a5800ed 和精确 head 运行同一完整 Ruff 命令,失败全文一致,且本 PR 未改该路径。后续流水线因此跳过/聚合失败,构建检查观察时仍在运行;我没有把远端 CI 写成全绿。受影响的恢复不变量已独立验证,合并就绪仍须按仓库门禁单独判断。
我的整体评价 / Verdict
这个切片解决的是“保留最新现场后,如何有证据地回到正常执行”这一实际缺口,复用现有当前准入与原生 reader,比人工清空状态更可靠。新增的 source inventory 和进程证明有维护成本,但旧记录无法补造 attempt 身份,需要保留有明确边界的 legacy 停止源路径;没有理由再增加平行调度器。
本次只改 benchmark 操作者 CLI、进程传输和 README,未改网页或聊天展示。没有新增渲染界面;本评审不宣称通用恢复 UI 已交付。独立复现的缺陷均已在这个精确 head 闭合,未发现剩余阻塞项。结论限于传输恢复正确性和真实调用链;不代表模型收益、实验成绩、或已获得合并授权。
English verdict: APPROVE — exact head 8633d29. Same-session continuation, immutable phase input, source provenance and default-path isolation are independently qualified; model adoption and evaluator restoration remain separate.
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent — OpenAI gpt-6.1-sol — runtime_reported — max
REQUEST_CHANGES:当前 head 8633d29ef8a58d9089ef522ca6c3a110d11d36ba 有一项已复现的 P2,停止源准备把 Unix deadline 传给 monotonic 归档器,导致读取超时失效。
本次已完整读回同 head 的既有独立批准。它覆盖 namespace、SHM 和 handoff 的修复,但没有验证这里的 archive deadline。此评审依据另行复现的具体新反例,不重复批准,也不删除原讨论。
动机 / Motivation
面向需要接续预算中断工作的 benchmark 操作者。旧路径在 Host 已退出且保留已完成工作时仍会停留在原 attempt;新路径验证原进程、会话和历史后追加 phase,保留文件系统与未完义务,但停止源准备的读取期限目前失效。正常源清单、SQLite WAL 与 proof 安装读回可执行;独立 Docker 反例证明超时参数未限制实际归档读取。本 PR 不授权新预算、评分机会、模型调用或合并,也不证明科学收益、完整研究恢复或安装版采用。
改动思路 / Approach
恢复阶段复用既有 scheduler、会话准入和 Docker archive owner,新增部分主要是 provider/process IO;应在同一 owner 内修正时钟,不需要新增恢复 authority。当前 PR 的可审边界是保留文件系统的显式 Host transport recovery,后续 native evaluator、真实模型和研究效果仍分别验收。相比直接清除 pending 或从旧 checkpoint 重做,核对原 attempt、真实进程终止、当前会话和完整历史是必要的。原文件与已经结算的 Turn 保留,新的 phase 只接续传输;下一次 wake 仍通过普通准入,没有额外用户确认步骤。旧 worker 缺少进程观察时,使用显式停止源 proof,而不是补造原观察。
下面是同一个停止源、同一真实 Docker archive owner 的独立观测。monotonic 指不会随系统时钟调整而跳变的计时基准;对照只在私有测试进程中改换时钟,产品源码未改。
| 场景 | 当前代码 / 对照结果 |
|---|---|
| 正常清单及 proof 安装 | 13 个参与项、两份真实 SQLite WAL;proof 字节回读一致,源一直停止 |
| 当前代码,请求 30s | 实际 HTTP timeout 约 17.9 亿秒,已明显偏离声明 |
| 当前代码,请求 1ms | 约 222ms 后仍成功 |
| 同源 monotonic 时钟对照,请求 1ms | 归档 HTTP 读正常抛出 ReadTimeout,未发布成功 proof |
具体改动 / Changes
完整十文件差异为 +1138/-17:六个生产文件 +574/-17、三个测试文件 +480、文档 +84。评审先读的原合同是 benchmark/README.md#explicit-warm-worker-composition-qualification-in-progress,固定版本 22b0f6c25a0450a66bd93f05954808dc0a5800ed。这里的四个 criterion_id 是原合同段落及现有 archive 参数合同的评审索引,并非新增产品要求:retained-work 已实现原状态/会话保留;current-admission 在定向 Stop/profile/session 反例中保持;bounded-provider-read 当前未满足,最小修复就是统一归档时钟并验证超时;separate-research-authority 继续把传输、评测与新预算分开。没有使用 PR 新增的文案反向证明旧版已经允许该恢复。
关键代码讲解
resume_state_file在原锁和前驱链内选择追加 phase,携带原 replan attempts 和 recovered session。相同 deadline 的重试复用当前 phase;变更 deadline 的重试拒绝。原 scheduler/Goal 文件没有被这一步改写。read_interrupted_host要求唯一原 wake、已结束进程组、当前绑定与 profile,读取完整 native tail 后再次核验准入。错误 session、重复 wake、仍存活进程及变化历史不能成为接续凭据。prepare_stopped_recovery复用已有物理 archive/WAL reader,拒绝运行中、有外部挂载或非 inert 的源。它只可选择安装无执行能力的 proof;问题位于这条 provider 路径的 deadline 参数,而非需要另一套恢复状态机。native_interrupted_turn从原 completed-checkpoint reader 抽取完整历史枚举,独立核对 interrupted tail、进程时间窗、pending effect 与两次读取的一致性;原_complete_history仍要求 completed final cursor。worker 复用既有进程 observer,scheduler 增加 attempt 身份;这些是已披露的被动诊断变化,不应写成普通 receipt 逐字不变。
最新版本另增加 recovery_handoff:显式物理文件与 SHA256 通过现有 content-only handoff decoder 进入 heartbeat;缺失、改字节、FIFO 或超出界限均拒绝,成功的同会话 receipt 确认 digest 后停止重复展示。301a755 增量还补原 Docker UTS hostname 校验及仅省略真实 SQLite SHM;该 hostname 是可信 Docker 操作者下的防误用边界,不是密码学认证。8633d29 再补 pre-dispatch phase 的 handoff 冻结及重放。已逐行审这两次完整增量,保留原 replan owner,不从传输成功推断语义 replan 已完成。
对主干的风险 / Risks
[P2] Docker archive 的 deadline 使用了错误时钟
stopped_recovery.py:89 使用 time.time() + timeout,但现有 checkpoint_controller._remaining() 用 deadline - time.monotonic() 算剩余值,并将其交给 archive 的 HTTP timeout。两者的原点不同,因此实际期限被延长到约 17.9 亿秒。该问题不需要伪造或损坏输入,正常 stopped source 就会触发;现有 mock archive 直接复制文件而忽略 deadline,所以定向测试通过仍不能发现它。发生慢读或 daemon 卡住时,操作者无法按声明的时间得到拒绝。
最小修复是在初始清单读取和后续 proof existence/readback 的所有 _archive_component 调用中使用同一 monotonic 时钟,并校验有限正 timeout。增加真实或 deadline-sensitive reader 回归:传入 SDK 的剩余时间不得超过声明 allowance,过期必须拒绝且不能返回成功 proof。无需重置 phase、修改原历史或引入新 timer owner。
语义与 CI 对齐
PASS:301a755acf55ca588d6ebb7e61b8f39cd35503bb 的五个受影响模块终态 168 passed、1 个显式 Docker case skipped;另启用真实 Docker consumer 测试为 1 passed,验证原容器消费/重放及复制到另一容器拒绝。该版本真实 Docker deadline 复现为 1ms 请求约222ms后仍成功,monotonic 对照正常 ReadTimeout。8633d29ef8a58d9089ef522ca6c3a110d11d36ba 只再变 scheduler 与其 phase 测试;逐字 diff 证明 provider、native reader、worker 及 scheduler Host 脚本没有改变,上述证据据此限范围复用,phase suite 已重新运行。完整一般路径 parity 和真实模型/evaluator 仍未独立资格,不以这些通过数替代。
原 43997e8 的 224 passed/25 skipped 作为历史保留,只在不变的 completed-checkpoint/native owner 上复用,未改写成当前版本重新运行。其原始 25 项定向通过、Docker反例与准备失败也保留;旧 head 在发布前变更,未提交旧 review。当前 quick premerge 结果分别记录:机械检查与缺失的精确 quality receipt、benchmark_sensitive maintainer hold 分开;未豁免质量门禁。未查询、轮询或等待 CI。测试的 native 协议使用真实子进程和 SQLite,但 quota payload 有 stub,不认证真实 Codex、完整实验恢复、部署或科学收益。
我的整体评价 / Verdict
已检查全部十路径;没有 UI 源、页面布局或 rendered presentation 改动,CLI/内部 transport 不需要新增截图。未验证真实 Codex、安装版、完整 evaluator 恢复、模型采用和长期研究净益。恢复阶段复用既有 scheduler、会话准入和 Docker archive owner,新增部分主要是 provider/process IO;应在同一 owner 内修正时钟,不需要新增恢复 authority。当前 PR 的可审边界是保留文件系统的显式 Host transport recovery,后续 native evaluator、真实模型和研究效果仍分别验收。本改动有合理的有界内部传输用途,也复用了已有 owner;没有理由为这次修复新增通用 frontend、第二套准入或研究评分机制。但长期继续工作和 CLI 恢复体验都依赖及时的失败返回,当前时钟错误构成实际回归,故请求修复此精确 head。这里复用既有状态词汇,新增数据保留在 provider/local projection;不凭记录存在、测试数量或历史 approval 推断模型采用、科学收益或合并权限。
English verdict: REQUEST_CHANGES 8633d29. The real Docker archive receives an epoch deadline where its owner requires monotonic time, defeating bounded recovery reads; fix the clock and retain expiry coverage.
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 — OpenAI gpt-6.1-sol — runtime_reported — max
Reviewed exact head: b54ca62c892599ba623940fd1f83e0a59fccb849.
动机 / Motivation
这项改动面向需要从原容器接续预算中断工作的 benchmark 操作者。原生进程因本段预算结束而停止时,最新工作仍保留,但旧调度器会留住原 Host attempt,操作者无法从同一会话进入下一段。新路径核对停止源、原会话和当前准入后追加有固定截止的新阶段,普通 wake 可以继续使用原会话。后续模型表现、评估器恢复与新增预算由各自的验收和授权流程处理。真实评分器和完整研究状态仍需由实验接收端进行独立端到端验收。
改动思路 / Approach
旧 worker 没有事后可补的 attempt 身份,停止源证明承担这一兼容职责。已有调度器、准入与归档 owner 各自保留决策。本 PR 的交付范围是原地接续已验证的中断 Host、可选内容交接和停止源归档期限。 生产入口先核对原 Host pending witness、唯一 wake 和完整原生历史,再复核同一 Goal/Agent 的当前准入。追加阶段后,普通调度仍负责下一次工作。原 replan 未结算时保留 hold,成功回执只确认已绑定的交接内容。直接清除 pending 会失去原执行的归属和剩余工作证据。
| 场景 | 观察 |
|---|---|
| 已证中断、原会话与新阶段输入一致 | 原状态保留,下一 wake 使用原会话 |
| 到期归档或来源改变 | 拒绝并保留停止源和未决状态 |
| 同一阶段重复请求 | 保留首次截止值与交接摘要 |
具体改动 / Changes
对照变更前的 benchmark/README.md#explicit-warm-worker-composition-qualification-in-progress,固定版本 22b0f6c25a0450a66bd93f05954808dc0a5800ed。retained-work 保留工作区、会话与前驱记录,current-admission 仍由现有准入和 Stop 判断,bounded-provider-read 通过归档 owner 的单调截止值实现,research-authority 由原预算和评估 owner 独立处理。十个文件共 +1196/-17,包含六个生产路径、三个测试文件和 benchmark 使用说明。
关键代码讲解
prepare_stopped_recovery验证完整的原容器 ID、停止状态与物理文件。清单、proof 查重、回读沿同一个单调截止值。期限已过时先拒绝,再保留源给操作者。 stopped_recovery.pyread_interrupted_host以原 attempt、唯一 wake 和已终止进程证明来源,再核对当前会话准入。旧 worker 只能在同一容器中消费明确准备的证明。 interruption_recovery.pynative_interrupted_turn完整读取并复读同一原生历史,拒绝越窗、待定效果或移动的最后一轮。普通 checkpoint 仍要求 completed cursor。两种错误同现时,重复 Turn 的诊断会先于末尾状态诊断。 codex_checkpoint.pyresume_state_file通过原有锁和前驱链追加固定截止的 phase,保留历史及 replan 状态。可选recovery_handoff复用内容读取 owner,成功的同会话回执确认其摘要后结束重复呈现。 scheduler.py
对主干的风险 / Risks
前次 P2 在上一提交的真实 Docker 用例中复现。过期读取曾返回成功,测试报告 DID NOT RAISE TimeoutError。当前 head 以同一真实归档入口验证到期后不发归档请求、不发布成功证明,原容器保持停止。正常清单和安装读取的 HTTP timeout 都在剩余预算内递减,包括 proof 的查重及回读。Docker reload 和写入仍各自使用 transport timeout。只在请求归档和发布证明前检查剩余窗口,因此这里的验证限于归档和证明边界。独立补充审查也核对了这一修复及其期限边界。 前次 P2
语义与 CI 对齐
PASS。实际 Linux Docker 的停止源和 archive transport 48 项通过。原生 checkpoint、调度及中断接续回归 118 项通过,32 项为可选原生/环境跳过。相同的 18 项原调度路径在固定基线和新 head 均通过,覆盖期限、原会话、前驱保留与重试拒绝。当前主干与此 head 的合成树还通过了同一恢复、原生 reader 和真实 Docker 组合检查(46 passed, 27 skipped in 58.67s)。 premerge 的五项直接检查和 19 项选中检查无失败,保留 benchmark-sensitive 维护者审查。公开边界、Ruff 和双语差异检查通过。Goal 的 wait_for_ci=false,远端 CI 未查询。默认 wake 增加被动诊断字段,未显式接续时原任务选择、预算与普通提示仍由原 owner 决定。
我的整体评价 / Verdict
变更涉及 benchmark CLI、调度和 Docker transport。检查了这十个文件的调用面,界面视觉审查不适用。 已验证同会话接续能从当前工作继续,失败时操作者仍保有原现场与明确拒绝原因。新增 archive 计时复用已有 owner,旧格式保留仅服务仍可验证的停止源。执行权限、会话和受限阶段的词汇继续沿用现有合同。真实模型采用、评分器恢复和长期实验收益仍属于后续验收。全量复审和最新时钟反例闭合后,当前 head 无已验证的阻塞发现。
English verdict: APPROVE b54ca62. The exact head preserves same-session finite recovery, closes the reproduced Docker archive expiry failure, and passes the required local validation.
Budget expiry can leave a benchmark scheduler's original Host attempt held even after its process stopped and its native conversation retained completed work plus an interrupted final Turn. Explicit continuation now verifies that attempt and current session, then appends a finite scheduler phase without rewinding the filesystem, discarding replan obligations, replaying tools, or marking semantic work complete.
The normal next wake retains quota, Stop, profile, session and deadline checks. New attempts record passive process observations. An older Docker worker can prepare a read-back inert proof over its latest workspace, runtime, registry, wake and native stores including WAL. This path requires the original exited, unmounted container with its default container-ID hostname; the receiver checks its current UTS namespace. It is a trusted-operator accidental-cross-worker boundary, not protection against that operator spoofing a hostname. Only actual SQLite shared-memory indexes are omitted; arbitrary similarly named candidate files remain protected.
Optional recovery material uses the existing content-only handoff owner and an immutable digest for each phase. The normal heartbeat receives it, and a successful same-session Host receipt ends repeated presentation. Missing, changed, nonregular or oversized input fails closed; uncertain delivery retains the same input. Both interrupted and pre-dispatch continuation carry the input. A legitimate later budget phase may bind a new handoff without changing the earlier one. No Todo or ownership transfer is created. Pending semantic replans remain held for their original settlement owner.
Validation:
This is a benchmark operator transport, with no product setting or frontend surface. Python owns provider/process/archive IO; existing typed Goal/session owners retain admission. Synthetic inference and private read-only native evidence qualify components, not an active recovery, score improvement, or permission to launch. No active experiment was changed. No merge requested.