Skip to content

Add the agent eval harness - #5

Merged
galjos merged 1 commit into
mainfrom
feat/agent-eval-harness
Aug 3, 2026
Merged

Add the agent eval harness#5
galjos merged 1 commit into
mainfrom
feat/agent-eval-harness

Conversation

@galjos

@galjos galjos commented Aug 3, 2026

Copy link
Copy Markdown
Owner

odh-cli has had an agent eval harness since v0.3.0; pitstop had no evals/ directory at all. That gap is why the mcp 2.0.0 breakage was found by reading rather than by CI.

Same layout, filenames, JSON field names and ok - output style as the sibling repo, so the two read alike. python3 replaces jq — an eval suite for a stdlib-only runtime shouldn't require installing a tool to run it.

What it checks

31 live assertions over the contracts an agent actually depends on: envelope provenance, the quality block's screened/unscreened accounting being self-consistent with the prices returned, median_basis on every price, outlier present only when true, an unscreened price carrying no median to compare against, GeoJSON [lon, lat] ordering, bilingual comune resolution, and the table path naming its own source.

Where it runs, and why it's split

Per odh's stated rule in docs/evaluation.md, the live half is a weekly canary — a contributor can do nothing about MIMIT or Overpass being down, so it must not block a PR.

What runs per-PR is the offline half: every command string in recipes.json and tasks.json is parsed against the shipped argparse parser, so a recipe can never name a command the CLI cannot run. odh shipped exactly that bug for two releases, so the guard is in from day one.

Overpass

Reuses the canary's policy rather than inventing a second one — same retry ladder, empty answer warns, dishonest envelope fails. Two corrections found in review:

  • Empty is classified on count alone. Overpass also sheds load with a valid HTTP 200 carrying no elements and no remark, which leaves error unset — that was classifying as usable and running the data assertions against nothing.
  • 403 joins 429 as upstream's fault. It's how overpass-api.de blocks a shared client IP, not a rejected query.

Review corrections worth noting

  • The --fuel substring caveat only warned in one direction. Verified live: --fuel Gasolio also returns Gasolio Premium, speciale, Alpino and artico — 8 distinct names in BZ alone, so a premium blend gets ranked against ordinary diesel.
  • The coordinate_suspect definition was wrong: the comparison is against the median of the comune's own stations, with the ISTAT reference point only as fallback.
  • The mis-geocoded task pointed at a Bolzano query that surfaces zero flagged stations, making three of its pass criteria unfollowable. Repointed at Milan, where ROMENTINO (Novara) shows up as the 7th nearest station at 1.02 km while actually being ~30 km away — a much better illustration of the failure.

odh-cli has had one since v0.3.0; pitstop had no evals directory at all,
which is why the mcp 2.0.0 breakage was found by hand rather than by CI.
Same layout, filenames, JSON field names and "ok - " output style as the
sibling repo, so the two read alike.

python3 replaces jq. An eval suite for a stdlib-only runtime should not
require installing a tool to run it; assert.py takes the same
(label, file, expression) shape jq -e had.

31 live assertions over the contracts an agent actually depends on: the
envelope's provenance and quality accounting, that median_basis is on
every price, that outlier appears only when true, that an unscreened
price carries no median to compare against, GeoJSON [lon, lat] ordering,
and that the table path names its source too.

Split across the two workflows, following the rule odh states in
docs/evaluation.md: the live half is a weekly canary because a
contributor can do nothing about MIMIT or Overpass being down. What runs
per-PR is the offline half — every command string in recipes.json and
tasks.json is parsed against the shipped argparse parser, so a recipe can
never name a command the CLI cannot run. odh shipped exactly that bug for
two releases.

Overpass reuses the canary's policy rather than inventing a second one:
the same retry ladder, and an empty answer is a warning while a
dishonest envelope is a failure. Empty is classified on count alone,
since Overpass also sheds load with a valid 200 carrying no elements and
no error at all. 403 joins 429 as upstream's fault — it is how
overpass-api.de blocks a shared client IP, not a bad query.
@galjos
galjos merged commit 40aa960 into main Aug 3, 2026
5 checks passed
@galjos
galjos deleted the feat/agent-eval-harness branch August 3, 2026 08:19
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