Skip to content

feat(v1)!: move run info from trace to episode - #2244

Merged
mikasenghaas merged 5 commits into
mainfrom
feat/episode-run-info
Aug 4, 2026
Merged

feat(v1)!: move run info from trace to episode#2244
mikasenghaas merged 5 commits into
mainfrom
feat/episode-run-info

Conversation

@mikasenghaas

@mikasenghaas mikasenghaas commented Aug 4, 2026

Copy link
Copy Markdown
Member

Summary

Trace.run recorded which run (eval or train) a trace belonged to. But the episode is what a consumer actually dispatches, and an episode that produced no traces — cancelled, or a task that raised before reaching the env — had nowhere to record its run at all.

So the run moves up:

  • Episode.run: RunInfo | None, consumer-stamped, on the unit that was dispatched.
  • Episode.record_run(run, **info) sets the run and passes any extra info down to each trace, so a consumer stamps once instead of walking them.
  • Trace.run and Trace.record_run are removed.

The field stays optional and unstamped by the library — verifiers doesn't own the notion of a run, consumers do. vf's own eval CLI now stamps at the episode level in all three places it used to loop over traces.

Breaking

  • Trace.run is gone — read Episode.run. Traces persisted with a run field still load (records parse non-strict), but the value is dropped.
  • Trace.record_run is gone — call Episode.record_run, which also forwards **info to the traces. A consumer holding only loose traces can set trace.info directly.
  • A consumer that writes traces rather than episodes to disk no longer gets the run recorded in those rows, and should stamp what it needs into trace.info.

Verification

  • uv run pytest tests/v1 -m "not e2e" green.
  • ruff check / ruff format --check; ty reports nothing on the touched files.

🤖 Generated with Claude Code

Note

Move run metadata from Trace to Episode in eval runner

  • Adds run: RunInfo | None and info: dict fields to Episode, with a record_run() method to set them, mirroring the API previously on Trace.
  • Updates run_eval and run_eval_server in runner.py to call episode.record_run() once per episode instead of stamping each trace individually.
  • Removes run field and record_run() method from Trace entirely.
  • Risk: Breaking change — Trace serialization no longer includes a run field; any consumers reading run metadata from traces will need to read it from the parent Episode instead.

Macroscope summarized 1336d48.


Note

Medium Risk
Schema and API break for anything reading Trace.run; persisted traces may drop the old run field on load, but eval output shape stays episode-based.

Overview
Breaking: Trace.run and Trace.record_run are removed. Consumers should use Episode.run and Episode.record_run, so trace-less episodes (cancelled or failed before agents run) can still record which eval/train run they belonged to.

Episode gains optional run, episode-level info, and record_run(run, **info) that sets the run and merges metadata on the episode once instead of on every trace.

The v1 eval runner stamps EvalRunInfo on the completed episode in all paths (local on_complete, env-server run_unit, and legacy run_group where each trace is wrapped with Episode.of then append_episode instead of per-trace append_trace).

Reviewed by Cursor Bugbot for commit 1336d48. Bugbot is set up for automated code reviews on this repo. Configure here.

mikasenghaas and others added 2 commits August 4, 2026 16:55
Trace.run says which run a trace belongs to, but the episode is the thing
that gets dispatched — and an episode that produced no traces has nowhere
to say it at all. Episode gains the same consumer-stamped RunInfo, plus a
record_run that stamps it and every trace it carries in one step, so the
two cannot drift.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Trace.run said which run a trace belonged to, but the episode is what a
consumer dispatches — and an episode that produced no traces had nowhere
to record it at all. The field and Trace.record_run move onto Episode,
whose record_run sets the run and passes any extra info down to the
traces, so a consumer stamps once instead of walking them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mikasenghaas mikasenghaas changed the title feat(v1): record the run on the episode, not only its traces feat(v1)!: the run belongs to the episode, not the trace Aug 4, 2026
Comment thread verifiers/v1/cli/eval/runner.py
mikasenghaas and others added 2 commits August 4, 2026 17:17
record_run's extra metadata described the episode but was being copied
onto each of its traces. It has a home now.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
append_trace wraps a trace in an episode of its own, so the row on disk
was not the record the caller got back: it carried no run, and a
different env. Mint once, stamp, persist that.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mikasenghaas
mikasenghaas requested a review from hallerite August 4, 2026 17:25
@mikasenghaas
mikasenghaas marked this pull request as ready for review August 4, 2026 17:25
@macroscopeapp

macroscopeapp Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This is an explicitly marked breaking change (!) that relocates the run field and record_run() method from Trace to Episode, modifying the data model. Breaking schema/API changes warrant human review to assess downstream compatibility.

You can customize Macroscope's approvability policy. Learn more.

@mikasenghaas mikasenghaas changed the title feat(v1)!: the run belongs to the episode, not the trace feat(v1)!: move run info from trace to episode Aug 4, 2026
@mikasenghaas
mikasenghaas merged commit f14b41c into main Aug 4, 2026
13 checks passed
mikasenghaas added a commit that referenced this pull request Aug 4, 2026
They were written when the run was a field on Trace. #2244 moved the
field to Episode; the types stayed behind, and Trace has not referred to
one since.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
mikasenghaas added a commit that referenced this pull request Aug 6, 2026
This reverts commit f14b41c.

Run identity returns to Trace.run / Trace.record_run. The episode-level
home turned out to push consumers that keep per-trace records into
episode reconstruction for no gain.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants