Repository navigation
feat(grading): port the evaluator audit tool to the second plan - #130
Conversation
The second evaluator audit matches a second grader's answers to the first grader's claims by review, item, claim id and exact quote. The claim list that grade.py prepare --inventory fixes held each item's kind and quotes only, so a second grader chose its own ids. An inventory item may now list ids beside its quotes. The validator holds the claims of that item to those ids in order, and the prompt says so when a list carries them. A list without ids behaves as before.
evaluator_audit.py built the first plan's nine strata from verdict contract v1 and refused the plan audits.json now declares. It reads grades saved under contract v2 and builds the thirteen declared strata. - check runs the three whole-cohort checks and names each failing unit: saved credit against the credit the claims give, linked claims against their saved label and known problem, stale grades and missing rows. draw runs them first and refuses on a failure. - draw orders by the seeded hash with ties by unit id, records a stratum no larger than its size as audited whole and an empty one as empty, and lists a unit drawn in two strata once with both. - claims writes a sampled batch's claim list for grade.py prepare --inventory: item, kind, claim id and quote. second refuses a workspace prepared without it. - compare matches by review, item, claim id and exact quote and refuses a missing, added, renamed or re-quoted answer. Only a different credit, claim outcome or control result is a disagreement. Counts without a tolerance are saved under reported; nothing is computed from the second fact. - conclude holds each sampled stratum to its tolerance. A stratum audited whole records its confirmed errors and never fails on their count. The first plan's strata maps and its overlapping-quotation matcher are removed. The first round's saved records are not read.
An independent review of the port found seven defects. Each is fixed with a test that fails without the fix. - conclude trusted comparison.json. It now refuses when the sample or a second assessment changed since the comparison, and when comparison.json is not what the sample and the latest second assessments give. Every operation after the draw refuses a sample that is not the seeded draw of its populations at the declared sizes. A second assessment whose verdicts or receipt changed is refused. - claims overwrote its output file. It writes once, to a new file outside the round's directory. - compare dropped added answers. Claims are matched as multisets and the two sets of reviews must be equal, so an added or repeated answer or review refuses the comparison. - The third check skipped reviews that are not admitted, whose claims are units. Every graded review needs a row for each known problem. - The second check let a linked claim lose its saved known problem. The graded claim must hold an entry for it under every saved label. - The says-what counts covered only the problems a grader mentioned. They cover every claim and known problem of its task, with the raised pairs beside them. - A family awaiting approval was derived as missed while the grade saves it unresolved. It is a unit of no stratum and its saved credit must be unresolved. docs/evaluator-audit.md records three settled readings: a claim unit can come from a review that is not admitted, a known problem is a family with approved eligibility, and the control is the saved status.
…t builds them calibration.py and evaluator_audit.py each listed the thirteen stratum names. calibration.STRATA is now the tool's own table, so a stratum cannot be required without being built.
… each second assessment A second review found three ways past the audit's checks. - A population edited in sample.json was accepted, because the draw was rebuilt from the populations the sample itself saved. Cutting a sampled stratum to its drawn units made it audited whole, with no tolerance. Every operation after the draw now builds the units again from the pinned grades, the selected attempts and the task facts the sample pins, and refuses a sample whose strata, drawn units, counts or batches differ. The sample pins each task's known problems with their impact labels and its control status, because a ruling may change one of them before the conclusion without changing a grade. - A second assessment with no claim carried no pin of its receipt or raw verdicts, and assessment.json was unpinned until the comparison. The receipt is written last and records the hashes of the verdicts and the assessment. compare and conclude check both, and the comparison pins all three files of each assessment. - claims compared its resolved output path with an unresolved round directory, so a round reached through a symlink took the file.
fc269f9 to
5286dca
Compare
kamui
left a comment
There was a problem hiding this comment.
Approved (advisory) — no findings.
Reviewed 5286dca. All nine changed files, the full diff, grading input fingerprints, grade projection, provenance checks, record locking and affected validators reviewed. Required independent verification completed. No finding or open question remains. The sample task facts still rely on committing sample.json immediately after drawing, as the PR discloses; no real audit has run because the cohort is ungraded.
Review details
Intent: Port the evaluator audit to verdict contract v2 and the thirteen declared strata, with a fixed claim list for the independent second pass.
Issue fit: The PR delivers the audit-tool portion of #30. Actual regrading, paid second assessments, audit reconciliation and dataset publication remain outside this change. Requirements were taken from the PR text and the declared audit plan.
Reviewed: 5286dca against merge-base 9feb2e1.
Checks:
- Accepted caller evidence from the clean reviewed head: evaluator-audit tests 49, calibration tests 21, grading tests 66 with sandbox escalation, and claim-grading tests 28 passed. Changed-test assertions and fixtures were inspected.
- Accepted exact-head calibration, current-grading and import checks, and diff whitespace validation. Prior sandbox startup failures were environment failures and were superseded by the successful escalated grading run.
- Current CI snapshot: Web and evidence and Client compatibility passed; Grading regressions pending. The prior broad-suite catalog failure is historical and also occurs on main on this host.
Why
The second evaluator audit is declared (#128), and
evaluator_audit.pystill built the first plan's strata from the previous verdict format, sodrawrefused the new plan. This ports the tool, so that the sample can be drawn once the last-push cohort is graded.Stacked on #128.
Scope
bench/tools/evaluator_audit.py: commandscheck,draw,claims,second,compare,concludefor the thirteen declared strata and three unit kinds.checkruns the three whole-cohort checks (saved credit equals the derivation, a claim with a canonical claim holds its saved label and known problem, no stale grade or missing row), anddrawrefuses on any failure.drawrecords each stratum assampled,wholeorempty; a stratum audited whole has no tolerance.claimswrites the first grader's claim list (item, kind, claim id, quote) for a sampled batch, and nothing else of the first verdict.comparematches by review, item, claim id and exact quote, as multisets; a missing, added, repeated, renamed or re-quoted answer or review refuses the comparison. It saves nothing aboutidentifies_causeorcause_only.concludeverifies every pin, rebuilds the comparison from the sample and the second assessments, and holds only sampled strata tomax_errors.bench/tools/grade.py,bench/tools/grading_validation.py: a fixed claim list may carry claim ids (ids, parallel toquotes), and the validator holds the answer to them. Lists without ids behave as before.bench/tools/calibration.py:STRATAcomes from the tool'sUNITS.docs/evaluator-audit.md,docs/current-grading.md: what the tool does today, and three readings of the plan stated in the doc.Tradeoffs
unresolved. All 67 are approved today.audited-clean. The provisional state a pending candidate causes does not remove it, so the population does not depend on what the first grader raised.unassessed(its remedy inventory is incomplete) still holds graded claims and credit, so it stays a unit anddrawdoes not wait for it.grade.py prepareadds one sentence to the grader's prompt: "Where an item lists ids, give its claims those ids, in that order." It is prompt text outside the pinned template.Blast Radius
The audit tool, and the claim-list path of
grade.py prepareand its validator.grade.pyandgrading_validation.pyare runner files, so a grading key prepared before this change fails dispatch with "runner changed after preparation"; no grading is prepared yet. Nothing is graded, so the tool has not run on real batches: on the real recordscheckexits 1 with "189 selected batch(es) have no grade".Verification
python3 -m unittest discover -s bench/tools -p "test_evaluator_audit.py": 43 pass.test_calibration.py21,test_grade.py66,test_claim_grading.py28 pass.python3 bench/tools/calibration.py checkandcurrent_grading.py check: pass.bun run test:bench: 934 tests, one failure,test_codex_grading.test_catalog_preserves_native_model_instructions, which also fails onmainon this host and passes in CI.sample.jsonpins the task facts its populations rest on (known problems, impact labels, control status), because a ruling can change them after the draw without changing a grade. An edit that changes those facts and the populations together is not caught untilcomparepins the sample. Committingsample.jsonright after the draw closes it; the claim strata do not have the gap, since they come from the pinned grades alone.Part of #30