feat(evals): eval-run-executor — governed set replay (R7 L1) - #203
Merged
Conversation
Replay an eval set against a model THROUGH the existing governance path, so a run
is a burst of billed upstream calls that enters the same budget/credit/tier/rate
guards a live request does — and never trips a shared breaker that would degrade
another tenant.
Two new tenant-scoped tables (four-manifest rule: migration f5b2d8c41a37 +
EXPECTED_TABLES + alembic env.py import + guardrails NOT-IN allow-list):
- eval_runs one row per launched run; status DERIVED from its cases (M7)
- eval_case_results per-case outcome; response_text is the ZDR-gated payload-at-rest;
UNIQUE(eval_run_id, eval_case_id) makes a resumed drive idempotent
The executor REUSES CompletionUseCase.complete() per case (never reimplements
governance), so M1 (9-guard order) + M2 (one usage_record per dial, on the served
model id) hold by construction. It injects its OWN per-tenant breaker + concurrency
semaphore (TenantExecutionRegistry) via complete(upstream=...) — NEVER the global
app.state.circuit_breaker — closing the recurring cross-tenant-DoS defect
(R:GLOBAL_BREAKER). Every dial carries a per-call timeout; breaker-open and timeout
both fail the case closed (errored), the run continues.
Security:
- ZDR refused OUTRIGHT at launch (403 ERR_ZDR_PAYLOAD_BLOCKED) AND re-checked
ATOMICALLY (raise_if_zdr_locked) at the first payload write — a flip mid-run
persists nothing further and marks the run blocked.
- Auth-scoped resume: the raw API key is NEVER persisted at rest (only key_id).
In-process crash resumes from the in-memory key; a cross-redeploy resume must
re-supply the key via a fresh authenticated request — never a forged identity.
- Uniform 404 for absent/cross-tenant runs (ERR_EVAL_RUN_NOT_FOUND) — no oracle.
API (one OpenAI-wire envelope, reused from the eval-set-store surface):
POST /v1/evals/sets/{set_id}/runs -> 201 { id:"er_..", status, case_count, ... }
GET /v1/evals/runs/{run_id} -> 200 { status, counts:{...} }
GET /v1/evals/runs/{run_id}/cases -> 200 list, case-creation order (A5)
Launch enqueues onto app.state.eval_run_queue when present and FAILS OPEN to an
inline drive (the vector-store ingest idiom) — the durable Redis worker loop is a
follow-up; the seam is in place and no CHECK depends on it.
TDD: 13 red-first CHECKS (M1-M8, A1-A6, E1-E6, R:*) — governance-per-case,
over-budget-no-dial, one-usage-record-per-dial, per-tenant-breaker isolation,
ZDR-atomic-zero-results, resume-no-rebill, timeout-errored-run-continues,
uniform-404, case-creation-order, empty-set-vacuous, cross-tenant-launch +
billing-identity, snapshot-fixed-at-launch, bounded-per-tenant-concurrency.
make ci green incl. migration-parity + guardrails no-new-tables gates; pyright +
ruff clean.
ADD: eval-run-executor frozen sha256:2abaa868 (reseal binding A1/A2/A3/A6/M8) ->
gate PASS. R7 evals-regression-gate.
author: Tin Dang
The lint gate is `ruff check . && ruff format --check .`; my local check covered ruff check but not the formatter. Format-only: migration, run_router, and the test file. No behavior change. author: Tin Dang
CI shard 2 tripped the repo-hygiene guard (tests/repo_hygiene/test_no_unbounded_positive_wait.py, ERR_UNBOUNDED_WAIT): test_resume_does_not_rebill_terminal_cases had a bare `await asyncio.sleep(0.05)` immediately before `assert upstream.calls == 3`. The guard reads a fixed sleep- then-assert as an unbounded positive wait. It is in fact a NEGATIVE wait: the resume drive is already awaited to completion, and the sleep only gives an ERRANT fire-and-forget re-dial/re-bill a window to land so the following assertions can prove it did NOT. A bounded poll_until can't express "prove nothing more ever happens" — it returns on the first satisfied tick. The real guarantee is skip-existing + UNIQUE(eval_run_id, eval_case_id); the wait only widens the window for a violation to surface. Annotate the sleep `# NEGATIVE WAIT: <reason>` per the guard's own remedy. No production code changes; the 13 CHECKS and both lint halves stay green. Local verify: repo_hygiene guard 5 passed; evals_runs suite 13 passed; ruff check . + ruff format --check . clean. author: Tin Dang
pilotspacex-byte
approved these changes
Aug 13, 2026
pilotspacex-byte
left a comment
Contributor
There was a problem hiding this comment.
pilotspacex-byte byte-approval — operator-directed, one-time, DISCLOSED. This is NOT independent four-eyes review; it unblocks the protected gate on Tin's direction and still owes a genuine second human before the SOC 2 audit. CI fully green (ci + dashboard + 4 gateway shards + coverage all pass at 3acc47a). eval-run-executor: reuses complete() per case (governance/billing by construction), injects a per-tenant breaker via complete(upstream=) never the global one, ZDR two-layer atomic, auth-scoped resume (no raw key at rest), uniform 404. 13 red-first CHECKS green; ADD frozen sha256:2abaa868 -> gate PASS.
This was referenced Aug 13, 2026
TinDang97
added a commit
that referenced
this pull request
Aug 14, 2026
Close and archive R7 milestone `evals-regression-gate` (7/7 exit criteria) and cut the release. R7 is the first product-feature milestone since R6's substrate work: a tenant runs a named eval set against a candidate model and gets a scored pass/fail verdict against a pinned baseline, so a model swap is proven safe BEFORE it ships — without touching the hot proxy path, auto-promoting on a verdict, or scoring with an LLM judge. Shipped across the milestone (all merged, all gated PASS): - eval-set-store (#201) — /v1/evals/sets + cases; ZDR disposition frozen first - deterministic-scorers (#202) — exact · contains · regex · json-schema, re-run stable - eval-run-executor (#203) — governed set replay: billed traffic, per-tenant breaker - baseline-and-verdict (#204) — pin baseline, exact integer verdict, no_baseline state - evals-console (#205) — verdict-first, read-focused, reuses the /v1 verdict core Version bumped across all eight sites per the RELEASES.md checklist: pyproject + `__version__` fallback, Chart.yaml version (0.2.1->0.2.2) + appVersion, values.yaml gateway+dashboard tags, values-prod.yaml both `-prod` overrides. Dashboard package.json stays independently versioned (0.1.0) — a gateway release does not ship a phantom UI release. Guards green: tests/release_provenance (served /openapi.json == pyproject == fallback, RELEASES newest >= pyproject) and the production digest-pin / multi-arch image guards (14 passed). Waivers: 0.14.0's suite-stability and pgvector-deploy-runbook carry forward unchanged (both RISK-ACCEPTED, owner Tin Dang, expire 2026-09-30); ci-restoration stays DISCHARGED. No new waivers. REMAINING IS HUMAN-RUN (tagging PUBLISHES images via publish-images.yml): 1. git tag -a v0.15.0 on the merge commit, and push 2. verify the publish-images run is green (reads back the manifest for both images; do not deploy a tag whose publish job is not green) 3. staging first, following the pgvector runbook (dump/restore path) OPEN, carried to R8 `soc2-groundwork` and NOT waived: the `required_approving_review_count: 1` gate was satisfied on all five R7 PRs by an operator-directed self-approval via a second account (`pilotspacex-byte`), disclosed on each PR. That evidences a green required check on the merged artifact; it does NOT evidence independent four-eyes review. Every R7 merge still owes a genuine second human with write access before the SOC 2 audit. author: Tin Dang
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
eval-run-executor — governed set replay (R7 L1)
Third of R7's evals-regression-gate tasks (after #201 eval-set-store, #202 deterministic-scorers). Replays an eval set against a model through the real governance path, so a run is a burst of billed upstream calls that enters the same budget/credit/tier/rate guards a live request does — and never trips a shared breaker that would degrade another tenant.
What it does
CompletionUseCase.complete()per case — never reimplements governance. M1 (9-guard order) and M2 (exactly oneusage_recordsrow per dial, on the served model id) hold by construction.complete(upstream=...)— never the globalapp.state.circuit_breaker. Closes the recurring cross-tenant-DoS defect (R:GLOBAL_BREAKER). Every dial has a per-call timeout; breaker-open and timeout fail the case closed (errored), the run continues.UNIQUE(eval_run_id, eval_case_id)+ skip-existing makes a resumed drive never re-dial or re-bill a terminal case.Security
ERR_ZDR_PAYLOAD_BLOCKED) and re-checked atomically (raise_if_zdr_locked) at the first payload write — a flip mid-run persists nothing further and marks the runblocked.key_id). In-process crash resumes from the in-memory key; a cross-redeploy resume must re-supply the key via a fresh authenticated request — never a forged identity.ERR_EVAL_RUN_NOT_FOUND) — no enumeration oracle.Schema (four-manifest rule)
Two new tenant-scoped tables via migration
f5b2d8c41a37:eval_runs+eval_case_results(response_text= ZDR-gated payload-at-rest). Registered across all four manifests (migration ·EXPECTED_TABLES· alembicenv.pyimport · guardrails NOT-IN allow-list).API (one OpenAI-wire envelope, reused from eval-set-store)
Launch enqueues onto
app.state.eval_run_queuewhen present and fails open to an inline drive (the vector-store ingest idiom). The durable Redis worker loop is a follow-up; the seam is in place and no CHECK depends on it.Tests — 13 red-first CHECKS (M1-M8, A1-A6, E1-E6, R:*)
governance-per-case · over-budget-no-dial · one-usage-record-per-dial · per-tenant-breaker isolation · ZDR-atomic-zero-results · resume-no-rebill · timeout-errored-run-continues · uniform-404 · case-creation-order · empty-set-vacuous · cross-tenant-launch + billing-identity · snapshot-fixed-at-launch · bounded-per-tenant-concurrency.
make cigreen incl. migration-parity + guardrails no-new-tables gates; pyright + ruff clean.ADD: eval-run-executor frozen
sha256:2abaa868(reseal binding A1/A2/A3/A6/M8) → gate PASS.