feat(self-eval): baseline persistence + live agent-backed eval runner (Phase A substrate) - #65
Merged
Merged
Conversation
…on rate (A2) The Self-Eval Gate refuses a config change that regresses a workspace's private suite below a frozen baseline. This adds where that baseline lives: * SelfEvalBaseline model + migration 0040 — one row per (workspace, suite), NOT NULL workspace_id (tenant-scoped), unique(workspace_id, benchmark_suite_id), storing baseline_rate + resolved/total provenance + a redacted config snapshot. Deferred from 0001_baseline like benchmark_suite (its FK target), so the metadata baseline never creates it before benchmark_suite exists. * SelfEvalService — workspace_baseline() (the gate's baseline_for lookup), baseline_for_suite(), and record_baseline(overwrite=) with cold-start establish semantics so a regressing run can never lower the bar it defends. Storage-only: the promotion policy lives in the run/enforcement layer, and callers pass an already-redacted config. Registered in models/__init__ + EXPECTED_MODELS. Migration round-trips clean on the Postgres stepwise walk. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…box (A3) The real EvalRunner the Self-Eval Gate blocks on, in the worker (the only layer that may depend on both forge_agent and forge_eval, keeping forge_eval agent-free): * build_coder_tools — a path-safe read/write/list repo tool set for the agent. * agent_solve — checks out a case's base_commit into a scratch worktree, runs a coding AgentRunner (config under test) that only sees the public query, and diffs the worktree into the SolveFn file-map the sandboxed runner re-applies before the HIDDEN tests. The agent never sees fail_to_pass/pass_to_pass. * ProductionEvalRunner — resolves the workspace's private suite, loads its minted cases, and scores via run_self_eval over LocalSandboxProvider; returns None on any cold-start (no suite / no cases / no BYOK model) so the gate no-ops rather than fabricating a score. Tested fully offline: a scripted model writes the fix, real git worktrees are checked out from a temp repo, hidden tests run in the local sandbox, and a correct config scores 1.0 while a still-broken one scores 0.0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Self-Eval Gate enforcement — substrate (A2 + A3)
The Self-Eval Gate engine shipped in #64 as a tested engine with injected seams. This wires the two production substrates it needs, with zero change to any existing endpoint — purely additive.
A2 — baseline persistence
SelfEvalBaselinemodel + migration0040— one row per (workspace, suite), NOT NULLworkspace_id(tenant-scoped), unique(workspace_id, benchmark_suite_id), storingbaseline_rate+ resolved/total provenance + a redacted config snapshot. Deferred from0001_baselinelike its FK targetbenchmark_suite, so the metadata baseline never creates it first (verified on the Postgres stepwise-walk).SelfEvalService—workspace_baseline()(the gate'sbaseline_forlookup),baseline_for_suite(), andrecord_baseline(overwrite=)with cold-start establish semantics so a regressing run can never lower the bar it defends.A3 — live agent-backed eval runner
apps/worker(the only layer that may depend on bothforge_agentandforge_eval, keepingforge_evalagent-free).build_coder_tools— a path-safe read/write/list repo tool set.agent_solve— checks out a case'sbase_commitinto a scratch worktree, runs a codingAgentRunner(config under test) that only ever sees the publicquery, and diffs the worktree into theSolveFnfile-map the sandboxed runner re-applies before the hidden tests. The agent never seesfail_to_pass/pass_to_pass.ProductionEvalRunner— resolves the workspace's private suite, loads its minted cases, and scores viarun_self_evaloverLocalSandboxProvider. ReturnsNoneon any cold-start (no suite / no cases / no BYOK model) so the gate no-ops rather than fabricating a score.Verification (all offline, no network / no live model)
SelfEvalService: 6 tests (cold start, upsert, overwrite-guard, workspace isolation, config-snapshot copy).ProductionEvalRunner: 8 tests incl. a full end-to-end — a scripted model writes the fix, real git worktrees are checked out from a temp repo, hidden tests run in the local sandbox; a correct config scores 1.0, a still-broken one scores 0.0.make typecheck— 585 files, no issues. Migration round-trips clean on the Postgres stepwise walk.Follow-up PR wires the enforcement itself (A1 config-gate at the AO settings endpoints + A4
POST /runsbaseline establishment).🤖 Generated with Claude Code