Repository navigation
Releases: scitix/sieval
Release list
v0.14.0
A minor bump: new config keys runner_config.stop_after and a model's
lifecycle, a task's grader / extractor may name a models: entry that
sieval run launches, sieval run gains exit code 6 for an engine lost
mid-run, and --dry-run reports new barriers, phases and launches
fields. No identity or on-disk format changes: meta.json identity stays
schema 4, RESULT_SCHEMA_VERSION stays 1, and 0.13.x result directories
resume.
Migrating from 0.13.x
- Exit code 6 (#246):
sieval runexits 6 when an engine it launched exits or fails its health check for 180 s in a row mid-run. It is not a refusal and writes noSIEVAL_REFUSALline; under-o json,data.outcomeisengine_died. A scheduler that treated every non-zero exit alike now sees this code;--resumeretries the failed samples. - New
error_reasonvalues (#246):engine_died(in flight when the engine was lost; a resume retries it and spends a retry) andengine_died_unsent(never sent; retried without spending one). An older SiEval reads both as ordinary retriable failures. stop_aftergoes in the top-levelrunner_config(#247). It is session-wide: a task's ownrunner_config.stop_afteris refused, and it needsrecord_each_stage: true(the default). The stopped run writes noreport.jsonunless it stopped afterreport, and recordsruns[].stopped_after.- New
error_reasonvaluebarrier_iteration(#247): withmax_iterationsunset, a sample asking to iterate past a barrier oninferenceorpostprocessfails with it; a resume without that barrier can retry it. A task withmax_iterationsabove 1 under such a barrier is refused before the run. --dry-runneeds_inferencevslaunches(#247): the top-levelneeds_inferencesays whether a model under test starts; a launched judge or extractor does not set it. The newlauncheslists every engine the run starts, judges included: a caller that readneeds_inferenceto decide whether the run needs GPUs should readlaunches.- Barriers and lifecycles are scheduling only: they enter no identity and never refuse a resume.
runs[]gainsstopped_afterandserving.lifecycles, both additive.
Added
- Stage barriers and
stop_after.runner_config.stop_after: <stage>(preprocess,inference,postprocess,feedbackorreport) ends the run once every sample of every task has finished that stage or failed;--resumecontinues from the next stage with the same identities as an uninterrupted run. The barriers arestop_afterplus every lifecycle boundary, with no key of their own; at each, no sample starts the next stage until all have finished this one.--dry-runlists them underbarriers, with what implied each. From Python:MultiTaskRunner(stop_after=, barriers=, on_barrier=)(#247, closes #245). - Model lifecycles and launched judges. A model
sieval runlaunches may setlifecycle: {from: S, until: T}(either bound optional) to run its engine only between those barriers and then free its GPUs. A task'sgraderorextractormay name amodels:entry, whichsieval runlaunches like the subject; a launched judge that statesweightsis compared by them instead of its name in thefeedbackidentity. With the subjectuntil: inferenceand the judgefrom: inference, the judge takes the subject's GPUs within one run. Models alive at the same time get disjoint GPU blocks (indices into an inheritedCUDA_VISIBLE_DEVICES) and their own ports, and a phase that does not fit is refused before any engine starts. A model starts only when some sample still needs it, so a resume with inference complete starts only the judge.--dry-runreportsphasesandlaunches;runs[].serving.lifecyclesrecords the lifecycles (#247, closes #245).
Fixed
- A run fails fast when an engine it launched dies. An engine lost mid-run (an SGLang out-of-memory exit) used to fail every later request one by one through its client retries until no sample was left.
sieval runnow polls each launched engine's process every second and its health every 10 s; on a loss, every stage still needing that engine fails at once and stages on other engines carry on. Each task still writesreport.json, the engine is stopped (its leftover process group killed so no worker keeps the GPUs), no later serving group starts, and the run exits 6 naming the engine, its exit code or failing health check, the failures per task and its last log lines. An engine stopped on purpose, lost after its last sample, or not launched by SiEval (api_base,sieval infer start) is not a loss (#246, follow-up to #243).
v0.13.2
A patch release: a model that serves input-scoring tasks on SGLang reserves
memory for their logits, so the engine no longer runs out of memory under full
load. The plan lowers mem_fraction_static and sets a chunked_prefill_size,
reported in --dry-run under serving.<group>.engines.<model>.headroom;
infer.overrides wins. No identity or on-disk format changes: meta.json
identity stays schema 4 and 0.13.1 result directories resume.
Fixed
- An engine that serves input scoring reserves logit headroom. A task that scores its input (
TaskRequirements.input_scoring: the PPL and CLP tasks) makes SGLang compute full-vocabulary logits for every prompt token of a prefill batch, and a recipe sized for generation left too little memory for them: under full load the engine died and every later request failed. An SGLang plan serving such a task now capschunked_prefill_sizeatmin(10% of GPU memory ÷ row, longest scored prompt, 8192), rounded to 1024, whererow = vocab_size × (dtype bytes + 12), and lowersmem_fraction_staticby that reserve's share of GPU memory (Qwen3-30B-A3B-Base on H100 80GB: 3072 tokens, 0.87 becomes 0.79).vocab_sizeandtorch_dtypecome fromconfig.json, GPU memory fromSIEVAL_TARGET_GPUornvidia-smi; when either is unknown, or on a vLLM plan, the plan is unchanged and the reason says why. A pinnedinfer.overridesvalue is kept, but a pinnedchunked_prefill_sizewhose reserve exceeds the 10% budget is refused unlessmem_fraction_staticis pinned too. The reserve changes the launch only, so it is recorded ininfer_plans.yamlandruns[].serving, never in the inference identity, and a resume does not take it twice (#243, closes #242).
v0.13.1
A patch release: a max_tokens-derived context need reserves room for the
prompt, without moving a task that fits under the native window into a scaled
group. No on-disk format changes: meta.json identity stays schema 4 and
0.13.0 result directories resume, except where the served window changed
(below).
Migrating from 0.13.0
- A task's served window changes when its need comes from
max_tokens, so its resume is refused. The window is part of the inference identity, and a resume never reruns inference. On a modelsieval runlaunches with a known native window, amax_tokensbelownativethat 0.13.0 served at exactlymax_tokens, or at the recipe window with fewer than 4096 tokens to spare, is now served atnative. The other tasks on that model's default plan share the window, so theirs changes too. Amax_tokensat or abovenativeis served in scaled group<model>@<max_tokens + 4096>, where 0.13.0 served it atmax_tokens(in<model>@<max_tokens>, or unscaled when the recipe window held it). Start such a run fresh, or pin the recorded window withinfer.overrides(context_length/max_model_len). A model whose tasks all fit the recipe window with 4096 to spare, or all setmin_contextor declareTaskRequirements.min_context, keeps its window (#239, #240). - Where 4096 more no longer fits, the task is refused before launch: a
max_tokensabovecontext_limit - 4096on an endpoint, above the plan's window minus 4096 when the native window is unknown, or abovecontext.max - 4096when scaled. Set the task'smin_contextif its prompts are known to be shorter (#239).
Fixed
- A raised serving window leaves room for the prompt. 0.13.0 raised a plan's window to exactly a task's
max_tokens, so every request with a non-empty prompt was refused as longer than the context. A need derived frommax_tokensnow adds 4096 tokens for the prompt;min_contextand a task's declared need already count it and are unchanged. A task with longer prompts setsmin_context(#239, closes #238). - A
max_tokensbelow the native window is served at that window, never scaled. With the 4096 added, a task such asmax_tokens: 38000on a model withnative: 40960would move into a scaled (YaRN) group, and scaling changes outputs. Such a task now raises the window tonative; its prompt getsnative - max_tokenstokens, and a longer prompt is that sample's context overflow, as before. Amax_tokensat or abovenativestill getsmax_tokens + 4096, in a scaled group whencontext.maxandscalingallow (#240, refs #238).
v0.13.0
A minor bump: meta.json identity moves to schema 4, where inference
digests what the model is asked, including its context limit, and no longer
how it is served; inference_identity takes context_limit instead of
recipe. RESULT_SCHEMA_VERSION stays 1, so 0.12.x result directories
resume, but a run recorded at a context window that sieval run now raises is
refused on resume. Refusals get their own exit codes and a machine-readable
stderr line, and a task can declare the Python packages it needs.
Migrating from 0.12.x
meta.jsonidentityis schema 4 (#233). A reader ofmeta.jsonmust accept schemas 1 to 4.inferencedrops the engine and serving recipe and adds the context limit; eachruns[]entry recordsservinginstead, never compared. A schema 1 to 3 directory resumes once by the digest it was written with, so its engine and recipe must still match, then is rewritten as schema 4.inference_identitytakescontext_limitinstead ofrecipe;TaskRunner,MultiTaskRunner.add_taskandtask_resume_plantakecontext_limit(#233).- New root-model keys:
context_limit(an endpoint's window),weights(compared on resume instead of the name when both runs state it),serving(an endpoint's statedengine_version/topology/hardware; refused on a modelsieval runlaunches) (#233), andcontext(native/max/scaling) (#236). - Serving groups (#236): a task needing more than the recipe window raises it up to
native, or, up tomax, runs on its own scaled engine in serving group<model>@<window>. Groups run one after another;--dry-runlists them underserving, and--serving-group KEYruns one. - Breaking for resume: a run recorded at a window
sieval runnow raises is refused, since the window is part of the inference identity and a resume never reruns inference. Start it fresh, or pin the recorded window withinfer.overrides(context_length/max_model_len) (#236). - Refusals exit 3 (resume), 4 (hardware) or 5 (environment), not 1, and write one
SIEVAL_REFUSAL {json}line per refusal to stderr (#230, #235). A scheduler that treated every non-zero exit alike now sees these codes; the line'svis 2. extraat both placements is refused (models.<m>.extraandmodels.<m>.args.extra, or both in an inlinegrader/extractorconfig). Keep one (#228). A 0.12.0 result directory written from a top-levelextraran without it, so its resume is refused; start it fresh.
Added
- Refusals exit with their own code.
sieval run,evalandinfer startexit 3 on a refused resume and 4 on refused hardware (no GPU for an engine, or not the declared GPUs), and print oneSIEVAL_REFUSAL {json}line to stderr; both used to exit 1 like a crash.--dry-run, and a batch failing in more than one way, still exit 1. Annvidia-smitimeout now fails instead of reading as "no GPU".StageResumeErrorandResumeVersionErrorgaintask; GPU refusals raiseLaunchGpuError(aRuntimeError). See Exit codes (#230, closes #229). - A task declares the Python packages it needs, and a run without them is refused.
Task.python_requires = {import name: PEP 508 requirement}on the class, or apython_requires_for(context)classmethod when the need depends on the task'sargs.sieval runandsieval evalcheck it before any engine starts or dataset loads: a package is met when its import name is found (not imported) and, if pinned, the installed distribution satisfies the pin; extras are rejected. A missing package is anenvironmentrefusal: exit 5, oneSIEVAL_REFUSALline per task withkind: "environment",reason: "python_requires".--dry-runreports it as a newdependenciescheck,task list/showas apython-requiresentry undermissing, andTaskMeta.python_requiresis inmeta/index.json.sieval infer startdoes not check it. TheSIEVAL_REFUSALline'svmoves to 2; theresumeandhardwarelines are otherwise unchanged. It is outside every identity, so resumes are unaffected. No built-in task declares one yet (#235, closes #234). - How the model is served no longer refuses a resume.
meta.jsonidentitymoves to schema 4:inferencedigests what the model is asked, now including the context limit, and drops the engine and serving recipe. Eachruns[]entry recordsservinginstead, never compared, so a run on 1 GPU resumes on 8 and a launched engine's run resumes on an equivalent endpoint. New root-model keys:context_limit(an endpoint's window; a launched engine's comes from its plan),weights(compared on resume instead of the name when both runs state it) andserving(engine_version/topology/hardwareof an endpoint, recorded inruns[].serving.stated). Readers ofmeta.jsonmust accept schemas 1 to 4. A schema 1 to 3 directory resumes once by the digest it was written with, so its engine and recipe must still match, then is rewritten as schema 4.inference_identitytakescontext_limitinstead ofrecipe;TaskRunner,MultiTaskRunner.add_taskandtask_resume_plantakecontext_limit(#233, closes #232). sieval runsizes serving to what the tasks need. A task's need isTaskRequirements.min_context(RULER declares one) or its effectivemax_tokens, overridable with a task'smin_context; a root model's newcontext:block statesnative/max/scaling. The recipe window is raised up tonative; a need up tomaxgets its own scaled engine in serving group<model>@<window>, run after the default group; anything else, or a need beyond a window pinned byinfer.overridesorcontext_limit, is refused before launch.--dry-runlists groups underserving,--serving-group KEYruns one, andruns[].serving.grouprecords it.sieval infer start <yaml>serves the same raised window. Breaking for resume: a run recorded at a window now raised is refused (inference is never rerun); start fresh or pin it withinfer.overrides. An SGLanggenmodel with nodialect:now defaults tosglang_legacywhen a task scores input, instead of refusing (#236, closes #231).
Fixed
- A model's top-level
extrareaches the model.models.<m>.extrapassed--dry-runand was then dropped at binding, soModel.extrawas{}and the inference identity omitted it. It now binds likeargs.extraon every dialect and on derived models;args.extraidentities are unchanged. A 0.12.0 result directory written from a top-levelextraran without it, so its resume is refused as an inference change; start it fresh (#228, closes #227). - Breaking:
extraat both placements is refused before any engine starts, on named models and inlinegrader/extractorconfigs. Inline configs used to accept both and silently useargs.extra. Keep one (#228).
v0.12.0
A minor bump: meta.json identity moves to schema 3, with one identity per
stage, and the 0.10/0.11 deprecations are removed. RESULT_SCHEMA_VERSION
stays 1, so 0.10.x and 0.11.0 result directories resume, and an unchanged task
upgrades in place to schema 3 without regrading. sieval run now starts an
engine only for samples left to infer, and sieval run --dry-run reports what
the run would do, per model and per task.
Migrating from 0.11.x
meta.jsonidentityis schema 3 (#211, #218): one identity per stage,data,preprocess(wasprompt),inference,postprocess,feedback,report. The combinedgraderis gone; judges and services move tofeedback.preprocessis{digest, modules, args, splits?, fallback?}, the code and arguments that render a prompt, instead of a digest of the rendered prompts. Eachpreprocessrecord is stamped{data, preprocess}instead of{data, prompt}. A reader ofmeta.jsonmust accept schemas 1 to 3: 1 from 0.10.x and 0.11.0, 2 from unreleasedmainbuilds only, 3 from now on.RESULT_SCHEMA_VERSIONstays 1, so 0.10.x and 0.11.0 directories resume: an unchanged task's directory upgrades in place without regrading, after one localpreprocesscall per recorded sample. Apreprocesschange now restarts every sample of the task.TaskSaver.begin_run(identity={...})andset_identity(**stages)replace the per-stage keyword arguments.- Removed (#222):
sieval.cli.leaderboard.session, deprecated in 0.11.0. Import fromsieval.cli.session, and resolvers fromsieval.cli.resolution.--resume-from DIRis an unknown option. Use--resume DIR.runner_config.auto_resumeandrunner_config.resume_from, top-level or per task, are refused before anything runs, naming theresumeform to use. In 0.11.0 they warned and still worked. Writeresume: trueorresume: <dir>.- The Transport aliases (
sieval.core.models.Transport,OpenAIChatTransport,OpenAICompletionsTransport); use the Dialect names.SglangTransportstays.sieval.infer.InferConfigis gone.
SIEVAL_TARGET_GPU(<name>:<count>:<memory MiB>, asnvidia-smireports, e.g.NVIDIA H100 80GB HBM3:8:81559) declares the GPUs a serving plan is resolved for, so a CPU node resolves the plan, and the inference identity, a GPU node would. Unset, nothing changes. Set, an engine launches only on a node with exactly those GPUs (#215).sieval runlaunches engines lazily on a resume (#216): a run that may resume plans each task first and starts only the engines some task still has samples to infer with. A resume that reruns only grading stages starts no engine and runs without GPUs. A fresh run launches as before.sieval run --dry-runnow loads every dataset and starts each vendored service a task declares, as the run does, in order to plan each task (#217). A dry-run on a node without the data fails theresume_plancheck, where 0.11.0's passed; stage the data, or mount it, before the dry-run. It still launches no engine and writes no result directory.Model.extracarries capabilities a task may ask for, starting withsequence_wrappers(#218, #221). A malformedsequence_wrapperstemplate is refused when the model is built and by--dry-run.- A plugin task declares its report metric names with
report_metrics = report_metrics(...)(sieval.core.tasks.report_metrics) on its class (#225). Undeclared,tasks.<task>.metricsin the dry-run isnull; a malformed declaration fails thereport_metricscheck.
Changed
preprocessis identified by code, not by the prompts it renders (#218): the static walk the grading stages use, thegrader_args()it reads, and for few-shot a digest of the split it draws from. A model'sextrareaches the request, whichinferencedigests, so a wrapping and a plain model sharepreprocessand differ ininference. A run-time name or a file opened at run time falls back to the task's whole code and the data files beside the reader. A preprocess change now restarts every sample of the task, where before only the samples whose prompt changed restarted.- A resume reruns from the earliest stage that changed (#210). An extraction change reruns from
postprocess, a scoring change (judge, prompt, sampling, service,feedbackcode) fromfeedback, and areport-only change recomputesreport.jsonfrom the records with no engine or judge call. Before, each of these regraded every sample. Code is attributed to stages by a static walk; a run-time lookup (getattr(self, <expr>),eval,importlib) falls back to all grading code. No built-in task falls back. runs[].resumecounts what a resume did with each recorded sample.sieval runstarts an engine only for a model with samples to infer (closes #213). A run that may resume (--resume, orresumein arunner_config) first plans each task's resume, read-only, through the runner's own resume planning (TaskRunner.plan_run), and launches only the engines whose models some task still has samples to infer with. A resume that reruns only grading stages, or re-reports, starts no engine and runs on a node without GPUs; when some sample needs inference andnvidia-smifinds no GPU, the run is refused before anything starts. The plans,infer_plans.yaml, the inference identity and its request digest are what an eager launch records. A fresh run is not planned and launches as before. A sample thatfeedbacksends to another iteration after a rerun fromfeedbackfails atinferwhen its engine was not started, and a resume that starts it retries it.
Added
Model.extrais the capability contract between tasks and models, starting withsequence_wrappers(#218). A task asks for a capability by key and does nothing different when it is absent.sequence_wrappers: {<seq_type>: "<format with {seq}>"}(typesdna,rna,protein,mol) gives the special tokens a model was trained with around biological sequences; a task reads it withsequence_wrapper(self.model.extra, <type>)inpreprocess. A malformed template is refused when the model is built and by--dry-run. No built-in task injects such sequences yet.SIEVAL_TARGET_GPUdeclares the GPUs a serving plan is resolved for, as<name>:<count>:<memory MiB>with the name and memorynvidia-smireports, e.g.NVIDIA H100 80GB HBM3:8:81559. Recipe resolution reads it instead ofnvidia-smi, on any node, so a CPU node resolves the plan, and the inference identity, a node with those GPUs would. Unset, nothing changes. Declared, an engine launches only on a node with exactly those GPUs.infer_plans.yamlgainsgpu, the GPUs its plans were resolved for, outside every identity; asieval run --resumedeclaring the same GPUs reuses the recorded plan of each served model whosepath,infer, capability layer anddeterministicare unchanged, unless the plan held an engine secret, whichinfer_plans.yamlrecords redacted (#215, closes #212).sieval.core.runners.task_resume_plan/plan_resume: the per-stage resume plan, without running anything.TaskRunner.plan_run/MultiTaskRunner.plan_run(RunPlan): the runner's per-sample plan of a run,to_inferincluded, read-only; the onesieval runlaunches by.sieval run --dry-runreports what the run would do (closes #214).-o jsonaddsgpu,models(each served model's plan asinfer_plans.yamlwould record it, each process its launch starts, andneeds_inference, whether this run starts it),tasks(each task'sstart,resume_planwith the countsruns[].resumewill record,nullfor a fresh start,new,to_inferandto_grade) andneeds_inference, whether any engine starts. The plans come from the callsieval runlaunches by. A resume that would be refused, or planning that raises, fails the newresume_plancheck; when the dry-run stops before planning,tasksandneeds_inferencearenull. It launches no engine, writes no result directory, reads--resumedirectories in place, and runs on a node without GPUs givenSIEVAL_TARGET_GPU. Planning loads the datasets and starts each vendored service a task declares, as the run does, so a dry-run that passes its checks costs a session setup. The existing checks are unchanged.sieval run --dry-runreports each task'sstages(per-stagesame/differs/unknown, andrerun_from, the stage a resume reruns from), its ownneeds_inference, and itsmetrics(below);RunPlangainsstages(closes #219).- A task's report metric names are known before it runs (closes #223):
tasks.<task>.metricsin the dry-run is{names, patterns}, ornullwhen unknown, and a malformed declaration fails a newreport_metricscheck. Built-in tasks are declared insieval/meta/report_metrics.py, outside every stage identity; a plugin task declaresreport_metrics = report_metrics(...)(sieval.core.tasks.report_metrics) on its class. Every task test checks its report against the declaration.
Removed
sieval.cli.leaderboard.session, deprecated in 0.11.0. Import fromsieval.cli.session(resolvers fromsieval.cli.resolution).- The resume aliases deprecated in 0.10.0.
--resume-from DIRis now an unknown option (use--resume DIR). A config settingrunner_config.auto_resumeorrunner_config.resume_from, top-level or per task, is refused before anything runs, naming theresumeform to use, rather than ignored, so a resume never silently becomes a fresh run.TaskRunnerConfig(auto_resume=, resume_from=),EvalSession(resume_from=),arun_session(resume_from=)/run_session(resume_from=)andsieval.core.runners.fold_resume_aliasesare gone; passresume=Trueorresume=<dir>. - The transport import aliases:
sieval.core.models.Transport(usesieval.core.models.dialect.Dialect), andOpenAIChatTransport/OpenAICompletionsTransport...
v0.11.0
A minor bump: sieval leaderboard is removed and SiEval is scoped to an
evaluation engine, and a resume is now admitted by the result schema version
instead of the package version. No stage identity changes: IDENTITY_SCHEMA
and RESULT_SCHEMA_VERSION are both 1, every built-in task's grader digest is
the one 0.10.2 computes, and 0.10.0, 0.10.1 and 0.10.2 result directories,
local builds included, resume. anomalies.json's rules_hash changes, since
the rule set gained context_overflow.
Migrating from 0.10.x
sieval leaderboard runis nowsieval eval, with the same options.sieval leaderboard report/list, alignment cards and the shipped leaderboard specs are gone; compare runs from their result files andmeta.json. A config'salignment:block loads with a warning and is ignored.- Import the engine from
sieval.cli.session.sieval.cli.leaderboard.sessionstill works for this release, with aDeprecationWarning, and forwards every name. - Each task directory gains
requests.jsonl, one line per model request attempt. Setrunner_config.record_requests: falseto turn it off. - A prompt longer than the context window scores as wrong and is flagged by the
context_overflowanomaly, instead of failing the sample; it counts underreport.jsonsieval.context_overflowandanomalies, notfailed. A task declarescontext_overflow = "fail"to keep the failure. - The resume gate reads
meta.jsonresult_schema_version. A directory without it maps from itsversion(0.10.0 or later is schema 1), so 0.10.x directories resume as they are. Replaceresume_version_verdictwithresume_schema_verdict.
Added
requests.jsonl: every model request attempt is recorded. One line per attempt beside a task's shards: phase, role, model, sample, attempt number, timings (connect_sis the wait for a pooled connection), HTTP status or exception class, provider request id, retry wait, usage, and the occupancy of every limiter it ran under. Judges and extractors are covered without task code.profile.jsongains a per-phase, per-modelrequestssummary,report.json'ssievalblock its counts and limiter peaks, and eachmeta.jsonruns[]entry the run's own counts. The file is append-only, rotated (request_log_max_bytes,request_log_max_files), and read by nothing: no identity, digest or score depends on it.record_requests: falseturns it off (#197, #201).sieval run --checkpoint <path>andsieval run|eval --api-base <url> --model <name>add the onemodels:entry a config with onlydatasets:andtasks:lacks, andeffective_config.yamlrecords it, so a rerun or resume needs no flags. Both flags together,--api-basewithout--model, or either on a config that defines models is refused before anything launches;--dry-runreports it as thecli_modelcheck (#195, #198).result_schema_versioninmeta.json(RESULT_SCHEMA_VERSION, starting at 1) versions the result directory a resume reads, separately fromidentity.schema. The package version stays inversionandruns[].sievalas provenance (#202, #203).context_overflowanomaly rule (gen tasks), andModel.context_overflow_outputfor a task that measures its own prompt and records the overflow without sending it (#206, #207).
Changed
- BREAKING — SiEval is an evaluation engine. The
leaderboardcommand group is removed withrun,reportandlist;sieval eval(cli/eval.py) replacessieval leaderboard runand always reportscommand="eval"/eval.dry_run. The engine moves tosieval.cli.session.card.py,catalog.py,scanner.py,annotation.py, the leaderboard renderers andleaderboards/are deleted;examples/leaderboard-math-sft.yamlis nowexamples/math-suite.yaml(#194, #199). - BREAKING — resume compatibility is keyed on the result schema version, not the package version. A resume refuses another schema version, naming both schema versions and both SiEval versions. A directory without the field maps from its
version: 0.10.0 and later, local builds included, is 1; older, unparseable or0.0.0ones are refused as before. Dev and local builds (0.10.2+gc18745b) now resume across builds when the schema matches.resume_version_verdictis replaced byresume_schema_verdict(#202, #203). - A prompt longer than the model's context window is scored as wrong, not failed. When the server refuses the model under test's prompt as too long (SGLang's "is longer than the model's context length" or "Requested token count exceeds the model's maximum context length", vLLM's and OpenAI's "maximum context length", a 400 or 413), the call inside
inferreturns one empty text per rollout with finish reasoncontext_overflow. The task grades it like any blank answer, thecontext_overflowrule flags it, andreport.json'ssievalblock counts it underanomaliesand the newcontext_overflowkey, not underfailed. It used to fail the sample on every resume, so a run with one never completed. A task declarescontext_overflow = "fail"to keep the failure, now recorded with reasoncontext_overflowand never retried. Timeouts, connection errors, 5xx and a judge's own overflow still fail; a logprob call fails ascontext_overflow. A task that catches the refusal itself (Multi-IF's and SysBench's walks) is unchanged.extraction_failureandempty_postprocessleave such rollouts to the new rule. Inrequests.jsonland the request summaries the refused attempt keeps its status and is counted under outcomecontext_overflowinstead of4xx(#206, #207). - A resume scores a recorded overflow without asking again. A directory whose samples failed with a context-overflow refusal at
infer(as 0.10.x recorded them) resumes them from the recorded refusal when the inference identity matches: no request is sent, no retry is spent, and the sample is graded and counted as above. The recorded message must name a 400 or 413 (or no status, as a stream error does), as live: a 429 or 5xx quoting the words stays a retriable failure. A task whoseinfercalls the model under test more than once, in turn or concurrently, is inferred again instead, since the record cannot say which call was refused. Because a refusal that escapesinfermakes the runner callinferonce more with refusals converted, aninfershould have no side effects beyond its model calls (#206, #207). max_retriesmeans the same on every connection family. The Anthropic and Google clients used to retry only connect failures, so a 429 or 503 from such a judge failed its sample at once. They now retry as the OpenAI SDK does: 408/409/429/5xx and transport errors,x-should-retry,retry-after(-ms)within 60 s, 0.5 s doubling to 8 s with the SDK's jitter. Both families get the SDK's connection limits (1000/100; httpx's default of 100 queued requests past a higher concurrency limit) and follow redirects, and Anthropic's HTTP errors name the provider's reason, as Google's do. The retry policy is renamedsieval-http:max-retries=, so a binding plan made under the old meaning is refused rather than reread (#201).progress.jsonis written off the event loop, asreport.jsonandmeta.jsonare; on a network filesystem its fsync used to stall every task in a session (#196, #200).
Fixed
- The deprecated
sieval.cli.leaderboard.sessionalias forwards every global ofsieval.cli.sessionandsieval.cli.resolution, not only its ten__all__names;getattr(alias, "DETERMINISTIC_DEFAULT_SEED", None)returnedNoneand silently droppedseedin deterministic runs (#204, #205).
Deprecated
sieval.cli.leaderboard.session, kept for one release (#199). The resume aliases deprecated in 0.10.0 (--resume-from,auto_resume,resume_from) are still accepted and still warn.
Identity
RESULT_SCHEMA_VERSION stays 1 although scoring an overflow is a core change that alters results: 0.10.x never finalized an overflowed sample, so a resume reuses no result the change would have made differently, and it builds that sample as a fresh run would. A reused 0.10.x report.json gains context_overflow in its sieval block. Every built-in task's grader digest is 0.10.2's, and inference digests are unchanged.
v0.10.2
No on-disk format or stage identity changes: IDENTITY_SCHEMA stays 1, every
built-in task's grader digest is the one 0.10.1 computes, and 0.10.0 and 0.10.1
result directories resume. Two configurations that used to run are now refused:
an evaluation that loads a staged dataset holding bytes other than its pinned
revision, and an args.api_base on a model sieval run launches.
Added
- Input-side top-k logprobs. A request that scores its input with
top_logprobs > 0, such asalogprobs(echo=True, logprobs=N), returns the top-N alternatives at every echoed input position inModelOutput.input_top_logprobs(IR:InputScoringResult.top_logprobs, aligned withtoken_logprobs). Supported onsglang_legacyandopenai_completions; a missing or misaligned input top-k is refused.top_logprobsstill holds only the generated tokens'.alogprobs'logprobsdefaults to 0 withecho(what was sent before) and 5 without; an explicit value is now sent withechotoo, so only a caller passingecho=True, logprobs=N>0sends a different request than in 0.10.1. No built-in task does (#178). gatedin the dataset registry.DatasetMeta.gated(frozen wire field; absent reads asfalse, so olderindex.jsonfiles load).hleis gated.sieval dataset listgains a GATED column,dataset showaGated:line, anddataset downloadrefuses a gated source without a Hugging Face token, or the Hub's refusal, with a message naming the gate and what to set (#181, #182).bbh,mgsm,mmlu_reduxandtrivia_qaare registered, each revision-pinned, sosieval dataset downloadfetches them and tasks name them by bare repo id. MGSM points atjuletxara/mgsm, sinceljvmiranda921/mgsmis gone from the Hub. Anhf:source may end in#<glob>, forwarded assnapshot_download(allow_patterns=...);trivia_qastages onlyrc.nocontext/*(about 60 MB of a 35 GB repo) and evaluatesvalidation, because upstreamtestis unlabeled (#180, #184).
Fixed
- Staged datasets are checked against their pin.
hf:sources must carry the download recordsnapshot_downloadwrites naming the pinned commit for every file;url:sources must match their declared checksum.sieval dataset downloadrecords each checksum it verified in<dataset>/.sieval/download/, and probes read that record while size and mtime match, else hash once per process. Probes never write into the data dir, so a read-only or sharedSIEVAL_DATA_DIRworks (#179, #183, #187, #190). - A
sglang_legacymodel with aninfer:block reaches the enginesieval runlaunched; it used to fall back to the OpenAI SDK default base and fail every request with HTTP 404 (#185, #186). - An engine
sieval runlaunched gets the placeholder keylocalwhen the config names none, instead of failing at client creation withoutOPENAI_API_KEYor sending whatever that variable held. An explicit key still wins, and an endpoint the run did not launch still reads the SDK's env var (#188, #191).
Changed
- BREAKING — a stale staged dataset is refused.
sieval dataset downloadrefuses a source whose staged directory holds other bytes, with the reason and a--forcehint, and deletes nothing.--forceon anhf:source clears the repo directory before fetching, sincesnapshot_downloadkeeps files it did not write. Readiness reports such a source as missing data (missing[].stalein JSON,[stale: …]in text).sieval run/sieval evalrefuse a datasetpath:that resolves to a registered source's staging directory holding other bytes; apath:outside staging loads as given. A data dir filled by hand now readsready: no: re-runsieval dataset download <name> --force(#179, #183). - BREAKING —
args.api_basenext topathorinfer.checkpointis refused before any engine starts, bysieval runand--dry-runalike. It used to be ignored by canonical dialects and to bypass the launched engine onsglang_legacy. Remove it to evaluate the launched engine (the #185 workaround is no longer needed), or removeinfer/pathto evaluate the endpoint. A top-levelapi_basestill turns auto-serve off.EvalSessionalso refuses a configuredapi_basethat differs from a realized deployment's (#189, #192).
v0.10.1
A patch release despite two breaking changes, because neither touches an
on-disk format: meta.json, report.json and the shard records read as
before, IDENTITY_SCHEMA stays 1, and a 0.10.0 result directory still resumes
(one retuned serving plan aside, below). What breaks is configuration (the
embedding endpoint must now be set) and the grader digest; a resume that sees a
changed grader digest regrades on the recorded inference, so no sample is
inferred again.
Added
- Per-rollout generation logprobs at
n > 1.infer_args: {return_logprobs: true, top_logprobs: N}used to be refused aboven: 1; now every rollout's logprobs land inModelOutput.choice_logprobs, oneRolloutLogprobsper rollout intextsorder, and the single-sequence fields stayNone. Supported onsglang_legacy(each sample's ownmeta_info, and a reply with a sample count other thannis refused),openai_completionsandopenai_chat(streaming included).google_genaiandopenai_responsesrefuse it before any I/O. Old records decode withchoice_logprobs=None. For dialect authors: anOutputContractdefined outside SiEval needs achoice_logprobsrule, or building it raises (#171, #175). client_timeout: {connect, read, write, pool}, in seconds, wherevermax_retriesis accepted (a root model, top level orargs, and an inlinegrader/extractor; a derived model is refused). It is a client setting: never sent in the request body and in no stage identity, so changing it resumes without a rerun or regrade. Defaults are 5 s connect and 600 s for the rest; an enginesieval runlaunched defaults to a 30 s connect. A model'sargs.timeoutis still a request argument, not the client timeout (#169, #174).
Fixed
qwen3-30b-a3bSGLangmem_fraction_staticdrops from 0.90 to 0.87 on A100-80G bf16 and H100-80G bf16/fp8. At tp2×dp4, 0.90 left DP0 too little memory for SGLang's piecewise CUDA graph capture and the server OOMed at startup; that H100 configuration never came up at 0.90. The serving plan is part of the inference identity, so an earlier result for this model on these GPUs that used the recipe default (no hand-pinned value) now reads as a different inference:--resumerefuses it, and a leaderboard shows it Pending (#168, #172).- A request timeout's
error_msgnames the phase that timed out, e.g.Request timed out. (timeout phase: connect);error_reasonis unchanged (#169, #174).
Changed
- BREAKING — NL2SH-ALFA and T-Eval no longer default to an internal embedding endpoint. NL2SH-ALFA (both readings) and T-Eval with
eval_thought=Trueneed bothSIEVAL_EMBED_APIandSIEVAL_EMBED_API_KEYset, and the task fails at construction if either is unset. T-Eval withouteval_thoughtneeds neither (#167). - BREAKING — the grader identity is keyed by file path within its code root, not by import name.
identity.grader.moduleskeys become file paths (sieval/tasks/gsm8k_0shot_gen.py, or./…for the task's own plugin package), andidentity.grader.taskbecomes<file key>:<qualname>. Every plugin package the walk reaches is digested whole, whatever its name, namespace packages included. Within the task's own plugin package, absolute self-imports are normalised before hashing and a directory without__init__.pydigests as having an empty one, so a renamed copy (such as sieval-plugins'sieval_plugins__<task>__<variant>) digests the same as the original. Grader digests rotate fleet-wide, built-in tasks included;IDENTITY_SCHEMAstays 1, and a resume of a 0.10.0 directory regrades on the recorded inference (#170, #173, #176). - CI's change detection compares a push to
mainagainst the previous commit, so a re-run no longer fails on a stale default-branch name (#166).
v0.10.0
A minor bump for four breaking changes, all in on-disk or CLI-report contracts:
manifest.json is gone, every exit path finalizes report.json and
anomalies.json the same way, a resume compares stage identities instead of
config text, and sieval infer reports engine_pid instead of handle_id. The
theme is RFC #148: meta.json now records where a result directory came from,
and a resume reruns, regrades or refuses by which stage changed. Two native
provider dialects (Anthropic Messages, Google GenAI) and auto-started vendored
services land alongside.
Added
api_key_env: <VAR>reads a model's key from an environment variable, whereverapi_keyis accepted (root models and inlinegrader/extractor), on every dialect. Setting both is refused; an unset variable fails before any engine starts. Neither the value nor the name is in any identity, so rotating a key or switching forms resumes without a rerun (#148, #163).- Per-stage resume.
--resume(in place) and--resume DIR/runner_config.resume(start from another, possibly read-only, run of another task) compare the four stage identities: changed data or prompt reruns those samples, a changed grader regrades on the recorded inference, a changed inference or an unknown stage it would reuse is refused (#157). Task.grader_args(): task arguments folded into the grader identity, read aftersetup(); a task excludes arguments that cannot change a verdict viaGRADER_ARGS_EXCLUDED(#157, #158).- Stage identities and run history in
meta.json.identity(schema 1) holdsdata,prompt,inferenceandgraderdigests — the inference digest folds in what each sample was actually sent, the grader digest walks the task's MRO, its static imports and plugin packages, and records each judge's model, version, sampling and prompt (never itsapi_base).runs[]is append-only, andmeta.jsonis rewritten atomically on every run (#150, #154). dialect: anthropic_messages— native Anthropic Messages JSON and SSE, with explicit capability admission, request auditing, replay-safe extended-thinking continuations, and refusals lifted as scoreable terminal outcomes.max_tokensis required (#145).dialect: google_genai— native GeminigenerateContent(v1/v1beta): streaming, function and hosted tools, thinking, logprobs, seeds, opaque continuation. Google enforces model limits itself, so a provider 400 is the error and a gateway alias skips nothing; a YAML-bound model takes reasoning and logprobs as supported, while tools, structured output, images and continuation still fail reconciliation withmodel_outcome_missinguntil Google model profiles exist (#147, #153, #156).- SiEval starts the services it vendors. A task declares them in
Task.services; the ten families that post toSIEVAL_CODE_EVAL_APIdeclarecode-eval.sieval run,sieval evalandsieval leaderboard runstart each declared service whose endpoint variable is unset — once per run, on a free port, stopped when the run ends. The started evaluator grades without a sandbox and warns so; point the variable at a containerized endpoint to avoid it. Running it with SiEval's own interpreter needs the newcode-evaldependency group.identity.grader.servicesrecords each service asvendored(commit, code digest, interpreter runtime) orexternal(#155). - SIGTERM stops
sieval runandsieval evalas Ctrl+C does; exit 143 (#158). - Google
request_paramsrecordno_effectfor a thinking budget or summary the reply shows no sign of (#158).
Fixed
effective_config.yamlandinfer_plans.yamlwrite everyapi_key/authorizationvalue as<redacted>; rerunning such a file is refused until the key is supplied again (#163).- A resume's
runs[].configinmeta.jsonshowed a changedapi_keyby value; it now shows<redacted>(#163). - A
--resume DIRrun killed beforemeta.jsonrecorded it now resumes on the same command, instead of being refused as a run of unknown version. The copy writes.copyingfirst and removes it once the run is recorded; the same--resume DIRcopies again, and--resumealone refuses it (UnfinishedCopyError) (#162). - An
.idxoutside a<iteration>/<stage>/directory named for aTaskStageis neither loaded nor counts as a started run (#162). - A directory holding shards counts as started whatever
meta.jsonsays: a fresh run refuses it instead of adopting its samples, and a resume without a usablemeta.json(a killed v0.6 run, including the latestoutputs/<task>/<timestamp>, no longer skipped) is refused by the version gate (#160). - A run stopped mid-way keeps every finished sample: the saver flushes on every exit, samples still in the storage stream are drained to disk, and a failed or cancelled flush re-queues its batch instead of dropping it (#154, #158).
- A run interrupted before every sample passed
preprocessresumes instead of refusing ondata; a refused resume appends noruns[]entry (#158). - A fast resume that finds
report.jsonfrom a run that never ended finalizes again instead of reusing it; refinalizing a run whoseend_runfailed writesanomalies.json(#154, #158). - Atomic writes use a unique temp file with fsync, and create
report.jsonandmeta.jsonas0o666 & ~umask, not0600(#154, #158). - The grader identity covers patch packages and whole plugin packages, including modules loaded with
importlib(#154, #158). - A resume with another model regrades the recorded inference, and is refused if it would infer any sample (#158).
- The inference requests digest keeps only the request body and a normalized stream flag, so Google's model path or a gateway prefix no longer moves it (#154).
- Google usage:
output_tokensincludes thoughts andinput_tokensthe tool-use prompt, soreasoning_tokensis a breakdown of its parent; Google'serror.messageis appended to the HTTP error, so a failed sample'serror_msgnames the reason (#147, #156). - Google's request envelope is marked explicitly, not detected by a
pathkey (#158). - A bad code-eval copy or interpreter fails before any engine starts; service logs move to
logs/services/<name>/(#158). LiveOIBench refuses an evaluator whose/languageslackscpp, and fails a rollout that could not compile for want ofg++instead of scoring it 0 (#155). SIEVAL_JUDGE_MODEL_REFis validated when a runner is built and unmatched roles are warned about;tunedModels/is stripped likemodels/(#154, #158).sieval runno longer collides with aninfer startof the same model; every handle write goes through one locked transition, and a pending handle stays held while any of its engines is alive (#149, #155).- The resume benchmarks seed their result directory with a real run, so the
benchmarkgate andtests/performance/test_resume_speed.pypass again after per-stage resume; each resume test now asserts it re-infers only the missing samples (#161).
Changed
- One resume option,
--resume [DIR], onsieval run,sieval evalandsieval leaderboard run.--resumeresumes each task in place;--resume DIRstarts each task fromDIR/<task>, as--resume-from DIRdid. ADIRthat is the run's own directory resumes in place instead of being refused. YAML:runner_config.resume(trueor a task directory). Python:TaskRunnerConfig.resumeandresume=onEvalSession/arun_session/run_session.resumenever entersruns[].config(#164). - BREAKING —
manifest.jsonis removed. A sample's state is its latest shard record, found through.idx; read per-sample status from the.idxcolumns or the record'serror_*fields (#159). - BREAKING — every exit path finalizes the same way.
report.jsongains asievalblock (total,final,failed,anomalies) that decides a fast resume;anomalies.jsoncovers every iteration and losessummaryand its timestamped backups;runs[].rules_hashnames the rules applied (#159). - BREAKING — a resume compares stage identities, not config text.
effective_config.yamlandinfer_plans.yamlno longer refuse a resume and are audit records;gate_resume_identityand_append_resume_noteare removed, and YAML headers keep only the first run's provenance. The version-series gate stays (#150, #157). - BREAKING —
sieval infer start/list/show/stopJSON reportsengine_pidinstead ofhandle_id. Handle files useowner_pid/engine_pid(oldpid/handle_idfiles still load and are rewritten on the next transition).sieval runkeeps its handles under~/.sieval/handles/run-<pid>/. Engine logs move to<result_dir>/logs/<model>/<role>.logforsieval runwith a result_dir, else~/.sieval/logs/<model>/<role>-<deployment_id>.log, pruned at launch to the last N per model and role (--keep-logs→SIEVAL_KEEP_LOGS→ 3; 0 deletes on stop; negative keeps all) (#149). - Behavior change —
n_truncatedcounts every interrupted output, not just budget stops: GoogleMAX_TOKENS/CONTINUATIONand candidate policy stops (SAFETY,RECITATION, …), and Anthropicrefusaland context-window stops. A new per-choicefinish_reason_sourcesrecords which. Anthropic runs that refuse show highern_truncatedthan before — not a regression. The rule prose changed, sorules_hashrotates fleet-wide to2c440347324b1edb(#145, #147). meta.jsonrecordsconfig(the session'seffective_config.yaml) andruns[].id, a run ID sortable by start time; the leaderboard scanner reads them instead of walking up the filesystem (#159).- A failed write of
meta.jsonorreport.jsonnow fails the task (#150). A task namedlogsis refused:<result_dir>/logs/is reserved (#155). google_genaino longer validates Gemini limits by model name: unsupported thinking levels and budgets get Google's own 400, Gemini 3candidateCount > 1is allowed, and Gemini 3temperature/top_p/top_kare f...
v0.9.0
A minor bump for four breaking changes, none of which raise on an old input: a
report.json key unification, a config-format change where a dialect must now
be named rather than inferred, a request-audit contract that only an out-of-tree
dialect can notice, and two new ci95_units rules. The largest theme is
execution-graded evaluation — text-to-SQL, shell, C++ and multi-language
code now run and are judged by what they produce, which is what most of the new
infrastructure exists to support.
Added
- New benchmark tasks & datasets:
- BFCL v3 (single-turn) —
bfcl_v3_{non_live,live}_0shot_genand their_fctwins over 3,641 rows, sieval's first native-function-calling protocol._fcis a new variant word: it changes which model capability is exercised, so Prompt and FC are separate tasks the way BFCL's own leaderboard reports them side by side. Multi-turn is not implemented (#143). - LiveOIBench — 380 of 403 informatics-olympiad problems graded in C++ with IOI-style subtask partial credit and ranked against the contests' real human contestants. The 23 interactive problems are excluded rather than scored zero, so numbers are not comparable to the paper's 403-problem table (#121).
- Ag-LiveCodeBench-X — LiveCodeBench v5's stdin/stdout subset made language-agnostic, with
languagea required task argument because the benchmark measures a different thing per language (#123). - QuoteBench — 56 Bash tasks graded by exact final program state, shipped as two tasks because
rawandnested_shellare two command-path contracts, and the paper's finding is that they reverse the order of 5 of 26 model pairs (#140). - NL2SH-ALFA — natural language to Bash, execution-graded, as an unqualified task and a
_parsetwin; the gap between the two readings reaches 32% on small models (#139). - MultiPL-E — HumanEval in 24 languages and MBPP in 23, with the chat task grading the model's own copy of the prefix, as upstream does deliberately (#138).
- Spider 1.0 — sieval's first in-process SQL execution substrate, with the hardened reading carried by the unqualified task and the delta measured at 99.903% verdict parity against upstream (#124).
- Spider 2.0-lite — all 547 questions over three engines; a credential-less run caps near 24.7%, so a per-backend breakdown always ships beside the headline (#125).
- WikiSQL — upstream's own logical-form protocol, so no model-authored SQL is executed; the grader is anchored on upstream's shipped example predictions (#122).
- MATH-Perturb — 279 Level-5 problems each under simple and hard perturbation, promoted to
stableon a measured deepseek-math-7b-rl alignment run (#130). - SysBench — 500 Chinese 5-turn sessions, LLM-judged (#103).
- SciTaRC — composite QA over raw LaTeX tables (#119).
- BFCL v3 (single-turn) —
- Every metric that can carry an interval now carries its own —
<metric>_ci95, with a new nestedci95_unitsobject saying which population each is clustered on. A headline interval now reaches 52 of 58 reports, and five new population keys ship (n_versions,n_problems_wo_critical_thinking,n_subjects,n_subsets, andn_problemson SimpleQA-Verified). Purely additive:score_ci95andn_problemskeep their spelling and their values, verified over 3,216 paired emitter comparisons (#126). ifeval/multi_if/ifbench_fixedvariants — seven repaired constraint checkers across the family, each with a quantified score delta (#104, #105).report.jsongainsn_truncated+n_scored_rolloutson everygentask, injected by the runner so a task cannot report zero by having forgotten to look. Reported as a pair, because the count alone is unreadable (#113).filtergains composite keys, derived (callable) keys, avalues_file, and arequire_allflag — each pinned intoeffective_config.yamlby a provenance digest that participates in the strict--resumecomparison (#106).- OpenAI Responses API dialect (#141).
TaskRequirements.function_tools, so a task can demand the tools API and be rejected at construction;ModelOutput.tool_callsnow forwards through the legacy bridge, which is what makes the declaration satisfiable (#143).DEFAULT_REQUEST_TIMEOUTis declared instead of inherited — openai's SDK andhttpxdisagree by 120x on the default, so a dialect's connection family used to decide how long a generation could take. No behavioural change today; a trap defused ahead of the first native transport (#112).- Repeated rows record which copy they are, both in the dataset and per sample (#114).
ihevalrecords carry a per-rowkey;extrapreviously named only a cell, so two rows of one cell produced byte-identical records (#111).sysbenchreports every breakdown rate's denominator, and counts what it used to drop (#110).sieval infer startexposes the readiness budget onrun(#135).
Fixed
- IFBench stopped scoring a biased subset when its NLTK corpora are missing.
nltk.downloaddefaults toraise_on_error=False, so offline the import completed as if the data were there and the absence surfaced oneLookupErrorat a time — landing those samples infailswhiledenominator_policy: judgedscored the remainder. The published number was computed over the subset whose constraints never touched NLTK (#109). - A broken grader no longer reads as a wrong answer (#131).
- One task's crash no longer cancels the rest of the batch — a single task raising used to take every sibling runner down with it, losing even tasks that had already finished computing their reports (#117).
t_eval_before_calling_0shot_genomits an axis with no samples behind it instead of writingnull, and reportsn_graded/n_parsedso an absent axis can be read (#116).- A missing split is reported from every dataset transform, not just
filter(#108). - A
--resumeno longer aborts on a field explicitly declared non-matching (#137). - A deploy that never becomes ready says why (#134); a hardware key matches when the GPU reports no memory size (#133).
- Deterministic request seeds are dialect-aware (#118); legacy model provenance is stable (#132).
- A timeout is read off the message prefix rather than by substring match (#142).
Changed
- BREAKING — the LLM-judged family's grader-parse metric is unified to
n_grader_unparsed, replacing four spellings across five tasks. A consumer reading an old name gets a missing key, which reads as "not reported" rather than erroring.judgeis now confined to upstream contract names and prose, never a record field or metric key (#103). - BREAKING — SysBench
ssrchanges meaning under an unchanged key. It is now the paper's mean normalised count of consecutive fully-satisfied turns from a session's start; the old reading reported only the final term and ran ~20 points low. Same key, different number — a consumer diffing an oldreport.jsonagainst a new one sees a silent 20-point jump, not a missing key. SysBench never shipped a run, so no published sieval number is invalidated (#103). - BREAKING (config format) — engine identity no longer selects the request dialect.
infer.backend: sglangno longer activates the native/generatebypass. Atype: genconfig that relied on the implicit native path must declaredialect: sglang_legacyexplicitly. Migration is guarded, not silent: the omitted-dialect case raises pre-I/O and names both options (#120). - BREAKING — the dialect request-audit contract is source-bound.
consumed(path, *wire_evidence)now requires evidence,PreparedRequest.consumed_paths/.passthroughare gone, andbodyis recursively frozen. Both shipped dialects were migrated; a third-party dialect implementingprepare()will not load unmigrated (#129). - BREAKING for a strict consumer of
ci95_units— two rules are now enforced at report-write time: every entry's value must be a population count (n_…), and two metrics sharing one interval must publish the same number within 0.005 points.metric_intervalalso raises on a non-countunitbefore it estimates anything, because the corrupted rate would otherwise reach disk presented as a percentage (#126). vendor/code-evaluatorgains four execution sources — C++ (liveoibench),agnostics,quotebench, and a declarative language table backingcpp/bash/perlfor MultiPL-E — plus its first stateful route (POST /shell-evaluations) and a newGET /languagesprobe, called atsetup()before any inference so an unsupported language cannot burn a full generation budget and reportpass@1 = 0. The three existing executors are untouched, so no existing task's grading moves.- CI's test step cut from 4m41 to 2m07 (#107).
Docs
- Recipe comments trimmed to what they have to carry (#136).