Skip to content

feat(cli): add --no-eval to turn the accuracy eval off for a whole run - #1105

Merged
xiaofei-zheng merged 13 commits into
mainfrom
feat/zgong/eval-policy
Aug 7, 2026
Merged

feat(cli): add --no-eval to turn the accuracy eval off for a whole run#1105
xiaofei-zheng merged 13 commits into
mainfrom
feat/zgong/eval-policy

Conversation

@ZhengGong-amd

Copy link
Copy Markdown
Collaborator

Branch: feat/zgong/eval-policy, 1 commit on top of 789436d1e. Closes #1089

RUN_EVAL=false leaves the baseline without an accuracy reference, and since
08da16d the baseline guard rejects exactly that — so the run stops before it
optimizes anything. --no-eval is one store_true flag; default off is
today's behaviour unchanged.

The change

Two edits, both joining a condition that already exists:

  • baseline.py::_run_once — the disable_run_eval force-off already
    writes RUN_EVAL=false; the flag joins it.
  • baseline.py::_maybe_stop_on_missing_baseline_accuracy — an early return
    beside the _should_establish_quality_ref one. The guard rejects a reference
    that was supposed to be measured; under --no-eval none was asked for.

Same expression also absorbs the flag in eval_already_off: with eval off, an
eval-failure marker cannot be about an eval that ran.

What follows for free

No candidate-side gate is touched:

why
candidate RUN_EVAL candidates template from the baseline's materialized YAML, so they inherit the disable
accuracy_keep_block baseline_accuracy stays 0, so base > 0 is false and it already returns (False, "", True)
explore's inline gate serving arm guarded by baseline_accuracy > 0, never arms
framework / integrate / kernel gates read accuracy_baseline from state.baseline_accuracy (phases/framework.py:3485)
eval-concurrency preflight hard-fail keyed on _materialized_run_eval_disabled, now True
sweep / conc_sweep already inject RUN_EVAL=false

The inheritance was verified, not assumed: materializing the baseline with
RUN_EVAL=false then re-materializing it as a candidate yields 'false' on
both. That is why the change stays at two sites — an earlier draft that pushed
the decision into materialize_config_with_envs fought the same inheritance.

A measured regression still blocks: the scriptable (xDiT) image quality_gate
is computed by the benchmark run itself and never consulted RUN_EVAL.

Files

file change
cli/parser.py --no-eval, store_true, following --no-explore
cli/bootstrap.py one line into the SharedState construction
state/shared_state.py eval_disabled: bool = False
executors/baseline.py _eval_disabled helper + 3 call sites, docstrings refreshed
docs/reference/environment-variables.md flag list + one sentence

Net ~30 source lines.

Tests

  • test_no_eval_forces_run_eval_false — end to end: materialized YAML carries
    RUN_EVAL=false, stop_reason empty.
  • test_no_stop_when_eval_is_disabled — the guard exemption. Its siblings
    (test_stop_serving_operator_disabled_via_config,
    test_stop_serving_eval_failure_fallback) are untouched and still stop,
    which is what proves the exemption is narrow.
  • test_cli_no_explore.py — flag defaults False, sets True, state field
    defaults False.

343 passed across the 12 affected files; ruff check clean. pylint --errors-only shows only the three pre-existing __dataclass_fields__
findings in shared_state.py (confirmed by stashing).

Compatibility

Default-off is byte-for-byte today's behaviour. SharedState.from_dict filters
to known __dataclass_fields__, so an old state.json loads and reads
False; the field persists across a resume.

Not in this branch

  • No tri-state. Add a user-configurable eval policy (baseline-only / off) for performance-focused runs #1089 proposed HYPERLOOM_EVAL_POLICY
    (full/baseline_only/off). One flag covers the ask, and a tri-state
    costs a policy check at every candidate gate — all of which the
    baseline_accuracy == 0 path already handles.
  • No env var. A CLI flag needs no cross-process allowlist entries
    (specialist, kernel-agent, multi-node) to survive a subprocess.
  • No "unvalidated" stamp in reports/final.{json,md}. Under --no-eval a
    baseline_accuracy of 0.0 reads like a collapsed model, so an annotation
    on report.py::_format_completeness_annotations is worth adding — but it is
    reporting, not this flag's logic.

A CI/CD tuning run that cares only about throughput has no way to skip the
eval today: RUN_EVAL=false leaves the baseline without an accuracy
reference, and the baseline guard rejects that, so the run stops before it
optimizes anything.

--no-eval writes RUN_EVAL=false into the baseline's materialized YAML and
exempts the baseline guard. Everything downstream follows for free:
candidates template from that YAML so they inherit the disable, and
baseline_accuracy stays 0, which accuracy_keep_block and explore's inline
gate already treat as "grade on throughput only". So no candidate-side gate
needs touching. The eval-concurrency preflight hard-fail also self-disables,
since it keys off the materialized RUN_EVAL.

A measured regression still blocks: the scriptable image quality_gate is
computed by the benchmark run itself and never consulted RUN_EVAL.

Closes #1089

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ZhengGong-amd
ZhengGong-amd requested a review from a team as a code owner August 6, 2026 06:59
ZhengGong-amd and others added 8 commits August 6, 2026 08:21
Conflict in baseline.py::_run_once: main added the
defer_accuracy_until_after_measure local right where this branch added
--no-eval to the RUN_EVAL force-off condition. Both kept.

Main's staged accuracy round is a new eval participation point that
--no-eval has to cover: it re-runs the benchmark on the hot server with
run_eval=True hard-coded, so the flag would have leaked one eval per
baseline. The deferral is now cancelled when the flag is set.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
_eval_disabled read `ctx.extra["shared_state"] or self.shared_state`, but the
kernel integrate lane constructs BaselineExecutor with neither, so the flag
resolved False there. That left defer_accuracy_until_after_measure (set
unconditionally by that lane) uncancelled and _write_lifecycle_config re-wrote
RUN_EVAL=true, i.e. a full lm_eval per re-baseline. Route through the existing
_resolve_shared_state, which falls back to the session dir, and take the
sibling _eval_enablement_active with it so both read the same source.

Refs #1089

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
_enqueue_framework_agent_task is the only bench lane without a config_path, so
FrameworkAgentExecutor templates from the shipped default YAML, which carries
no RUN_EVAL and is therefore materialized with the "true" default. Under
--no-eval every framework candidate still paid a full GSM8K run.

Injecting baseline_config_path the way the other lanes do is not an option
here: materialize_config_with_envs is not idempotent for sglang, so
re-templating from the baseline's materialized YAML re-prepends
$INFERENCE_OPTIMIZER_SERVER_ARGS and, since sglang is last-wins, resurrects the
operator value over a baseline that deliberately overrode it. Carry the
decision as a disable_run_eval param instead, which is all the lane needs.

Refs #1089

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
The eval-origin enablement lane exists to repair a broken accuracy eval, so it
is incoherent with --no-eval and the two disagreed in opposite directions:
integrate_patch forced RUN_EVAL=true for an enablement candidate, re-enabling
the eval the flag had turned off, while the revalidation baseline's
disable_run_eval=False was overridden by the flag, leaving a revalidation that
could never revalidate anything.

Gate the lane itself rather than patching either side. eval_enablement_allowed
already takes shared_state and is the single admission point for all three
callers (baseline routing, writeback budget suppression, specialist dispatch),
so closing it there makes both branches unreachable instead of contradictory.
launch_enablement_allowed is untouched: a baseline that cannot boot is
orthogonal to the eval.

Refs #1089

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Both enablement RUN_EVAL force-ons keyed on params["enablement"] alone, but
only the eval-origin gate requires a score: _runnable_decision fails closed on
a missing accuracy for eval-origin and leaves a boot-origin candidate
provisional. The launch lane stays open under --no-eval by design, so its
integrate candidate was re-enabling an eval the session had turned off and that
nothing would have rejected it for lacking.

Scope both sites to the eval origin through one predicate, which the runnable
gate already keyed on.

Refs #1089

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
_run_eval_enabled had the precedence inverted against every other eval site
and against its own neighbours (MAGPIE_EVAL_TASKS / _LIMIT), so an exported
RUN_EVAL=true could resurrect an eval the session had turned off.

Refs #1089

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Two eval costs that survived --no-eval because neither reads the session state.

Multi-node preflight installed lm_eval off the process RUN_EVAL alone, which a
CLI flag never sets. The install runs with check=True, so a run that will never
load the harness could still fail to start on it. Preflight runs before the
--resume block reads state.json, so the flag is resolved from both the args and
the resumed session rather than the args alone.

The GEAK GEMM shape-capture wrapper defaulted RUN_EVAL to true from the
inherited env, so every capture paid a GSM8K run. Nothing grades it -- the
payload asks for E2E_METRIC=output and consumes baseline_tput only -- so this
is disabled outright rather than gated on the flag, matching the sibling
capture path that already hard-sets RUN_EVAL=false.

Refs #1089

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
The other run-scoped toggles (kernel, framework phase, explore) each print
their persisted state on resume and refuse to apply retroactively once the
phase they gate has been entered. eval_disabled had neither: a resume silently
inherited the persisted value with no line in the summary, and --no-eval
against a normal session was dropped without a word.

The cutoff is the anchored accuracy rather than a phase, because the baseline
runs inside PRELUDE and the phase alone cannot say whether a reference exists.
Once it does, every KEEP so far was graded against it, so the flag is refused
with a warning naming the score.

Refs #1089

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@ZhengGong-amd
ZhengGong-amd force-pushed the feat/zgong/eval-policy branch from 5e1577a to ebcacdc Compare August 6, 2026 11:15
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown

CI E2E report — ❌ Timeout

item value
result ❌ Timeout
model Qwen/Qwen3-0.6B (dense)
resources 1× GPU, TP=1
PR branch feat/zgong/eval-policy
commit 16b88ef3f9f150b6e768b9ca03e634892de2421f
session_id be189725-7e60-4680-b546-2e200b419fd9
queue → dispatch 0s
run time 222m 3s
total 222m 3s
reason Timed out — the run never reached a terminal state in time (task stuck, or the GPU stayed queued too long).
detail not terminal after 13200s

details

ZhengGong-amd and others added 4 commits August 7, 2026 02:40
Textual auto-merge was clean across all ten files both sides touched. The
semantic review that matters for this branch is whether main opened a lane the
--no-eval feature does not cover: it did not. main adds no RUN_EVAL write site
outside tests, no new accuracy-gated enqueue, and leaves the single
require_accuracy_for_keep site the branch already carries disable_run_eval
through. eval_disabled is likewise not surfaced in the prompt render, matching
main's treatment of the sibling kernel_enabled toggle, so nothing needs
mirroring there either.

Co-authored-by: Cursor <cursoragent@cursor.com>
The three flags retired with the kernel LLM role were re-registered as no-ops
so a launcher or operator template that still passes them would not exit 2 in
argparse. --kernel-prompt took a path, and registering it as store_true meant
the path was not consumed: it fell through as a stray positional and argparse
exited 2 anyway, reproducing the exact failure the shim exists to prevent.
Register it separately with type=str so the value is swallowed.

Restore the launcher guard the shim silently disarmed. Once the parser accepts
the retired names they are "known" flags, so the name-membership check can no
longer notice a launcher reintroducing one; assert their absence directly, as
before, and add a parse-level regression test for the no-op contract itself.

The membership check also never modelled arity, which is why it would have
reported --kernel-prompt as accepted while a real run died. Check that a flag
a launcher hands a value to is one argparse takes a value for. Both directions
were confirmed by mutation: injecting a store_true flag with a value fails the
new arity case while the name case still passes.

Co-authored-by: Cursor <cursoragent@cursor.com>
The bug this test guards was a shared-state dump assembled before the gap was
recomputed, so the prompt carried both the stale 0.00 and the fresh value. The
positive assertion alone cannot see that shape: it passes as soon as 15.00
appears anywhere, whether or not 0.00 is still sitting above it. Restore the
negative half.

Co-authored-by: Cursor <cursoragent@cursor.com>
The Removed entry listed the three kernel CLI flags as removed, and marked the
whole entry breaking, while the parser accepts them. Split the two cases: the
env vars really are gone, the flags parse as hidden no-ops until the callers
that pass them are updated. Note that --kernel-prompt still takes its path, so
the distinction is not merely cosmetic.

Add the missing Unreleased entry for --no-eval: what it changes about the
baseline anchor and the candidate gates, that a measured regression still
blocks, that it is session state rather than a parsed arg so the lanes that
template their own bench config are covered, and that it is refused once an
accuracy has been anchored.

Co-authored-by: Cursor <cursoragent@cursor.com>
@xiaofei-zheng
xiaofei-zheng merged commit 081e2f1 into main Aug 7, 2026
26 of 28 checks passed
@xiaofei-zheng
xiaofei-zheng deleted the feat/zgong/eval-policy branch August 7, 2026 03:11
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.

Add a user-configurable eval policy (baseline-only / off) for performance-focused runs

2 participants