Spaces:
Running
Running
File size: 24,030 Bytes
2d3d73f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | "use strict";
(() => {
const contract = window.BenchContract;
const T = {
en: {
search:"Search benchmark", language:"Language", show:"Show", all:"All", withResults:"With a published number", clear:"Clear filters",
benchmark:"Benchmark", results:"Results", notPublished:"Not published yet",
noPacket:"No results are published yet. The list below is the plan: 50 benchmarks, their sources and metrics. For models whose training data we have, a number appears only after a contamination scan.",
loadError:"A pinned file could not be verified, so nothing is shown.", rejected:"Results are hidden because the result file did not pass the checks",
empty:"No benchmark matches the filters.", shown:"Showing", of:"of", benchmarks:"benchmarks",
pills:{total:"benchmarks", langs:"38 EN · 12 PL", models:"models", published:"with a published number"},
higher:"higher is better", lower:"lower is better", ci:"95% CI", noCI:"no interval", random:"random", majority:"majority", delta:"difference",
majorityShare:"predicts its most common class in", none:"none", refMissing:"reference: not available",
scan:{clean:"clean", flagged:"flagged", partially_scanned:"scan incomplete", unscanned:"scan pending", unknown:"training data unknown"},
noNumber:{partially_scanned:"No number: the scan did not cover enough items.", unscanned:"No number until the contamination scan is done."},
hitFree:"Without items found in training data", hitFreeAnswer:"Without hits in question or answer fields", hits:"items with hits", n:"n",
noHitFree:"no items without hits", tooFew:"too few items for a number",
mostly:"fewer than 50 items without hits in training data", inSlayer:"in the Slayer training corpus", slayerSubset:"subsets defined by the Slayer training corpus", mostlyVerdict:"No better/worse from the full sample here: only a paired test on the items without answer-field hits can give one.",
pending:n => `${n} benchmarks are not measured yet; adding them cannot change the verdicts shown; it can settle rows now inconclusive and adds verdicts for the new rows.`,
constant:"constant answer", constantNote:"One class for all items: not compared between models.",
states:{ok:"Measured",not_run:"Not run",blocked_access:"Data access blocked",blocked_runtime:"Runtime blocked",blocked_security:"Blocked by security review",blocked_judge:"No accepted judge",unsupported:"Not supported",failed:"Run failed",skipped:"Skipped"},
verdicts:{better:"better than",worse:"worse than",inconclusive:"inconclusive vs"}, verdictNote:"paired test, Holm-adjusted", verdictNoteSubset:"paired test on items without answer-field hits, Holm-adjusted",
amendments:{answer_leading_space_strip:"Scoring corrected after first run (leading space), see METHOD.", other:"Scoring amended after first run, see METHOD."},
scoringNotes:{source_extractor_floor:"Floor: the source 0-shot extractor reads the text between the first and last $, so answers in \\boxed{} score 0. Not a comparison of ability, see METHOD.", other:"Scoring note, see METHOD."},
details:"Source and sample", population:"population / sample / scored", revision:"revision", licence:"licence (dataset card)", files:"Pinned files",
packet:"result file", run:"run", protocol:"protocol"
},
pl: {
search:"Szukaj benchmarku", language:"Język", show:"Pokaż", all:"Wszystkie", withResults:"Z opublikowaną liczbą", clear:"Wyczyść filtry",
benchmark:"Benchmark", results:"Wyniki", notPublished:"Jeszcze nie opublikowano",
noPacket:"Nie ma jeszcze opublikowanych wyników. Poniżej jest plan: 50 benchmarków, ich źródła i miary. Dla modeli, których dane treningowe mamy, liczba pojawia się dopiero po skanie kontaminacji.",
loadError:"Nie udało się zweryfikować przypiętego pliku, więc niczego nie pokazuję.", rejected:"Wyniki ukryte, bo plik wyników nie przeszedł kontroli",
empty:"Żaden benchmark nie pasuje do filtrów.", shown:"Pokazano", of:"z", benchmarks:"benchmarków",
pills:{total:"benchmarków", langs:"38 EN · 12 PL", models:"modele", published:"z opublikowaną liczbą"},
higher:"więcej = lepiej", lower:"mniej = lepiej", ci:"95% CI", noCI:"bez przedziału", random:"losowo", majority:"większość", delta:"różnica",
majorityShare:"najczęstsza własna klasa w", none:"brak", refMissing:"odniesienie: brak",
scan:{clean:"czysty", flagged:"trafienia", partially_scanned:"skan niepełny", unscanned:"skan w toku", unknown:"dane treningowe nieznane"},
noNumber:{partially_scanned:"Bez liczby: skan nie objął dość pozycji.", unscanned:"Bez liczby do czasu skanu kontaminacji."},
hitFree:"Bez pozycji znalezionych w danych treningowych", hitFreeAnswer:"Bez trafień w polach pytania i odpowiedzi", hits:"pozycji z trafieniem", n:"n",
noHitFree:"brak pozycji bez trafień", tooFew:"za mało pozycji na liczbę",
mostly:"mniej niż 50 pozycji bez trafień w danych treningowych", inSlayer:"w korpusie treningowym Slayera", slayerSubset:"podzbiory wyznaczone korpusem treningowym Slayera", mostlyVerdict:"Tu nie ma werdyktu lepszy/gorszy z całej próbki: może go dać tylko test sparowany na pozycjach bez trafień w polach odpowiedzi.",
pending:n => `${n} benchmarków nie jest jeszcze zmierzonych; ich dodanie nie zmieni pokazanych werdyktów; może rozstrzygnąć wiersze dziś nierozstrzygnięte i doda werdykty dla nowych wierszy.`,
constant:"stała odpowiedź", constantNote:"Jedna klasa dla wszystkich pozycji: nie porównujemy między modelami.",
states:{ok:"Pomiar",not_run:"Nie uruchomiono",blocked_access:"Brak dostępu do danych",blocked_runtime:"Blokada środowiska",blocked_security:"Zablokowane przez przegląd bezpieczeństwa",blocked_judge:"Brak przyjętego sędziego",unsupported:"Nieobsługiwane",failed:"Błąd biegu",skipped:"Pominięte"},
verdicts:{better:"lepszy niż",worse:"gorszy niż",inconclusive:"nierozstrzygnięte wobec"}, verdictNote:"test sparowany, poprawka Holma", verdictNoteSubset:"test sparowany na pozycjach bez trafień w polach odpowiedzi, poprawka Holma",
amendments:{answer_leading_space_strip:"Punktacja poprawiona po pierwszym biegu (spacja na początku), zob. METHOD.", other:"Punktacja zmieniona po pierwszym biegu, zob. METHOD."},
scoringNotes:{source_extractor_floor:"Podłoga: ekstraktor źródła (0-shot) czyta tekst między pierwszym a ostatnim $, więc odpowiedzi w \\boxed{} dostają 0. To nie jest porównanie umiejętności, zob. METHOD.", other:"Uwaga o punktacji, zob. METHOD."},
details:"Źródło i próbka", population:"populacja / próbka / ocenione", revision:"rewizja", licence:"licencja (karta zbioru)", files:"Przypięte pliki",
packet:"plik wyników", run:"bieg", protocol:"protokół"
}
};
const state = {lang:"en", tasks:null, packet:null, index:null, packetSHA:null, error:null, files:[], query:"", language:"all", show:"all"};
function el(tag, text, cls) {
const n = document.createElement(tag);
if (text !== undefined && text !== null) n.textContent = String(text);
if (cls) n.className = cls;
return n;
}
function fmt(v, unit) {
const digits = unit === "byte_ppl" ? 3 : unit === "percent" ? 1 : 3;
return new Intl.NumberFormat(state.lang === "pl" ? "pl-PL" : "en-GB", {minimumFractionDigits:digits, maximumFractionDigits:digits}).format(v);
}
const unitLabel = u => u === "percent" ? "%" : u === "byte_ppl" ? "byte-PPL" : "";
const pct = v => new Intl.NumberFormat(state.lang === "pl" ? "pl-PL" : "en-GB", {style:"percent", maximumFractionDigits:1}).format(v);
function modelName(m) { return m.repo.split("/").pop(); }
// Thresholds and the "most items found in training data" class come from the contract, which also guarantees that every
// non-withheld verdict in an accepted packet follows the display rules (binding rules 2026-10-29 16:55 and 17:07).
const MIN_HIT_FREE_N = contract.MIN_HIT_FREE_N;
const mostlyTrained = taskId => state.index ? contract.mostlyTrained(state.index.observations, taskId, state.packet.protocol_id) : null;
// Whether the cell carries a number at all, and why not otherwise.
function numberRule(o) {
if (o.state !== "ok") return {show:false, reason:null};
if (["clean","flagged","unknown"].includes(o.contamination)) return {show:true};
return {show:false, reason:o.contamination};
}
function hitFreeLine(label, value, n, rate, ci, unit, t) {
const tail = `${t.n} ${n}; ${pct(rate)} ${t.hits}`;
if (n === 0) return `${label}: ${t.noHitFree}`;
if (n < MIN_HIT_FREE_N) return `${label}: ${t.tooFew} (${tail})`;
const interval = ci ? `${t.ci} ${fmt(ci.lower, unit)} – ${fmt(ci.upper, unit)}` : t.noCI;
return `${label}: ${fmt(value, unit)}, ${interval} (${tail})`;
}
const isConstant = x => !!(x && x.reference && x.reference.constant_prediction === true);
function cell(task, model, t) {
const td = el("td");
const o = state.index && state.index.observations.get(contract.key(task.id, model.model_id, state.packet.protocol_id));
if (!o) { td.append(el("span", t.notPublished, "state")); return td; }
const mostly = mostlyTrained(task.id);
const rule = numberRule(o);
const tags = el("div", undefined, "tags");
if (o.state !== "ok") {
td.append(el("span", t.states[o.state], "state"));
if (o.reason) td.append(el("span", o.reason, "meta"));
} else if (!rule.show) {
td.append(el("span", t.noNumber[rule.reason], "state"));
} else {
const v = el("span", fmt(o.value, o.unit), mostly === null ? "value" : "value dim");
if (unitLabel(o.unit)) v.append(el("small", unitLabel(o.unit)));
td.append(v);
td.append(el("span", o.ci95 ? `${t.ci} ${fmt(o.ci95.lower, o.unit)} – ${fmt(o.ci95.upper, o.unit)}` : t.noCI, "meta"));
if (mostly !== null) td.append(el("span", `${t.mostly} (${pct(mostly)} ${t.hits}${o.contamination === "unknown" ? `, ${t.inSlayer}` : ""})`, "mostly"));
const hasA = Number.isInteger(o.n_hit_free), hasB = Number.isInteger(o.n_hit_free_answer_fields);
if (hasA) td.append(el("span", hitFreeLine(t.hitFree, o.value_hit_free, o.n_hit_free, o.hit_rate, o.ci95_hit_free, o.unit, t), "ref"));
if (hasB) td.append(el("span", hitFreeLine(t.hitFreeAnswer, o.value_hit_free_answer_fields, o.n_hit_free_answer_fields, o.hit_rate_answer_fields, o.ci95_hit_free_answer_fields, o.unit, t), "ref"));
if ((hasA || hasB) && o.contamination === "unknown") td.append(el("span", t.slayerSubset, "meta"));
const r = o.reference;
const refs = [];
if (r && r.chance_value !== null) refs.push(`${t.random} ${fmt(r.chance_value, o.unit)}`);
if (r && r.majority_value !== null) refs.push(`${t.majority} ${fmt(r.majority_value, o.unit)}`);
td.append(el("span", refs.length ? refs.join(" · ") : t.refMissing, "ref"));
if (r && r.majority_prediction_share !== null) td.append(el("span", `${t.majorityShare} ${pct(r.majority_prediction_share)}`, "meta"));
if (isConstant(o)) tags.append(el("span", t.constant, "tag constant"));
}
const scanClass = {clean:"clean", flagged:"flagged", unknown:"unknown"}[o.contamination] || "pending";
tags.append(el("span", t.scan[o.contamination], `tag ${scanClass}`));
td.append(tags);
if (rule.show && isConstant(o)) td.append(el("span", t.constantNote, "meta"));
if (rule.show && mostly !== null) td.append(el("span", t.mostlyVerdict, "meta"));
for (const c of state.index.contrasts) {
if (c.task_id !== task.id || c.model_id !== model.model_id || c.verdict === "withheld") continue;
const ref = state.index.models.get(c.model_ref);
const p = new Intl.NumberFormat(state.lang === "pl" ? "pl-PL" : "en-GB", {maximumSignificantDigits:2}).format(c.p_holm);
const note = c.subset === "full" ? t.verdictNote : `${t.verdictNoteSubset}, ${t.n} ${c.n}`;
const signed = v => `${v > 0 ? "+" : ""}${fmt(v, c.unit)}`;
const isNum = v => typeof v === "number" && Number.isFinite(v);
const diff = isNum(c.delta) ? `${t.delta} ${signed(c.delta)}${c.ci95 ? ` (${t.ci} ${signed(c.ci95.lower)} – ${signed(c.ci95.upper)})` : ""} · ` : "";
td.append(el("span", `${t.verdicts[c.verdict]} ${modelName(ref)}`, "verdict"), el("span", `${diff}${note}: p = ${p}`, "meta"));
}
const d = el("details");
d.append(el("summary", t.details));
d.append(el("p", `${t.population}: ${o.n_population ?? "—"} / ${o.n_selected ?? "—"} / ${o.n_scored}`));
d.append(el("p", `results_sha256 ${o.results_sha256 ?? "—"}`));
if (o.contamination_receipt_sha256) d.append(el("p", `scan receipt ${o.contamination_receipt_sha256}`));
td.append(d);
return td;
}
// Polish labels for the tasks_50 domain values; the English view shows the value itself.
const DOMAIN_PL = {
syntax:"składnia", science_reasoning:"rozumowanie naukowe", language_modeling:"modelowanie języka", morphosyntax:"morfoskładnia",
commonsense:"zdrowy rozsądek", physical_reasoning:"rozumowanie fizyczne", coreference:"koreferencja", science_knowledge:"wiedza naukowa",
reading:"czytanie", causal_reasoning:"rozumowanie przyczynowe", entailment:"wynikanie", word_sense:"znaczenie słowa",
adversarial_entailment:"wynikanie (adwersaryjne)", contextual_prediction:"przewidywanie z kontekstu", logical_reasoning:"rozumowanie logiczne",
mathematics_mc:"matematyka (wybór)", sentiment:"wydźwięk", topic_classification:"klasyfikacja tematu", question_relevance:"trafność pytania",
paraphrase:"parafraza", summary_matching:"dopasowanie streszczenia", toxicity_detection:"wykrywanie toksyczności",
sentence_entity_classification:"klasyfikacja zdań i encji", question_answering:"odpowiadanie na pytania", academic_knowledge:"wiedza akademicka",
mathematics_generation:"matematyka (generowanie)", competition_mathematics:"matematyka konkursowa", truthfulness:"prawdomówność",
instruction_following:"wykonywanie poleceń", native_exam_knowledge:"wiedza z egzaminów krajowych", unanswerable_reading:"czytanie z pytaniami bez odpowiedzi",
discrete_reading:"czytanie z liczeniem", conversational_reading:"czytanie w dialogu", closed_book_knowledge:"wiedza bez kontekstu",
biomedical_reading:"czytanie biomedyczne", medical_exam_knowledge:"wiedza z egzaminów medycznych", social_reasoning:"rozumowanie społeczne",
formal_reasoning:"rozumowanie formalne", adversarial_paraphrase:"parafraza (adwersaryjna)", acceptability:"poprawność zdania", entity_reading:"czytanie o encjach"
};
const domainLabel = d => (state.lang === "pl" && DOMAIN_PL[d]) || d.replace(/_/g, " ");
function taskHeader(task, t) {
const th = el("th", task.name, "task");
th.scope = "row";
th.append(el("span", `${task.language} · ${domainLabel(task.domain)}`, "meta"));
th.append(el("span", `${task.metric.split(",")[0]} · ${task.higher_is_better ? t.higher : t.lower}`, "meta"));
// Public scoring amendments are a property of the pinned benchmark list, never of a result file.
for (const code of task.scoring_amendments || []) th.append(el("span", t.amendments[code] || t.amendments.other, "amend"));
for (const code of task.scoring_notes || []) th.append(el("span", t.scoringNotes[code] || t.scoringNotes.other, "amend"));
const d = el("details");
d.append(el("summary", t.details));
for (const s of task.license.source_revisions) {
const p = el("p");
const a = el("a", s.repo_id);
a.href = `https://huggingface.co/datasets/${s.repo_id}`;
a.rel = "noopener";
p.append(a, document.createTextNode(` · ${t.revision} ${s.revision.slice(0, 8)}`));
d.append(p);
}
d.append(el("p", `${t.licence}: ${task.license.declared_tags.join(", ") || t.none}`));
d.append(el("p", `${task.split} · ${task.shots}-shot · ${task.instrument}`));
th.append(d);
return th;
}
function render() {
const t = T[state.lang];
const app = document.getElementById("app");
const pills = document.getElementById("pills");
pills.replaceChildren();
const pill = (b, txt) => { const p = el("span", undefined, "pill"); p.append(el("b", b), document.createTextNode(` ${txt}`)); pills.append(p); };
if (!state.tasks) {
app.replaceChildren(el("p", `${t.loadError} (${state.error})`, "notice error"));
return;
}
const rows = state.tasks.rows;
// Models whose training corpus was scanned come first; models with unknown training data follow, in packet order.
const scanned = m => state.index && [...state.index.observations.values()].some(o => o.model_id === m.model_id && o.contamination !== "unknown");
const models = state.packet ? [...state.packet.models].sort((a, b) => scanned(b) - scanned(a)) : [];
const published = new Set();
if (state.index) for (const o of state.index.observations.values()) if (numberRule(o).show) published.add(o.task_id);
pill(rows.length, t.pills.total);
pills.append(el("span", t.pills.langs, "pill"));
if (models.length) pill(models.length, t.pills.models);
pill(published.size, t.pills.published);
// Benchmarks where some model has no measurement yet (binding sentence 2026-10-29 20:18).
const pendingEl = document.getElementById("pending");
const unmeasured = state.index ? rows.filter(r => models.some(m => { const o = state.index.observations.get(contract.key(r.id, m.model_id, state.packet.protocol_id)); return !o || o.state !== "ok"; })).length : 0;
pendingEl.hidden = unmeasured === 0;
pendingEl.textContent = unmeasured ? t.pending(unmeasured) : "";
const nodes = [];
if (state.error && state.tasks) nodes.push(el("p", `${t.rejected}: ${state.error}`, "notice error"));
else if (!state.packet) nodes.push(el("p", t.noPacket, "notice"));
const controls = el("div", undefined, "controls");
const search = el("input"); search.type = "search"; search.value = state.query;
const lang = el("select");
for (const [v, txt] of [["all", t.all], ["EN", "EN"], ["PL", "PL"]]) { const op = el("option", txt); op.value = v; lang.append(op); }
lang.value = state.language;
const show = el("select");
for (const [v, txt] of [["all", t.all], ["published", t.withResults]]) { const op = el("option", txt); op.value = v; show.append(op); }
show.value = state.show;
show.disabled = !state.packet;
const clear = el("button", t.clear, "clear"); clear.type = "button";
const lab = (txt, input) => { const l = el("label", txt); l.append(input); return l; };
controls.append(lab(t.search, search), lab(t.language, lang), lab(t.show, show), clear);
const summary = el("p", undefined, "summary");
summary.setAttribute("role", "status");
const wrap = el("div", undefined, "wrap");
wrap.tabIndex = 0;
wrap.setAttribute("role", "region");
wrap.setAttribute("aria-label", t.results);
const table = el("table");
table.setAttribute("aria-labelledby", "results-title");
const head = el("tr");
const th0 = el("th", t.benchmark); th0.scope = "col"; head.append(th0);
if (models.length) for (const m of models) {
const th = el("th", modelName(m)); th.scope = "col";
th.append(el("span", m.revision ? `${t.revision} ${m.revision.slice(0, 8)}` : "", "meta"));
head.append(th);
} else { const th = el("th", t.results); th.scope = "col"; head.append(th); }
const thead = el("thead"); thead.append(head);
const tbody = el("tbody");
table.append(thead, tbody);
wrap.append(table);
const empty = el("p", t.empty, "summary");
nodes.push(controls, summary, wrap, empty);
app.replaceChildren(...nodes);
function fill() {
const q = state.query.trim().toLocaleLowerCase(state.lang);
const visible = rows.filter(r => (state.language === "all" || r.language === state.language) &&
(state.show === "all" || published.has(r.id)) &&
`${r.name} ${r.benchmark_id} ${r.domain}`.toLocaleLowerCase(state.lang).includes(q));
const frag = document.createDocumentFragment();
for (const r of visible) {
const tr = el("tr");
tr.append(taskHeader(r, t));
if (models.length) for (const m of models) tr.append(cell(r, m, t));
else tr.append(el("td", t.notPublished, "state"));
frag.append(tr);
}
tbody.replaceChildren(frag);
summary.textContent = `${t.shown} ${visible.length} ${t.of} ${rows.length} ${t.benchmarks}`;
empty.hidden = visible.length !== 0;
wrap.hidden = visible.length === 0;
}
search.addEventListener("input", () => { state.query = search.value; fill(); });
lang.addEventListener("change", () => { state.language = lang.value; fill(); });
show.addEventListener("change", () => { state.show = show.value; fill(); });
clear.addEventListener("click", () => { state.query = ""; state.language = "all"; state.show = "all"; search.value = ""; lang.value = "all"; show.value = "all"; fill(); search.focus(); });
fill();
const files = document.getElementById("files");
files.replaceChildren(el("p", t.files));
for (const f of state.files) { const p = el("p"); p.append(el("code", `${f.name} · sha256 ${f.sha}`)); files.append(p); }
if (state.packet) files.append(el("p", `${t.packet}: ${t.run} ${state.packet.run_id} · ${t.protocol} ${state.packet.protocol_id}`));
}
async function read(path, pin) {
const res = await fetch(path, {cache:"no-store"});
if (!res.ok) throw new Error(`${path}: HTTP ${res.status}`);
const bytes = await res.arrayBuffer();
const digest = await crypto.subtle.digest("SHA-256", bytes);
const sha = [...new Uint8Array(digest)].map(b => b.toString(16).padStart(2, "0")).join("");
if (pin && sha !== pin) throw new Error(`${path}: pinned bytes changed`);
state.files.push({name:path, sha});
return {bytes, sha};
}
const json = r => JSON.parse(new TextDecoder().decode(r.bytes));
function setLang(l) {
state.lang = l === "pl" ? "pl" : "en";
document.body.dataset.lang = state.lang;
document.documentElement.lang = state.lang;
document.querySelectorAll(".lang button").forEach(b => b.setAttribute("aria-pressed", String(b.dataset.set === state.lang)));
try { localStorage.setItem("slayer-lang", state.lang); } catch (e) {}
render();
}
async function start() {
try {
const tasks = await read("tasks_50.json", contract.PINS.tasks);
await read("results.schema.json", contract.PINS.schema);
await read("METHOD.md", contract.PINS.method);
await read("contamination_field_roles.json", contract.PINS.fieldRoles);
state.tasks = json(tasks);
if (state.tasks.rows.length !== 50) throw new Error("tasks_50.json: expected 50 rows");
} catch (e) { state.error = e.message; state.tasks = null; return; }
try {
const feed = json(await read("results-feed.json"));
if (feed.results !== null) {
if (feed.results !== "results.json") throw new Error("only results.json next to this page is allowed");
// The feed names the exact reviewed packet; any other bytes are refused.
if (!/^[0-9a-f]{64}$/.test(feed.sha256 || "")) throw new Error("results-feed.json: missing sha256 of results.json");
const res = await read("results.json", feed.sha256);
const packet = json(res);
state.index = contract.validate(packet, state.tasks);
state.packet = packet;
state.packetSHA = res.sha;
}
} catch (e) { state.error = e.message; state.packet = null; state.index = null; }
}
document.querySelectorAll(".lang button").forEach(b => b.addEventListener("click", () => setLang(b.dataset.set)));
let saved = null; try { saved = localStorage.getItem("slayer-lang"); } catch (e) {}
const q = new URLSearchParams(location.search).get("lang");
start().finally(() => setLang(q || saved || "en"));
})();
|