Spaces:
Running
Running
Rebuild portal for matched RoboTwin native policy experiments
Browse files- README.md +6 -63
- app.js +22 -142
- data.json +98 -0
- index.html +1 -25
- manifest.json +28 -0
- sources.json +56 -0
- style.css +1 -5
README.md
CHANGED
|
@@ -1,70 +1,13 @@
|
|
| 1 |
---
|
| 2 |
title: Programmable VLA
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: static
|
| 7 |
-
app_file: index.html
|
| 8 |
pinned: false
|
| 9 |
-
|
| 10 |
---
|
| 11 |
|
| 12 |
-
# Programmable VLA
|
| 13 |
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
The initial release contains **three valid LIBERO integration episodes** on
|
| 17 |
-
`libero/libero-spatial-01`, seed 0, initial-state index 0:
|
| 18 |
-
|
| 19 |
-
| Method | Native outcome | Control steps |
|
| 20 |
-
| --- | --- | --- |
|
| 21 |
-
| B0 · standalone frozen VLA | Success | 77 / 600 |
|
| 22 |
-
| B1 · pure Kinex agent | Step limit | 600 / 600 |
|
| 23 |
-
| B2 · Kinex + frozen VLA | Success | 79 / 600 |
|
| 24 |
-
|
| 25 |
-
The native total-step limit is 605, including five initialization frames.
|
| 26 |
-
There is no planner-decision cap. B1/B2 use GPT-6 sol with high reasoning effort.
|
| 27 |
-
The policy is the original frozen StarVLA Qwen3-VL-4B OFT checkpoint at step 50000.
|
| 28 |
-
No encoder, scientific training or progress monitor is involved.
|
| 29 |
-
|
| 30 |
-
One task and one initial state per method support integration and behavior
|
| 31 |
-
inspection, not a benchmark-level comparison. B2 delegates the full task in one
|
| 32 |
-
accepted VLA call; this episode does not establish a planning benefit. Three
|
| 33 |
-
engineering failures before task actions are excluded and recorded in the report.
|
| 34 |
-
Earlier pilot experiments used a different protocol and are not pooled here.
|
| 35 |
-
|
| 36 |
-
## Evidence
|
| 37 |
-
|
| 38 |
-
The page provides both camera videos, observable agent sessions, VLA invocation
|
| 39 |
-
arguments and returns, policy input images, predicted action chunks, and executed
|
| 40 |
-
action CSVs. B1's joint commands are in its session; it has no OSC action rows.
|
| 41 |
-
Physics runs at 20 Hz; spectator cameras are captured at 10 Hz. The paired
|
| 42 |
-
1440 x 720 publication video encodes every source sample once at 4x simulation
|
| 43 |
-
speed. The viewer defaults to 1x for short policy invocations and supports speed
|
| 44 |
-
selection and the final native frame. Planning/inference pauses are omitted.
|
| 45 |
-
Native success is a separate evaluator result; the VLA does not report semantic
|
| 46 |
-
completion. Internal reasoning blocks, credentials, host-local paths and private
|
| 47 |
-
simulator state are excluded. Session tool IDs are remapped to local identifiers.
|
| 48 |
-
|
| 49 |
-
`data/report.json` is the machine-readable index. `data/manifest.json` records
|
| 50 |
-
SHA-256 checksums of all other exported files. Each episode includes the hash of
|
| 51 |
-
its retained native evidence archive.
|
| 52 |
-
|
| 53 |
-
Saved agent code and memos, full task instructions, paired tool calls and returns,
|
| 54 |
-
and audited per-response token usage are available in dedicated tabs. Displayed
|
| 55 |
-
USD costs are Standard API-equivalent estimates from official GPT-6 Sol rates
|
| 56 |
-
verified on 2026-10-28, not account charges. GPU inference cost is not measured.
|
| 57 |
-
|
| 58 |
-
Future training runs are assigned to the W&B team `programmable_vla`, project
|
| 59 |
-
`program_VLA`: https://forge.coreweave.com/wandb/programmable_vla
|
| 60 |
-
This release contains evaluation evidence only.
|
| 61 |
-
|
| 62 |
-
## Transfer diagnostic
|
| 63 |
-
|
| 64 |
-
The [Bridge-to-LIBERO probe](https://rle-bench-programmable-vla.static.hf.space/probes/bridge-20261028/index.html)
|
| 65 |
-
uses the released Qwen3-VL-4B OFT Bridge/RT-1 5k checkpoint on spatial-01, seed 0.
|
| 66 |
-
The valid episode reached 600 control steps without success. Its video, raw
|
| 67 |
-
predictions, conversion traces and native controls are retained separately from
|
| 68 |
-
the three integration episodes above. The checkpoint has an unresolved upstream
|
| 69 |
-
upload mismatch, and its camera, embodiment and action contract differ from the
|
| 70 |
-
LIBERO policy; this single probe is not a benchmark comparison.
|
|
|
|
| 1 |
---
|
| 2 |
title: Programmable VLA
|
| 3 |
+
emoji: 🤖
|
| 4 |
+
colorFrom: purple
|
| 5 |
+
colorTo: blue
|
| 6 |
sdk: static
|
|
|
|
| 7 |
pinned: false
|
| 8 |
+
license: apache-2.0
|
| 9 |
---
|
| 10 |
|
| 11 |
+
# Programmable VLA
|
| 12 |
|
| 13 |
+
Matched RoboTwin behavior experiments: standalone VLA, Kinex, and Kinex with a native policy tool. Sessions, tool calls, policy inputs and outputs, usage, videos, and artifacts.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.js
CHANGED
|
@@ -1,142 +1,22 @@
|
|
| 1 |
-
|
| 2 |
-
const $
|
| 3 |
-
const
|
| 4 |
-
const
|
| 5 |
-
|
| 6 |
-
const
|
| 7 |
-
const
|
| 8 |
-
const
|
| 9 |
-
const
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
}
|
| 19 |
-
|
| 20 |
-
function
|
| 21 |
-
function
|
| 22 |
-
|
| 23 |
-
function methods() {
|
| 24 |
-
$("#methods").innerHTML = report.episodes.map(e => `<a class="method-card ${current.method === e.method ? "active" : ""}" data-method="${e.method}" style="--variant:${colors[e.method]}" href="#${e.method}/${current.tab}" ${current.method === e.method ? 'aria-current="true"' : ""}><div class="card-header"><span class="method-label"><span class="method-id">${e.method}</span>${names[e.method]}</span>${badge(e)}</div><div class="card-model">${e.method === "B0" ? "Qwen3-VL OFT · frozen" : `GPT-6 Sol / high${e.method === "B2" ? " + OFT" : ""}`}</div><div class="card-stats"><div><strong>${number(e.control_steps)} / 600</strong><span>control steps</span></div><div><strong>${number(e.total_tokens)}</strong><span>total tokens</span></div><div><strong>${money(e.estimated_api_equivalent_usd)}</strong><span>API equiv. · est.</span></div></div></a>`).join("");
|
| 25 |
-
}
|
| 26 |
-
function tabs(e) {
|
| 27 |
-
const items = [["overview","Overview"],["instruction","Instruction"],["session","Session",e.session_messages],["tools","Tool calls",e.tool_calls],["vla","VLA I/O",e.vla_calls],["artifacts","Artifacts",e.artifacts],["usage","Tokens & cost"]];
|
| 28 |
-
$("#tabs").innerHTML = items.map(([key,label,count]) => `<a href="#${e.method}/${key}" class="${current.tab === key ? "active" : ""}" ${current.tab === key ? 'aria-current="page"' : ""}>${label}${count != null ? `<small>${count}</small>` : ""}</a>`).join("");
|
| 29 |
-
}
|
| 30 |
-
function overview(e, detail) {
|
| 31 |
-
return `<div class="episode-layout"><div class="video-panel"><div class="video-caption"><span>Third-person + wrist</span><span>1440 × 720</span></div><video id="episode-video" controls playsinline preload="metadata" poster="${e.path}/poster.jpg" src="${e.path}/video.mp4" aria-label="${e.method} paired camera recording"></video><div class="video-toolbar"><label>Speed <select id="playback-speed" aria-label="Video playback speed">${[.5,1,2,4,8].map(speed => `<option value="${speed/4}" ${speed === 1 ? "selected" : ""}>${speed}× simulation</option>`).join("")}</select></label><div><button id="final-frame" class="button">Final frame</button>${external(`${e.path}/video.mp4`,"Video","button")}${external(`${e.path}/terminal.jpg`,"Still","button")}</div></div></div><aside class="panel result-panel"><div class="result-head"><span class="eyebrow">NATIVE RESULT</span>${badge(e)}</div><div class="result-number">${e.control_steps}<span> / 600 control steps</span></div><div class="completion-track"><span style="width:${e.control_steps/6}%"></span></div><dl class="facts"><dt>Termination</dt><dd>${esc(e.native_reason)}</dd><dt>Simulation time</dt><dd>${e.simulation_time_s.toFixed(2)} s</dd><dt>Episode wall time</dt><dd>${e.wall_time_sec.toFixed(1)} s</dd><dt>Model responses</dt><dd>${e.model_responses}</dd><dt>Tool calls</dt><dd>${e.tool_calls}</dd><dt>Accepted VLA calls</dt><dd>${e.vla_calls}</dd><dt>API equiv. · est.</dt><dd>${money(e.estimated_api_equivalent_usd)}</dd></dl></aside></div><div class="metric-grid">${metric(number(detail.accounting.tokens.fresh_input),"Fresh input tokens")}${metric(number(detail.accounting.tokens.cache_read),"Cache read tokens")}${metric(number(detail.accounting.output_tokens),"Output tokens")}${metric(number(e.total_tokens),"Total input + output")}</div><div class="observation"><strong>Observed behavior</strong><span>${esc(e.observation)}</span></div>`;
|
| 32 |
-
}
|
| 33 |
-
function instruction(e, d) {
|
| 34 |
-
return `<section class="panel"><div class="panel-heading"><h2>Task instruction</h2>${links(e.path,[["Full instruction","instruction.txt"]])}</div><p class="instruction">${esc(report.instruction)}</p><details class="instruction-full"><summary>Full recorded agent input</summary>${code(d.instruction)}</details></section>`;
|
| 35 |
-
}
|
| 36 |
-
function image(src, label) { return `<img src="${esc(src)}" alt="${esc(label)}" data-image="${esc(src)}" loading="lazy">`; }
|
| 37 |
-
function blocks(content) {
|
| 38 |
-
return content.map(block => block.type === "image" ? image(block.src,"Recorded agent observation") : code(block.type === "text" ? block.text : block)).join("");
|
| 39 |
-
}
|
| 40 |
-
async function session(e, token) {
|
| 41 |
-
const messages = await load(`${e.path}/session.json`);
|
| 42 |
-
if (token !== epoch) return;
|
| 43 |
-
if (!messages.length) { $("#detail").innerHTML = `<div class="panel empty">B0 has no planner session. ${external(`#${e.method}/vla`,"View its policy invocation")}</div>`; return; }
|
| 44 |
-
$("#detail").innerHTML = `<section class="panel"><div class="panel-heading"><h2>Session & observations</h2>${links(e.path,[["Session JSON","session.json"]])}</div><div class="session-toolbar"><select id="event-filter" aria-label="Session filter"><option value="all">All messages</option><option value="assistant">Assistant</option><option value="toolResult">Tool results</option><option value="user">Instruction</option><option value="images">Observations</option></select><input id="event-search" type="search" aria-label="Search session" placeholder="Search text, tool or operation"><span id="event-count"></span></div><div id="session-events"></div><div class="session-more"><button id="more-events" class="button" hidden>Load more</button></div></section>`;
|
| 45 |
-
let limit = 30;
|
| 46 |
-
function render() {
|
| 47 |
-
const query = $("#event-search").value.toLowerCase(), filter = $("#event-filter").value;
|
| 48 |
-
const selected = messages.map((message,index) => ({message,index})).filter(({message}) => (filter === "all" || message.role === filter || (filter === "images" && message.content.some(b => b.type === "image"))) && JSON.stringify(message.content).toLowerCase().includes(query));
|
| 49 |
-
$("#event-count").textContent = `${selected.length} messages`;
|
| 50 |
-
$("#session-events").innerHTML = selected.slice(0,limit).map(({message,index}) => {
|
| 51 |
-
const tools = message.content.filter(b => b.type === "toolCall").map(b => b.name).join(", ");
|
| 52 |
-
const preview = message.content.find(b => b.type === "text")?.text?.slice(0,130) || tools;
|
| 53 |
-
const elapsed = message.timestamp == null ? "" : `+${((message.timestamp-messages[0].timestamp)/1000).toFixed(1)}s`;
|
| 54 |
-
return `<details class="event"><summary><span class="event-id">${String(index+1).padStart(3,"0")} · ${elapsed}</span><span class="event-name">${esc(message.role)}${tools ? ` · ${esc(tools)}` : ""}</span><span class="event-preview">${esc(preview)}</span></summary><div class="event-body">${blocks(message.content)}</div></details>`;
|
| 55 |
-
}).join("") || '<p class="empty">No matching messages.</p>';
|
| 56 |
-
$("#more-events").hidden = selected.length <= limit;
|
| 57 |
-
}
|
| 58 |
-
$("#event-filter").onchange = $("#event-search").oninput = () => { limit = 30; render(); };
|
| 59 |
-
$("#more-events").onclick = () => { limit += 30; render(); }; render();
|
| 60 |
-
}
|
| 61 |
-
async function tools(e, token) {
|
| 62 |
-
const calls = await load(`${e.path}/tool-calls.json`);
|
| 63 |
-
if (token !== epoch) return;
|
| 64 |
-
$("#detail").innerHTML = `<section class="panel"><div class="panel-heading"><h2>Tool calls · ${calls.length}</h2>${links(e.path,[["Tool I/O JSON","tool-calls.json"]])}</div><div class="session-toolbar"><input id="tool-search" type="search" aria-label="Search tool calls" placeholder="Filter by tool, operation or argument"><span id="tool-count"></span></div><div id="tool-list"></div></section>`;
|
| 65 |
-
function render() {
|
| 66 |
-
const selected = calls.filter(c => JSON.stringify(c).toLowerCase().includes($("#tool-search").value.toLowerCase()));
|
| 67 |
-
$("#tool-count").textContent = `${selected.length} calls`;
|
| 68 |
-
$("#tool-list").innerHTML = selected.map(call => `<details class="event"><summary><span class="event-id">${esc(call.id)}</span><span class="event-name">${esc(call.name)}</span><span class="event-preview">${esc(call.arguments.description || call.arguments.action || call.arguments.path || "")}</span></summary><div class="event-body"><h3>Arguments</h3>${code(call.arguments)}<h3>Return</h3>${blocks(call.result)}</div></details>`).join("") || '<p class="empty">No planner tool calls.</p>';
|
| 69 |
-
}
|
| 70 |
-
$("#tool-search").oninput = render; render();
|
| 71 |
-
}
|
| 72 |
-
function vla(e, d) {
|
| 73 |
-
if (!d.calls.length) return '<section class="panel empty">This method uses native arm and gripper commands. See Tool calls for the recorded actions.</section>';
|
| 74 |
-
$("#detail").innerHTML = `<section class="panel"><div class="panel-heading"><h2>Agent → VLA · ${d.calls.length} accepted call</h2>${links(e.path,[["Invocations","vla-calls.json"],["Executed actions","executed-actions.csv"]])}</div>${d.calls.map(call => `<div class="io-grid"><div><h3>Invocation input</h3>${code(call.input)}</div><div><h3>Executor return</h3>${code(call.output)}</div></div>`).join("")}<p class="caption">The native verdict is evaluated separately. The executor returns no semantic completion signal.</p></section><section class="panel section-gap"><div class="panel-heading"><h2>Policy observations → action chunk</h2><select id="policy-step" aria-label="Policy step">${d.policy_inputs.map((input,index) => `<option value="${index}">Chunk ${index+1} · control step ${input.control_step}</option>`).join("")}</select></div><div id="policy-content"></div>${links(e.path,[["Policy inputs","policy-inputs.json"],["Predicted chunks","policy-chunks.json"]])}</section>`;
|
| 75 |
-
function render() {
|
| 76 |
-
const index = Number($("#policy-step").value), input = d.policy_inputs[index];
|
| 77 |
-
$("#policy-content").innerHTML = `<p>${esc(input.instruction)}</p><div class="image-pair">${input.images.map((src,n) => `<figure>${image(src,n ? "Wrist policy input" : "Agent-view policy input")}<figcaption>${n ? "Wrist" : "Agent view"}</figcaption></figure>`).join("")}</div>${code(d.policy_chunks[index])}<p class="caption">8 × 7 unnormalized actions. First six values: OSC controller inputs; last value: gripper prediction.</p>`;
|
| 78 |
-
}
|
| 79 |
-
$("#policy-step").onchange = render; render();
|
| 80 |
-
}
|
| 81 |
-
async function artifacts(e, d, token) {
|
| 82 |
-
$("#detail").innerHTML = `<section class="panel"><div class="panel-heading"><h2>Saved agent artifacts · ${d.artifacts.length}</h2></div>${d.artifacts.length ? '<div class="artifact-list"><div id="artifact-nav" class="artifact-nav"></div><div id="artifact-content"></div></div>' : '<p class="empty">No agent-created files for this method.</p>'}</section><section class="panel section-gap"><div class="panel-heading"><h2>Episode evidence</h2></div><div class="links">${[["Result metadata","detail.json"],["Instruction","instruction.txt"],["Session","session.json"],["Tool calls","tool-calls.json"],["Usage","usage.json"],["Policy actions","executed-actions.csv"],["Media checks","media.json"],["Frame mapping","frame-mapping.json"],["Third-person source","third_person.mp4"],["Wrist source","wrist.mp4"]].map(([label,file])=>external(`${e.path}/${file}`,label)).join("")}</div></section>`;
|
| 83 |
-
let selected = -1;
|
| 84 |
-
async function show(index) {
|
| 85 |
-
selected = index;
|
| 86 |
-
$("#artifact-nav").querySelectorAll("button").forEach((b,n) => b.classList.toggle("active", n === index));
|
| 87 |
-
const resource = d.artifacts[index];
|
| 88 |
-
$("#artifact-content").innerHTML = '<p class="loading">Loading file…</p>';
|
| 89 |
-
const response = await fetch(resource.file);
|
| 90 |
-
if (!response.ok) throw Error(`Artifact unavailable: ${resource.name}`);
|
| 91 |
-
const text = await response.text();
|
| 92 |
-
if (token !== epoch || selected !== index) return;
|
| 93 |
-
$("#artifact-content").innerHTML = `<div class="panel-heading"><h3>${esc(resource.name.split("/").at(-1))}</h3>${external(resource.file,"Download","button")}</div>${code(text)}`;
|
| 94 |
-
}
|
| 95 |
-
if (d.artifacts.length) {
|
| 96 |
-
$("#artifact-nav").innerHTML = d.artifacts.map((r,i) => `<button data-artifact="${i}">${esc(r.name)}</button>`).join("");
|
| 97 |
-
$("#artifact-nav").onclick = event => { const button = event.target.closest("[data-artifact]"); if (button) show(Number(button.dataset.artifact)).catch(showError); };
|
| 98 |
-
await show(0);
|
| 99 |
-
}
|
| 100 |
-
}
|
| 101 |
-
function usage(e, d) {
|
| 102 |
-
const u = d.accounting, labels = {fresh_input:"Fresh input",cache_read:"Cache read",cache_write:"Cache write",output:"Output"};
|
| 103 |
-
return `<div class="metric-grid">${metric(number(u.input_tokens),"Input tokens · includes cache")}${metric(number(u.output_tokens),"Output tokens")}${metric(number(u.total_tokens),"Total tokens")}${metric(money(u.estimated_api_equivalent_usd),"API equivalent · estimated")}</div><section class="panel"><div class="panel-heading"><h2>Token & cost accounting</h2>${links(e.path,[["Usage JSON","usage.json"]])}</div><div class="table-wrap"><table class="data-table"><thead><tr><th>Category</th><th>Tokens</th><th>USD / 1M</th><th>Estimated USD</th></tr></thead><tbody>${Object.entries(labels).map(([key,label])=>`<tr><td>${label}</td><td>${number(u.tokens[key])}</td><td>$${u.pricing.per_million_tokens[key].toFixed(2)}</td><td>${money(u.cost_breakdown_usd[key])}</td></tr>`).join("")}<tr><td><strong>Total</strong></td><td>${number(u.total_tokens)}</td><td></td><td><strong>${money(u.estimated_api_equivalent_usd)}</strong></td></tr></tbody></table></div><p class="caption">Standard API-equivalent estimate from ${u.response_count} audited responses. Actual billed cost: ${money(u.actual_billed_usd)}. GPU cost: not measured. ${external(u.pricing.source,"Pricing source")} · ${esc(u.pricing.verified_date)}</p><details class="section-gap"><summary>Per-response usage</summary>${code(u.per_response_usage)}</details></section>`;
|
| 104 |
-
}
|
| 105 |
-
function viewer(src, label) { $("#viewer-image").src = src; $("#image-original").href = src; $("#image-label").textContent = label; $("#image-viewer").showModal(); }
|
| 106 |
-
function setupVideo() {
|
| 107 |
-
const video = $("#episode-video"); if (!video) return;
|
| 108 |
-
video.defaultPlaybackRate = .25; video.playbackRate = .25;
|
| 109 |
-
$("#playback-speed").onchange = event => { video.playbackRate = Number(event.target.value); };
|
| 110 |
-
$("#final-frame").onclick = () => { video.pause(); viewer(`${current.episode.path}/terminal.jpg`,"Final native frame · third-person + wrist"); };
|
| 111 |
-
}
|
| 112 |
-
function showError(error) { $("#detail").innerHTML = `<p class="error">${esc(error.message)}</p>`; }
|
| 113 |
-
async function route() {
|
| 114 |
-
if (!report) return;
|
| 115 |
-
if (location.hash === "#protocol") { $("#protocol").open = true; $("#protocol").scrollIntoView(); return; }
|
| 116 |
-
const [requestedMethod,requestedTab] = location.hash.slice(1).split("/");
|
| 117 |
-
const method = ["B0","B1","B2"].includes(requestedMethod) ? requestedMethod : "B2";
|
| 118 |
-
const tab = ["overview","instruction","session","tools","vla","artifacts","usage"].includes(requestedTab) ? requestedTab : "overview";
|
| 119 |
-
const e = report.episodes.find(row => row.method === method), token = ++epoch;
|
| 120 |
-
current = {method,tab,episode:e}; methods(); tabs(e);
|
| 121 |
-
$("#detail").innerHTML = '<p class="loading">Loading evidence…</p>';
|
| 122 |
-
try {
|
| 123 |
-
const detail = await load(`${e.path}/detail.json`); if (token !== epoch) return;
|
| 124 |
-
if (tab === "overview") { $("#detail").innerHTML = overview(e,detail); setupVideo(); }
|
| 125 |
-
if (tab === "instruction") $("#detail").innerHTML = instruction(e,detail);
|
| 126 |
-
if (tab === "session") await session(e,token);
|
| 127 |
-
if (tab === "tools") await tools(e,token);
|
| 128 |
-
if (tab === "vla") { const empty = vla(e,detail); if (empty) $("#detail").innerHTML = empty; }
|
| 129 |
-
if (tab === "artifacts") await artifacts(e,detail,token);
|
| 130 |
-
if (tab === "usage") $("#detail").innerHTML = usage(e,detail);
|
| 131 |
-
} catch(error) { if (token === epoch) showError(error); }
|
| 132 |
-
}
|
| 133 |
-
$("#close-viewer").onclick = () => $("#image-viewer").close();
|
| 134 |
-
$("#image-viewer").addEventListener("click", event => { if (event.target === $("#image-viewer")) $("#image-viewer").close(); });
|
| 135 |
-
document.addEventListener("click", event => { const img = event.target.closest("[data-image]"); if (img) viewer(img.dataset.image,img.alt); });
|
| 136 |
-
window.addEventListener("hashchange", route);
|
| 137 |
-
async function main() {
|
| 138 |
-
report = await load("data/report.json");
|
| 139 |
-
$("#protocol-content").innerHTML = `<p>One task, one initial state per method. Original frozen VLA; no encoder, training or progress monitor. Three pre-action engineering failures are excluded. Earlier pilots use a different protocol.</p><details class="section-gap"><summary>Effective configuration</summary>${code(report.protocol)}</details><p>Sessions contain observable messages, tool I/O and images. Internal reasoning and private simulator state remain excluded. Videos retain every synchronized camera sample and the terminal frame.</p><div class="links">${external("https://huggingface.co/StarVLA/Qwen3-VL-OFT-LIBERO-4in1","Policy checkpoint")}${external("data/report.json","Result index")}${external("data/manifest.json","Checksums")}</div>`;
|
| 140 |
-
await route();
|
| 141 |
-
}
|
| 142 |
-
main().catch(showError);
|
|
|
|
| 1 |
+
'use strict';
|
| 2 |
+
const $=s=>document.querySelector(s),esc=x=>String(x??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
|
| 3 |
+
const num=x=>x==null?'—':Number(x).toLocaleString('en-US'),money=x=>x==null?'—':'$'+Number(x).toFixed(4);
|
| 4 |
+
let data;const cache=new Map();
|
| 5 |
+
async function load(path){if(!cache.has(path)){const r=await fetch(path);if(!r.ok)throw new Error(`${path}: ${r.status}`);cache.set(path,await r.json());}return cache.get(path)}
|
| 6 |
+
const condition=id=>data.conditions.find(x=>x.id===id),episode=(t,c)=>data.episodes.find(e=>e.task===t&&e.condition===c);
|
| 7 |
+
const state=e=>!e?'pending':e.valid===false?'invalid':e.success===true?'success':e.success===false?'failure':e.status||'pending';
|
| 8 |
+
const badge=(e,url)=>`<a class="badge ${state(e)}" href="${url}">${{success:'Success',failure:'Failure',invalid:'Interrupted',pending:'Pending',running:'Running'}[state(e)]||esc(state(e))}</a>`;
|
| 9 |
+
const route=(t,c,tab='overview')=>`#episode/${t}/${c}/${tab}`;
|
| 10 |
+
function matrix(){return `<div class="table-wrap"><table><thead><tr><th>Task · seed 0</th>${data.conditions.map(c=>`<th>${esc(c.label)}</th>`).join('')}<th>Action limit</th></tr></thead><tbody>${data.tasks.map(t=>`<tr data-task="${esc(t.label.toLowerCase())}"><td><strong>${esc(t.label)}</strong></td>${data.conditions.map(c=>`<td>${badge(episode(t.id,c.id),route(t.id,c.id))}</td>`).join('')}<td>${num(t.max_steps)}</td></tr>`).join('')}</tbody></table></div>`}
|
| 11 |
+
function overview(tasksOnly=false){const cards=data.conditions.map(c=>{const all=data.episodes.filter(e=>e.condition===c.id),es=all.filter(e=>e.valid&&typeof e.success==='boolean'),wins=es.filter(e=>e.success).length;return `<article class="card"><h3>${esc(c.label)}</h3><div class="label">${esc(c.model)}</div><div class="value">${es.length?(100*wins/es.length).toFixed(0)+'%':'—'}</div><div class="label">${wins} / ${es.length} completed · ${data.tasks.length} planned</div><div class="meta"><span>${es.length?num(es.reduce((n,e)=>n+(e.input_tokens||0)+(e.output_tokens||0),0)):'—'} tokens</span><span>${(!es.length||es.some(e=>e.api_cost_usd==null))?'—':money(es.reduce((n,e)=>n+(e.api_cost_usd||0),0))} API equivalent</span></div></article>`}).join('');$('#main').innerHTML=`<div class="eyebrow">RoboTwin 2.0 · task03 · single seed</div><h1>${tasksOnly?'Explore tasks':'Agent decisions. Policy actions.'}</h1><p class="muted">Standalone VLA, Kinex, and Kinex with a native policy tool.</p>${tasksOnly?'':`<div class="cards">${cards}</div>`}<section class="panel"><div class="row"><h2>Matched task comparison</h2></div>${matrix()}<p class="note">Same instructions, seeds and native control budgets. Three-task behavior pilot; incomplete episodes are excluded from success-rate denominators.</p></section>`}
|
| 12 |
+
async function detail(tid,cid,tab){const t=data.tasks.find(x=>x.id===tid),c=condition(cid);if(!t||!c){overview();return}const e=episode(tid,cid);const tabs=['overview','instruction','session','tools','policy','artifacts'];$('#main').innerHTML=`<a href="#overview">← All experiments</a><div class="toolbar"><select id="task-select" aria-label="Task">${data.tasks.map(x=>`<option value="${x.id}" ${x.id===tid?'selected':''}>${esc(x.label)}</option>`).join('')}</select><select id="condition-select" aria-label="Baseline">${data.conditions.map(x=>`<option value="${x.id}" ${x.id===cid?'selected':''}>${esc(x.label)}</option>`).join('')}</select>${badge(e,route(tid,cid))}</div><h1>${esc(t.label)}</h1><p class="muted">${esc(c.model)} · ${num(t.max_steps)} action steps · seed 0</p><div class="tabs">${tabs.map(x=>`<a class="${tab===x?'active':''}" href="${route(tid,cid,x)}">${x==='tools'?'Tool calls':x==='policy'?'VLA input / output':x[0].toUpperCase()+x.slice(1)}</a>`).join('')}</div><section id="detail-content"></section>`;$('#task-select').onchange=x=>location.hash=route(x.target.value,cid,tab);$('#condition-select').onchange=x=>location.hash=route(tid,x.target.value,tab);const target=$('#detail-content');if(!e||!e.path){target.innerHTML='<div class="empty">Episode pending</div>';return}const d=await load(e.path+'/detail.json');if(!document.contains(target))return;
|
| 13 |
+
const metrics=`<div class="metrics">${[['Native steps',num(e.control_steps)],['Tool calls',num(e.tool_calls)],['VLA inferences',num(e.vla_calls)],['Input / output',`${num(e.input_tokens)} / ${num(e.output_tokens)}`],['API equivalent',money(e.api_cost_usd)]].map(([k,v])=>`<div class="metric"><b>${v}</b><span>${k}</span></div>`).join('')}</div>`;
|
| 14 |
+
if(tab==='overview')target.innerHTML=`<div class="panel">${e.video?`<video id="episode-video" class="video" controls playsinline preload="metadata" poster="${esc(e.poster||'')}"><source src="${esc(e.video)}" type="video/mp4"></video>`:'<div class="empty">Recording is not available yet</div>'}${metrics}<p class="note">${esc(d.cost_note||'API-equivalent cost is an estimate, not a subscription charge.')} ${esc(d.media_note||'')}</p></div><div class="panel"><h2>Observed behavior</h2><p>${esc(d.observation||'Analysis pending.')}</p><a href="${e.path}/detail.json">Episode record ↗</a></div>`;
|
| 15 |
+
else if(tab==='instruction')target.innerHTML=`<div class="panel"><h2>Task instruction</h2><div class="text">${esc(d.instruction)}</div></div>`;
|
| 16 |
+
else if(tab==='artifacts')target.innerHTML=`<div class="panel files"><h2>Recorded artifacts</h2>${(d.artifacts||[]).map(a=>`<a href="${esc(a.path)}" target="_blank" rel="noopener">${esc(a.name)} <span class="muted">${num(a.bytes)} bytes ↗</span></a>`).join('')}</div>`;
|
| 17 |
+
else if(tab==='session'){const v=await load(e.path+'/session.json');target.innerHTML=`<p class="muted">${num(v.length)} messages · <a href="${e.path}/session.json">Download full session</a></p>${v.map(m=>`<article class="message"><b>${esc(m.role)} ${esc(m.name||'')}</b><div class="text">${esc(m.text)}</div>${m.data?`<details><summary>Recorded payload</summary><pre>${esc(JSON.stringify(m.data,null,2))}</pre></details>`:''}</article>`).join('')||'<div class="empty">Standalone evaluation has no planning-agent session.</div>'}`;}
|
| 18 |
+
else if(tab==='tools'){const v=await load(e.path+'/tool-calls.json');target.innerHTML=`<p class="muted">${num(v.length)} calls · <a href="${e.path}/tool-calls.json">Download tool calls</a></p>${v.map((m,i)=>`<details><summary>${i+1}. ${esc(m.name)} <span class="muted">${esc(m.summary||'')}</span></summary><h3>Input</h3><pre>${esc(JSON.stringify(m.input,null,2))}</pre><h3>Output</h3><pre>${esc(typeof m.output==='string'?m.output:JSON.stringify(m.output,null,2))}</pre></details>`).join('')||'<div class="empty">No agent tool calls</div>'}`;}
|
| 19 |
+
else if(tab==='policy'){const v=await load(e.path+'/policy-calls.json');target.innerHTML=`<p class="muted">${num(v.length)} inferences · <a href="${e.path}/policy-calls.json">Download all input / output records</a></p>${v.map((m,i)=>`<details><summary>${i+1}. ${esc(m.task)} <span class="muted">${m.inference_s?.toFixed(2)||'—'} s</span></summary><div class="images">${(m.images||[]).map(x=>`<a href="${esc(x)}" target="_blank"><img loading="lazy" src="${esc(x)}" alt="Policy input observation"></a>`).join('')}</div><h3>Model output and submitted interface</h3><pre>${esc(JSON.stringify(m.output,null,2))}</pre></details>`).join('')||'<div class="empty">No VLA inference recorded</div>'}`;}}
|
| 20 |
+
function protocol(){$('#main').innerHTML=`<div class="eyebrow">Experiment protocol</div><h1>One task. Three control choices.</h1><div class="panel"><h2>Execution</h2><table><tbody>${[['Suite','RLE-Bench task03 · RoboTwin 2.0 · ALOHA AgileX'],['VLA','StarVLA/Qwen3-VL-OFT-Robotwin2 · steps 40,000'],['Agent','Kinex · GPT-6 Astra · high'],['Policy interface','Native run_policy · one inference per call · agent owns the outer loop'],['Control','25 Hz native joint / gripper frames; original task-specific limits'],['Selection','First three task03 tasks, seed 0; frozen before outcome inspection'],['Scope','Frozen-policy behavior only; no encoder or progress monitor']].map(([k,v])=>`<tr><th>${k}</th><td>${v}</td></tr>`).join('')}</tbody></table></div><p class="muted">This fixed-rate device protocol differs from upstream VLA trajectory execution. Published StarVLA benchmark scores are not a direct comparison. RoboTwin 2.0-Plus is a separate suite and is not included here.</p><a href="sources.json">Source and model identities ↗</a>`}
|
| 21 |
+
async function render(){try{const parts=location.hash.slice(1).split('/');if(parts[0]==='episode')await detail(parts[1],parts[2],parts[3]||'overview');else if(parts[0]==='protocol')protocol();else overview(parts[0]==='tasks')}catch(e){$('#main').innerHTML=`<div class="panel"><h1>Could not load this record</h1><p>${esc(e.message)}</p><a href="#overview">Return to overview</a></div>`}}
|
| 22 |
+
fetch('data.json').then(r=>r.json()).then(x=>{data=x;window.addEventListener('hashchange',render);render()}).catch(e=>{$('#main').textContent=e.message});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data.json
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"tasks": [
|
| 3 |
+
{
|
| 4 |
+
"id": "1",
|
| 5 |
+
"native_id": "robotwin/handover-block-aloha-agilex",
|
| 6 |
+
"label": "Handover block",
|
| 7 |
+
"max_steps": 800,
|
| 8 |
+
"seed": 0
|
| 9 |
+
},
|
| 10 |
+
{
|
| 11 |
+
"id": "2",
|
| 12 |
+
"native_id": "robotwin/place-dual-shoes-aloha-agilex",
|
| 13 |
+
"label": "Place dual shoes",
|
| 14 |
+
"max_steps": 600,
|
| 15 |
+
"seed": 0
|
| 16 |
+
},
|
| 17 |
+
{
|
| 18 |
+
"id": "3",
|
| 19 |
+
"native_id": "robotwin/put-bottles-dustbin-aloha-agilex",
|
| 20 |
+
"label": "Put bottles in dustbin",
|
| 21 |
+
"max_steps": 1700,
|
| 22 |
+
"seed": 0
|
| 23 |
+
}
|
| 24 |
+
],
|
| 25 |
+
"conditions": [
|
| 26 |
+
{
|
| 27 |
+
"id": "standalone",
|
| 28 |
+
"label": "Standalone VLA",
|
| 29 |
+
"model": "Qwen3-VL-OFT \u00b7 40k"
|
| 30 |
+
},
|
| 31 |
+
{
|
| 32 |
+
"id": "kinex",
|
| 33 |
+
"label": "Kinex",
|
| 34 |
+
"model": "GPT-6 Astra / high"
|
| 35 |
+
},
|
| 36 |
+
{
|
| 37 |
+
"id": "kinex_policy",
|
| 38 |
+
"label": "Kinex + VLA",
|
| 39 |
+
"model": "GPT-6 Astra / high \u00b7 native run_policy"
|
| 40 |
+
}
|
| 41 |
+
],
|
| 42 |
+
"episodes": [
|
| 43 |
+
{
|
| 44 |
+
"id": "standalone-1",
|
| 45 |
+
"task": "1",
|
| 46 |
+
"condition": "standalone",
|
| 47 |
+
"status": "running"
|
| 48 |
+
},
|
| 49 |
+
{
|
| 50 |
+
"id": "kinex-1",
|
| 51 |
+
"task": "1",
|
| 52 |
+
"condition": "kinex",
|
| 53 |
+
"status": "running"
|
| 54 |
+
},
|
| 55 |
+
{
|
| 56 |
+
"id": "kinex_policy-1",
|
| 57 |
+
"task": "1",
|
| 58 |
+
"condition": "kinex_policy",
|
| 59 |
+
"status": "running"
|
| 60 |
+
},
|
| 61 |
+
{
|
| 62 |
+
"id": "standalone-2",
|
| 63 |
+
"task": "2",
|
| 64 |
+
"condition": "standalone",
|
| 65 |
+
"status": "pending"
|
| 66 |
+
},
|
| 67 |
+
{
|
| 68 |
+
"id": "kinex-2",
|
| 69 |
+
"task": "2",
|
| 70 |
+
"condition": "kinex",
|
| 71 |
+
"status": "pending"
|
| 72 |
+
},
|
| 73 |
+
{
|
| 74 |
+
"id": "kinex_policy-2",
|
| 75 |
+
"task": "2",
|
| 76 |
+
"condition": "kinex_policy",
|
| 77 |
+
"status": "pending"
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"id": "standalone-3",
|
| 81 |
+
"task": "3",
|
| 82 |
+
"condition": "standalone",
|
| 83 |
+
"status": "pending"
|
| 84 |
+
},
|
| 85 |
+
{
|
| 86 |
+
"id": "kinex-3",
|
| 87 |
+
"task": "3",
|
| 88 |
+
"condition": "kinex",
|
| 89 |
+
"status": "pending"
|
| 90 |
+
},
|
| 91 |
+
{
|
| 92 |
+
"id": "kinex_policy-3",
|
| 93 |
+
"task": "3",
|
| 94 |
+
"condition": "kinex_policy",
|
| 95 |
+
"status": "pending"
|
| 96 |
+
}
|
| 97 |
+
]
|
| 98 |
+
}
|
index.html
CHANGED
|
@@ -1,25 +1 @@
|
|
| 1 |
-
<!doctype html>
|
| 2 |
-
<html lang="en">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="utf-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
-
<meta name="description" content="Programmable VLA experiments: robot recordings, agent sessions, tool calls and measured usage.">
|
| 7 |
-
<meta name="theme-color" content="#756ee4">
|
| 8 |
-
<title>Programmable VLA — RLE-Bench</title>
|
| 9 |
-
<link rel="stylesheet" href="style.css">
|
| 10 |
-
<script src="app.js" defer></script>
|
| 11 |
-
</head>
|
| 12 |
-
<body>
|
| 13 |
-
<a class="skip" href="#main">Skip to results</a>
|
| 14 |
-
<header class="site-header"><div class="header-inner"><a class="brand" href="#B2/overview"><span class="brand-icon">P</span><strong>programVLA</strong><span class="brand-divider">/</span><span>experiments</span></a><nav><a href="#B2/overview">Results</a><a href="#protocol">Protocol</a><a href="https://forge.coreweave.com/wandb/programmable_vla" target="_blank" rel="noopener">W&B ↗</a></nav><a class="header-link" href="https://huggingface.co/spaces/RLE-Bench/programmable-vla/tree/main" target="_blank" rel="noopener">Hugging Face ↗</a></div></header>
|
| 15 |
-
<main id="main" tabindex="-1">
|
| 16 |
-
<section class="hero"><div><p class="eyebrow">AGENT × VISION-LANGUAGE-ACTION</p><h1>Programmable <span>VLA</span></h1><p>Compare execution, delegation and agent behavior.</p></div><div class="hero-facts"><div><strong>3</strong><span>valid episodes</span></div><div><strong>1</strong><span>LIBERO task</span></div><div><strong>0</strong><span>seed / init state</span></div></div></section>
|
| 17 |
-
<div id="methods" class="method-cards" aria-label="Select method"></div>
|
| 18 |
-
<section id="experiment"><div class="task-heading"><div><p class="eyebrow">LIBERO / SPATIAL-01</p><h2>Bowl between plate and ramekin → center of plate</h2></div><span class="pill">600 control steps</span></div><nav id="tabs" class="detail-nav" aria-label="Episode sections"></nav><div id="detail" aria-live="polite"><p class="loading">Loading recorded results…</p></div></section>
|
| 19 |
-
<details id="protocol" class="protocol panel"><summary>Protocol & sources</summary><div id="protocol-content"></div></details>
|
| 20 |
-
</main>
|
| 21 |
-
<footer><span>RLE-Bench · Programmable VLA</span><div><a href="https://rle-bench-programmable-vla.static.hf.space/probes/bridge-20261028/index.html">Bridge transfer probe ↗</a><a href="data/report.json">Results JSON</a><a href="data/manifest.json">File manifest</a><a href="https://huggingface.co/spaces/RLE-Bench/kinex-benchmark-native-budget-with-robobridge">Kinex benchmark ↗</a></div></footer>
|
| 22 |
-
<dialog id="image-viewer"><div class="viewer-toolbar"><span id="image-label">Recorded observation</span><a id="image-original" target="_blank" rel="noopener">Original ↗</a><button id="close-viewer" aria-label="Close image">×</button></div><img id="viewer-image" alt="Recorded robot observation"></dialog>
|
| 23 |
-
<noscript><p><a href="data/report.json">Download the result index.</a></p></noscript>
|
| 24 |
-
</body>
|
| 25 |
-
</html>
|
|
|
|
| 1 |
+
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="theme-color" content="#756ee4"><title>Programmable VLA — RLE-Bench</title><link rel="stylesheet" href="style.css"><script src="app.js" defer></script></head><body><a class="skip" href="#main">Skip to content</a><header><div class="header-inner"><a class="brand" href="#overview">programmable<span>/</span><b>vla</b></a><nav><a href="#overview">Overview</a><a href="#tasks">Explore tasks</a><a href="#protocol">Protocol</a></nav><a class="external" href="https://huggingface.co/spaces/RLE-Bench/programmable-vla">Hugging Face ↗</a></div></header><main id="main"><p>Loading experiments…</p></main><footer><b>Programmable VLA</b><span>by RLE-Bench</span><a href="data.json">Results JSON</a><a href="manifest.json">Artifact manifest</a></footer></body></html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
manifest.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"files": {
|
| 3 |
+
"app.js": {
|
| 4 |
+
"bytes": 8878,
|
| 5 |
+
"sha256": "8429ad1235aa238a37d76a15ade2e1fbaa4eca1d573c99d6dc371403835480c9"
|
| 6 |
+
},
|
| 7 |
+
"README.md": {
|
| 8 |
+
"bytes": 321,
|
| 9 |
+
"sha256": "f57cb3993c5f2ed4aaa9a51f977138889b77cd9969617b85f49e27ff93dc6df0"
|
| 10 |
+
},
|
| 11 |
+
"sources.json": {
|
| 12 |
+
"bytes": 2232,
|
| 13 |
+
"sha256": "752c59a9e6e36a1aefd2401912d425c155402b0dc90622eff40278f4e4315a83"
|
| 14 |
+
},
|
| 15 |
+
"index.html": {
|
| 16 |
+
"bytes": 901,
|
| 17 |
+
"sha256": "c787bda4dcd8b664d4844e72a39ac6d2855bbbdbbe4b58cb317488b30aee86e3"
|
| 18 |
+
},
|
| 19 |
+
"data.json": {
|
| 20 |
+
"bytes": 1957,
|
| 21 |
+
"sha256": "3faf31ab4a47409fc9502556743b386690e24fbe177feab3eb81c64371490ec8"
|
| 22 |
+
},
|
| 23 |
+
"style.css": {
|
| 24 |
+
"bytes": 5015,
|
| 25 |
+
"sha256": "c9185472e4768289aa8bb101f9031f87988c3d03a7007a8467af90fd750a6117"
|
| 26 |
+
}
|
| 27 |
+
}
|
| 28 |
+
}
|
sources.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"protocol": {
|
| 3 |
+
"tasks": [
|
| 4 |
+
"robotwin/handover-block-aloha-agilex",
|
| 5 |
+
"robotwin/place-dual-shoes-aloha-agilex",
|
| 6 |
+
"robotwin/put-bottles-dustbin-aloha-agilex"
|
| 7 |
+
],
|
| 8 |
+
"selection_reason": "First three tasks in the existing task03 catalog order; frozen before new outcomes",
|
| 9 |
+
"baselines": [
|
| 10 |
+
"standalone",
|
| 11 |
+
"kinex",
|
| 12 |
+
"kinex_policy"
|
| 13 |
+
],
|
| 14 |
+
"model": "openai/gpt-6-astra",
|
| 15 |
+
"reasoning_effort": "high",
|
| 16 |
+
"endpoint": "openai/codex",
|
| 17 |
+
"checkpoint": "StarVLA/Qwen3-VL-OFT-Robotwin2",
|
| 18 |
+
"revision": "e9cdfc38a0db968bf3a865bcb542d3d455952226",
|
| 19 |
+
"checkpoint_file": "checkpoints/steps_40000_pytorch_model.pt",
|
| 20 |
+
"seeds": "inherit task03",
|
| 21 |
+
"control_hz": 25,
|
| 22 |
+
"standalone_max_actions": 16,
|
| 23 |
+
"episodes_per_task": 1,
|
| 24 |
+
"retries_of_valid_outcomes": 0,
|
| 25 |
+
"status": "implementation"
|
| 26 |
+
},
|
| 27 |
+
"images": {
|
| 28 |
+
"simulator": "sha256:76f216ea6cb3aa2bbfbc705fe0e6bd18e9952f1af23b1fec3b424308162416a3",
|
| 29 |
+
"task-owner": "sha256:6328c4b92b6d6d18c936b30c317ea0e45e00a9284eff2de7a0b324ce29a49b5e",
|
| 30 |
+
"agent-base": "sha256:a00a70c778ef42dce0b33ff22b1dec8da11309ddac675880b9da20b47aaff4ab",
|
| 31 |
+
"policy-images": "sha256:b68c21e960150c9dabaefa8736b89638e0884d5ca008f36feadf90433e09426f",
|
| 32 |
+
"policy-contract": "sha256:50fef70af05ca772d59f6ddf3d47cfd39b38798a55dc7c2e6b7dfd872a9b238f"
|
| 33 |
+
},
|
| 34 |
+
"sources": {
|
| 35 |
+
"kinex": {
|
| 36 |
+
"revision": "f4ab59e9e93aa2f569d88386799a2bed0670d59c",
|
| 37 |
+
"content_sha256": "d94724a0ddffe36dd713844e78ddfd03069d1f03a9f210e59c39ad7df1b083e3"
|
| 38 |
+
},
|
| 39 |
+
"rosbridge": {
|
| 40 |
+
"revision": "fb5347cdf04404fcecea5ecdff505bb038551082",
|
| 41 |
+
"content_sha256": "b8e1522c9538d42493a22ec1b794a825d65006f8a97454b20d22fd7a0e688c40",
|
| 42 |
+
"note": "Frozen standard task03 provider; Plus development is a separate suite."
|
| 43 |
+
},
|
| 44 |
+
"programvla": {
|
| 45 |
+
"revision": "d119fb57696dace85abe3aedc9edd1db12068516",
|
| 46 |
+
"wheel_sha256": "4e68938c169ab24ca73d8ed2d7122b3fcc8c0f0a94103052f52bb6bc28046d73"
|
| 47 |
+
},
|
| 48 |
+
"rlebench": {
|
| 49 |
+
"revision": "143a3522000d840a493202d247c0105b88a8b717",
|
| 50 |
+
"wheel_sha256": "ba45e87637a50b2eb58440dd7435ec7b25d11a71d68ca18c87fba6161c4bef58"
|
| 51 |
+
},
|
| 52 |
+
"starvla": {
|
| 53 |
+
"revision": "985c2238627481f25476fbee478083812dd82a21"
|
| 54 |
+
}
|
| 55 |
+
}
|
| 56 |
+
}
|
style.css
CHANGED
|
@@ -1,5 +1 @@
|
|
| 1 |
-
:root{
|
| 2 |
-
*{box-sizing:border-box}body{margin:0}a{color:inherit;text-decoration:none}a:hover{color:var(--purple-dark)}button,input,select{font:inherit}button{cursor:pointer;color:inherit;border:0;background:none}button,a,input,select,summary{touch-action:manipulation}button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible,summary:focus-visible{outline:3px solid #b7b2ff;outline-offset:3px}h1,h2,h3,p{margin:0}h1,h2,h3{letter-spacing:-.035em}h1{font-size:43px;font-weight:680;line-height:1.13}h2{font-size:21px;font-weight:650}h3{font-size:15px;font-weight:650}p{line-height:1.65}code,pre{font-family:ui-monospace,SFMono-Regular,Consolas,monospace}pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.65;font-size:12px;font-variant-ligatures:none;max-height:540px;overflow:auto}p,code{overflow-wrap:anywhere}[hidden]{display:none!important}.skip{position:absolute;top:-80px;background:#fff;padding:12px;z-index:100}.skip:focus{top:0}.site-header{background:#fffffff2;border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20;backdrop-filter:blur(12px)}.header-inner{max-width:1440px;margin:auto;padding:0 46px;min-height:76px;display:flex;align-items:center;gap:30px}.brand{display:flex;align-items:center;gap:11px;margin-right:auto;white-space:nowrap;font-size:15px}.brand strong{font-size:22px;letter-spacing:-.8px}.brand-icon{display:grid;place-items:center;background:var(--purple);color:white;width:33px;height:33px;border-radius:9px;font-size:23px;font-weight:750}.brand-divider{color:#d3d4df;font-size:22px}.header-inner nav{display:flex;gap:25px;font-size:12px;color:var(--muted)}.header-link{font-size:11px;border-left:1px solid var(--line);padding-left:25px;color:var(--muted)}main{max-width:1440px;padding:34px 46px 45px;margin:auto;min-height:75vh;outline:none}.eyebrow{font-size:10px;letter-spacing:1.45px;font-weight:650;color:var(--purple);line-height:1.5;text-transform:uppercase}.hero{display:flex;align-items:center;justify-content:space-between;gap:30px;margin:4px 0 30px}.hero .eyebrow{margin-bottom:12px}.hero h1 span{color:var(--purple)}.hero p:not(.eyebrow){color:var(--muted);margin-top:12px}.hero-facts{display:flex;text-align:center;gap:0}.hero-facts>div{padding:0 25px;border-left:1px solid var(--line)}.hero-facts>div:first-child{border:0}.hero-facts strong{display:block;font-size:29px;font-weight:600}.hero-facts span{font-size:11px;color:var(--muted)}.method-cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}.method-card{position:relative;display:block;border:1px solid var(--line);border-radius:var(--radius);background:#fff;padding:19px 21px;overflow:hidden;box-shadow:0 3px 5px #29274903;text-align:left;transition:border-color .15s,box-shadow .15s}.method-card:before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:var(--variant)}.method-card.active{border-color:var(--variant);box-shadow:0 0 0 1px var(--variant)}.method-card:hover{color:inherit;box-shadow:0 5px 17px #3029660c}.card-header{display:flex;align-items:center;justify-content:space-between;gap:10px}.method-label{font-weight:650;font-size:15px}.method-id{font-size:11px;color:var(--variant);margin-right:8px}.badge{font-size:10px;border-radius:20px;background:#eaf5ef;color:var(--green);padding:4px 9px;white-space:nowrap}.badge.fail{background:#fcf0ed;color:var(--red)}.card-model{font-size:11px;color:var(--muted);margin-top:8px}.card-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:17px}.card-stats strong{display:block;font-size:18px;letter-spacing:-.5px;font-weight:600;font-variant-numeric:tabular-nums}.card-stats span{font-size:10px;color:var(--muted)}.task-heading{display:flex;align-items:center;justify-content:space-between;gap:20px;margin:34px 0 20px}.task-heading .eyebrow{margin-bottom:7px}.task-heading h2{font-size:22px}.pill{font-size:11px;color:var(--muted);border:1px solid var(--line);padding:6px 10px;border-radius:6px;white-space:nowrap}.detail-nav{display:flex;gap:24px;align-items:center;border-bottom:1px solid var(--line);margin-bottom:22px;overflow:auto;white-space:nowrap}.detail-nav a{padding:0 0 13px;font-size:12px;color:var(--muted);border-bottom:2px solid transparent}.detail-nav a.active{color:var(--purple-dark);border-color:var(--purple);font-weight:650}.detail-nav small{font-size:10px;margin-left:5px;background:#eceef5;padding:2px 5px;border-radius:4px}.panel{background:#fff;border:1px solid var(--line);border-radius:var(--radius);padding:22px}.episode-layout{display:grid;grid-template-columns:minmax(0,1fr) 295px;gap:20px;align-items:stretch}.video-panel{border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;background:#fff;display:flex;flex-direction:column}.video-caption,.video-toolbar{display:flex;align-items:center;justify-content:space-between;padding:11px 16px;font-size:11px;color:var(--muted);gap:12px}.video-caption{border-bottom:1px solid var(--line)}video{width:100%;display:block;aspect-ratio:2/1;background:#17191d}.video-toolbar{margin-top:auto}.video-toolbar>div{display:flex;gap:8px}.video-toolbar label{display:flex;align-items:center;gap:8px}.video-toolbar select{font-size:11px}.button{display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--line);background:#fff;border-radius:6px;padding:7px 11px;font-size:11px;gap:6px}.button:hover{background:var(--lavender);color:var(--purple-dark)}select,input{border:1px solid var(--line);border-radius:6px;background:#fff;padding:8px 10px;color:var(--ink);font-size:12px}select{max-width:100%}.result-head{display:flex;justify-content:space-between;align-items:center}.result-number{font-size:35px;letter-spacing:-1px;font-weight:650;margin-top:18px;line-height:1.3}.result-number span{font-size:12px;color:var(--muted);letter-spacing:0;font-weight:400}.completion-track{background:#eceef6;border-radius:6px;height:5px;overflow:hidden;margin:12px 0 20px}.completion-track span{display:block;height:100%;background:var(--purple)}.facts{display:grid;grid-template-columns:1fr auto;gap:10px;font-size:12px;margin:0}.facts dt{color:var(--muted)}.facts dd{margin:0;font-variant-numeric:tabular-nums;text-align:right}.metric-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin:18px 0}.metric{padding:18px 20px;background:#fff;border:1px solid var(--line);border-radius:10px}.metric strong{display:block;font-size:23px;font-weight:600;letter-spacing:-.7px;font-variant-numeric:tabular-nums}.metric span{display:block;font-size:11px;color:var(--muted);margin-top:5px}.observation{display:flex;align-items:baseline;gap:18px;font-size:13px;margin:20px 0 0}.observation span{color:var(--muted)}.panel-heading{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:18px}.panel-heading h2{font-size:18px}.links{display:flex;gap:14px;flex-wrap:wrap;font-size:12px;color:var(--purple-dark)}.instruction{font-size:17px;line-height:1.7;max-width:900px}.instruction-full{margin-top:20px}details summary{cursor:pointer;font-size:13px}details[open]>summary{margin-bottom:14px}.code{background:#f6f7fa;border:1px solid #eef0f5;border-radius:7px;padding:16px}.session-toolbar{display:flex;gap:10px;align-items:center;margin-bottom:18px;flex-wrap:wrap}.session-toolbar input{flex:1;min-width:160px}.session-toolbar span{font-size:11px;color:var(--muted)}.event{border:1px solid var(--line);border-radius:8px;margin-top:10px;overflow:hidden}.event summary{display:flex;align-items:center;gap:12px;list-style:none;padding:13px 15px;font-size:12px;background:#fafbfe}.event summary::before{content:'›';color:var(--purple);font-size:18px}.event[open]>summary{margin-bottom:0}.event[open]>summary::before{transform:rotate(90deg)}.event .event-id{color:var(--muted);font-size:10px;font-variant-numeric:tabular-nums}.event .event-name{font-weight:600}.event .event-preview{color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}.event-body{padding:16px;display:grid;gap:14px}.event-body h3{font-size:12px}.event-body img{display:block;max-width:100%;max-height:320px;object-fit:contain;cursor:zoom-in}.session-more{margin-top:18px;text-align:center}.io-grid{display:grid;grid-template-columns:1fr 1fr;gap:18px}.io-grid h3{margin-bottom:10px}.image-pair{display:grid;grid-template-columns:1fr 1fr;gap:15px;margin:16px 0}.image-pair figure{margin:0}.image-pair img{width:100%;max-width:360px;cursor:zoom-in;border-radius:6px}.image-pair figcaption{font-size:11px;color:var(--muted);margin-top:4px}.section-gap{margin-top:20px}.artifact-list{display:grid;grid-template-columns:280px minmax(0,1fr);gap:20px}.artifact-nav{display:flex;flex-direction:column;gap:6px}.artifact-nav button{padding:11px;text-align:left;border:1px solid var(--line);border-radius:6px;font-size:11px;overflow-wrap:anywhere}.artifact-nav button.active{background:var(--lavender);border-color:#c9c5f4;color:var(--purple-dark)}.data-table{width:100%;border-collapse:collapse;font-size:12px}.data-table th{text-align:left;color:var(--muted);font-weight:500;background:#f8f9fc}.data-table td,.data-table th{padding:12px 14px;border-bottom:1px solid var(--line)}.data-table td:not(:first-child),.data-table th:not(:first-child){text-align:right;font-variant-numeric:tabular-nums}.table-wrap{overflow:auto}.caption{font-size:11px;color:var(--muted);margin-top:14px;line-height:1.6}.protocol{margin-top:28px;scroll-margin-top:100px}.protocol summary{font-weight:600}.protocol p{font-size:13px;margin-top:12px;max-width:950px}.protocol .links{margin-top:16px}.loading{padding:45px;text-align:center;color:var(--muted)}.empty{padding:28px;color:var(--muted);font-size:13px;text-align:center}.error{padding:16px;background:#fcf0ed;color:var(--red);border-radius:6px}.gallery{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}.gallery img{width:100%;cursor:zoom-in}.gallery figure{margin:0}.gallery figcaption{font-size:11px;color:var(--muted)}footer{max-width:1440px;margin:auto;padding:24px 46px 35px;border-top:1px solid var(--line);display:flex;justify-content:space-between;gap:20px;font-size:11px;color:var(--muted)}footer>div{display:flex;gap:18px;flex-wrap:wrap}dialog{border:1px solid var(--line);border-radius:12px;padding:18px;max-width:94vw;max-height:94vh}dialog::backdrop{background:#131625bb;backdrop-filter:blur(4px)}.viewer-toolbar{display:flex;gap:25px;align-items:center;margin-bottom:12px;font-size:12px}.viewer-toolbar span{margin-right:auto}.viewer-toolbar button{font-size:25px}dialog>img{max-width:86vw;max-height:77vh;object-fit:contain;display:block}#experiment{scroll-margin-top:96px}
|
| 3 |
-
@media(max-width:1000px){.header-inner,main,footer{padding-left:26px;padding-right:26px}.header-inner{gap:20px}.header-link{display:none}.hero-facts>div{padding:0 16px}.episode-layout{grid-template-columns:minmax(0,1fr) 240px}.result-panel{padding:18px}.method-card{padding:16px}.method-label{font-size:14px}.card-stats strong{font-size:16px}.detail-nav{gap:20px}.artifact-list{grid-template-columns:220px minmax(0,1fr)}}
|
| 4 |
-
@media(max-width:720px){.header-inner,main,footer{padding-left:18px;padding-right:18px}.header-inner{min-height:65px}.brand>span:last-child,.brand-divider{display:none}.brand strong{font-size:19px}.header-inner nav{gap:14px;font-size:11px}.hero{align-items:flex-start;flex-direction:column;gap:20px;margin-bottom:24px}h1{font-size:35px}.hero-facts{width:100%;justify-content:space-between}.hero-facts>div{flex:1;padding:0 10px}.hero-facts strong{font-size:25px}.method-cards{grid-template-columns:1fr;gap:10px}.method-card{padding:13px 16px}.card-stats{margin-top:10px}.card-model{margin-top:4px}.card-stats strong{font-size:17px}.task-heading{margin-top:25px;gap:10px}.task-heading h2{font-size:19px}.task-heading>.pill{display:none}.detail-nav{gap:19px}.episode-layout{grid-template-columns:1fr}.result-panel .facts{grid-template-columns:1fr 1fr}.result-number{margin-top:12px}.metric-grid{grid-template-columns:1fr 1fr;gap:10px}.metric{padding:14px}.metric strong{font-size:21px}.observation{display:block}.observation strong{display:block;margin-bottom:7px}.panel{padding:17px}.panel-heading{align-items:flex-start}.panel-heading h2{font-size:16px}.io-grid{grid-template-columns:1fr}.artifact-list{grid-template-columns:1fr}.artifact-nav{flex-direction:row;overflow:auto}.artifact-nav button{min-width:170px}.image-pair{gap:10px}.gallery{grid-template-columns:1fr 1fr}.video-toolbar{padding:10px}.video-toolbar>div{gap:5px}.video-toolbar .button{padding:6px}.event summary{padding:10px;gap:8px}.event-preview{display:none}.event-body{padding:12px}.session-toolbar input{min-width:130px}.data-table td,.data-table th{padding:10px 8px}footer{flex-direction:column}main{padding-top:24px}}
|
| 5 |
-
@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto!important;transition:none!important}}
|
|
|
|
| 1 |
+
:root{--bg:#f7f8fb;--ink:#272b34;--muted:#687083;--line:#e5e7ef;--accent:#756ee4;--soft:#efedfc}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.6 Inter,ui-sans-serif,system-ui,sans-serif}a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}button,input,select{font:inherit}button,select{cursor:pointer}button,a,select,input{outline-offset:4px}header{background:#fff;border-bottom:1px solid var(--line)}.header-inner{max-width:1280px;padding:21px 32px;margin:auto;display:flex;gap:42px;align-items:center}.brand{font-size:20px;font-weight:700;color:var(--ink);white-space:nowrap}.brand span{color:#b7b4c4;padding:0 11px}.brand b{font-weight:500;color:var(--muted)}nav{display:flex;gap:24px}nav a{color:var(--muted)}.external{margin-left:auto;font-size:13px}main{max-width:1216px;min-height:78vh;margin:auto;padding:40px 0 56px}h1{font-size:34px;line-height:1.2;letter-spacing:-1px;margin:6px 0 12px}h2{font-size:20px;line-height:1.35;margin:0 0 16px}h3{font-size:16px;margin:0 0 8px}p{margin:8px 0 18px}.muted,.subtle{color:var(--muted)}.eyebrow{text-transform:uppercase;letter-spacing:1.6px;font-size:11px;font-weight:700;color:var(--accent)}.cards{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin:28px 0}.card,.panel{background:#fff;border:1px solid var(--line);border-radius:14px;padding:24px}.card .value{font-size:36px;line-height:1.3;font-weight:650;margin-top:15px}.card .label{font-size:13px;color:var(--muted)}.card .meta{display:flex;gap:20px;margin-top:16px;font-size:13px;color:var(--muted)}.panel{margin:24px 0}.toolbar,.row{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.toolbar{margin:24px 0}.toolbar select,.toolbar input{background:#fff;border:1px solid var(--line);border-radius:8px;padding:10px 14px;color:var(--ink)}.toolbar input{margin-left:auto;max-width:100%}.table-wrap{overflow-x:auto}table{border-collapse:collapse;width:100%;font-size:14px}th{text-align:left;color:var(--muted);font-size:12px;font-weight:600;padding:13px;border-bottom:1px solid var(--line)}td{padding:18px 13px;border-bottom:1px solid var(--line)}tr:last-child td{border-bottom:0}.badge{display:inline-flex;gap:7px;align-items:center;border-radius:20px;padding:5px 11px;font-size:12px;background:#eff1f6;color:#687083;white-space:nowrap}.badge:before{content:'';height:6px;width:6px;border-radius:50%;background:currentColor}.badge.success{color:#27847a;background:#eaf6f2}.badge.failure{color:#b16b40;background:#fff2e8}.badge.invalid{color:#b94c69;background:#fcecf1}.badge.running{color:var(--accent);background:var(--soft)}.tabs{display:flex;gap:24px;border-bottom:1px solid var(--line);margin:26px 0 22px;overflow-x:auto;white-space:nowrap}.tabs a{padding:10px 0;color:var(--muted);border-bottom:2px solid transparent}.tabs a.active{color:var(--accent);border-color:var(--accent)}.video{width:100%;aspect-ratio:2;background:#161922;border-radius:10px;display:block}.empty{padding:80px 20px;text-align:center;color:var(--muted);background:#f2f3f8;border-radius:10px}.metrics{display:grid;grid-template-columns:repeat(5,1fr);gap:15px;margin-top:22px}.metric b{display:block;font-size:21px;font-weight:600}.metric span{font-size:12px;color:var(--muted)}pre{white-space:pre-wrap;overflow-wrap:anywhere;max-height:600px;overflow:auto;background:#f7f8fb;border:1px solid var(--line);border-radius:8px;padding:16px;font:12px/1.65 ui-monospace,monospace}details{background:#fff;border:1px solid var(--line);border-radius:10px;margin:12px 0;padding:16px}summary{cursor:pointer;overflow-wrap:anywhere}.text{white-space:pre-wrap;overflow-wrap:anywhere}.images{display:flex;gap:10px;flex-wrap:wrap;margin:14px 0}.images img{max-width:30%;border-radius:8px}.message{border-left:3px solid #ddd9f8;margin:16px 0;padding:12px 18px;background:#fff;border-radius:0 9px 9px 0}.message b{font-size:12px;color:var(--accent);text-transform:uppercase}.message .text{margin-top:8px;font-size:14px}.files a{display:block;padding:9px 0;border-bottom:1px solid var(--line);overflow-wrap:anywhere}.note{font-size:12px;color:var(--muted);margin-top:12px}footer{max-width:1216px;margin:auto;padding:24px 0;border-top:1px solid var(--line);display:flex;gap:20px;color:var(--muted);font-size:12px}footer b{color:var(--ink)}footer a:first-of-type{margin-left:auto}.skip{position:absolute;left:-1000px}.skip:focus{left:10px;top:10px;z-index:2;background:white;padding:8px}@media(max-width:1270px){main,footer{margin:0 28px}}@media(max-width:760px){.header-inner{padding:16px 20px;gap:14px;flex-wrap:wrap}.brand{font-size:18px}.external{display:none}nav{gap:17px;font-size:13px}main{padding-top:28px;margin:0 18px}h1{font-size:28px}.cards{grid-template-columns:1fr;gap:12px}.card{padding:18px}.card .value{font-size:30px}.panel{padding:18px}.metrics{grid-template-columns:repeat(2,1fr)}.tabs{gap:18px}.toolbar select{max-width:100%}footer{flex-wrap:wrap;margin:0 18px}footer a:first-of-type{margin-left:0}.images img{max-width:100%}.table-wrap{margin:0 -8px}}
|
|
|
|
|
|
|
|
|
|
|
|