Releases: ssf0409/tracelens
Release list
v0.5.0
TraceLens 0.5.0 makes evaluation results comparable and explainable. Every run records provenance (task content hashes, grader and adapter identity, runner settings) so two runs are checked for compatibility before they are compared; tracelens compare gives a verdict between two saved runs with a paired task bootstrap; tracelens inspect explains failed trials from a trials file; tracelens run --config tracelens.yaml replaces long flag lists; every command shares one exit-code contract; and the pass-rate, pass@k, and pass^k estimators were tightened so harness failures leave the denominator and unevaluable gates no longer pass. Releases are now prepared and published by the release pipeline.
Added
- One-click release preparation. The "Release prepare" workflow takes a
version, validates it against the tags and the changelog, moves the
[Unreleased]entries into a dated section (scripts/prepare_release.py,
which refuses to release nothing), and opens arelease: vX.Y.Zpull
request with the rendered notes; merging it makes the "Release tag"
workflow tag the merge commit and run the release workflow with
publish=true. Nothing releases on an ordinary merge, and the manual
tag path still works. (#88) tracelens report --format ci. Re-renders the one-line CI summary
tracelens runprinted, gate line included, from a saved results file,
so a job summary or script can read it without parsing Markdown.report
never re-decides the gate: it exits 0. (#75)- Releases create their GitHub Release automatically. The release
workflow now runs three jobs: build and verify (tag matches the built
version; release notes rendered from the changelog's dated section by
scripts/release_notes.py, failing before anything is published when the
section is missing or empty), publish to PyPI (skip-existingso a
re-run of an already-published tag is safe), and create the GitHub
Release with those notes and the wheel and sdist attached, marked as a
pre-release for any non-final version. The release step updates an
existing release instead of failing, so re-runs after a partial failure
are safe, andworkflow_dispatchis a dry run that publishes nothing.
docs/releasing.mdgains the verification checklist and failure/re-run
guidance. (#54) - Positioning and contributor guidance aligned with what is actually
demonstrated. The README and docs home lead with what TraceLens is
(repo-owned local regression checks, inspectable artifacts, no backend,
explicit uncertainty) and carry a "What is demonstrated today" table that
separates the tested mechanism from the not-yet-published downstream
evidence; the adjacent-tools page acknowledges that hosted platforms also
run evaluations, experiments, and CI checks and names no vendor features;
fingerprint explanations no longer claim exact reproducibility or causal
attribution (DecisionSpecdocstrings included);CONTRIBUTING.md
describes the current extras ([datasets],[docs], PyYAML in core),
themake verifygate, where things live, and three small first issues
(#74, #75, #76). (#53) - The documented user journey runs in CI from a built wheel.
tests/journey/test_user_journey.pydrives realtracelensprocesses
through the documented workflow in a scratch project (an existing
project,init,run --config, baselines from the README snippet, the
gate enabled intracelens.yaml, an intentional regression that blocks,
inspect,compare, a--task-idrerun, an infra outage and a grader
crash made unevaluable and told apart, malformed input and a bad config,
checkpoint/resume re-executing nothing,report,sample), checking
exit codes and persisted decisions at every step. A new CI job installs
a freshly built wheel into a clean environment and runs the journey
against its console script (TRACELENS_CLI). (#33, Stage A) tracelens inspect: explain failed trials from a trials file.
tracelens inspect eval/results/trials.json --failuresprints, per
failing trial, one kind (agent failure, infra error, or grader crash,
never conflated, harness causes first), status and attempts, expected
versus actual output (--eval-setjoins the task's name, input, and
declared expectation), every grader's verdict, score, metrics, and
feedback, and the transcript's steps, tokens, tool calls, and errors.
Absent fields readmissing; output is bounded (400 characters per
field, 20 steps per transcript) with an explicit count of what was
omitted, and--fulllifts the bounds. Filters:--kind agent|infra| grader|not-run|passed,--task-id,--grader(trials that grader
failed or crashed on),--all,--limit.--htmlwrites a
self-contained, escaped, offline drilldown that reads on a phone;
--jsonwrites the same view as data. The command exits 0 whenever the
file was read (it reports, the gate decides) and 2 on input errors.
tracelens run --task-id ID ...(run.task_idsintracelens.yaml)
reruns only the named tasks and refuses unknown ids; its provenance and
checkpoint identity cover the subset. New guide: "Debugging a Failed
Evaluation". (#52)tracelens compare: a verdict between two saved runs.
tracelens compare baseline-trials.json candidate-trials.json(and
compare_runs()in Python) implements the statistical contract's
run-versus-run section: tasks are aligned by content through the runs'
provenance (changed, added, or removed tasks and different graders make
the runs incompatible;--unmatched-tasks excludecompares the shared
tasks and lists the rest; artifacts without provenance align by id and
are labelled, or refused with--require-provenance), one statistic per
task and run is paired (--metric pass_rate | mean_score | <grader_id>.<metric_name>,--direction lowerfor latency-like metrics,
--graderfor multi-grader runs), and the mean paired difference gets a
percentile bootstrap over tasks, a sign-flip p-value (exact for small
suites), and a verdict against--threshold: improvement, equivalent
within the threshold, or significant but below it exit 0; regression
exits 1; inconclusive or insufficient evidence exits 2 (--observe
forces 0). The terminal summary ("what changed" from theDecisionSpec
diff next to "what moved" per task) and--output compare.jsonshare
every field, and the same inputs and--seedreproduce the record
exactly.examples/version_compare.pynow uses it. (#28)- Versioned run provenance and comparison compatibility. Every
EvaluationRunner.run()records aRunProvenanceon the batch
(batch.provenance;provenancein--outputand--save-trialsJSON;
a "Run Provenance" section in Markdown and HTML): ameasurementside
(eval-set and per-task SHA-256 content hashes, grader identities with an
optional declaredprovenance_version, runner settings) and a
candidateside (adapter identity,DecisionSpecfingerprint and spec).
check_compatibility(a, b)returns aCompatibilityReportthat is
compatible,incompatible(changed, added, or removed task content;
different graders), orunknown(no provenance on a side), with runner
and version differences as notes and candidate differences reported
separately with aDecisionSpecdiff. Baselines gaintask_hash
(TaskBaseline,update_baseline(task_hash=),promote(task_hash=);
results carrytask_summaries[].task_hash), and the CLI gate refuses to
compare a task whose content changed since its baseline was stored
(outcometask_content_changed, gate unevaluable, exit 2) instead of
matching on id; baselines without a hash still compare, with a warning.
Checkpoint identity now derives from the same hashing rule (values
unchanged). Artifacts written before this release load with
provenance=None; an unknownschema_versionis rejected clearly. The
tracelens initREADME snippet storestask_hashon each baseline. (#51) tracelens run --config tracelens.yaml. A project-owned run
configuration file holds exactly what therunflags hold (eval set,
adapter and graders, run counts, outputs, and the baseline gate).
Precedence is built-in defaults, then the file, then flags given
explicitly, so an omitted flag never resets a file value, and booleans
override in both directions (--progress/--no-progress,
--baseline-check/--no-baseline-check,--require-baselines/
--no-require-baselines). Paths in the file resolve relative to the
file; adapters and graders import fromrun.import_root(default: the
file's directory) so the command works from any directory; and the file
is parsed strictly with the safe YAML loader, so unknown keys, duplicate
keys, wrong types, unsafe constructs, and missing required settings exit
2 before any agent call.tracelens initnow writestracelens.yaml,
and the generated README and workflow run the same
tracelens run --config tracelens.yaml, so enabling the regression gate
is one edit to the config file. (#35)- Actionable CLI errors and discoverable outputs.
tracelens --debug(or
TRACELENS_DEBUG=1) adds the full traceback to input and configuration
errors, which are otherwise one or two lines on stderr with the next
action; an unimportable adapter or grader now explains the dotted-path
and project-root requirement.tracelens runvalidates--num-runs,
--max-concurrency,--timeout, and--max-infra-retriesbefore doing
anything, and lists every artifact it wrote on stderr
([tracelens] wrote results: ...) while stdout carries only the summary.
(#48) tracelens runaccepts JSONL and CSV eval sets.--eval-setpicks
the loader from the file suffix (.json,.jsonl,.csv); a directory
needs--eval-set-format json|jsonl|csv.--input-fieldand
--metadata-fieldsmap foreign JSONL/...
v0.4.0
[0.4.0] - 2026-07-19
Reliability and data-portability release: CI gates now distinguish agent
regressions from harness noise, long runs retry and resume safely, and new
project scaffolding plus JSONL, CSV, and optional Hugging Face loaders shorten
the path from local data to a reproducible evaluation.
Added
tracelens init. New CLI command that scaffolds a runnable starter
eval/suite, including tasks, adapter, grader, README, and a GitHub Actions
workflow. The command refuses to overwrite generated files unless--force
is provided.- Loud CI gate. The baseline check now always prints a gate summary
(N checked, M skipped (no baseline), K blocking regression(s)), warns
per task when a baseline is missing, and--require-baselinesturns
missing baselines into a hard failure. - Configurable infra classification.
RunnerConfig.infra_exception_types
(CLI:--infra-exceptions) extends which exception types are classified
INFRA_ERRORinstead ofFAILED. The default set
(DEFAULT_INFRA_EXCEPTION_TYPES) stays conservative:InfraError,
MemoryError,ConnectionError. - Noise-aware gating from the CLI.
TaskBaseline.decision_specstores
the full spec alongside the fingerprint,--decision-specloads the
current run's spec (adapter-stamped transcripts work too), and the
baseline check now runscompare_with_specs()— so sub-noise-band
regressions under a mismatched infra config are flagged but not
blocking, with the infra diff printed.--noise-bandtunes the band. - DecisionSpec write path.
update_baseline,
create_capability_baseline,create_canary_baseline,promote,
try_promote, andforce_promoteall accept adecision_spec;
creation derives the fingerprint from it when one isn't passed, and
promotion refreshes the stored spec (archiving the old one in
previous_versions) so it can't drift from the fingerprint. DEFAULT_INFRA_EXCEPTION_TYPESis exported top-level (from tracelens import DEFAULT_INFRA_EXCEPTION_TYPES), matching the
documented+ (OSError,)extension pattern.- Infra-error retry.
RunnerConfig.max_infra_retriesre-attempts trials
that endINFRA_ERROR, with exponential backoff
(infra_retry_backoff_seconds).FAILEDandTIMEOUTtrials never retry —
those are observations about the agent, and retrying them would launder
flakiness out of the pass rate. The final trial records its attempt count in
Trial.attempts, and retried-away error messages are kept in
Trial.metadata["infra_retry_errors"]. CLI:--max-infra-retries. - Checkpoint run identity. Checkpoint files now carry a versioned envelope
with the eval-set content hash, adapter/grader class identity, and the
run-levelDecisionSpecfingerprint when one is set (class paths alone
cannot distinguish two configs of the same adapter class). Resuming
against a checkpoint written by a different eval set, adapter, grader
stack, or decision spec raisesCheckpointError(exported from
tracelens) instead of silently merging foreign trials keyed only on
(task_id, run_index). Envelopes with an unknown format version or a
missing identity are rejected as corrupt. Note: resume requires stable
explicittask_ids — auto-generated ids change every process.
Pre-0.4 bare-batch checkpoints still load, with a loud warning that their
identity can't be verified. - JSONL and CSV task loaders.
JSONLTaskLoaderandCSVTaskLoader
(top-level exports) load eval sets from.jsonl/.csvfiles or
directories and save them back, with JSON-compatible round-trips (CSV
serialises structured Task fields and one canonical metadata column as JSON) and
no JSON coercion of free-text Task fields. Missing or ambiguous inputs,
malformed CSV structure, and mixed canonical/flat metadata representations
fail loudly. The optionalHFDatasetLoaderloads explicit Hub splits, supports
revision pinning, and round-trips local saved datasets through the same mapping
contract without adding a core dependency. Derived from #31 by @Balaji1304.
Docs:docs/task-sources.md.
Changed
- Gate misconfiguration is now an error.
tracelens run --baseline-checkwithout--baselines-file, or with a nonexistent or
unparseable baselines file, exits 2 before the eval runs instead of
silently skipping the entire regression check (the file is fully
loaded during preflight, so a corrupt file can no longer burn a full
eval before crashing).--require-baselinesor--noise-bandwithout
--baseline-checkis also an exit-2 usage error;--baselines-file
alone warns that it has no effect. - Harness failures no longer masquerade as agent regressions in the
gate. The baseline check excludesINFRA_ERRORand grader-crash
trials from the per-trial comparison samples (they remain visible via
infra_error_rate/grader_error_rate, a per-task exclusion note,
and askipped (no gradable trials)count when nothing gradable
remains).TIMEOUTtrials still count against the agent. - Adapter-raised
TimeoutErroris no longer reported as a budget
timeout. Only the runner's ownasyncio.wait_forbudget produces
TrialStatus.TIMEOUT; aTimeoutErrorfrom inside the adapter (e.g.
socket.timeout) now classifies throughinfra_exception_types
(FAILEDby default, infra if configured) and keeps its original
message. - Noise-downgraded reports are internally consistent.
compare_with_specs()now recomputesoverall_severityfrom the
blocking regressions and appends a noise-band note to the summary, so
a noise-only report no longer readsSEVEREwhile
should_block_ci()returns False.should_block_ci(..., ignore_noise_band=False)still counts every regression. - No more fabricated blocking on underpowered zero-variance samples.
A consistent drop that a valid z-test cannot call significant (e.g.
five identical scores half a baseline standard deviation below the
mean) no longer blocks CI — previously it always blocked via the
fabricated p=0.0. Decisive drops still block; degenerate cases with no
valid test still block on thresholds withinsufficient_data=True. - No fabricated significance on degenerate samples.
MetricRegression.p_valueisNone(not0.0) when no valid test
exists — n=1 withbaseline_std=0, or zero variance on both sides. Such
regressions are still reported and can still block CI, with severity
from the delta thresholds and an explicitinsufficient_dataflag.
Zero-variance samples against a known baseline spread now get a real
z-test. - Checkpoint resume re-runs infra-errored trials. Resume previously
skipped every finished trial, permanently freezingINFRA_ERRORresults
into the batch. A rerun with the same checkpoint path now re-executes
infra-errored trials andSKIPPEDplaceholders (TIMEOUTtrials stay
skipped — a timeout is an observation about the agent). The checkpoint file format changed to the
identity envelope described above; old files remain readable.
Fixed
InfraErrordocstring matched to behavior. It previously claimed
OSErrorand networkTimeoutErrorwere classified as infra; they never
were. The docstring now describes the real (configurable) set and that
the runner's own budget timeout is alwaysTIMEOUT.compare_to_baseline_summaryno longer crashes at n=1. The
Welch-Satterthwaite degrees of freedom fell back to a division by zero
when either side had a single sample.- Corrupt checkpoint files fail clearly. An unreadable or unparseable
checkpoint now raisesCheckpointErrorwith the offending path and a
recovery hint (the CLI prints the error and exits 2 — the misconfigured-run contract) instead of an
unhandledJSONDecodeError. RunnerConfig.fail_fastis honored. The field was previously accepted
and silently ignored. When enabled, the first trial whose execution fails —
final statusFAILED,INFRA_ERROR(aftermax_infra_retriesis
exhausted), orTIMEOUT— stops new work from being scheduled. In-flight
trials still run to completion; unstarted work items produce no trials at
all, so pass rates, the baseline gate, and checkpoints only ever see
trials that actually executed (a resume naturally runs the remainder).
Trials that execute but fail grading, and teardown errors on otherwise
successful trials, do not trip it. The runner logs how many work items
were left unrun.
Removed
Task.max_retries. Dead configuration — the runner never read it.
Retry policy is an execution concern and lives in
RunnerConfig.max_infra_retries. Eval-set JSON containing the old field
still loads; the value is ignored.
v0.3.0
[0.3.0] - 2026-06-10
Hardening release: the grading path now honors its own configuration, harness
failures are first-class signals, and long evaluations survive crashes.
Added
- Grader-crash tracking.
Outcome.grader_errormarks outcomes synthesized
from grader crashes;Trial.has_grader_errorand
TrialBatch.grader_error_count/grader_error_rateaggregate them, and
reports carry the counts next to the existing infra-error stats. A spike
here means the grading harness broke — not that the agent regressed. - Checkpoint/resume.
RunnerConfig.checkpoint_pathand
checkpoint_intervalpersist the batch atomically during long runs;
re-running with the same path resumes, skipping completed trials. CLI:
--checkpoint. - Progress reporting.
RunnerConfig.progress_callbackis called with
(completed, total)after each trial. CLI:--progressprints per-trial
progress to stderr. - DecisionSpec wiring.
EvaluationRunner(decision_spec=...)stamps the
spec onto every transcript that doesn't already carry one, so baselines
record the reproducibility fingerprint of the run that produced them. - Token usage roll-up.
TrialBatch.total_input_tokens/
total_output_tokens/total_tokens, mirrored onReportData, for cost
visibility without walking every transcript. - Quality infrastructure. CLI end-to-end integration tests, a
Makefile
with a singlemake verifygate (lock check → lint → typecheck → tests +
coverage), and a 90% coverage floor enforced in CI.
Fixed
LLMGraderhonorsGraderConfig. Each grading attempt is bounded by
timeout_seconds, and transient failures — including malformed responses,
which a fresh LLM call often fixes — retry perretry_on_error/
max_retrieswith exponential backoff (newretry_backoff_secondsknob).
These fields were previously accepted and silently ignored; a hung provider
stalled the whole eval indefinitely.MemoryErrorfrom graders propagates (kill-switch) instead of being
converted into bogus 0-score outcomes for the rest of the run.- CLI
--baseline-checkstatistics. The regression detector now receives
one metric sample per trial instead of a single pre-aggregated dict,
restoring the intended t-test over the sample distribution.
Changed
- Generalized maintainer guidance and public docs for the open source library:
removed private downstream project references, refreshed CI examples for the
current CLI, and updated package constraints to the latest PyPI release
(0.2.0).
v0.2.0
First feature release since the docs-only v0.1.1. Published to PyPI: pip install tracelens==0.2.0.
Highlights
- Human-eval calibration loop —
tracelens sampleselects trials for human review (diverse / boundary / failures / random) and emits a self-contained worksheet;tracelens reconcile(alias ofcalibrate) pairs grader vs. human per row (carriestrial_id, so no separate results file and multi-run trials stay distinct). Backed bysample_for_review()+CalibrationAnalyzer.analyze_worksheet(). - Infra-noise differentiator —
DecisionSpec.InfraConfig,TrialStatus.INFRA_ERROR+InfraError,RegressionDetector.compare_with_specs()(3pp noise band), infra metrics in reports, and a flagship benchmark pack reproducing Anthropic's infra-noise finding. - Adapters / graders / examples —
HTTPAPIAdapter, contract graders, and four runnable examples includinghuman_eval_calibration.py. - Onboarding docs — human-eval guide, baseline-regression tutorial, evaluation-recipes.
Breaking (0.x)
- Removed
WorkflowTask/WorkflowRunner/WorkflowAdapterandLiteLLMProvider;create_provider()supports only"in-memory"(subclassLLMProviderfor real vendors).
Full notes: CHANGELOG.md