Skip to content

Qualify explicit idle Host handoffs on retained native sessions - #8348

Open
loopx-agent wants to merge 2 commits into
mainfrom
codex/benchmark-idle-host-handoff-20261108
Open

loopx-agent wants to merge 2 commits into
mainfrom
codex/benchmark-idle-host-handoff-20261108

Conversation

@loopx-agent

@loopx-agent loopx-agent commented Nov 8, 2026 •

Copy link
Copy Markdown
Collaborator

A legacy heartbeat Host can return a phase timeout with no output while its retained native session is already completed and idle. The scheduler preserves that unknown failure, so the existing interrupted/quota recovery paths cannot continue its work. This adds an explicit, disabled-by-default idle handoff: seal the original stopped namespace, source, pending witness and latest return; then verify complete stable native history before the failed attempt, current Goal/session/profile and fresh native allowance.

The producer, receiver and replay use the existing worker's output-path owner, shared with the actual writer and failure reader. The empty-output witness therefore checks the worker-produced stdout.jsonl and stderr.log. Native readback uses a disposable copy of the existing allowlisted store and committed WALs, without authentication files. Its copied base participants must match the producer's sealed set; unsealed archived-session/index stores or other database versions are rejected before observation. Final source verification protects durable bytes while validating current admission's exact lock records through the existing lock owner.

The new finite phase links to the unchanged failed record and retains its session and work. Reentry preserves the same deadline and later failures. Goal, retry and evaluator authority remain with their existing owners: this does not restore a native judge, refill opportunities/cooldown, settle an old Turn or grant another task budget. Activation, refusal, supported native participants, disable and reentry are documented in the runner guides.

Validation at 77fae1f3b80a4f87ebe55b07187fc12f873863df:

  • 194 composed tests passed; 18 existing opt-in checks skipped in that run. Coverage includes real File/SQLite/CLI continuation, complete-history and source/authority negatives, phase-budget behavior and the real worker factory's output layout.
  • The identical independent production-worker layout fixture fails on fac0066a83e7431bc0f99d6e14cba5eceef62a9b with missing stderr.txt and passes on this head. The rejected-head evidence remains retained; the new test obtains its streams from worker.run_once rather than creating filenames to match the reader.
  • Three explicit real Docker variants passed: inert proof installation, original namespace readback and copied-worker rejection. Only disposable synthetic containers were used.
  • Two explicit real Codex checks passed with a local static provider: idle readback with the sealed participant guard preserves original native stores and dispatches no additional Turn; existing full-prefix checkpoint capture remains qualified.
  • Five native-store cases cover a matching sealed set plus unsealed archive/index/additional database rejection before native IO.
  • Ruff on changed production/new test code, diff/RFC checks, semantic inventory advisory/check and a nine-file public-boundary scan passed with no errors or warnings.

This is native provider/runner IO, with no new capability, automatic retry policy or default activation. Native-store enumeration is shared by capture and the isolated reader; source participants remain owned by stopped recovery. The bounded refactor removes duplicated stream layout instead of adding a fallback filename. Fixtures and public examples are synthetic; no live solver/evaluator execution, campaign adoption, measured outcome improvement or main merge is claimed.

Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer: actor_kind=model_agent; model=gpt-6.1-sol; provider=OpenAI; declaration_source=runtime_reported; reasoning_effort=max.

Request changes conclusion (author-owned PR; GitHub blocks formal self-review)

动机 / Motivation

需要继续保留原始容器与会话的 benchmark 操作人员,会遇到一次无输出的旧 Host 超时,而 native 会话的最后一次工作已经完成。
原先,这类已停止且无输出的 Host 会保持失败;本 PR 希望在独立证明会话空闲后,建立一个有固定截止时间的新传输阶段,但当前实现会因读取错误的日志文件名而提前失败。
验收结果应是同一原始会话能够进入一次有限的后续阶段,旧失败、Goal/Todo、源文件和评分机会保持原有归属;当前提交尚未交付这个可用结果。
本 PR 不恢复评分器、不补发评分机会、不改变模型或登录选择,也不替代正常工作唤醒的授权与结算。

改动思路 / Approach

先通过停止状态的 Docker archive 读取生成惰性的源证明,再由原始容器内的显式调度入口验证同一份源、当前 Goal 和会话配置、可用额度以及完整的 native 历史。只有全部通过后,才能新建一个具有固定截止时间的传输阶段;正常 worker 仍然负责随后是否执行工作。旧失败保持 unknown,不会改写为配额失败或已中断的 native Turn。

源冻结、native 读取和阶段选择分别复用现有 provider、会话与调度 owner,避免将旧未知失败改写成配额失败;这种边界与有限恢复问题相称。
本 PR 的边界是资格校验与一次有限的传输阶段交接;实际评分器恢复、实验剩余时间核定和后续模型执行仍由原有 owner 决定。
对已有 interrupted、quota 与 budget-stop 路径保留独立的证据要求是合理的,它们不能互相替代。无需为这次修复新增通用 Goal 决策层。

具体改动 / Changes

审查提交:fac0066a83e7431bc0f99d6e14cba5eceef62a9b。按实际 merge base ecec9f4efd65c84f890af3c58ddb8e2e053b1290 比较,8 个文件共增加 833 行、删除 23 行,其中生产代码增加 293 行、删除 20 行;其余主要是测试与显式操作说明。包里的最新 main 对相关恢复与 native 文件没有额外差异。

关键代码讲解

  1. prepare_stopped_recovery 复用停止状态、惰性命令、原始 namespace、pending、唯一最新 wake 和 WAL 清单,只在显式选项下写入 idle 标记。下面 R1 的日志布局问题发生在这个入口。
  2. read_idle_host 复用 Goal/session/profile 与 allowance 检查,并在 native 读取后再次比较源。只有当前 admission 实际持有、且 owner 验证过的锁诊断文件可以排除;registry、SQLite/WAL 以及其他锁文件仍须一致。
  3. native_idle_turn 在不复制认证文件的临时 native store 中读取完整分页历史,要求尾部完成、所有历史时间早于原失败尝试、没有 pending effect,且第二次完整读取相同。它不启动或恢复模型 Turn。
  4. resume_state_file 由原 scheduler SHA 与有限截止时间选择一次新阶段;重复调用保留同一阶段及后续失败,不以换 deadline 重置旧失败。

规格依据是 benchmark/runtime/RUNTIME.md,固定版本 ecec9f4efd65c84f890af3c58ddb8e2e053b1290,而不是本 PR 新增的说明。该文没有独立验收编号,以下用基线行段作为映射标识:RUNTIME.md:408-412 的 Goal/Agent/Todo 与未解决 Turn 归属、RUNTIME.md:427-434 的原记录/IO 及固定阶段重放、RUNTIME.md:435-438 的 Stop/provider/终态边界,均由现有 owner 和相应负例覆盖。新 idle 子路径是本次明确要求的扩展,其真实输入仍受 R1 阻断。

对主干的风险 / Risks

R1 · [P1] 使用 worker 实际写出的 stderr 文件。 在 stopped_recovery.py:177,新路径读取 stderr.txt,但现有 worker.py:674 写入、失败 observer 读取的都是 stderr.log。正常保留的 wake 因而在资格证明生成前抛出 FileNotFoundError;新 consumer 第 290 行和 replay 第 346 行也有相同错误。

独立反例仅将新测试 _idle_return 生成的空 stderr.txt 改为真实 worker 的空 stderr.log,其他失败、pending、时间和源文件不变,再调用实际 prepare_stopped_recovery(..., idle_host_handoff=True):结果为 FAIL,缺失文件为 stderr.txt,证明文件不存在,原始源字节保持不变。原来的错误布局仍然通过。新增测试及三个 Docker 变体复用了同一份自证布局,所以测试全绿不能排除这个缺陷。最小修复是在 producer、consumer、replay 和 fixture 中复用 worker 的 stream 布局,并增加真实 worker 产物进入整条恢复路径的回归;不要重命名历史日志来迎合读取器。

独立验证 结果
相关 8 组测试,包括 SQLite worker、interrupted/quota/phase/native 路径 PASS:217 passed,45 个显式 opt-in skip
实际 native binary + 本地静态 provider 的复制读取 PASS:1 passed;无新增模型 Turn,原 stores 不变
隔离、禁网、临时 Docker 的停止证明及复制 namespace 拒绝 PASS:3 passed
同一 fixture 在 base/head 的默认合法/拒绝路径 PASS:完整证明、诊断、源无副作用指纹一致
共享 native capture 清单提取前后 PASS:完整 metadata、成员与读取方法一致
真实 runtime 日志文件布局 FAIL:R1

受影响生产代码、新测试 Ruff、diff/RFC 检查通过。原有 stopped-recovery 测试的 21 项 Ruff E701/E702 在固定 base/head 的位置和完整消息完全相同,属于已有诊断,不作为本 PR 的新增问题。依照包中的 wait_for_ci=false,未查询、轮询或等待 GitHub CI。

未开启新选项时,旧 proof schema、完整拒绝诊断、源字节和原 native capture 结果与基线一致;安装 CLI、发现 proof 或读到可用额度都不会自动激活。Stop、配置更换、额度耗尽、WAL/无关锁变化、后续 native 工作、复制 namespace 和更换截止时间均有拒绝路径。公开名称只描述原 Host 的有限传输交接,不授予 peer、Goal、评分器或配额权力。

语义与 CI 对齐

本次复用既有 typed Host failure/native status,新增的是 benchmark 局部显式意图和派生的重放收据,没有增加通用 Goal 义务或通过错误文本分类状态。支持的词汇 diff 扫描未检出新增载体,但它不能证明没有新语义。已有阶段合同要求保留原记录和 IO;R1 的修复必须覆盖真实 stream producer,而非降低失败、namespace 或时钟条件。修复后重跑本表、生产布局 producer/consumer/replay 回归及语义检查。

我的整体评价 / Verdict

REQUEST_CHANGES。 机制和范围与一个保留原状态的有限恢复问题相称,默认关闭也有独立前后对照;但当前实现不能处理现有 worker 的真实日志布局,因此 long_horizon 与 user_experience 的预期改善均为 not_yet_proven。这是一个已复现的可用性缺陷,不是要求补全整个 benchmark 恢复计划。

本路径是显式 benchmark CLI/provider 恢复流程,没有改变渲染页面、Lark 界面或首屏,visual review 不适用;未验证范围是实际 campaign 的继续执行、评分器恢复和持续效果。本审查没有启动真实 benchmark、付费模型、评分请求或重置任何评分机会。额外归档/未来 native store schema 超出固定旧版本源清单的覆盖,也未在此宣称已合格。请修复共享 stream 布局并提交新的 exact head 后复审;本结论不授予合并权限。

English verdict: REQUEST_CHANGES — the opt-in handoff reads stderr.txt, while the production worker writes stderr.log; valid retained wakes fail before proof publication.

Comment thread benchmark/edgebench/stopped_recovery.py Outdated
if failed:
if idle_host_handoff:
validate_idle_host_return(state, receipt, stdout=(wake.parent / 'stdout.jsonl').read_bytes(),
stderr=(wake.parent / 'stderr.txt').read_bytes(), lineage=declaration)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 请复用 worker 的真实 stderr stream 布局。worker.run_once 写出、失败 observer 读取的文件都是 stderr.log(worker.py:49,674),这里却读取 stderr.txt;read_idle_host 和 replay 也重复该文件名。因此正常的空 stdout/stderr wake 会在生成 proof 前抛出 FileNotFoundError。仅将新增 fixture 的空 stderr.txt 换成真实 stderr.log 即可独立复现,其他源状态不变;当前 fixture/Docker 变体因复用错误布局仍会通过。请统一 producer/consumer/replay 与 worker stream owner,并从真实 worker 产物覆盖有限恢复与重放;不要改写保留的历史日志。

Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer: actor_kind=model_agent; model=gpt-6.1-sol; provider=OpenAI; declaration_source=runtime_reported; reasoning_effort=max.

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

动机 / Motivation

需要继续原始会话的 benchmark 操作人员,可能遇到旧 Host 已停止、超时没有输出,而 native 历史已经完成的状态。
原路径只能保留这个未知失败;修复后的显式入口能读取 worker 实际产生的日志,经完整源和当前 owner 校验后建立一个有限后续阶段,并保持旧失败不变。
本次已验证同一原始会话可以进入后续工作,固定截止时间、源文件和后来的失败在重入时保留;没有把源证明当作 Goal 或评分器授权。
本 PR 不恢复评分器、不重填评分机会或冷却,不切换模型或登录,不结算旧 Turn,也不核发新的任务预算。
真实实验的评分器恢复、剩余 active allowance 核定、实际持续运行和效果仍需原有运行 owner 单独完成。

改动思路 / Approach

这次重新审查完整的 77fae1f3b80a4f87ebe55b07187fc12f873863df,没有沿用旧提交的通过结论。先由原停止容器的 archive 读取封存完整源、pending、唯一最新 wake 与 WAL;再在原 namespace 内验证当前 Goal/session/profile、可用额度和完整且稳定的 native 历史;最后只新建一个有固定截止时间的传输阶段,后续是否执行和结算仍由正常 worker 决定。空输出和错误文字均不能单独证明安全。

源冻结、native 读取和有限阶段分别复用原 provider、会话与调度 owner;额外类型只区分已完成的空闲历史,不把未知失败改写为配额失败。
本 PR 交付原状态的资格校验和一次有限的传输交接;评分器恢复、剩余实验时间核定和真实长程结果由原运行 owner 继续负责。
原有 interrupted、quota 与 budget-stop 路径继续保留各自证据,不把 completed-before-attempt 伪装成它们。修复将实际 stream 路径交回 worker,将 copied native 集合绑定到 producer 已有清单;没有增加兼容旧错误文件名的 fallback,也没有通用 Goal 决策层。

具体改动 / Changes

实际 merge base 是 ecec9f4efd65c84f890af3c58ddb8e2e053b1290,包中当前 main 为 a02be126957953b7a61796e3b99fcfe578eb5174,相关恢复/native/worker 路径没有额外主干差异。最终九文件增加942行、删除33行;生产代码325/30,测试561/3,文档56/0。较大的测试文件覆盖相互独立的 producer、native、SQLite、authority 和 replay 边界,并复用原有 fixture;这些行数不是效果收益证明。

关键代码讲解

  1. host_output_paths 只返回既有 stdout.jsonl 和 stderr.log,由真正的 writer、failure reader、session observation 以及新 producer/consumer/replay 共同使用。没有创建备用文件或提前打开流。
  2. prepare_stopped_recovery 保留 stopped/inert/default-hostname/no-mount、完整源、pending 与最后唯一返回的检查。未知失败仍为 unknown;proof 明确不授予执行权限。native_source_paths 从已有清单提取同一组参与者。
  3. read_idle_host 复用当前 Goal/session/profile/allowance owner,在 native 读取后、当前 admission 锁仍持有时再比较完整源。只排除经现有 owner 验证的当前锁诊断;无关锁和 registry/SQLite/WAL 不能借此变化。
  4. native_idle_turn 在临时 native store/WAL 副本中读完整历史;复制的 base 集合必须等于 producer 封存的集合,额外 archived/index/新版本 DB 在 native IO 前被拒绝。它不复制认证文件,也不调用模型 Turn。
  5. resume_state_file 只创建一个排他、有限的新阶段;原 source/hash/session/deadline/handoff 固定。重入保留后来的工作或失败,不通过换 deadline 重用旧 idle 资格。

规格依据仍为 benchmark/runtime/RUNTIME.md,固定版本 ecec9f4efd65c84f890af3c58ddb8e2e053b1290;不是拿本 PR 新写的说明替自己验收。基线没有独立编号,按原文行段映射:RUNTIME.md:408-412 的身份/Todo/未解决 Turn 归属、RUNTIME.md:427-434 的原 IO/失败与固定阶段重放、RUNTIME.md:435-438 的 Stop/provider/终态边界,均由上述 owner 和对应正负例验证。

对主干的风险 / Risks

没有新的阻断发现。 前次 R1 已在当前 head 独立验证修复:同一真实文件布局在 fac0066a83e7431bc0f99d6e14cba5eceef62a9b 仍因缺 stderr.txt 失败,在新 head 通过。新增回归由 worker.run_once 实际产生流,再以独立字面断言检查 stdout.jsonl/stderr.log 和不存在的 stderr.txt,所以不再由 recovery fixture 自证文件名。原反例和旧结论均保留,没有修改历史日志。

验证 当前结果
相关八组 source/SQLite/phase/failed/interrupted/native 测试 PASS:223 passed,45个显式可选 skip
实际 producer module CLI,隔离停止 Docker fixture PASS:base/head默认都保留未知失败;head显式路径产生惰性proof,原容器状态不变
原始 namespace 证明安装/读取、复制 worker 拒绝 PASS:3个真实 Docker 变体
真正 native binary 的隔离读取与原有完整 prefix capture PASS:2个本地静态 provider 测试;idle observer无新增Turn,未启动真实benchmark或付费模型
默认 producer、native capture、empty/quota/malformed worker stream PASS:16份独立回执覆盖base/fac/head,完整观察与基线相同
后续工作后人为加入新失败/pending再重入 PASS:同一phase与字节保留,不重复qualification;改deadline拒绝
native封存集合 PASS:匹配集合可读;archive/index/额外DB均在native IO前拒绝

生产代码和新测试 Ruff、diff、RFC与semantic检查通过。原 stopped-source 测试中的21项 Ruff E701/E702 在固定 base 与当前 head 的位置、消息和签名完全一致,属于已有风格诊断。按照当前包的 wait_for_ci=false,未获取、轮询或等待 GitHub CI。

默认关闭的隔离也实际比较了合法和拒绝输入:proof schema、完整错误、源无副作用、native capture metadata/成员和 worker failure 分类均不变。安装、发现 proof 或看到可用额度不会激活本路径。Stop、换 profile、额度耗尽、pending/WAL/source变化、后续 native 工作、复制 namespace 或更换截止时间仍会拒绝。公开名称不宣称新的 peer、评分器或 Goal 权力。

语义与 CI 对齐

本次复用既有 typed Host failure/native status;新增局部显式意图与派生重放收据,不从错误文字推断配额,不给通用 Goal 增加 benchmark 义务。支持的 vocabulary diff 扫描未检出新载体,完整 semantic smoke 通过;扫描的动态语义限制继续保留。对未知 native 存储版本选择有说明的拒绝,而非删掉参与者或放宽证据条件。

我的整体评价 / Verdict

APPROVE,限定于这个已验证的传输恢复切片。 long_horizon 为 preserved:原研究状态、失败和时钟不被重置;user_experience 为 improved:正常 worker 产物终于可以进入显式恢复路径,拒绝仍保持原证据。实际长程模型效果、评分器/counter恢复和剩余实验预算未在此资格化,因此这是 justified_increment,不是整个 campaign 已完成的结论。

检查的是显式 benchmark CLI、Docker/native provider 与原阶段的恢复路径,没有改变任何渲染页面、Lark 界面或首屏。真实 campaign 的持续效果不属于此界面审查;没有渲染表现变更。最强剩余限制是 native API/存储版本适配和实际运行采纳:额外存储目前明确拒绝,真实后续运行仍须原 owner 验证。没有实际benchmark、评分请求、付费solver或原状态恢复动作。

保留旧收据兼容性有实际持久化依据;本次已完成同域的共享 stream/base路径整理。没有发现必须再引入抽象、策略、权限或表单的理由。本评论不授予合并、启动或恢复权限;发布后仍会单独读取 approval closeout,报告任何旧review/thread或平台策略持有。

English verdict: APPROVE — the exact head fixes the production stream mismatch, rejects unsealed native stores, and validates one bounded preserved-session handoff with unchanged defaults and authority.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant