Skip to content

feat: remove the eval CLI - #2610

Open
mikasenghaas wants to merge 2 commits into
mainfrom
feat/drop-eval-cli
Open

mikasenghaas wants to merge 2 commits into
mainfrom
feat/drop-eval-cli

Conversation

@mikasenghaas

@mikasenghaas mikasenghaas commented Sep 15, 2026

Copy link
Copy Markdown
Member

Summary

  • Remove the eval console script and everything only it used: verifiers/v1/cli/eval/ (main, runner, resume), the rich eval dashboard, configs/cli/eval.py, utils/platform.py, the configs/*.toml examples and the evaluate-environments skill. Evaluation moves to prime-rl's uv run eval (feat: consolidate eval cli prime-rl#3471), which brings adaptive concurrency, the local dashboard, pre-installed environments and a shared workspace with training.
  • RunConfig + default_run_name move to configs/cli/run.py for the CLIs that stay (validate, gepa); cli/output.py takes any config that owns a run directory.
  • The e2e suite runs tasksets in-process through tests/v1/runner.py instead of the CLI.
  • prime-runs is no longer a dependency; docs and scaffold hints point at uv run validate and prime-rl's uv run eval.

On hold. The eval CLI stays for a transition period after prime-rl's uv run eval lands; #2512 (streamed traces) no longer stacks on this branch and lands first. Rebase onto main once the transition period ends.

Breaking

  • uv run eval is gone, with --rich, --push, --resume, --dry-run and the configs/*.toml examples. Use prime-rl's uv run eval <taskset-id>.
  • Removed from the library surface: verifiers.v1.configs.cli.eval (EvalConfig, RichConfig), verifiers.v1.cli.eval, verifiers.v1.cli.dashboard.eval, verifiers.v1.utils.platform. RunConfig/default_run_name now import from verifiers.v1.configs.cli.run.
  • prime-runs is no longer a transitive dependency; install it directly if you relied on it.
  • Hosted evaluations ran uv run eval --run.attach $EVALUATION_ID inside the sandbox (feat(v1): run.attach streams the eval into a run the platform already created #2569); that path needs prime-rl's uv run eval to grow --run.attach before this lands.

Verification

  • uv run pytest tests/v1 -m "not e2e": 81 passed; uv run ruff check . && uv run ruff format . clean.

🤖 Generated with Claude Code


Note

High Risk
Breaking public API and CLI (uv run eval, push/resume/rich flags, EvalConfig); hosted eval attach paths need prime-rl parity before upgrade.

Overview
Removes the in-repo uv run eval product and hands full model evaluations to prime-rl (uv run eval). The eval console script, EvalConfig, the eval runner/resume path, the Rich live dashboard, platform push (prime-runs / utils/platform.py), and all configs/*.toml eval examples and the evaluate-environments skill are deleted.

What stays wired for local dev: RunConfig and default_run_name move to configs/cli/run.py; validate, gepa, debug, and replay still write run dirs via generalized cli/output.py. E2E tests exercise envs through new tests/v1/runner.py (RunnerConfig + run_episodes) instead of spawning the eval CLI. Docs, AGENTS.md, and init scaffolding now emphasize uv run validate and prime-rl for evals.

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

Note

Remove the eval CLI and replace with shared run_episodes runner

  • Removes the eval console-script registration and the prime-runs dependency from pyproject.toml; the validate, debug, replay, and gepa scripts remain.
  • Adds RunnerConfig and run_episodes in tests/v1/runner.py to execute task rollouts through either an in-process environment backend or a spawned env-server pool, replacing the old run_eval path.
  • Extracts shared run-identity definitions (RunConfig, default_run_name) into verifiers/v1/configs/cli/run.py and updates validate, gepa, and output helpers to use them.
  • Updates v1 tests in conftest.py and test_envs.py to use run_v1/run_v1_server fixtures backed by run_episodes instead of the eval CLI.
  • Updates docs (getting_started.md, tasksets.md, overview.md, gepa.md), AGENTS.md, and the init scaffold command to direct users to uv run validate for checks and to prime-rl for evaluations.
  • Risk: importing verifiers.v1.cli.dashboard no longer exposes the evaluation dashboard attribute; any out-of-tree consumers of that symbol will break. Installing the project no longer provides an eval command.

Macroscope summarized 067fe68.

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.
Comment thread verifiers/v1/cli/init.py Outdated
@macroscopeapp

macroscopeapp Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR removes the standalone eval CLI, platform run integration, dashboard, resume machinery, and bundled evaluation workflow, shifting evaluation to prime-rl and changing related production configuration/output code. The cross-repository migration and unresolved scaffold onboarding concern create substantial user-facing risk requiring human review.

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

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>
mikasenghaas added a commit that referenced this pull request Sep 16, 2026
## Summary

- Served episodes stream turn by turn over the env-serve wire
(`verifiers/v1/serve/delta.py`). `Trace.notify` fires at every phase
change and after every recorded turn; the worker's `DeltaStreamer` diffs
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.run` assembles 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 takes `on_delta` so a caller can relay or persist the stream; the
client's receive loop survives a malformed frame.
- `pending` preview: the interception server hands each model request's
uncommitted tail (tool results, user turns) to `Trace.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.
- The eval CLI is `uv run vf-eval` and runs in-process only. Serving an
env to many consumers is prime-rl's job (its `uv run eval` runs 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's `eval`. The env-server e2e fixture drives a worker pool
through `EnvClient` directly.

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

- Env-serve wire: replies are 4 frames (`client_id, request_id, kind,
data`) with `kind` = `delta` | `reply`; `RunResponse` carries the
episode head and per-trace counts instead of the traces. A client and
server must be on the same side of this change.
- Every console script is prefixed: `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. `vf-eval` has no `[serve]` / `--serve.*` / `--no-serve`: rollouts
always run in-process; use prime-rl's `uv run eval` for env-server runs.
Existing venvs: `uv sync --reinstall-package verifiers
--reinstall-package prime-rl` regenerates the scripts.
- `Env.run_slot` takes `on_trace`; `Trace` gains
`watch`/`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 through `DeltaStreamer`
→ `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 serialized `Trace` field.
- `uv run pytest tests/v1 -m "not e2e"` green apart from the
config-parse cases of tasksets not installed in the venv; ruff clean.
- End to end through prime-rl: gsm8k single turn, terminal-bench-2
fix-git with bash and with the rlm harness delegating to a sub-agent
(semantic links `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](https://claude.com/claude-code)


<!-- 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]
> ### Stream served episodes turn by turn with delta frames
> - Adds `DeltaStreamer` in
[delta.py](https://github.com/PrimeIntellect-ai/verifiers/pull/2512/files#diff-106a565d15f6f5c86f7357854d512768b3f8a4775026a0eae32c69b828f5da31)
that watches trace changes during `run_slot` and sends incremental
deltas; the client `EpisodeAssembly` reconstructs a `WireEpisode` from
those deltas plus a final episode head and `TraceSummary` counts.
> - Changes the wire protocol to three-frame messages (request ID, kind,
data). Delta frames are relayed by the pool and client without closing
the request; reply frames close it. Updated in
[server.py](https://github.com/PrimeIntellect-ai/verifiers/pull/2512/files#diff-64422f6a8749fcc024415b2756129bc98000e830e74b3b5245de50a555480a22),
[pool.py](https://github.com/PrimeIntellect-ai/verifiers/pull/2512/files#diff-0c9c59578214be2580d340bc524321e352f48038207a68945637d00fc399600c),
and
[client.py](https://github.com/PrimeIntellect-ai/verifiers/pull/2512/files#diff-ef98a21052536967b8f8723e36022f69e539f4e8b13794791e8254434ac4696e).
> - Adds a trace watcher/preview API in
[trace.py](https://github.com/PrimeIntellect-ai/verifiers/pull/2512/files#diff-834820c3aa80d87ee1c1c57fb54c74f09c66ac727036d964e6005c8613c00b5e).
`Env.run_slot` gains an `on_trace` callback; `Rollout.open`/`close` and
`InterceptionServer` notify the trace on phase changes and pending turn
previews.
> - `PendingTurn.commit`/`commit_prompt` now clear the trace's pending
preview after committing.
> - Risk: `RunResponse` in
[types.py](https://github.com/PrimeIntellect-ai/verifiers/pull/2512/files#diff-8e290c0dfc583c92b20ee9f20fa2ecd0df82459ad63f8e819e87aa856de97cf4)
removes the serialized `WireEpisode` field and replaces it with an
episode head and `TraceSummary` list — any out-of-tree consumer
expecting the full episode in the run response will break.
>
> <!-- Macroscope's changelog starts here -->
> #### Changes since #2512 opened
>
> - Renamed console script entry points in `pyproject.toml` and updated
all documentation and usage strings to use `vf-` prefixed command names
[02a6eff]
> - Refactored trace preview system from unkeyed to keyed architecture
[55500a3]
> - Updated all trace preview and clear operations to use keyed API with
PendingTurn instances as keys [55500a3]
> - Added abandon mechanism for cleaning up previews when turns fail or
are cancelled [55500a3]
> - Changed `verifiers.v1.trace.Trace` to store preview entries by
`id()` of the key object rather than by the key object itself [73d602d]
> - Updated `PRIME_RL_HINT` constant in the `hint.py` module [fc7e45b]
> <!-- Macroscope's changelog ends here -->
>
> <!-- Macroscope's review summary starts here -->
>
> <sup><a href="https://app.macroscope.com">Macroscope</a> summarized
fe771d8.</sup>
> <!-- Macroscope's review summary ends here -->
>
<!-- Macroscope's pull request summary ends here -->

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **High Risk**
> Breaking env-serve wire protocol and `RunResponse` shape 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 use **`DeltaStreamer`** to diff
live traces on `Trace.notify()` and send **`delta`** frames; clients
**`EpisodeAssembly`** rebuilds traces and validate once against a final
**head + `TraceSummary` counts**. The wire format is now **`[request_id,
kind, data]`** with `kind` = `delta` | `reply`; the pool relays deltas
without closing the request.
> 
> **`Trace`** gains **`watch` / `notify` / keyed `preview` /
`clear_preview`**; rollouts and the interception server fire
notifications (including **pending tool/user tails** before commit).
**`Env.run_slot`** adds **`on_trace`** so the server can subscribe
traces to the streamer.
> 
> **`vf-eval` is renamed and narrowed**: console scripts are **`vf-*`**
to avoid clashing with prime-rl’s **`eval`**, docs/config comments
follow suit, and **`vf-eval` always runs in-process**—**`[serve]` /
`--no-serve` are removed** from eval config—with dashboard/log hints to
use **prime-rl** for env-server scale and live dashboards.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
fc7e45b. 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>
mikasenghaas added a commit to PrimeIntellect-ai/prime-rl that referenced this pull request Sep 16, 2026
## 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>
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.

1 participant