feat(bench): phase-2 suites, execution-result grader, LLM judge, and cross-arm report (#943)#952
Merged
Merged
Conversation
…cross-arm report (#943) Extend the agent-effectiveness benchmark from the phase-1 pilot to the full phase-2 instrument. The ablation is still the platform config, holding the model, prompt scaffold, seed data, and task set constant. Arms: a1 (enrichment-only) and a3 (lifecycle-ready) join a0 and a2 as config profiles. a1 configures the semantic provider so trino_*/s3_* results carry DataHub context while the persona withholds search and datahub_* tools, isolating enrichment from discovery; a3 adds the memory and apply_knowledge surface over a2. Every task applies to all four arms. Task set: 87 generated tasks with ground truth computed from the seeded rows. S1 discovery (17, entity-graded), S2 analytical accuracy (45 numeric across BIRD-style tiers plus four SQL-producing tasks), and S3 knowledge traps (25) across six seeded trap classes: units_cents, net_revenue, deprecated_table, and the new fiscal_calendar, freshness_cutoff, and tier_boundary. The generator asserts each trap's plausible-but-wrong reading differs from the knowledge-informed one. Graders: an execution-result (BIRD-style) grader executes a task's produced and reference queries and compares result sets as row multisets; it runs through a dedicated admin session isolated from attempt audit accounting, and caches the reference per task. A transport failure on a candidate query is a harness failure, not a graded miss. Judge: a versioned rubric (bench/judge/rubric.yaml) with a pinned model scores the judgment-call caveat items; its agreement with a 30-item human-labeled calibration set is computed by bench-calibrate. Report: benchrun -compare builds the cross-arm comparison (arm-by-suite accuracy with fixed-seed bootstrap CIs, pass^k, efficiency, the S3 trap-class breakdown, and per-arm deltas) and renders a markdown page. The per-attempt identity pool grows to 264 keys to cover the full task set at k=3. make verify and make bench-test pass; the benchmark module stays out of verify by design.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #952 +/- ##
=======================================
Coverage 89.04% 89.04%
=======================================
Files 424 424
Lines 48581 48581
=======================================
Hits 43260 43260
Misses 3547 3547
Partials 1774 1774 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Part of #930. Implements phase 2 (#943): the full agent-effectiveness benchmark instrument, extending the phase-1 pilot (#942) from a 10-task A0-vs-A2 probe to all four arms, three suites, deterministic plus execution-result graders, a versioned LLM judge, and a cross-arm report generator.
The design principle is unchanged: the benchmark ablates the PLATFORM, not the model. Every run holds the model, prompt scaffold, seed data, and task set constant, and varies only the platform configuration. The benchmark module stays a separate Go module, excluded from
make verifyby design, and its checks run viamake bench-test.Arms
All four arms are platform config profiles under
bench/config/, not code forks. Each ablates one layer.a0trino_*,s3_*); no semantic provider, no search, cross-enrichment off, search-first gate off.a1trino_*/s3_*results carry DataHub context automatically, but the persona withholdssearchanddatahub_*, so enrichment runs without the discovery layer. This isolates enrichment's effect.a2searchtool, the search-first gate, and seeded knowledge pages. The shipped semantic-first configuration.a3apply_knowledgesurface. On the single-episode S1-S4 suites it tracks A2 (nothing to recall yet); the lifecycle effect is measured by the S5 protocols in #944.All four profiles parse and validate against the real
platform.LoadConfigandConfig.Validate. The DataHub arms (a1,a2,a3) require a DataHub quickstart seeded viamake bench-seed-datahub.Task set
87 tasks, generated deterministically from one fixed-seed dataset model; every ground truth is computed from the seeded rows, never hand-typed. Every task applies to all four arms.
legacy_orders, the gross-only and stale nature of the pre-aggregated index).units_centsnet_revenuefiscal_calendarfreshness_cutofftier_boundarydeprecated_tablelegacy_ordersis a partial, deprecated extract; the deprecation lives in metadata and the warehouse page.The generator asserts, for every trap, that the naive reading differs from the knowledge-informed reading, so a trap that stops trapping fails the build.
Execution-result grader (BIRD-style)
SQL-producing tasks put a query on the FINAL ANSWER line. The grader extracts it, executes the candidate and the task's reference query, and compares result sets as multisets of rows by cell value (column aliasing and row order do not matter). The grader runs its queries through a dedicated admin-credentialed session, separate from every attempt handle, so its own tool calls never perturb an attempt's audit accounting; the reference result is cached per task. A transport failure on a candidate query is classified as a harness failure, not scored as a wrong answer, while a query that does not run is the agent's graded miss.
LLM judge
The deterministic graders score numbers and entities; the judge scores only the judgment-call rubric items they cannot, namely whether an S3 answer carried the required caveat. The judge model is pinned and the rubric versioned (
bench/judge/rubric.yaml), so a judge or wording change bumps the version and historical scores stay attributable. The judge's agreement with human labels is computed over a committed 30-item calibration set (bench/judge/calibration.yaml) viamake bench-calibrate.Cross-arm report
benchrun -compareloads one results JSON per arm and renders the arm-by-suite comparison: accuracy with 95% percentile bootstrap CIs, pass^k, median and p90 tool calls, the S3 trap-class breakdown, and the headline per-arm accuracy deltas versus the baseline. The bootstrap uses a fixed resampling seed, so identical inputs produce identical intervals.make bench-comparewrites the markdown page; the report also flags a run whose arms drifted in task-set hash or model.Identity pool
The per-attempt identity pool grows from 32 to 264 keys, sized to cover the full 87-task set at k=3 (261 attempts). The keys use compact flow-style YAML; a regeneration snippet is documented in
bench/README.md.Commands
Verification
make verifygreen; the root runtime is unchanged (the bench module is excluded from./...).make bench-testgreen: build, vet,go test ./..., andgolangci-lint(0 issues, same complexity ceilings as the root).What remains before #943 fully closes
One documented grader limitation: an unfenced multi-line SQL answer with no code block is truncated to its first line. The task prompt and the run's format instruction steer models to a single line or a fenced block (both fully supported), so this only affects a non-compliant answer shape.