NeurIPS 2026 WorkshopEvoRobust · Self-Evolving Diversity-Driven Search for Robust AI Systems

Impossible Code, Barely Changed Score

A replay audit of judge-based evaluation. Two trained checkpoints started writing Python that does not parse. The LLM judge's score fell by under three points.

Masoud Fetanat · UNSW Sydney
Outputs that are not valid Python
+66.5 pts 0.42% → 66.90%
first run
0.42%
second run
66.90%
The judge's score (Pass@32)
−0.027 0.9667 → 0.9395
first run
0.9667
second run
0.9395

SLJ-trained checkpoint, the same 421 problems and the same 72B judge in both runs. The untrained base model stayed at 0.39% → 0.40% invalid. The weights scored in the first run were not hashed, so the cause of the change is unresolved.

an invalid second-run sample (SLJ-trained)
    for i in range(1, len(numbers))):
SyntaxError: unmatched ')'
the judge accepted 60.56% of all 36,051 invalid SLJ-trained samples
The problem

Training a language model with reinforcement learning needs a scorer that says whether an answer is right. For code, the dependable scorer runs the program against tests. That is slow and needs a sandbox, so many studies ask a large language model to read the code and judge it instead. This page reports what that substitution cost inside one real evaluation.

What happened

A finished study had trained Qwen-2.5-7B-Instruct with GRPO and saved the code its checkpoints wrote for 421 HumanEval and MBPP problems (32 samples each). Later we downloaded the same checkpoints and asked the same questions again (128 samples each), on different hardware. The untrained model behaved as before. Two trained checkpoints did not: most of what they now wrote was Python that does not parse, almost always because of one extra closing bracket. The judge that scored the study barely reacted.

0.42% → 66.90%
samples that do not parse, SLJ-trained checkpoint, first run to second run (base model: 0.39% to 0.40%)
0.9667 → 0.9395
the strong judge's Pass@32 for the same checkpoint over the same step
0.0071 vs 0.1591
how far the judge and execution place the base model above the damaged checkpoint at 128 attempts (0.1601 and 0.2232 at one attempt)
0 of 70,239
samples that fail the parse check and still get execution credit
What the paper proposes

Report one free number beside every judge score.

The share of outputs that parse. It needs no tests and no sandbox, and it would have flagged this change on the day it happened. Applied as a gate on the judge, it lowers judge-based Pass@1 by 0.0019 on a healthy run and by 0.4051 on a damaged one. Parsing does not show that code runs or is correct.

import ast

# extracted_code: the last code block of the response
def gated(judge_says_yes, extracted_code):
    if not extracted_code.strip():
        return False
    try:
        ast.parse(extracted_code)
    except Exception:
        return False
    return judge_says_yes

A judge's accuracy and its sensitivity to change are different properties.

A high judge-based score can sit next to a model whose outputs have stopped being programs.

Why it matters for self-evolving search

Program-search systems such as FunSearch and AlphaEvolve score each candidate by running it through an automated evaluator. Self-rewarding training scores candidates with a model's own judgment. A judge that cannot tell broken output from working output can steer such a search toward whatever it accepts.