telearms-report / index.html
mliu48's picture
Report 2026-10-28
44c6f77 verified
Raw History Blame Contribute Delete
59.4 kB
<!doctype html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><style>:root{color-scheme:light dark}body{margin:0}img{max-width:100%}[hidden]{display:none!important}</style></head><body><title>v4 Task Balance</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Condensed:wght@600;700&family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500;600&display=swap">
<style>
:root{
color-scheme: light;
--surface-1:#fcfcfb; --surface-2:#f3f4f7; --surface-3:#eceef3;
--ink:#0b0b0b; --ink-2:#52514e; --ink-3:#7b7a74;
--rule:#e2e7ef; --rule-2:#cfd6e2;
--series:#2a78d6; --series-soft:#cde2fb;
--series-b:#eb6834;
--critical:#d03b3b;
--font-d:"IBM Plex Sans Condensed","Helvetica Neue",Arial,sans-serif;
--font-b:"IBM Plex Sans","Helvetica Neue",Arial,sans-serif;
--font-m:"IBM Plex Mono",ui-monospace,"SFMono-Regular",Menlo,monospace;
}
@media (prefers-color-scheme: dark){
:root:not([data-theme="light"]){
color-scheme: dark;
--surface-1:#1a1a19; --surface-2:#222421; --surface-3:#2a2c29;
--ink:#ffffff; --ink-2:#c3c2b7; --ink-3:#8e8d84;
--rule:#2c3038; --rule-2:#3a3f48;
--series:#3987e5; --series-soft:#1d3048;
--series-b:#d95926;
--critical:#d03b3b;
}
}
:root[data-theme="dark"]{
color-scheme: dark;
--surface-1:#1a1a19; --surface-2:#222421; --surface-3:#2a2c29;
--ink:#ffffff; --ink-2:#c3c2b7; --ink-3:#8e8d84;
--rule:#2c3038; --rule-2:#3a3f48;
--series:#3987e5; --series-soft:#1d3048;
--series-b:#d95926;
--critical:#d03b3b;
}
*{box-sizing:border-box}
body{
background:var(--surface-1); color:var(--ink);
font:400 15px/1.55 var(--font-b);
-webkit-font-smoothing:antialiased;
}
.wrap{max-width:1080px; margin:0 auto; padding:0 20px; padding-block:40px 64px}
.num{font-family:var(--font-m); font-variant-numeric:tabular-nums}
/* ---- identity rail ---------------------------------------------------- */
header{display:flex; flex-wrap:wrap; gap:28px 40px; align-items:flex-end;
padding-bottom:22px; border-bottom:2px solid var(--ink)}
h1{font:700 clamp(30px,5vw,46px)/1.02 var(--font-d); letter-spacing:-.015em;
margin:0; text-wrap:balance}
h1 small{display:block; font:600 13px/1.4 var(--font-m); letter-spacing:.08em;
text-transform:uppercase; color:var(--ink-3); margin-bottom:10px}
.ident{display:grid; grid-template-columns:auto auto; gap:3px 16px;
font-family:var(--font-m); font-size:12.5px; margin-left:auto}
.ident dt{color:var(--ink-3)}
.ident dd{margin:0; color:var(--ink-2); font-variant-numeric:tabular-nums}
.ident a{color:var(--series); text-underline-offset:2px}
.lede{margin:22px 0 0; max-width:62ch; color:var(--ink-2); font-size:16px}
.lede b{color:var(--ink); font-weight:600}
/* ---- stat tiles -------------------------------------------------------- */
.tiles{display:grid; grid-template-columns:repeat(4,1fr); gap:1px;
margin:30px 0 0; background:var(--rule); border:1px solid var(--rule)}
.tile{background:var(--surface-1); padding:16px 18px 18px}
.tile dt{font:500 11px/1.3 var(--font-m); letter-spacing:.07em;
text-transform:uppercase; color:var(--ink-3)}
.tile dd{margin:8px 0 0; font:600 29px/1 var(--font-d);
font-variant-numeric:tabular-nums; letter-spacing:-.01em}
.tile .sub{display:block; margin-top:6px; font:400 12px/1.35 var(--font-m);
color:var(--ink-3)}
/* ---- chart ------------------------------------------------------------- */
section{margin-top:52px}
h2{font:600 19px/1.2 var(--font-d); margin:0 0 4px; letter-spacing:-.005em}
.note{margin:0 0 18px; font-size:13.5px; color:var(--ink-3); max-width:66ch}
.controls{display:flex; flex-wrap:wrap; gap:10px; align-items:center;
margin-bottom:16px}
.seg{display:inline-flex; border:1px solid var(--rule-2); border-radius:3px;
overflow:hidden}
.seg button{appearance:none; border:0; background:var(--surface-1);
font:500 12px/1 var(--font-m); letter-spacing:.04em; text-transform:uppercase;
color:var(--ink-2); padding:8px 13px; cursor:pointer}
.seg button+button{border-left:1px solid var(--rule-2)}
.seg button[aria-pressed="true"]{background:var(--ink); color:var(--surface-1)}
.seg button:focus-visible{outline:2px solid var(--series); outline-offset:-2px}
.legend{display:flex; gap:16px; align-items:center; margin-left:auto;
font:400 12px/1 var(--font-m); color:var(--ink-2)}
.legend span{display:inline-flex; gap:6px; align-items:center}
.key{width:11px; height:11px; border-radius:2px; display:inline-block}
.key.s{background:var(--series)} .key.c{background:var(--critical)}
.key.b{background:var(--series-b)}
.key.e{background:transparent; border:1.5px solid var(--ink-2); width:9px; height:9px; border-radius:50%}
.rows{border-top:1px solid var(--rule)}
.row{display:grid; grid-template-columns:26px minmax(132px,210px) 1fr 62px;
align-items:center; gap:12px; padding:5px 0;
border-bottom:1px solid var(--rule); position:relative}
.row:hover{background:var(--surface-2)}
.rk{font:400 11px/1 var(--font-m); color:var(--ink-3); text-align:right;
font-variant-numeric:tabular-nums}
.nm{font:400 12.5px/1.3 var(--font-m); color:var(--ink); overflow:hidden;
text-overflow:ellipsis; white-space:nowrap}
.nm .dot{display:inline-block; width:5px; height:5px; border-radius:50%;
border:1.5px solid var(--ink-2); margin-right:6px; vertical-align:middle}
.track{position:relative; height:14px}
.bar{position:absolute; left:0; top:0; height:14px; background:var(--series);
border-radius:0 4px 4px 0; min-width:2px;
transition:width .35s cubic-bezier(.3,.7,.3,1)}
.row.low .bar{background:var(--critical)}
.vl{font:500 12.5px/1 var(--font-m); font-variant-numeric:tabular-nums;
text-align:right; color:var(--ink-2)}
.row.low .vl{color:var(--critical); font-weight:600}
.thresh{position:absolute; top:0; bottom:0; width:0;
border-left:1px dashed var(--ink-3); pointer-events:none}
.threshwrap{position:relative; grid-column:3; height:0}
.threshlab{font:400 11px/1 var(--font-m); color:var(--ink-3);
margin:6px 0 0; grid-column:3}
/* ---- cumulative -------------------------------------------------------- */
figure{margin:0}
svg{display:block; width:100%; height:auto; overflow:visible}
#cum text{font-family:var(--font-m); font-size:11px; fill:var(--ink-3);
font-variant-numeric:tabular-nums}
#cum text.lab{fill:var(--ink); font-size:11.5px; font-weight:500}
#cum .grid{stroke:var(--rule); stroke-width:1}
#cum .guide{stroke:var(--rule-2); stroke-width:1.5; stroke-dasharray:3 4}
#cum .drop{stroke:var(--ink-3); stroke-width:1; stroke-dasharray:2 3}
#cum .area{fill:var(--series); fill-opacity:.13}
#cum .line{fill:none; stroke:var(--series); stroke-width:2; stroke-linejoin:round}
#cum .pt{fill:var(--series); stroke:var(--surface-1); stroke-width:2}
figcaption{font-size:13px; color:var(--ink-3); margin-top:10px; max-width:64ch}
/* ---- table ------------------------------------------------------------- */
details{margin-top:18px; border:1px solid var(--rule); border-radius:3px}
summary{cursor:pointer; padding:11px 14px; font:500 12px/1 var(--font-m);
letter-spacing:.05em; text-transform:uppercase; color:var(--ink-2)}
summary:focus-visible{outline:2px solid var(--series); outline-offset:-2px}
.tblwrap{overflow-x:auto; border-top:1px solid var(--rule)}
table{border-collapse:collapse; width:100%; font-family:var(--font-m); font-size:12.5px}
th,td{text-align:right; padding:7px 14px; border-bottom:1px solid var(--rule);
font-variant-numeric:tabular-nums; white-space:nowrap}
th{font-weight:500; color:var(--ink-3); text-transform:uppercase;
font-size:11px; letter-spacing:.05em}
th:nth-child(2),td:nth-child(2){text-align:left; white-space:normal}
tbody tr:hover{background:var(--surface-2)}
/* ---- tooltip ----------------------------------------------------------- */
#tip{position:fixed; z-index:9; pointer-events:none; opacity:0;
transition:opacity .12s; background:var(--surface-1);
border:1px solid var(--rule-2); border-radius:3px; padding:10px 12px;
font:400 12px/1.5 var(--font-m); color:var(--ink);
box-shadow:0 6px 22px rgba(0,0,0,.14); max-width:260px}
#tip[data-on="1"]{opacity:1}
#tip .t{font-weight:600; margin-bottom:5px; font-family:var(--font-b);
font-size:13px; line-height:1.3}
#tip dl{display:grid; grid-template-columns:auto auto; gap:1px 14px; margin:0}
#tip dt{color:var(--ink-3)} #tip dd{margin:0; font-variant-numeric:tabular-nums}
#tip .flag{margin-top:6px; padding-top:6px; border-top:1px solid var(--rule);
color:var(--ink-2)}
/* ---- eval ------------------------------------------------------------- */
.score{display:grid; grid-template-columns:repeat(3,1fr); gap:1px;
background:var(--rule); border:1px solid var(--rule); margin-bottom:26px}
.score>div{background:var(--surface-1); padding:15px 18px 17px}
.score dt{font:500 11px/1.3 var(--font-m); letter-spacing:.07em;
text-transform:uppercase; color:var(--ink-3)}
.score dd{margin:8px 0 0; font:600 29px/1 var(--font-d);
font-variant-numeric:tabular-nums}
.score .sub{display:block; margin-top:6px; font:400 12px/1.35 var(--font-m);
color:var(--ink-3)}
.score .up{color:var(--series)}
.erows{border-top:1px solid var(--rule)}
.erow{display:grid; grid-template-columns:minmax(132px,220px) 1fr 54px;
align-items:center; gap:12px; padding:7px 0;
border-bottom:1px solid var(--rule)}
.erow:hover{background:var(--surface-2)}
.erow .nm2{font:400 12.5px/1.3 var(--font-m); overflow:hidden;
text-overflow:ellipsis; white-space:nowrap}
.pair{display:grid; gap:2px}
.pbar{height:11px; border-radius:0 4px 4px 0; min-width:2px; position:relative}
.pbar.ft{background:var(--series)} .pbar.bl{background:var(--series-b)}
.pbar span{position:absolute; left:calc(100% + 6px); top:-1px;
font:500 10.5px/13px var(--font-m); color:var(--ink-2);
font-variant-numeric:tabular-nums; white-space:nowrap}
.erow .dl{font:500 12.5px/1 var(--font-m); text-align:right;
font-variant-numeric:tabular-nums}
.erow .dl.pos{color:var(--series)} .erow .dl.neg{color:var(--critical)}
.erow .dl.flat{color:var(--ink-3)}
.only{font:400 11px/1 var(--font-m); color:var(--ink-3)}
@media (max-width:720px){
.score{grid-template-columns:1fr}
.erow{grid-template-columns:1fr 46px; row-gap:4px}
.erow .nm2{grid-column:1/3}
.pair{grid-column:1/3}
.erow .dl{grid-column:2; grid-row:1}
}
#scat text{font-family:var(--font-m); font-size:11px; fill:var(--ink-3);
font-variant-numeric:tabular-nums}
#scat text.ax{font-size:11.5px; fill:var(--ink-2)}
#scat text.pl{font-size:10.5px; fill:var(--ink-2)}
#scat .grid{stroke:var(--rule); stroke-width:1}
#scat .band{fill:var(--critical); fill-opacity:.06}
#scat .bandline{stroke:var(--critical); stroke-width:1; stroke-dasharray:3 3}
#scat .dot{fill:var(--series); stroke:var(--surface-1); stroke-width:1.5}
#scat .dot.z{fill:var(--critical)}
#scat .fit{stroke:var(--ink-3); stroke-width:1.5; stroke-dasharray:5 4; fill:none}
.quart{display:grid; grid-template-columns:repeat(4,1fr); gap:1px;
background:var(--rule); border:1px solid var(--rule); margin:22px 0 0}
.quart>div{background:var(--surface-1); padding:13px 16px 15px}
.quart dt{font:500 11px/1.3 var(--font-m); letter-spacing:.06em;
text-transform:uppercase; color:var(--ink-3)}
.quart dd{margin:7px 0 0; font:600 25px/1 var(--font-d);
font-variant-numeric:tabular-nums}
.quart .sub{display:block; margin-top:5px; font:400 11.5px/1.35 var(--font-m);
color:var(--ink-3)}
.quart .lo dd{color:var(--critical)}
@media (max-width:720px){ .quart{grid-template-columns:repeat(2,1fr)} }
.key.o{background:var(--surface-1); border:2px solid var(--ink-3); border-radius:50%;
width:10px; height:10px}
.drows{border-top:1px solid var(--rule)}
.drow{display:grid; grid-template-columns:minmax(132px,240px) 1fr 54px;
align-items:center; gap:12px; padding:6px 0; border-bottom:1px solid var(--rule)}
.drow:hover{background:var(--surface-2)}
.drow .nm2{font:400 12.5px/1.3 var(--font-m); overflow:hidden; text-overflow:ellipsis;
white-space:nowrap}
.dtrack{position:relative; height:14px}
.dtrack .axis{position:absolute; left:0; right:0; top:6px; height:2px; background:var(--rule)}
.dtrack .span{position:absolute; top:5px; height:4px; background:var(--series); opacity:.35;
border-radius:2px}
.dtrack .d1,.dtrack .d3{position:absolute; top:1px; width:12px; height:12px;
margin-left:-6px; border-radius:50%}
.dtrack .d1{background:var(--surface-1); border:2px solid var(--ink-3)}
.dtrack .d3{background:var(--series); border:2px solid var(--surface-1)}
.drow .dl{font:500 12.5px/1 var(--font-m); text-align:right; font-variant-numeric:tabular-nums}
.drow .dl.pos{color:var(--series)} .drow .dl.neg{color:var(--critical)}
@media (max-width:720px){
.drow{grid-template-columns:1fr 46px; row-gap:4px}
.drow .nm2{grid-column:1/3} .dtrack{grid-column:1/3} .drow .dl{grid-column:2; grid-row:1}
}
footer{margin-top:48px; padding-top:16px; border-top:1px solid var(--rule);
font:400 12px/1.6 var(--font-m); color:var(--ink-3)}
@media (max-width:720px){
.tiles{grid-template-columns:repeat(2,1fr)}
.ident{margin-left:0}
.row{grid-template-columns:24px 1fr 56px; row-gap:3px}
.nm{grid-column:2/4}
.track{grid-column:1/4}
.vl{grid-column:3; grid-row:1}
.threshwrap,.threshlab{grid-column:1/4}
}
@media (prefers-reduced-motion:reduce){*{transition:none!important}}
/* ---- model pickers ----------------------------------------------------- */
.pickers{display:flex; flex-wrap:wrap; gap:14px 22px; align-items:flex-end;
padding:16px 18px; border:1px solid var(--rule); background:var(--surface-2)}
.pick{display:grid; gap:6px; min-width:0}
.pick label{font:500 11px/1.2 var(--font-m); letter-spacing:.07em; text-transform:uppercase;
color:var(--ink-3); display:flex; gap:7px; align-items:center}
.pick select{appearance:none; font:400 13px/1.2 var(--font-m); color:var(--ink);
background:var(--surface-1); border:1px solid var(--rule-2); border-radius:3px;
padding:8px 30px 8px 10px; max-width:min(440px, 86vw);
background-image:linear-gradient(45deg,transparent 50%,var(--ink-3) 50%),
linear-gradient(135deg,var(--ink-3) 50%,transparent 50%);
background-position:calc(100% - 15px) 52%, calc(100% - 10px) 52%;
background-size:5px 5px; background-repeat:no-repeat}
.pick select:focus-visible{outline:2px solid var(--series); outline-offset:1px}
.pick .meta{font:400 11.5px/1.3 var(--font-m); color:var(--ink-3)}
.empty{font-size:13.5px; color:var(--ink-3); padding:14px 0; max-width:66ch}
.key.o{background:var(--surface-1); border:2px solid var(--ink-3); border-radius:50%;
width:10px; height:10px}
</style>
<div class="wrap">
<header>
<h1><small>TeleArms Β· LeRobot v3.0</small>Model &amp; Task Report <span id="h1-date"></span></h1>
<dl class="ident" id="ident"></dl>
</header>
<div class="pickers" style="margin-top:26px">
<div class="pick"><label for="sel-a"><i class="key s"></i>Model A</label>
<select id="sel-a"></select><span class="meta" id="meta-a"></span></div>
<div class="pick"><label for="sel-b"><i class="key b"></i>Model B</label>
<select id="sel-b"></select><span class="meta" id="meta-b"></span></div>
<div class="pick"><label for="sel-cap">Step cap</label>
<select id="sel-cap"></select><span class="meta">at 30 Hz</span></div>
</div>
<dl class="tiles" id="tiles"></dl>
<section>
<h2>Policy success rate</h2>
<p class="note" id="enote"></p>
<dl class="score" id="score"></dl>
<div class="erows" id="erows"></div>
</section>
<section>
<h2>Does data volume predict success?</h2>
<p class="note" id="c-note"></p>
<figure id="c-fig">
<svg id="scat" viewBox="0 0 720 300" role="img" aria-label="Training episodes against success rate per task."></svg>
<figcaption id="c-cap"></figcaption>
</figure>
<dl class="quart" id="quart"></dl>
</section>
<section>
<h2>Episodes per task</h2>
<p class="note">The dataset now. Dashed line: the 100-episode cutoff (<code>task_lt_100</code>).</p>
<div class="controls">
<div class="seg" role="group" aria-label="Scale">
<button id="b-lin" aria-pressed="true">Linear</button>
<button id="b-log" aria-pressed="false">Log</button>
</div>
<div class="legend">
<span><i class="key s"></i>above cutoff</span>
<span><i class="key c"></i>below cutoff</span>
</div>
</div>
<div class="rows" id="rows"></div>
</section>
<section>
<h2>Cumulative share</h2>
<p class="note" id="cum-note"></p>
<figure>
<svg id="cum" viewBox="0 0 720 230" role="img" aria-label="Cumulative share of episodes by task rank."></svg>
</figure>
</section>
<section>
<h2>Table view</h2>
<details>
<summary>Every task</summary>
<div class="tblwrap">
<table>
<thead><tr><th>#</th><th>Task</th><th>Dataset now</th><th>A trained on</th>
<th id="th-a">A rate</th><th id="th-b">B rate</th></tr></thead>
<tbody id="tbody"></tbody>
</table>
</div>
</details>
</section>
<footer id="foot"></footer>
</div>
<div id="tip" role="status" aria-live="polite"></div>
<script id="data" type="application/json">{"generated": "2026-10-28T05:56-07:00", "dataset": {"tag": "v4_dr_20261014", "hf": "mliu48/telearms-yam-cube-v4-dr", "camera_resolution": [640, 360], "robot": "bimanual_yam", "fps": 30, "fingerprint": "05922f62", "episodes": 99496, "frames": 50614016, "threshold": 100, "tasks": [{"task": "Front To Back Cube Line", "n": 7515, "frames": 4998575}, {"task": "Front To Back Cube Line (relabeled)", "n": 7496, "frames": 4991416}, {"task": "Letter Face Alignment", "n": 7106, "frames": 3662600}, {"task": "Align Blocks", "n": 4829, "frames": 1472905}, {"task": "Cube Cluster Center", "n": 3374, "frames": 2770461}, {"task": "Rotate Letter Block (relabeled)", "n": 3001, "frames": 1584212}, {"task": "Rotate Letter Block", "n": 3001, "frames": 1584212}, {"task": "Cube Patch Placement", "n": 2827, "frames": 1121128}, {"task": "Cube Patch Placement (relabeled)", "n": 2825, "frames": 1120532}, {"task": "Semantic Cube On Red Patch A Up", "n": 2292, "frames": 1424308}, {"task": "Semantic Cube On Red Patch A Up (relabeled)", "n": 2288, "frames": 1420084}, {"task": "Vertical Insert Two Blocks", "n": 2253, "frames": 486896}, {"task": "Red Left Of Blue Placement", "n": 2201, "frames": 556060}, {"task": "Sequential Push Block to Target", "n": 2178, "frames": 1105754}, {"task": "Sequential Push Block to Target (relabeled)", "n": 2178, "frames": 1105754}, {"task": "Red Left Of Blue Placement (relabeled)", "n": 2173, "frames": 548534}, {"task": "Hi Cube Placement", "n": 1695, "frames": 1236660}, {"task": "Hi Cube Placement (relabeled)", "n": 1693, "frames": 1235059}, {"task": "L Cube Arrangement", "n": 1546, "frames": 1234599}, {"task": "L Cube Arrangement (relabeled)", "n": 1546, "frames": 1234599}, {"task": "Front Edge Cube Row", "n": 1508, "frames": 924564}, {"task": "Red Behind Blue Placement", "n": 1461, "frames": 411521}, {"task": "Red Behind Blue Placement (relabeled)", "n": 1435, "frames": 402870}, {"task": "Red Cube In Front Of Blue Cube", "n": 1382, "frames": 357243}, {"task": "Red Cube In Front Of Blue Cube (relabeled)", "n": 1350, "frames": 350020}, {"task": "Blue On Red Stack To Green Target", "n": 1264, "frames": 481128}, {"task": "Blue On Red Stack To Green Target (relabeled)", "n": 1260, "frames": 479231}, {"task": "Arrange Shapes", "n": 1178, "frames": 338448}, {"task": "Red On Semantic Cube Stacking (relabeled)", "n": 1115, "frames": 308222}, {"task": "Red On Semantic Cube Stacking", "n": 1115, "frames": 308222}, {"task": "Semantic Cube Blue B Placement", "n": 839, "frames": 370260}, {"task": "Semantic Cube Blue B Placement (relabeled)", "n": 838, "frames": 369561}, {"task": "Colored Cube Row Arrangement (relabeled)", "n": 830, "frames": 736200}, {"task": "Colored Cube Row Arrangement", "n": 830, "frames": 736200}, {"task": "Alternate Red Blue Row", "n": 729, "frames": 457973}, {"task": "Microsoft Logo Cubes", "n": 715, "frames": 657541}, {"task": "Microsoft Logo Cubes (relabeled)", "n": 715, "frames": 657541}, {"task": "Alternate Red Blue Row (relabeled)", "n": 714, "frames": 449563}, {"task": "Adjacent Red Cube Placement", "n": 709, "frames": 197382}, {"task": "Adjacent Red Cube Placement (relabeled)", "n": 709, "frames": 197382}, {"task": "Aligned Cube Row Placement", "n": 678, "frames": 307938}, {"task": "Aligned Cube Row Placement (relabeled)", "n": 678, "frames": 307938}, {"task": "Green Cube On Yellow Target (relabeled)", "n": 675, "frames": 104343}, {"task": "Green Cube On Yellow Target", "n": 675, "frames": 104343}, {"task": "Blue Cube On Red Target", "n": 628, "frames": 115105}, {"task": "Cube Center Placement", "n": 614, "frames": 97632}, {"task": "Blue Cube On Red Target (relabeled)", "n": 601, "frames": 108802}, {"task": "Red Cube Center Placement", "n": 520, "frames": 89354}, {"task": "Semantic Cube Green Target Red Stack", "n": 513, "frames": 314743}, {"task": "Semantic Cube Green Target Red Stack (relabeled)", "n": 513, "frames": 314743}, {"task": "Red Cube Center Placement (relabeled)", "n": 503, "frames": 85658}, {"task": "Cube Forward Right Placement", "n": 495, "frames": 87890}, {"task": "Cube Forward Right Placement (relabeled)", "n": 465, "frames": 81414}, {"task": "Push Block to Target", "n": 426, "frames": 276953}, {"task": "Three Cube Wall Row", "n": 424, "frames": 194582}, {"task": "Three Cube Wall Row (relabeled)", "n": 422, "frames": 193857}, {"task": "Cube Midpoint Placement", "n": 358, "frames": 61353}, {"task": "Cube Midpoint Placement (relabeled)", "n": 358, "frames": 61353}, {"task": "Opposite Corner Cube Placement", "n": 333, "frames": 97329}, {"task": "Three Cube Pyramid Stacking", "n": 315, "frames": 163340}, {"task": "Three Cube Pyramid Stacking (relabeled)", "n": 315, "frames": 163340}, {"task": "Opposite Corner Cube Placement (relabeled)", "n": 308, "frames": 90321}, {"task": "Cube Row Arrangement", "n": 298, "frames": 209304}, {"task": "Alternate Green Yellow Row", "n": 286, "frames": 186281}, {"task": "Alternate Green Yellow Row (relabeled)", "n": 286, "frames": 186281}, {"task": "Semantic Cube Pyramid Build", "n": 268, "frames": 253240}, {"task": "Semantic Cube Pyramid Build (relabeled)", "n": 268, "frames": 253240}, {"task": "Block Line Arrangement", "n": 232, "frames": 222958}, {"task": "Dog Cube Row Arrangement", "n": 214, "frames": 204481}, {"task": "Dog Cube Row Arrangement (relabeled)", "n": 214, "frames": 204481}, {"task": "Top Letter Cube Stacking", "n": 204, "frames": 169531}, {"task": "Spell Ok Cube Alignment (relabeled)", "n": 184, "frames": 133306}, {"task": "Spell Ok Cube Alignment", "n": 184, "frames": 133306}, {"task": "Arrange Alphabetical Order (relabeled)", "n": 173, "frames": 105231}, {"task": "Arrange Alphabetical Order", "n": 173, "frames": 105231}, {"task": "Aligned Letter Cube Row", "n": 161, "frames": 132116}, {"task": "Semantic Cubes 1x4 Line 1234", "n": 140, "frames": 155534}, {"task": "Blue Base Red Pyramid", "n": 127, "frames": 123074}, {"task": "Blue Base Red Pyramid (relabeled)", "n": 126, "frames": 121872}, {"task": "Alphabet Cube Row Arrange", "n": 110, "frames": 77582}, {"task": "Alphabet Cube Row Arrange (relabeled)", "n": 110, "frames": 77582}, {"task": "Dual Cube Side Placement", "n": 104, "frames": 25817}, {"task": "Dual Cube Side Placement (relabeled)", "n": 104, "frames": 25817}]}, "models": [{"id": "molmoact2_telearms_v4", "kind": "MolmoAct2", "lr": null, "trained_on": {"fingerprint": "1f7e903e", "source": null, "episodes": null, "counts": null}, "runs": {"5400": {"Adjacent Red Cube Placement": {"rate": 0.4, "n": 10}, "Align Blocks": {"rate": 0.8, "n": 10}, "Aligned Cube Row Placement": {"rate": 0.5, "n": 10}, "Aligned Letter Cube Row": {"rate": 0.0, "n": 10}, "Alphabet Cube Row Arrange": {"rate": 0.1, "n": 10}, "Alternate Green Yellow Row": {"rate": 0.4, "n": 10}, "Alternate Red Blue Row": {"rate": 0.4, "n": 10}, "Arrange Alphabetical Order": {"rate": 0.0, "n": 10}, "Arrange Shapes": {"rate": 0.7, "n": 10}, "Block Line Arrangement": {"rate": 0.1, "n": 10}, "Blue Base Red Pyramid": {"rate": 0.0, "n": 10}, "Blue Cube On Red Target": {"rate": 0.3, "n": 10}, "Blue On Red Stack To Green Target": {"rate": 0.8, "n": 10}, "Colored Cube Row Arrangement": {"rate": 0.2, "n": 10}, "Cube Center Placement": {"rate": 0.8889, "n": 9}, "Cube Cluster Center": {"rate": 0.5, "n": 10}, "Cube Forward Right Placement": {"rate": 0.3, "n": 10}, "Cube Midpoint Placement": {"rate": 1.0, "n": 10}, "Cube Patch Placement": {"rate": 0.9, "n": 10}, "Cube Row Arrangement": {"rate": 0.2, "n": 10}, "Dog Cube Row Arrangement": {"rate": 0.0, "n": 10}, "Dual Cube Side Placement": {"rate": 0.0, "n": 10}, "Front Edge Cube Row": {"rate": 0.4, "n": 10}, "Front To Back Cube Line": {"rate": 0.4, "n": 10}, "Green Cube On Yellow Target": {"rate": 1.0, "n": 9}, "Hi Cube Placement": {"rate": 0.4, "n": 10}, "L Cube Arrangement": {"rate": 0.7, "n": 10}, "Letter Face Alignment": {"rate": 0.2, "n": 10}, "Microsoft Logo Cubes": {"rate": 0.2, "n": 10}, "Opposite Corner Cube Placement": {"rate": 0.0, "n": 10}, "Push Block to Target": {"rate": 0.9, "n": 10}, "Red Behind Blue Placement": {"rate": 0.9, "n": 10}, "Red Cube Center Placement": {"rate": 0.8, "n": 10}, "Red Cube In Front Of Blue Cube": {"rate": 1.0, "n": 10}, "Red Left Of Blue Placement": {"rate": 1.0, "n": 10}, "Red On Semantic Cube Stacking": {"rate": 0.5, "n": 10}, "Rotate Letter Block": {"rate": 0.5, "n": 10}, "Semantic Cube Blue B Placement": {"rate": 0.5, "n": 10}, "Semantic Cube Green Target Red Stack": {"rate": 0.2, "n": 10}, "Semantic Cube On Red Patch A Up": {"rate": 0.2, "n": 10}, "Semantic Cube Pyramid Build": {"rate": 0.0, "n": 10}, "Semantic Cubes 1x4 Line 1234": {"rate": 0.0, "n": 10}, "Sequential Push Block to Target": {"rate": 1.0, "n": 10}, "Spell Ok Cube Alignment": {"rate": 0.0, "n": 10}, "Three Cube Pyramid Stacking": {"rate": 0.6, "n": 10}, "Three Cube Wall Row": {"rate": 0.6, "n": 10}, "Top Letter Cube Stacking": {"rate": 0.0, "n": 10}, "Vertical Insert Two Blocks": {"rate": 0.9, "n": 10}}}}, {"id": "pi05_all_a40x7_v4_simtime_20260914_vision_v4_100k", "kind": "pi05 expert only", "lr": 2.5e-05, "trained_on": {"fingerprint": "dc4c58a8", "source": null, "episodes": null, "counts": null}, "runs": {"5400": {"Align Blocks": {"rate": 0.8, "n": 10}, "Cube Cluster Center": {"rate": 1.0, "n": 10}, "Cube Patch Placement": {"rate": 1.0, "n": 10}, "Front To Back Cube Line": {"rate": 0.7, "n": 10}, "Hi Cube Placement": {"rate": 0.0, "n": 10}, "Letter Face Alignment": {"rate": 0.8, "n": 10}, "Rotate Letter Block": {"rate": 0.9, "n": 10}, "Semantic Cube On Red Patch A Up": {"rate": 0.3, "n": 10}, "Sequential Push Block to Target": {"rate": 1.0, "n": 10}, "Vertical Insert Two Blocks": {"rate": 0.3, "n": 10}}, "1800": {"Align Blocks": {"rate": 0.6, "n": 10}, "Cube Cluster Center": {"rate": 1.0, "n": 10}, "Cube Patch Placement": {"rate": 1.0, "n": 10}, "Front To Back Cube Line": {"rate": 0.2, "n": 10}, "Hi Cube Placement": {"rate": 0.0, "n": 10}, "Letter Face Alignment": {"rate": 0.5, "n": 10}, "Rotate Letter Block": {"rate": 0.8, "n": 10}, "Semantic Cube On Red Patch A Up": {"rate": 0.2, "n": 10}, "Sequential Push Block to Target": {"rate": 0.9, "n": 10}, "Vertical Insert Two Blocks": {"rate": 0.2, "n": 10}}}}, {"id": "pi05_telearms_v4_fullft_lr7.07e-5", "kind": "pi05 full fine-tune", "lr": 7.07e-05, "trained_on": {"fingerprint": "1f7e903e", "source": null, "episodes": null, "counts": null}, "runs": {"5400": {"Adjacent Red Cube Placement": {"rate": 1.0, "n": 10}, "Align Blocks": {"rate": 1.0, "n": 10}, "Aligned Cube Row Placement": {"rate": 0.9, "n": 10}, "Aligned Letter Cube Row": {"rate": 0.0, "n": 10}, "Alphabet Cube Row Arrange": {"rate": 0.0, "n": 10}, "Alternate Green Yellow Row": {"rate": 0.8, "n": 10}, "Alternate Red Blue Row": {"rate": 0.8, "n": 10}, "Arrange Alphabetical Order": {"rate": 0.1, "n": 10}, "Arrange Shapes": {"rate": 1.0, "n": 10}, "Block Line Arrangement": {"rate": 0.7, "n": 10}, "Blue Base Red Pyramid": {"rate": 0.4, "n": 10}, "Blue Cube On Red Target": {"rate": 1.0, "n": 10}, "Blue On Red Stack To Green Target": {"rate": 1.0, "n": 10}, "Colored Cube Row Arrangement": {"rate": 0.9, "n": 10}, "Cube Center Placement": {"rate": 1.0, "n": 9}, "Cube Cluster Center": {"rate": 0.9, "n": 10}, "Cube Forward Right Placement": {"rate": 0.2, "n": 10}, "Cube Midpoint Placement": {"rate": 1.0, "n": 10}, "Cube Patch Placement": {"rate": 1.0, "n": 10}, "Cube Row Arrangement": {"rate": 0.8, "n": 10}, "Dog Cube Row Arrangement": {"rate": 0.1, "n": 10}, "Dual Cube Side Placement": {"rate": 0.0, "n": 10}, "Front Edge Cube Row": {"rate": 0.7, "n": 10}, "Front To Back Cube Line": {"rate": 1.0, "n": 10}, "Green Cube On Yellow Target": {"rate": 1.0, "n": 9}, "Hi Cube Placement": {"rate": 0.4, "n": 10}, "L Cube Arrangement": {"rate": 0.9, "n": 10}, "Letter Face Alignment": {"rate": 0.9, "n": 10}, "Microsoft Logo Cubes": {"rate": 1.0, "n": 10}, "Opposite Corner Cube Placement": {"rate": 0.0, "n": 10}, "Push Block to Target": {"rate": 1.0, "n": 10}, "Red Behind Blue Placement": {"rate": 1.0, "n": 10}, "Red Cube Center Placement": {"rate": 1.0, "n": 10}, "Red Cube In Front Of Blue Cube": {"rate": 1.0, "n": 10}, "Red Left Of Blue Placement": {"rate": 1.0, "n": 10}, "Red On Semantic Cube Stacking": {"rate": 1.0, "n": 10}, "Rotate Letter Block": {"rate": 0.9, "n": 10}, "Semantic Cube Blue B Placement": {"rate": 0.9, "n": 10}, "Semantic Cube Green Target Red Stack": {"rate": 0.9, "n": 10}, "Semantic Cube On Red Patch A Up": {"rate": 0.8, "n": 10}, "Semantic Cube Pyramid Build": {"rate": 0.1, "n": 10}, "Semantic Cubes 1x4 Line 1234": {"rate": 0.1, "n": 10}, "Sequential Push Block to Target": {"rate": 1.0, "n": 10}, "Spell Ok Cube Alignment": {"rate": 0.2, "n": 10}, "Three Cube Pyramid Stacking": {"rate": 0.7, "n": 10}, "Three Cube Wall Row": {"rate": 1.0, "n": 10}, "Top Letter Cube Stacking": {"rate": 0.1, "n": 10}, "Vertical Insert Two Blocks": {"rate": 1.0, "n": 10}}, "1800": {"Adjacent Red Cube Placement": {"rate": 1.0, "n": 10}, "Align Blocks": {"rate": 1.0, "n": 10}, "Aligned Cube Row Placement": {"rate": 0.6, "n": 10}, "Aligned Letter Cube Row": {"rate": 0.0, "n": 10}, "Alphabet Cube Row Arrange": {"rate": 0.0, "n": 10}, "Alternate Green Yellow Row": {"rate": 0.5, "n": 10}, "Alternate Red Blue Row": {"rate": 0.5, "n": 10}, "Arrange Alphabetical Order": {"rate": 0.1, "n": 10}, "Arrange Shapes": {"rate": 0.9, "n": 10}, "Block Line Arrangement": {"rate": 0.3, "n": 10}, "Blue Base Red Pyramid": {"rate": 0.3, "n": 10}, "Blue Cube On Red Target": {"rate": 0.9, "n": 10}, "Blue On Red Stack To Green Target": {"rate": 1.0, "n": 10}, "Colored Cube Row Arrangement": {"rate": 0.7, "n": 10}, "Cube Center Placement": {"rate": 1.0, "n": 9}, "Cube Cluster Center": {"rate": 0.9, "n": 10}, "Cube Forward Right Placement": {"rate": 0.1, "n": 10}, "Cube Midpoint Placement": {"rate": 1.0, "n": 10}, "Cube Patch Placement": {"rate": 1.0, "n": 10}, "Cube Row Arrangement": {"rate": 0.6, "n": 10}, "Dog Cube Row Arrangement": {"rate": 0.0, "n": 10}, "Dual Cube Side Placement": {"rate": 0.0, "n": 10}, "Front Edge Cube Row": {"rate": 0.5, "n": 10}, "Front To Back Cube Line": {"rate": 0.9, "n": 10}, "Green Cube On Yellow Target": {"rate": 1.0, "n": 9}, "Hi Cube Placement": {"rate": 0.3, "n": 10}, "L Cube Arrangement": {"rate": 0.7, "n": 10}, "Letter Face Alignment": {"rate": 0.9, "n": 10}, "Microsoft Logo Cubes": {"rate": 0.8, "n": 10}, "Opposite Corner Cube Placement": {"rate": 0.0, "n": 10}, "Push Block to Target": {"rate": 1.0, "n": 10}, "Red Behind Blue Placement": {"rate": 1.0, "n": 10}, "Red Cube Center Placement": {"rate": 1.0, "n": 10}, "Red Cube In Front Of Blue Cube": {"rate": 1.0, "n": 10}, "Red Left Of Blue Placement": {"rate": 1.0, "n": 10}, "Red On Semantic Cube Stacking": {"rate": 0.9, "n": 10}, "Rotate Letter Block": {"rate": 0.6, "n": 10}, "Semantic Cube Blue B Placement": {"rate": 0.6, "n": 10}, "Semantic Cube Green Target Red Stack": {"rate": 0.6, "n": 10}, "Semantic Cube On Red Patch A Up": {"rate": 0.7, "n": 10}, "Semantic Cube Pyramid Build": {"rate": 0.1, "n": 10}, "Semantic Cubes 1x4 Line 1234": {"rate": 0.0, "n": 10}, "Sequential Push Block to Target": {"rate": 1.0, "n": 10}, "Spell Ok Cube Alignment": {"rate": 0.0, "n": 10}, "Three Cube Pyramid Stacking": {"rate": 0.9, "n": 10}, "Three Cube Wall Row": {"rate": 0.8, "n": 10}, "Top Letter Cube Stacking": {"rate": 0.1, "n": 10}, "Vertical Insert Two Blocks": {"rate": 1.0, "n": 10}}}}, {"id": "pi05_telearms_v4dr", "kind": "pi05 full fine-tune", "lr": 0.0001414, "trained_on": {"fingerprint": "05922f62", "source": "live", "episodes": 99496, "counts": {"Front To Back Cube Line": 7515, "Front To Back Cube Line (relabeled)": 7496, "Letter Face Alignment": 7106, "Align Blocks": 4829, "Cube Cluster Center": 3374, "Rotate Letter Block (relabeled)": 3001, "Rotate Letter Block": 3001, "Cube Patch Placement": 2827, "Cube Patch Placement (relabeled)": 2825, "Semantic Cube On Red Patch A Up": 2292, "Semantic Cube On Red Patch A Up (relabeled)": 2288, "Vertical Insert Two Blocks": 2253, "Red Left Of Blue Placement": 2201, "Sequential Push Block to Target": 2178, "Sequential Push Block to Target (relabeled)": 2178, "Red Left Of Blue Placement (relabeled)": 2173, "Hi Cube Placement": 1695, "Hi Cube Placement (relabeled)": 1693, "L Cube Arrangement": 1546, "L Cube Arrangement (relabeled)": 1546, "Front Edge Cube Row": 1508, "Red Behind Blue Placement": 1461, "Red Behind Blue Placement (relabeled)": 1435, "Red Cube In Front Of Blue Cube": 1382, "Red Cube In Front Of Blue Cube (relabeled)": 1350, "Blue On Red Stack To Green Target": 1264, "Blue On Red Stack To Green Target (relabeled)": 1260, "Arrange Shapes": 1178, "Red On Semantic Cube Stacking (relabeled)": 1115, "Red On Semantic Cube Stacking": 1115, "Semantic Cube Blue B Placement": 839, "Semantic Cube Blue B Placement (relabeled)": 838, "Colored Cube Row Arrangement (relabeled)": 830, "Colored Cube Row Arrangement": 830, "Alternate Red Blue Row": 729, "Microsoft Logo Cubes": 715, "Microsoft Logo Cubes (relabeled)": 715, "Alternate Red Blue Row (relabeled)": 714, "Adjacent Red Cube Placement": 709, "Adjacent Red Cube Placement (relabeled)": 709, "Aligned Cube Row Placement": 678, "Aligned Cube Row Placement (relabeled)": 678, "Green Cube On Yellow Target (relabeled)": 675, "Green Cube On Yellow Target": 675, "Blue Cube On Red Target": 628, "Cube Center Placement": 614, "Blue Cube On Red Target (relabeled)": 601, "Red Cube Center Placement": 520, "Semantic Cube Green Target Red Stack": 513, "Semantic Cube Green Target Red Stack (relabeled)": 513, "Red Cube Center Placement (relabeled)": 503, "Cube Forward Right Placement": 495, "Cube Forward Right Placement (relabeled)": 465, "Push Block to Target": 426, "Three Cube Wall Row": 424, "Three Cube Wall Row (relabeled)": 422, "Cube Midpoint Placement": 358, "Cube Midpoint Placement (relabeled)": 358, "Opposite Corner Cube Placement": 333, "Three Cube Pyramid Stacking": 315, "Three Cube Pyramid Stacking (relabeled)": 315, "Opposite Corner Cube Placement (relabeled)": 308, "Cube Row Arrangement": 298, "Alternate Green Yellow Row": 286, "Alternate Green Yellow Row (relabeled)": 286, "Semantic Cube Pyramid Build": 268, "Semantic Cube Pyramid Build (relabeled)": 268, "Block Line Arrangement": 232, "Dog Cube Row Arrangement": 214, "Dog Cube Row Arrangement (relabeled)": 214, "Top Letter Cube Stacking": 204, "Spell Ok Cube Alignment (relabeled)": 184, "Spell Ok Cube Alignment": 184, "Arrange Alphabetical Order (relabeled)": 173, "Arrange Alphabetical Order": 173, "Aligned Letter Cube Row": 161, "Semantic Cubes 1x4 Line 1234": 140, "Blue Base Red Pyramid": 127, "Blue Base Red Pyramid (relabeled)": 126, "Alphabet Cube Row Arrange": 110, "Alphabet Cube Row Arrange (relabeled)": 110, "Dual Cube Side Placement": 104, "Dual Cube Side Placement (relabeled)": 104}}, "runs": {"5400": {"Adjacent Red Cube Placement": {"rate": 0.8, "n": 10}, "Align Blocks": {"rate": 1.0, "n": 10}, "Aligned Cube Row Placement": {"rate": 1.0, "n": 10}, "Aligned Letter Cube Row": {"rate": 0.0, "n": 10}, "Alphabet Cube Row Arrange": {"rate": 0.0, "n": 10}, "Alternate Green Yellow Row": {"rate": 0.7, "n": 10}, "Alternate Red Blue Row": {"rate": 0.6, "n": 10}, "Arrange Alphabetical Order": {"rate": 0.1, "n": 10}, "Arrange Shapes": {"rate": 1.0, "n": 10}, "Block Line Arrangement": {"rate": 0.7, "n": 10}, "Blue Base Red Pyramid": {"rate": 0.4, "n": 10}, "Blue Cube On Red Target": {"rate": 1.0, "n": 10}, "Blue On Red Stack To Green Target": {"rate": 1.0, "n": 10}, "Colored Cube Row Arrangement": {"rate": 0.7, "n": 10}, "Cube Center Placement": {"rate": 1.0, "n": 9}, "Cube Cluster Center": {"rate": 1.0, "n": 10}, "Cube Forward Right Placement": {"rate": 0.2, "n": 10}, "Cube Midpoint Placement": {"rate": 1.0, "n": 10}, "Cube Patch Placement": {"rate": 1.0, "n": 10}, "Cube Row Arrangement": {"rate": 0.7, "n": 10}, "Dog Cube Row Arrangement": {"rate": 0.0, "n": 10}, "Dual Cube Side Placement": {"rate": 0.7, "n": 10}, "Front Edge Cube Row": {"rate": 0.8, "n": 10}, "Front To Back Cube Line": {"rate": 1.0, "n": 10}, "Green Cube On Yellow Target": {"rate": 1.0, "n": 9}, "Hi Cube Placement": {"rate": 0.5, "n": 10}, "L Cube Arrangement": {"rate": 1.0, "n": 10}, "Letter Face Alignment": {"rate": 1.0, "n": 10}, "Microsoft Logo Cubes": {"rate": 0.8, "n": 10}, "Opposite Corner Cube Placement": {"rate": 0.0, "n": 10}, "Push Block to Target": {"rate": 1.0, "n": 10}, "Red Behind Blue Placement": {"rate": 1.0, "n": 10}, "Red Cube Center Placement": {"rate": 1.0, "n": 10}, "Red Cube In Front Of Blue Cube": {"rate": 1.0, "n": 10}, "Red Left Of Blue Placement": {"rate": 1.0, "n": 10}, "Red On Semantic Cube Stacking": {"rate": 1.0, "n": 10}, "Rotate Letter Block": {"rate": 1.0, "n": 10}, "Semantic Cube Blue B Placement": {"rate": 0.5, "n": 10}, "Semantic Cube Green Target Red Stack": {"rate": 0.2, "n": 10}, "Semantic Cube On Red Patch A Up": {"rate": 0.8, "n": 10}, "Semantic Cube Pyramid Build": {"rate": 0.1, "n": 10}, "Semantic Cubes 1x4 Line 1234": {"rate": 0.0, "n": 10}, "Sequential Push Block to Target": {"rate": 1.0, "n": 10}, "Spell Ok Cube Alignment": {"rate": 0.4, "n": 10}, "Three Cube Pyramid Stacking": {"rate": 0.7, "n": 10}, "Three Cube Wall Row": {"rate": 1.0, "n": 10}, "Top Letter Cube Stacking": {"rate": 0.0, "n": 10}, "Vertical Insert Two Blocks": {"rate": 1.0, "n": 10}}}}], "default_a": "molmoact2_telearms_v4", "default_b": "pi05_telearms_v4_fullft_lr7.07e-5"}</script>
<script>
(function () {
const D = JSON.parse(document.getElementById('data').textContent);
const L = D.dataset, T = L.tasks, MODELS = D.models;
const byId = Object.fromEntries(MODELS.map(m => [m.id, m]));
const fmt = n => Number(n).toLocaleString('en-US');
const pct = v => (v * 100).toFixed(0) + '%';
const $ = id => document.getElementById(id);
const ns = 'http://www.w3.org/2000/svg';
const tip = $('tip');
const totalLive = T.reduce((s, r) => s + r.n, 0);
const maxLive = Math.max(...T.map(r => r.n));
const minLive = Math.min(...T.map(r => r.n));
function svgAdd(svg, tag, attrs, text) {
const e = document.createElementNS(ns, tag);
for (const k in attrs) e.setAttribute(k, attrs[k]);
if (text != null) e.textContent = text;
svg.appendChild(e);
return e;
}
function showTip(ev, html) {
tip.innerHTML = html;
tip.setAttribute('data-on', '1');
let x = (ev.clientX || 0) + 14, y = (ev.clientY || 0) + 14;
const b = tip.getBoundingClientRect();
if (x + b.width > innerWidth - 8) x = (ev.clientX || 0) - b.width - 14;
if (y + b.height > innerHeight - 8) y = innerHeight - b.height - 8;
tip.style.left = Math.max(8, x) + 'px';
tip.style.top = Math.max(8, y) + 'px';
}
const hideTip = () => tip.setAttribute('data-on', '0');
const esc = s => String(s).replace(/[&<>"]/g, c => ({'&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;'}[c]));
// ---- selection state ------------------------------------------------------
const store = {
get(k) { try { return localStorage.getItem('tb.' + k); } catch (e) { return null; } },
set(k, v) { try { localStorage.setItem('tb.' + k, v); } catch (e) { /* storage off */ } },
};
const S = {
a: byId[store.get('a')] ? store.get('a') : D.default_a,
b: store.get('b') === '' || byId[store.get('b')] ? store.get('b') : D.default_b,
cap: store.get('cap'),
};
const runOf = (id, cap) => (id && byId[id] && byId[id].runs[cap]) || null;
const capsOf = id => (id && byId[id] ? Object.keys(byId[id].runs) : []);
const capLabel = c => c === 'unknown' ? 'unknown cap'
: fmt(c) + ' steps Β· ' + (Number(c) / 30 / 60).toFixed(Number(c) % 1800 ? 1 : 0) + ' min';
function agg(run, tasks) {
let hits = 0, total = 0, k = 0;
for (const t of tasks || Object.keys(run || {})) {
const r = run && run[t];
if (!r) continue;
hits += Math.round(r.rate * r.n); total += r.n; k++;
}
return {hits, total, tasks: k, rate: total ? hits / total : null};
}
// ---- static: live dataset ---------------------------------------------------
const share5 = T.slice(0, 5).reduce((s, r) => s + r.n, 0) / totalLive;
const half = Math.floor(T.length / 2);
const shareBottom = T.slice(T.length - half).reduce((s, r) => s + r.n, 0) / totalLive;
const median = (() => { const v = T.map(r => r.n).sort((a, b) => a - b), m = v.length >> 1;
return v.length % 2 ? v[m] : (v[m - 1] + v[m]) / 2; })();
// Heading carries the generation date as MMDD (e.g. 1007).
$('h1-date').textContent = D.generated.slice(5, 7) + D.generated.slice(8, 10);
const cams = L.camera_resolution ? `224 px (${L.camera_resolution.join('Γ—')} letterboxed)` : '224 px';
$('ident').innerHTML = [['tag', L.tag], ['robot', L.robot], ['rate', `${L.fps} Hz Β· ${cams} Β· 3 cams`],
['dataset now', L.fingerprint + ' Β· ' + fmt(L.episodes) + ' episodes']]
.map(([k, v]) => `<dt>${k}</dt><dd>${esc(v)}</dd>`).join('') +
(L.hf ? `<dt>data</dt><dd><a href="https://huggingface.co/datasets/${esc(L.hf)}">${esc(L.hf)}</a></dd>` : '');
$('cum-note').textContent = `Top 5 tasks hold ${(share5 * 100).toFixed(1)}% of episodes; ` +
`the smaller half of the tasks holds ${(shareBottom * 100).toFixed(1)}%.`;
$('foot').innerHTML = `Generated ${esc(D.generated)} by <span class="num">tools/build_report.py</span>.`;
// Episodes-per-task rows
let scale = 'lin';
const width = n => scale === 'log'
? Math.max(0.4, (Math.log(Math.max(n, 50)) - Math.log(50)) / (Math.log(maxLive) - Math.log(50)) * 100)
: n / maxLive * 100;
const cum = []; T.reduce((s, r) => (cum.push(s + r.n), s + r.n), 0);
const rowsEl = $('rows');
rowsEl.style.position = 'relative';
T.forEach((r, i) => {
const low = r.n < L.threshold;
const el = document.createElement('div');
el.className = 'row' + (low ? ' low' : '');
el.tabIndex = 0;
el.innerHTML = `<div class="rk">${i + 1}</div><div class="nm" title="${esc(r.task)}">${esc(r.task)}</div>` +
`<div class="track"><div class="bar"></div></div><div class="vl">${fmt(r.n)}</div>`;
el.querySelector('.bar').style.width = width(r.n) + '%';
const show = ev => {
const a = runOf(S.a, S.cap), ar = a && a[r.task];
showTip(ev, `<div class="t">${esc(r.task)}</div><dl>` +
`<dt>episodes</dt><dd>${fmt(r.n)}</dd><dt>share</dt><dd>${(r.n / totalLive * 100).toFixed(1)}%</dd>` +
`<dt>cumulative</dt><dd>${(cum[i] / totalLive * 100).toFixed(1)}%</dd><dt>frames</dt><dd>${fmt(r.frames)}</dd>` +
`<dt>rank</dt><dd>${i + 1} of ${T.length}</dd></dl>` +
(ar ? `<div class="flag">Model A: ${pct(ar.rate)} success</div>` : '') +
(low ? `<div class="flag">Below the ${L.threshold}-episode cutoff</div>` : ''));
};
el.addEventListener('mouseenter', show); el.addEventListener('mousemove', show);
el.addEventListener('focus', () => { const b = el.getBoundingClientRect(); show({clientX: b.left + 40, clientY: b.top}); });
el.addEventListener('mouseleave', hideTip); el.addEventListener('blur', hideTip);
rowsEl.appendChild(el);
});
const rule = document.createElement('div'); rule.className = 'thresh'; rowsEl.appendChild(rule);
const ruleLab = document.createElement('div');
ruleLab.style.cssText = 'position:absolute;font:400 10.5px/1 var(--font-m);color:var(--ink-3);white-space:nowrap;pointer-events:none';
ruleLab.textContent = 'task_lt_100'; rowsEl.appendChild(ruleLab);
function placeRule() {
const first = rowsEl.querySelector('.track'); if (!first) return;
const tr = first.getBoundingClientRect(), rr = rowsEl.getBoundingClientRect();
const left = (tr.left - rr.left) + tr.width * width(L.threshold) / 100;
rule.style.left = left + 'px'; rule.style.top = (tr.top - rr.top) + 'px';
rule.style.height = (rr.height - (tr.top - rr.top) - 26) + 'px';
ruleLab.style.left = (left + 5) + 'px'; ruleLab.style.top = (rr.height - 22) + 'px';
}
function setScale(s) {
scale = s;
$('b-lin').setAttribute('aria-pressed', s === 'lin'); $('b-log').setAttribute('aria-pressed', s === 'log');
rowsEl.querySelectorAll('.row').forEach((el, i) => { el.querySelector('.bar').style.width = width(T[i].n) + '%'; });
placeRule();
}
$('b-lin').onclick = () => setScale('lin'); $('b-log').onclick = () => setScale('log');
placeRule(); addEventListener('resize', placeRule);
// Cumulative curve
(function () {
const svg = $('cum'), W = 720, H = 230, m = {t: 14, r: 46, b: 34, l: 46};
const iw = W - m.l - m.r, ih = H - m.t - m.b, n = T.length;
const X = i => m.l + i / n * iw, Y = p => m.t + (1 - p) * ih;
[0, .25, .5, .75, 1].forEach(p => {
svgAdd(svg, 'line', {x1: m.l, x2: m.l + iw, y1: Y(p), y2: Y(p), 'class': 'grid'});
svgAdd(svg, 'text', {x: m.l - 9, y: Y(p) + 4, 'text-anchor': 'end'}, Math.round(p * 100) + '%');
});
svgAdd(svg, 'line', {x1: m.l, y1: Y(0), x2: m.l + iw, y2: Y(1), 'class': 'guide'});
svgAdd(svg, 'text', {x: m.l + iw - 4, y: Y(1) - 8, 'text-anchor': 'end'}, 'perfectly balanced');
let area = `M${X(0)},${Y(0)}`, line = '';
cum.forEach((v, i) => { area += ` L${X(i + 1)},${Y(v / totalLive)}`; line += `${i ? ' L' : 'M'}${X(i + 1)},${Y(v / totalLive)}`; });
svgAdd(svg, 'path', {d: area + ` L${X(n)},${Y(0)} Z`, 'class': 'area'});
svgAdd(svg, 'path', {d: line, 'class': 'line'});
[5, 10].filter(k => k <= n).forEach(k => {
const x = X(k), y = Y(cum[k - 1] / totalLive);
svgAdd(svg, 'line', {x1: x, y1: y, x2: x, y2: Y(0), 'class': 'drop'});
svgAdd(svg, 'circle', {cx: x, cy: y, r: 4, 'class': 'pt'});
svgAdd(svg, 'text', {x: x + 8, y: y - 7, 'class': 'lab'}, `top ${k} β†’ ${(cum[k - 1] / totalLive * 100).toFixed(0)}%`);
});
[1, Math.round(n / 4), Math.round(n / 2), Math.round(3 * n / 4), n].forEach(i =>
svgAdd(svg, 'text', {x: X(i), y: H - m.b + 19, 'text-anchor': 'middle'}, i));
svgAdd(svg, 'text', {x: m.l + iw / 2, y: H - 2, 'text-anchor': 'middle'}, 'task rank');
})();
// ---- pickers ------------------------------------------------------------------
const modelMeta = m => !m ? '' : [m.kind, m.lr ? 'lr ' + m.lr : null,
m.trained_on ? 'trained on ' + m.trained_on.fingerprint + (m.trained_on.source ? ` (${m.trained_on.source})` : ' (snapshot not kept)') : null,
Object.keys(m.runs).length ? Object.keys(m.runs).length + ' eval run' + (Object.keys(m.runs).length > 1 ? 's' : '') : 'not evaluated']
.filter(Boolean).join(' Β· ');
function fillModels() {
const opts = MODELS.map(m => `<option value="${esc(m.id)}">${esc(m.id)}</option>`).join('');
$('sel-a').innerHTML = opts;
$('sel-b').innerHTML = '<option value="">β€” none β€”</option>' + opts;
$('sel-a').value = S.a || ''; $('sel-b').value = S.b || '';
}
function fillCaps() {
const caps = [...new Set([...capsOf(S.a), ...capsOf(S.b)])].sort((x, y) => Number(x) - Number(y));
if (!caps.includes(S.cap)) S.cap = caps.includes('5400') ? '5400' : caps[caps.length - 1] || null;
$('sel-cap').innerHTML = caps.map(c => `<option value="${c}">${capLabel(c)}</option>`).join('');
$('sel-cap').value = S.cap || '';
$('sel-cap').disabled = !caps.length;
}
$('sel-a').onchange = e => { S.a = e.target.value; store.set('a', S.a); renderAll(); };
$('sel-b').onchange = e => { S.b = e.target.value; store.set('b', S.b); renderAll(); };
$('sel-cap').onchange = e => { S.cap = e.target.value; store.set('cap', S.cap); renderAll(); };
// ---- tiles: what model A trained on vs the dataset now ---------------------------
function renderTiles() {
const A = byId[S.a], tr = A && A.trained_on;
const tile = (k, v, s) => `<div class="tile"><dt>${k}</dt><dd class="num">${v}</dd><span class="sub">${s}</span></div>`;
const known = tr && tr.counts;
$('tiles').innerHTML =
tile('Model A trained on', known ? fmt(tr.episodes) : 'β€”',
known ? `${Object.keys(tr.counts).length} tasks Β· snapshot ${tr.fingerprint}`
: A ? 'training set not on disk' : 'no model') +
tile('Dataset now', fmt(L.episodes), `${T.length} tasks Β· ${fmt(L.frames)} frames`) +
tile('Median / task', fmt(Math.round(median)), 'dataset now') +
tile('Spread', (maxLive / minLive).toFixed(1) + '&times;', `${fmt(maxLive)} down to ${fmt(minLive)}`);
}
// ---- success rate ---------------------------------------------------------------
function renderScore() {
const A = byId[S.a], B = byId[S.b], ra = runOf(S.a, S.cap), rb = runOf(S.b, S.cap);
const ga = agg(ra), gb = agg(rb);
const shared = ra && rb ? Object.keys(ra).filter(t => rb[t]) : [];
const sa = agg(ra, shared), sb = agg(rb, shared);
const tile = (k, v, s, cls) => `<div><dt>${k}</dt><dd class="num ${cls || ''}">${v}</dd><span class="sub">${s}</span></div>`;
$('score').innerHTML =
tile('Model A', ga.rate == null ? 'β€”' : pct(ga.rate), ra ? `${ga.hits}/${ga.total} over ${ga.tasks} tasks` : 'no run at this cap', 'up') +
tile('Model B', !B ? 'β€”' : gb.rate == null ? 'β€”' : pct(gb.rate), !B ? 'none selected' : rb ? `${gb.hits}/${gb.total} over ${gb.tasks} tasks` : 'no run at this cap') +
tile('Head to head', shared.length ? `${pct(sb.rate)} β†’ ${pct(sa.rate)}` : 'β€”',
shared.length ? `B β†’ A on the ${shared.length} tasks both were scored on` : 'needs two models scored on the same tasks');
// Episodes per task vary by run (suite default 2, older runs 10), and one episode is
// 100/n pp of a task's rate.
const per = r => r ? Math.max(...Object.values(r).map(x => x.n)) : 0;
const na = per(ra), nb = per(rb), n = Math.min(...[na, nb].filter(Boolean));
$('enote').innerHTML = !isFinite(n) ? ''
: (na && nb && na !== nb ? `Model A ran ${na} episodes per task, model B ${nb}` : `${n} episodes per task`)
+ `, so &plusmn;${Math.round(100 / n)}&nbsp;pp on a task is within noise.`;
const er = $('erows'); er.innerHTML = '';
const tasks = [...new Set([...Object.keys(ra || {}), ...Object.keys(rb || {})])]
.sort((x, y) => ((ra && ra[y] ? ra[y].rate : -1) - (ra && ra[x] ? ra[x].rate : -1)) || x.localeCompare(y));
if (!tasks.length) { er.innerHTML = '<p class="empty">Neither selected model has results at this step cap.</p>'; return; }
tasks.forEach(t => {
const a = ra && ra[t], b = rb && rb[t];
const bar = (r, cls) => r ? `<div class="pbar ${cls}" style="width:${Math.max(1.5, r.rate * 100)}%"><span>${pct(r.rate)}</span></div>` : '';
let d = '<span class="only">β€”</span>', cls = 'flat';
if (a && b) { const g = Math.round((a.rate - b.rate) * 100); cls = g > 0 ? 'pos' : g < 0 ? 'neg' : 'flat'; d = (g > 0 ? '+' : '') + g; }
const el = document.createElement('div'); el.className = 'erow';
el.innerHTML = `<div class="nm2" title="${esc(t)}">${esc(t)}</div><div class="pair">${bar(a, 'ft')}${bar(b, 'bl')}</div><div class="dl ${cls}">${d}</div>`;
er.appendChild(el);
});
}
// ---- data volume vs success (model A, against what A trained on) -----------------
function ranks(v) {
const idx = v.map((x, i) => [x, i]).sort((p, q) => p[0] - q[0]), r = new Array(v.length);
for (let i = 0; i < idx.length;) {
let j = i; while (j + 1 < idx.length && idx[j + 1][0] === idx[i][0]) j++;
for (let k = i; k <= j; k++) r[idx[k][1]] = (i + j) / 2 + 1;
i = j + 1;
}
return r;
}
function pearson(x, y) {
const n = x.length, mx = x.reduce((a, b) => a + b) / n, my = y.reduce((a, b) => a + b) / n;
let sxy = 0, sxx = 0, syy = 0;
for (let i = 0; i < n; i++) { sxy += (x[i] - mx) * (y[i] - my); sxx += (x[i] - mx) ** 2; syy += (y[i] - my) ** 2; }
return sxx && syy ? sxy / Math.sqrt(sxx * syy) : NaN;
}
function quantile(sorted, q) {
const pos = (sorted.length - 1) * q, lo = Math.floor(pos), hi = Math.ceil(pos);
return sorted[lo] + (sorted[hi] - sorted[lo]) * (pos - lo);
}
function renderScatter() {
const A = byId[S.a], ra = runOf(S.a, S.cap), counts = A && A.trained_on && A.trained_on.counts;
const svg = $('scat'); svg.innerHTML = ''; $('quart').innerHTML = '';
const pts = counts && ra ? Object.keys(ra).filter(t => counts[t]).map(t => ({task: t, n: counts[t], rate: ra[t].rate})) : [];
$('c-fig').hidden = pts.length < 4;
if (pts.length < 4) {
$('c-note').textContent = !A ? 'Pick a model A.'
: !ra ? 'Model A has no results at this step cap.'
: 'Model A\'s training set is not on disk, so its per-task volume is unknown.';
$('c-cap').textContent = '';
return;
}
const xs = pts.map(p => p.n), ys = pts.map(p => p.rate);
const rho = pearson(ranks(xs), ranks(ys)), rlog = pearson(xs.map(Math.log), ys);
const zero = pts.filter(p => p.rate === 0);
$('c-note').textContent = 'Model A: success per task vs. episodes it trained on (log scale).';
$('c-cap').textContent = `Spearman ρ = ${rho.toFixed(2)} over ${pts.length} tasks · r = ${rlog.toFixed(2)} on log volume. ` +
`Red: never succeeded.`;
const W = 720, H = 300, m = {t: 16, r: 16, b: 46, l: 48}, iw = W - m.l - m.r, ih = H - m.t - m.b;
const lo = Math.log(Math.max(1, Math.min(...xs) * 0.8)), hi = Math.log(Math.max(...xs) * 1.15);
const X = n => m.l + (Math.log(n) - lo) / (hi - lo) * iw, Y = v => m.t + (1 - v) * ih;
if (Math.exp(lo) < 300 && Math.exp(hi) > 300) {
svgAdd(svg, 'rect', {x: m.l, y: m.t, width: X(300) - m.l, height: ih, 'class': 'band'});
svgAdd(svg, 'line', {x1: X(300), y1: m.t, x2: X(300), y2: Y(0), 'class': 'bandline'});
svgAdd(svg, 'text', {x: X(300) + 7, y: m.t + 13, 'class': 'pl'}, '300 episodes');
}
[0, .25, .5, .75, 1].forEach(v => {
svgAdd(svg, 'line', {x1: m.l, x2: m.l + iw, y1: Y(v), y2: Y(v), 'class': 'grid'});
svgAdd(svg, 'text', {x: m.l - 9, y: Y(v) + 4, 'text-anchor': 'end'}, Math.round(v * 100) + '%');
});
[100, 300, 1000, 3000, 10000].filter(n => Math.log(n) > lo && Math.log(n) < hi)
.forEach(n => svgAdd(svg, 'text', {x: X(n), y: H - m.b + 20, 'text-anchor': 'middle'}, fmt(n)));
svgAdd(svg, 'text', {x: m.l + iw / 2, y: H - 8, 'text-anchor': 'middle', 'class': 'ax'}, 'training episodes (log scale)');
const L2 = xs.map(Math.log), n = L2.length, sx = L2.reduce((a, b) => a + b), sy = ys.reduce((a, b) => a + b);
const sxx = L2.reduce((a, b) => a + b * b, 0), sxy = L2.reduce((a, b, i) => a + b * ys[i], 0);
const slope = (n * sxy - sx * sy) / (n * sxx - sx * sx), icept = (sy - slope * sx) / n;
const cl = v => Math.max(0, Math.min(1, v)), f1 = lo + 0.05, f2 = hi - 0.05;
svgAdd(svg, 'path', {d: `M${X(Math.exp(f1))},${Y(cl(icept + slope * f1))} L${X(Math.exp(f2))},${Y(cl(icept + slope * f2))}`, 'class': 'fit'});
pts.forEach(p => {
const c = svgAdd(svg, 'circle', {cx: X(p.n), cy: Y(p.rate), r: 5, 'class': 'dot' + (p.rate === 0 ? ' z' : '')});
const show = ev => showTip(ev, `<div class="t">${esc(p.task)}</div><dl><dt>success</dt><dd>${pct(p.rate)}</dd><dt>trained on</dt><dd>${fmt(p.n)} episodes</dd></dl>`);
c.addEventListener('mouseenter', show); c.addEventListener('mousemove', show); c.addEventListener('mouseleave', hideTip);
});
// Quartiles of training volume, pandas-qcut style (right-inclusive edges).
const sorted = [...xs].sort((a, b) => a - b), edges = [0, .25, .5, .75, 1].map(q => quantile(sorted, q));
const bins = [[], [], [], []];
pts.forEach(p => { let b = edges.findIndex((e, i) => i > 0 && p.n <= e) - 1; bins[Math.max(0, b)].push(p); });
$('quart').innerHTML = bins.map((g, i) => {
if (!g.length) return '';
const ns2 = g.map(p => p.n).sort((a, b) => a - b), md = ns2.length % 2 ? ns2[ns2.length >> 1] : (ns2[ns2.length / 2 - 1] + ns2[ns2.length / 2]) / 2;
const r = g.reduce((a, p) => a + p.rate, 0) / g.length;
return `<div class="${i === 0 ? 'lo' : ''}"><dt>Q${i + 1}${i === 0 ? ' fewest' : i === 3 ? ' most' : ''}</dt>` +
`<dd>${pct(r)}</dd><span class="sub">${g.length} tasks Β· median ${fmt(Math.round(md))} episodes</span></div>`;
}).join('');
}
// ---- table ----------------------------------------------------------------------
function renderTable() {
const ra = runOf(S.a, S.cap), rb = runOf(S.b, S.cap);
const extra = [...new Set([...Object.keys(ra || {}), ...Object.keys(rb || {})])].filter(t => !T.some(r => r.task === t));
const list = T.map(r => r.task).concat(extra);
$('tbody').innerHTML = list.map((t, i) => {
const r = T.find(x => x.task === t), a = ra && ra[t], b = rb && rb[t];
const trained = byId[S.a] && byId[S.a].trained_on && byId[S.a].trained_on.counts;
return `<tr><td>${i + 1}</td><td>${esc(t)}</td><td>${r ? fmt(r.n) : 'β€”'}</td>` +
`<td>${trained && trained[t] ? fmt(trained[t]) : 'β€”'}</td><td>${a ? pct(a.rate) : 'β€”'}</td><td>${b ? pct(b.rate) : 'β€”'}</td></tr>`;
}).join('');
}
function renderAll() {
fillCaps();
$('meta-a').textContent = modelMeta(byId[S.a]);
$('meta-b').textContent = modelMeta(byId[S.b]);
renderTiles(); renderScore(); renderScatter(); renderTable();
}
fillModels();
if (!MODELS.length) {
renderTiles(); $('score').innerHTML = ''; $('erows').innerHTML = '<p class="empty">No models under models/ yet.</p>';
} else {
renderAll();
}
})();
</script>
</body></html>