← back to Model Arena
ALL-MUST-WORK: local models (qwen3-14b, hermes3-8b) use design PACK not the live tool loop — 8B/14B returned 0 chars through function-calling; API models keep the tool loop
f4b407f731bf4f96b4315bc560f293631efa68b1 · 2026-07-25 01:46:25 -0700 · Steve Abrams
Files touched
A data/artifacts/327c5eb5b964/qwen3-14b.htmlA data/artifacts/327c5eb5b964/qwen3-14b.pngA data/artifacts/5410cf08e245/gpt.htmlA data/artifacts/5410cf08e245/gpt.pngM data/challenges.jsonM data/costlog.jsonlM server.js
Diff
commit f4b407f731bf4f96b4315bc560f293631efa68b1
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sat Jul 25 01:46:25 2026 -0700
ALL-MUST-WORK: local models (qwen3-14b, hermes3-8b) use design PACK not the live tool loop — 8B/14B returned 0 chars through function-calling; API models keep the tool loop
---
data/artifacts/327c5eb5b964/qwen3-14b.html | 224 +++++++
data/artifacts/327c5eb5b964/qwen3-14b.png | Bin 0 -> 10935 bytes
data/artifacts/5410cf08e245/gpt.html | 993 +++++++++++++++++++++++++++++
data/artifacts/5410cf08e245/gpt.png | Bin 0 -> 128900 bytes
data/challenges.json | 205 +++---
data/costlog.jsonl | 1 +
server.js | 8 +-
7 files changed, 1347 insertions(+), 84 deletions(-)
diff --git a/data/artifacts/327c5eb5b964/qwen3-14b.html b/data/artifacts/327c5eb5b964/qwen3-14b.html
new file mode 100644
index 0000000..49776ed
--- /dev/null
+++ b/data/artifacts/327c5eb5b964/qwen3-14b.html
@@ -0,0 +1,224 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="UTF-8">
+ <title>Neon Noir Drive</title>
+ <style>
+ html, body {
+ margin: 0;
+ padding: 0;
+ overflow: hidden;
+ background-color: #000;
+ font-family: 'Courier New', Courier, monospace;
+ color: #00ffcc;
+ }
+
+ canvas {
+ display: block;
+ }
+
+ #score {
+ position: absolute;
+ top: 10px;
+ left: 10px;
+ font-size: 24px;
+ text-shadow: 0 0 10px #00ffcc;
+ pointer-events: none;
+ }
+ </style>
+</head>
+<body>
+ <div id="score">Score: 0</div>
+ <canvas id="gameCanvas"></canvas>
+
+ <script>
+ const canvas = document.getElementById('gameCanvas');
+ const ctx = canvas.getContext('2d');
+ const scoreDisplay = document.getElementById('score');
+
+ canvas.width = window.innerWidth;
+ canvas.height = window.innerHeight;
+
+ let carX = canvas.width / 2 - 25;
+ let carY = canvas.height - 75;
+ let carSpeed = 5;
+ let carWidth = 50;
+ let carHeight = 50;
+
+ let roadY = 0;
+ let roadSpeed = 4;
+
+ let obstacles = [];
+ let buildings = [];
+ let score = 0;
+ let gameOver = false;
+
+ const carColor = '#00ffcc';
+
+ const keys = {};
+ window.addEventListener('keydown', e => keys[e.key] = true);
+ window.addEventListener('keyup', e => keys[e.key] = false);
+
+ function drawCar(x, y) {
+ ctx.fillStyle = carColor;
+ ctx.beginPath();
+ ctx.moveTo(x, y);
+ ctx.lineTo(x + 30, y + 15);
+ ctx.lineTo(x + 10, y + 30);
+ ctx.lineTo(x, y + 15);
+ ctx.closePath();
+ ctx.fill();
+ }
+
+ function drawBuilding(x, y, width, height, color) {
+ ctx.fillStyle = color;
+ ctx.fillRect(x, y, width, height);
+ }
+
+ function drawObstacle(x, y, width, height, color) {
+ ctx.fillStyle = color;
+ ctx.beginPath();
+ ctx.moveTo(x, y);
+ ctx.lineTo(x + width, y);
+ ctx.lineTo(x + width, y + height);
+ ctx.lineTo(x, y + height);
+ ctx.closePath();
+ ctx.fill();
+ }
+
+ function createObstacle() {
+ const width = 40 + Math.random() * 40;
+ const height = 40 + Math.random() * 40;
+ const x = Math.random() * (canvas.width - width - 50);
+ const y = -height;
+ const color = `hsl(${Math.random() * 360}, 100%, 60%)`;
+ obstacles.push({ x, y, width, height, color });
+ }
+
+ function createBuilding() {
+ const height = 100 + Math.random() * 150;
+ const width = 80 + Math.random() * 100;
+ const x = Math.random() * (canvas.width - width);
+ const y = -height;
+ const color = `hsl(${Math.random() * 360}, 80%, 50%)`;
+ buildings.push({ x, y, width, height, color });
+ }
+
+ function updateObstacles() {
+ for (let i = obstacles.length - 1; i >= 0; i--) {
+ obstacles[i].y += roadSpeed;
+ if (obstacles[i].y > canvas.height) {
+ obstacles.splice(i, 1);
+ }
+ }
+ }
+
+ function updateBuildings() {
+ for (let i = buildings.length - 1; i >= 0; i--) {
+ buildings[i].y += roadSpeed;
+ if (buildings[i].y > canvas.height) {
+ buildings.splice(i, 1);
+ }
+ }
+ }
+
+ function checkCollision(x1, y1, w1, h1, x2, y2, w2, h2) {
+ return !(
+ x1 + w1 < x2 ||
+ x1 > x2 + w2 ||
+ y1 + h1 < y2 ||
+ y1 > y2 + h2
+ );
+ }
+
+ function update() {
+ if (gameOver) return;
+
+ carX += (keys['ArrowRight'] ? carSpeed : 0) + (keys['ArrowLeft'] ? -carSpeed : 0);
+ carX = Math.max(0, Math.min(canvas.width - carWidth, carX));
+
+ if (keys['ArrowUp']) {
+ carY -= carSpeed;
+ } else if (keys['ArrowDown']) {
+ carY += carSpeed;
+ }
+
+ roadY += roadSpeed;
+
+ if (Math.random() < 0.01) createObstacle();
+ if (Math.random() < 0.02) createBuilding();
+
+ updateObstacles();
+ updateBuildings();
+
+ for (let obstacle of obstacles) {
+ if (checkCollision(carX, carY, carWidth, carHeight, obstacle.x, obstacle.y, obstacle.width, obstacle.height)) {
+ gameOver = true;
+ }
+ }
+
+ score++;
+ scoreDisplay.textContent = "Score: " + score;
+ }
+
+ function draw() {
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+ // Road
+ ctx.fillStyle = '#000';
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+
+ // Road lines
+ ctx.strokeStyle = '#00ffcc';
+ ctx.lineWidth = 3;
+ ctx.setLineDash([20, 10]);
+ ctx.beginPath();
+ for (let i = 0; i < canvas.height; i += 20) {
+ ctx.moveTo(0, i + roadY);
+ ctx.lineTo(canvas.width, i + roadY);
+ }
+ ctx.stroke();
+ ctx.setLineDash([]);
+
+ // Buildings
+ for (let building of buildings) {
+ drawBuilding(building.x, building.y, building.width, building.height, building.color);
+ }
+
+ // Obstacles
+ for (let obstacle of obstacles) {
+ drawObstacle(obstacle.x, obstacle.y, obstacle.width, obstacle.height, obstacle.color);
+ }
+
+ // Car
+ drawCar(carX, carY);
+
+ // Game Over
+ if (gameOver) {
+ ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+ ctx.fillStyle = '#00ffcc';
+ ctx.font = '48px "Courier New", Courier, monospace';
+ ctx.textAlign = 'center';
+ ctx.fillText('Game Over', canvas.width / 2, canvas.height / 2);
+ ctx.font = '24px "Courier New", Courier, monospace';
+ ctx.fillText('Press R to restart', canvas.width / 2, canvas.height / 2 + 40);
+ }
+ }
+
+ function gameLoop() {
+ update();
+ draw();
+ requestAnimationFrame(gameLoop);
+ }
+
+ window.addEventListener('keydown', (e) => {
+ if (gameOver && e.key === 'r') {
+ location.reload();
+ }
+ });
+
+ gameLoop();
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/327c5eb5b964/qwen3-14b.png b/data/artifacts/327c5eb5b964/qwen3-14b.png
new file mode 100644
index 0000000..f3e1191
Binary files /dev/null and b/data/artifacts/327c5eb5b964/qwen3-14b.png differ
diff --git a/data/artifacts/5410cf08e245/gpt.html b/data/artifacts/5410cf08e245/gpt.html
new file mode 100644
index 0000000..a81ad75
--- /dev/null
+++ b/data/artifacts/5410cf08e245/gpt.html
@@ -0,0 +1,993 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8" />
+<title>Designer Wallcoverings Memory</title>
+<style>
+:root {
+ --bg: #0d0d0f;
+ --surface: #17171c;
+ --surface-soft: #1f1f26;
+ --text: #f5f2ea;
+ --muted: #8a8578;
+ --accent: #c9a961;
+ --accent-soft: #7d6a45;
+
+ --radius-card: 10px;
+ --radius-soft: 18px;
+ --shadow-soft: 0 22px 60px rgba(0, 0, 0, 0.55);
+ --shadow-subtle: 0 12px 30px rgba(0, 0, 0, 0.45);
+ --border-hairline: 1px solid rgba(201,169,97,0.32);
+
+ --font-display: "Playfair Display", "Didot", "Bodoni MT", Georgia, serif;
+ --font-serif: "Playfair Display", "EB Garamond", "Cormorant Garamond", Georgia, serif;
+ --font-sans: "Avenir Next", "Century Gothic", "Segoe UI", system-ui, sans-serif;
+
+ --fs-caption: 12px;
+ --fs-body: 16px;
+ --fs-lead: 21px;
+ --fs-h3: 28px;
+ --fs-h2: 38px;
+ --fs-h1: 50px;
+
+ --easing-swift-out: cubic-bezier(.22,.9,.24,1);
+ --easing-hero: cubic-bezier(.22,1,.36,1);
+}
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+html, body {
+ margin: 0;
+ padding: 0;
+ height: 100%;
+ background: radial-gradient(circle at top, #272733 0, #0d0d0f 55%);
+ color: var(--text);
+ font-family: var(--font-sans);
+}
+
+body {
+ display: flex;
+ flex-direction: column;
+}
+
+/* Top bar */
+.top-bar {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 64px;
+ padding: 0 36px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ backdrop-filter: blur(16px);
+ background: linear-gradient(to bottom, rgba(13,13,15,0.96), rgba(13,13,15,0.82));
+ border-bottom: 1px solid rgba(201,169,97,0.32);
+ z-index: 20;
+}
+
+.wordmark {
+ font-family: var(--font-serif);
+ font-size: 15px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--text);
+ white-space: nowrap;
+}
+
+.top-bar-meta {
+ display: flex;
+ gap: 18px;
+ font-size: 11px;
+ text-transform: uppercase;
+ letter-spacing: 0.14em;
+ color: var(--muted);
+}
+
+.top-bar-meta span {
+ padding: 4px 10px;
+ border-radius: 999px;
+ border: 1px solid rgba(138,133,120,0.6);
+}
+
+/* Layout */
+.main {
+ flex: 1;
+ padding: 96px 24px 32px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.shell {
+ width: 100%;
+ max-width: 980px;
+ display: grid;
+ grid-template-columns: minmax(0, 3fr) minmax(260px, 1.6fr);
+ gap: 32px;
+ align-items: stretch;
+}
+
+@media (max-width: 900px) {
+ .shell {
+ grid-template-columns: minmax(0, 1fr);
+ }
+}
+
+/* Panel styles */
+.panel {
+ background: radial-gradient(circle at top left, rgba(201,169,97,0.16), transparent 55%), var(--surface);
+ border-radius: var(--radius-soft);
+ border: var(--border-hairline);
+ box-shadow: var(--shadow-soft);
+ padding: 22px 22px 24px;
+ position: relative;
+ overflow: hidden;
+}
+
+.panel::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ pointer-events: none;
+ background:
+ linear-gradient(120deg, rgba(255,255,255,0.08), transparent 22%, transparent 78%, rgba(255,255,255,0.02));
+ mix-blend-mode: soft-light;
+ opacity: 0.75;
+}
+
+/* Heading block */
+.panel-header {
+ position: relative;
+ display: flex;
+ justify-content: space-between;
+ align-items: baseline;
+ margin-bottom: 18px;
+ z-index: 1;
+}
+
+.panel-title {
+ font-family: var(--font-display);
+ font-size: 26px;
+ letter-spacing: 0.06em;
+ text-transform: uppercase;
+ margin: 0;
+}
+
+.panel-subtitle {
+ font-size: 12px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+/* Stats row */
+.stats {
+ position: relative;
+ display: flex;
+ gap: 18px;
+ align-items: center;
+ margin-bottom: 16px;
+ padding-bottom: 14px;
+ border-bottom: 1px solid rgba(138,133,120,0.35);
+ z-index: 1;
+}
+
+.stat-block {
+ display: flex;
+ flex-direction: column;
+ gap: 3px;
+}
+
+.stat-label {
+ font-size: 11px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+.stat-value {
+ font-family: var(--font-display);
+ font-size: 19px;
+}
+
+/* Control buttons */
+.controls {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+ margin-left: auto;
+}
+
+.btn {
+ position: relative;
+ border-radius: 999px;
+ padding: 7px 16px 8px;
+ border: 1px solid rgba(201,169,97,0.6);
+ background: radial-gradient(circle at top, rgba(201,169,97,0.28), rgba(125,106,69,0.9));
+ color: #0b0b0d;
+ font-size: 11px;
+ font-weight: 600;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ cursor: pointer;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 6px;
+ outline: none;
+ box-shadow: 0 10px 25px rgba(0,0,0,0.65);
+ transition:
+ background 160ms var(--easing-swift-out),
+ transform 160ms var(--easing-swift-out),
+ box-shadow 160ms var(--easing-swift-out),
+ border-color 160ms var(--easing-swift-out);
+}
+
+.btn span.bullet {
+ width: 4px;
+ height: 4px;
+ border-radius: 50%;
+ background: #0b0b0d;
+}
+
+.btn:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 14px 30px rgba(0,0,0,0.75);
+ border-color: rgba(255,231,178,0.9);
+}
+
+.btn:active {
+ transform: translateY(0);
+ box-shadow: 0 8px 18px rgba(0,0,0,0.7);
+}
+
+/* Game grid */
+.grid {
+ position: relative;
+ z-index: 1;
+ display: grid;
+ grid-template-columns: repeat(4, minmax(0, 1fr));
+ gap: 14px;
+ margin-top: 4px;
+}
+
+@media (max-width: 900px) {
+ .grid {
+ gap: 10px;
+ }
+}
+
+/* Card */
+.card {
+ position: relative;
+ cursor: pointer;
+ perspective: 900px;
+ height: 0;
+ padding-bottom: 115%;
+}
+
+.card-inner {
+ position: absolute;
+ inset: 0;
+ transform-style: preserve-3d;
+ transition: transform 520ms var(--easing-swift-out);
+}
+
+.card.is-flipped .card-inner,
+.card.is-matched .card-inner {
+ transform: rotateY(180deg);
+}
+
+.card-face {
+ position: absolute;
+ inset: 0;
+ border-radius: var(--radius-card);
+ backface-visibility: hidden;
+ overflow: hidden;
+}
+
+/* Card back */
+.card-back {
+ background:
+ linear-gradient(135deg, rgba(201,169,97,0.22), transparent 40%, rgba(125,106,69,0.8)),
+ radial-gradient(circle at 10% 0, rgba(255,255,255,0.18), transparent 55%),
+ linear-gradient(135deg, #181821, #101015);
+ border: 1px solid rgba(201,169,97,0.5);
+ box-shadow: var(--shadow-subtle);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ position: relative;
+}
+
+.card-back::before {
+ content: "";
+ position: absolute;
+ inset: 10%;
+ border-radius: calc(var(--radius-card) - 2px);
+ border: 1px solid rgba(245,242,234,0.14);
+}
+
+/* Subtle monogram pattern on back */
+.card-back::after {
+ content: "DW";
+ font-family: var(--font-serif);
+ font-size: 17px;
+ letter-spacing: 0.28em;
+ text-transform: uppercase;
+ color: rgba(13,13,15,0.84);
+ text-shadow: 0 0 0 rgba(0,0,0,0.6);
+}
+
+/* Card front */
+.card-front {
+ transform: rotateY(180deg);
+ background: #101015;
+ border: 1px solid rgba(245,242,234,0.16);
+ box-shadow: var(--shadow-subtle);
+ display: flex;
+ flex-direction: column;
+}
+
+.card-front-header {
+ padding: 6px 10px 4px;
+ border-bottom: 1px solid rgba(138,133,120,0.5);
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background: radial-gradient(circle at top, rgba(201,169,97,0.18), transparent 75%);
+}
+
+.card-front-name {
+ font-family: var(--font-serif);
+ font-size: 12px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--text);
+ white-space: nowrap;
+}
+
+.card-front-tag {
+ font-size: 10px;
+ text-transform: uppercase;
+ letter-spacing: 0.18em;
+ color: var(--muted);
+}
+
+/* Swatch area */
+.card-swatch {
+ position: relative;
+ flex: 1;
+ overflow: hidden;
+}
+
+/* Pattern definitions */
+.pattern {
+ position: absolute;
+ inset: 0;
+ background-size: 24px 24px;
+ opacity: 0.96;
+}
+
+/* Damask: baroque floral using gradients + masks */
+.pattern-damask {
+ background-image:
+ radial-gradient(circle at 0 0, rgba(245,242,234,0.24) 0, rgba(245,242,234,0.24) 16%, transparent 18%),
+ radial-gradient(circle at 100% 100%, rgba(245,242,234,0.2) 0, rgba(245,242,234,0.2) 14%, transparent 16%),
+ radial-gradient(circle at 50% 50%, rgba(245,242,234,0.12) 0, rgba(245,242,234,0.12) 32%, transparent 34%);
+ background-color: #17171f;
+}
+
+/* Toile: sketchy pastoral stripes */
+.pattern-toile {
+ background-image:
+ repeating-linear-gradient(135deg, rgba(245,242,234,0.26) 0, rgba(245,242,234,0.26) 1px, transparent 1px, transparent 6px),
+ repeating-linear-gradient(180deg, rgba(201,169,97,0.14) 0, rgba(201,169,97,0.14) 2px, transparent 2px, transparent 14px);
+ background-color: #161621;
+}
+
+/* Ikat: blurred diamonds */
+.pattern-ikat {
+ background-image:
+ radial-gradient(circle at 0 50%, rgba(201,169,97,0.85) 0, rgba(201,169,97,0.85) 32%, transparent 40%),
+ radial-gradient(circle at 50% 0, rgba(245,242,234,0.9) 0, rgba(245,242,234,0.9) 26%, transparent 34%),
+ radial-gradient(circle at 100% 50%, rgba(201,169,97,0.75) 0, rgba(201,169,97,0.75) 30%, transparent 40%),
+ radial-gradient(circle at 50% 100%, rgba(245,242,234,0.75) 0, rgba(245,242,234,0.75) 25%, transparent 38%);
+ background-size: 44px 44px;
+ background-color: #101018;
+ filter: blur(0.2px);
+}
+
+/* Chinoiserie: fine branches + blossoms */
+.pattern-chinoiserie {
+ background-image:
+ radial-gradient(circle at 10% 20%, rgba(245,242,234,0.7) 0, rgba(245,242,234,0.7) 2px, transparent 3px),
+ radial-gradient(circle at 40% 70%, rgba(245,242,234,0.6) 0, rgba(245,242,234,0.6) 2px, transparent 3px),
+ radial-gradient(circle at 80% 30%, rgba(245,242,234,0.6) 0, rgba(245,242,234,0.6) 2px, transparent 3px),
+ repeating-linear-gradient(120deg, rgba(125,106,69,0.7) 0, rgba(125,106,69,0.7) 1px, transparent 1px, transparent 9px);
+ background-color: #151521;
+}
+
+/* Trellis: lattice */
+.pattern-trellis {
+ background-image:
+ linear-gradient(45deg, transparent 0, transparent 47%, rgba(245,242,234,0.65) 47%, rgba(245,242,234,0.65) 53%, transparent 53%),
+ linear-gradient(-45deg, transparent 0, transparent 47%, rgba(245,242,234,0.65) 47%, rgba(245,242,234,0.65) 53%, transparent 53%);
+ background-size: 26px 26px;
+ background-color: #101018;
+}
+
+/* Fret: Greek key style maze */
+.pattern-fret {
+ background-image:
+ linear-gradient(90deg, rgba(201,169,97,0.85) 2px, transparent 2px 12px, rgba(201,169,97,0.5) 12px 14px, transparent 14px),
+ linear-gradient(180deg, rgba(201,169,97,0.85) 2px, transparent 2px 12px, rgba(201,169,97,0.5) 12px 14px, transparent 14px);
+ background-size: 16px 16px;
+ background-color: #15151f;
+}
+
+/* Botanical: leaves & stems */
+.pattern-botanical {
+ background-image:
+ radial-gradient(circle at 10% 30%, rgba(245,242,234,0.85) 0, rgba(245,242,234,0.85) 3px, transparent 4px),
+ radial-gradient(circle at 35% 60%, rgba(245,242,234,0.65) 0, rgba(245,242,234,0.65) 3px, transparent 4px),
+ radial-gradient(circle at 70% 20%, rgba(245,242,234,0.75) 0, rgba(245,242,234,0.75) 3px, transparent 4px),
+ radial-gradient(circle at 80% 80%, rgba(245,242,234,0.75) 0, rgba(245,242,234,0.75) 3px, transparent 4px),
+ repeating-linear-gradient(145deg, rgba(125,106,69,0.85) 0, rgba(125,106,69,0.85) 1px, transparent 1px, transparent 7px);
+ background-color: #141821;
+}
+
+/* Stripe: tailored hotel stripe */
+.pattern-stripe {
+ background-image:
+ repeating-linear-gradient(90deg,
+ rgba(245,242,234,0.92) 0,
+ rgba(245,242,234,0.92) 3px,
+ rgba(201,169,97,0.85) 3px,
+ rgba(201,169,97,0.85) 4px,
+ #14141f 4px,
+ #14141f 13px);
+ background-color: #14141f;
+}
+
+/* Card overlays */
+.card-swatch::after {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background:
+ radial-gradient(circle at top, rgba(255,255,255,0.2), transparent 50%),
+ linear-gradient(to bottom, rgba(0,0,0,0.2), rgba(0,0,0,0.85));
+ mix-blend-mode: soft-light;
+ opacity: 0.7;
+}
+
+/* Win overlay */
+.win-overlay {
+ position: absolute;
+ inset: 0;
+ background: radial-gradient(circle at top, rgba(13,13,15,0.1), rgba(13,13,15,0.96));
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 5;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 380ms var(--easing-hero);
+}
+
+.win-overlay.is-visible {
+ opacity: 1;
+ pointer-events: auto;
+}
+
+.win-dialog {
+ background: radial-gradient(circle at top left, rgba(201,169,97,0.18), transparent 65%), var(--surface-soft);
+ border-radius: 18px;
+ border: 1px solid rgba(201,169,97,0.6);
+ padding: 26px 26px 22px;
+ max-width: 340px;
+ text-align: left;
+ box-shadow: 0 26px 80px rgba(0,0,0,0.86);
+ animation: scaleIn 520ms var(--easing-hero) both;
+}
+
+.win-label {
+ font-size: 11px;
+ letter-spacing: 0.2em;
+ text-transform: uppercase;
+ color: var(--muted);
+ margin-bottom: 8px;
+}
+
+.win-title {
+ font-family: var(--font-display);
+ font-size: 24px;
+ margin: 0 0 8px;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+}
+
+.win-body {
+ font-size: 13px;
+ line-height: 1.6;
+ color: var(--muted);
+ margin-bottom: 14px;
+}
+
+.win-metrics {
+ display: flex;
+ gap: 16px;
+ font-size: 12px;
+ margin-bottom: 16px;
+}
+
+.win-metrics span {
+ display: block;
+}
+
+.win-metrics .label {
+ text-transform: uppercase;
+ letter-spacing: 0.18em;
+ font-size: 10px;
+ color: rgba(138,133,120,0.9);
+}
+
+.win-metrics .value {
+ font-family: var(--font-display);
+ font-size: 17px;
+}
+
+/* Side legend */
+.legend {
+ position: relative;
+ z-index: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+}
+
+.legend-copy {
+ font-size: 13px;
+ line-height: 1.7;
+ color: var(--muted);
+ max-width: 40rem;
+}
+
+.legend-list {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ border-radius: 14px;
+ border: 1px solid rgba(201,169,97,0.4);
+ background: linear-gradient(145deg, rgba(23,23,28,0.92), rgba(12,12,15,0.98));
+ box-shadow: 0 14px 36px rgba(0,0,0,0.7);
+}
+
+.legend-item {
+ display: grid;
+ grid-template-columns: 40px minmax(0, 1.3fr) minmax(0, 2fr);
+ gap: 10px;
+ padding: 10px 12px;
+ align-items: center;
+ border-bottom: 1px solid rgba(60,60,70,0.8);
+}
+
+.legend-item:last-child {
+ border-bottom: none;
+}
+
+.legend-swatch {
+ width: 32px;
+ height: 32px;
+ border-radius: 8px;
+ overflow: hidden;
+ border: 1px solid rgba(201,169,97,0.6);
+ box-shadow: 0 10px 24px rgba(0,0,0,0.7);
+ position: relative;
+}
+
+.legend-swatch-inner {
+ position: absolute;
+ inset: 0;
+}
+
+.legend-name {
+ font-family: var(--font-serif);
+ font-size: 12px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+}
+
+.legend-desc {
+ font-size: 12px;
+ color: var(--muted);
+}
+
+/* Animation keyframes from HyperFrames */
+@keyframes fadeUp {
+ from {opacity:0; transform:translateY(28px);}
+ to {opacity:1; transform:none;}
+}
+@keyframes scaleIn {
+ from {opacity:0; transform:scale(.92);}
+ to {opacity:1; transform:none;}
+}
+@keyframes clipReveal {
+ from {clip-path:inset(0 100% 0 0);}
+ to {clip-path:inset(0);}
+}
+@keyframes blurIn {
+ from {opacity:0; filter:blur(12px);}
+ to {opacity:1; filter:blur(0);}
+}
+
+.panel.game-panel {
+ animation: fadeUp 0.7s var(--easing-hero) both;
+}
+.panel.info-panel {
+ animation: fadeUp 0.7s var(--easing-hero) both;
+ animation-delay: 90ms;
+}
+
+/* Accessibility states */
+.card.is-matched {
+ cursor: default;
+}
+.card.disabled {
+ pointer-events: none;
+}
+
+/* Focus outline */
+button:focus-visible,
+.card:focus-visible {
+ outline: 1px solid rgba(255,231,178,0.9);
+ outline-offset: 2px;
+}
+</style>
+</head>
+<body>
+<header class="top-bar">
+ <div class="wordmark">DESIGNER WALLCOVERINGS</div>
+ <div class="top-bar-meta">
+ <span>Pattern Memory Study</span>
+ <span>Muted Luxe Edition</span>
+ </div>
+</header>
+
+<main class="main">
+ <div class="shell">
+ <!-- Game Panel -->
+ <section class="panel game-panel" aria-label="Memory game">
+ <div class="panel-header">
+ <h1 class="panel-title">Pattern Pairing</h1>
+ <div class="panel-subtitle">Match each motif to its twin</div>
+ </div>
+
+ <div class="stats">
+ <div class="stat-block" aria-live="polite">
+ <span class="stat-label">Timer</span>
+ <span class="stat-value" id="time">00:00</span>
+ </div>
+ <div class="stat-block" aria-live="polite">
+ <span class="stat-label">Moves</span>
+ <span class="stat-value" id="moves">0</span>
+ </div>
+ <div class="controls">
+ <button class="btn" id="restartBtn" type="button">
+ <span class="bullet"></span>
+ Restart Layout
+ </button>
+ </div>
+ </div>
+
+ <div class="grid" id="grid" aria-label="Pattern cards"></div>
+
+ <!-- Win overlay -->
+ <div class="win-overlay" id="winOverlay" aria-hidden="true">
+ <div class="win-dialog">
+ <div class="win-label">Collection complete</div>
+ <h2 class="win-title">Wallcovering Suite Mastered</h2>
+ <p class="win-body">
+ You’ve paired each design motif with its perfect counterpart. Consider this your instant upgrade in
+ pattern literacy.
+ </p>
+ <div class="win-metrics">
+ <div>
+ <span class="label">Time</span>
+ <span class="value" id="winTime">00:00</span>
+ </div>
+ <div>
+ <span class="label">Moves</span>
+ <span class="value" id="winMoves">0</span>
+ </div>
+ </div>
+ <button class="btn" id="playAgainBtn" type="button">
+ <span class="bullet"></span>
+ Play Again
+ </button>
+ </div>
+ </div>
+ </section>
+
+ <!-- Info / Legend Panel -->
+ <aside class="panel info-panel" aria-label="Motif legend">
+ <div class="panel-header">
+ <h2 class="panel-title" style="font-size:22px; letter-spacing:0.14em;">Motif Lexicon</h2>
+ <div class="panel-subtitle">Study the signatures</div>
+ </div>
+ <p class="legend-copy">
+ Each pair reveals a distinct wallcovering language—from classical damask to tailored stripe.
+ Note the geometry, movement, and spacing; these are the cues designers read at a glance.
+ </p>
+ <ul class="legend-list">
+ <li class="legend-item">
+ <div class="legend-swatch"><div class="legend-swatch-inner pattern pattern-damask"></div></div>
+ <div class="legend-name">Damask</div>
+ <div class="legend-desc">Ornate, mirrored florals with regal symmetry and a heritage feel.</div>
+ </li>
+ <li class="legend-item">
+ <div class="legend-swatch"><div class="legend-swatch-inner pattern pattern-toile"></div></div>
+ <div class="legend-name">Toile</div>
+ <div class="legend-desc">Delicate scenic narratives in fine linework, often pastoral.</div>
+ </li>
+ <li class="legend-item">
+ <div class="legend-swatch"><div class="legend-swatch-inner pattern pattern-ikat"></div></div>
+ <div class="legend-name">Ikat</div>
+ <div class="legend-desc">Soft, feathered diamonds that suggest hand-dyed threads.</div>
+ </li>
+ <li class="legend-item">
+ <div class="legend-swatch"><div class="legend-swatch-inner pattern pattern-chinoiserie"></div></div>
+ <div class="legend-name">Chinoiserie</div>
+ <div class="legend-desc">Lyrical branches, blossoms, and pagodas—painterly and romantic.</div>
+ </li>
+ <li class="legend-item">
+ <div class="legend-swatch"><div class="legend-swatch-inner pattern pattern-trellis"></div></div>
+ <div class="legend-name">Trellis</div>
+ <div class="legend-desc">Lattice frameworks that feel architectural yet airy.</div>
+ </li>
+ <li class="legend-item">
+ <div class="legend-swatch"><div class="legend-swatch-inner pattern pattern-fret"></div></div>
+ <div class="legend-name">Fret</div>
+ <div class="legend-desc">Interlocking key motifs with strong neoclassical structure.</div>
+ </li>
+ <li class="legend-item">
+ <div class="legend-swatch"><div class="legend-swatch-inner pattern pattern-botanical"></div></div>
+ <div class="legend-name">Botanical</div>
+ <div class="legend-desc">Leafy repeats that bring a softened, organic cadence.</div>
+ </li>
+ <li class="legend-item">
+ <div class="legend-swatch"><div class="legend-swatch-inner pattern pattern-stripe"></div></div>
+ <div class="legend-name">Stripe</div>
+ <div class="legend-desc">Tailored bands that elongate walls and sharpen architecture.</div>
+ </li>
+ </ul>
+ </aside>
+ </div>
+</main>
+
+<script>
+(function() {
+ const motifs = [
+ { name: 'Damask', className: 'pattern-damask' },
+ { name: 'Toile', className: 'pattern-toile' },
+ { name: 'Ikat', className: 'pattern-ikat' },
+ { name: 'Chinoiserie', className: 'pattern-chinoiserie' },
+ { name: 'Trellis', className: 'pattern-trellis' },
+ { name: 'Fret', className: 'pattern-fret' },
+ { name: 'Botanical', className: 'pattern-botanical' },
+ { name: 'Stripe', className: 'pattern-stripe' }
+ ];
+
+ const gridEl = document.getElementById('grid');
+ const movesEl = document.getElementById('moves');
+ const timeEl = document.getElementById('time');
+ const restartBtn = document.getElementById('restartBtn');
+ const winOverlay = document.getElementById('winOverlay');
+ const playAgainBtn = document.getElementById('playAgainBtn');
+ const winTimeEl = document.getElementById('winTime');
+ const winMovesEl = document.getElementById('winMoves');
+
+ let firstCard = null;
+ let secondCard = null;
+ let lockBoard = false;
+ let moves = 0;
+ let matchesFound = 0;
+ let startTime = null;
+ let timerId = null;
+
+ function formatTime(msElapsed) {
+ const totalSec = Math.floor(msElapsed / 1000);
+ const m = String(Math.floor(totalSec / 60)).padStart(2, '0');
+ const s = String(totalSec % 60).padStart(2, '0');
+ return m + ':' + s;
+ }
+
+ function startTimer() {
+ if (timerId) return;
+ startTime = Date.now();
+ timerId = setInterval(() => {
+ const now = Date.now();
+ timeEl.textContent = formatTime(now - startTime);
+ }, 1000);
+ }
+
+ function stopTimer() {
+ if (timerId) {
+ clearInterval(timerId);
+ timerId = null;
+ }
+ }
+
+ function createCard(id, motif) {
+ const card = document.createElement('button');
+ card.type = 'button';
+ card.className = 'card';
+ card.setAttribute('data-id', id);
+ card.setAttribute('data-motif', motif.name);
+ card.setAttribute('aria-label', motif.name + ' motif card');
+ card.setAttribute('aria-pressed', 'false');
+
+ const inner = document.createElement('div');
+ inner.className = 'card-inner';
+
+ const back = document.createElement('div');
+ back.className = 'card-face card-back';
+
+ const front = document.createElement('div');
+ front.className = 'card-face card-front';
+
+ const header = document.createElement('div');
+ header.className = 'card-front-header';
+
+ const nameEl = document.createElement('div');
+ nameEl.className = 'card-front-name';
+ nameEl.textContent = motif.name;
+
+ const tagEl = document.createElement('div');
+ tagEl.className = 'card-front-tag';
+ tagEl.textContent = 'Design Motif';
+
+ header.appendChild(nameEl);
+ header.appendChild(tagEl);
+
+ const swatch = document.createElement('div');
+ swatch.className = 'card-swatch';
+
+ const pattern = document.createElement('div');
+ pattern.className = 'pattern ' + motif.className;
+ swatch.appendChild(pattern);
+
+ front.appendChild(header);
+ front.appendChild(swatch);
+
+ inner.appendChild(back);
+ inner.appendChild(front);
+ card.appendChild(inner);
+
+ card.addEventListener('click', () => handleCardClick(card));
+
+ return card;
+ }
+
+ function shuffle(array) {
+ for (let i = array.length - 1; i > 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ [array[i], array[j]] = [array[j], array[i]];
+ }
+ return array;
+ }
+
+ function setupBoard() {
+ gridEl.innerHTML = '';
+ firstCard = null;
+ secondCard = null;
+ lockBoard = false;
+ moves = 0;
+ matchesFound = 0;
+ movesEl.textContent = '0';
+ timeEl.textContent = '00:00';
+ stopTimer();
+ startTime = null;
+
+ const deck = [];
+ let id = 0;
+ motifs.forEach(motif => {
+ deck.push(createCard(id++, motif));
+ deck.push(createCard(id++, motif));
+ });
+ shuffle(deck);
+
+ deck.forEach(card => gridEl.appendChild(card));
+ }
+
+ function handleCardClick(card) {
+ if (lockBoard || card.classList.contains('is-flipped') || card.classList.contains('is-matched')) return;
+
+ if (!startTime) {
+ startTimer();
+ }
+
+ card.classList.add('is-flipped');
+ card.setAttribute('aria-pressed', 'true');
+
+ if (!firstCard) {
+ firstCard = card;
+ return;
+ }
+
+ if (card === firstCard) return;
+
+ secondCard = card;
+ moves++;
+ movesEl.textContent = String(moves);
+ checkMatch();
+ }
+
+ function checkMatch() {
+ const isMatch = firstCard.getAttribute('data-motif') === secondCard.getAttribute('data-motif');
+ if (isMatch) {
+ handleMatch();
+ } else {
+ handleMismatch();
+ }
+ }
+
+ function handleMatch() {
+ firstCard.classList.add('is-matched');
+ secondCard.classList.add('is-matched');
+ firstCard.classList.add('disabled');
+ secondCard.classList.add('disabled');
+ matchesFound++;
+ resetTurn();
+
+ if (matchesFound === motifs.length) {
+ endGame();
+ }
+ }
+
+ function handleMismatch() {
+ lockBoard = true;
+ setTimeout(() => {
+ firstCard.classList.remove('is-flipped');
+ secondCard.classList.remove('is-flipped');
+ firstCard.setAttribute('aria-pressed', 'false');
+ secondCard.setAttribute('aria-pressed', 'false');
+ resetTurn();
+ }, 820);
+ }
+
+ function resetTurn() {
+ [firstCard, secondCard] = [null, null];
+ lockBoard = false;
+ }
+
+ function endGame() {
+ stopTimer();
+ const finalTime = startTime ? Date.now() - startTime : 0;
+ winTimeEl.textContent = formatTime(finalTime);
+ winMovesEl.textContent = String(moves);
+ winOverlay.classList.add('is-visible');
+ winOverlay.setAttribute('aria-hidden', 'false');
+ }
+
+ function restartGame() {
+ winOverlay.classList.remove('is-visible');
+ winOverlay.setAttribute('aria-hidden', 'true');
+ setupBoard();
+ }
+
+ restartBtn.addEventListener('click', restartGame);
+ playAgainBtn.addEventListener('click', restartGame);
+
+ setupBoard();
+})();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/5410cf08e245/gpt.png b/data/artifacts/5410cf08e245/gpt.png
new file mode 100644
index 0000000..3eab39f
Binary files /dev/null and b/data/artifacts/5410cf08e245/gpt.png differ
diff --git a/data/challenges.json b/data/challenges.json
index 46b4f38..ea81007 100644
--- a/data/challenges.json
+++ b/data/challenges.json
@@ -14606,7 +14606,7 @@
"thumb": true
}
],
- "judging": true
+ "judging": false
},
{
"id": "b72f0e9e751b",
@@ -14761,7 +14761,7 @@
"thumb": true
}
],
- "judging": true
+ "judging": false
},
{
"id": "d7f4f8ca5f8d",
@@ -14916,7 +14916,7 @@
"thumb": true
}
],
- "judging": true,
+ "judging": false,
"judged_at": null
},
{
@@ -15065,7 +15065,7 @@
"thumb": true
}
],
- "judging": true
+ "judging": false
},
{
"id": "172f180e3161",
@@ -15166,8 +15166,9 @@
"thumb": true
}
],
- "judging": true,
- "judged_at": null
+ "judging": false,
+ "judged_at": null,
+ "category": "Games"
},
{
"id": "eda6b5e29387",
@@ -15261,7 +15262,8 @@
"thumb": true
}
],
- "judging": true
+ "judging": false,
+ "category": "Custom"
},
{
"id": "028885e12558",
@@ -15436,7 +15438,7 @@
"thumb": true
}
],
- "judging": true,
+ "judging": false,
"judged_at": null
},
{
@@ -15524,7 +15526,8 @@
"thumb": true
}
],
- "judging": true
+ "judging": false,
+ "category": "Custom"
},
{
"id": "6a3a34df3dc6",
@@ -15689,7 +15692,7 @@
"thumb": true
}
],
- "judging": true
+ "judging": false
},
{
"id": "689983752ba8",
@@ -15847,7 +15850,7 @@
"thumb": true
}
],
- "judging": true,
+ "judging": false,
"judged_at": null
},
{
@@ -15927,7 +15930,8 @@
"thumb": true
}
],
- "judging": true
+ "judging": false,
+ "category": "Games"
},
{
"id": "8443d9162963",
@@ -16007,8 +16011,9 @@
"thumb": true
}
],
- "judging": true,
- "judged_at": null
+ "judging": false,
+ "judged_at": null,
+ "category": "Games"
},
{
"id": "6923e6180f0f",
@@ -16154,7 +16159,7 @@
"thumb": true
}
],
- "judging": true
+ "judging": false
},
{
"id": "b3721d9fe563",
@@ -16301,7 +16306,7 @@
"thumb": true
}
],
- "judging": true
+ "judging": false
},
{
"id": "71a0784e71c8",
@@ -16343,13 +16348,13 @@
},
{
"model": "hermes3-8b",
- "status": "error",
- "error": "no HTML document in model output (0 chars)",
+ "status": "queued",
+ "error": null,
"seconds": 17,
"cost": null,
- "started_at": "2026-07-25T08:42:15.481Z",
- "finished_at": "2026-07-25T08:42:32.683Z",
- "queued_at": "2026-07-25T08:25:23.397Z",
+ "started_at": null,
+ "finished_at": null,
+ "queued_at": "2026-07-25T08:46:25.711Z",
"toolCalls": [
"opendesign",
"hyperframes",
@@ -16473,7 +16478,7 @@
"thumb": true
}
],
- "judging": true,
+ "judging": false,
"judged_at": null
},
{
@@ -16488,33 +16493,37 @@
"runs": [
{
"model": "qwen3-14b",
- "status": "running",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
+ "seconds": 56,
+ "cost": 0,
"started_at": "2026-07-25T08:44:31.327Z",
- "finished_at": null,
- "queued_at": "2026-07-25T08:34:13.027Z"
+ "finished_at": "2026-07-25T08:45:27.478Z",
+ "queued_at": "2026-07-25T08:34:13.027Z",
+ "bytes": 5738,
+ "thumb": true
},
{
"model": "gemma3-12b",
- "status": "queued",
+ "status": "running",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
- "started_at": null,
+ "started_at": "2026-07-25T08:46:22.621Z",
"finished_at": null,
- "queued_at": "2026-07-25T08:34:13.034Z"
+ "queued_at": "2026-07-25T08:46:22.560Z",
+ "resumes": 1
},
{
"model": "hermes3-8b",
"status": "queued",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
"started_at": null,
"finished_at": null,
- "queued_at": "2026-07-25T08:34:13.041Z"
+ "queued_at": "2026-07-25T08:46:22.563Z",
+ "resumes": 1
},
{
"model": "qwen25-7b",
@@ -16532,13 +16541,16 @@
"model": "hf-qwen-coder-32b",
"status": "queued",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
"started_at": null,
"finished_at": null,
- "queued_at": "2026-07-25T08:34:13.051Z"
+ "queued_at": "2026-07-25T08:46:22.566Z",
+ "resumes": 1
}
- ]
+ ],
+ "aiPick": null,
+ "category": "Games"
},
{
"id": "6eb0315c9845",
@@ -16553,31 +16565,34 @@
"model": "qwen3-14b",
"status": "queued",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
"started_at": null,
"finished_at": null,
- "queued_at": "2026-07-25T08:35:55.343Z"
+ "queued_at": "2026-07-25T08:46:22.569Z",
+ "resumes": 1
},
{
"model": "gemma3-12b",
"status": "queued",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
"started_at": null,
"finished_at": null,
- "queued_at": "2026-07-25T08:35:55.352Z"
+ "queued_at": "2026-07-25T08:46:22.572Z",
+ "resumes": 1
},
{
"model": "hermes3-8b",
"status": "queued",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
"started_at": null,
"finished_at": null,
- "queued_at": "2026-07-25T08:35:55.359Z"
+ "queued_at": "2026-07-25T08:46:22.575Z",
+ "resumes": 1
},
{
"model": "qwen25-7b",
@@ -16595,11 +16610,12 @@
"model": "hf-qwen-coder-32b",
"status": "queued",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
"started_at": null,
"finished_at": null,
- "queued_at": "2026-07-25T08:35:55.371Z"
+ "queued_at": "2026-07-25T08:46:22.578Z",
+ "resumes": 1
},
{
"model": "claude-code",
@@ -16666,7 +16682,8 @@
"bytes": 19690,
"thumb": true
}
- ]
+ ],
+ "aiPick": null
},
{
"id": "c135c54c4121",
@@ -16682,53 +16699,60 @@
"model": "qwen3-14b",
"status": "queued",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
"started_at": null,
"finished_at": null,
- "queued_at": "2026-07-25T08:45:15.872Z"
+ "queued_at": "2026-07-25T08:46:22.581Z",
+ "resumes": 1
},
{
"model": "gemma3-12b",
"status": "queued",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
"started_at": null,
"finished_at": null,
- "queued_at": "2026-07-25T08:45:15.878Z"
+ "queued_at": "2026-07-25T08:46:22.584Z",
+ "resumes": 1
},
{
"model": "hermes3-8b",
"status": "queued",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
"started_at": null,
"finished_at": null,
- "queued_at": "2026-07-25T08:45:15.884Z"
+ "queued_at": "2026-07-25T08:46:22.586Z",
+ "resumes": 1
},
{
"model": "qwen25-7b",
"status": "running",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
- "started_at": "2026-07-25T08:45:15.903Z",
+ "started_at": "2026-07-25T08:46:22.633Z",
"finished_at": null,
- "queued_at": "2026-07-25T08:45:15.891Z"
+ "queued_at": "2026-07-25T08:46:22.589Z",
+ "resumes": 1
},
{
"model": "hf-qwen-coder-32b",
"status": "queued",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
"started_at": null,
"finished_at": null,
- "queued_at": "2026-07-25T08:45:15.897Z"
+ "queued_at": "2026-07-25T08:46:22.592Z",
+ "resumes": 1
}
- ]
+ ],
+ "aiPick": null,
+ "category": "Games"
},
{
"id": "5410cf08e245",
@@ -16743,92 +16767,109 @@
"model": "qwen3-14b",
"status": "queued",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
"started_at": null,
"finished_at": null,
- "queued_at": "2026-07-25T08:45:15.963Z"
+ "queued_at": "2026-07-25T08:46:22.596Z",
+ "resumes": 1
},
{
"model": "gemma3-12b",
"status": "queued",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
"started_at": null,
"finished_at": null,
- "queued_at": "2026-07-25T08:45:15.969Z"
+ "queued_at": "2026-07-25T08:46:22.599Z",
+ "resumes": 1
},
{
"model": "hermes3-8b",
"status": "queued",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
"started_at": null,
"finished_at": null,
- "queued_at": "2026-07-25T08:45:15.975Z"
+ "queued_at": "2026-07-25T08:46:22.602Z",
+ "resumes": 1
},
{
"model": "qwen25-7b",
"status": "queued",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
"started_at": null,
"finished_at": null,
- "queued_at": "2026-07-25T08:45:15.978Z"
+ "queued_at": "2026-07-25T08:46:22.605Z",
+ "resumes": 1
},
{
"model": "hf-qwen-coder-32b",
"status": "queued",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
"started_at": null,
"finished_at": null,
- "queued_at": "2026-07-25T08:45:15.981Z"
+ "queued_at": "2026-07-25T08:46:22.608Z",
+ "resumes": 1
},
{
"model": "claude-code",
"status": "running",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
- "started_at": "2026-07-25T08:45:15.997Z",
+ "started_at": "2026-07-25T08:46:22.637Z",
"finished_at": null,
- "queued_at": "2026-07-25T08:45:15.985Z"
+ "queued_at": "2026-07-25T08:46:22.611Z",
+ "resumes": 1
},
{
"model": "kimi",
"status": "running",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
- "started_at": "2026-07-25T08:45:16.001Z",
+ "started_at": "2026-07-25T08:46:22.643Z",
"finished_at": null,
- "queued_at": "2026-07-25T08:45:15.987Z"
+ "queued_at": "2026-07-25T08:46:22.614Z",
+ "resumes": 1
},
{
"model": "gpt",
- "status": "running",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
+ "seconds": 54,
+ "cost": 0.1186,
"started_at": "2026-07-25T08:45:16.006Z",
- "finished_at": null,
- "queued_at": "2026-07-25T08:45:15.991Z"
+ "finished_at": "2026-07-25T08:46:10.120Z",
+ "queued_at": "2026-07-25T08:45:15.991Z",
+ "toolCalls": [
+ "opendesign",
+ "opendesign",
+ "hyperframes",
+ "hyperframes"
+ ],
+ "bytes": 26136,
+ "thumb": true
},
{
"model": "grok",
"status": "running",
"error": null,
- "seconds": null,
+ "seconds": 0,
"cost": null,
- "started_at": "2026-07-25T08:45:16.010Z",
+ "started_at": "2026-07-25T08:46:22.658Z",
"finished_at": null,
- "queued_at": "2026-07-25T08:45:15.994Z"
+ "queued_at": "2026-07-25T08:46:22.617Z",
+ "resumes": 1
}
- ]
+ ],
+ "aiPick": null
}
]
\ No newline at end of file
diff --git a/data/costlog.jsonl b/data/costlog.jsonl
index ae7c15e..6539c24 100644
--- a/data/costlog.jsonl
+++ b/data/costlog.jsonl
@@ -234,3 +234,4 @@
{"ts":"2026-07-25T08:36:36.723Z","provider":"openai","model":"gpt-5.1","task":"model-arena-tools","input_tokens":2727,"output_tokens":5819,"cost_usd":0.086238}
{"ts":"2026-07-25T08:37:23.677Z","provider":"xai","model":"grok-4.5","task":"model-arena-tools","input_tokens":4922,"output_tokens":7428,"cost_usd":0.126186}
{"ts":"2026-07-25T08:37:33.195Z","provider":"moonshot","model":"kimi-k2.5","task":"model-arena-tools","input_tokens":4905,"output_tokens":5077,"cost_usd":0.015636}
+{"ts":"2026-07-25T08:46:10.116Z","provider":"openai","model":"gpt-5.1","task":"model-arena-tools","input_tokens":2702,"output_tokens":8132,"cost_usd":0.118577}
diff --git a/server.js b/server.js
index f8f13f9..7500a4a 100644
--- a/server.js
+++ b/server.js
@@ -69,9 +69,13 @@ header h1{font-size:15px;margin:0;font-weight:600}header .by{color:#8a93a0;font-
// Local ollama models are free and enabled by default. Metered models require
// their env key AND explicit per-run selection in the UI (never pre-checked).
const MODELS = [
- { id: 'qwen3-14b', label: 'Qwen3 14B', kind: 'local', host: 'http://localhost:11434', model: 'qwen3:14b', estCost: 0, tools: true },
+ // small local models get the design PACK (material injected as text), not the live
+ // tool-calling loop — an 8B/14B is unreliable at function-calling and returned 0 chars
+ // through the tool loop (ALL-MUST-WORK fix, 2026-07-25). Live tool loop stays on the
+ // reliable API models (kimi/gpt/grok) + claude-code.
+ { id: 'qwen3-14b', label: 'Qwen3 14B', kind: 'local', host: 'http://localhost:11434', model: 'qwen3:14b', estCost: 0 },
{ id: 'gemma3-12b', label: 'Gemma3 12B', kind: 'local', host: 'http://localhost:11434', model: 'gemma3:12b', estCost: 0 },
- { id: 'hermes3-8b', label: 'Hermes3 8B', kind: 'local', host: 'http://localhost:11434', model: 'hermes3:8b', estCost: 0, tools: true },
+ { id: 'hermes3-8b', label: 'Hermes3 8B', kind: 'local', host: 'http://localhost:11434', model: 'hermes3:8b', estCost: 0 },
// was Mac1 (192.168.1.133) — that Ollama host wedges (model pinned in VRAM, generations hang);
// repointed to Mac2-local qwen2.5 for reliable liveness. Set OLLAMA_MAC1=1 to use Mac1 again.
{ id: 'qwen25-7b', label: 'Qwen2.5 (local)', kind: 'local', host: process.env.OLLAMA_MAC1 ? 'http://192.168.1.133:11434' : 'http://localhost:11434', model: process.env.OLLAMA_MAC1 ? 'qwen2.5:7b' : 'qwen2.5:latest', estCost: 0 },
← 5092bf1 night-loop: cycle 01:45 — judged=71a0784e71c8 · fired 1 →; F
·
back to Model Arena
·
Beauty loop: Cost Savings Ticker (referee 9.3 vs designer 3, adc0d82 →