"use strict"; const FALLBACK_FEEDBACK = "Revise the review to better match the rubric's content, tone, style, and length."; const state = { index: null, trajectories: [], visible: [], checkpoints: [], payload: null, activeRound: 0, view: "trajectory", }; const byId = (id) => document.getElementById(id); const finite = (value) => value !== null && value !== undefined && Number.isFinite(Number(value)); const number = (value) => (finite(value) ? Number(value) : null); function formatScore(value, digits = 3) { return finite(value) ? Number(value).toFixed(digits) : "N/A"; } function formatSigned(value, digits = 3) { if (!finite(value)) return "N/A"; const numeric = Number(value); return `${numeric > 0 ? "+" : ""}${numeric.toFixed(digits)}`; } function formatPercent(value, digits = 1) { if (!finite(value)) return "N/A"; return `${(Number(value) * 100).toFixed(digits)}%`; } function mean(values) { const valid = values.filter(finite).map(Number); return valid.length ? valid.reduce((total, value) => total + value, 0) / valid.length : null; } function words(value) { return String(value || "").trim().split(/\s+/).filter(Boolean).length; } function cleanResearchText(value) { return String(value || "") .replace(//gi, "\n") .replace(/<\/?(?:response|rubric)>/gi, "") .replace(/&(#x[0-9a-f]+|#\d+|quot|amp|apos|lt|gt|nbsp);/gi, (match, entity) => { const named = { quot: '"', amp: "&", apos: "'", lt: "<", gt: ">", nbsp: " " }; const lowered = entity.toLowerCase(); if (Object.prototype.hasOwnProperty.call(named, lowered)) return named[lowered]; const numeric = lowered.startsWith("#x") ? Number.parseInt(lowered.slice(2), 16) : Number.parseInt(lowered.slice(1), 10); if (!Number.isInteger(numeric) || numeric < 0 || numeric > 0x10ffff) return match; try { return String.fromCodePoint(numeric); } catch (_error) { return match; } }) .trim(); } function appendInline(container, text) { const chunks = String(text).split(/(\*\*[^*]+\*\*)/g); chunks.forEach((chunk) => { if (chunk.startsWith("**") && chunk.endsWith("**") && chunk.length > 4) { const strong = document.createElement("strong"); strong.textContent = chunk.slice(2, -2); container.appendChild(strong); } else { container.appendChild(document.createTextNode(chunk)); } }); } function renderStructured(container, value) { container.replaceChildren(); const text = cleanResearchText(value); if (!text) { const empty = document.createElement("p"); empty.textContent = "No text was logged."; container.appendChild(empty); return; } const blocks = text.split(/\n\s*\n/).filter((block) => block.trim()); blocks.forEach((block) => { const lines = block.split("\n").filter((line) => line.trim()); const numbered = lines.length > 1 && lines.every((line) => /^\s*\d+[.)]\s+/.test(line)); if (numbered) { const list = document.createElement("ol"); lines.forEach((line) => { const item = document.createElement("li"); appendInline(item, line.replace(/^\s*\d+[.)]\s+/, "")); list.appendChild(item); }); container.appendChild(list); return; } const paragraph = document.createElement("p"); lines.forEach((line, index) => { if (index) paragraph.appendChild(document.createElement("br")); appendInline(paragraph, line); }); container.appendChild(paragraph); }); } function addOption(select, value, label) { const option = document.createElement("option"); option.value = String(value); option.textContent = label; select.appendChild(option); } function badge(label, className = "") { const element = document.createElement("span"); element.className = `badge ${className}`.trim(); element.textContent = label; return element; } function metricCell(label, value, detail, className = "") { const cell = document.createElement("div"); cell.className = `metric-cell ${className}`.trim(); const name = document.createElement("span"); name.textContent = label; const strong = document.createElement("strong"); strong.textContent = value; cell.append(name, strong); if (detail) { const small = document.createElement("small"); small.textContent = detail; cell.appendChild(small); } return cell; } function scorePill(label, value, className = "") { const pill = document.createElement("div"); pill.className = `score-pill ${className}`.trim(); const name = document.createElement("span"); name.textContent = label; const strong = document.createElement("strong"); strong.textContent = value; pill.append(name, strong); return pill; } function deltaClass(value) { if (!finite(value) || Math.abs(Number(value)) < 1e-9) return ""; return Number(value) > 0 ? "positive" : "negative"; } function outcomeLabel(value) { const labels = { improved: "Gold improved", unchanged: "Gold unchanged", worsened: "Gold worsened" }; return labels[value] || String(value || "Outcome unavailable"); } function trajectorySummary(record, payload = null) { return (payload && (payload.trajectory || payload.summary)) || record || {}; } function trajectoryId(record) { return String(record.id || record.trajectory_id || record.path || ""); } function trajectoryPath(record) { return String(record.path || record.data_path || `data/trajectories/${trajectoryId(record)}.json`); } function checkpointId(record) { return String(record.checkpoint_id || `${record.run_id || record.run_label || "run"}:${record.step}:${record.uid}`); } function checkpointLabel(checkpoint) { const title = checkpoint.title || checkpoint.context_label || checkpoint.uid || "Source example"; const run = checkpoint.run_label || checkpoint.run_id || "run"; return `Step ${checkpoint.step} · ${title} · ${run}`; } function buildCheckpointIndex() { const supplied = Array.isArray(state.index.checkpoints) ? state.index.checkpoints : []; const byKey = new Map(supplied.map((item) => [String(item.id || checkpointId(item)), { ...item }])); state.trajectories.forEach((record) => { const id = checkpointId(record); if (!byKey.has(id)) { byKey.set(id, { id, run_id: record.run_id, run_label: record.run_label, step: record.step, uid: record.uid, title: record.title, author: record.author, category: record.category, }); } const checkpoint = byKey.get(id); checkpoint.id = id; }); state.checkpoints = [...byKey.values()].sort((a, b) => Number(a.step) - Number(b.step) || String(a.run_id).localeCompare(String(b.run_id))); } function populateCheckpointSelect(preferred = null) { const select = byId("checkpoint-select"); const current = preferred || select.value; select.replaceChildren(); state.checkpoints.forEach((checkpoint) => addOption(select, checkpoint.id, checkpointLabel(checkpoint))); if (state.checkpoints.some((checkpoint) => checkpoint.id === current)) select.value = current; if (!select.value && state.checkpoints.length) select.value = state.checkpoints[0].id; } function applyTrajectoryFilter(preferredId = null) { const checkpoint = byId("checkpoint-select").value; const outcome = byId("outcome-select").value; let visible = state.trajectories.filter((record) => checkpointId(record) === checkpoint); if (outcome !== "all") visible = visible.filter((record) => String(record.outcome) === outcome); if (!visible.length && outcome !== "all") { byId("outcome-select").value = "all"; visible = state.trajectories.filter((record) => checkpointId(record) === checkpoint); } state.visible = visible.sort((a, b) => Number(a.rubric_idx) - Number(b.rubric_idx) || Number(a.judge_idx) - Number(b.judge_idx)); const select = byId("trajectory-select"); const current = preferredId || select.value; select.replaceChildren(); state.visible.forEach((record) => { const tie = Number(record.tie_count || 1) > 1 ? ` · ${record.tie_count}-way tie` : ""; addOption( select, trajectoryId(record), `Rubric ${record.rubric_idx} · path ${record.judge_idx} · selected r${record.selected_round}${tie} · ${outcomeLabel(record.outcome)}`, ); }); if (state.visible.some((record) => trajectoryId(record) === current)) select.value = current; if (!select.value && state.visible.length) select.value = trajectoryId(state.visible[0]); updateTrajectoryPosition(); } function selectedRecord() { const id = byId("trajectory-select").value; return state.visible.find((record) => trajectoryId(record) === id) || null; } function updateTrajectoryPosition() { const id = byId("trajectory-select").value; const index = state.visible.findIndex((record) => trajectoryId(record) === id); byId("trajectory-position").textContent = index >= 0 ? `${index + 1} of ${state.visible.length}` : "No paths"; byId("previous-trajectory").disabled = index <= 0; byId("next-trajectory").disabled = index < 0 || index >= state.visible.length - 1; } async function loadSelectedTrajectory() { const record = selectedRecord(); updateTrajectoryPosition(); if (!record) { showError("No trajectory matches these filters."); return; } byId("loading").hidden = false; byId("trajectory-content").hidden = true; byId("error").hidden = true; try { const response = await fetch(trajectoryPath(record)); if (!response.ok) throw new Error(`HTTP ${response.status}`); state.payload = await response.json(); state.activeRound = 0; renderTrajectory(record, state.payload); byId("loading").hidden = true; byId("trajectory-content").hidden = false; } catch (error) { showError(`Could not load this trajectory (${error.message}).`); } } function showError(message) { byId("loading").hidden = true; byId("trajectory-content").hidden = true; byId("error").textContent = message; byId("error").hidden = false; } function extractContext(payload) { if (typeof payload.context === "string") return { text: payload.context }; return payload.context || payload.source_context || {}; } function extractRubric(payload) { if (typeof payload.rubric === "string") return { parsed: payload.rubric, generated: payload.rubric }; return payload.rubric || {}; } function extractPrompts(payload) { return payload.prompts || payload.prompt || {}; } function renderTrajectory(record, payload) { const summary = trajectorySummary(record, payload); const checkpoint = payload.checkpoint || {}; const context = extractContext(payload); const rubric = extractRubric(payload); const rounds = payload.rounds || payload.turns || []; payload.rounds = rounds; const title = context.title || checkpoint.title || record.title || "Target book"; byId("record-eyebrow").textContent = `Step ${checkpoint.step ?? record.step} · ${checkpoint.run_label || record.run_label || checkpoint.run_id || record.run_id}`; byId("record-title").textContent = title; byId("record-subtitle").textContent = [context.author || record.author, context.category || record.category].filter(Boolean).join(" · "); byId("record-id").textContent = `${checkpoint.uid || record.uid} · rubric ${summary.rubric_idx ?? record.rubric_idx} · path ${summary.judge_idx ?? record.judge_idx}`; renderSummary(summary, rounds); renderContext(context, payload.target_response || payload.target || payload.reference_response || ""); renderPrompts(extractPrompts(payload)); renderRubric(rubric, summary, record); renderRoundTrack(rounds); renderRoundDetail(rounds); renderHistory(rounds); refreshIcons(); } function summaryValue(summary, ...keys) { for (const key of keys) if (summary[key] !== undefined) return summary[key]; return null; } function renderSummary(summary, rounds) { const initialGold = summaryValue(summary, "initial_gold") ?? rounds[0]?.gold_score; const lastGold = summaryValue(summary, "last_gold") ?? rounds.at(-1)?.gold_score; const selectedGold = summaryValue(summary, "selected_gold", "selected_gold_weighted"); const bestGold = summaryValue(summary, "best_gold", "oracle_best_gold") ?? Math.max(...rounds.map((row) => Number(row.gold_score))); const selectedDelta = finite(selectedGold) && finite(initialGold) ? Number(selectedGold) - Number(initialGold) : null; const spearman = summaryValue(summary, "proxy_gold_spearman", "spearman"); const tieCount = Number(summary.tie_count || summary.selected_tie_count || 1); const selectedRound = summary.selected_round; const container = byId("trajectory-summary"); container.replaceChildren( metricCell("Initial gold", formatScore(initialGold), "round 0", "gold"), metricCell("Selected gold", formatScore(selectedGold), tieCount > 1 ? `mean of ${tieCount} tied rounds` : `round ${selectedRound}`, "gold"), metricCell("Selected change", formatSigned(selectedDelta), "selected minus initial", deltaClass(selectedDelta)), metricCell("Last gold", formatScore(lastGold), `round ${rounds.length - 1}`, "gold"), metricCell("Oracle best gold", formatScore(bestGold), "best logged state", "gold"), metricCell("Proxy-gold rank", formatScore(spearman), "Spearman across valid rounds", "proxy"), ); } function renderContext(context, target) { const metadata = [ ["Title", context.title], ["Author", context.author], ["Category", context.category], ["Store", context.store_label || context.store], ["Subtitle", context.subtitle], ["Price", context.price], ].filter(([, value]) => value !== null && value !== undefined && String(value).trim()); const list = byId("context-meta"); list.replaceChildren(); metadata.forEach(([label, value]) => { const wrapper = document.createElement("div"); const term = document.createElement("dt"); term.textContent = label; const definition = document.createElement("dd"); definition.textContent = String(value); wrapper.append(term, definition); list.appendChild(wrapper); }); renderStructured(byId("context-text"), context.text || context.context || ""); renderStructured(byId("target-response"), target); resetClamp("context-text", "context-toggle", "Show full context", "Collapse context"); } function renderMessages(container, messages) { container.replaceChildren(); (messages || []).forEach((message) => { const wrapper = document.createElement("article"); wrapper.className = "message"; const role = document.createElement("div"); role.className = "message-role"; role.textContent = message.role || "message"; const content = document.createElement("div"); content.className = "message-content"; content.textContent = cleanResearchText(message.content || ""); wrapper.append(role, content); container.appendChild(wrapper); }); if (!messages || !messages.length) { const empty = document.createElement("p"); empty.textContent = "No prompt messages were exported."; container.appendChild(empty); } } function renderPrompts(prompts) { const candidateMessages = prompts.candidate_messages || prompts.icl_messages || []; const rubricMessages = prompts.rubric_messages || prompts.rubric_prompt || []; renderMessages(byId("candidate-messages"), candidateMessages); renderMessages(byId("rubric-messages"), rubricMessages); byId("candidate-prompt-size").textContent = `${candidateMessages.length} messages · ${candidateMessages.reduce((total, item) => total + words(item.content), 0).toLocaleString()} words`; byId("rubric-prompt-size").textContent = `${rubricMessages.length} messages · ${rubricMessages.reduce((total, item) => total + words(item.content), 0).toLocaleString()} words`; } function renderRubric(rubric, summary, record) { const generated = rubric.generated || rubric.generated_rubric || rubric.parsed || rubric.parsed_rubric || ""; const parsed = rubric.parsed || rubric.parsed_rubric || generated; renderStructured(byId("rubric-text"), generated); renderStructured(byId("parsed-rubric"), parsed); const exact = Boolean(parsed); byId("rubric-status").textContent = exact ? "Exact logged rubric" : "Rubric unavailable"; byId("rubric-status").className = `status-badge ${exact ? "valid" : ""}`; byId("rubric-eyebrow").textContent = `Rubric ${summary.rubric_idx ?? record.rubric_idx} · shared by this judge path`; byId("parsed-rubric-size").textContent = `${words(parsed).toLocaleString()} words`; byId("parsed-rubric-details").hidden = parsed === generated; resetClamp("rubric-text", "rubric-toggle", "Show full rubric", "Collapse rubric"); } function resetClamp(contentId, buttonId, collapsedLabel, expandedLabel) { const content = byId(contentId); const button = byId(buttonId); content.classList.add("is-clamped"); button.setAttribute("aria-expanded", "false"); button.textContent = collapsedLabel; button.dataset.collapsedLabel = collapsedLabel; button.dataset.expandedLabel = expandedLabel; } function renderRoundTrack(rounds) { const track = byId("round-track"); track.replaceChildren(); rounds.forEach((round, index) => { const button = document.createElement("button"); const tie = Number(round.selection_weight || 0) > 0; button.type = "button"; button.className = `round-button${index === state.activeRound ? " active" : ""}${tie ? " tie" : ""}`; button.setAttribute("role", "option"); button.setAttribute("aria-selected", String(index === state.activeRound)); button.dataset.round = String(index); const top = document.createElement("div"); top.className = "round-button-top"; const label = document.createElement("span"); label.textContent = `Round ${round.round ?? index}`; const mark = document.createElement("span"); mark.className = "round-button-mark"; mark.textContent = round.selected_final ? "returned" : tie ? "top" : ""; top.append(label, mark); const scores = document.createElement("div"); scores.className = "round-button-scores"; const proxy = document.createElement("span"); proxy.textContent = `P ${formatScore(round.proxy_score, 2)}`; const gold = document.createElement("span"); gold.textContent = `G ${formatScore(round.gold_score, 2)}`; scores.append(proxy, gold); const delta = index ? Number(round.gold_score) - Number(rounds[index - 1].gold_score) : 0; const change = document.createElement("div"); change.className = `round-button-delta ${deltaClass(delta)}`.trim(); change.textContent = index ? `${formatSigned(delta, 2)} gold` : "initial state"; button.append(top, scores, change); button.addEventListener("click", () => setActiveRound(index)); track.appendChild(button); }); updateRoundControls(rounds.length); } function updateRoundControls(length) { byId("previous-round").disabled = state.activeRound <= 0; byId("next-round").disabled = state.activeRound >= length - 1; } function setActiveRound(index) { const rounds = state.payload?.rounds || []; if (!rounds.length) return; state.activeRound = Math.max(0, Math.min(index, rounds.length - 1)); renderRoundTrack(rounds); renderRoundDetail(rounds); renderHistory(rounds); } function roundBadges(round) { const fragment = document.createDocumentFragment(); if (round.selected_final) fragment.appendChild(badge("Returned representative", "selected")); if (Number(round.selection_weight || 0) > 0) { const ties = (state.payload?.rounds || []).filter((item) => Number(item.selection_weight || 0) > 0).length; fragment.appendChild(badge(ties > 1 ? `Reward weight ${formatScore(round.selection_weight, 3)}` : "Top proxy round", ties > 1 ? "tie" : "selected")); } if (!round.proxy_valid) fragment.appendChild(badge("Invalid proxy output", "invalid")); return fragment; } function responseScores(round, previous = null) { const container = document.createElement("div"); container.className = "response-scores"; const proxy = document.createElement("div"); proxy.className = "response-score proxy"; proxy.append(Object.assign(document.createElement("span"), { textContent: "Proxy" }), Object.assign(document.createElement("strong"), { textContent: formatScore(round.proxy_score) })); const gold = document.createElement("div"); gold.className = "response-score gold"; gold.append(Object.assign(document.createElement("span"), { textContent: "Gold" }), Object.assign(document.createElement("strong"), { textContent: formatScore(round.gold_score) })); const delta = previous && finite(round.gold_score) && finite(previous.gold_score) ? Number(round.gold_score) - Number(previous.gold_score) : 0; const change = document.createElement("div"); change.className = `response-score ${previous ? deltaClass(delta) : ""}`.trim(); change.append(Object.assign(document.createElement("span"), { textContent: previous ? "Gold vs prior" : "Gold change" }), Object.assign(document.createElement("strong"), { textContent: previous ? formatSigned(delta) : "Initial" })); container.append(proxy, gold, change); return container; } function renderRoundDetail(rounds) { const index = state.activeRound; const current = rounds[index]; const next = rounds[index + 1] || null; if (!current) return; const feedback = current.feedback_used || current.feedback || FALLBACK_FEEDBACK; const fallback = Boolean(current.feedback_fallback) || (!current.feedback && !current.proxy_valid); byId("feedback-eyebrow").textContent = fallback ? "Fallback feedback after invalid judge output" : `Judge feedback for round ${current.round ?? index}`; byId("feedback-title").textContent = next ? `Instruction used to generate round ${next.round ?? index + 1}` : "Terminal feedback (no later revision)"; byId("feedback-text").textContent = feedback; byId("feedback-note").textContent = next ? "The candidate generator also received the full earlier candidate, feedback, and proxy-score history. Gold rewards were hidden from it." : "This feedback was scored and logged, but the configured round limit ended before another candidate was generated."; byId("feedback-note").className = `feedback-note${fallback ? " fallback" : ""}`; const pills = byId("feedback-score-pills"); pills.replaceChildren( scorePill("Current proxy", formatScore(current.proxy_score), "proxy"), scorePill("Current gold", formatScore(current.gold_score), "gold"), ); if (next) { pills.append( scorePill("Next proxy change", finite(current.proxy_score) && finite(next.proxy_score) ? formatSigned(Number(next.proxy_score) - Number(current.proxy_score)) : "N/A", "proxy"), scorePill("Next gold change", formatSigned(Number(next.gold_score) - Number(current.gold_score)), "gold"), ); } byId("current-response-title").textContent = `Round ${current.round ?? index}`; byId("current-badges").replaceChildren(roundBadges(current)); const currentScores = responseScores(current, rounds[index - 1] || null); currentScores.id = "current-scores"; document.querySelector(".current-pane .response-scores")?.replaceWith(currentScores); renderStructured(byId("current-response"), current.candidate || current.response || ""); const nextPane = document.querySelector(".next-pane"); if (next) { nextPane.classList.remove("empty"); byId("next-response-title").textContent = `Round ${next.round ?? index + 1}`; byId("next-badges").replaceChildren(roundBadges(next)); const nextScores = responseScores(next, current); nextScores.id = "next-scores"; document.querySelector(".next-pane .response-scores")?.replaceWith(nextScores); renderStructured(byId("next-response"), next.candidate || next.response || ""); } else { nextPane.classList.add("empty"); byId("next-response-title").textContent = "No subsequent round"; byId("next-badges").replaceChildren(); const emptyScores = document.createElement("div"); emptyScores.className = "response-scores"; emptyScores.id = "next-scores"; document.querySelector(".next-pane .response-scores")?.replaceWith(emptyScores); renderStructured(byId("next-response"), "The configured round limit was reached, so this feedback did not produce another logged response."); } updateRoundControls(rounds.length); } function renderHistory(rounds) { const body = byId("history-body"); body.replaceChildren(); rounds.forEach((round, index) => { const row = document.createElement("tr"); if (index === state.activeRound) row.className = "active"; row.tabIndex = 0; row.addEventListener("click", () => setActiveRound(index)); row.addEventListener("keydown", (event) => { if (event.key === "Enter" || event.key === " ") setActiveRound(index); }); const roundCell = document.createElement("td"); const roundButton = document.createElement("button"); roundButton.type = "button"; roundButton.textContent = `Round ${round.round ?? index}`; roundCell.appendChild(roundButton); const proxy = document.createElement("td"); proxy.className = "numeric proxy-value"; proxy.textContent = formatScore(round.proxy_score); const gold = document.createElement("td"); gold.className = "numeric gold-value"; gold.textContent = formatScore(round.gold_score); const changeValue = index ? Number(round.gold_score) - Number(rounds[index - 1].gold_score) : 0; const change = document.createElement("td"); change.className = `numeric ${deltaClass(changeValue)}`.trim(); change.textContent = index ? formatSigned(changeValue) : "Initial"; const decision = document.createElement("td"); decision.textContent = [round.decision, round.preference].filter(Boolean).join(" · ") || "N/A"; const selection = document.createElement("td"); selection.textContent = round.selected_final ? `Returned${Number(round.selection_weight || 0) < 1 ? ` · weight ${formatScore(round.selection_weight, 3)}` : ""}` : Number(round.selection_weight || 0) > 0 ? `Tie weight ${formatScore(round.selection_weight, 3)}` : ""; const feedback = document.createElement("td"); feedback.className = "feedback-preview"; feedback.textContent = round.feedback_used || round.feedback || (round.proxy_valid ? "" : FALLBACK_FEEDBACK); row.append(roundCell, proxy, gold, change, decision, selection, feedback); body.appendChild(row); }); } function toggleClamp(button, content) { const expanded = button.getAttribute("aria-expanded") === "true"; button.setAttribute("aria-expanded", String(!expanded)); content.classList.toggle("is-clamped", expanded); button.textContent = expanded ? button.dataset.collapsedLabel : button.dataset.expandedLabel; } function switchView(view) { state.view = view; document.querySelectorAll(".tab").forEach((tab) => { const active = tab.dataset.view === view; tab.classList.toggle("active", active); tab.setAttribute("aria-selected", String(active)); }); byId("trajectory-view").hidden = view !== "trajectory"; byId("overview-view").hidden = view !== "overview"; if (view === "overview") renderOverview(); } function summaryMetric(summary, ...names) { for (const name of names) if (summary && summary[name] !== undefined) return summary[name]; return null; } function renderOverview() { const summary = state.index.summary || {}; const records = state.trajectories; const initial = summaryMetric(summary, "initial_gold_mean") ?? mean(records.map((row) => row.initial_gold)); const selected = summaryMetric(summary, "selected_gold_mean") ?? mean(records.map((row) => row.selected_gold)); const last = summaryMetric(summary, "last_gold_mean") ?? mean(records.map((row) => row.last_gold)); const best = summaryMetric(summary, "best_gold_mean", "oracle_best_gold_mean") ?? mean(records.map((row) => row.best_gold)); const spearman = summaryMetric(summary, "proxy_gold_spearman_mean", "mean_proxy_gold_spearman") ?? mean(records.map((row) => row.proxy_gold_spearman)); const overview = byId("overview-summary"); overview.replaceChildren( metricCell("Initial gold mean", formatScore(initial), `${records.length} paths`, "gold"), metricCell("Selected gold mean", formatScore(selected), "tie-weighted", "gold"), metricCell("Selected change", formatSigned(finite(selected) && finite(initial) ? Number(selected) - Number(initial) : null), "vs initial", deltaClass(finite(selected) && finite(initial) ? Number(selected) - Number(initial) : null)), metricCell("Last gold mean", formatScore(last), "round 8", "gold"), metricCell("Oracle best mean", formatScore(best), "best state per path", "gold"), metricCell("Mean rank agreement", formatScore(spearman), "trajectory Spearman", "proxy"), ); renderOutcomeChart(summary); renderRoundChart(summary.per_round || summary.rounds || []); renderCheckpointTable(); } function renderOutcomeChart(summary) { const supplied = summary.outcome_counts || {}; const counts = { improved: Number(supplied.improved ?? state.trajectories.filter((row) => row.outcome === "improved").length), unchanged: Number(supplied.unchanged ?? state.trajectories.filter((row) => row.outcome === "unchanged").length), worsened: Number(supplied.worsened ?? state.trajectories.filter((row) => row.outcome === "worsened").length), }; const total = Object.values(counts).reduce((sum, value) => sum + value, 0) || 1; const container = byId("outcome-chart"); container.replaceChildren(); const bar = document.createElement("div"); bar.className = "outcome-bar"; Object.entries(counts).forEach(([name, count]) => { const segment = document.createElement("div"); segment.className = `outcome-segment ${name}`; segment.style.width = `${(count / total) * 100}%`; const label = document.createElement("span"); label.textContent = `${name} ${count}`; segment.appendChild(label); segment.title = `${name}: ${count} (${formatPercent(count / total)})`; bar.appendChild(segment); }); const legend = document.createElement("div"); legend.className = "outcome-legend"; Object.entries(counts).forEach(([name, count]) => { const item = document.createElement("span"); item.append(document.createTextNode(`${name[0].toUpperCase()}${name.slice(1)}`)); const strong = document.createElement("strong"); strong.textContent = `${count} · ${formatPercent(count / total)}`; item.appendChild(strong); legend.appendChild(item); }); container.append(bar, legend); } function svgElement(name, attributes = {}) { const element = document.createElementNS("http://www.w3.org/2000/svg", name); Object.entries(attributes).forEach(([key, value]) => element.setAttribute(key, String(value))); return element; } function renderRoundChart(rows) { const container = byId("round-chart"); container.replaceChildren(); if (!rows.length) { const empty = document.createElement("p"); empty.textContent = "Per-round aggregates were not exported."; container.appendChild(empty); return; } const width = 1000; const height = 310; const left = 54; const right = 24; const top = 20; const bottom = 42; const plotWidth = width - left - right; const plotHeight = height - top - bottom; const x = (index) => left + (rows.length === 1 ? 0 : (index / (rows.length - 1)) * plotWidth); const y = (value) => top + (1 - Math.max(0, Math.min(1, Number(value)))) * plotHeight; const svg = svgElement("svg", { viewBox: `0 0 ${width} ${height}`, role: "img", "aria-label": "Mean proxy and gold scores by feedback round" }); [0, 0.25, 0.5, 0.75, 1].forEach((value) => { svg.appendChild(svgElement("line", { x1: left, y1: y(value), x2: width - right, y2: y(value), class: "chart-grid" })); const label = svgElement("text", { x: left - 10, y: y(value) + 4, "text-anchor": "end", class: "chart-axis-label" }); label.textContent = value.toFixed(2); svg.appendChild(label); }); rows.forEach((row, index) => { const label = svgElement("text", { x: x(index), y: height - 16, "text-anchor": "middle", class: "chart-axis-label" }); label.textContent = `Round ${row.round ?? index}`; svg.appendChild(label); }); const proxyValues = rows.map((row) => number(row.proxy_mean ?? row.mean_proxy)); const goldValues = rows.map((row) => number(row.gold_mean ?? row.mean_gold)); const makePath = (values) => values.map((value, index) => `${index ? "L" : "M"} ${x(index)} ${y(value)}`).join(" "); if (proxyValues.every(finite)) svg.appendChild(svgElement("path", { d: makePath(proxyValues), class: "chart-proxy" })); if (goldValues.every(finite)) svg.appendChild(svgElement("path", { d: makePath(goldValues), class: "chart-gold" })); proxyValues.forEach((value, index) => { if (!finite(value)) return; const dot = svgElement("circle", { cx: x(index), cy: y(value), r: 4, class: "chart-dot-proxy" }); const title = svgElement("title"); title.textContent = `Round ${rows[index].round ?? index}: proxy ${formatScore(value)}`; dot.appendChild(title); svg.appendChild(dot); }); goldValues.forEach((value, index) => { if (!finite(value)) return; const dot = svgElement("circle", { cx: x(index), cy: y(value), r: 4, class: "chart-dot-gold" }); const title = svgElement("title"); title.textContent = `Round ${rows[index].round ?? index}: gold ${formatScore(value)}`; dot.appendChild(title); svg.appendChild(dot); }); container.appendChild(svg); } function checkpointStatistics(checkpoint) { const records = state.trajectories.filter((record) => checkpointId(record) === checkpoint.id); return { count: records.length, initial: checkpoint.initial_gold_mean ?? mean(records.map((row) => row.initial_gold)), selected: checkpoint.selected_gold_mean ?? mean(records.map((row) => row.selected_gold)), best: checkpoint.best_gold_mean ?? checkpoint.oracle_best_gold_mean ?? mean(records.map((row) => row.best_gold)), }; } function renderCheckpointTable() { const body = byId("checkpoint-body"); body.replaceChildren(); state.checkpoints.forEach((checkpoint) => { const stats = checkpointStatistics(checkpoint); const row = document.createElement("tr"); row.addEventListener("click", () => { byId("checkpoint-select").value = checkpoint.id; applyTrajectoryFilter(); switchView("trajectory"); loadSelectedTrajectory(); }); const cells = [ checkpoint.step, checkpoint.title || checkpoint.context_label || checkpoint.uid, stats.count, formatScore(stats.initial), formatScore(stats.selected), formatScore(stats.best), ]; cells.forEach((value, index) => { const cell = document.createElement("td"); cell.textContent = String(value ?? "N/A"); if (index >= 2) cell.className = "numeric"; row.appendChild(cell); }); body.appendChild(row); }); } function moveTrajectory(offset) { const current = state.visible.findIndex((record) => trajectoryId(record) === byId("trajectory-select").value); const next = Math.max(0, Math.min(current + offset, state.visible.length - 1)); if (next === current || !state.visible[next]) return; byId("trajectory-select").value = trajectoryId(state.visible[next]); loadSelectedTrajectory(); } function refreshIcons() { if (window.lucide && typeof window.lucide.createIcons === "function") window.lucide.createIcons(); } function bindEvents() { document.querySelectorAll(".tab").forEach((tab) => tab.addEventListener("click", () => switchView(tab.dataset.view))); byId("checkpoint-select").addEventListener("change", () => { applyTrajectoryFilter(); loadSelectedTrajectory(); }); byId("outcome-select").addEventListener("change", () => { applyTrajectoryFilter(); loadSelectedTrajectory(); }); byId("trajectory-select").addEventListener("change", loadSelectedTrajectory); byId("previous-trajectory").addEventListener("click", () => moveTrajectory(-1)); byId("next-trajectory").addEventListener("click", () => moveTrajectory(1)); byId("previous-round").addEventListener("click", () => setActiveRound(state.activeRound - 1)); byId("next-round").addEventListener("click", () => setActiveRound(state.activeRound + 1)); byId("context-toggle").addEventListener("click", () => toggleClamp(byId("context-toggle"), byId("context-text"))); byId("rubric-toggle").addEventListener("click", () => toggleClamp(byId("rubric-toggle"), byId("rubric-text"))); document.addEventListener("keydown", (event) => { if (state.view !== "trajectory" || ["INPUT", "SELECT", "TEXTAREA", "SUMMARY"].includes(document.activeElement?.tagName)) return; if (event.key === "ArrowLeft") setActiveRound(state.activeRound - 1); if (event.key === "ArrowRight") setActiveRound(state.activeRound + 1); }); } async function initialize() { bindEvents(); refreshIcons(); try { const response = await fetch("data/index.json"); if (!response.ok) throw new Error(`HTTP ${response.status}`); state.index = await response.json(); state.trajectories = state.index.trajectories || state.index.records || []; if (!state.trajectories.length) throw new Error("the snapshot contains no trajectories"); byId("page-title").textContent = state.index.title || "Feedback trajectories"; byId("strategy-label").textContent = state.index.strategy || "self_reflection_best"; const counts = state.index.counts || {}; byId("dataset-count").textContent = `${counts.trajectories || state.trajectories.length} trajectories · ${counts.checkpoints || new Set(state.trajectories.map(checkpointId)).size} checkpoint examples`; buildCheckpointIndex(); populateCheckpointSelect(); applyTrajectoryFilter(); renderOverview(); await loadSelectedTrajectory(); } catch (error) { showError(`Could not load the feedback snapshot (${error.message}).`); } } initialize();