Repository navigation
feat(verifiers): user_sim_judge grades the user sim of a run, record-only - #682
Open
sarah-chitty-1 wants to merge 13 commits into
Open
sarah-chitty-1 wants to merge 13 commits into
sarah-chitty-1 wants to merge 13 commits into
Conversation
…an always_on run Started Nov 10 on the old user-sim branch and moved onto main unchanged, apart from the user sim modules' new task_steps/agent/ path. Not reviewed or calibrated; the design is still open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…with one judge model, and records only - Both kinds of run with the built-in user sim: an always_on step's stored timeline, or a prompt_agent step's user_sim_reads, each read whole from its object_url. run_step_id names the step; unset, the run must have one. - The user sim's instructions are rebuilt from its user_sims record with user_sim_versions.setup, as deploy_user_sim_agent wrote them, and checked against the recorded prompt_sha256. - One judge_model, defaulting to rubrics_verifier's (the config's judge role, else claude-sonnet-4-6); the two-judge split is gone. user_sim_error is yes / no / unknown (a check that could make it one couldn't be judged). - Record only: mark_user_sim_error (off by default) sets the prompt response's error_type to user_sim_error, only when the instructions match the recorded hash. The step doesn't fail the task by default. - Tests: a fake judge, one always_on and one prompt_agent run, every check's verdict, task items, the hash check, errored runs skipped, marking off by default and on when opted in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…k (G4) - guidance: an unanswered question fails only when the assistant needs it answered; giving something again when asked is now a fail line. Self-contradiction moves to made_up. - oversharing: something the assistant should know from its notes, credentials, and answering a may-I-share question against PRIVATE lines or rules. - delegation: a broken "ask first" or "never" item must be objected to (the user sim's prompt always says so); a "tell you after" item left out of the final report must be asked about once. - rogue: letting the assistant off for a broken limit or skipped step. - style: same-length messages, described traits and caricature, missing pushback or reactions, and acting out of step with its situation (F4). - ending (G4): a new check, run by default and able to mark a run. The step tells the judge when the run ended at the user sim's max_replies, which its instructions never mention. - docstring: A5 is the separate rate_user_satisfaction step's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tty/fd-5490-user-sim-judge-v2 # Conflicts: # src/agent_env/task/episode/rules.py
parse_answer kept a "fail" whose cited turns were all outside the graded ones (turns=[] but could_change_grade still true), an unsupported failure that could mark the run. A check's or task item's fail must now cite at least one graded turn; otherwise the answer is not usable, so the judge is asked once more and a second such answer gives the check (or item) the verdict "error". Pass and n/a answers are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…no failure is asked again
The answer format put the verdict first, so the judge committed to "fail" and then argued itself out of it ("No clear
failure found"); in 2 of 4 real runs that alone made the run a user sim error. The prompt and schema now ask for the
reason, then turns, then verdict and could_change_grade (items alike), and say to decide after reasoning, within the
40-word limit. As a backstop, a fail whose reason says no failure was found is not usable, so it is asked again once.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…o failure; name the error-note limit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An item has id, family, kind (hard / general / auto), check (text still loads as its old name), name, short, na_when and, for auto, metric and max. Hard items are told to the judge as exact rules, general ones fail only on a clear instance. Auto items are counted on the graded answers with no model call. na_when always is n/a with its static_na_reason and no call; never asks an n/a again. A call takes at most MAX_ITEMS_PER_CALL (12) items; the rest go in item-only calls. rubric_task_version is compared with the run's task instance version: on a mismatch the items aren't graded and the entry says so, the general checks still run. Bad items are refused with a clear error per item. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…/fd-5490-user-sim-judge-v2
…t's own path; auto items take only na_when always The judge rebuilt the prompt from the record's opening text alone, so an opening with files never matched prompt_sha256 (no "(you attached ...)" notes, no ATTACHED_KNOWN line). deploy_user_sim_agent's person() is now a module function, and recorded_person() builds it from the record (opening_parts when present); the judge calls that and user_sim_versions.setup, so the files and the new already_told / should_already_know sections rebuild as deployed. An auto item is counted, never judged, so auto_result ignored any na_when but always: a conditional na_when did nothing and na_when never still gave n/a with no messages. Any other value is now refused when the task loads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t, not the task version Any edit to a hub task makes a new version, so rubric_task_version skipped a rubric after the next edit even when the user sim's person didn't change. user_sim_common.persona_fingerprint hashes the persona's description, permissions and keep_private and the opening_prompt as written (recipe in its docstring, pinned by a test, since psi-benchmark-tasks's converter computes it too); deploy_user_sim_agent records it as persona_sha256. The judge's rubric_persona_sha256 replaces rubric_task_version: a mismatch skips the task items and still runs the checks, a match grades them, a run with no fingerprint is unknown and grades them. The task-instance lookup is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sarah-chitty-1
changed the base branch from
main
to
sarahchitty/fd-5491-satisfaction-step
November 14, 2026 02:17
…y the start of When always_on's stored timeline can't be read, the judge falls back to the record's timeline_tail, which keeps each message's first 300 characters. A length item counted on that could pass an answer that was over its limit. Such answers are now marked cut; over the max as kept is still a fail, otherwise the item is error (unknown), not pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
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.
Stacked on #681 (files in the opening, the rating step, the two new persona sections); merge that first.
A new verifier step,
user_sim_judge, grades the user sim of a run (the AI playing the user), not the assistant (FD-5490). It covers always_on runs andprompt_agentchats with the built-in user sim (deploy_user_sim_agent).It only records verdicts for now. Nothing marks a run or changes what graders read until the judge is calibrated against a person's labels. Marking is behind
mark_user_sim_error, off by default.What it does
prompt_sha256.user_sim_readsentries.rubric_itemsunder any family, in the shape of a criterion in a task'susersim.yaml(psi-benchmark-tasks turns one into the other). Each item rides along with the check that owns its family, at most 12 to a call:kind:hard(an exact rule from the user sim's instructions, failed on any breach),general(judged), orauto(counted, not judged).na_when: when the item never came up.alwaysmakes it n/a with no call and needs astatic_na_reason;nevermeans it always applies. An auto item takes onlyalways.rubric_persona_sha256is the fingerprint of the persona and opening the items were written for (persona_fingerprint, whichdeploy_user_sim_agentrecords as the run'spersona_sha256). If they differ, the task items aren't graded and the entry says why; the general checks still run. Other task edits don't affect it.rate_user_satisfactionstep (feat(user sim): files in the first message, and a rating step after the run #681).Settings and output
judge_model, defaulting to the same modelrubrics_verifieruses. A run-wide--judge-modeldoesn't change it; only this step's ownstep_paramsdo.unknown.metadata["user_sim_judge"][<verifier id>]. There's noverificationsentry, so nothing mixes into the assistant's scores.fail_task_on_errorfalse).max_replies, the judge is told the reply limit, which the user sim itself never sees, so the ending check can allow a short sign-off there.Tests
tst/unit/task_step/verifiers/test_user_sim_judge.py(28) uses a fake model, with one always_on and one chat run.tst/unit/task_stepandtask/episode: 3,217 passed; the twotest_mcp_cli_buildertests that needclickwere deselected. No paid calls.Not done: calibration. The old test labels are AI-written, so the judge will be calibrated on a person's own labels of about 60 answers before marking is turned on.
🤖 Generated with Claude Code


Confidence Score: 5/5
The PR appears safe to merge after its stated dependency, PR #681.Summary
Adds a record-only judge for the user simulator, separate from the assistant’s scores.
Reviews (12) · Last reviewed commit: "user_sim_judge: an auto item can't pass ..." · Reviewed by Greptile