From 653510aab4376ab8022647e446ebec87d8bb1082 Mon Sep 17 00:00:00 2001 From: Dotta Date: Sun, 6 Sep 2026 12:19:31 -0500 Subject: [PATCH] fix(evals): fail closed without maintained campaign --- .../scripts/runner-protocol-eval-campaign.mjs | 8 +------ .../runner-protocol-eval-campaign.test.mjs | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/packages/paperclip-runner/scripts/runner-protocol-eval-campaign.mjs b/packages/paperclip-runner/scripts/runner-protocol-eval-campaign.mjs index 360472ae32..13ccfbb108 100644 --- a/packages/paperclip-runner/scripts/runner-protocol-eval-campaign.mjs +++ b/packages/paperclip-runner/scripts/runner-protocol-eval-campaign.mjs @@ -79,13 +79,7 @@ function parseRosterSelection(value) { async function maintainedRosterSelection(programRoot) { const campaignPath = resolve(programRoot, "campaigns/live-direct-full.json"); - let campaign; - try { - campaign = await loadObject(campaignPath); - } catch (error) { - if (error?.code === "ENOENT") return null; - throw error; - } + const campaign = await loadObject(campaignPath); if ( campaign.schema !== "paperclip-runner/live-campaign/v1" || !Array.isArray(campaign.lanes) diff --git a/packages/paperclip-runner/scripts/runner-protocol-eval-campaign.test.mjs b/packages/paperclip-runner/scripts/runner-protocol-eval-campaign.test.mjs index 511ed41c64..0703d3de7d 100644 --- a/packages/paperclip-runner/scripts/runner-protocol-eval-campaign.test.mjs +++ b/packages/paperclip-runner/scripts/runner-protocol-eval-campaign.test.mjs @@ -187,6 +187,29 @@ test("all selects the maintained enabled campaign and explicit diagnostics can s ); }); +test("all fails closed when the maintained campaign is missing", async () => { + const { root, program } = await fixture(); + await rm(join(program, "campaigns/live-direct-full.json")); + + await assert.rejects( + buildProtocolEvalCatalog({ + evalsRoot: root, + campaignId: "gha-42-1", + }), + /ENOENT/, + ); + + const diagnostic = await buildProtocolEvalCatalog({ + evalsRoot: root, + campaignId: "gha-42-2", + rosterSelection: "protocol-live-opencode-model", + }); + assert.deepEqual( + diagnostic.rosters.map((roster) => roster.rosterId), + ["protocol-live-opencode-model"], + ); +}); + test("aggregates retained attempts and synthesizes missing cells as infrastructure", async () => { const { root, config, evalCase } = await fixture(); const catalog = await buildProtocolEvalCatalog({