Cheat sheets

Eval-Driven Agent Development

Run eval cases, gate merges, review with a rubric, and gate prompt and report changes. Python stdlib.

  • Concepts and terms
  • Tasks and commands
  • Annotated code
  • Diagrams
  • Comparisons
  • Defaults and numbers
  • Troubleshooting
  • Questions and tips

Source

Run the lessons and projects#

CommandWhat it does
python3 code/main.pyRuns the lesson demo. Lessons 38 and 39 write JSON reports
VERIFY_DEMO_MODE=1 python3 code/main.py --strictGate demo with the demo secret. Every warn becomes a block
python3 code/main.py --floor <value>Gate demo with a different coverage floor
python3 scripts/project_test.py <project> --init learning-artifacts/<project>Makes a learner workspace
python3 scripts/project_test.py <project> --stage <n> --path learning-artifacts/<project>Tests one stage of your workspace
python3 scripts/project_test.py <project> --all --solution --strictChecks the reference solution
python3 <dir>/cli.py <cases> <baseline> <candidate> --out <json> --markdown <md>Prompt diff. Add --allow-configuration-change for a model change
python3 <dir>/cli.py <claims> --out <json> --html <html>Report audit. Add --research-payload for a report payload

Gate one task#

art = Artifacts(task_id="T-001",
acceptance_commands=accept,zero exit means done
feedback=[{"command": accept[0], "exit_code": 0}],
scope_report={"forbidden_writes": [], "off_scope_writes": []},
rule_report=[{"slug": "done/tests-pass", "passed": True}],
coverage_report={"current": 0.84, "previous": 0.85},
head_commit="a1b2c3d")
report = verify(art, strict=False, coverage_floor=0.80)
report.passedFalse on any block finding
record_override(task_id, finding_code, reason, user_id, head_commit)
verify_signature(entry)HMAC check of the override

Defaults and numbers#

SettingDefaultNote
max_rounds3Evaluator-optimizer rounds per case
regression_threshold0.05ci_gate blocks above it
COVERAGE_FLOOR_DEFAULT0.80Below it is a block
COVERAGE_REGRESSION_DELTA0.01Larger drop than the last merge blocks
release_gate min_pass1.0Pass fraction in [0,1]
release_gate max_regressions0Integer regression budget
judge_claim threshold0.8Overlap score to count as supported
compare samples2000Bootstrap resamples, seed=7

Troubleshooting#

SymptomCauseFix
Eval scores are unreadableNo baselineStore a last-known-good baseline
Judge passes wrong outputLLM judge without groundingGround the judge on external tools
Evals pass, production failsOver-fitting to evalsRotate cases
False alarms in CIFlaky, non-deterministic casesPin seeds, snapshot state
refused to start: VERIFY_OVERRIDE_SECRET is unsetNo override secretSet the env var, or VERIFY_DEMO_MODE=1 for the demo
recording does not match casesCase list changed after recordingMake new recordings
model/settings changed; explicitly allow this experimentBaseline and candidate configs differPass --allow-configuration-change
order_requires_review on a true claimLexical rule rejects a paraphraseA human reviews the claim

Builder to sign-off#

noyesmodelBuilder Agentwrites the diffstoreArtifactsdiff, scope, rules,feedbackprocessVerification gatedeterministic, no LLMstoreverification_report.jsonpassed true or falseclientRefuse donesurface to humanmodelReviewer Agentread only, rubricclientHuman sign-offreadsreview_report.jsonnoyesmodelBuilder Agentwrites the diffstoreArtifactsdiff, scope, rules,feedbackprocessVerification gatedeterministic, no LLMstoreverification_report.jsonpassed true or falseclientRefuse donesurface to humanmodelReviewer Agentread only, rubricclientHuman sign-offreadsreview_report.json

Three evaluation layers#

FactorStatic benchmarksCustom offlineOnline
ExamplesSWE-bench Verified, GAIA, BFCL V4LLM-as-judge, execution, trajectorySession replays, guardrail alerts
Use forCross-model comparisonYour product shapeProduction behavior
MeasuresBroad capabilityRight patches for your productPer-step cost and latency
Watch forContamination, 32.67% leakageJudges hallucinate tooTie each failure to a new case

Evaluator-optimizer loop#

1Proposercase.proposer(feedback) gives a candidate.2Judgecase.judge(candidate) returns ok and a reason.3Refinethe reason becomes the next feedback.4Stopafter max_rounds the case fails.5CI gateci_gate blocks a regression above the threshold.

Reviewer rubric#

Problem fit
solved the task as stated?
Scope discipline
edits inside the contract?
Assumptions
written down?
Verification quality
acceptance proves the goal?
Handoff readiness
next session can pick up?
Scores
0 to 2 each, total out of 10.
Verdict
pass at 7 or more, else soft_fail.
hard_fail
total below 5 or any 0.

Prompt Regression Tester#

TaskCode
Unique ids, known check kindsvalidate_cases(cases)
Check kindscontains, excludes, json
Score one recorded responsescore_response(response, checks)
Pair revisions by case idcompare(cases, baseline, candidate)
Pair statesstable_pass, regressed, improved
Ship or blockrelease_gate(report)
Bind recording to casescase_sha256 == case_digest(cases)
Load a provenance-bound runload_run(raw, cases)

Report Judge#

TaskCode
One claim per sentenceparse_claims(text)
Lexical support of one claimsupport(claim, source)
Judge cites against evidencejudge_claim(claim, evidence)
Reasons for a zero scorenegation, number, uncited
Precision, recall, coveragescore_report(text, evidence)
Score weightsprecision 0.5, recall 0.25
Statesno_evidence, needs_review
Paired bootstrapcompare(baseline, candidate)

Questions#

Why no LLM in the gate?
The gate gives the same verdict for the same artifacts every time.
Who overrides a block?
Only a human, with override_reason and overridden_by.
Why a separate reviewer?
Role separation: different prompt, different inputs, no write access.
Why pair cases by id?
An average can hide a serious regression.
Why is recall null?
Recall and coverage need labels. Without labels they are unavailable.

Tips#

  • Keep evals next to code. Run them in CI on every PR.
  • Map every guardrail and every learned rule to an eval case.
  • Write one report per task to outputs/verification/<task_id>.json.
  • Use --strict on release branches only. It is not the global default.
  • Run the reviewer on a 10-20 task calibration set after each prompt change.
  • Below 80% agreement, revise the rubric before the reviewer ships.

Gate finding codes#

acceptance.missing
block. A command never ran.
acceptance.failed
block. Nonzero exit.
feedback.null_exit
block. No exit code.
scope.forbidden
block. scope.off_scope: warn.
coverage.below_floor
block. coverage.missing: warn.