feat: stream served episodes turn by turn - #2512
Conversation
Evaluation lives in prime-rl (`uv run evals`): multi-env, adaptive concurrency, cursor checkpoints, dashboard and platform upload. Keeping a second single-env `eval` CLI here only confused which one to use, so it goes: the entrypoint, its rich live view, traces.jsonl resume, platform push, EvalConfig and the root configs/*.toml, plus the evaluation doc and skill. RunConfig and default_run_name move to configs/cli/run.py for validate and gepa. output.py types its run directory through a small protocol. The platform module keeps the sample format and credentials prime-rl's monitors use. The e2e suite runs envs through a test-local runner (tests/v1/runner.py) covering the in-process and env-server paths. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`uv run eval` replaces `uv run evals` so verifiers users keep their command; the sidecar is `online-eval`. Modules, configs (EvalConfig, OnlineEvalConfig, SFTEvalConfig; the orchestrator's interval block is ScheduledEvalConfig), log files and resolved-config names follow. examples/eval/ gains TOMLs for the CLI usage verifiers used to document (best-of-n, wiki-search, terminal-bench-2 with retries, rlm in docker with sampling) and a README. A GPU integration test runs `uv run eval` against a local vLLM server from configs/ci/integration. The verifiers submodule points at the branch that removes its `eval` console script, so the shared venv has one `eval`; re-pin to main once PrimeIntellect-ai/verifiers#2512 lands. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
prime-rl owns the upload path (its train and eval monitors), so the sample format and credentials move there too. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…dy created (#2569) ## Summary A hosted evaluation creates its evaluation record before the sandbox exists and hands the sandbox that id as `$EVALUATION_ID`. Until now the sandbox's `uv run eval` opened a run of its own through prime-runs, so a hosted v1 eval would produce a second, unlinked evaluation while the platform's record sat at running. This adds the one knob the platform needs to run the same command a researcher runs locally. - **`run.attach <evaluation-id>`** on `EvalConfig`: `open_run` passes it to `prime_runs.init(id=...)`. prime-runs 0.1.2 (PrimeIntellect-ai/prime#913, released) attaches eval runs the way it already attached training runs: no create, sinks keyed to that id, `/finalize` on a clean finish, failure marking left to the launcher (the platform reads the sandbox exit code), and the launcher's `metadata` document left alone. Requires `push`, validated on the config. - **No local fallback when attaching.** Without `run.attach` the behaviour is unchanged: a run that cannot be opened is logged and the eval continues locally. With it, a failed attach or the SDK's `PRIME_RUNS_MODE=disabled` kill switch raises: a local run nobody reads is not a substitute while the launcher's run waits until it times out. - Docs bullet under "Common config values", `prime-runs>=0.1.2` and the relock (the lock diff is the one package). Nothing changes for local runs; `run.attach` is unset unless a launcher sets it. ## Verified against prod With this branch and prime-runs from `main` (== 0.1.2): an evaluation created launcher-style through the evals API (`metadata={"launcher": "hosted-smoke"}`), then ``` eval alphabet-sort -n 1 -r 1 --no-serve --no-rich --run.attach <that id> ``` exited 0 with `--push: completed -> .../evaluations/<that id>`. Afterwards the evaluation had `total_samples` 1, the run's metrics (`avg_reward`, `avg_metrics.alphabet_sort`, `avg_error`), its original metadata byte for byte, and status PROCESSING; no second evaluation was created. The same command without `--run.attach` still creates its own run as before (checked earlier on the SDK side). Smoke evaluations deleted. ## Test plan - New `tests/v1/test_platform_run.py` (mocked `pr.init`): attach needs push; no attach → `id=None` and the created run's id is assigned; attach → `id=<attach>` and the config carries that id; failed attach raises; failed open without attach still falls back to a local run; kill switch refuses an attach. - `tests/v1/test_configs.py` still parses every checked-in config. ruff check + format clean. ## Follow-up (not here) `EvalsBackend.attach` makes no request, so a wrong id only surfaces on the first upload (404 in the run's footer) and the eval still exits 0. For hosted evals the id is always the platform's own; the platform's v1 runner will check `total_samples` on exit rather than trusting the exit code alone. Relates to #2512 (if the `eval` console script moves, the hosted runner's command moves with it). Linear: ENG-5781. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01XrcqANSZ24BALuWS9MciYv <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes platform run lifecycle for hosted evals (hard failures on attach); local-only evals are unchanged when `run.attach` is unset. > > **Overview** > Adds **`run.attach <evaluation-id>`** so hosted sandboxes can upload into an evaluation the launcher already created instead of opening a second run. `open_run` passes that id to **`prime_runs.init(id=...)`** (bump to **0.1.2**); the config gets the same id for traces and the run dir. > > **Attach is strict:** it requires **`push`**, rejects **`PRIME_RUNS_MODE=disabled`**, and **does not fall back** to a local run on attach failure—unlike a normal push open, which still continues locally. Docs cover **`push`** and **`run.attach`** under common eval config. > > New **`tests/v1/test_platform_run.py`** mocks `pr.init` for attach validation, success paths, fallback without attach, and kill-switch behavior. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 2a989a8. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- Macroscope's pull request summary starts here --> <!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. --> <!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. --> > [!NOTE] > ### Add `run.attach` to stream hosted evals into existing platform runs in v1 > - `RunConfig.attach` identifies an existing platform run to attach a hosted sandbox evaluation to. The `attach_needs_push` validator rejects configurations that set `run.attach` with push disabled. > - [platform.py](https://github.com/PrimeIntellect-ai/verifiers/pull/2569/files#diff-8644072f827be448db5b0010e0969c6c86d9bbf07191ca00a993f416d123235f) `open_run` passes the attach id to online SDK initialization. Attached evaluations fail with a runtime error if attachment cannot be performed, instead of falling back to a disabled local run. Unattached runs keep the existing fallback behavior. > - The SDK kill switch rejects attach requests before initialization, preventing a silent conversion to a local run. > - Raises the minimum `prime-runs` dependency from 0.1.1 to 0.1.2. > - Risk: `open_run` now raises an attachment-specific runtime error on SDK failures for attached runs (no local fallback); reviewers should verify callers in [platform.py](https://github.com/PrimeIntellect-ai/verifiers/pull/2569/files#diff-8644072f827be448db5b0010e0969c6c86d9bbf07191ca00a993f416d123235f) handle this error path. > > <!-- Macroscope's review summary starts here --> > > <sup><a href="https://app.macroscope.com">Macroscope</a> summarized 2a989a8.</sup> > <!-- Macroscope's review summary ends here --> > <!-- Macroscope's pull request summary ends here --> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Main moved the eval CLI's platform upload onto prime-runs (#2415, #2569, #2577) and taught the runner `run.attach`. All of that lives in files this branch deletes, so the merge keeps the deletions and drops the new `tests/v1/test_platform_run.py` with them. Nothing in verifiers imports `prime_runs` any more, so the dependency goes too; prime-rl depends on it directly. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A served rollout was visible only as its final episode; the env-serve wire now streams each trace as it changes. The rollout fires Trace.notify at every phase change and the interception proxy after every recorded turn; the worker's DeltaStreamer diffs the live traces against what it already sent and ships the new part (header once, appended nodes/calls/errors, links onto earlier nodes, changed scalars). The reply that ends a run carries the episode head and per-trace counts, and the client assembles the episode from the deltas, so the stream costs about what the one-shot reply did. Frames gain a kind (`delta` | `reply`); the pool relays deltas without closing the request. EnvClient.run takes on_update to watch the assembly grow. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A consumer that persists the stream needs the delta itself, not only the assembly it produced. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
One primitive for a served rollout's progress: the delta. The client still assembles the episode it returns from the same deltas. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`reasoning_details` items (`reasoning.text`, `reasoning.summary`, `reasoning.encrypted`) were hashed as raw provider state, so a harness that replays them through its own SDK, which concatenates the streamed `format` field per chunk, never matched the committed assistant node and forked a branch every turn. Their text is already the reasoning content; only the fields required on replay (an encrypted blob, a signature) count. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The eval CLI is gone, so the per-taskset smoke test shells out to nothing; it now runs each taskset in-process through the shared runner (one capped rollout, the taskset's own harness). The e2e config builder drops its stale platform-push kwarg. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A tool result reaches the framework inside the harness's next model request and its node only lands when that turn commits, after the model has answered, so a watcher saw it a whole model call late. The interception server now hands the request's uncommitted tail to the trace as a preview; the delta stream ships it as pending, the assembly keeps it until the turn's nodes land, and the finished record never carries it.
A send that failed was logged and its delta forgotten, so the client tripped over the count check at the end of an otherwise good run; a flush scheduled at the last notify could also start after the streamer had exited. Each trace's delta now carries the cursor it would leave behind, stored only after the send succeeds, and the exit cancels the pending schedule and lets in-flight flushes finish before the final one. The client's receive loop logs and skips a malformed frame or a raising delta handler instead of dying and hanging every request. Trace.clear_preview replaces poking the private field from graph.py.
prime-rl's `uv run eval` replaces it: the `eval` console script, its runner, resume, rich dashboard, platform upload and example configs go, along with the `prime-runs` dependency. `RunConfig` moves to `configs/cli/run.py` for the run-directory CLIs that stay (validate, gepa), and the e2e suite runs tasksets in-process.
Main fixed the cause in the bash harness's streaming path (#2604), so replayed reasoning details match verbatim and the hash needs no special case; the regression test for the mangled form goes with it.
hallerite
left a comment
There was a problem hiding this comment.
The streaming approach looks useful. I found one mutation issue at the boundary between the client assembly and consumers that buffer deltas, described inline.
The scaffold installs only verifiers, which has no eval executable since the eval CLI moved to prime-rl. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The assembly kept the node dicts of the delta itself, so a later links delta grew semantic_parents inside a delta the caller already held. A consumer that serializes deltas after the fact (prime-rl's buffered live writer) then saw the link twice: once in the node, once as the link update. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The CLI's removal moves to its own PR for a transition period; this branch carries only the streamed traces. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Serving an env to many consumers is prime-rl's job: its eval runs env servers and consumes their delta stream. The CLI keeps the quick local path, so it never assembles deltas. The env-server test fixture drives a worker pool through EnvClient directly. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Both packages install an `eval` script and whichever is installed last wins, so in a prime-rl workspace the verifiers entry hands over to prime-rl's entrypoint. Standalone, the TUI footer and the console log recommend prime-rl's eval: streamed traces, a live dashboard, multi-env runs and env servers. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This PR adds turn-by-turn episode streaming with a new delta wire protocol and client-side assembly, while also changing the eval CLI from server-backed execution to in-process execution. The resulting changes span shared serving, trace, rollout, interception, retry, serialization, and dashboard paths, creating a broad runtime and compatibility surface. You can add or adjust custom eligibility rules. Learn more. |
prime-rl's eval owns the `eval` script; two packages installing the same script leave the winner to install order, and the verifiers entry should not look for prime-rl. The CLI keeps working under `vf-eval` for the transition. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`vf-eval`, `vf-validate`, `vf-debug`, `vf-replay`, `vf-init`, `vf-gepa`: generic names collide with the scripts of a workspace that installs verifiers as a dependency (prime-rl's `eval`), and the winner is whichever package was installed last. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Parallel agents share one trace, so a single preview list let one request's preview overwrite another's and any commit clear them all. Each request now previews under its own key; a commit clears only its own, and a request that fails or is cancelled before committing takes its preview back before the failure is recorded. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 55500a3. Configure here.
A PendingTurn is a dataclass and not hashable. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
hallerite
left a comment
There was a problem hiding this comment.
Thanks for fixing the delta aliasing issue; the node/link copying addresses the earlier finding, and the 99 non-live verifiers tests passed locally. One remaining compatibility issue: holding the CLI-removal PR does not by itself preserve hosted evals, because this PR renames the executable they invoke.
## Summary Migrates the eval CLI from verifiers into the prime-rl ecosystem: `uv run eval` is prime-rl's entrypoint for evaluating any model on any environment, standalone or as the online evals of a training run. Why: - consolidation of features: adaptive concurrency, the local dashboard, resume from the trace stream, live rollouts - easier code sharing between the CLI entrypoints (`rl`, `sft`, `eval`) - direct access to the pre-installed environments (`prime-envs` submodule) - one workspace for post-training: training and evals Important: - the verifiers eval CLI stays for a transition period as the quick in-process path, renamed `uv run vf-eval` so prime-rl owns `eval` (PrimeIntellect-ai/verifiers#2610 removes it later); env servers and their streamed traces (PrimeIntellect-ai/verifiers#2512, merged; the submodule points at verifiers `main`) are consumed here only - evals run through env servers, for scalability; the launcher (`eval`, `sft`, `rl`) owns them - `--resume` continues an interrupted run from its trace stream: landed episodes rejoin the epoch, only the owed rollouts run; `num_examples`/`group_size` may change, the model, sampling and env config may not - multi-env capable (`[[source]]` blocks); the single-env command shorthands are preserved - adaptive concurrency only against local deployments (it reads vLLM `/metrics`); against an API, concurrency is pinned via `min_inflight = max_inflight` (the default pins 128) - prime-rl's core dependencies are plain CPU; install them and the environments with `uv sync --all-packages` - Prime runs and traces integrate through the single monitor abstraction (`--monitors.prime`, `--monitors.wandb`, the file monitor) Examples: ```bash uv run eval gsm8k # default model on Prime Inference uv run eval gsm8k -n 32 -r 4 -m openai/gpt-5.6-luna # 32 tasks × 4 rollouts, another model uv run eval terminal-bench-2 --env.taskset.tasks '["fix-git"]' --env.agent.harness.id bash -n 1 -r 2 uv run eval @ configs/debug/eval/single-turn.toml # gsm8k, null harness uv run eval @ configs/debug/eval/multi-turn.toml # 16 terminal-bench-2 tasks, bash harness uv run eval @ configs/debug/eval/multi-env.toml # terminal-bench-2 under bash and rlm side by side uv run eval @ configs/debug/eval/aime2026.toml # AIME 2026, avg@16 uv run eval @ configs/debug/eval/tb2.toml # Terminal-Bench 2, avg@4 uv run eval @ configs/debug/eval/resume.toml --run.name x # then: --resume uv run eval gsm8k --monitors.prime # stream the evaluation to the platform ``` ## Breaking - `uv run evals` is `uv run eval` (`EvalsConfig` → `EvalConfig`); config shape: `[eval.client]` → `[client]`, `[eval.concurrency]` → `[concurrency]`, `[[eval.source]]` → `[[source]]`, `eval.num_examples`/`eval.group_size` → top level. `[online]` is gone: online evals are spawned by `sft`. - `eval` has no `[ckpt]` block; `--resume` is a switch that reads the run's trace stream. - SFT online evals: no public entrypoint (`uv run sft` with an `[eval]` block spawns it); `logs/attempt_N/evals.log` → `eval.log`, `evals.json` → `eval.json`, W&B label `online-eval`; `EvalsEvalConfig` → `SFTOnlineEvalConfig`. - `ratio` is accepted on training sources only, `interval` on online eval sources only; a standalone eval's `[[source]]` takes neither. - `orchestrator.env_server_base_port` and the eval entrypoint's `env_server_base_port` are removed: launcher-managed env servers bind an OS-assigned port and publish it (`configs/attempt_N/resolved/envs/<split>/<name>.address`); `serve.address` pins one. `uv run env-server` without `serve.address` binds an OS-assigned port (`address_file` publishes it). - `configs/evals/swe.toml` is removed (`uv run eval swebench-verified --env.agent.harness.id bash`). ## Verification - Unit: `uv run pytest tests/unit` green (configs, orchestrator, eval, monitors incl. the live reader). - Debug configs: single-turn, multi-turn, multi-env and aime2026 run to completion against Prime Inference. Resume: single-env and multi-env runs interrupted with SIGTERM and resumed hold exactly examples × group_size unique episodes with the plan and epoch metrics over the full set; resuming with a larger `group_size` runs only the extra rollouts; resuming with another model is refused. - Core install (`uv sync` without extras) runs `uv run eval`; an SFT run with online evals starts one env server per source. - Live streaming, on the final code: gsm8k 16 single-turn episodes, terminal-bench-2 fix-git with bash (13-14 turns, the pending preview alternating with committed turns in the live files), kuhn-poker 4 two-seat episodes (8 traces), a 5-step reverse-text RL run (768 train episodes with token ids, logprobs and masks); no assembly mismatch. - Platform: `--monitors.prime` on a two-rollout fix-git eval opened the evaluation 9 s after launch, streamed both rollouts and closed it; the dashboard linked to it throughout. - Dashboard behaviour checked in headless Chromium: live rows and viewer follow, handover in place, metrics pane per env, filter menus, platform button states. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Breaking CLI and config renames affect existing scripts; env-server address discovery replaces fixed ports across `rl`, `sft`, and `eval` launch paths. > > **Overview** > **Replaces `uv run evals` with `uv run eval`** as the standalone evaluation entrypoint, sharing the orchestrator eval pipeline (per-source env servers, adaptive or pinned concurrency, file/W&B/Prime monitors). Config is **flattened** (`[[source]]`, `[client]`, `[concurrency]` at top level); **`--resume`** continues from the trace stream instead of a `[ckpt]` cursor; SFT **online eval** is renamed and typed as `SFTOnlineEvalConfig` (no public `[online]` block). > > **Env server wiring changes:** fixed `env_server_base_port` ranges are removed—launcher-managed servers bind **OS-assigned loopback ports** and publish addresses via **`address_file`** / `configs/.../envs/<split>/<name>.address`. Training **`ratio`** and online-eval **`interval`** are scoped to the right source types only. > > **Docs and examples** add `docs/eval.md`, per-example `eval.toml` files, and `configs/debug/eval/*` smokes; **`configs/evals/swe.toml` is deleted**. CI adds a **gsm8k eval** integration test on VM runners. > > **Dashboard** gains live rollout APIs and eval-centric metrics (plan-driven progress, platform links, eval run status), renames **`evals.log` → `eval.log`**, and tightens static asset revalidation. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 82f2f0e. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

Summary
verifiers/v1/serve/delta.py).Trace.notifyfires at every phase change and after every recorded turn; the worker'sDeltaStreamerdiffs the run's live traces against what it already sent and ships the new part (header once, appended nodes/calls/errors, semantic links, changed scalars), so every byte crosses the wire once. A cursor advances only after its delta is on the wire.EnvClient.runassembles the episode from the deltas (EpisodeAssembly, which copies the nodes it keeps so a later link never mutates a delta the caller holds), validates it once, and takeson_deltaso a caller can relay or persist the stream; the client's receive loop survives a malformed frame.pendingpreview: the interception server hands each model request's uncommitted tail (tool results, user turns) toTrace.preview, so a watcher sees a tool result before the model has answered; the committed turn replaces it and the finished record never carries it.uv run vf-evaland runs in-process only. Serving an env to many consumers is prime-rl's job (itsuv run evalruns env servers and consumes this stream), so the CLI keeps the quick local path and never assembles deltas; its TUI footer and console log point at prime-rl'seval. The env-server e2e fixture drives a worker pool throughEnvClientdirectly.Based on
main; the eval CLI stays for a transition period (#2610 removes it later). prime-rl PrimeIntellect-ai/prime-rl#3471 consumes the stream for its live traces.Breaking
client_id, request_id, kind, data) withkind=delta|reply;RunResponsecarries the episode head and per-trace counts instead of the traces. A client and server must be on the same side of this change.vf-eval,vf-validate,vf-debug,vf-replay,vf-init,vf-gepa. Generic names collide with the scripts of a workspace that installs verifiers as a dependency (prime-rl'seval), and the winner is whichever package was installed last.vf-evalhas no[serve]/--serve.*/--no-serve: rollouts always run in-process; use prime-rl'suv run evalfor env-server runs. Existing venvs:uv sync --reinstall-package verifiers --reinstall-package prime-rlregenerates the scripts.Env.run_slottakeson_trace;Tracegainswatch/notify/preview/clear_preview.Verification
tests/v1/test_serve_delta.py: turns, a link onto an earlier node, a retried attempt and the final reward round-trip throughDeltaStreamer→EpisodeAssembly→WireEpisode; a refused send is diffed again; the pending preview streams, is replaced by the committed turn and never reaches the record; assembling never mutates a delta; the field lists cover every serializedTracefield.uv run pytest tests/v1 -m "not e2e"green apart from the config-parse cases of tasksets not installed in the venv; ruff clean.subagent_call/subagent_return), kuhn-poker two-seat episodes, 5-step reverse-text RL runs with token ids and logprobs, including router replay plus sampling replay on a MoE; no assembly mismatch.🤖 Generated with Claude Code
Note
Stream served episodes turn by turn with delta frames
DeltaStreamerin delta.py that watches trace changes duringrun_slotand sends incremental deltas; the clientEpisodeAssemblyreconstructs aWireEpisodefrom those deltas plus a final episode head andTraceSummarycounts.Env.run_slotgains anon_tracecallback;Rollout.open/closeandInterceptionServernotify the trace on phase changes and pending turn previews.PendingTurn.commit/commit_promptnow clear the trace's pending preview after committing.RunResponsein types.py removes the serializedWireEpisodefield and replaces it with an episode head andTraceSummarylist — any out-of-tree consumer expecting the full episode in the run response will break.Changes since #2512 opened
pyproject.tomland updated all documentation and usage strings to usevf-prefixed command names [02a6eff]verifiers.v1.trace.Traceto store preview entries byid()of the key object rather than by the key object itself [73d602d]PRIME_RL_HINTconstant in thehint.pymodule [fc7e45b]Macroscope summarized fe771d8.
Note
High Risk
Breaking env-serve wire protocol and
RunResponseshape require matching client/server versions; CLI renames and removal of eval’s serve path change how users run evaluations.Overview
This PR streams env-server episodes incrementally instead of returning one fat
RunResponse. Workers useDeltaStreamerto diff live traces onTrace.notify()and senddeltaframes; clientsEpisodeAssemblyrebuilds traces and validate once against a final head +TraceSummarycounts. The wire format is now[request_id, kind, data]withkind=delta|reply; the pool relays deltas without closing the request.Tracegainswatch/notify/ keyedpreview/clear_preview; rollouts and the interception server fire notifications (including pending tool/user tails before commit).Env.run_slotaddson_traceso the server can subscribe traces to the streamer.vf-evalis renamed and narrowed: console scripts arevf-*to avoid clashing with prime-rl’seval, docs/config comments follow suit, andvf-evalalways runs in-process—[serve]/--no-serveare removed from eval config—with dashboard/log hints to use prime-rl for env-server scale and live dashboards.Reviewed by Cursor Bugbot for commit fc7e45b. Bugbot is set up for automated code reviews on this repo. Configure here.