Skip to content

feat(bench): HarnessBench 评测适配层——generic_cli 桥接、harness/bare 双模式与机器审计 - #276

Open
LnYo-Cly wants to merge 24 commits into
mainfrom
feature/integrate-harnessbench
Open

feat(bench): HarnessBench 评测适配层——generic_cli 桥接、harness/bare 双模式与机器审计#276
LnYo-Cly wants to merge 24 commits into
mainfrom
feature/integrate-harnessbench

Conversation

@LnYo-Cly

Copy link
Copy Markdown
Owner

概要

为 ai4j 建立 HarnessBench 2.0 评测适配(task task_87fb0b8c6e06e1c49f5dbc260a):

  • benchmarks/harnessbench-ai4j/ 独立评测目录:不进生产 Maven 模块,HarnessBench 的 Python/Docker 依赖不进 SDK
  • Java bridge:每轮一个新 JVM,generic_cli 官方适配器经 HARNESSBENCH_* env 驱动
    • harness 模式:CodingAgentHarness 文件持久化,跨轮/跨进程按 session 解析绑定既有 runtime Task(动态 Task,不预注册 bench task_id)
    • bare 模式:transcript-replay 对照组,审计如实报告无持久化状态
  • 机器审计harness_audit.json 从磁盘 store 读回投影(tasks/executions/checkpoints/waits/gates/tool invocations/idempotency 计数),execution_trace.json 每轮时间线;不含 prompt/凭据
  • 协议回归(无模型依赖,25 断言全绿):动态 Task 创建、跨进程续跑、有界切片 checkpoint 持久化+恢复、异步工具 WAITING 持久开等待、provider 失败退出码 1、bare 对照
  • 退出码契约:0=可继续(含 WAITING/BLOCKED/IN_REVIEW)1=FAILED 2=UNKNOWN/CANCELLED(禁止盲重试)
  • docs/COVERAGE.md:8 个任务类别 × 5 个证据通道(官方 oracle / LLM rubric / 协议 smoke / 自定义审计 / 模块套件)的归属矩阵

验证

  • benchmarks/harnessbench-ai4j/tests/run_protocol_tests.sh → 25 passed, 0 failed
  • mvn -pl ai4j-harness -DskipTests=false test → Tests run: 50, Failures: 0, Errors: 0
  • 生产模块零改动(diff 仅 benchmarks/)

未执行(显式记录)

  • 真实模型跑分:需 AI4J_BENCH_API_KEY(环境 blocker,非跳过声明)
  • Docker 隔离路径:bridge 与其他 CLI adapter 同为 host 运行

- benchmarks/harnessbench-ai4j: 独立评测目录,不进入生产 Maven 模块
- Java bridge (HarnessBenchBridge): 每轮新进程,HARNESSBENCH_* env 驱动;
  harness 模式走 CodingAgentHarness 文件持久化,跨轮按 session 解析绑定
  既有 runtime Task;bare 模式为 transcript-replay 对照组
- 审计: harness_audit.json 从磁盘 store 读回投影(tasks/executions/
  checkpoints/waits/gates/...),execution_trace.json 每轮时间线;不含
  prompt/凭据
- 协议回归: tests/run_protocol_tests.sh 6 场景 25 断言全绿(无模型依赖);
  audit/check_audit.py 按能力条件断言、未覆盖项如实报 not exercised
- 退出码契约: 0=可继续(含 WAITING/BLOCKED) 1=FAILED 2=UNKNOWN/CANCELLED
…表示暴露

行为保持不变的清理,让既有 quality-gates 门(maxAllowedViolations=0)在含
ai4j-harness 的 reactor 上通过;不改任何门配置。spotbugs:check 0 findings,
模块测试 50/50 绿。
真实模型跑分发现的两处桥接缺陷(非 kernel 缺陷):
1. live 运行误设 includeBuiltInTools(false),模型无法操作 workspace(001-file 冒烟暴露)
2. agent 动态任务经 kernel 治理进入 IN_REVIEW 后,下轮 prompt 重绑该任务会被
   HarnessConflictException 拒绝(058 暴露)。修复:IN_REVIEW 时不绑定任务,
   降级为 session-scoped 继续工作,治理状态原样留在审计——不绕过任何门。
协议回归 25/25 绿;057=0.92 059=1.0 105=0.69 106=0.89(gpt-5.6-luna 实跑)。
同模型同任务跨框架对比用:pi(--thinking/--session-id 续跑)、opencode(--pure/-c)、
hermes(oneshot --query-file/--continue,沙箱本地 HERMES_HOME + 专用 config)。
gpt-5.6-luna 网关间歇性 5xx(temporarily unavailable/upstream),裸连一次即败整轮。
RetryingModelClient 对瞬态错误做 3 次退避重试;协议回归 25/25 绿。
AgentContext→AgentPrompt 的 reasoning 字段在 Chat 面最后一步丢失,思考等级无法
随请求下发。补 String→reasoningEffort 映射;ai4j-agent 395 测试全绿。
对照臂 wrapper 默认切 gpt-5.6-terra/medium(bench 评测配置)。
- AI4J_BENCH_WALL_SECONDS(默认900s) 避免内核默认 300s 墙钟截断长轮
- README 记录同模型同等级五行对照与裸配置说明
- BuiltInTools 新增 strictTool 工厂;write_file/edit(参数全必填)开
  strict=true + enforceStrictSchema(),provider 侧保证调用符合 schema
- read_file/glob/grep(可选参数)与 bash/apply_patch(多态参数)保持
  non-strict:OpenAI strict 全必填要求与这两类契约冲突
- 系统提示词从 13 行工具复述瘦身为 4 句(角色/工具选择/bash 时机/
  patch 语法),工具清单与参数契约由 API tools 参数承载
- 网关实测 strict:true 透传;ai4j 347 + coding 134 测试全绿,协议回归 25/25
多态 action enum 使 bash 无法表达清晰的参数契约,系统提示词需携带
exec vs start 时机复述句。拆分后:
- bash:command 必填的 exec-only(cwd/timeoutMs 可选),description 承载
  自终止语义;BashToolExecutor 既有 action 缺省 exec 逻辑零改动兼容
- bash_process:action[start,status,logs,write,stop,list] + 进程参数,
  description 承载后台/交互语义;不进 read-only 集合
- CodingAgentBuilder 两名同路由至 BashToolExecutor;旧调用显式传
  action=start 到 bash 仍被执行器受理(运行时向后兼容)
- 系统提示词删除 bash 时机句(task task_57214ea9741edb6864882910b2)

验证:ai4j 348 + agent 395 + harness 50 + coding 134 全绿
命令经 cmd.exe /c / sh -lc 包装启动,Process 对象是 shell;stop 的
destroy/destroyForcibly 只杀 shell,实际工作负载(孙进程)孤儿存活继续
运行(如监听端口)。live 复现:模型调用 stop 自述成功后 python 服务器
仍在监听 8765。

修复:stop 先经 Process.descendants() 反射终止全部后代再杀 shell。
两层 JDK9+ 模块访问规避(Java 8 编译/运行兼容,Java 8 回退旧行为):
- descendants stream 向下转型到 java.util.stream.Stream 接口调用
  forEach(实现类 ReferencePipeline 反射被模块系统拒绝)
- ProcessHandle.destroy 经 java.lang.ProcessHandle 公共接口类反射
  (ProcessHandleImpl 是 package-private,getClass().getMethod 被拒)

验证:standalone 进程树 killed=2、端口释放;coding 134 测试绿;
bp-live5 live 场景 stop 后 8801 监听归零。
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