scripts/toolperf_abeval/README.md
The hard A/B evaluation used for the August 2026 core-toolset performance batch (tracker: #77056). It measures whether a set of tool-layer changes actually reduces model waste — LLM turns, tool calls, tool errors, retries, result bytes, wall clock — on a battery of error-inducing tasks, each derived from a waste class measured in real production traffic.
baseline and fixes runs differ ONLY by
PYTHONPATH (a checkout of origin/main vs your integration branch). Same
Hermes home, same model, same tasks, same reps.python vs python3/venv confusion, an
already-applied patch, an ambiguous multi-match edit, wrong-casing search,
hidden-dir search, giant truncated output, cd-heavy multi-dir work, a
blocklist-tripping inline script, and a paginated big-file read. A change
that claims to fix a waste class must move the needle on its trap.llm/tool scope events), plus wall
clock and a per-task programmatic success check (marker strings + on-disk
verification).run_ids in meta.jsonl are skipped, so a
killed battery continues where it left off. Startup crashes (nonzero exit
with empty output) are NOT recorded — they retry on resume instead of
polluting cells (this bit the first pass of the Aug 2026 run).Create a dedicated Hermes home with credentials for the models under test:
export ABEVAL_HOME=/tmp/abeval-home
mkdir -p "$ABEVAL_HOME"
# minimal config.yaml + provider key, e.g. OpenRouter:
cat > "$ABEVAL_HOME/config.yaml" <<'YAML'
model:
provider: openrouter
YAML
printf 'OPENROUTER_API_KEY=%s\n' "$KEY" > "$ABEVAL_HOME/.env"
HERMES_HOME=$ABEVAL_HOME hermes plugins enable observability/nemo_relay
Prepare the two trees:
git worktree add /tmp/abeval-baseline origin/main
# fixes tree = your integration branch checkout
cd scripts/toolperf_abeval
export ABEVAL_ROOT=/tmp/abeval-workspace # results + sandboxes land here
export ABEVAL_HOME=/tmp/abeval-home
./run_all.sh /tmp/abeval-baseline /path/to/fixes-tree 3 \
"anthropic/claude-sonnet-4.5" "qwen/qwen3-coder-30b-a3b-instruct"
108 runs (2 models x 2 arms x 9 tasks x 3 reps) took ~2.5h on the original battery. Re-print tables any time:
python3 ab_eval.py report --models "anthropic/claude-sonnet-4.5,qwen/qwen3-coder-30b-a3b-instruct"
meta.jsonl tail) before calling it a regression.Add a task by appending to TASKS (the prompt), make_sandbox (the trap),
and SUCCESS (the programmatic check). Keep checks strict and mechanical —
marker strings and on-disk state, never judge-by-vibes.