feat(tests): take the eval model from env vars, bump coder_eval to 0.9.2 - #2419
feat(tests): take the eval model from env vars, bump coder_eval to 0.9.2#2419bai-uipath wants to merge 3 commits into
Conversation
The six experiment YAMLs no longer pin `model: claude-sonnet-5`. In CI those lines were already dead — every runner passes `--model`, which outranks the experiment — and a shared file cannot name one model when the same experiment runs under codex and antigravity too. coder_eval interpolates env vars only in path fields, so the pins are removed rather than templated. The three gates that ran without `--model` now pass one, resolved from `vars.CLAUDE_CODE_MODEL` with the pinned value as the fallback, so an unset variable keeps today's behavior. run-coder-eval.yml picks up per-harness variables the same way, and antigravity's default moves to gemini-3.6-flash. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…path Each harness already read its own env var; the literal fallback behind it meant a missing or misspelled variable ran a whole nightly on a model nobody chose and reported it as the real one. Remove the literals so the variable is the only source and an unresolved model is a hard error. daily.sh and daily-windows.ps1 abort naming the variable they wanted; harness_smoke_model raises, reddening that harness's pre-flight line instead of smoking the wrong model; eval-runner run --model is now required and run_tests takes no default. test_daily_model keeps a denylist of the retired ids so a literal cannot creep back into any of the three mirrors. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @bai-uipath's task in 2m 14s —— View job PR Review: feat(tests): take the eval model from env vars, bump coder_eval to 0.9.2
SummaryRemoves hardcoded Change-by-Change Review1.
|
| Area | Status | Notes |
|---|---|---|
| Frontmatter | N/A | No skill files changed |
| E2E Tests | N/A | No test task YAMLs changed |
| Skill Body | N/A | No skill files changed |
| References & Assets | N/A | No reference files changed |
| Repo Hygiene | OK | No secrets, no personal paths, changes scoped to CI infra |
Issues for Manual Review
- Repo variables are set. The three gates and the dispatch workflow depend on
vars.CLAUDE_CODE_MODEL,vars.CODEX_MODEL, andvars.ANTIGRAVITY_MODELbeing set on the repository. The PR description states they are set, and guard failures were observed when they weren't. Verify the variables are present in Settings → Variables. - Antigravity model upgrade. The PR description notes the
ANTIGRAVITY_MODELvariable is set togemini-3.6-flash, while the old hardcoded default wasgemini-3.5-flash. This is a model upgrade, not just a refactor. Confirm this is intentional and that antigravity tasks pass on the new model (the validation table in the PR description shows SUCCESS). - Local dev experience. Bare
coder-eval runwithout--modelnow gets$BEDROCK_MODELinstead of the experiment'sclaude-sonnet-5. This is documented as intentional but may surprise contributors with unusual local.envconfigs. Consider noting this in the test README if it comes up.
Conclusion
Clean, well-structured infrastructure change. The model resolution is now consistent across all four entry points (smoke, smoke-rpa, activation, dispatch), with no hardcoded fallbacks and clear fail-fast guards. The experiment YAMLs are properly decoupled from any specific model, making them genuinely harness-agnostic. The coder_eval version bump is straightforward. No issues found that would block merge.
The model guard added with the env-var switch sat as the first line of the smoke step, which carries continue-on-error, and both threshold steps read zero tasks as a pass. An unresolved CLAUDE_CODE_MODEL therefore ran nothing and reported green (run 30672478895 on this branch did exactly that). Hoist the guard into its own step in both smoke workflows so an unset variable fails before any task runs, and make the Linux pass-rate gate fail closed when the smoke step failed without producing a single task.json. A legitimate empty selection still passes: that path leaves the smoke step successful. The RPA score gate already failed closed on zero tasks, which is why it went red where the Linux gate went green. Also collapses the six identical five-line comment blocks in the experiment YAMLs to one line each. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
What
Stop pinning the agent model in the experiment YAMLs, and take it from a repo variable at every entry point that runs an eval. No model id is hardcoded in any of them. Also bumps the
coder_evalpin to 0.9.2.Companion to UiPath/coder_eval_uipath#74, which gives the nightly runner one model variable per harness.
The model pins
Six experiment files pinned
model: claude-sonnet-5:default,nightly,smoke,smoke-windows,activation,skill-comparison-template. All six are removed.In the nightly and in
run-coder-eval.ymlthose lines were already dead.--modelis the last layer of coder_eval's config merge and outranks the experiment, so the pin never applied. They were also wrong in principle: the same experiment file runs under codex and antigravity, which cannot use a Claude model.They are removed rather than templated because coder_eval expands environment variables only in path fields, so a
${VAR}inagent.modelwould be passed through as a literal model name.The gates that had no
--modelThree entry points relied on the pin, so removing it would have silently repointed them at
$BEDROCK_MODEL. Each now passes a model explicitly, resolved fromvars.CLAUDE_CODE_MODEL:smoke-skills.ymlsmoke-rpa-skills.ymlactivation-gate.yml, viaactivation_gate.pyThere is no literal fallback behind the variable. An unset
AGENT_MODELfails the step, guarded beforecoder-evalis invoked, andactivation_gate.pyexits 2. Gating on a model nobody configured produces a verdict about the wrong thing, and for the activation gate specifically the recall baselines are model-specific, so a silent substitution makes the number meaningless rather than merely wrong. Passing the model at the call site keeps that visible where the baselines live.$BEDROCK_MODELis deliberately not used for this. It is the evaluation-side model, feeding thellm_judgegrader and the simulated user, and reusing it for the agent would move the grader whenever the agent under test changes.run-coder-eval.ymlpicks upCLAUDE_CODE_MODEL/CODEX_MODEL/ANTIGRAVITY_MODELthe same way, replacing three hardcoded model names per job, each guarded. Itsagent_modelinput still overrides all of them for a one-off run. Antigravity's model moves togemini-3.6-flash.Required repo variables
The three gates and the dispatch workflow read repo variables, which are now set on this repo:
These are the exact values the deleted literals carried, so CI behavior is unchanged.
vars, notsecrets: nothing here is sensitive, and a secret cannot be read back for an audit.coder_eval 0.9.2
Three upstream changes since 0.9.1:
fix(reports): errors count as misses, and cost is no longer lost on error paths. This lowers reported pass rates, by up to ~10 points on a run with a normal error share, with no underlying regression. Compare againsterror_sharebefore reading a drop as a real change.feat(evalboard): harness comparison on the overview, and per-run identity.feat(litellm): per-call cost and cache accounting for the open-weight backend.Kept in this PR rather than split out. It is independent of the model change, so read the next nightly's drop against
error_sharebefore attributing any of it here.The gate went green on an empty run
The model guard started as the first line of the
Run smoke testsstep. That step carriescontinue-on-error: true, and both threshold steps below it read zero tasks as a pass:Enforce LLM reviewer score threshold:if not run_dirs: sys.exit(0)Enforce pass-rate threshold (>= 95%):if n == 0: print('No smoke-tagged tasks matched — skipping rate check'); sys.exit(0)So when run 30672478895 resolved
AGENT_MODELempty (queued 90 seconds before the repo variables were created), the guard fired correctly, the step exited in under a second having run nothing, and the job still reported success:The RPA gate does not have this hole (
if not task_jsons: print('::error::No task.json files found — nothing to gate'); sys.exit(1)), which is why RPA went red off the same empty variable while Linux went green. That asymmetry was the bug, not the guard.Two changes:
Require an agent modelstep ahead of the smoke step in both workflows, so an unresolved model fails before any task runs, in a step that names what is missing.failure. A legitimately empty selection still passes, since that path leaves the smoke step successful, and flake tolerance is untouched: once any task runs, the rate check governs exactly as before.Validation
Live runs on coder_eval 0.9.2, from this branch, one task per harness (
uipath-admin/audit_events_basic_smoke, tempdir driver,experiments/default.yamlwith its pin removed):--modelgiveneu.anthropic.claude-sonnet-5eu.anthropic.claude-sonnet-4-6--modelclaude-sonnet-4-6eu.anthropic.claude-sonnet-4-6gpt-5.6-terraeu.anthropic.claude-sonnet-4-6gemini-3.6-flasheu.anthropic.claude-sonnet-4-6All four load the experiment files with no
model:key and pass. The runs recordframework_version: 0.9.2, confirming the pin resolves.Row 1 versus row 2 is the point of the change. With
--model, the agent under test and the evaluation route are two different models in the same run. Without it, they collapse onto$BEDROCK_MODEL.Known consequence for bare local runs. Row 2 is a real change:
coder-eval runwith no--modelused to getclaude-sonnet-5from the experiment file and now gets$BEDROCK_MODELfrom.env. Intended, since that is the environment-variable mechanism, but anyone with an unusual localBEDROCK_MODELwill see their model move.Linux smoke gate. 40 tasks under the docker driver on coder_eval 0.9.2, with
experiments/smoke.yamlcarrying nomodel:key and--model "$AGENT_MODEL"supplying it. Pass rate 97.5% (39/40), above the 95% threshold. Editingtests/.coder-eval-versionis itself one of the infra triggers for that gate, so the pin bump got a full run rather than the changed-skills subset.That run measured
e629efeea, while the workflows still carried a|| 'claude-sonnet-5'literal behind the variable. The commit that removed the fallback got a smoke run that executed zero tasks and still reported green (below).Windows RPA gate.
skill-rpa-coded-test-casefailed once withMAX_TURNS_EXHAUSTEDat 998s. The same task passed 3/3 on other branches the same day at 1128 to 1301s,vars.CLAUDE_CODE_MODELwas not yet set so the model was byte-identical to the deleted pin, and the 0.9.1 to 0.9.2 diff moves no dependency or CLI pin and touches the Claude agent only through LiteLLM paths that are inert on Bedrock. Re-ran: passed.activation_gate.py. Verified the constructed command carries
--model <AGENT_MODEL>, and that an unset variable exits 2 before spawning coder-eval. The activation gate does not fire on this PR, since no skill frontmatter changed.Companion. UiPath/coder_eval_uipath#74 is green, with the per-harness resolution matrix unit-tested against the shipped
daily.shblock, a denylist test that fails if a literal model id reappears in any of the three mirrors, and pwsh parity verified. Its three ADO dry runs then resolvedeu.anthropic.claude-sonnet-5/gpt-5.6-terra/gemini-3.6-flash, one per harness, off the variable group, and the antigravity build carried both the Linux and Windows slices to green including the codex and antigravity pre-flight smokes, which readCODEX_MODEL/ANTIGRAVITY_MODELwith no fallback.One thing the smoke run exposed: the gate logs the command as
--model ***. GitHub masks a value only when it matches a registered secret, sosecrets.BEDROCK_MODELholds a plain model name. That is the concrete version of the argument for moving model config tovars: nothing is protected (the model name is inrun.jsonand on the evalboard either way), the value cannot be read back for an audit, and the smoke log can no longer tell you which model it graded. Out of scope here, but it is why the new variables usevarsrather thansecrets.