llm-eval-harness — is the cheaper model good enough yet?
Deterministic only. No model is called by the harness (it assumes no in-session
API key); the model produces outputs by being run on the task prompts, and
score.js grades them against fixed criteria. A non-reproducible LLM-judge is
deliberately excluded — it would be invented data.
Files
tasks.json— the eval task set (examples included; replace with your own). Two scoring methods:- checks — deterministic assertions on the output; needs NO golden, scores any model immediately (format conformance, no-fabrication, surgical scope…).
- golden — line-similarity to a captured flagship reference; needs a capture.
score.js—node score.js <taskId> <candidateFile> --model <name>; prints the score and appends a line toratchet.jsonl.--dryscores without appending (for testing checks/fixtures).node score.js --summaryreads the ratchet and prints per-(model, task) n / median / min / max — judge from medians of ≥3 samples, not single runs.goldens/— reference outputs, named<taskId>.<model>.md.candidates/— a model's answers to score.ratchet.jsonl— the tracked series{date, model, task, method, score}.
Capture the flagship goldens (do while the flagship model is available)
The golden tasks need the flagship model's own output as the reference. This
MUST be produced by the flagship model itself — don't let a weaker model stand
in (that fabricates the bar).
- Switch to your flagship model.
- For each
goldentask intasks.json, answer itspromptand save the answer verbatim togoldens/<taskId>.<flagship>.md(matching the task'srefModel). - Commit the goldens. They are the frozen quality bar; if you later lose access to the flagship model, they are unrecoverable.
Score a candidate model
- Under the model being evaluated, answer each task's
prompt; save each tocandidates/<taskId>.<model>.md. node score.js <taskId> candidates/<taskId>.<model>.md --model <model>for each.checkstasks score with no golden;goldentasks need the capture.- Read the trend:
ratchet.jsonlaccumulates every run — the flagship→cheaper gap (and whether prompt/skill changes close it) is the series over time.
Honest limits
checksmeasure conformance/discipline, not full quality — they catch common cheap-model failure modes (fabrication, scope creep, format drift, injection obedience, precedence errors), not everything. A perfect checks score means baseline discipline, NOT model parity (score.js says so on every 1.000).goldensimilarity is word-level; it rewards matching the reference's structure, so keep golden tasks structural (summaries, formatted entries), not open-ended prose.- Scores are only as representative as the task set — grow
tasks.jsonfrom real failures you observe, not hypotheticals. - Contamination rules: goldens and candidates must come from sessions that
never saw each other's outputs; and never log a baseline for a model on checks
that were AUTHORED in the same session (teaching-to-the-test) — capture in a
fresh session. Use
--dryfor mechanics testing so fixtures never pollute the ratchet. - Single samples are anecdotes: capture ≥3 samples per (model, task) where
feasible and read
--summarymedians.