Skip to content

feat(v1): configurable agentic-judge grading policy, uploads, and reward weights - #2109

Merged
mikasenghaas merged 19 commits into
mainfrom
feat/agentic-judge-ootb
Jul 23, 2026
Merged

feat(v1): configurable agentic-judge grading policy, uploads, and reward weights#2109
mikasenghaas merged 19 commits into
mainfrom
feat/agentic-judge-ootb

Conversation

@mikasenghaas

@mikasenghaas mikasenghaas commented Jul 23, 2026

Copy link
Copy Markdown
Member

Summary

Makes the built-in agentic-judge env a complete out-of-the-box judge, configurable end-to-end from TOML/CLI so domain-specific setups (SWE, search, ...) are pure .md + .toml artifacts:

  • One box, shared — the box is provisioned once from the solver's runtime policy (--env.solver.runtime.type docker|prime, checked at construction); the solver plays the task in it and the judge then inspects the work exactly as the agent left it. The judge pins only its model; its runtime policy is unused. (Borrowed boxes are never retried into, so per-agent rollout retries don't apply; episode retries still do.)
  • [env.task] (JudgeTaskConfig) — the judge's minted task:
    • prompt: grading-policy override, one field — a value ending in .md/.txt is read from disk, anything else is inline policy text (a missing file fails at env construction). A policy replaces only the judging instructions: the verdict contract and workspace note are always appended, so it can never break verdict parsing. {prompt} interpolates the solver task's prompt; if absent, the task statement is appended.
    • hint: optional hints injected as their own section (inline text or a .md/.txt file) — task-family pointers into the trace or box, e.g. where the reference answer lives for math, or "diff the repo / read info.patch" for SWE.
    • rubric: criteria the judge grades against — a .toml/.json criteria file in the plugged rubric judge's format ({name, text, weight=1, choices worst→best}; logic mirrored, not imported), defaulting to a single built-in solved criterion. The judge writes {"verdicts": [{"name", "reason", "verdict"}, ...]} to /tmp/verdict.json; finalize validates strictly (name set must match, only on-menu answers), records judge/<name> metrics on the solver trace, and rewards the weighted mean.
    • The solver's COMPLETE raw trace record always lands at /tmp/trace.json (not configurable) — messages, tool calls, trace.info artifacts (e.g. a captured patch), and the task row with whatever scores/reference material it carries; nothing is stripped. Independence is prompted, not enforced: the workspace note tells the judge recorded scores and references are context, never the standard, and warns that the record can be very large — peek selectively, never dump it whole. A policy that needs a record field as a file instructs the judge to extract it.
  • [env.score] (ScoreConfig) — reward composition on the solver's trace: task_weight (default 0: judge-only reward) rescales the taskset's own rewards, judge_weight (default 1) scales the verdict.

Verification

  • uv run eval @ configs/agentic_judge.toml (gsm8k, docker, glm-5.2), re-smoked after every design round (rubric verdicts, shared-only box, full-record upload): trace records show the judge on the borrowed solver box, verdicts land as judge/solved + the judge reward, and the default score.task_weight=0 zeroes the task's own reward.
  • scaleswe-v1 through --env.id agentic-judge (prime + docker, bash seats), and a 64-instance dogfood: the judge flipped 8/9 manually-identified narrow-test false negatives to ≥0.7 while keeping 7/8 pytest-passing controls at 1.0; on a re-run with rubric verdicts and judge-side patch extraction it flipped 17/23 pytest-failures and kept 36/40 passes, agreeing with the earlier judge on every audited case. Gap experiment, run twice on 256 fixed-seed instances x {glm-4.5-air, glm-5.2}: judge scoring widened the model gap from +0.206 to +0.290 (continuous 0-10 verdicts; 243 pairs) and, on the rubric-verdict re-run, from +0.210 to +0.380 (binary solved; 224 pairs; delta +0.170, 95% bootstrap CI [+0.089, +0.246]). (Experiment builds predate the shared-box/full-record round.)
  • ruff check, ruff format --check, repo ty check (diagnostic count unchanged vs main), full non-e2e tests/v1 green; test_env_id_agentic_judge covers the config surface (needs PRIME_API_KEY + docker).

…ard weights

- prompt/prompt_file: policy-only override; the verdict contract and workspace
  note are always appended, and the task statement is appended when the policy
  doesn't place {prompt} itself
- [env.uploads]: transcript/trace paths (nullable) plus trace.info key -> path
  uploads (e.g. a captured patch as a real file in the judge's box)
- the uploaded raw record strips rewards/metrics/task so the judge can't anchor
  on the graded run's own scores or the row's ground truth
- JudgeTask replays the source task's setup in the judge's box, so the judge
  sees the solver's true starting state (e.g. a repo reset to base commit)
- judge_weight / task_reward_weight for reward composition

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread docs/v1/env.md Outdated
Comment thread verifiers/v1/envs/agentic_judge/env.py Outdated
Comment thread verifiers/v1/envs/agentic_judge/env.py Outdated
Comment thread verifiers/v1/envs/agentic_judge/env.py Outdated
Comment thread verifiers/v1/envs/agentic_judge/env.py Outdated
mikasenghaas and others added 3 commits July 23, 2026 00:27
…ce-centric naming

- [env.task]: prompt (inline text or .md/.txt policy file, one field) + uploads
- [env.score]: task_weight (default 0 = judge-only) + judge_weight (default 1)
- raw record uploads as /tmp/trace.json; prompt wording says trace
- docs/v1/env.md diff dropped

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The box is provisioned once from the solver's runtime policy via
agents.solver.provision; solver and judge play in it back to back, so the judge
inspects the work exactly as the agent left it. --env.shared-runtime false
keeps the fresh-box mode: a new box mirroring the solver task's world, replayed
to the starting state via the source task's setup. The container requirement
follows whoever provisions the judge's box (solver when shared, judge
otherwise), and a shared box skips the setup replay (it would destroy the
solver's work).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- verdicts use the plugged rubric judge's criteria format (mirrored, not
  imported): {name, text, weight=1, choices worst->best} from a .toml/.json
  criteria file (--env.task.rubric), one built-in solved criterion by default;
  the judge writes {"verdicts": [{name, reason, verdict}, ...]} to
  /tmp/verdict.json and finalize validates strictly (name set must match, only
  on-menu answers), records judge/<name> metrics on the solver trace, and
  rewards the weighted mean
- uploads collapse to --env.task.trace (the raw record): a policy that needs a
  trace.info field as a file (e.g. the captured patch) instructs the judge to
  extract it — no rendered-transcript or per-key upload knobs

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread verifiers/v1/envs/agentic_judge/env.py
mikasenghaas and others added 2 commits July 23, 2026 19:05
AgentConfig.replay points a seat at a saved run dir (or traces.jsonl):
_ReplayEpisodeAgent revalidates the saved trace for each task and re-stamps it
with the seat's standing instead of sampling, so the other seats iterate
against fixed work — e.g. re-judging saved solver rollouts through the real
agentic-judge env: --env.solver.replay <run>. A single-seat run matches any
requested seat name. A replayed seat runs no model and leaves no runtime
state, so envs that need the seat's box refuse it (agentic-judge requires
--env.shared-runtime false and says so at construction).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread configs/agentic_judge.toml
mikasenghaas and others added 6 commits July 23, 2026 20:16
- shared_runtime knob removed: the judge always plays in the solver's box
  (container requirement on the solver); the fresh-box mode is gone with it
- the uploaded record is complete — nothing stripped; the workspace note tells
  the judge recorded scores and reference material are context, never the
  standard

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… drop finalize docstring

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…onfig

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread verifiers/v1/envs/agentic_judge/env.py
Comment thread verifiers/v1/envs/agentic_judge/env.py
mikasenghaas and others added 4 commits July 23, 2026 20:33
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ge box

A solver could leave /tmp/trace.json as a symlink onto any writable file; the
upload would follow it and overwrite the target. Same treatment the verdict
file already gets.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…write-wins

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mikasenghaas
mikasenghaas marked this pull request as ready for review July 23, 2026 20:57

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ca25ca9. Configure here.

Comment thread verifiers/v1/envs/agentic_judge/env.py
Comment thread verifiers/v1/envs/agentic_judge/env.py
@macroscopeapp

macroscopeapp Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR adds new feature capabilities including configurable rubric criteria, custom prompt/hint files, weighted reward composition, and changes the architecture so the judge shares the solver's container. These new features and runtime behavior changes warrant human review.

You can customize Macroscope's approvability policy. Learn more.

mikasenghaas and others added 2 commits July 23, 2026 21:07
The judge plays in the solver's box, but its config defaulted to subprocess —
tripping the base env's host-execution warning and stamping a runtime the judge
never uses onto its trace. Overwrite it with the solver's policy at
construction so both stay truthful.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ord can be huge

--env.task.hint (inline text or .md/.txt file) injects a Hints section between
the policy and the verdict contract — task-family pointers into the trace or
box (math: where the reference answer lives; SWE: diff the repo / read
info.patch). The workspace note now also tells the judge to peek at the record
selectively instead of dumping it whole.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mikasenghaas
mikasenghaas merged commit 7052102 into main Jul 23, 2026
12 checks passed
@mikasenghaas
mikasenghaas deleted the feat/agentic-judge-ootb branch July 23, 2026 21:52
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.

2 participants