Stored Results, Run Directories, and Repair¶
Karenina provides public workflows for loading completed result exports, organizing new runs, evaluating saved responses, and repairing selected rows. These APIs keep analysis code on the same validated pipeline used during normal verification.
Load stored results¶
Use ResultsIOManager as the default loader for Karenina result exports:
from pathlib import Path
from karenina.benchmark import ResultsIOManager
rows = ResultsIOManager.iter_from_json(Path("results.json"))
for result in rows:
print(result.metadata.question_id, result.metadata.failure)
iter_from_json() validates each row as a VerificationResult and streams
large exports without loading the complete file. Its raw=True option is a
low-level migration and recovery facility. Normal analysis code should use the
validated default.
Scenario exports should be loaded as a complete result set so their compact execution records and run metadata remain available:
result_set = ResultsIOManager.load_result_set_from_json(Path("scenario_results.json"))
scenarios = result_set.get_scenario_results()
scenario_df = scenarios.to_dataframe()
turn_df = scenarios.to_turn_dataframe()
outcome_df = scenarios.to_outcome_dataframe()
This is the standard stored-scenario path. It validates flat results and scenario records together instead of requiring application code to parse the JSON wrapper.
Use karenina.benchmark.format_trace_messages when a post-hoc analysis needs
to format all or part of a stored template.trace_messages list. The public
helper retains assistant text, tool calls, and tool results in Karenina's
canonical trace format.
To evaluate a new rubric over saved responses, use the public TaskEval-backed facade:
from karenina.benchmark import evaluate_rubric_on_results
judgments = evaluate_rubric_on_results(
ResultsIOManager.iter_from_json(Path("results.json")),
rubric,
parsing_model,
)
This path does not regenerate answers. Model-backed rubric traits still call their configured judge.
Timestamped run directories¶
The CLI can create a standard run directory automatically:
karenina verify benchmark.jsonld \
--preset comparison.json \
--run-root runs \
--run-label otp_parametric
The directory name contains a UTC timestamp. It contains results.json,
run_manifest.json, traces/, and workspaces/. The manifest records model
identities, the benchmark source, selected question count, configuration,
paths, timestamps, and lifecycle status. Credential fields are masked.
Python callers can use create_run_directory() or
managed_run_directory() from karenina.benchmark. The managed context marks
the manifest completed, interrupted, or failed when the context exits. Pass
resume=True with the same label and creation timestamp to reopen an existing
directory explicitly. Accidental reuse raises FileExistsError.
Repair selected rows¶
karenina repair loads a completed JSON export with ResultsIOManager, selects
exact row identities, reruns them through the ordinary benchmark pipeline, and
splices only those replacements into the export.
Start with a dry run:
karenina repair results.json \
--benchmark benchmark.jsonld \
--preset comparison.json \
--failure-group retry \
--dry-run
Then run the repair:
karenina repair results.json \
--benchmark benchmark.jsonld \
--preset comparison.json \
--failure-group retry \
--mode replay
Replay mode reuses the selected answer traces and reruns downstream parsing and verification. It uses strict replay, so a missing trace raises instead of silently calling an answerer. Live mode regenerates the selected answers.
An in-place repair writes a timestamped backup before replacing the export and
writes a JSON provenance sidecar containing the source checksum and replaced
row identities. At least one filter is required unless --all is explicit.