| (function () { |
| "use strict"; |
|
|
| var D = window.FINEPROOFS_DISTRIBUTION; |
| if (!D || !D.meta || !Array.isArray(D.problems)) { |
| throw new Error("FineProofs distribution data is missing"); |
| } |
|
|
| var SVG_NS = "http://www.w3.org/2000/svg"; |
| var TRACE_DATA_URL = "https://huggingface.co/datasets/asingh15/fineproofs-branch-rollout-distribution/resolve/main/data/traces/"; |
| var TRACE_SCHEMA = "fineproofs_reasoning_traces/v1"; |
| var MAX_TRACE_SHARDS = 6; |
| var TRACE_PAGE_SIZE = 300; |
| var POINT = Object.fromEntries(D.meta.point_fields.map(function (name, index) { return [name, index]; })); |
| var HIST_OFFSET = D.meta.point_fields.length; |
| var traceShardCache = new Map(); |
| var traceShardRequests = new Map(); |
| var traces = []; |
| D.problems.forEach(function (problem) { |
| problem.t.forEach(function (trace) { |
| traces.push({ |
| key: problem.i + "_b" + trace.b, |
| problem: problem, |
| trace: trace, |
| search: (problem.i + " " + problem.q).toLowerCase() |
| }); |
| }); |
| }); |
|
|
| var state = { |
| view: "overview", |
| selectedKey: traces.length ? traces[0].key : null, |
| pointIndex: 0, |
| reasoningMode: "prefix", |
| reasoningRequest: 0, |
| visibleTraceLimit: TRACE_PAGE_SIZE, |
| search: "", |
| pattern: "all", |
| endpoint: "all" |
| }; |
|
|
| function byId(id) { return document.getElementById(id); } |
| function setText(id, value) { byId(id).textContent = value; } |
| function fmtInt(value) { return Number(value).toLocaleString(); } |
| function fmtGrade(value) { return Number(value).toFixed(3); } |
| function fmtPct(value, digits) { return (Number(value) * 100).toFixed(digits == null ? 1 : digits) + "%"; } |
| function fmtCompact(value) { |
| var number = Number(value); |
| if (number >= 1000000) return (number / 1000000).toFixed(number >= 10000000 ? 0 : 1) + "M"; |
| if (number >= 1000) return (number / 1000).toFixed(number >= 100000 ? 0 : 1) + "k"; |
| return String(Math.round(number)); |
| } |
| function titleCase(value) { return value.charAt(0).toUpperCase() + value.slice(1); } |
| function selectedRecord() { |
| return traces.find(function (record) { return record.key === state.selectedKey; }) || traces[0]; |
| } |
| function svgNode(tag, attributes, text) { |
| var node = document.createElementNS(SVG_NS, tag); |
| Object.keys(attributes || {}).forEach(function (name) { node.setAttribute(name, attributes[name]); }); |
| if (text != null) node.textContent = text; |
| return node; |
| } |
| function appendTitle(node, value) { node.appendChild(svgNode("title", {}, value)); } |
|
|
| function rememberTraceShard(shard, data) { |
| traceShardCache.delete(shard); |
| traceShardCache.set(shard, data); |
| while (traceShardCache.size > MAX_TRACE_SHARDS) { |
| traceShardCache.delete(traceShardCache.keys().next().value); |
| } |
| } |
|
|
| async function decodeTraceShard(buffer) { |
| var bytes = new Uint8Array(buffer); |
| if (bytes.length >= 2 && bytes[0] === 0x1f && bytes[1] === 0x8b) { |
| if (typeof window.DecompressionStream !== "function") { |
| throw new Error("This browser cannot decompress reasoning trace files."); |
| } |
| var compressed = new Blob([buffer]).stream(); |
| return new Response(compressed.pipeThrough(new window.DecompressionStream("gzip"))).text(); |
| } |
| return new TextDecoder("utf-8").decode(bytes); |
| } |
|
|
| async function loadTraceShard(shard) { |
| if (traceShardCache.has(shard)) { |
| var cached = traceShardCache.get(shard); |
| rememberTraceShard(shard, cached); |
| return cached; |
| } |
| if (traceShardRequests.has(shard)) return traceShardRequests.get(shard); |
|
|
| var request = (async function () { |
| var response = await fetch(TRACE_DATA_URL + encodeURIComponent(shard) + ".json.gz", { cache: "force-cache" }); |
| if (!response.ok) throw new Error("Trace shard request failed (HTTP " + response.status + ")."); |
| var parsed = JSON.parse(await decodeTraceShard(await response.arrayBuffer())); |
| if (!parsed || parsed.schema_version !== TRACE_SCHEMA || parsed.shard !== shard || !parsed.problems) { |
| throw new Error("Trace shard has an unsupported schema."); |
| } |
| rememberTraceShard(shard, parsed); |
| return parsed; |
| })(); |
| traceShardRequests.set(shard, request); |
| try { |
| return await request; |
| } finally { |
| traceShardRequests.delete(shard); |
| } |
| } |
|
|
| function traceStepEnd(traceData, stepIndex) { |
| var match = traceData.steps.find(function (step) { return Number(step[0]) === Number(stepIndex); }); |
| if (!match) throw new Error("The selected prefix boundary is missing from this trace."); |
| var end = Number(match[1]); |
| if (!Number.isFinite(end)) throw new Error("The selected prefix has an invalid character boundary."); |
| return Math.max(0, Math.min(traceData.reasoning.length, end)); |
| } |
|
|
| function setReasoningStatus(kind, message) { |
| var section = byId("reasoning-section"); |
| var status = byId("reasoning-state"); |
| var indicator = status.querySelector(".reasoning-state-indicator"); |
| section.setAttribute("aria-busy", kind === "loading" ? "true" : "false"); |
| status.dataset.kind = kind; |
| status.hidden = false; |
| indicator.textContent = kind === "error" ? "!" : ""; |
| setText("reasoning-state-text", message); |
| byId("reasoning-empty").hidden = true; |
| byId("reasoning-text").hidden = true; |
| byId("reasoning-tail").hidden = true; |
| byId("reasoning-tail-text").textContent = ""; |
| } |
|
|
| function selectedReasoningSlice(record, traceData) { |
| var point = record.trace.p[state.pointIndex]; |
| var selectedStep = Number(point[POINT.step_idx]); |
| var selectedEnd = traceStepEnd(traceData, selectedStep); |
| var finalStep = traceData.steps.reduce(function (maximum, step) { |
| return Math.max(maximum, Number(step[0])); |
| }, 0); |
| var totalSteps = Number.isFinite(Number(traceData.num_steps)) ? Number(traceData.num_steps) : Number(point[POINT.num_steps]); |
| var start = 0; |
| var end = selectedEnd; |
| var shownEnd = end; |
| var tailText = ""; |
| var tailStart = null; |
| var range = "Start to step " + selectedStep; |
| var steps = selectedStep + " / " + point[POINT.num_steps]; |
|
|
| if (state.reasoningMode === "segment") { |
| var previousStep = state.pointIndex > 0 ? Number(record.trace.p[state.pointIndex - 1][POINT.step_idx]) : 0; |
| start = state.pointIndex > 0 ? traceStepEnd(traceData, previousStep) : 0; |
| range = state.pointIndex > 0 ? "Step " + previousStep + " to " + selectedStep : "Start to step " + selectedStep; |
| steps = state.pointIndex > 0 ? previousStep + " to " + selectedStep : selectedStep + " / " + point[POINT.num_steps]; |
| } else if (state.reasoningMode === "full") { |
| var sampledComplete = traceData.sampled_complete !== false; |
| tailStart = sampledComplete ? null : traceStepEnd(traceData, finalStep); |
| end = tailStart == null ? traceData.reasoning.length : tailStart; |
| shownEnd = traceData.reasoning.length; |
| tailText = tailStart == null ? "" : traceData.reasoning.slice(tailStart); |
| range = "Complete base trace"; |
| steps = sampledComplete ? totalSteps + " total" : totalSteps + " total · graded to " + finalStep; |
| } |
|
|
| return { |
| text: traceData.reasoning.slice(start, end), |
| start: start, |
| end: end, |
| shownEnd: shownEnd, |
| tailText: tailText, |
| tailStart: tailStart, |
| range: range, |
| steps: steps, |
| selectedStep: selectedStep |
| }; |
| } |
|
|
| async function renderReasoningTrace(record) { |
| var requestId = ++state.reasoningRequest; |
| var point = record.trace.p[state.pointIndex]; |
| var modeLabels = { prefix: "Selected prefix", segment: "New segment", full: "Full trace" }; |
| setText("reasoning-context", "Base " + record.trace.b + " · step " + point[POINT.step_idx] + " · " + modeLabels[state.reasoningMode]); |
| setText("reasoning-range", "-"); |
| setText("reasoning-steps", "-"); |
| setText("reasoning-chars", "-"); |
| setReasoningStatus("loading", "Loading reasoning trace"); |
|
|
| try { |
| var problemId = String(record.problem.i); |
| var shardData = await loadTraceShard(problemId.slice(0, 2).toLowerCase()); |
| var problemData = shardData.problems[problemId]; |
| var traceData = problemData && problemData[String(record.trace.b)]; |
| if (!traceData || typeof traceData.reasoning !== "string" || !Array.isArray(traceData.steps)) { |
| throw new Error("Reasoning trace is unavailable for this base sample."); |
| } |
| if (requestId !== state.reasoningRequest) return; |
|
|
| var selection = selectedReasoningSlice(record, traceData); |
| setText("reasoning-range", selection.range); |
| setText("reasoning-steps", selection.steps); |
| var charLabel = fmtInt(selection.start) + "–" + fmtInt(selection.shownEnd) + " (" + fmtInt(selection.shownEnd - selection.start) + " shown)"; |
| if (selection.tailStart != null) charLabel += " · graded to " + fmtInt(selection.tailStart); |
| setText("reasoning-chars", charLabel); |
| byId("reasoning-section").setAttribute("aria-busy", "false"); |
| byId("reasoning-state").hidden = true; |
| var empty = byId("reasoning-empty"); |
| var text = byId("reasoning-text"); |
| text.textContent = selection.text; |
| empty.hidden = selection.text.length !== 0; |
| text.hidden = selection.text.length === 0; |
| var tail = byId("reasoning-tail"); |
| var tailText = byId("reasoning-tail-text"); |
| tailText.textContent = selection.tailText; |
| text.scrollTop = 0; |
| tailText.scrollTop = 0; |
| tail.hidden = selection.tailStart == null || selection.tailText.length === 0; |
| if (!tail.hidden) { |
| setText("reasoning-tail-range", "Characters " + fmtInt(selection.tailStart) + "–" + fmtInt(selection.shownEnd) + " · not a collected prefix"); |
| } |
| } catch (error) { |
| if (requestId !== state.reasoningRequest) return; |
| setReasoningStatus("error", error && error.message ? error.message : "Reasoning trace could not be loaded."); |
| } |
| } |
|
|
| function renderMath(root) { |
| if (!root || typeof window.renderMathInElement !== "function") return; |
| window.renderMathInElement(root, { |
| delimiters: [ |
| { left: "$$", right: "$$", display: true }, |
| { left: "\\[", right: "\\]", display: true }, |
| { left: "\\(", right: "\\)", display: false }, |
| { left: "$", right: "$", display: false } |
| ], |
| throwOnError: false |
| }); |
| } |
|
|
| function addChartAxes(svg, width, height, margins, yMax, yFormatter) { |
| var innerWidth = width - margins.left - margins.right; |
| var innerHeight = height - margins.top - margins.bottom; |
| for (var tick = 0; tick <= 4; tick += 1) { |
| var fraction = tick / 4; |
| var y = margins.top + innerHeight * (1 - fraction); |
| svg.appendChild(svgNode("line", { x1: margins.left, x2: margins.left + innerWidth, y1: y, y2: y, class: "chart-gridline" })); |
| svg.appendChild(svgNode("text", { x: margins.left - 9, y: y + 4, "text-anchor": "end", class: "chart-label" }, yFormatter(yMax * fraction))); |
| } |
| svg.appendChild(svgNode("line", { x1: margins.left, x2: margins.left, y1: margins.top, y2: margins.top + innerHeight, class: "chart-axis" })); |
| svg.appendChild(svgNode("line", { x1: margins.left, x2: margins.left + innerWidth, y1: margins.top + innerHeight, y2: margins.top + innerHeight, class: "chart-axis" })); |
| return { width: innerWidth, height: innerHeight }; |
| } |
|
|
| function drawHistogram(svg, histogram, barClass, ariaTitle) { |
| svg.replaceChildren(); |
| var width = 760; |
| var height = Number(svg.getAttribute("viewBox").split(" ")[3]); |
| var compact = height < 260; |
| var margins = { left: 54, right: 15, top: 16, bottom: compact ? 39 : 45 }; |
| var counts = histogram.counts; |
| var edges = histogram.edges; |
| var maxCount = Math.max.apply(null, counts) || 1; |
| var total = counts.reduce(function (sum, value) { return sum + value; }, 0); |
| var frame = addChartAxes(svg, width, height, margins, maxCount, fmtCompact); |
| var slot = frame.width / counts.length; |
| counts.forEach(function (count, index) { |
| var barHeight = frame.height * count / maxCount; |
| var bar = svgNode("rect", { |
| x: margins.left + index * slot + 1, |
| y: margins.top + frame.height - barHeight, |
| width: Math.max(1, slot - 2), |
| height: Math.max(count ? 1 : 0, barHeight), |
| rx: 1, |
| class: "chart-bar " + barClass |
| }); |
| var high = edges[index + 1]; |
| appendTitle(bar, edges[index].toFixed(2) + " to " + high.toFixed(2) + ": " + fmtInt(count) + " (" + fmtPct(count / total, 2) + ")"); |
| svg.appendChild(bar); |
| }); |
| [0, 0.25, 0.5, 0.75, 1].forEach(function (value) { |
| var x = margins.left + value * frame.width; |
| svg.appendChild(svgNode("text", { x: x, y: height - 14, "text-anchor": value === 0 ? "start" : value === 1 ? "end" : "middle", class: "chart-label" }, value.toFixed(2))); |
| }); |
| svg.insertBefore(svgNode("title", {}, ariaTitle), svg.firstChild); |
| } |
|
|
| function renderGlobal() { |
| var construction = D.meta.construction; |
| var grades = D.meta.continuation_grades; |
| setText("stat-problems", fmtInt(construction.source_problems)); |
| setText("stat-traces", fmtInt(construction.selected_base_trajectories)); |
| setText("stat-prefixes", fmtInt(construction.prefix_rows)); |
| setText("stat-grades", fmtInt(construction.continuation_grades)); |
| setText("stat-mean", fmtGrade(grades.mean)); |
| setText("run-label", "Run " + D.meta.run_id); |
| setText("run-id", D.meta.run_id); |
| setText("continuation-summary", "Mean " + fmtGrade(grades.mean) + " · median " + fmtGrade(grades.median) + " · " + fmtInt(grades.truncated_count) + " truncated"); |
| setText("prefix-median", "Median " + fmtGrade(D.meta.prefix_values.median)); |
| } |
|
|
| function renderComposition() { |
| var root = byId("credit-composition"); |
| root.replaceChildren(); |
| var grades = D.meta.continuation_grades; |
| var rows = [ |
| { label: "Zero", value: grades.zero_count, className: "zero" }, |
| { label: "Partial", value: grades.partial_count, className: "partial" }, |
| { label: "Full", value: grades.full_credit_count, className: "full" } |
| ]; |
| rows.forEach(function (item) { |
| var row = document.createElement("div"); |
| row.className = "composition-row " + item.className; |
| var label = document.createElement("span"); |
| label.textContent = item.label; |
| var track = document.createElement("div"); |
| track.className = "composition-track"; |
| var fill = document.createElement("div"); |
| fill.className = "composition-fill"; |
| fill.style.width = fmtPct(item.value / grades.count, 3); |
| track.appendChild(fill); |
| var value = document.createElement("strong"); |
| value.textContent = fmtPct(item.value / grades.count, 1); |
| row.append(label, track, value); |
| root.appendChild(row); |
| }); |
| var total = document.createElement("div"); |
| total.className = "composition-total"; |
| total.textContent = fmtInt(grades.at_least_half_credit_count) + " grades (" + fmtPct(grades.at_least_half_credit_count / grades.count, 2) + ") received at least half credit."; |
| root.appendChild(total); |
| } |
|
|
| function depthColor(group) { |
| return { all: "#007c78", endpoint_correct: "#087a52", endpoint_incorrect: "#b42318" }[group]; |
| } |
|
|
| function drawDepthChart() { |
| var svg = byId("depth-chart"); |
| svg.replaceChildren(); |
| var width = 1080; |
| var height = 340; |
| var margins = { left: 58, right: 22, top: 22, bottom: 48 }; |
| var frame = addChartAxes(svg, width, height, margins, 1, function (value) { return value.toFixed(2); }); |
| function xFor(index) { return margins.left + frame.width * ((index + 0.5) / 10); } |
| function yFor(value) { return margins.top + frame.height * (1 - value); } |
| for (var index = 0; index < 10; index += 1) { |
| svg.appendChild(svgNode("text", { x: xFor(index), y: height - 17, "text-anchor": "middle", class: "chart-label" }, (index * 10) + "–" + ((index + 1) * 10) + "%")); |
| } |
| ["all", "endpoint_correct", "endpoint_incorrect"].forEach(function (group) { |
| var records = D.meta.depth_summary.filter(function (record) { return record.group === group; }).sort(function (a, b) { return a.depth_bin - b.depth_bin; }); |
| var upper = records.map(function (record) { return xFor(record.depth_bin) + "," + yFor(record.p75); }); |
| var lower = records.slice().reverse().map(function (record) { return xFor(record.depth_bin) + "," + yFor(record.p25); }); |
| svg.appendChild(svgNode("polygon", { points: upper.concat(lower).join(" "), fill: depthColor(group), opacity: group === "all" ? "0.10" : "0.06" })); |
| var path = records.map(function (record, recordIndex) { return (recordIndex ? "L" : "M") + xFor(record.depth_bin) + " " + yFor(record.mean); }).join(" "); |
| svg.appendChild(svgNode("path", { d: path, fill: "none", stroke: depthColor(group), "stroke-width": group === "all" ? "3" : "2.5", "vector-effect": "non-scaling-stroke" })); |
| records.forEach(function (record) { |
| var circle = svgNode("circle", { cx: xFor(record.depth_bin), cy: yFor(record.mean), r: group === "all" ? "4" : "3.5", fill: depthColor(group), stroke: "#ffffff", "stroke-width": "1.5" }); |
| appendTitle(circle, titleCase(group.replace("endpoint_", "endpoint ")) + " · " + (record.depth_bin * 10) + "–" + ((record.depth_bin + 1) * 10) + "% · mean " + fmtGrade(record.mean) + " · IQR " + fmtGrade(record.p25) + "–" + fmtGrade(record.p75) + " · n=" + fmtInt(record.count)); |
| svg.appendChild(circle); |
| }); |
| }); |
| svg.appendChild(svgNode("text", { x: margins.left + frame.width / 2, y: height - 1, "text-anchor": "middle", class: "chart-value-label" }, "Normalized reasoning depth")); |
| svg.insertBefore(svgNode("title", {}, "Prefix mean grade by normalized trajectory depth"), svg.firstChild); |
| } |
|
|
| function renderOverview() { |
| drawHistogram(byId("continuation-chart"), D.meta.continuation_grades.histogram, "continuation", "Distribution of all continuation grades"); |
| drawHistogram(byId("prefix-chart"), D.meta.prefix_values.histogram, "prefix", "Distribution of prefix mean grades"); |
| renderComposition(); |
| drawDepthChart(); |
| } |
|
|
| function filteredTraces() { |
| var query = state.search.trim().toLowerCase(); |
| return traces.filter(function (record) { |
| if (query && !record.search.includes(query)) return false; |
| if (state.pattern !== "all" && record.trace.k !== state.pattern) return false; |
| if (state.endpoint === "correct" && record.trace.e < 0.5) return false; |
| if (state.endpoint === "incorrect" && record.trace.e >= 0.5) return false; |
| return true; |
| }); |
| } |
|
|
| function miniChart(trace) { |
| var svg = svgNode("svg", { viewBox: "0 0 76 34", class: "mini-chart", "aria-hidden": "true" }); |
| svg.appendChild(svgNode("line", { x1: 1, x2: 75, y1: 33, y2: 33 })); |
| var points = trace.p.map(function (point) { |
| return (2 + point[POINT.progress] * 72) + "," + (32 - point[POINT.mean_grade] * 29); |
| }).join(" "); |
| svg.appendChild(svgNode("polyline", { points: points })); |
| return svg; |
| } |
|
|
| function selectTrace(key) { |
| state.selectedKey = key; |
| state.pointIndex = 0; |
| renderTrajectoryList(); |
| renderSelectedTrajectory(); |
| } |
|
|
| function renderTrajectoryList() { |
| var root = byId("trajectory-list"); |
| var filtered = filteredTraces(); |
| if (filtered.length && !filtered.some(function (record) { return record.key === state.selectedKey; })) { |
| state.selectedKey = filtered[0].key; |
| state.pointIndex = 0; |
| } |
| setText("trajectory-count", fmtInt(filtered.length)); |
| root.replaceChildren(); |
| var fragment = document.createDocumentFragment(); |
| var visibleCount = Math.min(state.visibleTraceLimit, filtered.length); |
| filtered.slice(0, visibleCount).forEach(function (record) { |
| var button = document.createElement("button"); |
| button.type = "button"; |
| button.className = "trajectory-item"; |
| button.setAttribute("role", "option"); |
| button.setAttribute("aria-selected", record.key === state.selectedKey ? "true" : "false"); |
| var copy = document.createElement("div"); |
| var id = document.createElement("strong"); |
| id.textContent = record.problem.i + " · b" + record.trace.b; |
| var grade = document.createElement("span"); |
| grade.textContent = "Endpoint " + fmtGrade(record.trace.e) + " · " + record.trace.p.length + " prefixes"; |
| var pattern = document.createElement("small"); |
| pattern.textContent = record.trace.k; |
| copy.append(id, grade, pattern); |
| button.append(copy, miniChart(record.trace)); |
| button.title = record.problem.q.slice(0, 180).replace(/\s+/g, " "); |
| button.addEventListener("click", function () { selectTrace(record.key); }); |
| fragment.appendChild(button); |
| }); |
| if (!filtered.length) { |
| var empty = document.createElement("div"); |
| empty.className = "composition-total"; |
| empty.textContent = "No trajectories match the current filters."; |
| fragment.appendChild(empty); |
| } else if (filtered.length > visibleCount) { |
| var footer = document.createElement("div"); |
| footer.className = "trajectory-list-footer"; |
| var shown = document.createElement("span"); |
| shown.textContent = "Showing " + fmtInt(visibleCount) + " of " + fmtInt(filtered.length) + " matching traces"; |
| var more = document.createElement("button"); |
| more.type = "button"; |
| more.className = "load-more-button"; |
| more.textContent = "Load " + fmtInt(Math.min(TRACE_PAGE_SIZE, filtered.length - visibleCount)) + " more"; |
| more.addEventListener("click", function () { |
| state.visibleTraceLimit += TRACE_PAGE_SIZE; |
| renderTrajectoryList(); |
| }); |
| footer.append(shown, more); |
| fragment.appendChild(footer); |
| } else if (filtered.length > TRACE_PAGE_SIZE) { |
| var complete = document.createElement("div"); |
| complete.className = "composition-total"; |
| complete.textContent = "Showing all " + fmtInt(filtered.length) + " matching traces."; |
| fragment.appendChild(complete); |
| } |
| root.appendChild(fragment); |
| } |
|
|
| function switchToSibling(problem, baseSample) { |
| var key = problem.i + "_b" + baseSample; |
| if (traces.some(function (record) { return record.key === key; })) selectTrace(key); |
| } |
|
|
| function renderTraceSwitch(record) { |
| var root = byId("trace-switch"); |
| root.replaceChildren(); |
| record.problem.t.forEach(function (trace) { |
| var button = document.createElement("button"); |
| button.type = "button"; |
| button.setAttribute("aria-pressed", trace.b === record.trace.b ? "true" : "false"); |
| button.textContent = "Base " + trace.b; |
| button.title = "Base sample " + trace.b + ", endpoint grade " + fmtGrade(trace.e); |
| button.addEventListener("click", function () { switchToSibling(record.problem, trace.b); }); |
| root.appendChild(button); |
| }); |
| } |
|
|
| function drawTrajectoryChart(record) { |
| var svg = byId("trajectory-chart"); |
| svg.replaceChildren(); |
| var width = 940; |
| var height = 350; |
| var margins = { left: 56, right: 26, top: 22, bottom: 47 }; |
| var frame = addChartAxes(svg, width, height, margins, 1, function (value) { return value.toFixed(2); }); |
| function xFor(value) { return margins.left + frame.width * value; } |
| function yFor(value) { return margins.top + frame.height * (1 - value); } |
| [0, 0.25, 0.5, 0.75, 1].forEach(function (value) { |
| svg.appendChild(svgNode("text", { x: xFor(value), y: height - 17, "text-anchor": value === 0 ? "start" : value === 1 ? "end" : "middle", class: "chart-label" }, fmtPct(value, 0))); |
| }); |
| record.trace.p.forEach(function (point) { |
| var x = xFor(point[POINT.progress]); |
| svg.appendChild(svgNode("line", { x1: x, x2: x, y1: yFor(point[POINT.q75_grade]), y2: yFor(point[POINT.q25_grade]), class: "trajectory-whisker" })); |
| }); |
| var line = record.trace.p.map(function (point, index) { |
| return (index ? "L" : "M") + xFor(point[POINT.progress]) + " " + yFor(point[POINT.mean_grade]); |
| }).join(" "); |
| svg.appendChild(svgNode("path", { d: line, class: "trajectory-line" })); |
| record.trace.p.forEach(function (point, index) { |
| var circle = svgNode("circle", { |
| cx: xFor(point[POINT.progress]), cy: yFor(point[POINT.mean_grade]), r: 6, |
| class: "trajectory-point" + (index === state.pointIndex ? " selected" : ""), |
| tabindex: 0, role: "button", "aria-label": "Select step " + point[POINT.step_idx] |
| }); |
| appendTitle(circle, "Step " + point[POINT.step_idx] + " · mean " + fmtGrade(point[POINT.mean_grade]) + " · IQR " + fmtGrade(point[POINT.q25_grade]) + "–" + fmtGrade(point[POINT.q75_grade])); |
| circle.addEventListener("click", function () { state.pointIndex = index; renderSelectedPoint(record); drawTrajectoryChart(record); }); |
| circle.addEventListener("keydown", function (event) { |
| if (event.key === "Enter" || event.key === " ") { |
| event.preventDefault(); |
| state.pointIndex = index; |
| renderSelectedPoint(record); |
| drawTrajectoryChart(record); |
| } |
| }); |
| svg.appendChild(circle); |
| }); |
| var endpointX = xFor(1); |
| var endpointY = yFor(record.trace.e); |
| var size = 8; |
| var diamond = svgNode("polygon", { points: [endpointX + "," + (endpointY - size), (endpointX + size) + "," + endpointY, endpointX + "," + (endpointY + size), (endpointX - size) + "," + endpointY].join(" "), class: "endpoint-diamond" }); |
| appendTitle(diamond, "Base endpoint grade " + fmtGrade(record.trace.e)); |
| svg.appendChild(diamond); |
| svg.appendChild(svgNode("text", { x: margins.left + frame.width / 2, y: height - 1, "text-anchor": "middle", class: "chart-value-label" }, "Normalized reasoning depth")); |
| svg.insertBefore(svgNode("title", {}, "Mean continuation grade across the selected base trajectory"), svg.firstChild); |
| } |
|
|
| function metricNode(label, value) { |
| var wrapper = document.createElement("div"); |
| var term = document.createElement("dt"); |
| var detail = document.createElement("dd"); |
| term.textContent = label; |
| detail.textContent = value; |
| wrapper.append(term, detail); |
| return wrapper; |
| } |
|
|
| function renderSelectedPoint(record) { |
| var points = record.trace.p; |
| state.pointIndex = Math.max(0, Math.min(state.pointIndex, points.length - 1)); |
| var point = points[state.pointIndex]; |
| setText("point-title", "Step " + point[POINT.step_idx] + " of " + point[POINT.num_steps] + " · " + fmtPct(point[POINT.progress], 1)); |
| var stats = byId("point-stats"); |
| stats.replaceChildren( |
| metricNode("Mean", fmtGrade(point[POINT.mean_grade])), |
| metricNode("Median", fmtGrade(point[POINT.median_grade])), |
| metricNode("Std. dev.", fmtGrade(point[POINT.std_grade])), |
| metricNode("Zero credit", point[POINT.zero_count] + " / 32"), |
| metricNode("Full credit", point[POINT.full_credit_count] + " / 32"), |
| metricNode("Truncated", point[POINT.truncated_count] + " / 32") |
| ); |
| var counts = point.slice(HIST_OFFSET, HIST_OFFSET + D.meta.point_grade_histogram_bins); |
| var edges = Array.from({ length: counts.length + 1 }, function (_, index) { return index / counts.length; }); |
| drawHistogram(byId("point-chart"), { counts: counts, edges: edges }, "point", "Continuation grade distribution for the selected prefix"); |
| byId("previous-point").disabled = state.pointIndex === 0; |
| byId("next-point").disabled = state.pointIndex === points.length - 1; |
| renderReasoningTrace(record); |
| } |
|
|
| function renderSelectedTrajectory() { |
| var record = selectedRecord(); |
| if (!record) return; |
| setText("trajectory-position", "Problem " + (D.problems.indexOf(record.problem) + 1) + " of " + fmtInt(D.problems.length)); |
| setText("trajectory-title", record.problem.i); |
| setText("trajectory-meta", "Base sample " + record.trace.b + " · " + record.trace.p.length + " prefixes · endpoint grade " + fmtGrade(record.trace.e)); |
| setText("pattern-badge", titleCase(record.trace.k)); |
| var problem = byId("problem-text"); |
| problem.textContent = record.problem.q; |
| renderMath(problem); |
| renderTraceSwitch(record); |
| drawTrajectoryChart(record); |
| renderSelectedPoint(record); |
| } |
|
|
| function renderMethod() { |
| var provenance = D.meta.prm_provenance; |
| if (provenance) { |
| var partial = Number(provenance.partial_rows.train) + Number(provenance.partial_rows.val); |
| var endpoints = Number(provenance.hard_endpoints.rows.train) + Number(provenance.hard_endpoints.rows.val); |
| setText("prm-accounting", "The downstream build retains " + fmtInt(partial) + " partial-prefix rows and " + fmtInt(endpoints) + " eligible hard endpoints after empty-prefix, endpoint-validity, and prompt-length filtering."); |
| } |
| var root = byId("run-details"); |
| root.replaceChildren( |
| metricNode("Continuations / prefix", fmtInt(D.meta.construction.continuations_per_prefix)), |
| metricNode("Semantic prefixes", fmtInt(D.meta.construction.semantic_problem_prefixes)), |
| metricNode("Non-grade history rows", fmtInt(D.meta.construction.skipped_non_grade_journal_rows)), |
| metricNode("Built (UTC)", new Date(D.meta.built_at_utc).toISOString().replace(".000Z", "Z")) |
| ); |
| } |
|
|
| function showView(name) { |
| state.view = name; |
| document.querySelectorAll("[data-view]").forEach(function (button) { |
| var selected = button.dataset.view === name; |
| button.setAttribute("aria-selected", selected ? "true" : "false"); |
| button.tabIndex = selected ? 0 : -1; |
| }); |
| ["overview", "trajectories", "method"].forEach(function (view) { |
| byId(view + "-view").hidden = view !== name; |
| }); |
| if (name === "trajectories") { |
| renderTrajectoryList(); |
| renderSelectedTrajectory(); |
| } |
| } |
|
|
| document.querySelectorAll("[data-view]").forEach(function (button) { |
| button.addEventListener("click", function () { showView(button.dataset.view); }); |
| button.addEventListener("keydown", function (event) { |
| if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return; |
| var buttons = Array.from(document.querySelectorAll("[data-view]")); |
| var index = buttons.indexOf(button); |
| var next = event.key === "ArrowRight" ? (index + 1) % buttons.length : (index - 1 + buttons.length) % buttons.length; |
| buttons[next].focus(); |
| showView(buttons[next].dataset.view); |
| }); |
| }); |
|
|
| byId("search-input").addEventListener("input", function (event) { |
| state.search = event.target.value; |
| state.visibleTraceLimit = TRACE_PAGE_SIZE; |
| renderTrajectoryList(); |
| renderSelectedTrajectory(); |
| }); |
| byId("pattern-filter").addEventListener("change", function (event) { |
| state.pattern = event.target.value; |
| state.visibleTraceLimit = TRACE_PAGE_SIZE; |
| renderTrajectoryList(); |
| renderSelectedTrajectory(); |
| }); |
| byId("endpoint-filter").addEventListener("change", function (event) { |
| state.endpoint = event.target.value; |
| state.visibleTraceLimit = TRACE_PAGE_SIZE; |
| renderTrajectoryList(); |
| renderSelectedTrajectory(); |
| }); |
| byId("trajectory-filters").addEventListener("reset", function () { |
| window.setTimeout(function () { |
| state.search = ""; |
| state.pattern = "all"; |
| state.endpoint = "all"; |
| state.visibleTraceLimit = TRACE_PAGE_SIZE; |
| renderTrajectoryList(); |
| renderSelectedTrajectory(); |
| }, 0); |
| }); |
| byId("previous-point").addEventListener("click", function () { |
| state.pointIndex -= 1; |
| renderSelectedTrajectory(); |
| }); |
| byId("next-point").addEventListener("click", function () { |
| state.pointIndex += 1; |
| renderSelectedTrajectory(); |
| }); |
| document.querySelectorAll("[data-reasoning-mode]").forEach(function (button) { |
| button.addEventListener("click", function () { |
| state.reasoningMode = button.dataset.reasoningMode; |
| document.querySelectorAll("[data-reasoning-mode]").forEach(function (modeButton) { |
| modeButton.setAttribute("aria-pressed", modeButton === button ? "true" : "false"); |
| }); |
| var record = selectedRecord(); |
| if (record) renderReasoningTrace(record); |
| }); |
| }); |
|
|
| renderGlobal(); |
| renderOverview(); |
| renderMethod(); |
| showView("overview"); |
| if (window.lucide) window.lucide.createIcons({ attrs: { "stroke-width": 1.8 } }); |
| })(); |
|
|