Repository navigation
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 forwarded and recorded (#153, #156).- User-visible dialect and capability errors describe current behavior instead of citing PR numbers (#146).
- Agent configuration is harness-neutral:
AGENTS.mdis the instruction source of truth with a generated rule map, and skills live under.agents/skills/(#144).
Deprecated
--resume-from,runner_config.auto_resume/resume_from, the matchingTaskRunnerConfigfields and theresume_from=argument map toresumeand warn once. An alias that disagrees withresumeis refused. Removed next release (#164).
Docs
- Contributor docs say bare
ty check, which also checkstests/, as CI does (#149).