Something went wrong. Try again.
Parametric learning in your code harness.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>machine</title><style>/* Layout: a fixed sidebar of sections and a scrolling main column; one column with a top bar on phones. */:root { --bg: #0a0a0a; --surface: #141414; --raised: #1a1a1a; --border: #2a2a2a; --text: #e5e5e5; --text-2: #b0b0b0; --muted: #8a8a8a; --accent: #c4aacf; --link: #d4b9df; --good: #7cc495; --warn: #e0b46a; --bad: #e07070; --body: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif; --mono: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; color-scheme: dark;}@media (prefers-color-scheme: light) { :root { --bg: #ffffff; --surface: #fafafa; --raised: #f5f5f5; --border: #e8e8e8; --text: #1a1a1a; --text-2: #2a2a2a; --muted: #555555; --accent: #b497bf; --link: #72567e; --good: #2f6b45; --warn: #8a5a00; --bad: #aa3333; color-scheme: light; }}* { box-sizing: border-box; }html, body { height: 100%; }body { margin: 0; background: var(--bg); color: var(--text); font: 14px/1.5 var(--body); }:where(a, button, select, [tabindex]):focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }button, select { font: inherit; color: inherit; }code, .mono { font-family: var(--mono); font-size: 0.8125rem; }
.app { display: grid; grid-template-columns: 232px minmax(0, 1fr); min-height: 100%; }@media (max-width: 760px) { .app { grid-template-columns: minmax(0, 1fr); } }
nav.side { border-right: 1px solid var(--border); padding: 16px 12px; display: flex; flex-direction: column; gap: 4px; position: sticky; top: 0; height: 100vh; }@media (max-width: 760px) { nav.side { position: static; height: auto; flex-direction: row; flex-wrap: wrap; border-right: 0; border-bottom: 1px solid var(--border); padding: 12px 16px; } }.brand { display: flex; align-items: center; gap: 10px; padding: 6px 10px 18px; font-size: 1.125rem; letter-spacing: 0.06em; }@media (max-width: 760px) { .brand { padding: 4px 8px; width: 100%; } }.ring { width: 18px; height: 18px; border-radius: 50%; border: 5px solid var(--text); flex: none; }.nav-item { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 8px; color: var(--text-2); text-decoration: none; }.nav-item:hover { background: var(--surface); color: var(--text); }.nav-item[aria-current="page"] { background: var(--raised); color: var(--text); font-weight: 600; }.nav-item svg { width: 16px; height: 16px; flex: none; }.side-foot { margin-top: auto; padding: 10px; font-size: 0.75rem; color: var(--muted); display: flex; flex-direction: column; gap: 6px; }@media (max-width: 760px) { .side-foot { margin: 0; width: 100%; flex-direction: row; gap: 12px; padding: 4px 8px; } }.live { display: inline-flex; align-items: center; gap: 6px; }.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); }.live.on .dot { background: var(--good); box-shadow: 0 0 0 3px color-mix(in srgb, var(--good) 25%, transparent); }
main { padding: 28px 32px 64px; min-width: 0; }@media (max-width: 760px) { main { padding: 20px 16px 48px; } }h1 { font-size: 1.5rem; font-weight: 600; letter-spacing: -0.01em; margin: 0 0 4px; }.sub { color: var(--muted); margin: 0 0 24px; }h2 { font-size: 0.75rem; font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); margin: 28px 0 10px; display: flex; justify-content: space-between; gap: 12px; align-items: baseline; }h2 a, h2 button { text-transform: none; letter-spacing: 0; font-size: 0.8125rem; color: var(--link); background: none; border: 0; cursor: pointer; padding: 0; text-decoration: none; }
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }.stat { background: var(--bg); padding: 14px 16px; }.stat .k { font-size: 0.75rem; color: var(--muted); }.stat .v { font-size: 1.5rem; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }.stat .d { font-size: 0.75rem; color: var(--text-2); }
.grid2 { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: 28px; }@media (max-width: 1100px) { .grid2 { grid-template-columns: minmax(0, 1fr); gap: 0; } }
.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: 8px; }table { border-collapse: collapse; width: 100%; font-variant-numeric: tabular-nums; }th, td { text-align: left; padding: 9px 12px; border-bottom: 1px solid var(--border); vertical-align: top; }tr:last-child td { border-bottom: 0; }th { font-size: 0.75rem; font-weight: 500; color: var(--muted); background: var(--surface); white-space: nowrap; }td.n, th.n { text-align: right; }tbody tr.click { cursor: pointer; }tbody tr.click:hover td { background: var(--surface); }tbody tr.sel td { background: var(--raised); }.name { font-family: var(--mono); font-size: 0.8125rem; white-space: nowrap; }.dim { color: var(--muted); }.trunc { max-width: 380px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.score { display: inline-flex; align-items: center; gap: 8px; font-variant-numeric: tabular-nums; }.meter { width: 64px; height: 5px; border-radius: 999px; background: var(--border); overflow: hidden; }.meter span { display: block; height: 100%; background: var(--accent); }.pill { display: inline-block; font-size: 0.6875rem; padding: 1px 8px; border-radius: 999px; border: 1px solid var(--border); color: var(--text-2); white-space: nowrap; }.pill.good { color: var(--good); border-color: color-mix(in srgb, var(--good) 40%, transparent); }.pill.bad { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, transparent); }.pill.live { color: var(--link); border-color: var(--accent); }
.feed { list-style: none; margin: 0; padding: 0; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }.feed li { display: grid; grid-template-columns: 64px minmax(0, 9rem) minmax(0, 1fr); gap: 10px; padding: 8px 12px; border-bottom: 1px solid var(--border); font-size: 0.8125rem; align-items: baseline; }.feed li:last-child { border-bottom: 0; }.feed li.fresh { animation: flash 900ms ease; }.feed .t { color: var(--muted); font-variant-numeric: tabular-nums; font-size: 0.75rem; }.feed .m { font-family: var(--mono); font-size: 0.75rem; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.feed .x { min-width: 0; overflow-wrap: anywhere; }.feed .k { color: var(--link); }.feed .k.bad { color: var(--bad); }.feed .k.good { color: var(--good); }@media (max-width: 560px) { .feed li { grid-template-columns: 56px minmax(0, 1fr); } .feed .m { grid-column: 2; } .feed .x { grid-column: 1 / -1; } }@keyframes flash { from { background: var(--raised); } to { background: transparent; } }.empty { border: 1px dashed var(--border); border-radius: 8px; padding: 18px; color: var(--muted); }
.running { display: flex; flex-direction: column; gap: 8px; }.running .item { border: 1px solid var(--accent); border-radius: 8px; padding: 10px 12px; display: grid; gap: 2px; }.running .item .what { font-size: 0.8125rem; color: var(--text-2); overflow-wrap: anywhere; }
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }.card { border: 1px solid var(--border); border-radius: 8px; padding: 16px; display: flex; flex-direction: column; gap: 10px; background: var(--bg); }.card.child { border-left: 2px solid var(--accent); }.card .intent { color: var(--text-2); font-size: 0.875rem; }.crit { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; font-size: 0.8125rem; }.crit li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }.crit .g { color: var(--muted); font-size: 0.75rem; }.card .foot { display: flex; gap: 14px; flex-wrap: wrap; font-size: 0.75rem; color: var(--muted); border-top: 1px solid var(--border); padding-top: 10px; }.card button.go { align-self: flex-start; background: none; border: 1px solid var(--border); border-radius: 999px; padding: 3px 12px; cursor: pointer; color: var(--text); font-size: 0.8125rem; }
.toolbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 12px; }select { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 6px 10px; }
.split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 20px; align-items: start; }@media (max-width: 1200px) { .split { grid-template-columns: minmax(0, 1fr); } }.detail { border: 1px solid var(--border); border-radius: 8px; padding: 16px; display: flex; flex-direction: column; gap: 14px; position: sticky; top: 16px; max-height: calc(100vh - 32px); overflow: auto; background: var(--bg); }.detail-head { display: flex; justify-content: space-between; gap: 12px; align-items: start; }.close { background: none; border: 1px solid var(--border); border-radius: 999px; width: 30px; height: 30px; cursor: pointer; flex: none; color: var(--text-2); }.scrim { display: none; }@media (max-width: 1200px) { .detail { position: fixed; top: 0; right: 0; bottom: 0; width: min(680px, 100%); max-height: none; border-radius: 0; border-width: 0 0 0 1px; z-index: 10; box-shadow: -12px 0 32px rgba(0, 0, 0, 0.35); } .scrim { display: block; position: fixed; inset: 0; background: rgba(0, 0, 0, 0.4); z-index: 9; }}td.go { color: var(--muted); width: 1.5rem; text-align: right; font-size: 1.1rem; }tbody tr.click:hover td.go { color: var(--link); }.detail h3 { margin: 0; font-size: 1rem; }.block { background: var(--surface); border-radius: 8px; padding: 10px 12px; white-space: pre-wrap; overflow-wrap: anywhere; font-size: 0.8125rem; line-height: 1.55; }.turn { display: grid; gap: 4px; }.turn .who { font-size: 0.6875rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }details.reasoning summary { cursor: pointer; color: var(--link); font-size: 0.8125rem; }details.reasoning .block { margin-top: 6px; max-height: 320px; overflow: auto; }.crit-row { display: grid; grid-template-columns: minmax(0, 11rem) 118px minmax(0, 1fr); gap: 10px; font-size: 0.8125rem; padding: 6px 0; border-bottom: 1px solid var(--border); }.crit-row:last-child { border-bottom: 0; }
.train { border: 1px solid var(--border); border-radius: 8px; padding: 16px; display: grid; gap: 14px; margin-bottom: 16px; }.train-head { display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; }.kv { display: flex; gap: 18px; flex-wrap: wrap; font-size: 0.8125rem; color: var(--text-2); }.kv b { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }.chart { width: 100%; height: auto; display: block; }.legend { display: flex; gap: 16px; font-size: 0.75rem; color: var(--muted); }.legend i { display: inline-block; width: 14px; height: 2px; vertical-align: middle; margin-right: 6px; }.ck { display: grid; grid-template-columns: 5rem minmax(0, 1fr) auto; gap: 10px; align-items: center; font-size: 0.8125rem; padding: 6px 0; border-top: 1px solid var(--border); }.ck code { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.copy { background: none; border: 1px solid var(--border); border-radius: 999px; padding: 2px 10px; cursor: pointer; font-size: 0.75rem; }@media (prefers-reduced-motion: reduce) { * { animation: none !important; } }</style></head><body><div class="app"> <nav class="side" aria-label="Sections"> <div class="brand"><span class="ring" aria-hidden="true"></span>machine</div> <a class="nav-item" href="#overview" data-view="overview"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 7.5 8 3l5.5 4.5V13h-11z"/></svg>Overview</a> <a class="nav-item" href="#activity" data-view="activity"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M1.5 8h3l2-4.5 3 9 2-4.5h3"/></svg>Activity</a> <a class="nav-item" href="#machines" data-view="machines"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="8" r="5.5"/><circle cx="8" cy="8" r="2"/></svg>Machines</a> <a class="nav-item" href="#runs" data-view="runs"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 4h10M3 8h10M3 12h6"/></svg>Runs</a> <a class="nav-item" href="#training" data-view="training"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3v10.5h12"/><path d="M4.5 5.5c2 0 3 5 5 5.5s2.5-.5 3.5-1"/></svg>Training</a> <div class="side-foot"> <span class="live" id="live"><span class="dot"></span><span id="live-label">connecting</span></span> <span id="spend-foot"></span> </div> </nav> <main id="main"></main></div>
<script>const $ = (s, el = document) => el.querySelector(s);// A fine-tuned checkpoint's sampler path is long; show its run id's start and the checkpoint name.// A candidate's runs are labelled "candidate:<id>"; the id's last characters are enough to tell candidates apart.function shortVersion(version) { return version.startsWith("candidate:") ? `candidate …${version.slice(-4)}` : version;}
function shortModel(model) { const m = /^tinker:\/\/([0-9a-f]{8})[^/]*\/sampler_weights\/(.+)$/.exec(model ?? ""); return m ? `checkpoint ${m[1]}…/${m[2]}` : model;}
const esc = (s) => String(s ?? "").replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]);const money = (x) => (x === undefined || x === null ? "—" : x < 0.01 && x > 0 ? `$${x.toFixed(4)}` : `$${x.toFixed(2)}`);const pct = (x) => (x === undefined ? "—" : `${Math.round(x * 100)}%`);const ago = (iso) => { if (!iso) return "—"; const s = (Date.now() - new Date(iso).getTime()) / 1000; if (s < 60) return `${Math.max(0, Math.round(s))}s ago`; if (s < 3600) return `${Math.round(s / 60)}m ago`; if (s < 86400) return `${Math.round(s / 3600)}h ago`; return `${Math.round(s / 86400)}d ago`;};const clock = (iso) => new Date(iso).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: false });const meter = (x) => `<span class="score"><span class="meter"><span style="width:${Math.round((x ?? 0) * 100)}%"></span></span>${x === undefined ? "—" : x.toFixed(2)}</span>`;const css = (name) => getComputedStyle(document.documentElement).getPropertyValue(name).trim();
const state = { machines: [], runs: [], stats: null, training: [], events: [], filter: "", selected: null, view: "overview", config: {}, grading: new Set(), notice: "" };
async function load(what) { const get = (p) => fetch(p).then((r) => r.json()); if (!what || what.includes("machines")) state.machines = await get("/api/machines"); if (!what || what.includes("runs")) [state.runs, state.stats] = await Promise.all([get("/api/runs?limit=1000"), get("/api/stats")]); if (!what || what.includes("training")) state.training = await get("/api/training"); if (!what) state.config = await get("/api/config");}
// --- events -------------------------------------------------------------function describe(e) { const p = (v) => esc(typeof v === "string" ? v : JSON.stringify(v ?? "")); switch (e.type) { case "run_start": return [`started`, `${e.harness ? `${esc(e.harness)} · ` : ""}${p(e.input)}`]; case "step": return [`step ${e.step}`, "calls the model"]; case "tool_call": return [`tool`, `${esc(e.name)} ${p(JSON.stringify(e.input ?? {})).slice(0, 160)}`]; case "tool_result": return [`result`, `${esc(e.name)} → ${p(e.preview)}`]; case "reply": return [`replied`, p(e.preview)]; case "run_end": return [`finished`, `${e.costUsd ? money(e.costUsd) + " · " : ""}${p(e.output)}`]; case "graded": return [`scored ${Number(e.total).toFixed(2)}`, e.below?.length ? `below 1: ${esc(e.below.join(", "))}` : "every criterion met"]; case "run_error": return [`failed`, p(e.error)]; case "feedback": return [`marked ${esc(e.kind)}`, p(e.note ?? "")]; default: return [esc(e.type), ""]; }}const kindClass = (e) => (e.type === "run_error" ? "bad" : e.type === "graded" && e.total === 1 ? "good" : e.type === "graded" ? "bad" : "");
function feedHtml(events, limit, fresh = 0) { if (!events.length) return `<div class="empty">Nothing yet. Run a machine (<code>machine pirate</code> or <code>machine suite pirate</code>) and its steps appear here as they happen.</div>`; return `<ul class="feed">${events.slice(-limit).reverse().map((e, i) => { const [k, x] = describe(e); return `<li class="${i < fresh ? "fresh" : ""}"><span class="t">${clock(e.at)}</span><span class="m" title="${esc(e.machine)}">${esc(e.machine)}</span><span class="x"><span class="k ${kindClass(e)}">${k}</span> ${x}</span></li>`; }).join("")}</ul>`;}
/** Runs and sessions that started and have not finished, from the event log. */function runningNow() { const open = new Map(); const cutoff = Date.now() - 30 * 60_000; for (const e of state.events) { const key = e.run ?? (e.session ? `${e.machine}#${e.session}` : null); if (!key) continue; if (e.type === "run_start") open.set(key, { ...e, last: e }); else if (e.type === "run_end" || e.type === "run_error") { open.delete(key); if (e.session) open.delete(`${e.machine}#${e.session}`); } else if (open.has(key)) open.get(key).last = e; else if (e.session && open.has(`${e.machine}#${e.session}`)) open.get(`${e.machine}#${e.session}`).last = e; } return [...open.values()].filter((e) => new Date(e.last.at).getTime() > cutoff);}
function runningHtml() { const now = runningNow(); if (!now.length) return `<div class="empty">No machine is running right now.</div>`; return `<div class="running">${now.map((e) => { const [k, x] = describe(e.last); return `<div class="item"><div><span class="name">${esc(e.machine)}</span> <span class="pill live">${e.session ? "session" : esc(e.harness ?? "run")}</span> <span class="dim">${esc(e.model ?? "")}</span></div><div class="what"><span class="k">${k}</span> ${x}</div><div class="dim" style="font-size:.75rem">started ${ago(e.at)}</div></div>`; }).join("")}</div>`;}
// --- views --------------------------------------------------------------function overview() { const s = state.stats ?? { runs: 0, runsToday: 0, graded: 0, costUsd: 0, byMachine: {} }; const trainingCost = state.training.reduce((t, r) => t + (r.costUsd ?? 0), 0); const machines = state.machines; const rows = machines.map((m) => ({ m, st: s.byMachine[m.name] })).sort((a, b) => (b.st?.lastAt ?? "").localeCompare(a.st?.lastAt ?? "")); const latest = state.training.at(-1); return ` <h1>Overview</h1> <p class="sub">${machines.length} machines in this workspace · live from <code>.machine/</code></p> <div class="stats"> <div class="stat"><div class="k">Runs</div><div class="v">${s.runs}</div><div class="d">${s.runsToday} in the last day</div></div> <div class="stat"><div class="k">Graded</div><div class="v">${s.graded}</div><div class="d">${s.runs ? pct(s.graded / s.runs) : "—"} of runs</div></div> <div class="stat"><div class="k">Spend on runs</div><div class="v">${money(s.costUsd)}</div><div class="d">runs and judges, estimated</div></div> <div class="stat"><div class="k">Training</div><div class="v">${state.training.length}</div><div class="d">${money(trainingCost)} estimated</div></div> <div class="stat"><div class="k">Running now</div><div class="v">${runningNow().length}</div><div class="d">runs and sessions</div></div> </div> <div class="grid2"> <div> <h2><span>Machines</span><a href="#machines">All machines</a></h2> <div class="table-wrap"><table> <thead><tr><th>Machine</th><th class="n">Runs</th><th>Recent mean</th><th class="n">Pass</th><th class="n">Spend</th><th>Last run</th></tr></thead> <tbody>${rows.map(({ m, st }) => `<tr class="click" data-machine="${esc(m.name)}"><td class="name">${esc(m.name)}</td><td class="n">${st?.runs ?? 0}</td><td>${st?.mean !== undefined ? meter(st.mean) : '<span class="dim">—</span>'}</td><td class="n">${pct(st?.passRate)}</td><td class="n">${money(st?.costUsd)}</td><td class="dim">${ago(st?.lastAt)}</td></tr>`).join("")}</tbody> </table></div> ${latest ? `<h2><span>Latest training · ${esc(latest.name)}</span><a href="#training">Training</a></h2>${trainingChart(latest, 200, 600)}` : ""} </div> <div> <h2><span>Running now</span></h2> <div id="running">${runningHtml()}</div> <h2><span>Live activity</span><a href="#activity">All activity</a></h2> <div id="feed">${feedHtml(state.events, 14)}</div> </div> </div>`;}
function activity() { const names = [...new Set(state.events.map((e) => e.machine))].sort(); const events = state.filter ? state.events.filter((e) => e.machine === state.filter) : state.events; return ` <h1>Activity</h1> <p class="sub">Every step machines report, newest first. Any process that runs a machine appends to <code>.machine/events.jsonl</code>.</p> <div class="toolbar"><select id="filter" aria-label="Machine"><option value="">All machines</option>${names.map((n) => `<option ${n === state.filter ? "selected" : ""}>${esc(n)}</option>`).join("")}</select></div> <h2><span>Running now</span></h2><div id="running">${runningHtml()}</div> <h2><span>Events</span></h2><div id="feed">${feedHtml(events, 300)}</div>`;}
function machinesView() { const s = state.stats?.byMachine ?? {}; return ` <h1>Machines</h1> <p class="sub">Each machine is code under <code>machines/</code>. Children inherit every criterion of their parent and add their own.</p> <div class="cards">${state.machines.map((m) => { const st = s[m.name]; return `<div class="card ${m.parent ? "child" : ""}"> <div><span class="name">${esc(m.name)}</span>${m.parent ? ` <span class="pill">child of ${esc(m.parent)}</span>` : ""}</div> <div class="intent">${esc(m.intent)}</div> <ul class="crit">${m.criteria.map((c) => `<li><span>${esc(c.id)}${c.inherited ? ' <span class="g">inherited</span>' : ""}</span><span class="g">${esc(c.grader.split(":")[0])} · ${c.weight}</span></li>`).join("")}</ul> <div class="foot"><span>${esc(m.model)}</span>${m.tools.length ? `<span>tools: ${esc(m.tools.join(", "))}</span>` : ""}<span>${st?.runs ?? 0} runs</span>${st?.mean !== undefined ? `<span>mean ${st.mean.toFixed(2)}</span>` : ""}</div> <button class="go" data-machine="${esc(m.name)}">Runs</button> </div>`; }).join("")}</div>`;}
function runsView() { const runs = state.filter ? state.runs.filter((r) => r.machine === state.filter) : state.runs; const names = [...new Set(state.runs.map((r) => r.machine))].sort(); const ungraded = runs.filter((r) => r.total === undefined && r.harness !== "echo").length; const busy = state.grading.has(`all:${state.filter}`); return ` <h1>Runs</h1> <p class="sub">${state.filter ? (state.stats?.byMachine?.[state.filter]?.runs ?? runs.length) : (state.stats?.runs ?? runs.length)} stored runs${state.filter ? ` of ${esc(state.filter)}` : ""}${runs.length > 400 ? ", newest 400 shown" : ""}. Select one to see its trajectory and scorecard.</p> <div class="toolbar"><select id="filter" aria-label="Machine"><option value="">All machines</option>${names.map((n) => `<option ${n === state.filter ? "selected" : ""}>${esc(n)}</option>`).join("")}</select> ${state.filter && ungraded ? `<button class="copy" data-grade-all="${esc(state.filter)}" ${busy ? "disabled" : ""}>${busy ? "Grading…" : `Grade ${ungraded} ungraded`}</button>` : ""} <span class="dim" style="font-size:.75rem">judge: ${esc(state.config.judgeModel ?? "")} · up to ${money(state.config.gradeBudgetUsd)} per request</span> ${state.notice ? `<span class="dim" style="font-size:.75rem">${esc(state.notice)}</span>` : ""}</div> <div class="split"> <div class="table-wrap"><table> <thead><tr><th>When</th><th>Machine</th><th>Input</th><th>Score</th><th class="n">Cost</th><th></th></tr></thead> <tbody>${runs.slice(0, 400).map((r) => `<tr class="click ${state.selected?.id === r.id ? "sel" : ""}" data-run="${esc(r.id)}" data-machine="${esc(r.machine)}" tabindex="0" role="link" aria-label="Open run ${esc(r.id)}"> <td class="dim" style="white-space:nowrap">${ago(r.startedAt)}</td> <td class="name">${esc(r.machine)}${r.session ? ' <span class="pill">session</span>' : ""}${r.harness === "echo" ? ' <span class="pill">echo dry run</span>' : ""}</td> <td><div class="trunc">${esc(r.input)}</div><div class="dim" style="font-size:.75rem">${r.version ? `${esc(shortVersion(r.version))} · ` : ""}${r.harness === "echo" ? "no model called" : esc(shortModel(r.model))}${r.toolCalls ? ` · ${r.toolCalls} tool calls` : ""}${r.reasoning ? " · reasoning" : ""}${r.feedback?.length ? ` · ${esc(r.feedback.join("; "))}` : ""}</div></td> <td>${r.total !== undefined ? meter(r.total) : gradeButton(r.machine, r.id)}</td> <td class="n">${money(r.costUsd)}</td><td class="go" aria-hidden="true">›</td></tr>`).join("")}</tbody> </table></div> <div id="detail">${state.selected ? `<div class="scrim" data-close></div>${detailHtml(state.selected)}` : `<div class="empty">Select a run.</div>`}</div> </div>`;}
function detailHtml(run) { const sc = run.scorecard; const turns = run.trajectory.map((m) => { if (m.role === "user") return `<div class="turn"><div class="who">user</div><div class="block">${esc(m.content)}</div></div>`; if (m.role === "tool") return `<div class="turn"><div class="who">${esc(m.name)} result</div><div class="block mono">${esc(m.content.slice(0, 4000))}</div></div>`; const reasoning = m.reasoning ? `<details class="reasoning"><summary>Reasoning · ${m.reasoning.length.toLocaleString()} characters</summary><div class="block">${esc(m.reasoning)}</div></details>` : ""; if (m.toolCallId) return `<div class="turn">${reasoning}<div class="who">calls ${esc(m.name)}</div><div class="block mono">${esc(JSON.stringify(m.toolInput ?? {}, null, 2).slice(0, 4000))}</div></div>`; return `<div class="turn">${reasoning}<div class="who">assistant</div><div class="block">${esc(m.content)}</div></div>`; }).join(""); return `<div class="detail" role="dialog" aria-label="Run ${esc(run.id)}"> <div class="detail-head"><div><h3 class="name">${esc(run.machine)}</h3><div class="dim">${esc(run.id)} · ${run.version ? `${esc(shortVersion(run.version))} · ` : ""}${run.harness === "echo" ? "echo dry run, no model called" : esc(shortModel(run.model))} · ${esc(run.harness)}${run.revision ? ` · ${esc(run.revision)}` : ""}</div></div><button class="close" data-close aria-label="Close">✕</button></div> ${sc ? `<div><div class="dim" style="margin-bottom:6px">Score ${sc.total.toFixed(2)}${sc.usage?.costUsd ? ` · grading cost ${money(sc.usage.costUsd)}` : ""} ${gradeButton(run.machine, run.id, "Grade again")}</div>${Object.entries(sc.criteria).map(([id, c]) => `<div class="crit-row"><span class="name">${esc(id)}</span>${meter(c.score)}<span class="dim">${esc(c.reason)}</span></div>`).join("")}</div>` : `<div class="dim">Not graded yet. ${gradeButton(run.machine, run.id)}</div>`} ${run.feedback?.length ? `<div>${run.feedback.map((f) => `<span class="pill">${esc(f.kind)}${f.note ? `: ${esc(f.note)}` : ""}</span>`).join(" ")}</div>` : ""} ${turns} </div>`;}
function gradeButton(machine, id, label = "Grade") { const busy = state.grading.has(`${machine}/${id}`); return `<button class="copy" data-grade="${esc(id)}" data-grade-machine="${esc(machine)}" ${busy ? "disabled" : ""}>${busy ? "Grading…" : label}</button>`;}
async function grade(machine, id) { const key = id ? `${machine}/${id}` : `all:${machine}`; state.grading.add(key); state.notice = ""; render(); try { const q = new URLSearchParams({ machine, ...(id ? { id } : {}) }); const res = await fetch(`/api/grade?${q}`, { method: "POST", headers: { "x-machine-dashboard": "1" } }); const body = await res.json(); if (!res.ok) throw new Error(body.error ?? `HTTP ${res.status}`); const failed = body.graded.filter((g) => g.error); state.notice = `Graded ${body.graded.length - failed.length} of ${body.graded.length} with ${body.judge} for ${money(body.spentUsd)}${failed.length ? `. Failed: ${failed[0].error}` : ""}`; } catch (error) { state.notice = `Grading failed: ${error.message}`; } finally { state.grading.delete(key); } await load(["runs"]); if (id && state.selected?.id === id) state.selected = await fetch(`/api/run?machine=${encodeURIComponent(machine)}&id=${encodeURIComponent(id)}`).then((r) => r.json()); render();}
function trainingChart(t, height = 220, width = 1100) { const pts = t.steps; if (!pts.length) return `<div class="empty">No steps logged yet.</div>`; // Drawn at about its display size and scaled uniformly, so labels keep their shape. const W = width, H = height, L = 44, R = 12, T = 10, B = 26; const ys = pts.flatMap((p) => [p.train, p.test]).filter((v) => typeof v === "number"); const hi = Math.max(...ys) * 1.08, lo = 0; const maxStep = Math.max(1, pts.at(-1).step); const x = (s) => L + ((W - L - R) * s) / maxStep; const y = (v) => T + (H - T - B) * (1 - (v - lo) / (hi - lo)); const line = (key) => pts.filter((p) => typeof p[key] === "number").map((p, i) => `${i ? "L" : "M"}${x(p.step).toFixed(1)},${y(p[key]).toFixed(1)}`).join(" "); const ticks = [0, hi / 2, hi].map((v) => `<line x1="${L}" x2="${W - R}" y1="${y(v)}" y2="${y(v)}" stroke="${css("--border")}" stroke-width="1"/><text x="${L - 6}" y="${y(v) + 4}" text-anchor="end" font-size="11" fill="${css("--muted")}">${v.toFixed(2)}</text>`).join(""); const xt = [0, Math.round(maxStep / 2), maxStep].map((s) => `<text x="${x(s)}" y="${H - 8}" text-anchor="middle" font-size="11" fill="${css("--muted")}">${s}</text>`).join(""); const testPts = pts.filter((p) => typeof p.test === "number").map((p) => `<circle cx="${x(p.step)}" cy="${y(p.test)}" r="3" fill="${css("--link")}"/>`).join(""); return `<svg class="chart" viewBox="0 0 ${W} ${H}" role="img" aria-label="Loss by step for ${esc(t.name)}"> ${ticks}${xt} <path d="${line("train")}" fill="none" stroke="${css("--accent")}" stroke-width="2" vector-effect="non-scaling-stroke"/> <path d="${line("test")}" fill="none" stroke="${css("--link")}" stroke-width="1.5" stroke-dasharray="4 3" vector-effect="non-scaling-stroke"/> ${testPts} </svg> <div class="legend"><span><i style="background:${css("--accent")}"></i>training loss (NLL)</span><span><i style="background:${css("--link")}"></i>held-out loss</span><span>x: step</span></div>`;}
function trainingView() { if (!state.training.length) return `<h1>Training</h1><p class="sub">Fine-tunes logged under <code>.machine/training/</code>.</p><div class="empty">No training yet. Run <code>scripts/train_sft.py data.jsonl .machine/training/<name></code> and its losses appear here as it trains.</div>`; return `<h1>Training</h1><p class="sub">Fine-tunes logged under <code>.machine/training/</code>, newest last. Charts update while a run trains.</p> ${state.training.slice().reverse().map((t) => { const first = t.steps.find((p) => typeof p.test === "number")?.test; const last = [...t.steps].reverse().find((p) => typeof p.test === "number")?.test; return `<section class="train"> <div class="train-head"><div><span class="name">${esc(t.name)}</span> <span class="dim">· ${esc(t.model ?? "")}</span></div><span class="dim">updated ${ago(t.updatedAt)}</span></div> <div class="kv"><span>steps <b>${t.steps.length}</b></span><span>epochs <b>${t.epochs ?? "—"}</b></span><span>examples <b>${t.examples ?? "—"}</b></span><span>learning rate <b>${t.learningRate ? t.learningRate.toExponential(2) : "—"}</b></span><span>LoRA rank <b>${t.loraRank ?? "—"}</b></span><span>tokens <b>${t.tokens.toLocaleString()}</b></span><span>cost <b>${money(t.costUsd)}</b></span>${first !== undefined ? `<span>held-out loss <b>${first.toFixed(3)} → ${last.toFixed(3)}</b></span>` : ""}</div> ${trainingChart(t)} <div>${t.checkpoints.map((c) => `<div class="ck"><span class="name">${esc(c.name)}</span><code title="${esc(c.sampler ?? "")}">${esc(c.sampler ?? "")}</code><button class="copy" data-copy="${esc(c.sampler ?? "")}">Copy</button></div>`).join("")}</div> </section>`; }).join("")}`;}
// --- render & routing -----------------------------------------------------const views = { overview, activity, machines: machinesView, runs: runsView, training: trainingView };/** #run/<machine>/<id> opens a run; machine names may contain "/". */async function openFromHash() { const h = decodeURIComponent(location.hash.slice(1)); if (!h.startsWith("run/")) return false; const parts = h.slice(4).split("/"); const id = parts.pop(), machine = parts.join("/"); if (state.selected?.id !== id) { const res = await fetch(`/api/run?machine=${encodeURIComponent(machine)}&id=${encodeURIComponent(id)}`); state.selected = res.ok ? await res.json() : null; } return true;}
function render() { const h = location.hash.slice(1); state.view = h.startsWith("run/") ? "runs" : (h || "overview").split("/")[0]; if (!views[state.view]) state.view = "overview"; document.querySelectorAll(".nav-item").forEach((a) => (a.dataset.view === state.view ? a.setAttribute("aria-current", "page") : a.removeAttribute("aria-current"))); $("#main").innerHTML = views[state.view](); $("#spend-foot").textContent = state.stats ? `${money(state.stats.costUsd)} on runs` : "";}
document.addEventListener("click", async (e) => { const g = e.target.closest("[data-grade]"); if (g) { e.stopPropagation(); grade(g.dataset.gradeMachine, g.dataset.grade); return; } const ga = e.target.closest("[data-grade-all]"); if (ga) { grade(ga.dataset.gradeAll); return; } if (e.target.closest("[data-close]")) { state.selected = null; location.hash = "runs"; return; } const row = e.target.closest("[data-run]"); if (row) { location.hash = `run/${row.dataset.machine}/${row.dataset.run}`; return; } const m = e.target.closest("[data-machine]"); if (m) { state.filter = m.dataset.machine; state.selected = null; location.hash = "runs"; return; } const c = e.target.closest("[data-copy]"); if (c) { try { await navigator.clipboard.writeText(c.dataset.copy); c.textContent = "Copied"; } catch { c.textContent = "Select it"; } setTimeout(() => (c.textContent = "Copy"), 1500); }});document.addEventListener("change", (e) => { if (e.target.id === "filter") { state.filter = e.target.value; state.selected = null; render(); }});window.addEventListener("hashchange", async () => { if (!(await openFromHash()) && state.view === "runs" && !location.hash.startsWith("#run/")) state.selected = null; render();});document.addEventListener("keydown", (e) => { if (e.key === "Escape" && state.selected) { state.selected = null; location.hash = "runs"; } const row = e.target.closest?.("[data-run]"); if (row && (e.key === "Enter" || e.key === " ")) { e.preventDefault(); location.hash = `run/${row.dataset.machine}/${row.dataset.run}`; }});
// Live: the event stream refreshes the feed at once, and runs and training shortly after.let refreshTimer = null;function refreshSoon(what) { clearTimeout(refreshTimer); refreshTimer = setTimeout(async () => { await load(what); if (!["runs"].includes(state.view) || !state.selected) render(); }, 600);}function connect() { const es = new EventSource("/api/events"); es.addEventListener("open", () => { $("#live").classList.add("on"); $("#live-label").textContent = "live"; }); es.addEventListener("error", () => { $("#live").classList.remove("on"); $("#live-label").textContent = "reconnecting"; }); es.addEventListener("backlog", (m) => { state.events = JSON.parse(m.data); render(); }); es.addEventListener("event", (m) => { const ev = JSON.parse(m.data); state.events.push(ev); if (state.events.length > 1000) state.events = state.events.slice(-1000); const feed = $("#feed"); if (feed) feed.innerHTML = feedHtml(state.filter && state.view === "activity" ? state.events.filter((x) => x.machine === state.filter) : state.events, state.view === "activity" ? 300 : 14, 1); const running = $("#running"); if (running) running.innerHTML = runningHtml(); if (["run_end", "graded", "feedback", "run_error"].includes(ev.type)) refreshSoon(["runs"]); }); es.addEventListener("training", () => refreshSoon(["training"]));}
load().then(async () => { await openFromHash(); render(); connect(); });setInterval(() => { if (state.view === "overview") { const r = $("#running"); if (r) r.innerHTML = runningHtml(); } }, 5000);</script></body></html>