Conversation
huangruiteng
left a comment
There was a problem hiding this comment.
动机
TB4 对照的结论此前只存在于私有 harness:public 仓库里没有 Terminal-Bench 4.0 的可复算聚合,也没有 TB4 的 verdict/xhigh 报告代码。把这份对照的 public-safe 聚合、评分代码和报告整理进 benchmark/ 是有价值的第二 benchmark 家族,方向我认可;README 的口径声明(官方二值 reward 为主、派生 partial 明确标注为非官方分、机制解释标为假设)也写得清楚。
问题在于本 PR 的落地形态:它在 benchmark/terminal-bench-4/ 下又在仓库里复制了一份已经存在的五臂 harness 与同名 skill,而这份复制本身就带走了只落在单侧的修复。
改动思路
新增 benchmark/terminal-bench-4/:README.md(190 行报告)、data.json(1863 行 pinned 聚合)、agents/(5 个 Harbor adapter,2186 行)、scoring/(4 个文件,414 行)、skills/tb4-five-arm/SKILL.md(191 行);LoopX runtime(modes/ + turn/)按 PR 说明复用 ../swe-marathon/runtime,未重复。
具体改动
benchmark/terminal-bench-4/README.md(+190):五臂定义、评分口径、§3 结论表、§8 代码结构、§9 复现与血缘。benchmark/terminal-bench-4/data.json(1863 行):52 个 matched 任务 × 5 臂的聚合(arm_summary、cells、partial_metric、n_trials=260、denominator=52)。benchmark/terminal-bench-4/agents/*.py(5 个文件):harbor adapter;codex_loopx_agent.py承载三个 LoopX 臂,靠WEN_MODE分模式。benchmark/terminal-bench-4/scoring/*.py(4 个文件):轨迹判定 + xhigh 计数/矩阵出表。benchmark/terminal-bench-4/skills/tb4-five-arm/SKILL.md(191 行):五臂运行协议。
关键代码讲解
- 结论可复算这一点我独立验证通过:从
data.json重算得到 52 题、260 trial、各臂解出 9 / 4 / 4 / 3 / 2(mean 0.173 / 0.077 / 0.077 / 0.058 / 0.038),partial(n=42)为 0.633 / 0.718 / 0.640 / 0.668 / 0.594,与 README §3 表格逐格吻合。 agents/codex_goal_agent.py:47-56改成from loopx.capabilities.benchmark_toolkit.native_codex_goal import ...,并注释"不再 vendored 复制一份"——这个方向是对的,但它与本目录里同时存在的agents/native_codex_goal.py自相矛盾(见阻塞项)。agents/codex_loopx_agent.py:204-250是本 PR 真正的技术增量:as_root时显式docker exec -u root(否则任务 Dockerfile 设了非 root USER 时 as_root 段其实仍以非 root 跑),以及environment.default_user为空时用whoami反查真实用户(risk-scorer-replay/rs-archive-clone这两类题就栽在这里)。agents/codex_offline.py:26,39把硬编码/tmp换成tempfile.gettempdir()。
对主干的风险
阻塞项 1(P1,五臂 harness 与 skill 被复制成两份)。在受审 head 上:
benchmark/terminal-bench-4/skills/tb4-five-arm/SKILL.md与 main 的benchmark/swe-marathon/skills/tb4-five-arm/SKILL.md逐字节相同(shasum 均为1b76d5cebae38252965f495e3d38f1e16522bcbd3172fae189cb2e54dcf1bfc4),也就是同一个name: tb4-five-arm现在有两个权威副本,而这份文件在 main 里本来就有(来自 #3838)。README §9 也写着 "adapter / runtime 的收敛按维护者约定作为后续 follow-up",但这次是移动没删旧入口,不是新增内容。benchmark/terminal-bench-4/agents/{codex_goal_agent,codex_loopx_agent,codex_offline,native_codex_goal}.py与benchmark/swe-marathon/agents/下的同名文件相差 6 / 19 / 3 / 8 行,而且差异全是只落在 tb4 一侧的修复(-u root、whoami探测、tempfile.gettempdir()、toolkit import)。结果是合并当天,"同一套五臂 harness"就已经有两种行为。- 这正是 PR 自己在
codex_goal_agent.py:331记录过的那类偏差("第四次只打一边的偏差,方向是压低 treatment 臂"):同名异常类来自两个模块,于是超时只对 goal 臂生效。现在同一机制被复制到第二个目录,下一次修 harness 的人只要漏改一处,五臂对照就会再次单向失真,而没有任何检查会发现(该路径没有 CI,gh pr checks 4439无 check)。
最小修复(二选一,保持唯一 owner):删除本目录的 skills/tb4-five-arm/SKILL.md(沿用 main 已有的那份),或在同一个 PR 里把它从 benchmark/swe-marathon/skills/ 移走;adapter 侧把上面三处修复落回共享 owner,然后让 tb4 从共享 owner 导入,本目录只保留 data.json + scoring/ + README.md。若确实要先分叉,请在 README §9 写明两份 owner 与收敛条件。
阻塞项 2(P2,agents/native_codex_goal.py 是已发布模块的逐字节副本且无人引用)。该文件与 loopx/capabilities/benchmark_toolkit/native_codex_goal.py shasum 相同(bf5d9bb7cacba617),而它自己的 docstring 第 6 行写着 "so runner implementations do not carry a second copy of that state machine";本目录里也没有 caller——codex_goal_agent.py:49 已经改成 import toolkit 路径。同时 codex_goal_agent.py:331 的注释说它是"符号链接到 wen/loopx 源码树",在公开仓库里并不成立,会误导后续读者。最小修复:删掉这份副本,保留 toolkit import,并把该注释改成真实来源(建议同批回灌到 swe-marathon 副本,让同名异常类的双来源问题彻底消失)。
P3(workspace 索引与可复现路径)。benchmark/README.md 的 Current work 没有把 terminal-bench-4/ 列进去(swe-marathon 与 deepswe 都在);同时 README §8/§9 与 skill 让读者 source env.sh、跑 scripts/*.sh,而 env.sh、scripts/、scoring/xhigh_matrix.py:2 的 /tmp/xhigh_rows.json 都不在仓库里,公开读者按文档无法复现。建议补索引入口,并在 §9 明确"复现需要私有 harness,公共可复算路径只到 data.json"。
P3(公开文件里的本地语汇)。新增文件保留了 wen/loopx 源码树、wen/modes/profiles.py、WEN_MODE/WEN_BENCH/WEN_CLAIM_CODEX_APP、~/.local/share/uv/python/cpython-3.12.13-linux-x86_64-gnu 兜底路径、本机是 4090D、Supabase 注册表说明等本地运行上下文(codex_offline.py:33,142、codex_loopx_agent.py:102,297-306、codex_goal_agent.py:331、SKILL.md:34,51-52)。它们不进入核心控制面,但 wen/ 在公开仓库里没有任何定义,读者无法据此定位代码;建议换成中性说法或标注为本地环境说明。
其余残余风险:本轮未跑任何 harbor/TB4 job,adapter 与三处修复只有静态证据;data.json 与 README 逐格吻合但未从私有结果树重算;head 相对当前 main 是 BEHIND,合并前需 rebase。public boundary scan 本身干净(loopx check --scan-path benchmark/terminal-bench-4/ → 12 文件,0 error / 0 warning),未发现凭证、raw 轨迹或私有链接,9 个新增 py 文件 py_compile 与 git diff --check 均通过。
我的整体评价
REQUEST_CHANGES。这份 packet 最值钱的部分——pinned 聚合、可复算的结论、以及 codex_loopx_agent.py 里那三处真实修复——都值得进主干,我也确认 README §3 的数字能从 data.json 独立重算出来。问题集中在"搬进来时又复制了一份":skills/tb4-five-arm/SKILL.md 与 main 逐字节相同(移动没删旧入口),四个 adapter 与 swe-marathon 副本只差 6/19/3/8 行且差异全是单侧修复,其中一个文件还是已发布 toolkit 模块的逐字节副本且在本目录内无人引用。这不是"重复代码看着像",而是同一份 harness 行为的两个 owner:PR 自己的注释已经记录过一次由此产生的单向评分偏差,而这条路径没有任何 CI 会拦住下一次分叉。删掉重复的 skill 与 adapter 副本(或把三处修复落回共享 owner 后改为导入)、补上 benchmark/README.md 的索引入口,并说明哪些复现步骤需要私有 harness,我按新的 exact head 再复审一次。
English verdict: REQUEST_CHANGES at 8c6591a. The published packet is reproducible on its own terms - I recomputed README section 3 from data.json and got 9/4/4/3/2 solved over 52 tasks, 260 trials, and partial rates 0.633/0.718/0.640/0.668/0.594 on the n=42 subset, matching the table - and the public boundary scan, py_compile and git diff --check are all clean. The blockers are about how the harness arrived: benchmark/terminal-bench-4/skills/tb4-five-arm/SKILL.md is byte-identical (sha 1b76d5ce) to the copy that already exists at benchmark/swe-marathon/skills/tb4-five-arm/SKILL.md, so a move kept both copies; the four adapters under agents/ differ from the swe-marathon copies by only 6/19/3/8 lines, and every difference is a fix that exists only on the TB4 side (docker exec -u root, the whoami probe that recovers the task user, tempfile.gettempdir() instead of a hardcoded /tmp). agents/native_codex_goal.py is byte-identical (sha bf5d9bb7) to the shipped loopx/capabilities/benchmark_toolkit/native_codex_goal.py while nothing in the directory imports it, and its own docstring says runners should not carry a second copy of that state machine; codex_goal_agent.py:331 further describes it as a symlink into a private source tree, which is not true of the committed file. This is the same two-owners-one-behaviour setup the PR's own comment blames for a previous one-sided scoring bias, and no check on this path would catch the next divergence. Please keep one owner for the harness and the skill, keep data.json + scoring/ + README.md here, index the new packet from benchmark/README.md, and state which reproduction steps need the private harness; I will re-review the new exact head.
…tion TB4 v4.0.0 上 plain / goal / ssh-goal / codex-cli / heartbeat 五臂对照, effort 统一 xhigh,模型 GPT-5.6 Sol。 本目录(benchmark/terminal-bench-4/)只发布 TB4 特有的 public-safe 产物: - README.md:二值 Solve@1.0 主指标 + 派生 pytest 测试通过率 partial; 含 goal 家族为何未超过 plain 的 public-safe 分析(早退 vs 续跑被门禁挡住) - data.json:pinned public-safe 聚合,与 README 结论对应(本目录唯一可公众重算的产物) - scoring/:轨迹判定 + xhigh 报告/矩阵生成器 五臂 harness、tb4-five-arm skill 与 LoopX runtime 单一 owner 复用 SWE-Marathon,不再重复一份: - 把 TB4 侧的三处修复(as_root 显式 -u root、反查任务用户 whoami、tempfile.gettempdir()) 回灌到共享 owner benchmark/swe-marathon/agents/ - codex_goal_agent 改为从 loopx.capabilities.benchmark_toolkit.native_codex_goal 导入, 删除已无宿主 caller 的 vendored native_codex_goal.py(toolkit 为唯一 owner, 消除"同名异常类双来源"),并订正相关注释 - benchmark/README.md 索引新增 terminal-bench-4 Signed-off-by: hzeroyuke <14756703760@qq.com> Signed-off-by: Wanli-Lee <wanli_li@zju.edu.cn> Co-authored-by: Wanli-Lee <wanli_li@zju.edu.cn>
11acec0 to
7ae8e60
Compare
huangruiteng
left a comment
There was a problem hiding this comment.
动机
TB4 对照的结论此前只存在于私有 harness,public 仓库里既没有 Terminal-Bench 4.0 的可复算聚合,也没有 TB4 的 verdict/xhigh 报告代码。把这份对照的 public-safe 产物整理进 benchmark/ 是有价值的第二 benchmark 家族,方向我认可。
上一轮我在旧 head(8c6591ad2 → 11acec0c5)提的阻塞项是落地形态:benchmark/terminal-bench-4/ 里又复制了一份已经存在的五臂 harness 与同名 skill,且带走了只落在单侧的修复。作者在新 head 上按"唯一 owner"重做了什么,我逐项核实如下,所以这份 review 是对 7ae8e609834da025c8faa88025b2f446e97f010e 的复审(base main,merge base 0741865f0,12 文件 +2644/-759)。
改动思路
- 共享 harness 收回唯一 owner:
benchmark/terminal-bench-4/只发 TB4 特有的 public-safe 产物(README.md+data.json+scoring/),五臂 Harbor 适配器、tb4-five-armskill 与 LoopX runtime 全部指回benchmark/swe-marathon/{agents,skills,runtime},不再各存一份。 - 单侧修复回灌共享 owner:TB4 侧原本独有的三处修复(
docker exec -u root、default_user为空时用whoami反查任务用户、tempfile.gettempdir()取代硬编码/tmp)落到swe-marathon/agents/,于是"同一套五臂 harness"又只有一种行为。 - 原生 Goal 状态机收回 toolkit 唯一 owner:删掉
swe-marathon/agents/native_codex_goal.py这份 vendored 副本,codex_goal_agent.py改为从loopx.capabilities.benchmark_toolkit.native_codex_goal导入;同名异常类NativeGoalProtocolError因此只剩一份,之前那条"按类捕获会让超时只对 goal 臂生效"的坑在结构上消失。 - 补上 main 里的悬空引用:main 的
swe-marathon/skills/swe-marathon-five-arm/SKILL.md臂表与"已知坑"两处都写着codex_plain_appserver:CodexPlainAppServer/ "新增 codex_plain_appserver.py,plain 也走 app-server",但该文件在 main 上并不存在;本 PR 新增了它。 - 公共可复算面收敛:TB4 README §8/§9 明确"公众可复算路径只到
data.json",需要私有结果树与实验环境编排的部分标注为不可公开复现;scoring/xhigh_report.py/xhigh_matrix.py的中间产物路径改为$TB4_ROWS(缺省落系统临时目录),不再写死/tmp/xhigh_rows.json。
具体改动
benchmark/terminal-bench-4/在新 head 只剩 6 个文件:README.md、data.json、scoring/{verdict,check_rerun,xhigh_report,xhigh_matrix}.py;旧 head 里的agents/(4 个文件)与skills/tb4-five-arm/SKILL.md已删除,git ls-tree -r 7ae8e6098 benchmark/terminal-bench-4可核。benchmark/swe-marathon/agents/codex_loopx_agent.py:as_root分支显式docker exec -u root(:201-208),并在default_user为空时用whoami探真实任务用户(:236-250,注释点明risk-scorer-replay/rs-archive-clone两类题就栽在这里)。benchmark/swe-marathon/agents/codex_offline.py:26,39:_STAGE_DIR改用tempfile.gettempdir()。benchmark/swe-marathon/agents/codex_goal_agent.py:40-49:删掉sys.path.insert与 vendored 导入,改 import toolkit;:326-336的坑注释重写为"现在只有一个 owner"。benchmark/swe-marathon/agents/native_codex_goal.py删除(-740);git grep 'from native_codex_goal' 7ae8e6098 -- '*.py'只剩runtime/turn/goal_codex.py:497那处容器内 runner 模板(该模板本来就是从 toolkit 路径拷进容器的,见同文件:86),宿主侧已无引用。- 新增
benchmark/swe-marathon/agents/codex_plain_appserver.py(+133):CodexPlainAppServer(CodexGoalAgent)复用父类装配,只把start_native_goal_turn换成_start_turn_without_goal(initialize → thread/start → turn/start,跳过thread/goal/set),name()返回codex-plain-appserver,与 skill 里写的codex_plain_appserver:CodexPlainAppServer对得上。 benchmark/README.md:46-55:新增terminal-bench-4/README.md索引,并写明共享 harness/skill/runtime 的唯一 owner 在swe-marathon/。benchmark/terminal-bench-4/README.md:§8 代码结构改成"本目录只发 public-safe 产物 + 列出复用的共享组件";§9 增加TB4_ROWS,并把WEN_MODE之类的表述换成中性的"运行编排传入的模式开关"。
我在新 head 上实测:benchmark/terminal-bench-4/data.json 可独立重算出 §3 的口径(plain 9/52 mean 0.173、ssh-goal 4/52、codex-cli 4/52、heartbeat 3/52、goal 2/52,与 README 表一致);loopx check --scan-path benchmark/terminal-bench-4/ → public boundary scan clean: 6 files,--scan-path benchmark/swe-marathon/agents/ → clean: 4 files;新增/改动的 8 个 py 文件 py_compile 通过;git diff --check 干净。gh pr checks 4439 仍是 no checks reported(benchmark/** 在这条路径上没有 CI,这一点本轮不变)。
对主干的风险
上一轮的两个阻塞项已核实解决。 我按旧 head 的判据逐条复核:五臂 harness 与 skill 不再有第二份副本(tb4 目录只剩 README/data.json/scoring);native_codex_goal.py 的逐字节副本已删除,且删得安全——宿主机侧唯一引用者已改指 toolkit,容器侧模板本来就取 toolkit 路径;三处只存在于 TB4 侧的修复已回灌共享 owner,因此"合并当天就有两种行为"的问题消失。benchmark/README.md 的索引入口、TB4 README 对"需要私有 harness"的说明、scoring 的 /tmp 硬编码也一并修掉了。
新 head 上还剩三处不阻塞的问题:
- P2(新文件复刻了 toolkit 的请求组装):
codex_plain_appserver.py:41-104的_start_turn_without_goal把initialize+thread/start+turn/start的参数拼装从loopx.capabilities.benchmark_toolkit.native_codex_goal.start_native_goal_turn(:262-290)"照抄"了一份,只是去掉attach_native_goal那一步。这正是本 PR 刚消灭的"同一套协议行为两个 owner":toolkit 那边一旦给turn/start加参数(历史上就出现过这类偏差),只有 goal 臂会拿到,五臂对照会再次静默失衡,而这条路径没有 CI。更小的做法是在 toolkit 里留一个真正的缝,例如start_native_goal_turn(..., attach_goal: bool = True)(或把thread/start与turn/start拆成可组合的两步),让 plain 臂调用同一个 owner——行为不变,但"两条臂除了有没有 Goal 之外完全一致"由结构保证,而不是由注释保证。另外该文件的 docstring 现在声称"除有没有 Goal 之外的一切与 goal 臂逐字一致",但clientInfo已经不一致(见下条),这句话应当修正。 - P3(PR 描述与 head 不符):PR 正文仍写着本 PR 含
agents/、skills/tb4-five-arm/SKILL.md、三个 LoopX 臂"靠WEN_MODE区分",验证段落也还是"12 文件"。这些描述对应的是旧 head,现在目录里已不存在;squash 合并后这段正文就是合并历史,建议在合并前改成与当前 head 一致(只发README.md + data.json + scoring/,harness/skill/runtime 复用swe-marathon/,并说明新增的 plain app-server 适配器与它带来的口径变化)。 - P3(新增公开文件里的本地语汇):
codex_plain_appserver.py:49-50的clientInfo写作"name": "wen_plain_appserver","title": "wen plain (app-server, no Goal)",其余四臂走 toolkit(native_codex_goal.py:190-193的loopx_benchmark_toolkit)。这里wen/在公开仓库里没有定义,读的人无法据此定位代码;而且它恰好推翻了同文件"与 goal 臂逐字一致"的说法。建议换成中性名(如plain_appserver/codex plain (app-server, no Goal)),若确实需要让服务端能按身份区分 plain 臂,请在注释里写明这是有意差异。
其余残余风险:本轮未跑任何 harbor/TB4 job,适配器改动只有静态证据(新增的 plain 臂尤其如此);data.json 的数值来自私有结果树,公开可复算的只是"表格 ↔ 聚合"这一层;新增的 plain app-server 适配器让 main 上那条悬空引用变成真实文件,但历史 swe-marathon 结果里的 plain 臂是用 codex exec 跑的,两者传输不同,比较时必须注明(skill 的"已知坑"§3 已经这么写,建议在 README/简报层面也保留这句)。public/private 边界扫描干净,未发现凭证、raw 轨迹、私有链接或宿主机路径进入仓库。
我的整体评价
REQUEST_CHANGES,但只差最后三小步。这一版把上一轮的形态问题真正修掉了,而且是往正确的方向修:TB4 变成"只发聚合与评分代码"的 packet,五臂 harness、skill、runtime、原生 Goal 状态机各自回到唯一 owner,只落在 TB4 侧的三处修复回灌到共享 owner,删掉的 vendored 副本在宿主机侧确实无人引用;benchmark/README.md 的索引与"公众可复算路径只到 data.json"的说明也都补上了。剩下的是新引入的 133 行 plain 适配器:它照抄了 toolkit 的请求组装(P2,建议在 toolkit 留一个 attach_goal 缝)、文件内的 wen_ 命名与"逐字一致"自述相互矛盾(P3),以及 PR 正文仍描述已被删除的文件(P3)。这三处都很小,改完我按新的 exact head 再复审一次;本轮不做合并动作。
English verdict: REQUEST_CHANGES at 7ae8e609834da025c8faa88025b2f446e97f010e. This re-review confirms the two blockers from the previous head are resolved: benchmark/terminal-bench-4/ now ships only README.md, data.json and scoring/, with the five-arm adapters, the tb4-five-arm skill and the LoopX runtime single-owner under swe-marathon/; the three fixes that existed only on the TB4 side (docker exec -u root, the whoami task-user probe, tempfile.gettempdir()) are backported into that shared owner; the byte-identical vendored agents/native_codex_goal.py is deleted and codex_goal_agent.py imports the shipped toolkit module, so the duplicated NativeGoalProtocolError class is gone; benchmark/README.md now indexes the packet, TB4 README section 8/9 states that only data.json is publicly recomputable, and the scoring scripts no longer hardcode /tmp. Verified at this head: data.json recomputes the README section 3 table (plain 9/52, ssh-goal 4/52, codex-cli 4/52, heartbeat 3/52, goal 2/52), public boundary scans are clean (6 files / 4 files), py_compile and git diff --check pass, and no remaining host-side import of the deleted vendored module exists. What remains: the new codex_plain_appserver.py re-implements the toolkit turn/start request shaping instead of using a single-owner seam (P2 - this is the same duplicate-owner failure mode the PR just removed, and the path has no CI), its clientInfo identity is wen_plain_appserver while the other four arms send loopx_benchmark_toolkit (P3 - local vocabulary in a new public file, and it contradicts the file's own claim that everything except the Goal step matches the goal arm), and the PR description still lists agents/ and skills/tb4-five-arm/SKILL.md, which no longer exist at this head (P3 - the squash-merged body becomes the merged history). No merge performed this round.


在 benchmark/terminal-bench-4/ 下加入一份 codex×LoopX 评测:裸 codex、codex 原生 goal、以及三种 LoopX 模式(ssh-goal / codex-cli / heartbeat)在 Terminal-Bench 4.0(harbor-framework,tag v4.0.0)52 个 matched 任务上的对照(模型 GPT-5.6 Sol,effort 统一 xhigh,预算 ~30%)。
本 PR 为合并后的单一 PR,含:
证据与对照边界
验证
Review hold
探索性研究贡献。TB4 属新增对照;可按 maintainer 偏好对齐其发布形式(如托管一份 brief),或按 benchmark workspace 关于"maintainer 所有/未发布对照"的政策先挂靠一个公开 issue。本 PR 不启动任何 benchmark job、不改动评分/runner 行为;合并前仍应经 maintainer 显式 review。
Co-authored-by: Wanli-Lee wanli_li@zju.edu.cn