yuvin-labs's picture
Build ConsequenceBench public explorer
5c30572 verified
Raw
History Blame Contribute Delete
29.9 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Explore ConsequenceBench scenarios and development results.">
<title>ConsequenceBench Explorer</title>
<style>
:root {
color-scheme: light;
--bg: #f3f5f7;
--surface: #ffffff;
--surface-subtle: #f8f9fb;
--text: #101828;
--muted: #5f6b7a;
--border: #d7dde5;
--border-strong: #b8c1cc;
--blue: #2457d6;
--blue-soft: #eaf0ff;
--red: #b42318;
--red-soft: #fdeceb;
--green: #16794b;
--green-soft: #e8f6ef;
--amber: #9a5b00;
--amber-soft: #fff4dc;
--focus: #7aa2ff;
--radius: 6px;
--mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
--sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
min-width: 320px;
background: var(--bg);
color: var(--text);
font-family: var(--sans);
font-size: 15px;
line-height: 1.5;
}
button,
input,
select {
font: inherit;
}
a {
color: var(--blue);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
button,
input,
select,
a {
outline: none;
}
button:focus-visible,
input:focus-visible,
select:focus-visible,
a:focus-visible {
box-shadow: 0 0 0 3px var(--focus);
}
.topbar {
min-height: 64px;
border-bottom: 1px solid var(--border);
background: var(--surface);
}
.topbar-inner {
width: min(1440px, 100%);
min-height: 64px;
margin: 0 auto;
padding: 0 24px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 24px;
}
.brand {
display: flex;
align-items: baseline;
gap: 12px;
min-width: 0;
}
.brand-name {
color: var(--text);
font-size: 20px;
font-weight: 760;
white-space: nowrap;
}
.brand-label {
color: var(--blue);
font-family: var(--mono);
font-size: 12px;
font-weight: 700;
letter-spacing: 1px;
text-transform: uppercase;
}
.toplinks {
display: flex;
align-items: center;
gap: 18px;
white-space: nowrap;
}
.toplinks a {
color: var(--muted);
font-size: 14px;
font-weight: 650;
}
.status-strip {
border-bottom: 1px solid #ead3a7;
background: var(--amber-soft);
color: #603700;
font-size: 13px;
}
.status-strip-inner {
width: min(1440px, 100%);
margin: 0 auto;
padding: 9px 24px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
}
.status-strip strong {
font-family: var(--mono);
font-size: 12px;
letter-spacing: 0;
}
.shell {
width: min(1440px, 100%);
margin: 0 auto;
padding: 24px;
}
.overview {
display: grid;
grid-template-columns: minmax(300px, 1.8fr) repeat(4, minmax(120px, 0.65fr));
border: 1px solid var(--border);
background: var(--surface);
}
.overview-intro {
min-height: 126px;
padding: 22px 24px;
border-right: 1px solid var(--border);
}
.eyebrow {
margin: 0 0 9px;
color: var(--blue);
font-family: var(--mono);
font-size: 12px;
font-weight: 700;
letter-spacing: 1px;
text-transform: uppercase;
}
h1 {
margin: 0 0 8px;
font-size: 27px;
line-height: 1.2;
letter-spacing: 0;
}
.overview-intro p {
max-width: 650px;
margin: 0;
color: var(--muted);
}
.metric {
min-height: 126px;
padding: 22px 18px;
border-right: 1px solid var(--border);
display: flex;
flex-direction: column;
justify-content: center;
}
.metric:last-child {
border-right: 0;
}
.metric-value {
font-family: var(--mono);
font-size: 29px;
font-weight: 760;
line-height: 1;
}
.metric-label {
margin-top: 9px;
color: var(--muted);
font-size: 13px;
}
.workspace {
margin-top: 18px;
display: grid;
grid-template-columns: 260px minmax(0, 1fr);
gap: 18px;
align-items: start;
}
.filters {
border: 1px solid var(--border);
background: var(--surface);
}
.filters-header,
.panel-header {
min-height: 48px;
padding: 0 16px;
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.filters-header h2,
.panel-header h2 {
margin: 0;
font-size: 14px;
font-weight: 740;
letter-spacing: 0;
}
.filter-form {
padding: 16px;
}
.field {
margin-bottom: 15px;
}
.field:last-child {
margin-bottom: 0;
}
label {
display: block;
margin-bottom: 6px;
color: var(--muted);
font-family: var(--mono);
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
}
input,
select {
width: 100%;
min-height: 38px;
border: 1px solid var(--border-strong);
border-radius: var(--radius);
background: var(--surface);
color: var(--text);
padding: 7px 10px;
}
.filter-summary {
padding: 12px 16px;
border-top: 1px solid var(--border);
background: var(--surface-subtle);
color: var(--muted);
font-size: 13px;
}
.main-panel {
min-width: 0;
border: 1px solid var(--border);
background: var(--surface);
}
.tabs {
min-height: 48px;
border-bottom: 1px solid var(--border);
display: flex;
align-items: stretch;
overflow-x: auto;
}
.tab {
min-width: 132px;
border: 0;
border-right: 1px solid var(--border);
background: var(--surface-subtle);
color: var(--muted);
padding: 0 18px;
cursor: pointer;
font-size: 14px;
font-weight: 680;
}
.tab[aria-selected="true"] {
background: var(--surface);
color: var(--blue);
box-shadow: inset 0 -3px 0 var(--blue);
}
.tab-panel {
display: none;
}
.tab-panel.active {
display: block;
}
.table-wrap {
width: 100%;
overflow-x: auto;
}
table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
th {
height: 42px;
border-bottom: 1px solid var(--border);
background: var(--surface-subtle);
color: var(--muted);
font-family: var(--mono);
font-size: 11px;
font-weight: 700;
text-align: left;
text-transform: uppercase;
}
th,
td {
padding: 10px 14px;
vertical-align: middle;
}
td {
border-bottom: 1px solid #e8ecf1;
color: #273444;
font-size: 13px;
}
tbody tr {
cursor: pointer;
}
tbody tr:hover,
tbody tr.selected {
background: #f1f5ff;
}
.scenario-id,
.mono {
font-family: var(--mono);
}
.scenario-id {
color: var(--blue);
font-weight: 700;
}
.title-cell {
color: var(--text);
font-weight: 680;
overflow-wrap: anywhere;
}
.badge {
display: inline-flex;
min-height: 23px;
align-items: center;
border: 1px solid var(--border);
border-radius: 999px;
background: var(--surface-subtle);
padding: 2px 8px;
color: var(--muted);
font-family: var(--mono);
font-size: 11px;
font-weight: 700;
white-space: nowrap;
}
.badge.red {
border-color: #f0b8b3;
background: var(--red-soft);
color: var(--red);
}
.badge.green {
border-color: #b6ddca;
background: var(--green-soft);
color: var(--green);
}
.badge.blue {
border-color: #bfd0ff;
background: var(--blue-soft);
color: var(--blue);
}
.empty,
.loading,
.error {
padding: 42px 24px;
color: var(--muted);
text-align: center;
}
.error {
color: var(--red);
}
.detail {
display: grid;
grid-template-columns: 1.2fr 1fr;
border-top: 1px solid var(--border);
background: var(--surface-subtle);
}
.detail-copy,
.detail-facts {
padding: 20px;
}
.detail-copy {
border-right: 1px solid var(--border);
}
.detail h3 {
margin: 0 0 7px;
font-size: 19px;
letter-spacing: 0;
}
.detail-note {
margin: 12px 0 0;
color: var(--muted);
font-size: 13px;
}
.fact-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 14px 18px;
}
.fact dt {
margin: 0 0 3px;
color: var(--muted);
font-family: var(--mono);
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
}
.fact dd {
margin: 0;
overflow-wrap: anywhere;
color: var(--text);
font-size: 13px;
font-weight: 620;
}
.leaderboard-intro,
.method {
padding: 20px;
}
.leaderboard-intro {
border-bottom: 1px solid var(--border);
background: var(--amber-soft);
color: #603700;
font-size: 13px;
}
.leaderboard-table tbody tr {
cursor: default;
}
.number {
font-family: var(--mono);
font-weight: 700;
text-align: right;
}
.method {
max-width: 980px;
}
.method h3 {
margin: 0 0 6px;
font-size: 18px;
}
.method p {
margin: 0 0 18px;
color: var(--muted);
}
.method-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
border: 1px solid var(--border);
}
.method-item {
min-height: 155px;
padding: 18px;
border-right: 1px solid var(--border);
}
.method-item:last-child {
border-right: 0;
}
.method-item strong {
display: block;
margin-bottom: 8px;
}
.method-item span {
color: var(--muted);
font-size: 13px;
}
.hard-counters {
margin-top: 18px;
border: 1px solid #f0b8b3;
background: var(--red-soft);
padding: 16px 18px;
}
.hard-counters strong {
color: var(--red);
}
.footer {
width: min(1440px, 100%);
margin: 0 auto;
padding: 8px 24px 28px;
color: var(--muted);
font-size: 12px;
}
@media (max-width: 1050px) {
.overview {
grid-template-columns: repeat(4, 1fr);
}
.overview-intro {
grid-column: 1 / -1;
border-right: 0;
border-bottom: 1px solid var(--border);
}
.workspace {
grid-template-columns: 1fr;
}
.filter-form {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 12px;
}
.field {
margin: 0;
}
}
@media (max-width: 760px) {
.topbar-inner,
.status-strip-inner,
.shell {
padding-left: 16px;
padding-right: 16px;
}
.topbar-inner {
align-items: flex-start;
flex-direction: column;
padding-top: 14px;
padding-bottom: 14px;
}
.toplinks {
width: 100%;
overflow-x: auto;
}
.status-strip-inner {
align-items: flex-start;
flex-direction: column;
gap: 4px;
}
.overview {
grid-template-columns: repeat(2, 1fr);
}
.metric:nth-child(3) {
border-right: 0;
}
.metric:nth-child(4),
.metric:nth-child(5) {
border-top: 1px solid var(--border);
}
.filter-form {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.detail,
.method-grid {
grid-template-columns: 1fr;
}
.detail-copy,
.method-item {
border-right: 0;
border-bottom: 1px solid var(--border);
}
.method-item:last-child {
border-bottom: 0;
}
}
@media (max-width: 480px) {
.brand {
align-items: flex-start;
flex-direction: column;
gap: 2px;
}
.overview,
.filter-form,
.fact-grid {
grid-template-columns: 1fr;
}
.metric {
min-height: 96px;
border-right: 0;
border-top: 1px solid var(--border);
}
.overview-intro {
min-height: auto;
}
}
</style>
</head>
<body>
<header class="topbar">
<div class="topbar-inner">
<div class="brand">
<a class="brand-name" href="https://github.com/yuvin-labs/consequencebench" target="_blank" rel="noreferrer">ConsequenceBench</a>
<span class="brand-label">Public Explorer</span>
</div>
<nav class="toplinks" aria-label="Benchmark links">
<a href="https://github.com/yuvin-labs/consequencebench" target="_blank" rel="noreferrer">GitHub</a>
<a href="https://huggingface.co/datasets/yuvin-labs/consequencebench" target="_blank" rel="noreferrer">Dataset</a>
<a href="https://github.com/yuvin-labs/consequencebench/blob/main/docs/RUN_A_CANDIDATE.md" target="_blank" rel="noreferrer">Run an agent</a>
<a href="https://github.com/yuvin-labs/consequencebench/discussions" target="_blank" rel="noreferrer">Discuss</a>
</nav>
</div>
</header>
<div class="status-strip">
<div class="status-strip-inner">
<span><strong>DEVELOPMENT_PREVIEW_NOT_QUALIFIED</strong></span>
<span>All public effects are simulated. Published runs are self-reported development evidence.</span>
</div>
</div>
<main class="shell">
<section class="overview" aria-labelledby="overview-title">
<div class="overview-intro">
<p class="eyebrow">Agent consequence evaluation</p>
<h1 id="overview-title">Did the agent leave the external system correct?</h1>
<p>Inspect public scenario identities, causal families, oracle bindings, and recorded development runs.</p>
</div>
<div class="metric">
<span class="metric-value">100</span>
<span class="metric-label">Scenario identities</span>
</div>
<div class="metric">
<span class="metric-value">300</span>
<span class="metric-label">Lifecycle worlds</span>
</div>
<div class="metric">
<span class="metric-value">5</span>
<span class="metric-label">Operational domains</span>
</div>
<div class="metric">
<span class="metric-value">70</span>
<span class="metric-label">Unsafe-action opportunities</span>
</div>
</section>
<div class="workspace">
<aside class="filters" aria-labelledby="filters-title">
<div class="filters-header">
<h2 id="filters-title">Scenario filters</h2>
</div>
<form class="filter-form" id="filters">
<div class="field">
<label for="search">Search</label>
<input id="search" type="search" placeholder="ID or title">
</div>
<div class="field">
<label for="domain">Domain</label>
<select id="domain">
<option value="">All domains</option>
</select>
</div>
<div class="field">
<label for="lens">Governance lens</label>
<select id="lens">
<option value="">All lenses</option>
</select>
</div>
<div class="field">
<label for="outcome">Catalog baseline</label>
<select id="outcome">
<option value="">All outcomes</option>
</select>
</div>
</form>
<div class="filter-summary" id="filter-summary">Loading scenarios...</div>
</aside>
<section class="main-panel">
<div class="tabs" role="tablist" aria-label="Explorer views">
<button class="tab" role="tab" aria-selected="true" aria-controls="scenarios-panel" id="scenarios-tab">Scenarios</button>
<button class="tab" role="tab" aria-selected="false" aria-controls="runs-panel" id="runs-tab">Development runs</button>
<button class="tab" role="tab" aria-selected="false" aria-controls="method-panel" id="method-tab">Method and limits</button>
</div>
<div class="tab-panel active" id="scenarios-panel" role="tabpanel" aria-labelledby="scenarios-tab">
<div id="scenario-content" class="loading">Loading the canonical scenario catalog...</div>
<div id="scenario-detail"></div>
</div>
<div class="tab-panel" id="runs-panel" role="tabpanel" aria-labelledby="runs-tab">
<div class="leaderboard-intro">
These rows are not official safety rankings. They are internally operated, self-reported development runs on simulated worlds. Compare dimensions separately.
</div>
<div id="leaderboard-content" class="loading">Loading development results...</div>
</div>
<div class="tab-panel" id="method-panel" role="tabpanel" aria-labelledby="method-tab">
<div class="method">
<p class="eyebrow">Study separation</p>
<h3>Three questions, three scorecards</h3>
<p>ConsequenceBench does not collapse agent capability, governance conformance, and incremental governance effect into one reward.</p>
<div class="method-grid">
<div class="method-item">
<strong>Direct agent capability</strong>
<span>An arbitrary agent investigates and acts in evaluator-owned worlds. The result measures the candidate, not a governance product.</span>
</div>
<div class="method-item">
<strong>Governance conformance</strong>
<span>A named governance build is tested against declared evidence, authorization, execution, readback, obligation, and compensation contracts.</span>
</div>
<div class="method-item">
<strong>Frozen-candidate incremental effect</strong>
<span>The same immutable candidate, model, tools, budgets, faults, and retries are replayed through direct and governed paths.</span>
</div>
</div>
<div class="hard-counters">
<strong>Hard failures stay visible.</strong>
Unsafe effects, duplicate effects, false verification, secret exposure, missing legitimate effects, and infrastructure failures cannot be hidden by an aggregate reward.
</div>
</div>
</div>
</section>
</div>
</main>
<footer class="footer">
Data source: yuvin-labs/consequencebench on Hugging Face. Catalog baseline outcomes and generated-world decisions are distinct contracts.
</footer>
<script>
const catalogUrl = "https://huggingface.co/datasets/yuvin-labs/consequencebench/resolve/main/data/scenario_catalog.v1.json";
const leaderboardUrl = "https://huggingface.co/datasets/yuvin-labs/consequencebench/resolve/main/data/development_leaderboard.v1.json";
const state = {
scenarios: [],
filtered: [],
selectedId: null,
leaderboard: null
};
const escapeHtml = (value) => String(value ?? "")
.replaceAll("&", "&amp;")
.replaceAll("<", "&lt;")
.replaceAll(">", "&gt;")
.replaceAll('"', "&quot;")
.replaceAll("'", "&#039;");
const titleCase = (value) => String(value ?? "")
.replaceAll("_", " ")
.replace(/\b\w/g, (letter) => letter.toUpperCase());
const badgeClass = (value) => {
const normalized = String(value ?? "").toUpperCase();
if (["DENIED", "CRITICAL", "EXECUTE"].includes(normalized)) return "red";
if (["PASS", "TRUE", "GOVERNED"].includes(normalized)) return "green";
return "blue";
};
async function fetchJson(url) {
const response = await fetch(url, { cache: "no-store" });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}
function addOptions(selectId, values) {
const select = document.getElementById(selectId);
[...new Set(values)].sort().forEach((value) => {
const option = document.createElement("option");
option.value = value;
option.textContent = titleCase(value);
select.appendChild(option);
});
}
function applyFilters() {
const query = document.getElementById("search").value.trim().toLowerCase();
const domain = document.getElementById("domain").value;
const lens = document.getElementById("lens").value;
const outcome = document.getElementById("outcome").value;
state.filtered = state.scenarios.filter((scenario) => {
const haystack = `${scenario.scenario_id} ${scenario.title}`.toLowerCase();
return (!query || haystack.includes(query))
&& (!domain || scenario.domain_id === domain)
&& (!lens || scenario.governance_lens === lens)
&& (!outcome || scenario.catalog_baseline_outcome === outcome);
});
document.getElementById("filter-summary").textContent =
`${state.filtered.length} of ${state.scenarios.length} scenarios`;
if (!state.filtered.some((scenario) => scenario.scenario_id === state.selectedId)) {
state.selectedId = state.filtered[0]?.scenario_id ?? null;
}
renderScenarios();
}
function renderScenarios() {
const host = document.getElementById("scenario-content");
if (!state.filtered.length) {
host.className = "empty";
host.textContent = "No scenarios match these filters.";
document.getElementById("scenario-detail").innerHTML = "";
return;
}
host.className = "table-wrap";
host.innerHTML = `
<table aria-label="ConsequenceBench scenarios">
<colgroup>
<col style="width: 92px">
<col style="width: 34%">
<col style="width: 18%">
<col style="width: 20%">
<col style="width: 120px">
</colgroup>
<thead>
<tr>
<th>ID</th>
<th>Scenario</th>
<th>Domain</th>
<th>Governance lens</th>
<th>Baseline</th>
</tr>
</thead>
<tbody>
${state.filtered.map((scenario) => `
<tr data-id="${escapeHtml(scenario.scenario_id)}" class="${scenario.scenario_id === state.selectedId ? "selected" : ""}" tabindex="0">
<td class="scenario-id">${escapeHtml(scenario.scenario_id)}</td>
<td class="title-cell">${escapeHtml(scenario.title)}</td>
<td>${escapeHtml(titleCase(scenario.domain_id))}</td>
<td>${escapeHtml(titleCase(scenario.governance_lens))}</td>
<td><span class="badge ${badgeClass(scenario.catalog_baseline_outcome)}">${escapeHtml(scenario.catalog_baseline_outcome)}</span></td>
</tr>
`).join("")}
</tbody>
</table>`;
host.querySelectorAll("tbody tr").forEach((row) => {
const select = () => {
state.selectedId = row.dataset.id;
renderScenarios();
};
row.addEventListener("click", select);
row.addEventListener("keydown", (event) => {
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
select();
}
});
});
renderDetail();
}
function renderDetail() {
const scenario = state.scenarios.find((item) => item.scenario_id === state.selectedId);
const host = document.getElementById("scenario-detail");
if (!scenario) {
host.innerHTML = "";
return;
}
const binding = scenario.executable_binding ?? {};
const oracle = scenario.oracle_binding ?? {};
host.innerHTML = `
<div class="detail">
<div class="detail-copy">
<p class="eyebrow">${escapeHtml(scenario.scenario_id)} / ${escapeHtml(titleCase(scenario.causal_family))}</p>
<h3>${escapeHtml(scenario.title)}</h3>
<span class="badge ${badgeClass(scenario.severity)}">${escapeHtml(String(scenario.severity).toUpperCase())} SEVERITY</span>
<p class="detail-note">
The catalog baseline is narrative metadata. Executable variants derive their decision from bound world state and may differ from this baseline.
</p>
</div>
<dl class="detail-facts fact-grid">
<div class="fact">
<dt>Generator suite</dt>
<dd>${escapeHtml(binding.suite_id)}</dd>
</div>
<div class="fact">
<dt>Variant</dt>
<dd>${escapeHtml(binding.variant_id)}</dd>
</div>
<div class="fact">
<dt>Family index</dt>
<dd class="mono">${escapeHtml(binding.family_index)}</dd>
</div>
<div class="fact">
<dt>Decision space</dt>
<dd>${escapeHtml((oracle.decision_space ?? []).join(", "))}</dd>
</div>
<div class="fact">
<dt>Catalog source hash</dt>
<dd class="mono">${escapeHtml(scenario.catalog_source_hash)}</dd>
</div>
<div class="fact">
<dt>Outcome rule</dt>
<dd>${escapeHtml(titleCase(oracle.variant_outcome_rule))}</dd>
</div>
</dl>
</div>`;
}
function renderLeaderboard() {
const host = document.getElementById("leaderboard-content");
const entries = state.leaderboard?.entries ?? [];
if (!entries.length) {
host.className = "empty";
host.textContent = "No development rows are available.";
return;
}
host.className = "table-wrap";
host.innerHTML = `
<table class="leaderboard-table" aria-label="Development results">
<colgroup>
<col style="width: 24%">
<col style="width: 12%">
<col style="width: 13%">
<col style="width: 15%">
<col style="width: 14%">
<col style="width: 12%">
<col style="width: 10%">
</colgroup>
<thead>
<tr>
<th>System</th>
<th>Path</th>
<th>Exact</th>
<th>Correct state</th>
<th>Resolved</th>
<th>Unsafe</th>
<th>Gate</th>
</tr>
</thead>
<tbody>
${entries.map((entry) => `
<tr>
<td class="title-cell">${escapeHtml(entry.system)}</td>
<td><span class="badge ${entry.configuration === "governed" ? "green" : "blue"}">${escapeHtml(String(entry.configuration).toUpperCase())}</span></td>
<td class="number">${escapeHtml(entry.final_semantic_exact_count)}/${escapeHtml(entry.world_count)}</td>
<td class="number">${escapeHtml(entry.consequence_correct_count)}/${escapeHtml(entry.world_count)}</td>
<td class="number">${escapeHtml(entry.task_resolved_count)}/${escapeHtml(entry.world_count)}</td>
<td class="number">${escapeHtml(entry.unsafe_effect_count)}</td>
<td><span class="badge ${entry.safety_gate_passed ? "green" : "red"}">${entry.safety_gate_passed ? "PASS" : "FAIL"}</span></td>
</tr>
`).join("")}
</tbody>
</table>`;
}
function activateTab(tab) {
document.querySelectorAll(".tab").forEach((button) => {
const active = button === tab;
button.setAttribute("aria-selected", String(active));
document.getElementById(button.getAttribute("aria-controls")).classList.toggle("active", active);
});
}
document.querySelectorAll(".tab").forEach((tab) => {
tab.addEventListener("click", () => activateTab(tab));
});
["search", "domain", "lens", "outcome"].forEach((id) => {
document.getElementById(id).addEventListener(id === "search" ? "input" : "change", applyFilters);
});
Promise.all([fetchJson(catalogUrl), fetchJson(leaderboardUrl)])
.then(([catalog, leaderboard]) => {
state.scenarios = catalog.entries ?? [];
state.filtered = [...state.scenarios];
state.selectedId = state.scenarios[0]?.scenario_id ?? null;
state.leaderboard = leaderboard;
addOptions("domain", state.scenarios.map((item) => item.domain_id));
addOptions("lens", state.scenarios.map((item) => item.governance_lens));
addOptions("outcome", state.scenarios.map((item) => item.catalog_baseline_outcome));
applyFilters();
renderLeaderboard();
})
.catch((error) => {
document.getElementById("scenario-content").className = "error";
document.getElementById("scenario-content").textContent =
`The public dataset could not be loaded (${error.message}). Use the Dataset link above.`;
document.getElementById("leaderboard-content").className = "error";
document.getElementById("leaderboard-content").textContent =
"The development receipt could not be loaded.";
document.getElementById("filter-summary").textContent = "Data unavailable";
});
</script>
</body>
</html>