Spaces:
Running
Running
Download index.html from HerrHruby/SFT-v4-Dataset-Viewer: direct link, hf CLI and curl.
- Browser
- Download file 52.5 kB
-
https://huggingface.co/spaces/HerrHruby/SFT-v4-Dataset-Viewer/resolve/main/index.html
- Command line
-
hf download hf://spaces/HerrHruby/SFT-v4-Dataset-Viewer/index.html
-
curl -L -o index.html https://huggingface.co/spaces/HerrHruby/SFT-v4-Dataset-Viewer/resolve/main/index.html
52.5 kB
| <html lang="en" data-theme="dark"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| <title>SFT v4 Dataset Viewer</title> | |
| <style> | |
| *,*::before,*::after{box-sizing:border-box} | |
| :root{ | |
| color-scheme:dark; | |
| --bg:#14161b; --panel:#1b1e26; --panel2:#22262f; --panel3:#2a2f3a; | |
| --line:#333a49; --fg:#e7e9ef; --dim:#a3aabb; --faint:#7d8595; | |
| --accent:#7aa2f7; --good:#79dd8a; --bad:#ff8078; --warn:#f2c66a; | |
| --info:#6fd0e2; --muted:#8f97a8; --guided:#c4a2ff; --mark:#ffd866; | |
| --shadow:0 1px 2px rgba(0,0,0,.4); | |
| } | |
| :root[data-theme="light"]{ | |
| color-scheme:light; | |
| --bg:#f6f7f9; --panel:#ffffff; --panel2:#f0f2f6; --panel3:#e4e8ef; | |
| --line:#d3d9e3; --fg:#161a21; --dim:#4d5566; --faint:#6b7385; | |
| --accent:#2c5fd0; --good:#1c7a3a; --bad:#c02a20; --warn:#8a6100; | |
| --info:#116b7c; --muted:#5e6678; --guided:#6b3fc4; --mark:#ffe066; | |
| --shadow:0 1px 2px rgba(16,24,40,.08); | |
| } | |
| html,body{margin:0;padding:0} | |
| body{ | |
| background:var(--bg); color:var(--fg); font:14px/1.55 -apple-system,BlinkMacSystemFont, | |
| "Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif; | |
| } | |
| button,input,select{font:inherit;color:inherit} | |
| .hidden{display:none } | |
| a{color:var(--accent)} | |
| header.top{ | |
| position:sticky; top:0; z-index:20; background:var(--panel); border-bottom:1px solid var(--line); | |
| padding:8px 14px; display:flex; flex-direction:column; gap:8px; | |
| } | |
| .top-row{display:flex; flex-wrap:wrap; align-items:center; gap:8px} | |
| .brand{font-weight:700; letter-spacing:.02em} | |
| .brand span{color:var(--dim); font-weight:400; margin-left:8px; font-size:12px} | |
| .spacer{flex:1 1 auto} | |
| .ctl{ | |
| background:var(--panel2); border:1px solid var(--line); color:var(--fg); | |
| border-radius:6px; padding:4px 9px; cursor:pointer; font-size:12px; white-space:nowrap; | |
| } | |
| .ctl:hover{background:var(--panel3)} | |
| .ctl.on{background:var(--accent); border-color:var(--accent); color:#0b1220; font-weight:600} | |
| :root[data-theme="light"] .ctl.on{color:#fff} | |
| .ctl.tiny{padding:2px 7px; font-size:11px} | |
| .group{display:flex; flex-wrap:wrap; align-items:center; gap:4px} | |
| .group-label{color:var(--faint); font-size:11px; text-transform:uppercase; letter-spacing:.08em; margin-right:2px} | |
| input[type=text],input[type=search]{ | |
| background:var(--panel2); border:1px solid var(--line); border-radius:6px; padding:4px 8px; min-width:180px; | |
| } | |
| .hitcount{font-size:11px; color:var(--dim); min-width:70px} | |
| .app{display:flex; align-items:flex-start; gap:0} | |
| .sidebar{ | |
| width:330px; flex:0 0 330px; border-right:1px solid var(--line); background:var(--panel); | |
| position:sticky; top:0; max-height:100vh; overflow:auto; padding:10px; | |
| } | |
| .runstats{font-size:11px; color:var(--dim); line-height:1.7; margin-bottom:8px} | |
| .runstats b{color:var(--fg)} | |
| .side-h{font-size:11px; text-transform:uppercase; letter-spacing:.08em; color:var(--faint); margin:12px 0 6px} | |
| .traj{ | |
| display:block; width:100%; text-align:left; background:var(--panel2); border:1px solid var(--line); | |
| border-left:3px solid var(--line); border-radius:6px; padding:6px 8px; margin-bottom:6px; cursor:pointer; | |
| } | |
| .traj:hover{background:var(--panel3)} | |
| .traj.sel{border-left-color:var(--accent); background:var(--panel3)} | |
| .traj.superseded{opacity:.62; border-style:dashed} | |
| .traj .tid{font-weight:600; font-size:12px; word-break:break-all} | |
| .traj .row{display:flex; flex-wrap:wrap; gap:4px; margin-top:4px} | |
| .badge{ | |
| display:inline-block; font-size:10.5px; line-height:1.5; padding:1px 6px; border-radius:999px; | |
| border:1px solid currentColor; white-space:nowrap; | |
| } | |
| .b-good{color:var(--good)} .b-bad{color:var(--bad)} .b-warn{color:var(--warn)} | |
| .b-info{color:var(--info)} .b-muted{color:var(--muted)} .b-guided{color:var(--guided)} | |
| .b-accent{color:var(--accent)} .b-plain{color:var(--dim)} | |
| .badge.solid{background:currentColor} | |
| .badge.solid span{color:var(--panel); font-weight:700} | |
| main{flex:1 1 auto; min-width:0; padding:12px 16px 120px} | |
| .card{ | |
| background:var(--panel); border:1px solid var(--line); border-radius:8px; | |
| margin:0 0 10px; box-shadow:var(--shadow); overflow:hidden; | |
| } | |
| .card>.card-h{ | |
| display:flex; flex-wrap:wrap; align-items:center; gap:6px; padding:7px 10px; | |
| background:var(--panel2); border-bottom:1px solid var(--line); font-weight:600; font-size:13px; | |
| } | |
| .card>.card-b{padding:9px 10px} | |
| .card.nested{margin:8px 0 0; background:var(--panel2)} | |
| .card.nested>.card-h{background:var(--panel3)} | |
| details.card>summary{ | |
| list-style:none; cursor:pointer; display:flex; flex-wrap:wrap; align-items:center; gap:6px; | |
| padding:7px 10px; background:var(--panel2); border-bottom:1px solid transparent; font-weight:600; font-size:13px; | |
| } | |
| details.card[open]>summary{border-bottom-color:var(--line)} | |
| details.card>summary::-webkit-details-marker{display:none} | |
| details.card>summary::before{content:"\25B8"; color:var(--faint); margin-right:2px} | |
| details.card[open]>summary::before{content:"\25BE"} | |
| .layer.card{border-color:var(--line)} | |
| .layer.guided-layer{border-left:3px solid var(--guided)} | |
| .cand{border-left:3px solid var(--line)} | |
| .cand.guided-cand{border-left-color:var(--guided)} | |
| .cand:target,.flash{animation:flash 1.4s ease-out} | |
| @keyframes flash{from{background:rgba(122,162,247,.28)} to{background:transparent}} | |
| .meta{display:flex; flex-wrap:wrap; gap:4px 14px; font-size:11.5px; color:var(--dim); margin:2px 0 6px} | |
| .meta b{color:var(--fg); font-weight:600} | |
| .lbl{font-size:11px; text-transform:uppercase; letter-spacing:.07em; color:var(--faint); margin:8px 0 3px} | |
| .lbl:first-child{margin-top:0} | |
| ul.plain{margin:2px 0 6px; padding-left:18px} | |
| ul.plain li{margin:2px 0} | |
| .err{ | |
| background:rgba(255,128,120,.14); border:1px solid var(--bad); color:var(--bad); | |
| border-radius:6px; padding:5px 8px; margin:6px 0; font-size:12px; font-weight:600; | |
| white-space:pre-wrap; word-break:break-word; | |
| } | |
| .err-h{font-weight:700; margin-bottom:3px} | |
| .err-b{font-weight:600; font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; | |
| font-size:11.5px; margin-bottom:3px} | |
| .err-f{font-weight:400; font-style:italic; opacity:.85} | |
| .empty{color:var(--faint); font-style:italic; font-size:12px} | |
| .cid{ | |
| font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:11.5px; | |
| background:var(--panel3); border:1px solid var(--line); border-radius:5px; padding:0 5px; | |
| cursor:pointer; color:var(--accent); | |
| } | |
| .cid.plain{color:var(--dim); cursor:default} | |
| .tb{margin:3px 0 8px} | |
| .txt{ | |
| font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace; | |
| font-size:12.5px; line-height:1.62; white-space:pre-wrap; word-break:break-word; | |
| background:var(--panel2); border:1px solid var(--line); border-radius:6px; padding:8px 10px; | |
| overflow-x:auto; position:relative; | |
| } | |
| .txt.prose{font-family:inherit; font-size:13px; line-height:1.6} | |
| .txt.clamped{max-height:16em; overflow:hidden} | |
| .tb.clamp-on .txt.clamped::after{ | |
| content:""; position:absolute; left:0; right:0; bottom:0; height:3.2em; pointer-events:none; | |
| background:linear-gradient(to bottom,transparent,var(--panel2)); | |
| } | |
| .tb-tools{display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin-top:3px} | |
| .tb-note{font-size:11px; color:var(--faint)} | |
| mark{background:var(--mark); color:#171717; border-radius:2px} | |
| mark.here{outline:2px solid var(--accent)} | |
| table.grid{border-collapse:collapse; width:100%; font-size:12.5px; margin:4px 0 6px} | |
| table.grid th,table.grid td{border:1px solid var(--line); padding:4px 7px; text-align:left; vertical-align:top} | |
| table.grid th{background:var(--panel2); font-weight:600; font-size:11px; text-transform:uppercase; | |
| letter-spacing:.05em; color:var(--faint)} | |
| .wrap-scroll{overflow-x:auto} | |
| @media (max-width:900px){ | |
| /* stretch, not flex-start: in a column flex box flex-start sizes children to | |
| max-content and the page would scroll sideways */ | |
| .app{flex-direction:column; align-items:stretch} | |
| .sidebar{flex:none; max-height:44vh; border-right:none; border-bottom:1px solid var(--line); | |
| position:static; width:100%} | |
| main{padding:10px; width:100%} | |
| .card-h,details.card>summary{word-break:break-word} | |
| .meta span,.meta b{min-width:0; word-break:break-word} | |
| input[type=text],input[type=search]{min-width:120px} | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <header class="top"> | |
| <div class="top-row"> | |
| <div class="brand">SFT v4 Dataset Viewer<span id="run-name"></span></div> | |
| <div class="spacer"></div> | |
| <button class="ctl on" id="cot" title="Collapse everything before </think>">CoT hidden</button> | |
| <button class="ctl" id="raw" title="Open every raw provider output block">Raw hidden</button> | |
| <button class="ctl" id="expand-all">Expand all</button> | |
| <button class="ctl" id="collapse-layers">Collapse layers</button> | |
| <button class="ctl" id="theme">Light theme</button> | |
| </div> | |
| <div class="top-row"> | |
| <span class="group-label">stages</span> | |
| <span class="group" id="stage-chips"></span> | |
| <button class="ctl tiny" id="stages-all">all</button> | |
| <button class="ctl tiny" id="stages-none">none</button> | |
| <div class="spacer"></div> | |
| <input type="search" id="search" placeholder="search this trajectory" /> | |
| <button class="ctl tiny" id="prev">prev</button> | |
| <button class="ctl tiny" id="next">next</button> | |
| <button class="ctl tiny" id="only-matches">only matches</button> | |
| <span class="hitcount" id="hits"></span> | |
| </div> | |
| </header> | |
| <div class="app"> | |
| <aside class="sidebar"> | |
| <div class="runstats" id="stats"></div> | |
| <div class="runstats" id="gen"></div> | |
| <input type="text" id="traj-filter" placeholder="filter trajectories" style="width:100%" /> | |
| <div class="side-h">Trajectories</div> | |
| <div id="traj-list"></div> | |
| <div class="side-h hidden" id="filtered-h">Filtered out by F0</div> | |
| <div id="filtered-list"></div> | |
| </aside> | |
| <main id="main"></main> | |
| </div> | |
| <script src="data/run-data.js"></script> | |
| <script> | |
| ; | |
| var DATA = window.__RUN_DATA__; | |
| var THINK_OPEN = '<think>'; | |
| var THINK_CLOSE = '</think>'; | |
| var MAX_MARKS_PER_BLOCK = 300; | |
| var LAZY_MIN = 24000; // chars: bigger blocks are only materialised on demand | |
| var CLAMP_MIN = 700; // chars: shorter blocks need no expand control | |
| var STAGES = [ | |
| ['f0','F0'],['f1','F1'],['f2','F2'],['f3','F3'],['f4','F4'],['f5','F5'], | |
| ['answer','Final answer'],['judge','Judge'],['mr','MR target'],['term','Termination'] | |
| ]; | |
| var CONTRIB_CLASS = { | |
| new_information:'b-good', closes_gap:'b-good', correction_or_stronger:'b-good', | |
| independent_verification:'b-info', useful_negative:'b-warn', redundant:'b-muted', | |
| no_result:'b-muted', flawed_execution:'b-bad' | |
| }; | |
| var STATUS_CLASS = {present:'b-good', partial:'b-warn', missing:'b-bad', not_applicable:'b-muted'}; | |
| var state = { | |
| uid:null, stages:new Set(STAGES.map(function(s){return s[0];})), | |
| hideCot:true, showRaw:false, query:'', filterMatches:false | |
| }; | |
| var blocks = []; | |
| var markNodes = []; | |
| var markPos = -1; | |
| var explorationIndex = {}; // exploration_id -> anchor id | |
| function $(sel){ return document.querySelector(sel); } | |
| function el(tag, cls, text){ | |
| var node = document.createElement(tag); | |
| if(cls) node.className = cls; | |
| if(text !== undefined && text !== null && text !== '') node.textContent = String(text); | |
| return node; | |
| } | |
| function badge(text, cls){ return el('span', 'badge ' + (cls || 'b-plain'), text); } | |
| function num(x){ return (x === null || x === undefined) ? '—' : String(x); } | |
| // ---------------------------------------------------------------- text blocks | |
| function postThink(text){ | |
| var i = text.lastIndexOf(THINK_CLOSE); | |
| if(i < 0) return null; | |
| return text.slice(i + THINK_CLOSE.length).replace(/^\s+/, ''); | |
| } | |
| function displayText(b){ | |
| if(b.cot && state.hideCot && !b.showCot){ | |
| var tail = postThink(b.text); | |
| if(tail !== null) return tail; | |
| } | |
| return b.text; | |
| } | |
| function countMatches(hay, needle){ | |
| if(!needle) return 0; | |
| var h = hay.toLowerCase(), n = needle.toLowerCase(), c = 0, i = h.indexOf(n); | |
| while(i >= 0){ c++; i = h.indexOf(n, i + n.length); } | |
| return c; | |
| } | |
| function paint(node, text, query){ | |
| node.textContent = ''; | |
| if(!query){ node.textContent = text; return 0; } | |
| var h = text.toLowerCase(), n = query.toLowerCase(); | |
| var frag = document.createDocumentFragment(), from = 0, hits = 0, i = h.indexOf(n); | |
| while(i >= 0 && hits < MAX_MARKS_PER_BLOCK){ | |
| if(i > from) frag.appendChild(document.createTextNode(text.slice(from, i))); | |
| var m = el('mark'); m.textContent = text.slice(i, i + n.length); frag.appendChild(m); | |
| from = i + n.length; hits++; | |
| i = h.indexOf(n, from); | |
| } | |
| frag.appendChild(document.createTextNode(text.slice(from))); | |
| node.appendChild(frag); | |
| return hits; | |
| } | |
| function refreshBlock(b){ | |
| var text = displayText(b); | |
| var q = state.query; | |
| var hits = q ? countMatches(text, q) : 0; | |
| // a match hiding below the fold (or inside an unloaded block) is useless | |
| if(hits > 0 && b.lazy && !b.loaded){ b.loaded = true; b.autoExpanded = true; } | |
| if(hits > 0 && !b.expanded){ b.expanded = true; b.autoExpanded = true; } | |
| if(hits === 0 && b.autoExpanded){ b.expanded = false; b.autoExpanded = false; } | |
| var long = text.length > CLAMP_MIN; | |
| var clamp = long && !b.expanded; | |
| if(b.lazy && !b.loaded){ | |
| b.node.textContent = '(' + text.length.toLocaleString() + ' characters — press Load to render)'; | |
| b.node.classList.remove('clamped'); | |
| b.wrap.classList.remove('clamp-on'); | |
| } else { | |
| paint(b.node, text, q); | |
| b.node.classList.toggle('clamped', clamp); | |
| b.wrap.classList.toggle('clamp-on', clamp); | |
| } | |
| b.matches = hits; | |
| if(b.expandBtn){ | |
| b.expandBtn.classList.toggle('hidden', !(long || b.lazy)); | |
| b.expandBtn.textContent = (b.lazy && !b.loaded) | |
| ? 'Load (' + text.length.toLocaleString() + ' chars)' | |
| : (b.expanded ? 'Collapse' : 'Expand (' + text.length.toLocaleString() + ' chars)'); | |
| } | |
| if(b.cotBtn){ | |
| var tail = postThink(b.text); | |
| var hidden = b.text.length - (tail === null ? b.text.length : tail.length); | |
| var isHiding = state.hideCot && !b.showCot && tail !== null; | |
| b.cotBtn.textContent = isHiding ? 'show CoT (' + hidden.toLocaleString() + ' chars)' : 'hide CoT'; | |
| b.cotBtn.classList.toggle('on', !isHiding); | |
| b.cotBtn.classList.toggle('hidden', tail === null && !(b.text.indexOf(THINK_OPEN) >= 0)); | |
| } | |
| if(b.note) b.note.textContent = b.noteText || ''; | |
| } | |
| function refreshAll(){ | |
| blocks.forEach(refreshBlock); | |
| markNodes = Array.prototype.slice.call(document.querySelectorAll('#main mark')); | |
| markPos = -1; | |
| var total = blocks.reduce(function(a, b){ return a + b.matches; }, 0); | |
| $('#hits').textContent = state.query ? (total + ' match' + (total === 1 ? '' : 'es')) : ''; | |
| applyMatchFilter(); | |
| } | |
| function textBlock(parent, text, opts){ | |
| opts = opts || {}; | |
| text = (text === null || text === undefined) ? '' : String(text); | |
| if(!text && opts.hideEmpty) return null; | |
| var wrap = el('div', 'tb'); | |
| if(opts.label) wrap.appendChild(el('div', 'lbl', opts.label)); | |
| if(!text){ | |
| wrap.appendChild(el('div', 'empty', '(empty)')); | |
| parent.appendChild(wrap); | |
| return null; | |
| } | |
| var node = el('div', 'txt' + (opts.prose ? ' prose' : '')); | |
| wrap.appendChild(node); | |
| var tools = el('div', 'tb-tools'); | |
| // any block that actually carries a closed think span is CoT-toggleable, | |
| // whether or not the caller expected reasoning in that field | |
| var isCot = !!opts.cot || text.indexOf(THINK_CLOSE) >= 0; | |
| var b = { | |
| node:node, wrap:wrap, text:text, cot:isCot, expanded:!!opts.expanded, | |
| showCot:false, lazy:text.length > LAZY_MIN, loaded:false, matches:0, autoExpanded:false, | |
| noteText:opts.note || '', note:null, expandBtn:null, cotBtn:null | |
| }; | |
| var expandBtn = el('button', 'ctl tiny', 'Expand'); | |
| expandBtn.addEventListener('click', function(){ | |
| if(b.lazy && !b.loaded){ b.loaded = true; b.expanded = true; } | |
| else b.expanded = !b.expanded; | |
| refreshBlock(b); | |
| markNodes = Array.prototype.slice.call(document.querySelectorAll('#main mark')); | |
| }); | |
| tools.appendChild(expandBtn); | |
| b.expandBtn = expandBtn; | |
| if(isCot){ | |
| var cotBtn = el('button', 'ctl tiny', 'show CoT'); | |
| cotBtn.addEventListener('click', function(){ b.showCot = !b.showCot; refreshBlock(b); }); | |
| tools.appendChild(cotBtn); | |
| b.cotBtn = cotBtn; | |
| } | |
| var note = el('span', 'tb-note', opts.note || ''); | |
| tools.appendChild(note); | |
| b.note = note; | |
| wrap.appendChild(tools); | |
| parent.appendChild(wrap); | |
| blocks.push(b); | |
| refreshBlock(b); | |
| return b; | |
| } | |
| // ---------------------------------------------------------------- primitives | |
| function card(title, stage, opts){ | |
| opts = opts || {}; | |
| var root, body; | |
| if(opts.collapsible){ | |
| root = el('details', 'card' + (opts.cls ? ' ' + opts.cls : '')); | |
| if(opts.open) root.open = true; | |
| var head = el('summary'); | |
| head.appendChild(el('span', null, title)); | |
| (opts.badges || []).forEach(function(b){ head.appendChild(b); }); | |
| root.appendChild(head); | |
| body = el('div', 'card-b'); | |
| root.appendChild(body); | |
| } else { | |
| root = el('div', 'card' + (opts.cls ? ' ' + opts.cls : '')); | |
| var h = el('div', 'card-h'); | |
| h.appendChild(el('span', null, title)); | |
| (opts.badges || []).forEach(function(b){ h.appendChild(b); }); | |
| root.appendChild(h); | |
| body = el('div', 'card-b'); | |
| root.appendChild(body); | |
| } | |
| if(stage) root.dataset.stage = stage; | |
| return {root:root, body:body}; | |
| } | |
| function metaRow(parent, pairs){ | |
| var row = el('div', 'meta'); | |
| pairs.forEach(function(p){ | |
| if(p[1] === null || p[1] === undefined || p[1] === '') return; | |
| var span = el('span', null, p[0] + ': '); | |
| span.appendChild(el('b', null, String(p[1]))); | |
| row.appendChild(span); | |
| }); | |
| if(row.childNodes.length) parent.appendChild(row); | |
| } | |
| function parseError(parent, value, where){ | |
| if(!value) return; | |
| // Say plainly that the pipeline failed to produce this, and that the message | |
| // is the recorded reason. Printing a bare `parse_error: ...` under a heading | |
| // reads as though the viewer failed to render something that exists. | |
| var box = el('div', 'err'); | |
| box.appendChild(el('div', 'err-h', | |
| 'The pipeline produced no ' + (where || 'output') + ' here.')); | |
| box.appendChild(el('div', 'err-b', 'Recorded reason: ' + value)); | |
| box.appendChild(el('div', 'err-f', | |
| 'This is stored run data, not a display problem \\u2014 the phase failed and ' + | |
| 'the record was kept for audit.')); | |
| parent.appendChild(box); | |
| } | |
| function modelNote(meta){ | |
| if(!meta) return ''; | |
| var bits = []; | |
| if(meta.model) bits.push(meta.model); | |
| if(meta.attempts > 1) bits.push(meta.attempts + ' attempts'); | |
| if(meta.output_tokens) bits.push(meta.output_tokens.toLocaleString() + ' out-tok'); | |
| if(meta.reasoning_tokens) bits.push(meta.reasoning_tokens.toLocaleString() + ' reason-tok'); | |
| if(meta.latency_s) bits.push(meta.latency_s + 's'); | |
| return bits.join(' · '); | |
| } | |
| function bulletList(parent, label, items){ | |
| if(!items || !items.length) return; | |
| parent.appendChild(el('div', 'lbl', label + ' (' + items.length + ')')); | |
| var ul = el('ul', 'plain'); | |
| items.forEach(function(x){ ul.appendChild(el('li', null, x)); }); | |
| parent.appendChild(ul); | |
| } | |
| function anchorFor(layerIdx, cid){ return 'cand-' + layerIdx + '-' + cid; } | |
| function cidChip(cid, layerIdx, linkable){ | |
| var chip = el('span', 'cid' + (linkable ? '' : ' plain'), cid); | |
| if(linkable){ | |
| chip.title = 'jump to ' + cid; | |
| chip.addEventListener('click', function(){ | |
| var target = document.getElementById(anchorFor(layerIdx, cid)); | |
| if(!target) return; | |
| if(target.tagName === 'DETAILS') target.open = true; | |
| var parentDetails = target.closest('details.layer'); | |
| if(parentDetails) parentDetails.open = true; | |
| target.scrollIntoView({block:'center'}); | |
| target.classList.remove('flash'); | |
| void target.offsetWidth; | |
| target.classList.add('flash'); | |
| }); | |
| } | |
| return chip; | |
| } | |
| function explorationChip(id){ | |
| var chip = el('span', 'cid', id); | |
| var anchor = explorationIndex[id]; | |
| if(!anchor){ chip.className = 'cid plain'; return chip; } | |
| chip.addEventListener('click', function(){ | |
| var target = document.getElementById(anchor); | |
| if(!target) return; | |
| var parentDetails = target.closest('details.layer'); | |
| if(parentDetails) parentDetails.open = true; | |
| target.scrollIntoView({block:'center'}); | |
| target.classList.remove('flash'); | |
| void target.offsetWidth; | |
| target.classList.add('flash'); | |
| }); | |
| return chip; | |
| } | |
| function chipRow(parent, label, ids, layerIdx, linkable){ | |
| if(!ids || !ids.length) return; | |
| var row = el('div', 'meta'); | |
| row.appendChild(el('span', null, label + ': ')); | |
| ids.forEach(function(id){ row.appendChild(cidChip(id, layerIdx, linkable)); }); | |
| parent.appendChild(row); | |
| } | |
| // ---------------------------------------------------------------- sidebar | |
| function trajBadges(s, entry){ | |
| var out = []; | |
| if(s.source) out.push(badge(s.source, 'b-plain')); | |
| out.push(badge(s.terminated ? 'terminated' : 'incomplete', s.terminated ? 'b-good' : 'b-warn')); | |
| if(s.guided) out.push(badge('guided', 'b-guided')); | |
| if(s.minimum_layers_waived) out.push(badge('minimum waived', 'b-warn')); | |
| out.push(badge(s.n_layers + ' layer' + (s.n_layers === 1 ? '' : 's'), 'b-info')); | |
| if(s.normalized !== null && s.normalized !== undefined){ | |
| var cls = s.normalized >= 0.75 ? 'b-good' : (s.normalized >= 0.4 ? 'b-warn' : 'b-bad'); | |
| out.push(badge(scoreText(s), cls)); | |
| } else { | |
| out.push(badge('no score', 'b-muted')); | |
| } | |
| if(s.excluded_reason) out.push(badge(s.excluded_reason, 'b-bad')); | |
| if(s.parse_errors) out.push(badge(s.parse_errors + ' parse_error', 'b-bad')); | |
| if(entry && entry.superseded) out.push(badge('superseded rev ' + entry.revision, 'b-muted')); | |
| else if(entry && entry.revision_count > 1) out.push(badge('rev ' + entry.revision + '/' + entry.revision_count, 'b-accent')); | |
| return out; | |
| } | |
| function scoreText(s){ | |
| if(s.score === null || s.score === undefined) return 'no score'; | |
| var raw = String(s.score) + (s.score_scale ? ' of ' + s.score_scale.split('-').pop() : ''); | |
| if(s.normalized === null || s.normalized === undefined) return raw; | |
| return raw + ' (' + s.normalized.toFixed(2) + ')'; | |
| } | |
| function renderSidebar(){ | |
| var list = $('#traj-list'); | |
| list.textContent = ''; | |
| var q = ($('#traj-filter').value || '').toLowerCase(); | |
| var shown = 0; | |
| DATA.trajectories.forEach(function(entry){ | |
| var s = entry.summary; | |
| var hay = (s.problem_id + ' ' + s.source + ' ' + s.excluded_reason + ' ' + s.trajectory_id).toLowerCase(); | |
| if(q && hay.indexOf(q) < 0) return; | |
| shown++; | |
| var item = el('button', 'traj' + (entry.superseded ? ' superseded' : '') + (entry.uid === state.uid ? ' sel' : '')); | |
| item.appendChild(el('div', 'tid', s.problem_id || entry.identity)); | |
| var row = el('div', 'row'); | |
| trajBadges(s, entry).forEach(function(b){ row.appendChild(b); }); | |
| item.appendChild(row); | |
| item.addEventListener('click', function(){ select(entry.uid); }); | |
| list.appendChild(item); | |
| }); | |
| if(!shown) list.appendChild(el('div', 'empty', 'no trajectory matches this filter')); | |
| var flist = $('#filtered-list'); | |
| flist.textContent = ''; | |
| $('#filtered-h').classList.toggle('hidden', !DATA.filtered.length); | |
| DATA.filtered.forEach(function(row){ | |
| var hay = (row.problem_id + ' ' + row.source + ' ' + row.reason).toLowerCase(); | |
| if(q && hay.indexOf(q) < 0) return; | |
| var item = el('button', 'traj' + (row.uid === state.uid ? ' sel' : '')); | |
| item.appendChild(el('div', 'tid', row.problem_id)); | |
| var r = el('div', 'row'); | |
| if(row.source) r.appendChild(badge(row.source, 'b-plain')); | |
| r.appendChild(badge('F0 rejected', 'b-bad')); | |
| if(row.f0 && row.f0.validity) r.appendChild(badge(row.f0.validity, 'b-warn')); | |
| item.appendChild(r); | |
| item.addEventListener('click', function(){ select(row.uid); }); | |
| flist.appendChild(item); | |
| }); | |
| } | |
| // ---------------------------------------------------------------- sections | |
| function renderProblem(main, p, outcome, s, entry){ | |
| var head = card('Problem · ' + (p.problem_id || '(no id)'), null, {badges:trajBadges(s, entry)}); | |
| metaRow(head.body, [ | |
| ['trajectory', outcome.trajectory_id], ['version', outcome.version_id], | |
| ['final_layer', outcome.final_layer], ['terminated', outcome.terminated], | |
| ['guided', outcome.guided], ['excluded_reason', outcome.excluded_reason || '—'], | |
| ['productive_layers', outcome.productive_layers], | |
| ['minimum_layers', outcome.minimum_layers], | |
| ['minimum waived', outcome.minimum_layers_waived ? (outcome.minimum_waiver_reason || 'yes') : 'no'], | |
| ['MR targets', s.n_mr_targets], ['candidates', s.n_candidates], | |
| ['executions', s.n_executions], ['retained', s.n_retained] | |
| ]); | |
| if(entry.superseded){ | |
| head.body.appendChild(el('div', 'err', | |
| 'This is revision ' + entry.revision + ' of ' + entry.revision_count + | |
| ' for this identity; a later line in trajectories.jsonl supersedes it.')); | |
| } | |
| textBlock(head.body, p.problem, {label:'Problem statement', prose:true}); | |
| textBlock(head.body, p.rubric, {label:'Rubric', prose:true}); | |
| if(p.reference_solution) textBlock(head.body, p.reference_solution, {label:'Reference solution (metadata)', prose:true}); | |
| main.appendChild(head.root); | |
| } | |
| function renderF0(main, f0){ | |
| if(!f0) return; | |
| var vcls = f0.validity === 'valid' ? 'b-good' : (f0.validity === 'invalid' ? 'b-bad' : 'b-warn'); | |
| var c = card('F0 — problem validity & solution checklist', 'f0', { | |
| collapsible:true, open:true, | |
| badges:[badge(f0.validity || 'unknown', vcls), | |
| badge((f0.checklist || []).length + ' checklist items', 'b-info')] | |
| }); | |
| parseError(c.body, f0.parse_error, 'f0'); | |
| metaRow(c.body, [['model', modelNote(f0.model)]]); | |
| bulletList(c.body, 'Validity issues', f0.validity_issues); | |
| if((f0.checklist || []).length){ | |
| var wrap = el('div', 'wrap-scroll'); | |
| var t = el('table', 'grid'); | |
| var thead = el('tr'); | |
| ['item', 'importance', 'verify?', 'obligation', 'acceptable evidence'].forEach(function(h){ | |
| thead.appendChild(el('th', null, h)); | |
| }); | |
| t.appendChild(thead); | |
| f0.checklist.forEach(function(item){ | |
| var tr = el('tr'); | |
| var idcell = el('td'); | |
| idcell.appendChild(cidChip(item.item_id, -1, false)); | |
| tr.appendChild(idcell); | |
| tr.appendChild(el('td', null, item.importance || '—')); | |
| tr.appendChild(el('td', null, item.verification_needed ? 'yes' : 'no')); | |
| tr.appendChild(el('td', null, item.obligation)); | |
| var ev = el('td'); | |
| if((item.acceptable_evidence || []).length){ | |
| var ul = el('ul', 'plain'); | |
| item.acceptable_evidence.forEach(function(x){ ul.appendChild(el('li', null, x)); }); | |
| ev.appendChild(ul); | |
| } else ev.appendChild(el('span', 'empty', '—')); | |
| tr.appendChild(ev); | |
| t.appendChild(tr); | |
| }); | |
| wrap.appendChild(t); | |
| c.body.appendChild(wrap); | |
| } | |
| rawBlock(c.body, 'F0 raw output', f0.raw_output); | |
| main.appendChild(c.root); | |
| } | |
| function rawBlock(parent, label, text, note){ | |
| if(!text) return; | |
| var d = el('details', 'card nested'); | |
| var s = el('summary'); | |
| s.appendChild(el('span', null, label)); | |
| s.appendChild(badge('raw', 'b-muted')); | |
| s.appendChild(el('span', 'tb-note', ' ' + text.length.toLocaleString() + ' chars')); | |
| d.appendChild(s); | |
| var body = el('div', 'card-b'); | |
| d.appendChild(body); | |
| d.classList.add('raw-wrap'); | |
| if(state.showRaw) d.open = true; | |
| textBlock(body, text, {cot:true, note:note || ''}); | |
| parent.appendChild(d); | |
| } | |
| function renderAssessment(parent, a){ | |
| if(!a) return; | |
| bulletList(parent, 'Last-layer assessment', a.last_layer_assessment); | |
| bulletList(parent, 'Current strategies', a.current_strategies); | |
| bulletList(parent, 'Open questions & unknowns', a.open_questions_and_unknowns); | |
| bulletList(parent, 'Claims needing verification', a.claims_needing_verification); | |
| } | |
| function chainRows(layer){ | |
| var order = [], map = {}; | |
| function touch(cid){ | |
| cid = cid || '(no id)'; | |
| if(!map[cid]){ map[cid] = {cid:cid, cand:null, assess:null, execs:[], retries:[], review:null}; order.push(cid); } | |
| return map[cid]; | |
| } | |
| ((layer.f1 || {}).candidates || []).forEach(function(c){ touch(c.candidate_id).cand = c; }); | |
| ((layer.f2 || {}).assessments || []).forEach(function(a){ touch(a.candidate_id).assess = a; }); | |
| (layer.executions || []).forEach(function(e){ touch(e.candidate_id).execs.push(e); }); | |
| (layer.retry_executions || []).forEach(function(e){ | |
| var row = touch(e.candidate_id); | |
| var already = row.execs.some(function(x){ return x.attempt === e.attempt && x.report === e.report; }); | |
| if(!already) row.retries.push(e); | |
| }); | |
| ((layer.f4 || {}).reviews || []).forEach(function(r){ touch(r.candidate_id).review = r; }); | |
| return order.map(function(cid){ return map[cid]; }); | |
| } | |
| function renderCandidate(parent, layer, row){ | |
| var cand = row.cand, assess = row.assess, review = row.review; | |
| var guided = !!(cand && cand.guided) || row.execs.some(function(e){ return e.guided; }); | |
| var badges = []; | |
| if(cand && cand.candidate_type) badges.push(badge(cand.candidate_type, 'b-accent')); | |
| if(assess) badges.push(badge('F2 ' + assess.decision + (assess.rank >= 0 ? ' #' + assess.rank : ''), | |
| assess.decision === 'pass' ? 'b-good' : 'b-bad')); | |
| if(row.execs.length) badges.push(badge(row.execs.length + ' execution' + (row.execs.length === 1 ? '' : 's'), 'b-info')); | |
| if(row.retries.length) badges.push(badge(row.retries.length + ' retry', 'b-warn')); | |
| if(review){ | |
| badges.push(badge(review.contribution || 'no contribution', CONTRIB_CLASS[review.contribution] || 'b-muted')); | |
| badges.push(badge(review.retain ? 'retained' : 'dropped', review.retain ? 'b-good' : 'b-muted')); | |
| } | |
| if(guided) badges.push(badge('guided', 'b-guided')); | |
| var c = card('candidate ' + row.cid, null, { | |
| collapsible:true, open:true, badges:badges, | |
| cls:'nested cand' + (guided ? ' guided-cand' : '') | |
| }); | |
| c.root.id = anchorFor(layer.layer_idx, row.cid); | |
| if(cand){ | |
| var f1 = el('div'); | |
| f1.dataset.stage = 'f1'; | |
| f1.appendChild(el('div', 'lbl', 'F1 proposal')); | |
| metaRow(f1, [['type', cand.candidate_type], ['guided', cand.guided ? 'yes' : ''], | |
| ['source_item_id', cand.source_item_id || '']]); | |
| textBlock(f1, cand.direction, {label:'direction', prose:true}); | |
| textBlock(f1, cand.target, {label:'target', prose:true, hideEmpty:true}); | |
| textBlock(f1, cand.why_valuable, {label:'why valuable', prose:true, hideEmpty:true}); | |
| c.body.appendChild(f1); | |
| } | |
| if(assess){ | |
| var f2 = el('div'); | |
| f2.dataset.stage = 'f2'; | |
| f2.appendChild(el('div', 'lbl', 'F2 verdict')); | |
| metaRow(f2, [['decision', assess.decision], ['rank', assess.rank]]); | |
| chipRow(f2, 'overlaps with', assess.overlaps_with, layer.layer_idx, true); | |
| textBlock(f2, assess.expected_information_value, {label:'expected information value', prose:true, hideEmpty:true}); | |
| textBlock(f2, assess.critique, {label:'critique', prose:true, hideEmpty:true}); | |
| textBlock(f2, assess.reasoning, {label:'reasoning', prose:true, hideEmpty:true}); | |
| c.body.appendChild(f2); | |
| } | |
| row.execs.concat(row.retries).forEach(function(e, i){ | |
| var f3 = el('div'); | |
| f3.dataset.stage = 'f3'; | |
| var isRetryOnly = i >= row.execs.length; | |
| f3.appendChild(el('div', 'lbl', | |
| 'F3 execution' + (e.attempt ? ' · attempt ' + e.attempt : '') + (isRetryOnly ? ' (retry record)' : ''))); | |
| parseError(f3, e.parse_error, 'f3'); | |
| metaRow(f3, [['guided', e.guided ? 'yes' : ''], ['model', modelNote(e.model)]]); | |
| textBlock(f3, e.report, {label:'report (durable target)', note:'durable'}); | |
| rawBlock(f3, 'F3 raw provider output', e.raw_output); | |
| c.body.appendChild(f3); | |
| }); | |
| if(review){ | |
| var f4 = el('div'); | |
| f4.dataset.stage = 'f4'; | |
| f4.appendChild(el('div', 'lbl', 'F4 review')); | |
| parseError(f4, review.parse_error, 'f4 review'); | |
| var flags = el('div', 'meta'); | |
| // usable/faithful/retain read good when true, obvious_flaw when false; | |
| // forward_rejection_supported is informational either way | |
| [['usable', review.usable], ['faithful', review.faithful], ['obvious_flaw', review.obvious_flaw], | |
| ['retain', review.retain] | |
| ].forEach(function(p){ | |
| var good = p[0] === 'obvious_flaw' ? !p[1] : !!p[1]; | |
| flags.appendChild(badge(p[0] + ': ' + (p[1] ? 'yes' : 'no'), good ? 'b-good' : 'b-bad')); | |
| }); | |
| flags.appendChild(badge('forward_rejection_supported: ' + (review.forward_rejection_supported ? 'yes' : 'no'), | |
| review.forward_rejection_supported ? 'b-info' : 'b-muted')); | |
| flags.appendChild(badge('contribution: ' + (review.contribution || '—'), | |
| CONTRIB_CLASS[review.contribution] || 'b-muted')); | |
| if(review.redundancy_cause && review.redundancy_cause !== 'not_applicable'){ | |
| flags.appendChild(badge('redundancy: ' + review.redundancy_cause, 'b-warn')); | |
| } | |
| f4.appendChild(flags); | |
| textBlock(f4, review.forward_rejection_reason, {label:'forward rejection reason', prose:true, hideEmpty:true}); | |
| if(review.summary){ | |
| var sm = el('div'); | |
| sm.appendChild(el('div', 'lbl', 'frontier summary' + | |
| (review.summary.exploration_id ? ' · exploration ' + review.summary.exploration_id : ''))); | |
| textBlock(sm, review.summary.detailed_summary, {label:'detailed summary', prose:true, hideEmpty:true}); | |
| textBlock(sm, review.summary.rationale, {label:'rationale', prose:true, hideEmpty:true}); | |
| textBlock(sm, review.summary.core_result, {label:'core result', prose:true, hideEmpty:true}); | |
| f4.appendChild(sm); | |
| } | |
| c.body.appendChild(f4); | |
| } | |
| parent.appendChild(c.root); | |
| } | |
| function renderF5(parent, f5, layerIdx){ | |
| if(!f5) return; | |
| var c = card('F5 — checklist audit & termination decision', 'f5', { | |
| collapsible:true, open:true, cls:'nested', | |
| badges:[badge(f5.decision || 'no decision', f5.decision === 'terminate' ? 'b-good' : 'b-warn')] | |
| .concat(f5.confirmation_used ? [badge('confirmation used', 'b-info')] : []) | |
| .concat(f5.guided_item_id ? [badge('guided item ' + f5.guided_item_id, 'b-guided')] : []) | |
| }); | |
| parseError(c.body, f5.parse_error, 'f5'); | |
| metaRow(c.body, [['model', modelNote(f5.model)]]); | |
| if((f5.checklist || []).length){ | |
| var wrap = el('div', 'wrap-scroll'); | |
| var t = el('table', 'grid'); | |
| var head = el('tr'); | |
| ['item', 'status', 'supporting', 'verification', 'explanation'].forEach(function(h){ head.appendChild(el('th', null, h)); }); | |
| t.appendChild(head); | |
| f5.checklist.forEach(function(item){ | |
| var tr = el('tr'); | |
| var idc = el('td'); idc.appendChild(cidChip(item.item_id, -1, false)); tr.appendChild(idc); | |
| var st = el('td'); st.appendChild(badge(item.status || '—', STATUS_CLASS[item.status] || 'b-muted')); tr.appendChild(st); | |
| var sup = el('td'); | |
| (item.supporting_explorations || []).forEach(function(x){ sup.appendChild(explorationChip(x)); }); | |
| if(!(item.supporting_explorations || []).length) sup.appendChild(el('span', 'empty', '—')); | |
| tr.appendChild(sup); | |
| tr.appendChild(el('td', null, item.verification || '—')); | |
| tr.appendChild(el('td', null, item.explanation || '—')); | |
| t.appendChild(tr); | |
| }); | |
| wrap.appendChild(t); | |
| c.body.appendChild(wrap); | |
| } | |
| bulletList(c.body, 'Major unverified claims', f5.major_unverified_claims); | |
| textBlock(c.body, f5.reason, {label:'decision reason', prose:true, hideEmpty:true}); | |
| textBlock(c.body, f5.guided_diagnostic, {label:'guided diagnostic', prose:true, hideEmpty:true}); | |
| rawBlock(c.body, 'F5 raw output', f5.raw_output); | |
| if(f5.initial_raw_output && f5.initial_raw_output !== f5.raw_output){ | |
| rawBlock(c.body, 'F5 initial raw output (before confirmation)', f5.initial_raw_output); | |
| } | |
| parent.appendChild(c.root); | |
| } | |
| function renderMR(parent, mr){ | |
| var badges = [badge('layer ' + mr.layer_idx, 'b-info')]; | |
| if(mr.parse_error) badges.push(badge('parse_error', 'b-bad')); | |
| var c = card('MR target — layer ' + mr.layer_idx, 'mr', { | |
| collapsible:true, open:true, cls:'nested', badges:badges | |
| }); | |
| parseError(c.body, mr.parse_error, 'mr target'); | |
| metaRow(c.body, [['model', modelNote(mr.model)], | |
| ['assistant_target chars', (mr.assistant_target || '').length.toLocaleString()]]); | |
| chipRow(c.body, 'selected', mr.selected_candidate_ids, mr.layer_idx, true); | |
| chipRow(c.body, 'rejected', mr.rejected_candidate_ids, mr.layer_idx, true); | |
| chipRow(c.body, 'dropped after synthesis failure', mr.dropped_candidate_ids, mr.layer_idx, true); | |
| textBlock(c.body, mr.assistant_target, {label:'assistant target (training text)', cot:true}); | |
| textBlock(c.body, mr.stocktake, {label:'stocktake', cot:true, hideEmpty:true}); | |
| textBlock(c.body, mr.deliberation, {label:'deliberation', cot:true, hideEmpty:true}); | |
| (mr.direction_fragments || []).forEach(function(f){ | |
| var d = el('div'); | |
| var lbl = el('div', 'lbl'); | |
| lbl.appendChild(document.createTextNode('fragment ')); | |
| lbl.appendChild(cidChip(f.candidate_id, mr.layer_idx, true)); | |
| lbl.appendChild(document.createTextNode(' ')); | |
| lbl.appendChild(badge(f.disposition || '—', f.disposition === 'selected' ? 'b-good' : 'b-muted')); | |
| d.appendChild(lbl); | |
| textBlock(d, f.continuation, {cot:true}); | |
| c.body.appendChild(d); | |
| }); | |
| rawBlock(c.body, 'failed synthesis raw output', mr.failure_raw_output); | |
| parent.appendChild(c.root); | |
| } | |
| function renderLayer(main, layer, mrByLayer){ | |
| var badges = []; | |
| if(layer.guided) badges.push(badge('guided layer', 'b-guided')); | |
| if(layer.productive) badges.push(badge('productive', 'b-good')); | |
| if(layer.termination_deferred) badges.push(badge('termination deferred', 'b-warn')); | |
| var f1 = layer.f1 || {}, f2 = layer.f2 || {}, f4 = layer.f4 || {}, f5 = layer.f5 || {}; | |
| var passes = (f2.assessments || []).filter(function(a){ return a.decision === 'pass'; }).length; | |
| badges.push(badge((f1.candidates || []).length + ' candidates', 'b-plain')); | |
| badges.push(badge(passes + ' pass', 'b-good')); | |
| badges.push(badge((layer.executions || []).length + ' executions', 'b-info')); | |
| var retained = (f4.reviews || []).filter(function(r){ return r.retain; }).length; | |
| badges.push(badge(retained + ' retained', 'b-accent')); | |
| if(f4.escalated) badges.push(badge('F4 escalated', 'b-warn')); | |
| if(f5.decision) badges.push(badge('F5 ' + f5.decision, f5.decision === 'terminate' ? 'b-good' : 'b-warn')); | |
| var errs = countErrors(layer); | |
| if(errs) badges.push(badge(errs + ' parse_error', 'b-bad')); | |
| var c = card('Layer ' + layer.layer_idx, null, { | |
| collapsible:true, open:false, badges:badges, | |
| cls:'layer' + (layer.guided ? ' guided-layer' : '') | |
| }); | |
| textBlock(c.body, layer.search_context, {label:'search-budget context', prose:true, hideEmpty:true}); | |
| c.root.classList.add('layer'); | |
| var fb = el('div'); | |
| fb.dataset.stage = 'f1'; | |
| textBlock(fb, layer.frontier_before, {label:'frontier before this layer', hideEmpty:true}); | |
| c.body.appendChild(fb); | |
| if(layer.f1){ | |
| var f1c = card('F1 — assessment & candidate proposals', 'f1', { | |
| collapsible:true, open:true, cls:'nested', | |
| badges:[badge((layer.f1.candidates || []).length + ' candidates', 'b-plain')] | |
| }); | |
| parseError(f1c.body, layer.f1.parse_error, 'f1'); | |
| metaRow(f1c.body, [['model', modelNote(layer.f1.model)]]); | |
| renderAssessment(f1c.body, layer.f1.assessment); | |
| rawBlock(f1c.body, 'F1 raw output', layer.f1.raw_output); | |
| c.body.appendChild(f1c.root); | |
| } | |
| if(layer.unguided_f1){ | |
| var uc = card('F1 before teacher guidance — what the model proposed unaided', 'f1', { | |
| collapsible:true, open:false, cls:'nested', | |
| badges:[badge('unguided', 'b-muted'), | |
| badge((layer.unguided_f1.candidates || []).length + ' candidates', 'b-plain')] | |
| }); | |
| var ownIds = {}; | |
| (layer.unguided_f1.candidates || []).forEach(function(x){ ownIds[x.candidate_id] = true; }); | |
| var added = ((layer.f1 || {}).candidates || []) | |
| .filter(function(x){ return !ownIds[x.candidate_id]; }) | |
| .map(function(x){ return x.candidate_id; }); | |
| if(added.length) chipRow(uc.body, 'candidates added by guidance', added, layer.layer_idx, true); | |
| parseError(uc.body, layer.unguided_f1.parse_error, 'unguided f1'); | |
| renderAssessment(uc.body, layer.unguided_f1.assessment); | |
| (layer.unguided_f1.candidates || []).forEach(function(cand){ | |
| var d = el('div'); | |
| var lbl = el('div', 'lbl'); | |
| lbl.appendChild(cidChip(cand.candidate_id, -1, false)); | |
| lbl.appendChild(document.createTextNode(' ')); | |
| lbl.appendChild(badge(cand.candidate_type || '—', 'b-accent')); | |
| d.appendChild(lbl); | |
| textBlock(d, cand.direction, {prose:true}); | |
| uc.body.appendChild(d); | |
| }); | |
| rawBlock(uc.body, 'unguided F1 raw output', layer.unguided_f1.raw_output); | |
| c.body.appendChild(uc.root); | |
| } | |
| var chain = chainRows(layer); | |
| if(chain.length){ | |
| var cc = card('F1 → F2 → F3 → F4 per candidate', null, { | |
| collapsible:true, open:true, cls:'nested', | |
| badges:[badge(chain.length + ' candidate ids', 'b-plain')] | |
| }); | |
| chain.forEach(function(row){ renderCandidate(cc.body, layer, row); }); | |
| c.body.appendChild(cc.root); | |
| } | |
| if(layer.f2 && (layer.f2.raw_output || layer.f2.parse_error)){ | |
| var f2c = card('F2 — raw verdict output', 'f2', {collapsible:true, open:false, cls:'nested'}); | |
| parseError(f2c.body, layer.f2.parse_error, 'f2'); | |
| metaRow(f2c.body, [['model', modelNote(layer.f2.model)]]); | |
| textBlock(f2c.body, layer.f2.raw_output, {cot:true, hideEmpty:true}); | |
| c.body.appendChild(f2c.root); | |
| } | |
| if(layer.f4){ | |
| var f4c = card('F4 — review pass output', 'f4', { | |
| collapsible:true, open:false, cls:'nested', | |
| badges:(layer.f4.escalated ? [badge('escalated', 'b-warn')] : []) | |
| }); | |
| parseError(f4c.body, layer.f4.parse_error, 'f4'); | |
| metaRow(f4c.body, [['model', modelNote(layer.f4.model)]]); | |
| rawBlock(f4c.body, 'F4 raw output', layer.f4.raw_output); | |
| if(layer.f4.initial_raw_output && layer.f4.initial_raw_output !== layer.f4.raw_output){ | |
| rawBlock(f4c.body, 'F4 initial raw output (before escalation)', layer.f4.initial_raw_output); | |
| } | |
| c.body.appendChild(f4c.root); | |
| } | |
| renderF5(c.body, layer.f5, layer.layer_idx); | |
| (mrByLayer[layer.layer_idx] || []).forEach(function(mr){ renderMR(c.body, mr); }); | |
| main.appendChild(c.root); | |
| } | |
| function countErrors(node){ | |
| var n = 0; | |
| if(node && typeof node === 'object'){ | |
| if(Array.isArray(node)) node.forEach(function(x){ n += countErrors(x); }); | |
| else Object.keys(node).forEach(function(k){ | |
| if(k === 'parse_error'){ if(node[k]) n++; } | |
| else n += countErrors(node[k]); | |
| }); | |
| } | |
| return n; | |
| } | |
| function renderAnswer(main, fa){ | |
| if(!fa) return; | |
| var c = card('Final answer', 'answer', { | |
| collapsible:true, open:true, | |
| badges:[badge(fa.terminated ? 'terminated' : 'not terminated', fa.terminated ? 'b-good' : 'b-warn')] | |
| }); | |
| parseError(c.body, fa.parse_error, 'final answer'); | |
| metaRow(c.body, [['model', modelNote(fa.model)]]); | |
| textBlock(c.body, fa.answer, {label:'answer (durable)'}); | |
| textBlock(c.body, fa.frontier, {label:'frontier the answer was written from', hideEmpty:true}); | |
| rawBlock(c.body, 'final answer raw output', fa.raw_output); | |
| main.appendChild(c.root); | |
| } | |
| function renderJudge(main, j){ | |
| if(!j) return; | |
| var cls = (j.normalized === null || j.normalized === undefined) ? 'b-muted' | |
| : (j.normalized >= 0.75 ? 'b-good' : (j.normalized >= 0.4 ? 'b-warn' : 'b-bad')); | |
| var text = (j.score === null || j.score === undefined) | |
| ? 'no score' | |
| : num(j.score) + (j.score_max ? '/' + j.score_max : '') + | |
| (j.normalized === null || j.normalized === undefined ? '' : ' (' + j.normalized.toFixed(2) + ')'); | |
| var c = card('Final judge', 'judge', { | |
| collapsible:true, open:true, | |
| badges:[badge(text, cls), badge('scale ' + (j.score_scale || '?'), 'b-plain')] | |
| }); | |
| parseError(c.body, j.parse_error, 'judge'); | |
| metaRow(c.body, [['raw score', num(j.score)], ['scale', j.score_scale], | |
| ['normalized', j.normalized === null || j.normalized === undefined ? '—' : j.normalized.toFixed(3)], | |
| ['model', modelNote(j.model)]]); | |
| textBlock(c.body, j.explanation, {label:'explanation', prose:true}); | |
| rawBlock(c.body, 'judge raw output', j.raw_output); | |
| main.appendChild(c.root); | |
| } | |
| function renderTermination(main, t){ | |
| if(!t) return; | |
| var c = card('Termination target', 'term', { | |
| collapsible:true, open:true, | |
| badges:t.parse_error ? [badge('parse_error', 'b-bad')] : [] | |
| }); | |
| parseError(c.body, t.parse_error, 'termination target'); | |
| metaRow(c.body, [['model', modelNote(t.model)], | |
| ['assistant_target chars', (t.assistant_target || '').length.toLocaleString()]]); | |
| textBlock(c.body, t.assistant_target, {label:'assistant target (training text)', cot:true}); | |
| textBlock(c.body, t.cot, {label:'cot', cot:true, hideEmpty:true}); | |
| textBlock(c.body, t.rationale, {label:'rationale', cot:true, hideEmpty:true}); | |
| main.appendChild(c.root); | |
| } | |
| function renderFiltered(main, row){ | |
| var head = card('F0-rejected problem · ' + row.problem_id, null, { | |
| badges:[badge('filtered out', 'b-bad')].concat(row.source ? [badge(row.source, 'b-plain')] : []) | |
| }); | |
| metaRow(head.body, [['reason', row.reason || '—'], | |
| ['validity', row.f0 ? row.f0.validity : '—']]); | |
| textBlock(head.body, row.problem, {label:'Problem statement', prose:true}); | |
| textBlock(head.body, row.rubric, {label:'Rubric', prose:true, hideEmpty:true}); | |
| main.appendChild(head.root); | |
| renderF0(main, row.f0); | |
| } | |
| // ---------------------------------------------------------------- selection | |
| function findTrajectory(uid){ | |
| for(var i = 0; i < DATA.trajectories.length; i++){ | |
| if(DATA.trajectories[i].uid === uid) return DATA.trajectories[i]; | |
| } | |
| return null; | |
| } | |
| function findFiltered(uid){ | |
| for(var i = 0; i < DATA.filtered.length; i++){ | |
| if(DATA.filtered[i].uid === uid) return DATA.filtered[i]; | |
| } | |
| return null; | |
| } | |
| function select(uid){ | |
| state.uid = uid; | |
| blocks = []; | |
| explorationIndex = {}; | |
| var main = $('#main'); | |
| main.textContent = ''; | |
| var entry = findTrajectory(uid); | |
| if(entry){ | |
| var d = entry.data; | |
| (d.layers || []).forEach(function(layer){ | |
| (((layer.f4 || {}).reviews) || []).forEach(function(r){ | |
| if(r.summary && r.summary.exploration_id){ | |
| explorationIndex[r.summary.exploration_id] = anchorFor(layer.layer_idx, r.candidate_id); | |
| } | |
| }); | |
| }); | |
| renderProblem(main, d.problem, d.outcome, entry.summary, entry); | |
| renderF0(main, d.f0); | |
| var mrByLayer = {}; | |
| (d.mr_targets || []).forEach(function(mr){ | |
| (mrByLayer[mr.layer_idx] = mrByLayer[mr.layer_idx] || []).push(mr); | |
| }); | |
| var seen = {}; | |
| (d.layers || []).forEach(function(layer){ | |
| seen[layer.layer_idx] = true; | |
| renderLayer(main, layer, mrByLayer); | |
| }); | |
| if(!(d.layers || []).length){ | |
| main.appendChild(el('div', 'empty', | |
| 'This trajectory has no layers' + | |
| (d.outcome.excluded_reason ? ' (excluded_reason: ' + d.outcome.excluded_reason + ')' : '') + '.')); | |
| } | |
| var orphans = (d.mr_targets || []).filter(function(mr){ return !seen[mr.layer_idx]; }); | |
| if(orphans.length){ | |
| var oc = card('MR targets without a matching layer', 'mr', {collapsible:true, open:true}); | |
| orphans.forEach(function(mr){ renderMR(oc.body, mr); }); | |
| main.appendChild(oc.root); | |
| } | |
| renderAnswer(main, d.final_answer); | |
| renderJudge(main, d.final_judge); | |
| renderTermination(main, d.termination_target); | |
| } else { | |
| var f = findFiltered(uid); | |
| if(f) renderFiltered(main, f); | |
| } | |
| applyStageFilter(); | |
| refreshAll(); | |
| renderSidebar(); | |
| window.scrollTo(0, 0); | |
| } | |
| // ---------------------------------------------------------------- controls | |
| function applyStageFilter(){ | |
| document.querySelectorAll('#main [data-stage]').forEach(function(n){ | |
| n.classList.toggle('hidden', !state.stages.has(n.dataset.stage)); | |
| }); | |
| document.querySelectorAll('#main .cand').forEach(function(c){ | |
| c.classList.toggle('hidden', !c.querySelector('[data-stage]:not(.hidden)')); | |
| }); | |
| document.querySelectorAll('#main .layer').forEach(function(l){ | |
| l.classList.toggle('hidden', !l.querySelector('[data-stage]:not(.hidden)')); | |
| }); | |
| } | |
| function applyMatchFilter(){ | |
| var on = state.filterMatches && state.query; | |
| document.querySelectorAll('#main .card').forEach(function(c){ | |
| if(!on){ c.classList.remove('nomatch'); c.style.display = ''; return; } | |
| c.style.display = c.querySelector('mark') ? '' : 'none'; | |
| }); | |
| } | |
| function jumpMark(delta){ | |
| if(!markNodes.length) return; | |
| if(markPos >= 0 && markNodes[markPos]) markNodes[markPos].classList.remove('here'); | |
| markPos = (markPos + delta + markNodes.length) % markNodes.length; | |
| var m = markNodes[markPos]; | |
| var d = m.closest('details'); | |
| while(d){ d.open = true; d = d.parentElement ? d.parentElement.closest('details') : null; } | |
| m.classList.add('here'); | |
| m.scrollIntoView({block:'center'}); | |
| } | |
| function buildStageChips(){ | |
| var host = $('#stage-chips'); | |
| STAGES.forEach(function(s){ | |
| var b = el('button', 'ctl tiny on', s[1]); | |
| b.addEventListener('click', function(){ | |
| if(state.stages.has(s[0])) state.stages.delete(s[0]); else state.stages.add(s[0]); | |
| b.classList.toggle('on', state.stages.has(s[0])); | |
| applyStageFilter(); | |
| }); | |
| b.dataset.stage = s[0]; | |
| host.appendChild(b); | |
| }); | |
| } | |
| function setAllStages(on){ | |
| state.stages = on ? new Set(STAGES.map(function(s){ return s[0]; })) : new Set(); | |
| document.querySelectorAll('#stage-chips .ctl').forEach(function(b){ b.classList.toggle('on', on); }); | |
| applyStageFilter(); | |
| } | |
| function setTheme(theme){ | |
| document.documentElement.setAttribute('data-theme', theme); | |
| $('#theme').textContent = theme === 'dark' ? 'Light theme' : 'Dark theme'; | |
| try { localStorage.setItem('mtv4-theme', theme); } catch(e) {} | |
| } | |
| function init(){ | |
| $('#run-name').textContent = DATA.run_name || DATA.run_dir; | |
| var st = DATA.stats; | |
| $('#stats').textContent = | |
| st.trajectories + ' trajectories · ' + st.terminated + ' terminated · ' + st.guided + ' guided · ' + | |
| st.minimum_waived + ' minimum waived · ' + | |
| st.excluded + ' excluded · ' + st.superseded + ' superseded · ' + st.filtered + ' F0-filtered · ' + | |
| st.parse_errors + ' parse errors · mean score ' + | |
| (st.mean_normalized === null || st.mean_normalized === undefined ? '—' : st.mean_normalized); | |
| $('#gen').textContent = DATA.run_dir + ' · generated ' + DATA.generated_at; | |
| buildStageChips(); | |
| $('#stages-all').addEventListener('click', function(){ setAllStages(true); }); | |
| $('#stages-none').addEventListener('click', function(){ setAllStages(false); }); | |
| $('#cot').addEventListener('click', function(){ | |
| state.hideCot = !state.hideCot; | |
| this.classList.toggle('on', state.hideCot); | |
| this.textContent = state.hideCot ? 'CoT hidden' : 'CoT shown'; | |
| refreshAll(); | |
| }); | |
| $('#raw').addEventListener('click', function(){ | |
| state.showRaw = !state.showRaw; | |
| this.classList.toggle('on', state.showRaw); | |
| this.textContent = state.showRaw ? 'Raw shown' : 'Raw hidden'; | |
| document.querySelectorAll('#main .raw-wrap').forEach(function(d){ d.open = state.showRaw; }); | |
| }); | |
| $('#expand-all').addEventListener('click', function(){ | |
| document.querySelectorAll('#main details').forEach(function(d){ d.open = true; }); | |
| }); | |
| $('#collapse-layers').addEventListener('click', function(){ | |
| document.querySelectorAll('#main details.layer').forEach(function(d){ d.open = false; }); | |
| }); | |
| var timer = null; | |
| $('#search').addEventListener('input', function(){ | |
| var value = this.value; | |
| if(timer) clearTimeout(timer); | |
| timer = setTimeout(function(){ state.query = value; refreshAll(); }, 160); | |
| }); | |
| $('#next').addEventListener('click', function(){ jumpMark(1); }); | |
| $('#prev').addEventListener('click', function(){ jumpMark(-1); }); | |
| $('#only-matches').addEventListener('click', function(){ | |
| state.filterMatches = !state.filterMatches; | |
| this.classList.toggle('on', state.filterMatches); | |
| applyMatchFilter(); | |
| }); | |
| $('#traj-filter').addEventListener('input', renderSidebar); | |
| $('#theme').addEventListener('click', function(){ | |
| setTheme(document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark'); | |
| }); | |
| var saved = 'dark'; | |
| try { saved = localStorage.getItem('mtv4-theme') || 'dark'; } catch(e) {} | |
| setTheme(saved); | |
| renderSidebar(); | |
| var first = DATA.trajectories.length ? DATA.trajectories[0].uid | |
| : (DATA.filtered.length ? DATA.filtered[0].uid : null); | |
| if(first) select(first); | |
| else $('#main').appendChild(el('div', 'empty', 'This run directory contains no trajectories.')); | |
| } | |
| init(); | |
| </script> | |
| </body> | |
| </html> | |