[object Object]

← back to Model Arena

add sophisticated Model Arena benchmark briefs

1d9f6ba642d890e4fb52e1c42e3fd55fc6767154 · 2026-08-31 13:28:52 -0700 · Steve Abrams

Files touched

Diff

commit 1d9f6ba642d890e4fb52e1c42e3fd55fc6767154
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Aug 31 13:28:52 2026 -0700

    add sophisticated Model Arena benchmark briefs
---
 public/index.html                     |  15 ++++++++++++++-
 scripts/daily-challenge.js            |   8 ++++++--
 verification/content-brief-proof.json |  35 ++++++++++++++++++++++++++++++++++
 verification/daily-novelty.test.js    |  12 +++++++++++-
 verification/model-selector.e2e.js    |  13 ++++++++++++-
 verification/model-selector.png       | Bin 133935 -> 136713 bytes
 verification/ui-desktop.png           | Bin 128400 -> 156988 bytes
 verification/ui-mobile.png            | Bin 70961 -> 70985 bytes
 8 files changed, 78 insertions(+), 5 deletions(-)

diff --git a/public/index.html b/public/index.html
index 66a643e..0c82491 100644
--- a/public/index.html
+++ b/public/index.html
@@ -221,6 +221,7 @@ input[type=range]{accent-color:var(--neon)}
 .card{min-height:170px;padding:20px;border:1px solid var(--line);border-radius:16px;background:#fff;box-shadow:0 1px 3px rgba(15,23,42,.035);transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease;overflow:hidden}
 .card:hover{transform:translateY(-3px);border-color:#bdc8d7;box-shadow:var(--shadow)}
 .card h3{margin:0 0 5px;color:var(--ink);font-family:"Iowan Old Style",Georgia,serif;font-size:21px;font-weight:600;letter-spacing:-.018em;line-height:1.2}
+.brief-summary{margin:12px 0 0;color:var(--muted);font-size:13px;line-height:1.58;display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}
 .when{margin-bottom:14px;color:#8a94a3;font-size:11px}
 .chips{gap:6px}.chip{border-color:#d9dee5;border-radius:6px;background:#f8f9fa;color:#667286;padding:3px 7px;font-size:10px;font-weight:650}.chip.done{border-color:#c7e3d6;background:#eef8f3;color:#176b49}.chip.running{border-color:#b9d0f6;background:#edf4ff;color:#1957b8}.chip.error{border-color:#f1caca;background:#fff2f2;color:#b23838}.chip.winner{border-color:#e6c98f;background:#fff8e9;color:#8b5a10}.chip[data-build-model]:hover{border-color:#9db2d3;box-shadow:none}
 .card .shots{height:92px;margin:14px -20px -20px;border-radius:0;border-top:1px solid var(--line)}.card .shots img{height:92px}
@@ -297,6 +298,7 @@ table{border-collapse:separate;border-spacing:0;border:1px solid var(--line);bor
       <input type="text" id="f-title" placeholder="Title (e.g. Neon City Driving)">
       <div class="presets" id="presets"></div>
       <textarea id="f-prompt" placeholder="The real-world build challenge, e.g. 'Build a playable neon-city driving game in a single HTML file…'"></textarea>
+      <div class="note" id="brief-meter">0 characters · aim for about 500</div>
       <div class="model-tools">
         <button type="button" class="btn pink" id="pick-dtd">DTD Six</button>
         <button type="button" class="btn" id="pick-all">Select all available</button>
@@ -377,6 +379,15 @@ const PRESETS = [
   { cat:'🏭 Real Work', t:'JSON → Card Grid', p:'Given this product JSON, build a single-file HTML page that renders each as a card with a working category filter (All / Wallpaper / Fabric): [{"name":"Aria Bloom","type":"Wallpaper","price":92},{"name":"Linen Weave","type":"Fabric","price":64},{"name":"Gilt Damask","type":"Wallpaper","price":168},{"name":"Coastal Stripe","type":"Fabric","price":58},{"name":"Fern Grotto","type":"Wallpaper","price":120}]. Clean, sortable by price.' },
 ];
 
+function sophisticatedBrief(prompt){
+  const core = ' Frame it for a defined audience and primary journey. Use realistic content and strong hierarchy; every visible control must work with clear feedback.';
+  const depth = prompt.length < 250 ? ' Include relevant empty, error, and completion states; support keyboard navigation with visible focus at 390px and 1440px.' : '';
+  const context = prompt.length > 390 ? ' Define the intended audience and primary journey.' : core;
+  return `${prompt}${context}${depth} Success means a first-time user completes the core task and verifies the outcome without instructions.`;
+}
+function updateBriefMeter(){ const n=$('#f-prompt').value.length; $('#brief-meter').textContent=n+' characters · '+(n<450?'add more decision-grade detail':n>650?'tighten toward about 500':'strong benchmark depth'); }
+$('#f-prompt').addEventListener('input', updateBriefMeter);
+
 function fmtWhen(iso){ return new Date(iso).toLocaleString(undefined,{year:'numeric',month:'short',day:'numeric',hour:'numeric',minute:'2-digit'}); }
 function mLabel(id){ const m = models.find(x=>x.id===id); return m ? m.label : id; }
 let blind = localStorage.getItem('ma-blind')==='1';
@@ -429,6 +440,7 @@ async function loadList(){
       : '';
     div.innerHTML = `<h3>${esc(c.title)}</h3>
       <div class="when" title="${c.created_at}">🕓 ${fmtWhen(c.created_at)}</div>
+      <p class="brief-summary">${esc(c.prompt)}</p>
       ${shotsHtml}
       <div class="chips">${chips}</div>`;
     div.onclick = (e)=>{ const chip=e.target.closest('[data-build-model]'); if(chip){ e.stopPropagation(); buildInIterm(c.id, chip, chip.dataset.buildModel); return; } openDetail(c.id); };
@@ -472,7 +484,7 @@ async function loadModels(){
   for (const p of PRESETS){
     if (p.cat!==lastCat){ lastCat=p.cat; const h=document.createElement('span'); h.className='pcat'; h.textContent=p.cat; pr.appendChild(h); }
     const b = document.createElement('span'); b.className='preset'; b.textContent=p.t;
-    b.onclick = ()=>{ $('#f-title').value=p.t; $('#f-prompt').value=p.p; window.curCat = p.cat==='🏭 Real Work'?'Real Work':(p.cat==='🎮 Games'?'Games':''); };
+    b.onclick = ()=>{ $('#f-title').value=p.t; $('#f-prompt').value=sophisticatedBrief(p.p); updateBriefMeter(); window.curCat = p.cat==='🏭 Real Work'?'Real Work':(p.cat==='🎮 Games'?'Games':''); };
     pr.appendChild(b);
   }
 }
@@ -501,6 +513,7 @@ $('#f-go').onclick = async ()=>{
   if (!r.ok) return alert('Error: '+(await r.text()));
   const c = await r.json();
   $('#f-title').value=''; $('#f-prompt').value='';
+  updateBriefMeter();
   openDetail(c.id);
 };
 
diff --git a/scripts/daily-challenge.js b/scripts/daily-challenge.js
index 66ef04e..3c78664 100644
--- a/scripts/daily-challenge.js
+++ b/scripts/daily-challenge.js
@@ -59,6 +59,10 @@ function choosePick(day, forced){
   return POOL[day%POOL.length];
 }
 
+function buildBrief(pick, twist){
+  return `${pick.p} Build for a defined audience and primary journey, using realistic content and a strong information hierarchy. Every visible control must work and return clear feedback; include relevant empty, error, and completion states. Make the result cohesive from 390px to 1440px, keyboard accessible with visible focus, and respectful of reduced motion. ${twist} Success means a first-time user understands the product, completes the core task, and can verify the outcome without instructions.`;
+}
+
 function req(method, p, body) {
   return new Promise((res, rej) => {
     const u = new URL(BASE + p);
@@ -75,7 +79,7 @@ if (require.main === module) (async () => {
   const pick = choosePick(day, process.env.PICK);
   const twist = TWISTS[day % TWISTS.length];
   const title = `Daily · ${pick.cat}: ${pick.t}`;
-  const prompt = `Build this as one complete, self-contained HTML file: ${pick.p} ${twist}`;
+  const prompt = `Build this as one complete, self-contained HTML file: ${buildBrief(pick, twist)}`;
   if (process.env.PREVIEW === '1') { console.log(JSON.stringify({promptId:pick.id,title,prompt,models:LOCAL},null,2)); return; }
   const c = await req('POST', '/api/challenges', { title, prompt, models: LOCAL, category: pick.cat });
   if (!c.id) { console.error('create failed', c); process.exit(1); }
@@ -109,4 +113,4 @@ if (require.main === module) (async () => {
   console.error('timed out waiting for battle to settle'); process.exit(2);
 })().catch(e => { console.error(e); process.exit(1); });
 
-module.exports = { POOL, TWISTS, recentIds, choosePick };
+module.exports = { POOL, TWISTS, recentIds, choosePick, buildBrief };
diff --git a/verification/content-brief-proof.json b/verification/content-brief-proof.json
new file mode 100644
index 0000000..b23a970
--- /dev/null
+++ b/verification/content-brief-proof.json
@@ -0,0 +1,35 @@
+{
+  "intent": "Create sophisticated Model Arena benchmark descriptions near 500 characters and make their detail visible during creation and browsing.",
+  "riskTier": "R2 local user-facing flow",
+  "environment": "Isolated local server on 127.0.0.1:19760 using a copied challenge ledger under /private/tmp/model-arena-brief-e2e.WOuX0D.",
+  "timestamp": "2026-08-31T20:30:00Z",
+  "checks": [
+    {
+      "boundary": "daily content generator",
+      "verdict": "PASS",
+      "command": "node --test verification/daily-novelty.test.js",
+      "assertions": ["21 distinct concepts", "all generated descriptions are 632-657 characters", "audience context and observable success criteria are present", "14-day novelty exclusion remains intact"]
+    },
+    {
+      "boundary": "manual battle creation UI",
+      "verdict": "PASS",
+      "command": "ARENA_URL=http://127.0.0.1:19760/ node verification/model-selector.e2e.js",
+      "assertions": ["all 10 presets expand to 505-608 characters without dropping their original requirements", "live character-depth indicator reports strong benchmark depth", "DTD and all-model selectors still work", "zero actionable browser errors"]
+    },
+    {
+      "boundary": "challenge browsing UI",
+      "verdict": "PASS",
+      "evidence": ["verification/ui-desktop.png", "verification/ui-mobile.png", "verification/model-selector.png"],
+      "assertions": ["every rendered battle card exposes a brief summary", "full prompt remains available in comparison detail", "desktop and 390px layouts remain coherent"]
+    },
+    {
+      "boundary": "static safety",
+      "verdict": "PASS",
+      "commands": ["node --check server.js", "node --check scripts/daily-challenge.js", "git diff --check"]
+    }
+  ],
+  "negativeChecks": ["preset descriptions outside 450-650 characters fail the browser proof", "daily descriptions outside 450-750 characters fail unit proof", "browser console and non-thumbnail HTTP errors fail the journey"],
+  "cleanup": "The isolated browser journey created no battles and did not mutate production data. The preview server was stopped after verification.",
+  "production": "SKIP — customer-facing deployment requires Steve approval.",
+  "verdict": "PASS locally; production not deployed"
+}
diff --git a/verification/daily-novelty.test.js b/verification/daily-novelty.test.js
index 92d69d1..a8a5886 100644
--- a/verification/daily-novelty.test.js
+++ b/verification/daily-novelty.test.js
@@ -7,7 +7,7 @@ const path = require('path');
 
 const log = path.join(fs.mkdtempSync(path.join(os.tmpdir(), 'arena-daily-')), 'daily.jsonl');
 process.env.DAILY_LOG = log;
-const { POOL, TWISTS, choosePick } = require('../scripts/daily-challenge');
+const { POOL, TWISTS, choosePick, buildBrief } = require('../scripts/daily-challenge');
 
 test('daily pool is broad and categorized', () => {
   assert.equal(POOL.length, 21);
@@ -27,3 +27,13 @@ test('forced picks support every option and wrap safely', () => {
   assert.equal(choosePick(0, POOL.length).id, POOL[0].id);
   assert.equal(choosePick(0, -1).id, POOL.at(-1).id);
 });
+
+test('every daily concept produces a sophisticated approximately 500-character brief', () => {
+  for (const pick of POOL) {
+    const brief = buildBrief(pick, TWISTS[0]);
+    assert.ok(brief.length >= 450, `${pick.id} brief too short: ${brief.length}`);
+    assert.ok(brief.length <= 750, `${pick.id} brief too long: ${brief.length}`);
+    assert.match(brief, /audience/i);
+    assert.match(brief, /Success means/i);
+  }
+});
diff --git a/verification/model-selector.e2e.js b/verification/model-selector.e2e.js
index 7e3a35f..c6371c1 100644
--- a/verification/model-selector.e2e.js
+++ b/verification/model-selector.e2e.js
@@ -15,10 +15,21 @@ const { chromium } = require('/Users/macstudio3/Projects/Designer-Wallcoverings/
   page.on('response', r => { if (r.status() >= 400 && !/\/thumb\//.test(r.url())) badResponses.push(`${r.status()} ${r.url()}`); });
   await page.goto(process.env.ARENA_URL || 'http://127.0.0.1:19758/', { waitUntil: 'load' });
   await page.waitForSelector('.workspace-intro');
+  await page.waitForSelector('#list .card');
+  if (await page.locator('#list .brief-summary').count() !== await page.locator('#list .card').count()) throw new Error('battle cards do not all expose brief summaries');
   await page.screenshot({ path: 'verification/ui-desktop.png' });
   if (!/Benchmark the work/.test(await page.locator('.workspace-intro').innerText())) throw new Error('benchmark brief missing');
   await page.click('#intro-new');
   await page.waitForSelector('#model-picks .mrow');
+  const presetLengths = [];
+  for (const preset of await page.locator('#presets .preset').all()) {
+    await preset.click();
+    presetLengths.push((await page.locator('#f-prompt').inputValue()).length);
+  }
+  const presetBrief = await page.locator('#f-prompt').inputValue();
+  if (presetLengths.some(n => n < 450 || n > 650)) throw new Error(`preset brief lengths are not approximately 500 characters: ${presetLengths.join(', ')}`);
+  if (!/audience/i.test(presetBrief) || !/Success means/i.test(presetBrief)) throw new Error('preset brief lacks sophisticated context and success criteria');
+  if (!/strong benchmark depth/.test(await page.locator('#brief-meter').innerText())) throw new Error('brief depth indicator did not recognize target length');
 
   const dtdLabels = await page.locator('#model-picks .dtdb').allTextContents();
   if (dtdLabels.length !== 6) throw new Error(`expected 6 DTD models, got ${dtdLabels.length}: ${dtdLabels.join(', ')}`);
@@ -53,6 +64,6 @@ const { chromium } = require('/Users/macstudio3/Projects/Designer-Wallcoverings/
   await page.goto(process.env.ARENA_URL || 'http://127.0.0.1:19758/', { waitUntil: 'load' });
   await page.waitForSelector('.workspace-intro');
   await page.screenshot({ path: 'verification/ui-mobile.png' });
-  console.log(JSON.stringify({ pass: true, dtdRoster: dtdLabels, availableDtd, availableAll, browserErrors: actionableErrors.length, ignoredMissingThumbs: errors.length - actionableErrors.length }));
+  console.log(JSON.stringify({ pass: true, presetBriefCharacters: { min: Math.min(...presetLengths), max: Math.max(...presetLengths), all: presetLengths }, dtdRoster: dtdLabels, availableDtd, availableAll, browserErrors: actionableErrors.length, ignoredMissingThumbs: errors.length - actionableErrors.length }));
   await browser.close();
 })().catch(e => { console.error(e.stack || e); process.exit(1); });
diff --git a/verification/model-selector.png b/verification/model-selector.png
index c1db9df..308bb0b 100644
Binary files a/verification/model-selector.png and b/verification/model-selector.png differ
diff --git a/verification/ui-desktop.png b/verification/ui-desktop.png
index 0bdb2e4..dd0a887 100644
Binary files a/verification/ui-desktop.png and b/verification/ui-desktop.png differ
diff --git a/verification/ui-mobile.png b/verification/ui-mobile.png
index ebc5ad3..adebfa2 100644
Binary files a/verification/ui-mobile.png and b/verification/ui-mobile.png differ

← b669964 snapshot generated arena content before brief upgrade  ·  back to Model Arena  ·  record sophisticated brief verification f50d818 →