From 513f02e969ffd136f0a5d4e2e00f6e1bff80d995 Mon Sep 17 00:00:00 2001 From: Bai Li Date: Wed, 8 Jul 2026 15:51:21 -0700 Subject: [PATCH 1/4] feat(evalboard): add a Harness (RunConfig) column to the runs tables Read the run-level RunConfig (harness/model/environment) that eval_runner stamps into run.json, falling back to the most common per-task agent_config.type, and show the harness on the main + ad-hoc runs tables. Environment (alpha/prod) is captured on the run overview but intentionally not surfaced yet. Co-Authored-By: Claude Opus 4.8 (1M context) --- evalboard/app/page.tsx | 12 +++++- evalboard/lib/__tests__/runs.test.ts | 36 ++++++++++++++++++ evalboard/lib/overview.ts | 6 +++ evalboard/lib/runs.ts | 55 ++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 1 deletion(-) diff --git a/evalboard/app/page.tsx b/evalboard/app/page.tsx index dc57bb89..e3a1223a 100644 --- a/evalboard/app/page.tsx +++ b/evalboard/app/page.tsx @@ -330,6 +330,7 @@ export default async function Page({ Run + Harness Pass rate @@ -363,6 +364,9 @@ export default async function Page({ {fmtRunTime(r.id)} + + {r.harness ?? "—"} + {isFiltered @@ -454,6 +458,9 @@ export default async function Page({ Run + + Harness + Date @@ -503,6 +510,9 @@ export default async function Page({ )} + + {r.harness ?? "—"} + {fmtTimestamp(r.startedAt)} diff --git a/evalboard/lib/__tests__/runs.test.ts b/evalboard/lib/__tests__/runs.test.ts index e0d47cc3..5fd0c719 100644 --- a/evalboard/lib/__tests__/runs.test.ts +++ b/evalboard/lib/__tests__/runs.test.ts @@ -15,6 +15,7 @@ import { type ArtifactRef, clearRunCacheDir, extractComponentShas, + extractRunConfig, findMatureSourceRuns, isExcludedArtifact, type MessageEvent, @@ -346,6 +347,41 @@ describe("extractComponentShas", () => { }); }); +describe("extractRunConfig", () => { + test("prefers the run-level RunConfig stamp (harness + environment)", () => { + const out = extractRunConfig({ + environment_info: { + run_config: { + harness: "codex", + model: "gpt-5.4", + environment: "prod", + }, + }, + }); + expect(out.harness).toBe("codex"); + expect(out.environment).toBe("prod"); + }); + + test("falls back to the most common per-task agent_config.type", () => { + const out = extractRunConfig({ + task_results: [ + { task_id: "a", agent_config: { type: "antigravity" } }, + { task_id: "b", agent_config: { type: "antigravity" } }, + { task_id: "c", agent_config: { type: "claude-code" } }, + ], + }); + expect(out.harness).toBe("antigravity"); + // environment is only known from the run-level stamp, never derived. + expect(out.environment).toBeNull(); + }); + + test("null harness when nothing identifies it (legacy runs)", () => { + const out = extractRunConfig({ task_results: [{ task_id: "a" }] }); + expect(out.harness).toBeNull(); + expect(out.environment).toBeNull(); + }); +}); + describe("findMatureSourceRuns", () => { // Newest-first run list with injected run.json readers (the deps test seam). const ids = ["r5", "r4", "r3", "r2", "r1"]; diff --git a/evalboard/lib/overview.ts b/evalboard/lib/overview.ts index f2cf064f..89c3cf83 100644 --- a/evalboard/lib/overview.ts +++ b/evalboard/lib/overview.ts @@ -95,6 +95,10 @@ export interface RunListingRow { tasksRun: number; totalCostUsd: number | null; taskDurationSeconds: number | null; + // Run-level harness (coder-eval AgentKind) for the Harness column; null on + // legacy runs that predate the RunConfig stamp / carry no agent_config.type. + // Optional so existing test factories stay valid. + harness?: string | null; } // Window-level rollup across every matched run (pre-limit), so the front-page @@ -680,6 +684,7 @@ export async function getRunListing( tasksRun: scopedTasks.length, totalCostUsd: scopedCost, taskDurationSeconds: scopedDur, + harness: overview.harness ?? null, }); } @@ -735,6 +740,7 @@ export function buildAdhocRows( tasksRun: overview.tasks.length, totalCostUsd: overview.totalCostUsd, taskDurationSeconds: overview.taskDurationSeconds, + harness: overview.harness ?? null, }); } rows.sort( diff --git a/evalboard/lib/runs.ts b/evalboard/lib/runs.ts index 2e874940..ef682c10 100644 --- a/evalboard/lib/runs.ts +++ b/evalboard/lib/runs.ts @@ -346,6 +346,10 @@ interface RawTaskResult { // Model the task ran on (e.g. "claude-sonnet-4-6"). Used to price token // buckets as USD. Absent on legacy runs. model_used?: string | null; + // Per-task agent config; `type` is the harness (coder-eval AgentKind, e.g. + // "claude-code" | "codex" | "antigravity"). Used to derive the run's harness + // when the run-level RunConfig stamp is absent (direct coder-eval / legacy runs). + agent_config?: { type?: string | null } | null; // Activation enrichment the dashboard folds onto each case row in the nested // activation run.json (see cli.py _finalize_activation_run). Absent on skills // rows. `prompt` = the case's prompt text; `expected_skill` = the skill the @@ -790,6 +794,12 @@ export interface RunOverview { totalCostUsd: number | null; taskDurationSeconds: number | null; componentShas: ComponentSha[]; + // Run-level harness (coder-eval AgentKind) from the RunConfig stamp + // (environment_info.run_config), falling back to the most common per-task + // agent_config.type. `environment` (alpha/prod) is captured but intentionally + // NOT surfaced in the UI yet. Both optional so test factories predating them stay valid. + harness?: string | null; + environment?: string | null; // run.json `start_time` (ISO wall-clock). Pipeline runs derive their date // from the date-shaped id; ad-hoc ids carry no date, so the ad-hoc listing // orders by this instead. Optional so test factories predating it stay valid. @@ -814,6 +824,50 @@ export function visibleTurnsFromRaw(t: { return null; } +// The run's harness + environment. Prefers the run-level RunConfig stamped by +// eval_runner into environment_info.run_config; falls back to the most common +// per-task agent_config.type (direct coder-eval / legacy runs carry no stamp). +// Returns null harness when nothing identifies it (legacy pre-harness runs). +export function extractRunConfig(data: RawRunJson): { + harness: string | null; + environment: string | null; +} { + const rc = data.environment_info?.run_config; + if (rc && typeof rc === "object" && !Array.isArray(rc)) { + const r = rc as Record; + return { + harness: typeof r.harness === "string" ? r.harness : null, + environment: + typeof r.environment === "string" ? r.environment : null, + }; + } + return { + harness: mostCommonAgentType(data.task_results ?? []), + environment: null, + }; +} + +// Most frequent per-task agent_config.type across a run's rows, or null if none +// declare one. A run is single-harness in practice, so this is just a robust +// "the harness these tasks ran on" for runs without the run-level stamp. +function mostCommonAgentType(rows: RawTaskResult[]): string | null { + const counts = new Map(); + for (const r of rows) { + const t = r.agent_config?.type; + if (typeof t === "string" && t) + counts.set(t, (counts.get(t) ?? 0) + 1); + } + let best: string | null = null; + let bestN = 0; + for (const [t, n] of counts) { + if (n > bestN) { + best = t; + bestN = n; + } + } + return best; +} + export async function readRunOverview( id: string, ): Promise { @@ -859,6 +913,7 @@ export async function readRunOverview( ? taskDurationSum : (data.total_duration_seconds ?? null), componentShas: extractComponentShas(data.environment_info), + ...extractRunConfig(data), startedAt: data.start_time ?? null, }; } From 3e35a89cbcfd6c04c9313a67c30f33fd7e355e25 Mon Sep 17 00:00:00 2001 From: Bai Li Date: Wed, 8 Jul 2026 16:31:20 -0700 Subject: [PATCH 2/4] feat(evalboard): add Gemini rates to the frontend pricing table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirror the five Gemini models from src/coder_eval/pricing.py into lib/pricing.ts so the Tokens↔USD toggle and per-message cost column price Antigravity/Gemini runs instead of showing "—". Repoint the pricing-parity drift guard at the post-proxy-removal pricing.py path (the file moved in #463), restoring the test that enforces this mirror. Co-Authored-By: Claude Opus 4.8 (1M context) --- evalboard/lib/__tests__/pricing-parity.test.ts | 6 +++--- evalboard/lib/pricing.ts | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/evalboard/lib/__tests__/pricing-parity.test.ts b/evalboard/lib/__tests__/pricing-parity.test.ts index 9100682a..5fe056d6 100644 --- a/evalboard/lib/__tests__/pricing-parity.test.ts +++ b/evalboard/lib/__tests__/pricing-parity.test.ts @@ -5,7 +5,7 @@ import { describe, expect, test } from "vitest"; import { PRICING } from "../pricing"; // Drift guard: lib/pricing.ts is a hand-copied mirror of the authoritative -// Python table in src/coder_eval/proxy/pricing.py. If the backend reprices a +// Python table in src/coder_eval/pricing.py. If the backend reprices a // model (or adds one) and this mirror isn't updated, the frontend's "estimated" // USD figures silently disagree with the backend's authoritative Cost on the // same tokens. This test parses the Python table and asserts both tables have @@ -13,7 +13,7 @@ import { PRICING } from "../pricing"; // into a failing build. const here = dirname(fileURLToPath(import.meta.url)); -const PY_PATH = resolve(here, "../../../src/coder_eval/proxy/pricing.py"); +const PY_PATH = resolve(here, "../../../src/coder_eval/pricing.py"); // Match: "model-id": ModelPricing(1.25, 10.0, 1.25, 0.125), const ROW_RE = @@ -36,7 +36,7 @@ function parsePythonTable(): Record< return out; } -describe("pricing.ts ↔ proxy/pricing.py parity", () => { +describe("pricing.ts ↔ pricing.py parity", () => { const py = parsePythonTable(); test("parses a non-trivial Python table", () => { diff --git a/evalboard/lib/pricing.ts b/evalboard/lib/pricing.ts index 10fada2c..29f27360 100644 --- a/evalboard/lib/pricing.ts +++ b/evalboard/lib/pricing.ts @@ -1,6 +1,6 @@ // Per-million-token prices and cost math. Ported from -// src/coder_eval/proxy/pricing.py — keep in sync when that table changes. -// Source: Anthropic / OpenAI public pricing. +// src/coder_eval/pricing.py — keep in sync when that table changes. +// Source: Anthropic / OpenAI / Google public pricing. // // This is the single source of truth for rates on the frontend: the // cascade-aware thinking-cost simulator (lib/thinkingSim.ts) and the @@ -15,7 +15,7 @@ export interface Pricing { } // Exported so a unit test can assert key-and-rate parity against the -// authoritative Python table (src/coder_eval/proxy/pricing.py) and fail the +// authoritative Python table (src/coder_eval/pricing.py) and fail the // build on drift — this hand-copied mirror is otherwise guarded only by a // comment. Not part of the consumer API; use resolvePricing() instead. export const PRICING: Record = { @@ -41,6 +41,15 @@ export const PRICING: Record = { "gpt-5.3-codex": p(1.75, 14, 1.75, 0.175), "gpt-5.4": p(2.5, 15, 2.5, 0.25), "gpt-5.5": p(5, 30, 5, 0.5), + // Google Gemini (AntigravityAgent). Gemini bills no separate cache-write + // fee (cache_write == input, effectively unused); cache_read is the cached- + // input rate. Pro's >200K-token tier is higher — this flat rate reads low + // for very-large-context runs, fine for typical eval tasks. + "gemini-3-pro-preview": p(2, 12, 2, 0.2), + "gemini-3.1-pro-preview": p(2, 12, 2, 0.2), + "gemini-3.1-pro-preview-customtools": p(2, 12, 2, 0.2), + "gemini-3.5-flash": p(1.5, 9, 1.5, 0.15), + "gemini-3-flash-preview": p(1.5, 9, 1.5, 0.15), }; function p( From 133e69ef6df1165e4129bd66c59fc542defe2f13 Mon Sep 17 00:00:00 2001 From: Bai Li Date: Wed, 8 Jul 2026 17:05:05 -0700 Subject: [PATCH 3/4] feat(evalboard): show harness as a vendor logo (internal, main table only) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the raw harness text in the runs table with the recognizable vendor mark (Anthropic / OpenAI / Google) via a small HarnessBadge, so a run's agent reads at a glance — mirroring the Slack rollup's vendor emoji. Gate the column behind isInternal (edition.ts) and keep it on the main runs table only, dropping it from the ad-hoc table. A missing harness defaults to claude-code (the nightly). Co-Authored-By: Claude Opus 4.8 (1M context) --- evalboard/app/_components/harness-badge.tsx | 37 ++++++++++++++++++++ evalboard/app/page.tsx | 25 +++++++------ evalboard/lib/overview.ts | 2 +- evalboard/public/harness/antigravity.png | Bin 0 -> 4535 bytes evalboard/public/harness/claude-code.png | Bin 0 -> 11502 bytes evalboard/public/harness/codex.png | Bin 0 -> 4600 bytes 6 files changed, 52 insertions(+), 12 deletions(-) create mode 100644 evalboard/app/_components/harness-badge.tsx create mode 100644 evalboard/public/harness/antigravity.png create mode 100644 evalboard/public/harness/claude-code.png create mode 100644 evalboard/public/harness/codex.png diff --git a/evalboard/app/_components/harness-badge.tsx b/evalboard/app/_components/harness-badge.tsx new file mode 100644 index 00000000..a9eca2bf --- /dev/null +++ b/evalboard/app/_components/harness-badge.tsx @@ -0,0 +1,37 @@ +import Image from "next/image"; + +// Vendor logo for a run's harness (RunConfig). Renders the recognizable +// vendor mark instead of raw "claude-code"/"codex"/"antigravity" text, +// mirroring the Slack rollup's vendor emoji. A missing harness defaults to +// claude-code (the nightly). This is an internal-only column — the caller +// gates it behind isInternal (see lib/edition.ts). +const HARNESS_LOGO: Record = { + "claude-code": { + src: "/harness/claude-code.png", + label: "Claude Code · Anthropic", + }, + codex: { src: "/harness/codex.png", label: "Codex · OpenAI" }, + antigravity: { + src: "/harness/antigravity.png", + label: "Antigravity · Google Gemini", + }, +}; + +export function HarnessBadge({ harness }: { harness?: string | null }) { + const key = harness ?? "claude-code"; + const logo = HARNESS_LOGO[key]; + // Unknown harness: show the raw id rather than a misleading logo. + if (!logo) { + return {key}; + } + return ( + {logo.label} + ); +} diff --git a/evalboard/app/page.tsx b/evalboard/app/page.tsx index e3a1223a..5cd66b92 100644 --- a/evalboard/app/page.tsx +++ b/evalboard/app/page.tsx @@ -15,6 +15,7 @@ import { ChipLegend, MergedTagRail } from "./_overview/tag-rail"; import { TableScroll } from "./_components/scroll-table"; import { CollapsibleRail } from "./_components/collapsible-rail"; import { isInternal } from "@/lib/edition"; +import { HarnessBadge } from "@/app/_components/harness-badge"; export const dynamic = "force-dynamic"; @@ -330,7 +331,11 @@ export default async function Page({ Run - Harness + {isInternal && ( + + Harness + + )} Pass rate @@ -364,9 +369,13 @@ export default async function Page({ {fmtRunTime(r.id)} - - {r.harness ?? "—"} - + {isInternal && ( + + + + )} {isFiltered @@ -458,9 +467,6 @@ export default async function Page({ Run - - Harness - Date @@ -510,9 +516,6 @@ export default async function Page({ )} - - {r.harness ?? "—"} - {fmtTimestamp(r.startedAt)} diff --git a/evalboard/lib/overview.ts b/evalboard/lib/overview.ts index 89c3cf83..68c81568 100644 --- a/evalboard/lib/overview.ts +++ b/evalboard/lib/overview.ts @@ -740,7 +740,7 @@ export function buildAdhocRows( tasksRun: overview.tasks.length, totalCostUsd: overview.totalCostUsd, taskDurationSeconds: overview.taskDurationSeconds, - harness: overview.harness ?? null, + // Harness is a main-table-only (internal) column; ad-hoc rows omit it. }); } rows.sort( diff --git a/evalboard/public/harness/antigravity.png b/evalboard/public/harness/antigravity.png new file mode 100644 index 0000000000000000000000000000000000000000..c46f02e8ab7320fd83ffcc5bbe7ff9dc6b8c901d GIT binary patch literal 4535 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 V+ooRxTmZ8HD9WnI)JmC${Xg~KVFv&J literal 0 HcmV?d00001 diff --git a/evalboard/public/harness/codex.png b/evalboard/public/harness/codex.png new file mode 100644 index 0000000000000000000000000000000000000000..bf3eadc04e0583be0307a9c60987fcdae5a4e07d GIT binary patch literal 4600 zcmZ`-S2WxU_x+9DjS?j~LDU%~qKsaKj5hk{(aGq7L1dD+qeN$P5(H6$(W6EgU36DS zMD$#)5-pMVd@ujC{tw^7IeYDW&R*yBtQ~J^45z2LO#=V`y@9@t*$ra-TQu} z#to2pY8q(*Ktl@c)kE?d&hM&kW&{8cA~$<60Pyoh!tMaTV<-UZIRk)l4gjzR6m%eA zHvZ=*f9#o@X)>tSu-NM;T^G*j1B^b*8oSGdh9RDZl9;j{@)&Gzc z|Egp3kIp7HHA%HJ6;)k=PWByrinPQHYG}jz^OV4xUF-At>cx}1uVLTc9n^Ka+xt~@ z(DnG=S|7gYa+^AlBx8GRp}h<(_bb-)e(JNJREMix8Do}&2z7C6)El{?r@_goJ z;a4f%_S5}wnRQ!o$7A=d){nXRkF0+!PDF?jOp&a^{L3Xsr zk|=}^@kuvirq&Qp+DIMIYiUf{chqDOQ$-XXZapvf`fd)o#f(tNGQTtV{Pq47Rr-YA z=MpZwxX(qGuX0PwBZrgYqq}e+=4{O~Xt7{TEbdA?L^PY-ATiaIb^%^<&sa98388dF z#zwWOIMo}MlygV##7>FTGj-N5kt1qRUVleRaYrdp->*b;8 zI5orV%<|KpUYEJz1ijp#Z}x$QX+zxmRS*}6{#Mtu3*de&mGML=WK?c;c;3VG z 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 Date: Thu, 9 Jul 2026 11:17:58 -0700 Subject: [PATCH 4/4] fix(evalboard): fall back to agent_config type when run_config omits harness A present-but-partial run_config stamp (object present, harness key missing or empty string) short-circuited the mostCommonAgentType fallback and returned null, mislabeling a real codex/antigravity run as the claude-code default logo. Guard on truthiness and fall back to the per-task agent_config vote so only a genuinely unidentifiable run defaults. Addresses review feedback on the harness column (coder_eval.bak#494). Co-Authored-By: Claude Opus 4.8 (1M context) --- evalboard/lib/runs.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/evalboard/lib/runs.ts b/evalboard/lib/runs.ts index ef682c10..26fa767e 100644 --- a/evalboard/lib/runs.ts +++ b/evalboard/lib/runs.ts @@ -836,7 +836,14 @@ export function extractRunConfig(data: RawRunJson): { if (rc && typeof rc === "object" && !Array.isArray(rc)) { const r = rc as Record; return { - harness: typeof r.harness === "string" ? r.harness : null, + // A present-but-partial stamp (run_config object with no/empty + // harness) falls back to the per-task agent_config vote rather + // than nulling out — otherwise a real codex/antigravity run is + // mislabeled as the claude-code default. + harness: + typeof r.harness === "string" && r.harness + ? r.harness + : mostCommonAgentType(data.task_results ?? []), environment: typeof r.environment === "string" ? r.environment : null, };