From 984300ba217dd47eeee00909c4e950640cb5a2e1 Mon Sep 17 00:00:00 2001 From: Max Gorog Date: Fri, 8 May 2026 20:00:42 -0500 Subject: [PATCH] model bars: derive gradient from name (procedural, not per-name CSS) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CSS-rule-per-canonical-name approach was wrong: any name the producer publishes that wasn't in the hardcoded list (mlp_realistic, cnn_oracle, knn_semi, anything new tomorrow) rendered grey because no .model-fill. rule matched. Replace with a deterministic FNV-1a hash of the model string โ†’ hue, applied inline as an OKLCH gradient when the row is created. Every model string gets a stable, distinct color regardless of suffix or case. Inline style beats any CSS rule, so this works whatever's in dashboard.css. Co-Authored-By: Claude Opus 4.7 (1M context) --- training/dashboard/static/dashboard.js | 30 ++++++++++++++++++++------ training/dashboard/static/index.html | 2 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/training/dashboard/static/dashboard.js b/training/dashboard/static/dashboard.js index 2a1e81d..1a5768b 100644 --- a/training/dashboard/static/dashboard.js +++ b/training/dashboard/static/dashboard.js @@ -1760,24 +1760,42 @@ def train_nn(*, model, X_train, y_train, X_val, y_val, root.innerHTML = ''; root.appendChild(awaitingNote('awaiting model_metric events ยท turn demo on for examples')); } + // Derive a gradient deterministically from the model name. Any + // string the producer publishes (mlp / mlp_realistic / cnn_oracle + // / knn_semi / something we never anticipated) maps to a stable + // hue, so the bar always paints. Beats hardcoding CSS rules per + // known name and missing whatever the producer adds tomorrow. + function modelHue(s) { + // FNV-1a 32-bit, cheap and deterministic across browsers. + let h = 2166136261; + for (let i = 0; i < s.length; i++) { + h ^= s.charCodeAt(i); + h = (h * 16777619) >>> 0; + } + return h % 360; + } + function gradientFor(model) { + const hue = modelHue(String(model)); + return `linear-gradient(90deg, oklch(72% 0.18 ${hue}), oklch(46% 0.20 ${hue}))`; + } function ensureRow(model) { if (rows.has(model)) return rows.get(model); if (root.querySelector('.awaiting')) root.innerHTML = ''; const row = document.createElement('div'); row.className = 'model-row'; row.innerHTML = `
${model}
-
+
0.000
`; root.appendChild(row); - const entry = { row, fill: row.querySelector('.model-fill'), acc: row.querySelector('.model-acc') }; + const fill = row.querySelector('.model-fill'); + // Inline style beats any CSS rule, so the gradient survives no + // matter what's in dashboard.css. + fill.style.background = gradientFor(model); + const entry = { row, fill, acc: row.querySelector('.model-acc') }; rows.set(model, entry); return entry; } function render(model, accuracy) { const r = ensureRow(model); - // Full 0โ€“1 visible scale. The previous (acc-0.5)/0.5 mapping - // clamped honest-low cross-host F1s to 0% width and made the - // bars look unpopulated. Producer-side change โ€” see - // docs/dashboard-request-scenes-7-8-12.md for context. const visible = Math.max(0, Math.min(1, accuracy)); r.fill.style.width = (visible * 100).toFixed(1) + '%'; r.acc.textContent = accuracy.toFixed(3); diff --git a/training/dashboard/static/index.html b/training/dashboard/static/index.html index 166ce5d..ddab6b2 100644 --- a/training/dashboard/static/index.html +++ b/training/dashboard/static/index.html @@ -648,6 +648,6 @@ - +