/* ========================================================================== ToolUse.1 — shared client Loads results (live results.json, else embedded snapshot), renders the leaderboard, and drives the motion layer: reveal-on-scroll, count-up, score bars, sortable columns. ========================================================================== */ "use strict"; /* Gate motion behind a class so the no-JS view stays fully visible. */ document.documentElement.classList.add("js"); /* Inlined snapshot so pages render when opened straight from disk (file:// blocks fetch). A served results.json overrides it. */ const EMBEDDED_RESULTS = { benchmark: "ToolUse.1", version: "1.0.0", updated: "2026-10-17", corpus: { cases: 114, call_cases: 78, no_call_cases: 36, tools: 9, protocols: 3 }, rows: [ { model: "oracle", link: "", protocol: "all", score: 1.0, score_ci95: [0.9889, 1.0], correct_call: 1.0, abstention: 1.0, spurious_call_rate: 0.0, n_cases: 342, notes: "reads the expectations out of the corpus — grader reference", self_check: true, by_protocol: { json: 1.0, xml: 1.0, plain: 1.0 }, }, { model: "HardcoreAI/Nova-1.1-0.8B", link: "https://huggingface.co/HardcoreAI/Nova-1.1-0.8B", protocol: "all", score: 0.6404, score_ci95: [0.5882, 0.6894], correct_call: 0.5855, abstention: 0.7593, spurious_call_rate: 0.1667, n_cases: 342, notes: "greedy · thinking off · batch 8 · English-only · fine-tuned", self_check: false, by_protocol: { json: 0.6754, xml: 0.6316, plain: 0.614 }, }, { model: "Qwen/Qwen3.5-0.8B", link: "https://huggingface.co/Qwen/Qwen3.5-0.8B", protocol: "all", score: 0.5936, score_ci95: [0.5408, 0.6443], correct_call: 0.4829, abstention: 0.8333, spurious_call_rate: 0.0648, n_cases: 342, notes: "greedy · thinking off · batch 8 · English-only · base model", self_check: false, by_protocol: { json: 0.6754, xml: 0.6754, plain: 0.4298 }, }, ], }; const pct = (v) => (typeof v === "number" ? (v * 100).toFixed(1) + "%" : "—"); const ci = (lo, hi) => (lo == null || hi == null ? "—" : `${(lo * 100).toFixed(1)}% – ${(hi * 100).toFixed(1)}%`); const prefersReduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches; /* ------------------------------------------------------------- motion */ function revealOnScroll(root = document) { const nodes = root.querySelectorAll(".reveal"); if (prefersReduced || !("IntersectionObserver" in window)) { nodes.forEach((n) => n.classList.add("in")); return; } const io = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add("in"); io.unobserve(entry.target); } }); }, { rootMargin: "0px 0px -8% 0px", threshold: 0.08 }, ); nodes.forEach((n) => io.observe(n)); } function countUp(el) { const target = parseFloat(el.dataset.count); const suffix = el.dataset.suffix || ""; if (prefersReduced || Number.isNaN(target)) { el.textContent = `${target}${suffix}`; return; } const start = performance.now(); const dur = 900; const step = (now) => { const t = Math.min(1, (now - start) / dur); const eased = 1 - Math.pow(1 - t, 3); el.textContent = `${Math.round(target * eased)}${suffix}`; if (t < 1) requestAnimationFrame(step); else el.textContent = `${target}${suffix}`; }; requestAnimationFrame(step); } /* ------------------------------------------------------------- rendering */ function scoreCell(value) { const wrap = document.createElement("div"); wrap.className = "score-cell"; const bar = document.createElement("div"); bar.className = "bar"; const fill = document.createElement("i"); fill.dataset.w = Math.max(0, Math.min(1, value || 0)); bar.append(fill); const val = document.createElement("span"); val.className = "score-value"; val.textContent = pct(value); wrap.append(bar, val); return wrap; } function spuriousCell(value) { const cell = document.createElement("td"); cell.className = "num"; if (typeof value !== "number") { cell.textContent = "—"; return cell; } cell.textContent = pct(value); cell.classList.add(value >= 0.3 ? "spurious-high" : value >= 0.1 ? "spurious-mid" : ""); return cell; } function protoMini(byProtocol) { const wrap = document.createElement("div"); wrap.className = "proto-mini"; ["json", "xml", "plain"].forEach((key) => { const box = document.createElement("div"); const label = document.createElement("span"); label.className = "pl"; label.textContent = key; const bar = document.createElement("div"); bar.className = "pb"; const fill = document.createElement("i"); fill.dataset.w = Math.max(0, Math.min(1, byProtocol?.[key] ?? 0)); bar.append(fill); const val = document.createElement("span"); val.className = "pv"; val.textContent = pct(byProtocol?.[key]); box.append(label, bar, val); wrap.append(box); }); return wrap; } function rowNode(row, index, opts = {}) { const { withProtocol = false, withNotes = false } = opts; const tr = document.createElement("tr"); tr.dataset.score = row.score ?? 0; tr.dataset.correct_call = row.correct_call ?? 0; tr.dataset.abstention = row.abstention ?? 0; tr.dataset.spurious_call_rate = row.spurious_call_rate ?? 0; tr.dataset.n_cases = row.n_cases ?? 0; const rank = document.createElement("td"); rank.className = "col-rank"; const badge = document.createElement("span"); badge.className = `rank-badge${index < 3 ? ` rank-${index + 1}` : ""}`; badge.textContent = index + 1; rank.append(badge); tr.append(rank); const model = document.createElement("td"); model.className = "col-model"; if (row.link) { const a = document.createElement("a"); a.className = "model-link model-name"; a.href = row.link; a.target = "_blank"; a.rel = "noopener"; a.textContent = row.model; model.append(a); } else { const s = document.createElement("span"); s.className = "model-name"; s.textContent = row.model; model.append(s); } const sub = [row.protocol === "all" ? "all protocols" : `protocol: ${row.protocol}`, row.notes].filter(Boolean).join(" · "); if (sub) { const s = document.createElement("span"); s.className = "model-sub"; s.textContent = sub; model.append(s); } tr.append(model); const score = document.createElement("td"); score.className = "num"; score.append(scoreCell(row.score)); const c = document.createElement("span"); c.className = "ci"; c.textContent = Array.isArray(row.score_ci95) ? ci(row.score_ci95[0], row.score_ci95[1]) : ""; score.append(c); tr.append(score); tr.append(Object.assign(document.createElement("td"), { className: "num", textContent: pct(row.correct_call) })); tr.append(Object.assign(document.createElement("td"), { className: "num", textContent: pct(row.abstention) })); tr.append(spuriousCell(row.spurious_call_rate)); tr.append(Object.assign(document.createElement("td"), { className: "num", textContent: row.n_cases ?? "—" })); if (withProtocol) { const proto = document.createElement("td"); proto.append(protoMini(row.by_protocol)); tr.append(proto); } if (withNotes) { const notes = document.createElement("td"); notes.className = "col-notes"; if (row.self_check) { const tag = document.createElement("span"); tag.className = "tag"; tag.textContent = "grader self-check"; notes.append(tag); } else if (row.notes) { const span = document.createElement("span"); span.className = "ci"; span.textContent = row.notes; notes.append(span); } tr.append(notes); } return tr; } function renderBoard(data, host) { const tbody = host.querySelector("[data-board-body]"); const stamp = host.querySelector("[data-board-stamp]"); const emptyEl = host.querySelector("[data-board-empty]"); const rows = [...(data.rows || [])].sort( (a, b) => (b.score ?? 0) - (a.score ?? 0) || (a.spurious_call_rate ?? 1) - (b.spurious_call_rate ?? 1), ); const hasProtocolCol = !!host.querySelector("[data-col-protocol]"); const hasNotesCol = !!host.querySelector("[data-col-notes]"); tbody.replaceChildren(...rows.map((row, i) => rowNode(row, i, { withProtocol: hasProtocolCol, withNotes: hasNotesCol }))); if (stamp) { stamp.textContent = [ `${rows.length} entr${rows.length === 1 ? "y" : "ies"}`, data.version ? `v${data.version}` : "", data.updated ? `updated ${data.updated}` : "", ].filter(Boolean).join(" · "); } if (emptyEl) emptyEl.hidden = rows.length > 0; requestAnimationFrame(() => { tbody.querySelectorAll("tr").forEach((tr, i) => { setTimeout(() => tr.classList.add("in"), prefersReduced ? 0 : 40 * i); }); tbody.querySelectorAll(".bar > i, .pb > i").forEach((fill) => { fill.style.width = `${Math.max(0, Math.min(1, parseFloat(fill.dataset.w) || 0)) * 100}%`; }); }); } /* ------------------------------------------------------------- sorting */ function wireSorting(host) { const headers = host.querySelectorAll("th[data-sort]"); headers.forEach((th) => { th.classList.add("sortable"); if (!th.querySelector(".arrow")) th.insertAdjacentHTML("beforeend", ' ↑↓'); th.addEventListener("click", () => { const key = th.dataset.sort; const dir = th.getAttribute("aria-sort") === "descending" ? "ascending" : "descending"; headers.forEach((h) => h.removeAttribute("aria-sort")); th.setAttribute("aria-sort", dir); const tbody = host.querySelector("[data-board-body]"); const glyph = th.querySelector(".arrow"); if (glyph) glyph.textContent = dir === "descending" ? " ↓" : " ↑"; const rows = [...tbody.querySelectorAll("tr")]; rows.sort((a, b) => { const av = parseFloat(a.dataset[key]) || 0; const bv = parseFloat(b.dataset[key]) || 0; return dir === "descending" ? bv - av : av - bv; }); tbody.replaceChildren(...rows); }); }); } /* ------------------------------------------------------------- bootstrap */ async function loadResults() { try { const res = await fetch("results.json", { cache: "no-store" }); if (!res.ok) throw new Error(`HTTP ${res.status}`); return await res.json(); } catch { return EMBEDDED_RESULTS; } } function applyMetricCards(data) { const best = [...(data.rows || [])] .filter((r) => !r.self_check && typeof r.score === "number") .sort((a, b) => (b.score ?? 0) - (a.score ?? 0))[0]; if (!best) return; const map = { overall: best.score, call: best.correct_call, abstain: best.abstention }; document.querySelectorAll("[data-metric]").forEach((el) => { const v = map[el.dataset.metric]; if (typeof v === "number") el.textContent = pct(v); }); const leader = document.querySelector("[data-leader]"); if (leader) leader.textContent = best.model; } document.addEventListener("DOMContentLoaded", async () => { document.querySelectorAll("[data-count]").forEach(countUp); revealOnScroll(); const boards = document.querySelectorAll("[data-board]"); if (!boards.length) return; const data = await loadResults(); boards.forEach((host) => { renderBoard(data, host); wireSorting(host); }); applyMetricCards(data); const year = document.getElementById("year"); if (year) year.textContent = new Date().getFullYear(); });