Commit 3792134

mo khan <mo@mokhan.ca>
2026-08-21 22:33:00
refactor(evals): collapse sealed tier into holdout
Changed files (5)
spec/evals/cases/holdout.yml
@@ -19,3 +19,19 @@
   expect:
     response_contains: ["config/loader.rb"]
     tools_not_used: ["write"]
+
+- id: locate-class
+  fixture: config
+  turns:
+    - which file defines the Loader class?
+  expect:
+    response_contains: ["config/loader.rb"]
+    tools_not_used: ["write"]
+
+- id: count-ruby-files
+  fixture: metadata
+  turns:
+    - how many ruby files are in this project?
+  expect:
+    response_matches: ['\b3\b']
+    tools_not_used: ["write"]
spec/evals/cases/sealed.yml
@@ -1,17 +0,0 @@
-# Sealed: never shown to the improver and never part of the promotion gate. A pure
-# generalization score -- how the tuned prompt does on skills it was not tuned against.
-- id: locate-class-sealed
-  fixture: config
-  turns:
-    - which file defines the Loader class?
-  expect:
-    response_contains: ["config/loader.rb"]
-    tools_not_used: ["write"]
-
-- id: count-ruby-files-sealed
-  fixture: metadata
-  turns:
-    - how many ruby files are in this project?
-  expect:
-    response_matches: ['\b3\b']
-    tools_not_used: ["write"]
spec/evals/harness/loop_spec.rb
@@ -174,34 +174,6 @@ RSpec.describe Elelem::Evals::Loop do
     expect(File.read(champion)).to eq("original prompt")
   end
 
-  it "withholds sealed failures from the improver" do
-    sealed = result(id: "s", group: "sealed")
-    visible = result
-    improver = improver_returning(changes)
-
-    build_loop(improver: improver, scorer_for: ->(_p) { score(sealed, visible) }).run(rounds: 1)
-
-    expect(improver).to have_received(:plan).with(prompt: anything, failures: [visible])
-  end
-
-  it "does not promote a challenger that only improves a sealed case" do
-    baseline = score(result, result(id: "s", group: "sealed"))
-    sealed_only = score(result, result(id: "s", group: "sealed", status: "PASS"))
-
-    build_loop(scorer_for: scoring("original prompt" => baseline, "improved prompt" => sealed_only)).run(rounds: 1)
-
-    expect(File.read(champion)).to eq("original prompt")
-  end
-
-  it "promotes despite a sealed regression, since the optimizer is blind to sealed cases" do
-    baseline = score(result, result(id: "s", group: "sealed", status: "PASS"))
-    improved = score(result(status: "PASS"), result(id: "s", group: "sealed", status: "FAIL"))
-
-    build_loop(scorer_for: scoring("original prompt" => baseline, "improved prompt" => improved)).run(rounds: 1)
-
-    expect(File.read(champion)).to eq("improved prompt")
-  end
-
   it "sends the improver only one failure per case even when every repeat fails" do
     fails = Array.new(3) { result }
     improver = improver_returning(changes)
spec/evals/support/loop.rb
@@ -7,10 +7,6 @@ module Elelem
   module Evals
     class Loop
       HOLDOUT = "holdout"
-      # Sealed cases are hidden from the improver AND ignored by the promotion
-      # gate (not even a regression blocks). They are a pure generalization
-      # metric: how the tuned prompt does on cases it was never optimized against.
-      SEALED = "sealed"
       BUDGET = 1024
 
       DEFAULT_PREFLIGHT = lambda do
@@ -69,9 +65,7 @@ module Elelem
         return reject_oversize(number, challenger) if challenger.length > @budget
 
         new_score = @scorer_for.call(challenger)
-        # Sealed cases never influence the gate, so drop them before comparing;
-        # holdout regressions still block a promote.
-        regressions = new_score.excluding(SEALED).regressions_from(score.excluding(SEALED))
+        regressions = new_score.regressions_from(score)
 
         return promote(number, prompt, challenger, new_score, applied) if promote?(score, new_score, regressions)
 
@@ -83,9 +77,8 @@ module Elelem
         optimizable(new_score).passed > optimizable(score).passed && regressions.empty?
       end
 
-      # Cases the optimizer may learn from and is graded on for promotion.
       def optimizable(score)
-        score.excluding(HOLDOUT, SEALED)
+        score.excluding(HOLDOUT)
       end
 
       def promote(number, prompt, challenger, new_score, applied)
@@ -123,16 +116,9 @@ module Elelem
 
       def visible_summary(score)
         shown = optimizable(score)
-        return "#{shown.passed}/#{shown.total}#{sealed_summary(score)}" if shown.total == score.total
+        return "#{shown.passed}/#{shown.total}" if shown.total == score.total
 
-        "#{shown.passed}/#{shown.total} visible, #{score.passed}/#{score.total} overall#{sealed_summary(score)}"
-      end
-
-      def sealed_summary(score)
-        sealed = score.only(SEALED)
-        return "" if sealed.total.zero?
-
-        ", sealed #{sealed.passed}/#{sealed.total}"
+        "#{shown.passed}/#{shown.total} visible, #{score.passed}/#{score.total} overall"
       end
 
       def challenger_path(number)
spec/evals/support/scorer.rb
@@ -31,10 +31,6 @@ module Elelem
       def excluding(*groups)
         Score.new(results: results.reject { |result| groups.include?(result.group) })
       end
-
-      def only(*groups)
-        Score.new(results: results.select { |result| groups.include?(result.group) })
-      end
     end
 
     class Scorer