Skip to content

Test the Gym and ATIF loaders on real data and fix what it exposed - #119

Merged
aleckhoury merged 5 commits into
trace-sessions/07-braintrustfrom
trace-sessions/08-gym-atif
Nov 2, 2026
Merged

aleckhoury merged 5 commits into
trace-sessions/07-braintrustfrom
trace-sessions/08-gym-atif

Conversation

@aleckhoury

Copy link
Copy Markdown
Contributor

Gym and ATIF have no session key, so they get no provider PR earlier in the stack; this PR adds their real-data tests and the loader fixes that data exposed.

Real-data tests

  • tests/test_real_gym.py: published example_rollouts.jsonl files from NVIDIA-NeMo/Gym 399e678 (tests/fixtures/real/gym_responses/): single tool call and multi-reward rollouts, plus the multi-turn gymnasium, aviary and graphwalks files used by the fixes below.
  • tests/test_real_atif.py: Harbor v0.24.0 ATIF trajectories (Apache-2.0, tests/fixtures/real/atif/): published Claude Code runs and Qwen Code output with embedded and nested subagents. The NOTICE Harbor entry now covers this directory too.

Loader fixes found on that data (one commit each; the bugs predate this stack)

  • Gym multi-turn rollouts load: user, system and developer messages that the gymnasium agent appends to response.output become user/system turns in order. Output that starts with a prompt-role message after non-empty input is still rejected as ambiguous.
  • Gym aviary rollouts (response.contains_transitions) load from their last transition; a transition that rewrites history is rejected.
  • Byte-identical Gym records load once; describe()["duplicate_record_count"] reports the repeats. The same rollout id with different bytes is still rejected.
  • An ATIF trajectory without trajectory_id is identified as atif-<sha256 of the line, 16 hex> instead of by its session_id, which ATIF v1.7+ allows to be shared by continuations and sibling runs. session_id stays on Trace.session_id.

Verified

ruff check, ruff format --check, ty check, the copyright-header check and pytest pass at every tip of this stack (#108–this PR); tests/test_codebase.py was skipped locally (needs ripgrep).

Stack position 8/8

@aleckhoury
aleckhoury added this pull request to stack #116 October 30, 2026 18:59
@aleckhoury
aleckhoury force-pushed the trace-sessions/08-gym-atif branch 2 times, most recently from 3565a9d to f626875 Compare November 2, 2026 21:38
@aleckhoury
aleckhoury force-pushed the trace-sessions/08-gym-atif branch 2 times, most recently from f767586 to 8281c69 Compare November 2, 2026 21:57
Published NeMo Gym example rollouts (NVIDIA-NeMo/Gym 399e678) and Harbor v0.24.0
ATIF trajectories (Apache-2.0): published Claude Code runs and Qwen Code output
with nested subagents.

Signed-off-by: Alec Khoury <akhoury@nvidia.com>
Gym's gymnasium agent appends each environment observation to
response.output as a role=user message before calling the model again
(responses_api_agents/gymnasium_agent/app.py, documented in its README),
and the tau2, simulated-user and stirrup agents do the same. The loader
rejected every such rollout: 10 of the example_rollouts.jsonl files
published at Gym 399e6783 failed. Prompt-role output messages now load in
order with unknown authorship. Output that starts with a prompt-role
message when the request has input stays rejected as ambiguous history.

Signed-off-by: Alec Khoury <akhoury@nvidia.com>
Gym's aviary agent (responses_api_agents/aviary_agent) sets
response.contains_transitions and records response.output as a list of
transitions, each the full model input after one environment step. The
loader expected output items and failed every published aviary file
(aviary, aviary_gsm8k, aviary_hotpotqa, aviary_bixbench at Gym 399e6783).
The last transition now loads as the conversation when each transition
extends the previous one; a transition that rewrites history (aviary's
collapse_old_env_states) is rejected.

Signed-off-by: Alec Khoury <akhoury@nvidia.com>
A record byte-identical to an earlier one repeats its response id (or
ng_trajectory rollout ID), so it is the same rollout recorded twice.
Gym publishes such files: graphwalks at 399e6783 has lines 4 and 5
identical (same response id, task and rollout index), and the
gymnasium example repeats one row 5 times. The content-hash identity made
the whole file fail as a duplicate trace id. The repeat now loads once and
GymTraceDescription.duplicate_record_count counts it, rather than becoming
a second trace that would double the rollout's evidence.

Signed-off-by: Alec Khoury <akhoury@nvidia.com>
ATIF-v1.7 (RFC 0001) makes session_id run-scoped: a trajectory, its
continuations and its siblings may share it, and trajectory_id is
optional on standalone trajectories. No Harbor root trajectory sets
trajectory_id, so the trace id fell back to session_id and two
spec-valid documents of one run failed the whole file as a duplicate
trace id (two real Harbor Qwen Code outputs sharing session-1, and
Harbor's golden linear-history continuation pair). A trajectory without
trajectory_id is now identified as "atif-" plus a SHA-256 prefix of its
line, like Gym records; session_id stays on Trace.session_id. A document
with neither id now loads instead of being rejected.

Signed-off-by: Alec Khoury <akhoury@nvidia.com>
@aleckhoury
aleckhoury force-pushed the trace-sessions/08-gym-atif branch from 8281c69 to 26faa39 Compare November 2, 2026 23:02
@aleckhoury
aleckhoury merged commit a78dc41 into main Nov 2, 2026
1 check passed
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