← back to Model Arena
Add ARENA_PAUSED gate: serve UI + results with zero model runs / zero spend
75c9bd6627edc96ff31cdac5a811c0d2703210ae · 2026-09-23 08:44:59 -0700 · Steve Abrams
Gates runModel() (the sole dispatch chokepoint for new/rerun/boot-resume runs)
and skips the boot resume-collection so paused restarts don't burn the resume
budget. Lets the arena come back up read-only without spending on metered LLMs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
Diff
commit 75c9bd6627edc96ff31cdac5a811c0d2703210ae
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Sep 23 08:44:59 2026 -0700
Add ARENA_PAUSED gate: serve UI + results with zero model runs / zero spend
Gates runModel() (the sole dispatch chokepoint for new/rerun/boot-resume runs)
and skips the boot resume-collection so paused restarts don't burn the resume
budget. Lets the arena come back up read-only without spending on metered LLMs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
server.js | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/server.js b/server.js
index b023560..1d4b81a 100644
--- a/server.js
+++ b/server.js
@@ -36,6 +36,9 @@ function shootThumb(htmlPath, outPng, cb) {
const PORT = parseInt(process.env.PORT || '9758', 10);
const BASIC_AUTH = process.env.BASIC_AUTH !== undefined ? process.env.BASIC_AUTH : 'admin:DW2024!';
+// ARENA_PAUSED=1 serves the UI + existing results read-only but runs NO model challenges
+// (no boot-resume of interrupted runs, no new/rerun dispatch) — zero metered spend while up.
+const ARENA_PAUSED = /^(1|true|yes|on)$/i.test(process.env.ARENA_PAUSED || '');
const DIR = __dirname;
// DATA_DIR keeps verification and canary servers from touching the live arena ledger.
const DATA = process.env.DATA_DIR ? path.resolve(process.env.DATA_DIR) : path.join(DIR, 'data');
@@ -141,6 +144,7 @@ const MAX_RESUMES = 4;
const resumeOnBoot = [];
for (const c of challenges) {
if (c.judging) c.judging = false; // a restart mid-judge would otherwise block judging forever
+ if (ARENA_PAUSED) continue; // paused: don't burn the resume budget — leave interrupted runs for a later unpaused boot
for (const r of c.runs) {
const corrupt = r.started_at && r.finished_at && r.finished_at < r.started_at;
const interrupted = r.status === 'running' || r.status === 'queued' ||
@@ -580,6 +584,7 @@ function maybeAutoJudge(challenge) {
}
function runModel(challenge, modelId) {
+ if (ARENA_PAUSED) return; // paused: never dispatch a model run (no metered spend)
const m = MODELS.find(x => x.id === modelId);
const run = challenge.runs.find(r => r.model === modelId);
if (!m || !run) return;
@@ -1072,8 +1077,8 @@ iframe{width:100%;height:460px;border:0;background:#000}.c.win iframe{height:560
});
server.listen(PORT, function () {
- console.log('[model-arena] http://localhost:' + this.address().port + (BASIC_AUTH ? ' (basic auth on)' : ''));
- if (resumeOnBoot.length) {
+ console.log('[model-arena] http://localhost:' + this.address().port + (BASIC_AUTH ? ' (basic auth on)' : '') + (ARENA_PAUSED ? ' [CHALLENGES PAUSED — no model runs, no spend]' : ''));
+ if (!ARENA_PAUSED && resumeOnBoot.length) {
console.log('[model-arena] resuming ' + resumeOnBoot.length + ' run(s) interrupted by restart');
for (const j of resumeOnBoot) runModel(j.c, j.model);
}
← 8fb3efb auto-data-snapshot: 2026-09-22T09:54:34 (3 data files) — dat
·
back to Model Arena
·
auto-data-snapshot: 2026-09-23T08:59:35 (1 data files) — dat 969f6b3 →