Spaces:
Running
Running
Commit ·
2811484
0
Parent(s):
OmniStepBench project page
Browse files- .gitattributes +63 -0
- DEPLOY.md +117 -0
- README.md +28 -0
- assets/css/palette.css +156 -0
- assets/css/style.css +0 -0
- assets/data/data.js +0 -0
- assets/fonts/README.md +77 -0
- assets/fonts/bangers-latin-400.woff2 +3 -0
- assets/fonts/caveat-latin-wght.woff2 +3 -0
- assets/fonts/fonts.css +89 -0
- assets/fonts/fonts.inline.css +0 -0
- assets/fonts/fredoka-latin-wght.woff2 +3 -0
- assets/fonts/jetbrainsmono-latin-wght.woff2 +3 -0
- assets/fonts/licenses/bangers-OFL.txt +93 -0
- assets/fonts/licenses/caveat-OFL.txt +93 -0
- assets/fonts/licenses/fredoka-OFL.txt +93 -0
- assets/fonts/licenses/jetbrainsmono-OFL.txt +93 -0
- assets/fonts/licenses/nunito-OFL.txt +93 -0
- assets/fonts/licenses/patrickhand-OFL.txt +93 -0
- assets/fonts/nunito-latin-wght-italic.woff2 +3 -0
- assets/fonts/nunito-latin-wght.woff2 +3 -0
- assets/fonts/patrickhand-latin-400.woff2 +3 -0
- assets/img/Case.png +3 -0
- assets/img/acc_cost.png +3 -0
- assets/img/banner.png +3 -0
- assets/img/benchmark_sunburst.png +3 -0
- assets/img/casestudy_pseudo_tool_call.png +3 -0
- assets/img/casestudy_rubric_leakage.png +3 -0
- assets/img/examples/task_agentvista_09.png +3 -0
- assets/img/examples/task_charxiv_01.jpg +3 -0
- assets/img/examples/task_hle_02.png +3 -0
- assets/img/examples/task_medxpertqa_02.jpg +3 -0
- assets/img/examples/task_mmsearchplus_00.png +3 -0
- assets/img/examples/task_simplevqa_08.jpg +3 -0
- assets/img/favicon.svg +15 -0
- assets/img/overview.png +3 -0
- assets/img/social-card.png +3 -0
- assets/js/content.js +291 -0
- assets/js/cost.js +531 -0
- assets/js/leaderboard.js +315 -0
- assets/js/main.js +95 -0
- assets/js/quickstart.js +206 -0
- assets/js/reliability.js +179 -0
- assets/js/util.js +431 -0
- assets/js/workloads.js +320 -0
- index.html +1142 -0
.gitattributes
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.avro filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.lz4 filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.mds filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
# Audio files - uncompressed
|
| 40 |
+
*.pcm filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
*.sam filter=lfs diff=lfs merge=lfs -text
|
| 42 |
+
*.raw filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
# Audio files - compressed
|
| 44 |
+
*.aac filter=lfs diff=lfs merge=lfs -text
|
| 45 |
+
*.flac filter=lfs diff=lfs merge=lfs -text
|
| 46 |
+
*.mp3 filter=lfs diff=lfs merge=lfs -text
|
| 47 |
+
*.ogg filter=lfs diff=lfs merge=lfs -text
|
| 48 |
+
*.wav filter=lfs diff=lfs merge=lfs -text
|
| 49 |
+
# Image files - uncompressed
|
| 50 |
+
*.bmp filter=lfs diff=lfs merge=lfs -text
|
| 51 |
+
*.gif filter=lfs diff=lfs merge=lfs -text
|
| 52 |
+
*.png filter=lfs diff=lfs merge=lfs -text
|
| 53 |
+
*.tiff filter=lfs diff=lfs merge=lfs -text
|
| 54 |
+
# Image files - compressed
|
| 55 |
+
*.jpg filter=lfs diff=lfs merge=lfs -text
|
| 56 |
+
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
| 57 |
+
*.webp filter=lfs diff=lfs merge=lfs -text
|
| 58 |
+
# Video files - compressed
|
| 59 |
+
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 60 |
+
*.webm filter=lfs diff=lfs merge=lfs -text
|
| 61 |
+
# Web fonts and documents
|
| 62 |
+
*.woff2 filter=lfs diff=lfs merge=lfs -text
|
| 63 |
+
*.pdf filter=lfs diff=lfs merge=lfs -text
|
DEPLOY.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# OmniStepBench project page
|
| 2 |
+
|
| 3 |
+
The official project page for **OmniStepBench: Deployment-Aware Agent Evaluation across Modalities and Task Complexity**
|
| 4 |
+
(arXiv [2609.06059](https://arxiv.org/abs/2609.06059), code [SeerRay-Lab/OmniStepBench](https://github.com/SeerRay-Lab/OmniStepBench)).
|
| 5 |
+
|
| 6 |
+
It is a static site: HTML, CSS and plain JavaScript, with no build step, no framework and no network
|
| 7 |
+
dependencies. Fonts are bundled, so the page renders fully offline (and from mainland China).
|
| 8 |
+
|
| 9 |
+
This folder is the Hugging Face Space [SeerRay-Lab/OmniStepBench](https://huggingface.co/spaces/SeerRay-Lab/OmniStepBench), a mirror of the project page at https://seerray-lab.github.io/OmniStepBench/. It is
|
| 10 |
+
generated from the page's source folder
|
| 11 |
+
`homepage/site/` by `huggingface/_build/build_space.py`; this file is that folder's `README.md`, renamed so that it
|
| 12 |
+
does not replace the Space card. Paths such as `../tools/` below are relative to `homepage/site/`.
|
| 13 |
+
|
| 14 |
+
## Preview
|
| 15 |
+
|
| 16 |
+
- Open `index.html` directly in a browser. It works over `file://`: scripts are classic `<script src>`
|
| 17 |
+
tags, data comes from a global (`window.OSB`) rather than `fetch()`, and there are no ES-module imports.
|
| 18 |
+
- Or serve the folder: `python3 -m http.server 8000` in this directory, then open http://localhost:8000.
|
| 19 |
+
|
| 20 |
+
## Deploy
|
| 21 |
+
|
| 22 |
+
This folder is deployed as a Hugging Face **static Space**: [SeerRay-Lab/OmniStepBench](https://huggingface.co/spaces/SeerRay-Lab/OmniStepBench). Hugging Face serves the files
|
| 23 |
+
at https://seerray-lab-omnistepbench.static.hf.space/ and shows that page inside the Space. The Space already exists, so
|
| 24 |
+
upload the whole folder as the Space repo root, e.g. from this folder:
|
| 25 |
+
`hf upload SeerRay-Lab/OmniStepBench . . --repo-type space --delete "*"` (`--delete` removes files the rebuilt site no longer has),
|
| 26 |
+
or `git push` to the Space repo. Nothing here needs a build step.
|
| 27 |
+
|
| 28 |
+
What differs from the source folder `homepage/site/` (all applied by `build_space.py`; do not edit this folder by
|
| 29 |
+
hand: change the source or the script and rebuild):
|
| 30 |
+
|
| 31 |
+
- `README.md` is the Space card: its YAML front matter holds the Space settings (`sdk: static`,
|
| 32 |
+
`app_file: index.html`, title, emoji, colours, tags, linked dataset).
|
| 33 |
+
- `.gitattributes` stores images, fonts and other binaries with Git LFS (the Hub rejects binaries committed as
|
| 34 |
+
plain Git objects).
|
| 35 |
+
- `index.html`: the social preview images (`og:image`, `twitter:image`) are absolute
|
| 36 |
+
(https://seerray-lab-omnistepbench.static.hf.space/assets/img/social-card.png) and `<link rel="canonical">` points to the primary homepage (https://seerray-lab.github.io/OmniStepBench/), since the Space is a mirror. (The Hugging Face dataset links in
|
| 37 |
+
the hero, cite and footer rows are part of the source page itself.)
|
| 38 |
+
- Hugging Face embeds the page in a sandboxed frame that cannot navigate the whole window, and sites such as
|
| 39 |
+
GitHub refuse to be framed, so a small script in `index.html` opens links to other sites in a new tab, only
|
| 40 |
+
while the page is framed.
|
| 41 |
+
- `_shots/` (review screenshots) is left out.
|
| 42 |
+
|
| 43 |
+
The same files also work on any other static host (GitHub Pages, Netlify, an nginx folder, ...). There, change the
|
| 44 |
+
absolute `og:image` / `twitter:image` URLs and the canonical URL in `index.html` to the new address; crawlers
|
| 45 |
+
ignore relative image URLs.
|
| 46 |
+
|
| 47 |
+
## Layout
|
| 48 |
+
|
| 49 |
+
```
|
| 50 |
+
index.html page skeleton (no data digits in static text), SVG sprite and mascot inline
|
| 51 |
+
assets/data/data.js window.OSB: every number, name and paper text shown on the page
|
| 52 |
+
assets/js/util.js helpers: DOM builder, tooltips, radiogroups, roving focus, copy, lightbox
|
| 53 |
+
assets/js/content.js hero, motivation, overview, findings, case study, cite, footer
|
| 54 |
+
assets/js/workloads.js 2x3 workload matrix, source benchmarks, task explorer
|
| 55 |
+
assets/js/leaderboard.js Table 1 leaderboard (Full / Text track, API / Local filter, sorting)
|
| 56 |
+
assets/js/cost.js Fig. 1 accuracy-cost scatter and the tokens-vs-dollars chart (Table 2)
|
| 57 |
+
assets/js/reliability.js evidence-based audit, hallucination patterns (Table 3), Figs. 5-6, taxonomy
|
| 58 |
+
assets/js/quickstart.js README quick start, tools used in the paper, task-file anatomy
|
| 59 |
+
assets/js/main.js boot: each section renders inside its own try/catch
|
| 60 |
+
assets/css/palette.css validated color tokens (data colors, surfaces, status)
|
| 61 |
+
assets/css/style.css the "underwater storybook" skin and all components
|
| 62 |
+
assets/fonts/ self-hosted woff2 (SIL OFL 1.1, licenses in licenses/)
|
| 63 |
+
assets/img/ paper figures, task images (img/examples/), favicon.svg, social-card.png
|
| 64 |
+
```
|
| 65 |
+
|
| 66 |
+
## Updating numbers
|
| 67 |
+
|
| 68 |
+
**All numbers come from `assets/data/data.js`. The paper is the single source of truth.**
|
| 69 |
+
|
| 70 |
+
1. Edit `assets/data/data.js` (or regenerate it with the data builder and copy it here). The comment
|
| 71 |
+
header at the top documents every key. Keep `data.js` a plain `window.OSB = {...};` assignment.
|
| 72 |
+
2. Do not type numbers into `index.html` or the JS modules. Charts, tables, tiles and prose read their
|
| 73 |
+
values from `window.OSB`; derived values (for example an Overall accuracy the paper does not tabulate)
|
| 74 |
+
use the paper's own definition and are labelled as derived on the page. Overall = the paper's prose value
|
| 75 |
+
where it states one, otherwise (162 × Table 1 Text Avg + 71 × MM Avg) / 233 (Eq. 11); this form reproduces
|
| 76 |
+
all 9 prose-stated Overalls. The round-1 QA patch that sets this (and withholds the task-file rubric) is
|
| 77 |
+
`homepage/tools/data_build/patch_data_r1.py`; the round-2 patch `homepage/tools/data_build/patch_data_r2.py`
|
| 78 |
+
keeps the example tasks disjoint from the tasks shown in the paper figures on the page (Fig. 3 =
|
| 79 |
+
`task_agentvista_00`, Fig. 5 = `task_simplevqa_07`, Fig. 6 = `task_tablebench_10`, whose answers those
|
| 80 |
+
figures show). The data builder re-applies both after every build. An English rendering of a Chinese
|
| 81 |
+
prompt that the paper does not give is stored as `englishTranslation` and labelled "our translation"
|
| 82 |
+
(`englishGloss` is reserved for wording quoted from the paper).
|
| 83 |
+
3. Paper-vs-code mismatches go into `discrepancies` in `data.js`. That list is never displayed.
|
| 84 |
+
4. Re-run the checks below.
|
| 85 |
+
|
| 86 |
+
Figures referenced by `data.js` (for example `img/overview.png`) resolve under `assets/`.
|
| 87 |
+
|
| 88 |
+
## Checks
|
| 89 |
+
|
| 90 |
+
The review tools live next to this folder, in `../tools/` (Node + Playwright Chromium; they are not part of
|
| 91 |
+
the deploy):
|
| 92 |
+
|
| 93 |
+
| Command | What it checks |
|
| 94 |
+
|---|---|
|
| 95 |
+
| `node ../tools/smoke.cjs` | 101 interaction checks: leaderboard tracks/filters/sorting/medals and the compact (overflowing) layout, workload matrix, table views, scatter and keyboard navigation, keyboard tooltips, focus rings, accessible names, lightbox, copy buttons, mobile menu (incl. focus leaving it), the Pause animations button, reduced motion, no horizontal overflow at 360–1920 px, zero console errors; round-2 regressions (no example task shown in an on-page figure, slim phone leaderboard, focused sort buttons never hidden under the sticky column, text-only notice inside the visible table, sources table scrolls in its card); round-3 regressions (every chart table view on a 390 px phone is a named, focusable region with its caption outside the scroller, a swipe hint while it overflows and arrow-key scrolling to the last column; a pixel diff shows the hero kelp never paints over hero text at 1024–1280 px, at rest or at either end of its sway) |
|
| 96 |
+
| `node ../tools/numbers.cjs` | static HTML has no digits in visible text; every number rendered on the page traces back to `data.js` |
|
| 97 |
+
| `node ../tools/labels.cjs` | scatter: every point is named or numbered (numbers are keyed under the chart) at every width; no label/label, label/point or label/tick overlaps; every name or number sits closer to its own dot than to any other, and a name next to its dot never runs over another dot that is nearer its centre |
|
| 98 |
+
| `node ../tools/audit.cjs` | real `file://` policy: fonts load, no external requests, WCAG AA text contrast, focus indicators, headings, landmarks, page weight |
|
| 99 |
+
| `node ../tools/shoot.cjs <dir> --full` | desktop (1440) and mobile (390) section screenshots, plus a full-page capture |
|
| 100 |
+
| `python3 ../tools/make-social-card.py` | rebuilds `assets/img/social-card.png` (1200x630) from the page's own art and data |
|
| 101 |
+
|
| 102 |
+
## Browser support and accessibility notes
|
| 103 |
+
|
| 104 |
+
- Tested in Chromium (desktop and mobile widths, real `file://` policy). Fonts load from `assets/fonts/fonts.css`.
|
| 105 |
+
Firefox gives every `file://` page its own origin and may refuse web fonts loaded from files, so a small
|
| 106 |
+
inline script in `<head>` switches to `assets/fonts/fonts.inline.css` (the same fonts as data URIs) only
|
| 107 |
+
when the page is opened from disk in Firefox. Served over http(s), every browser uses the woff2 files.
|
| 108 |
+
- Light theme only. Every chart has a hover and keyboard-focus tooltip and a table view; charts use one
|
| 109 |
+
Tab stop with arrow-key navigation (the leaderboard is a real table: its cell tooltips repeat what the
|
| 110 |
+
headers, crowns, ◆ marks and footnotes already show). All ambient motion stops under
|
| 111 |
+
`prefers-reduced-motion`, pauses when off screen, and can be paused with the "Pause animations" button in
|
| 112 |
+
the hero (remembered in localStorage).
|
| 113 |
+
|
| 114 |
+
## Credits
|
| 115 |
+
|
| 116 |
+
Illustrations (the lobster evaluator and the sea creatures) are original SVG art made for this page.
|
| 117 |
+
Figures 1, 2, 3, 5 and 6 are reproduced from the paper (Fig. 4 and the appendix case images are not used on the page). The page acknowledges OpenClaw and the 22 source benchmarks.
|
README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: OmniStepBench
|
| 3 |
+
emoji: 🦞
|
| 4 |
+
colorFrom: red
|
| 5 |
+
colorTo: blue
|
| 6 |
+
sdk: static
|
| 7 |
+
app_file: index.html
|
| 8 |
+
pinned: true
|
| 9 |
+
short_description: Deployment-Aware Agent Evaluation across Modalities
|
| 10 |
+
tags:
|
| 11 |
+
- benchmark
|
| 12 |
+
- agents
|
| 13 |
+
- openclaw
|
| 14 |
+
- evaluation
|
| 15 |
+
- leaderboard
|
| 16 |
+
datasets:
|
| 17 |
+
- SeerRay-Lab/OmniStepBench
|
| 18 |
+
thumbnail: https://seerray-lab-omnistepbench.static.hf.space/assets/img/social-card.png
|
| 19 |
+
---
|
| 20 |
+
|
| 21 |
+
# OmniStepBench: Deployment-Aware Agent Evaluation across Modalities and Task Complexity
|
| 22 |
+
|
| 23 |
+
Project page for OmniStepBench (mirror of https://seerray-lab.github.io/OmniStepBench/). A benchmark for deployment-aware agent evaluation across modalities and task complexity.
|
| 24 |
+
|
| 25 |
+
- 🌐 Homepage: https://seerray-lab.github.io/OmniStepBench/
|
| 26 |
+
- 📄 Paper: [arXiv 2609.06059](https://arxiv.org/abs/2609.06059)
|
| 27 |
+
- 💻 Code: [SeerRay-Lab/OmniStepBench](https://github.com/SeerRay-Lab/OmniStepBench)
|
| 28 |
+
- 🤗 Dataset: [SeerRay-Lab/OmniStepBench](https://huggingface.co/datasets/SeerRay-Lab/OmniStepBench)
|
assets/css/palette.css
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ==========================================================================
|
| 2 |
+
OmniStepBench homepage: color tokens (light theme only)
|
| 3 |
+
--------------------------------------------------------------------------
|
| 4 |
+
Visual source: the paper's Fig. 2 panel colors (1 blue / 2 green /
|
| 5 |
+
3 orange / 4 purple) plus the OpenClaw lobster red.
|
| 6 |
+
Method: dataviz color formula. Every DATA token below was checked with the
|
| 7 |
+
official validator (validate_palette.js, --mode light) against both page
|
| 8 |
+
surfaces, cream #FFF8EC and white #FFFFFF.
|
| 9 |
+
Verdicts are in palette.json; the usage rules are summarized below.
|
| 10 |
+
|
| 11 |
+
RULES FOR CHART AUTHORS
|
| 12 |
+
- Marks carry series colors. Labels, values, legends and axis text use ink
|
| 13 |
+
tokens, never a series color.
|
| 14 |
+
- Color follows the entity, not its rank. Keep the slot order below fixed.
|
| 15 |
+
- WARN: the light workload steps (--wl-text-ss, --wl-mm-ss) and
|
| 16 |
+
--pareto-muted are below 3:1 on the surface. Any chart that uses them
|
| 17 |
+
needs a relief channel: visible direct labels or the table view (every
|
| 18 |
+
chart ships a table view anyway).
|
| 19 |
+
- Status colors are reserved for state. Always pair them with an icon and
|
| 20 |
+
a label. Never use them for a series.
|
| 21 |
+
- Labels inside a colored mark use the matching --*-on token, which is the
|
| 22 |
+
one that clears 4.5:1. If a fill has no 4.5:1 on-color, put the label
|
| 23 |
+
outside the bar end in --ink.
|
| 24 |
+
========================================================================== */
|
| 25 |
+
|
| 26 |
+
:root {
|
| 27 |
+
color-scheme: light;
|
| 28 |
+
|
| 29 |
+
/* ---- Surfaces ---------------------------------------------------------- */
|
| 30 |
+
--surface-page: #FFF8EC; /* cream page plane (validator surface #1) */
|
| 31 |
+
--surface-card: #FFFFFF; /* chart cards / figures (validator surface #2) */
|
| 32 |
+
--surface-sunken: #F6ECDA; /* code blocks, table zebra, wells */
|
| 33 |
+
|
| 34 |
+
/* ---- Ink (text + cartoon outline) --------------------------------------
|
| 35 |
+
Contrast on cream / white:
|
| 36 |
+
ink 14.92 / 15.75, ink-2 7.84 / 8.28, ink-muted 5.89 / 6.22 (all pass AA) */
|
| 37 |
+
--ink: #2B2118; /* primary text, thick cartoon outlines, hard shadows */
|
| 38 |
+
--ink-2: #5A4C3D; /* secondary text */
|
| 39 |
+
--ink-muted: #6B5F50; /* captions, axis tick labels (still >= 4.5:1) */
|
| 40 |
+
--ink-inverse: #FFFFFF;
|
| 41 |
+
--outline: var(--ink);
|
| 42 |
+
|
| 43 |
+
/* ---- Chart chrome (hairlines, recessive) ------------------------------- */
|
| 44 |
+
--chart-grid: #ECE3D3; /* 1px solid gridlines */
|
| 45 |
+
--chart-axis: #CDBFA8; /* 1px baseline / axis rule */
|
| 46 |
+
--chart-ring: var(--surface-card); /* 2px surface ring around dots */
|
| 47 |
+
--chart-gap: var(--surface-card); /* 2px surface gap between touching bars */
|
| 48 |
+
|
| 49 |
+
/* ---- Brand: OpenClaw lobster (UI accent, NOT a data color) -------------- */
|
| 50 |
+
--lobster: #EC624A; /* fills, logo, big shapes; ink text on it 4.81:1 */
|
| 51 |
+
--lobster-ink: #B93D27; /* lobster-colored text/links: 5.29 cream / 5.59 white */
|
| 52 |
+
|
| 53 |
+
/* ---- Section chrome (from Fig. 2 panels; UI only, NOT data colors) -----
|
| 54 |
+
Contrast: fill vs --ink >= 13.6; sec ink vs its fill >= 4.9; edge vs cream >= 3.27;
|
| 55 |
+
white on badge >= 5.17 */
|
| 56 |
+
--sec-blue-fill: #EAF2FD; --sec-blue-edge: #4774CA; --sec-blue-badge: #1455B8; --sec-blue-ink: #1455B8;
|
| 57 |
+
--sec-green-fill: #EDF8EA; --sec-green-edge: #578E31; --sec-green-badge: #29793A; --sec-green-ink: #29793A;
|
| 58 |
+
--sec-orange-fill: #FDF0E2; --sec-orange-edge: #D86C1F; --sec-orange-badge: #B0520C; --sec-orange-ink: #A94F0A;
|
| 59 |
+
--sec-purple-fill: #F1ECFB; --sec-purple-edge: #6F2F9F; --sec-purple-badge: #6C47AD; --sec-purple-ink: #6C47AD;
|
| 60 |
+
|
| 61 |
+
/* ======================================================================
|
| 62 |
+
DATA COLORS
|
| 63 |
+
====================================================================== */
|
| 64 |
+
|
| 65 |
+
/* (a) Deployment: API vs Local. 2 slots, fixed order.
|
| 66 |
+
PASS on cream and white: CVD dE 23.7 (deutan), normal dE 31.1, both >= 3:1 */
|
| 67 |
+
--series-api: #7444B4; /* violet, from Fig. 2 panel 4 */
|
| 68 |
+
--series-local: #3C8836; /* green, from Fig. 2 panel 2 */
|
| 69 |
+
--series-api-on: #FFFFFF; /* 6.50:1 */
|
| 70 |
+
--series-local-on:#FFFFFF; /* 4.41:1, so bold >= 14pt only; otherwise label outside the bar in --ink */
|
| 71 |
+
|
| 72 |
+
/* (b) Modality: Text vs Multimodal. 2 slots, fixed order.
|
| 73 |
+
PASS on cream and white: CVD dE 28.6 (protan), normal dE 31.6, both >= 3:1.
|
| 74 |
+
These are the middle steps of the two workload families in (c). */
|
| 75 |
+
--series-text: #4A7AE4; /* blue, from Fig. 2 panel 1 */
|
| 76 |
+
--series-mm: #CC580B; /* orange, from Fig. 2 panel 3 */
|
| 77 |
+
--series-text-on: #FFFFFF; /* 4.04:1, so bold >= 14pt only */
|
| 78 |
+
--series-mm-on: #FFFFFF; /* 4.23:1, so bold >= 14pt only */
|
| 79 |
+
/* (b') Overall = both modalities combined (the leaderboard's aggregate column).
|
| 80 |
+
A DELIBERATE NEUTRAL, not a third categorical hue: it must not compete with
|
| 81 |
+
text/mm, and every free hue is taken (violet = API, green = local,
|
| 82 |
+
raspberry = Pareto, teal = heat ramp, reds/yellows = status).
|
| 83 |
+
validate_palette "#4A7AE4,#CC580B,#5B6878" (white and #F3FAFB):
|
| 84 |
+
lightness band PASS, CVD PASS (dE 13.6 protan), normal-vision PASS
|
| 85 |
+
(dE 21.1), contrast PASS (5.68:1 on white); chroma floor FAIL as expected
|
| 86 |
+
for a neutral (C 0.03). Distinct from the text token --ink-2 (1.48:1). */
|
| 87 |
+
--series-overall: #5B6878;
|
| 88 |
+
|
| 89 |
+
/* (c) Workload groups. 6 slots in a FIXED order:
|
| 90 |
+
text-ss, text-ms, text-mt, mm-ss, mm-ms, mm-mt
|
| 91 |
+
Composite encoding: hue = modality (blue family / orange family) and
|
| 92 |
+
lightness = execution complexity (single-step light, multi-step mid,
|
| 93 |
+
multi-step+tools dark), which mirrors the paper's Workload Matrix.
|
| 94 |
+
Categorical, adjacent pairs: PASS on both surfaces (worst CVD dE 13.6,
|
| 95 |
+
normal dE 15.7). The same holds on all pairs, so scatter and small
|
| 96 |
+
multiples are allowed.
|
| 97 |
+
WARN: contrast. --wl-text-ss (2.21 cream / 2.33 white) and --wl-mm-ss
|
| 98 |
+
(2.28 / 2.41) are below 3:1 and need relief (direct labels or table view).
|
| 99 |
+
Each family also PASSES the --ordinal ramp check (monotone L, dL >= 0.06,
|
| 100 |
+
hue spread 36 deg). */
|
| 101 |
+
--wl-text-ss: #18B6F2;
|
| 102 |
+
--wl-text-ms: #4A7AE4;
|
| 103 |
+
--wl-text-mt: #2C45AE;
|
| 104 |
+
--wl-mm-ss: #E29805;
|
| 105 |
+
--wl-mm-ms: #CC580B;
|
| 106 |
+
--wl-mm-mt: #922B01;
|
| 107 |
+
/* in-mark label colors (>= 4.5:1 only where noted; else label outside in --ink) */
|
| 108 |
+
--wl-text-ss-on: #2B2118; /* 6.76 */
|
| 109 |
+
--wl-text-mt-on: #FFFFFF; /* 8.17 */
|
| 110 |
+
--wl-mm-ss-on: #2B2118; /* 6.54 */
|
| 111 |
+
--wl-mm-mt-on: #FFFFFF; /* 8.18 */
|
| 112 |
+
/* --wl-text-ms and --wl-mm-ms: best on-color is 4.04 / 4.23, so use only for
|
| 113 |
+
bold text >= 14pt (18.66px), otherwise put the label outside the bar */
|
| 114 |
+
|
| 115 |
+
/* (d) Sequential heat ramp for leaderboard cells: one hue (teal), light to dark.
|
| 116 |
+
Teal is not used by any series, so a heat cell never reads as a modality or
|
| 117 |
+
a deployment type. Lightness is monotone and every step gap is >= 0.06.
|
| 118 |
+
Full 100-700 ramp: the light end recedes to the surface by design
|
| 119 |
+
(sequential), so the ordinal "light-end >= 2:1" check FAILS as expected.
|
| 120 |
+
Steps 400-700 used as an ordinal ramp: PASS on both surfaces. The
|
| 121 |
+
leaderboard's heat mode uses exactly these four steps (light end 2.16:1
|
| 122 |
+
on white, validate_palette --ordinal PASS).
|
| 123 |
+
Always print the number in the cell and show a scale legend, so color never
|
| 124 |
+
carries the value alone. */
|
| 125 |
+
--seq-100: #DEFAF7; --seq-100-on: #2B2118; /* 14.34 */
|
| 126 |
+
--seq-200: #B0EBE7; --seq-200-on: #2B2118; /* 11.91 */
|
| 127 |
+
--seq-300: #7EDAD7; --seq-300-on: #2B2118; /* 9.67 */
|
| 128 |
+
--seq-400: #40C2C3; --seq-400-on: #2B2118; /* 7.29 */
|
| 129 |
+
--seq-500: #02A6AD; --seq-500-on: #2B2118; /* 5.29 */
|
| 130 |
+
--seq-600: #0A818B; --seq-600-on: #FFFFFF; /* 4.64 */
|
| 131 |
+
--seq-700: #055F6C; --seq-700-on: #FFFFFF; /* 7.34 */
|
| 132 |
+
|
| 133 |
+
/* (e) Pareto emphasis: highlight the frontier, mute everything else.
|
| 134 |
+
The highlight is raspberry, a hue no series uses, so it reads the same in
|
| 135 |
+
the Text and Multimodal panels.
|
| 136 |
+
Highlight alone: PASS (L 0.52, C 0.20, 5.84 cream / 6.16 white).
|
| 137 |
+
Highlight vs muted: CVD dE 17.7 (deutan), normal dE 26.9, PASS. The
|
| 138 |
+
separation is carried mainly by lightness, which survives CVD.
|
| 139 |
+
Expected findings on the muted gray: chroma-floor FAIL (it is a
|
| 140 |
+
de-emphasis gray, not a categorical slot) and a contrast WARN
|
| 141 |
+
(2.54 cream / 2.68 white), so give muted points hover/focus tooltips
|
| 142 |
+
plus the table view.
|
| 143 |
+
All-pairs co-occurrence PASS: with (b) {text, mm, pareto-hi}, worst CVD
|
| 144 |
+
dE 16.8; with (a) {api, local, pareto-hi}, worst CVD dE 10.1. */
|
| 145 |
+
--pareto-hi: #B51C79;
|
| 146 |
+
--pareto-hi-on: #FFFFFF; /* 6.16 */
|
| 147 |
+
--pareto-muted: #A59D92;
|
| 148 |
+
--pareto-muted-on:#2B2118; /* 5.88 */
|
| 149 |
+
|
| 150 |
+
/* ---- Status (fixed, reserved; always icon + label, never a series) ----- */
|
| 151 |
+
--status-good: #0CA30C;
|
| 152 |
+
--status-warning: #FAB219;
|
| 153 |
+
--status-serious: #EC835A;
|
| 154 |
+
--status-critical: #D03B3B;
|
| 155 |
+
--status-good-text:#006300; /* success text on light surfaces */
|
| 156 |
+
}
|
assets/css/style.css
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
assets/data/data.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
assets/fonts/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# OmniStepBench homepage: local webfonts
|
| 2 |
+
|
| 3 |
+
These fonts are self-hosted, so the pages render offline, from mainland China and
|
| 4 |
+
over `file://`, with no CDN. Every file is a WOFF2 **latin subset**, downloaded
|
| 5 |
+
from the Google Fonts CSS2 API (fonts.gstatic.com), and all six families are licensed under the
|
| 6 |
+
**SIL Open Font License 1.1**. The license texts are in `licenses/`, copied from
|
| 7 |
+
github.com/google/fonts `ofl/<family>/OFL.txt`.
|
| 8 |
+
|
| 9 |
+
Include the fonts with `<link rel="stylesheet" href="shared/fonts/fonts.css">`.
|
| 10 |
+
The path is relative to the page. The `url()`s inside `fonts.css` are relative
|
| 11 |
+
to that CSS file.
|
| 12 |
+
|
| 13 |
+
`fonts.inline.css` is a generated alternative with the same `@font-face`
|
| 14 |
+
rules, but every font is inlined as a base64 `data:` URI (357 KB). Use it
|
| 15 |
+
instead of `fonts.css` only when a page is **not** in the same directory as
|
| 16 |
+
`shared/`, or in a parent of it, and must also work over `file://` in Firefox.
|
| 17 |
+
Firefox's strict file-origin policy can block font files from a parent
|
| 18 |
+
directory. Chromium loads both variants over `file://`; this was tested.
|
| 19 |
+
Only Chromium was available here, so Firefox itself was not tested.
|
| 20 |
+
|
| 21 |
+
| CSS `font-family` | Role (token in fonts.css) | File | Axis / weights | Style | Upstream version | License |
|
| 22 |
+
|---|---|---|---|---|---|---|
|
| 23 |
+
| `"Fredoka"` | rounded cartoon display (`--font-display`) | `fredoka-latin-wght.woff2` (29.7 KB) | variable wght 300–700 | normal | Fredoka 2.001 (gstatic v17) | OFL 1.1, © 2016 The Fredoka Project Authors |
|
| 24 |
+
| `"Bangers"` | comic headline, all-caps (`--font-comic`) | `bangers-latin-400.woff2` (23.5 KB) | 400 | normal | Bangers 2.100 (v25) | OFL 1.1, © 2010 The Bangers Project Authors |
|
| 25 |
+
| `"Patrick Hand"` | hand-drawn accent, small notes (`--font-hand`) | `patrickhand-latin-400.woff2` (23.9 KB) | 400 | normal | Patrick Hand 1.003 (v25) | OFL 1.1, © 2010–2012 Patrick Wagesreiter |
|
| 26 |
+
| `"Caveat"` | handwritten scribble, large annotations only (`--font-scribble`) | `caveat-latin-wght.woff2` (74.9 KB) | variable wght 400–700 | normal | Caveat 2.000 (v23) | OFL 1.1, © 2014 The Caveat Project Authors |
|
| 27 |
+
| `"Nunito"` | body text, UI, chart text (`--font-body`) | `nunito-latin-wght.woff2` (39.1 KB) | variable wght 200–1000 | normal | Nunito 3.602 (v32) | OFL 1.1, © 2014 The Nunito Project Authors |
|
| 28 |
+
| `"Nunito"` | body italic | `nunito-latin-wght-italic.woff2` (41.8 KB) | variable wght 200–1000 | italic | Nunito 3.602 (v32) | OFL 1.1 |
|
| 29 |
+
| `"JetBrains Mono"` | code, CLI flags, task ids (`--font-mono`) | `jetbrainsmono-latin-wght.woff2` (31.4 KB) | variable wght 400–800 (use 400/700) | normal | JetBrains Mono 2.211 (v24) | OFL 1.1, © 2020 The JetBrains Mono Project Authors |
|
| 30 |
+
|
| 31 |
+
Total: about 264 KB. A browser downloads a face only when some text uses it.
|
| 32 |
+
|
| 33 |
+
## Verification (2026-09-23)
|
| 34 |
+
|
| 35 |
+
- Each file starts with the `wOF2` magic bytes. Each also decodes with Node's
|
| 36 |
+
built-in brotli, and its `name`, `fvar`, `maxp` and `cmap` tables parse. The
|
| 37 |
+
inspector is `homepage/tools/fonts/woff2info.cjs`.
|
| 38 |
+
- Each file's md5 matches a fresh re-download of the same gstatic URL.
|
| 39 |
+
- Axis ranges are read from the `fvar` table:
|
| 40 |
+
- Fredoka: wght 300–700
|
| 41 |
+
- Caveat: wght 400–700
|
| 42 |
+
- Nunito: wght 200–1000
|
| 43 |
+
- JetBrains Mono: wght 400–800
|
| 44 |
+
- Coverage: every face maps ASCII A–Z, a–z, 0–9 and the usual punctuation, plus
|
| 45 |
+
`– — ’ “ ” · × ±`. None of the latin subsets contains `→` (U+2192) or `≈`
|
| 46 |
+
(U+2248). These characters render in the next font of the stack, so use
|
| 47 |
+
inline SVG icons for arrows in headings.
|
| 48 |
+
- A specimen page was rendered in headless Chromium over `file://`:
|
| 49 |
+
`homepage/tools/fonts/specimen.html`, with screenshots in `shots/`.
|
| 50 |
+
With both `fonts.css` and `fonts.inline.css`, all seven faces reported
|
| 51 |
+
"loaded", `document.fonts.check()` returned true for every family and
|
| 52 |
+
weight, and the page had no console errors and no failed requests. The
|
| 53 |
+
glyphs were inspected visually.
|
| 54 |
+
|
| 55 |
+
## Usage notes
|
| 56 |
+
|
| 57 |
+
- **Bangers** has uppercase-style glyphs only, so lowercase input renders as
|
| 58 |
+
small caps. Use it for short punchy labels such as section kickers and
|
| 59 |
+
badges. Do not use it for sentences or numbers that people need to read
|
| 60 |
+
precisely.
|
| 61 |
+
- **Numbers.** Nunito's default figures are already **tabular**. In Chromium
|
| 62 |
+
at 40px, `1111` and `0000` both measure 96.0px. The subset has no `tnum` or
|
| 63 |
+
`pnum` feature, so `font-variant-numeric` changes nothing. As a result,
|
| 64 |
+
leaderboard and table columns align on their own; right-align them. Hero
|
| 65 |
+
numbers will also use equal-width digits, which is an accepted trade-off.
|
| 66 |
+
Fredoka figures are proportional (`1111` 64px vs `0000` 92px). Do not use
|
| 67 |
+
Fredoka or Bangers for numbers in tables, charts or stat tiles: keep figures
|
| 68 |
+
in `--font-body` (dataviz rule: no display face on figures).
|
| 69 |
+
- **JetBrains Mono ligatures.** The subset has `calt` ligatures, so `=>`
|
| 70 |
+
renders as a single arrow glyph. Set `font-variant-ligatures: none` on code
|
| 71 |
+
and CLI blocks so users see the literal characters they will type.
|
| 72 |
+
- **Luckiest Guy** was considered and **rejected**: it is Apache-2.0, not OFL.
|
| 73 |
+
Bangers fills the comic-headline role.
|
| 74 |
+
- To refresh the fonts, request
|
| 75 |
+
`https://fonts.googleapis.com/css2?family=...&display=swap` with a modern Chrome
|
| 76 |
+
User-Agent. Take only the `/* latin */` block of each family. Keep the
|
| 77 |
+
`unicode-range` shown in `fonts.css`.
|
assets/fonts/bangers-latin-400.woff2
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:04f54ff42ea2b8fc50b4259c29c60b1e05e606b769c2fb541c98624346c9767c
|
| 3 |
+
size 23528
|
assets/fonts/caveat-latin-wght.woff2
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:891951df5e8b5b0f0bc760d31375405e795c666b5add70437de12d4a6482b33f
|
| 3 |
+
size 74932
|
assets/fonts/fonts.css
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ==========================================================================
|
| 2 |
+
OmniStepBench homepage: local webfonts (latin subset, woff2, SIL OFL 1.1).
|
| 3 |
+
Self-hosted, no network or CDN dependency. The URLs are relative to this
|
| 4 |
+
file, so the fonts also load when the page is opened via file://.
|
| 5 |
+
Details and license texts: README.md and licenses/ in this folder.
|
| 6 |
+
========================================================================== */
|
| 7 |
+
|
| 8 |
+
/* Latin subset coverage (same unicode-range Google Fonts uses for "latin").
|
| 9 |
+
Characters outside it, e.g. the arrow and approx signs, fall back to the next
|
| 10 |
+
family in the stack. */
|
| 11 |
+
|
| 12 |
+
/* Fredoka: rounded cartoon display face (variable, wght 300-700) */
|
| 13 |
+
@font-face {
|
| 14 |
+
font-family: "Fredoka";
|
| 15 |
+
font-style: normal;
|
| 16 |
+
font-weight: 300 700;
|
| 17 |
+
font-display: swap;
|
| 18 |
+
src: url("fredoka-latin-wght.woff2") format("woff2");
|
| 19 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
/* Bangers: comic headline face (400 only; all caps by design) */
|
| 23 |
+
@font-face {
|
| 24 |
+
font-family: "Bangers";
|
| 25 |
+
font-style: normal;
|
| 26 |
+
font-weight: 400;
|
| 27 |
+
font-display: swap;
|
| 28 |
+
src: url("bangers-latin-400.woff2") format("woff2");
|
| 29 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
/* Patrick Hand: hand-drawn accent (400). Legible at small sizes (notes, badges). */
|
| 33 |
+
@font-face {
|
| 34 |
+
font-family: "Patrick Hand";
|
| 35 |
+
font-style: normal;
|
| 36 |
+
font-weight: 400;
|
| 37 |
+
font-display: swap;
|
| 38 |
+
src: url("patrickhand-latin-400.woff2") format("woff2");
|
| 39 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
/* Caveat: handwritten scribble (variable, wght 400-700). Use only for short, large annotations. */
|
| 43 |
+
@font-face {
|
| 44 |
+
font-family: "Caveat";
|
| 45 |
+
font-style: normal;
|
| 46 |
+
font-weight: 400 700;
|
| 47 |
+
font-display: swap;
|
| 48 |
+
src: url("caveat-latin-wght.woff2") format("woff2");
|
| 49 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
/* Nunito: friendly, readable body face (variable, wght 200-1000, upright + italic) */
|
| 53 |
+
@font-face {
|
| 54 |
+
font-family: "Nunito";
|
| 55 |
+
font-style: normal;
|
| 56 |
+
font-weight: 200 1000;
|
| 57 |
+
font-display: swap;
|
| 58 |
+
src: url("nunito-latin-wght.woff2") format("woff2");
|
| 59 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 60 |
+
}
|
| 61 |
+
@font-face {
|
| 62 |
+
font-family: "Nunito";
|
| 63 |
+
font-style: italic;
|
| 64 |
+
font-weight: 200 1000;
|
| 65 |
+
font-display: swap;
|
| 66 |
+
src: url("nunito-latin-wght-italic.woff2") format("woff2");
|
| 67 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
/* JetBrains Mono: code, CLI flags, task ids (variable, wght 400-800; use 400 and 700) */
|
| 71 |
+
@font-face {
|
| 72 |
+
font-family: "JetBrains Mono";
|
| 73 |
+
font-style: normal;
|
| 74 |
+
font-weight: 400 800;
|
| 75 |
+
font-display: swap;
|
| 76 |
+
src: url("jetbrainsmono-latin-wght.woff2") format("woff2");
|
| 77 |
+
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
/* Font-stack tokens. Every stack ends in a system fallback, so text stays
|
| 81 |
+
readable if a woff2 fails to load. */
|
| 82 |
+
:root {
|
| 83 |
+
--font-display: "Fredoka", "Nunito", ui-rounded, "Segoe UI", system-ui, -apple-system, sans-serif;
|
| 84 |
+
--font-comic: "Bangers", "Fredoka", "Impact", "Arial Black", system-ui, sans-serif;
|
| 85 |
+
--font-hand: "Patrick Hand", "Caveat", "Comic Sans MS", "Segoe Print", cursive;
|
| 86 |
+
--font-scribble:"Caveat", "Patrick Hand", "Segoe Print", cursive;
|
| 87 |
+
--font-body: "Nunito", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
|
| 88 |
+
--font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace;
|
| 89 |
+
}
|
assets/fonts/fonts.inline.css
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
assets/fonts/fredoka-latin-wght.woff2
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:99d6c78e043710d4f83ed90716779798b7b04eb690f73e0ad0e8f32d1f0e98c2
|
| 3 |
+
size 29732
|
assets/fonts/jetbrainsmono-latin-wght.woff2
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:83c005d49d8a6a50474c73a5a36ac0468076e9c4a29da7bdb14995d80560a5be
|
| 3 |
+
size 31432
|
assets/fonts/licenses/bangers-OFL.txt
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Copyright 2010 The Bangers Project Authors (https://github.com/googlefonts/bangers)
|
| 2 |
+
|
| 3 |
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
| 4 |
+
This license is copied below, and is also available with a FAQ at:
|
| 5 |
+
https://scripts.sil.org/OFL
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
-----------------------------------------------------------
|
| 9 |
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
| 10 |
+
-----------------------------------------------------------
|
| 11 |
+
|
| 12 |
+
PREAMBLE
|
| 13 |
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
| 14 |
+
development of collaborative font projects, to support the font creation
|
| 15 |
+
efforts of academic and linguistic communities, and to provide a free and
|
| 16 |
+
open framework in which fonts may be shared and improved in partnership
|
| 17 |
+
with others.
|
| 18 |
+
|
| 19 |
+
The OFL allows the licensed fonts to be used, studied, modified and
|
| 20 |
+
redistributed freely as long as they are not sold by themselves. The
|
| 21 |
+
fonts, including any derivative works, can be bundled, embedded,
|
| 22 |
+
redistributed and/or sold with any software provided that any reserved
|
| 23 |
+
names are not used by derivative works. The fonts and derivatives,
|
| 24 |
+
however, cannot be released under any other type of license. The
|
| 25 |
+
requirement for fonts to remain under this license does not apply
|
| 26 |
+
to any document created using the fonts or their derivatives.
|
| 27 |
+
|
| 28 |
+
DEFINITIONS
|
| 29 |
+
"Font Software" refers to the set of files released by the Copyright
|
| 30 |
+
Holder(s) under this license and clearly marked as such. This may
|
| 31 |
+
include source files, build scripts and documentation.
|
| 32 |
+
|
| 33 |
+
"Reserved Font Name" refers to any names specified as such after the
|
| 34 |
+
copyright statement(s).
|
| 35 |
+
|
| 36 |
+
"Original Version" refers to the collection of Font Software components as
|
| 37 |
+
distributed by the Copyright Holder(s).
|
| 38 |
+
|
| 39 |
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
| 40 |
+
or substituting -- in part or in whole -- any of the components of the
|
| 41 |
+
Original Version, by changing formats or by porting the Font Software to a
|
| 42 |
+
new environment.
|
| 43 |
+
|
| 44 |
+
"Author" refers to any designer, engineer, programmer, technical
|
| 45 |
+
writer or other person who contributed to the Font Software.
|
| 46 |
+
|
| 47 |
+
PERMISSION & CONDITIONS
|
| 48 |
+
Permission is hereby granted, free of charge, to any person obtaining
|
| 49 |
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
| 50 |
+
redistribute, and sell modified and unmodified copies of the Font
|
| 51 |
+
Software, subject to the following conditions:
|
| 52 |
+
|
| 53 |
+
1) Neither the Font Software nor any of its individual components,
|
| 54 |
+
in Original or Modified Versions, may be sold by itself.
|
| 55 |
+
|
| 56 |
+
2) Original or Modified Versions of the Font Software may be bundled,
|
| 57 |
+
redistributed and/or sold with any software, provided that each copy
|
| 58 |
+
contains the above copyright notice and this license. These can be
|
| 59 |
+
included either as stand-alone text files, human-readable headers or
|
| 60 |
+
in the appropriate machine-readable metadata fields within text or
|
| 61 |
+
binary files as long as those fields can be easily viewed by the user.
|
| 62 |
+
|
| 63 |
+
3) No Modified Version of the Font Software may use the Reserved Font
|
| 64 |
+
Name(s) unless explicit written permission is granted by the corresponding
|
| 65 |
+
Copyright Holder. This restriction only applies to the primary font name as
|
| 66 |
+
presented to the users.
|
| 67 |
+
|
| 68 |
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
| 69 |
+
Software shall not be used to promote, endorse or advertise any
|
| 70 |
+
Modified Version, except to acknowledge the contribution(s) of the
|
| 71 |
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
| 72 |
+
permission.
|
| 73 |
+
|
| 74 |
+
5) The Font Software, modified or unmodified, in part or in whole,
|
| 75 |
+
must be distributed entirely under this license, and must not be
|
| 76 |
+
distributed under any other license. The requirement for fonts to
|
| 77 |
+
remain under this license does not apply to any document created
|
| 78 |
+
using the Font Software.
|
| 79 |
+
|
| 80 |
+
TERMINATION
|
| 81 |
+
This license becomes null and void if any of the above conditions are
|
| 82 |
+
not met.
|
| 83 |
+
|
| 84 |
+
DISCLAIMER
|
| 85 |
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
| 86 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
| 87 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
| 88 |
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
| 89 |
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
| 90 |
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
| 91 |
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
| 92 |
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
| 93 |
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
assets/fonts/licenses/caveat-OFL.txt
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Copyright 2014 The Caveat Project Authors (https://github.com/googlefonts/caveat)
|
| 2 |
+
|
| 3 |
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
| 4 |
+
This license is copied below, and is also available with a FAQ at:
|
| 5 |
+
http://scripts.sil.org/OFL
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
-----------------------------------------------------------
|
| 9 |
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
| 10 |
+
-----------------------------------------------------------
|
| 11 |
+
|
| 12 |
+
PREAMBLE
|
| 13 |
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
| 14 |
+
development of collaborative font projects, to support the font creation
|
| 15 |
+
efforts of academic and linguistic communities, and to provide a free and
|
| 16 |
+
open framework in which fonts may be shared and improved in partnership
|
| 17 |
+
with others.
|
| 18 |
+
|
| 19 |
+
The OFL allows the licensed fonts to be used, studied, modified and
|
| 20 |
+
redistributed freely as long as they are not sold by themselves. The
|
| 21 |
+
fonts, including any derivative works, can be bundled, embedded,
|
| 22 |
+
redistributed and/or sold with any software provided that any reserved
|
| 23 |
+
names are not used by derivative works. The fonts and derivatives,
|
| 24 |
+
however, cannot be released under any other type of license. The
|
| 25 |
+
requirement for fonts to remain under this license does not apply
|
| 26 |
+
to any document created using the fonts or their derivatives.
|
| 27 |
+
|
| 28 |
+
DEFINITIONS
|
| 29 |
+
"Font Software" refers to the set of files released by the Copyright
|
| 30 |
+
Holder(s) under this license and clearly marked as such. This may
|
| 31 |
+
include source files, build scripts and documentation.
|
| 32 |
+
|
| 33 |
+
"Reserved Font Name" refers to any names specified as such after the
|
| 34 |
+
copyright statement(s).
|
| 35 |
+
|
| 36 |
+
"Original Version" refers to the collection of Font Software components as
|
| 37 |
+
distributed by the Copyright Holder(s).
|
| 38 |
+
|
| 39 |
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
| 40 |
+
or substituting -- in part or in whole -- any of the components of the
|
| 41 |
+
Original Version, by changing formats or by porting the Font Software to a
|
| 42 |
+
new environment.
|
| 43 |
+
|
| 44 |
+
"Author" refers to any designer, engineer, programmer, technical
|
| 45 |
+
writer or other person who contributed to the Font Software.
|
| 46 |
+
|
| 47 |
+
PERMISSION & CONDITIONS
|
| 48 |
+
Permission is hereby granted, free of charge, to any person obtaining
|
| 49 |
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
| 50 |
+
redistribute, and sell modified and unmodified copies of the Font
|
| 51 |
+
Software, subject to the following conditions:
|
| 52 |
+
|
| 53 |
+
1) Neither the Font Software nor any of its individual components,
|
| 54 |
+
in Original or Modified Versions, may be sold by itself.
|
| 55 |
+
|
| 56 |
+
2) Original or Modified Versions of the Font Software may be bundled,
|
| 57 |
+
redistributed and/or sold with any software, provided that each copy
|
| 58 |
+
contains the above copyright notice and this license. These can be
|
| 59 |
+
included either as stand-alone text files, human-readable headers or
|
| 60 |
+
in the appropriate machine-readable metadata fields within text or
|
| 61 |
+
binary files as long as those fields can be easily viewed by the user.
|
| 62 |
+
|
| 63 |
+
3) No Modified Version of the Font Software may use the Reserved Font
|
| 64 |
+
Name(s) unless explicit written permission is granted by the corresponding
|
| 65 |
+
Copyright Holder. This restriction only applies to the primary font name as
|
| 66 |
+
presented to the users.
|
| 67 |
+
|
| 68 |
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
| 69 |
+
Software shall not be used to promote, endorse or advertise any
|
| 70 |
+
Modified Version, except to acknowledge the contribution(s) of the
|
| 71 |
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
| 72 |
+
permission.
|
| 73 |
+
|
| 74 |
+
5) The Font Software, modified or unmodified, in part or in whole,
|
| 75 |
+
must be distributed entirely under this license, and must not be
|
| 76 |
+
distributed under any other license. The requirement for fonts to
|
| 77 |
+
remain under this license does not apply to any document created
|
| 78 |
+
using the Font Software.
|
| 79 |
+
|
| 80 |
+
TERMINATION
|
| 81 |
+
This license becomes null and void if any of the above conditions are
|
| 82 |
+
not met.
|
| 83 |
+
|
| 84 |
+
DISCLAIMER
|
| 85 |
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
| 86 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
| 87 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
| 88 |
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
| 89 |
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
| 90 |
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
| 91 |
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
| 92 |
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
| 93 |
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
assets/fonts/licenses/fredoka-OFL.txt
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Copyright 2016 The Fredoka Project Authors (https://github.com/hafontia/Fredoka-One)
|
| 2 |
+
|
| 3 |
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
| 4 |
+
This license is copied below, and is also available with a FAQ at:
|
| 5 |
+
http://scripts.sil.org/OFL
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
-----------------------------------------------------------
|
| 9 |
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
| 10 |
+
-----------------------------------------------------------
|
| 11 |
+
|
| 12 |
+
PREAMBLE
|
| 13 |
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
| 14 |
+
development of collaborative font projects, to support the font creation
|
| 15 |
+
efforts of academic and linguistic communities, and to provide a free and
|
| 16 |
+
open framework in which fonts may be shared and improved in partnership
|
| 17 |
+
with others.
|
| 18 |
+
|
| 19 |
+
The OFL allows the licensed fonts to be used, studied, modified and
|
| 20 |
+
redistributed freely as long as they are not sold by themselves. The
|
| 21 |
+
fonts, including any derivative works, can be bundled, embedded,
|
| 22 |
+
redistributed and/or sold with any software provided that any reserved
|
| 23 |
+
names are not used by derivative works. The fonts and derivatives,
|
| 24 |
+
however, cannot be released under any other type of license. The
|
| 25 |
+
requirement for fonts to remain under this license does not apply
|
| 26 |
+
to any document created using the fonts or their derivatives.
|
| 27 |
+
|
| 28 |
+
DEFINITIONS
|
| 29 |
+
"Font Software" refers to the set of files released by the Copyright
|
| 30 |
+
Holder(s) under this license and clearly marked as such. This may
|
| 31 |
+
include source files, build scripts and documentation.
|
| 32 |
+
|
| 33 |
+
"Reserved Font Name" refers to any names specified as such after the
|
| 34 |
+
copyright statement(s).
|
| 35 |
+
|
| 36 |
+
"Original Version" refers to the collection of Font Software components as
|
| 37 |
+
distributed by the Copyright Holder(s).
|
| 38 |
+
|
| 39 |
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
| 40 |
+
or substituting -- in part or in whole -- any of the components of the
|
| 41 |
+
Original Version, by changing formats or by porting the Font Software to a
|
| 42 |
+
new environment.
|
| 43 |
+
|
| 44 |
+
"Author" refers to any designer, engineer, programmer, technical
|
| 45 |
+
writer or other person who contributed to the Font Software.
|
| 46 |
+
|
| 47 |
+
PERMISSION & CONDITIONS
|
| 48 |
+
Permission is hereby granted, free of charge, to any person obtaining
|
| 49 |
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
| 50 |
+
redistribute, and sell modified and unmodified copies of the Font
|
| 51 |
+
Software, subject to the following conditions:
|
| 52 |
+
|
| 53 |
+
1) Neither the Font Software nor any of its individual components,
|
| 54 |
+
in Original or Modified Versions, may be sold by itself.
|
| 55 |
+
|
| 56 |
+
2) Original or Modified Versions of the Font Software may be bundled,
|
| 57 |
+
redistributed and/or sold with any software, provided that each copy
|
| 58 |
+
contains the above copyright notice and this license. These can be
|
| 59 |
+
included either as stand-alone text files, human-readable headers or
|
| 60 |
+
in the appropriate machine-readable metadata fields within text or
|
| 61 |
+
binary files as long as those fields can be easily viewed by the user.
|
| 62 |
+
|
| 63 |
+
3) No Modified Version of the Font Software may use the Reserved Font
|
| 64 |
+
Name(s) unless explicit written permission is granted by the corresponding
|
| 65 |
+
Copyright Holder. This restriction only applies to the primary font name as
|
| 66 |
+
presented to the users.
|
| 67 |
+
|
| 68 |
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
| 69 |
+
Software shall not be used to promote, endorse or advertise any
|
| 70 |
+
Modified Version, except to acknowledge the contribution(s) of the
|
| 71 |
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
| 72 |
+
permission.
|
| 73 |
+
|
| 74 |
+
5) The Font Software, modified or unmodified, in part or in whole,
|
| 75 |
+
must be distributed entirely under this license, and must not be
|
| 76 |
+
distributed under any other license. The requirement for fonts to
|
| 77 |
+
remain under this license does not apply to any document created
|
| 78 |
+
using the Font Software.
|
| 79 |
+
|
| 80 |
+
TERMINATION
|
| 81 |
+
This license becomes null and void if any of the above conditions are
|
| 82 |
+
not met.
|
| 83 |
+
|
| 84 |
+
DISCLAIMER
|
| 85 |
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
| 86 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
| 87 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
| 88 |
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
| 89 |
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
| 90 |
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
| 91 |
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
| 92 |
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
| 93 |
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
assets/fonts/licenses/jetbrainsmono-OFL.txt
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
|
| 2 |
+
|
| 3 |
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
| 4 |
+
|
| 5 |
+
This license is copied below, and is also available with a FAQ at: https://scripts.sil.org/OFL
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
-----------------------------------------------------------
|
| 9 |
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
| 10 |
+
-----------------------------------------------------------
|
| 11 |
+
|
| 12 |
+
PREAMBLE
|
| 13 |
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
| 14 |
+
development of collaborative font projects, to support the font creation
|
| 15 |
+
efforts of academic and linguistic communities, and to provide a free and
|
| 16 |
+
open framework in which fonts may be shared and improved in partnership
|
| 17 |
+
with others.
|
| 18 |
+
|
| 19 |
+
The OFL allows the licensed fonts to be used, studied, modified and
|
| 20 |
+
redistributed freely as long as they are not sold by themselves. The
|
| 21 |
+
fonts, including any derivative works, can be bundled, embedded,
|
| 22 |
+
redistributed and/or sold with any software provided that any reserved
|
| 23 |
+
names are not used by derivative works. The fonts and derivatives,
|
| 24 |
+
however, cannot be released under any other type of license. The
|
| 25 |
+
requirement for fonts to remain under this license does not apply
|
| 26 |
+
to any document created using the fonts or their derivatives.
|
| 27 |
+
|
| 28 |
+
DEFINITIONS
|
| 29 |
+
"Font Software" refers to the set of files released by the Copyright
|
| 30 |
+
Holder(s) under this license and clearly marked as such. This may
|
| 31 |
+
include source files, build scripts and documentation.
|
| 32 |
+
|
| 33 |
+
"Reserved Font Name" refers to any names specified as such after the
|
| 34 |
+
copyright statement(s).
|
| 35 |
+
|
| 36 |
+
"Original Version" refers to the collection of Font Software components as
|
| 37 |
+
distributed by the Copyright Holder(s).
|
| 38 |
+
|
| 39 |
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
| 40 |
+
or substituting -- in part or in whole -- any of the components of the
|
| 41 |
+
Original Version, by changing formats or by porting the Font Software to a
|
| 42 |
+
new environment.
|
| 43 |
+
|
| 44 |
+
"Author" refers to any designer, engineer, programmer, technical
|
| 45 |
+
writer or other person who contributed to the Font Software.
|
| 46 |
+
|
| 47 |
+
PERMISSION & CONDITIONS
|
| 48 |
+
Permission is hereby granted, free of charge, to any person obtaining
|
| 49 |
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
| 50 |
+
redistribute, and sell modified and unmodified copies of the Font
|
| 51 |
+
Software, subject to the following conditions:
|
| 52 |
+
|
| 53 |
+
1) Neither the Font Software nor any of its individual components,
|
| 54 |
+
in Original or Modified Versions, may be sold by itself.
|
| 55 |
+
|
| 56 |
+
2) Original or Modified Versions of the Font Software may be bundled,
|
| 57 |
+
redistributed and/or sold with any software, provided that each copy
|
| 58 |
+
contains the above copyright notice and this license. These can be
|
| 59 |
+
included either as stand-alone text files, human-readable headers or
|
| 60 |
+
in the appropriate machine-readable metadata fields within text or
|
| 61 |
+
binary files as long as those fields can be easily viewed by the user.
|
| 62 |
+
|
| 63 |
+
3) No Modified Version of the Font Software may use the Reserved Font
|
| 64 |
+
Name(s) unless explicit written permission is granted by the corresponding
|
| 65 |
+
Copyright Holder. This restriction only applies to the primary font name as
|
| 66 |
+
presented to the users.
|
| 67 |
+
|
| 68 |
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
| 69 |
+
Software shall not be used to promote, endorse or advertise any
|
| 70 |
+
Modified Version, except to acknowledge the contribution(s) of the
|
| 71 |
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
| 72 |
+
permission.
|
| 73 |
+
|
| 74 |
+
5) The Font Software, modified or unmodified, in part or in whole,
|
| 75 |
+
must be distributed entirely under this license, and must not be
|
| 76 |
+
distributed under any other license. The requirement for fonts to
|
| 77 |
+
remain under this license does not apply to any document created
|
| 78 |
+
using the Font Software.
|
| 79 |
+
|
| 80 |
+
TERMINATION
|
| 81 |
+
This license becomes null and void if any of the above conditions are
|
| 82 |
+
not met.
|
| 83 |
+
|
| 84 |
+
DISCLAIMER
|
| 85 |
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
| 86 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
| 87 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
| 88 |
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
| 89 |
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
| 90 |
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
| 91 |
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
| 92 |
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
| 93 |
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
assets/fonts/licenses/nunito-OFL.txt
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Copyright 2014 The Nunito Project Authors (https://github.com/googlefonts/nunito)
|
| 2 |
+
|
| 3 |
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
| 4 |
+
This license is copied below, and is also available with a FAQ at:
|
| 5 |
+
http://scripts.sil.org/OFL
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
-----------------------------------------------------------
|
| 9 |
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
| 10 |
+
-----------------------------------------------------------
|
| 11 |
+
|
| 12 |
+
PREAMBLE
|
| 13 |
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
| 14 |
+
development of collaborative font projects, to support the font creation
|
| 15 |
+
efforts of academic and linguistic communities, and to provide a free and
|
| 16 |
+
open framework in which fonts may be shared and improved in partnership
|
| 17 |
+
with others.
|
| 18 |
+
|
| 19 |
+
The OFL allows the licensed fonts to be used, studied, modified and
|
| 20 |
+
redistributed freely as long as they are not sold by themselves. The
|
| 21 |
+
fonts, including any derivative works, can be bundled, embedded,
|
| 22 |
+
redistributed and/or sold with any software provided that any reserved
|
| 23 |
+
names are not used by derivative works. The fonts and derivatives,
|
| 24 |
+
however, cannot be released under any other type of license. The
|
| 25 |
+
requirement for fonts to remain under this license does not apply
|
| 26 |
+
to any document created using the fonts or their derivatives.
|
| 27 |
+
|
| 28 |
+
DEFINITIONS
|
| 29 |
+
"Font Software" refers to the set of files released by the Copyright
|
| 30 |
+
Holder(s) under this license and clearly marked as such. This may
|
| 31 |
+
include source files, build scripts and documentation.
|
| 32 |
+
|
| 33 |
+
"Reserved Font Name" refers to any names specified as such after the
|
| 34 |
+
copyright statement(s).
|
| 35 |
+
|
| 36 |
+
"Original Version" refers to the collection of Font Software components as
|
| 37 |
+
distributed by the Copyright Holder(s).
|
| 38 |
+
|
| 39 |
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
| 40 |
+
or substituting -- in part or in whole -- any of the components of the
|
| 41 |
+
Original Version, by changing formats or by porting the Font Software to a
|
| 42 |
+
new environment.
|
| 43 |
+
|
| 44 |
+
"Author" refers to any designer, engineer, programmer, technical
|
| 45 |
+
writer or other person who contributed to the Font Software.
|
| 46 |
+
|
| 47 |
+
PERMISSION & CONDITIONS
|
| 48 |
+
Permission is hereby granted, free of charge, to any person obtaining
|
| 49 |
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
| 50 |
+
redistribute, and sell modified and unmodified copies of the Font
|
| 51 |
+
Software, subject to the following conditions:
|
| 52 |
+
|
| 53 |
+
1) Neither the Font Software nor any of its individual components,
|
| 54 |
+
in Original or Modified Versions, may be sold by itself.
|
| 55 |
+
|
| 56 |
+
2) Original or Modified Versions of the Font Software may be bundled,
|
| 57 |
+
redistributed and/or sold with any software, provided that each copy
|
| 58 |
+
contains the above copyright notice and this license. These can be
|
| 59 |
+
included either as stand-alone text files, human-readable headers or
|
| 60 |
+
in the appropriate machine-readable metadata fields within text or
|
| 61 |
+
binary files as long as those fields can be easily viewed by the user.
|
| 62 |
+
|
| 63 |
+
3) No Modified Version of the Font Software may use the Reserved Font
|
| 64 |
+
Name(s) unless explicit written permission is granted by the corresponding
|
| 65 |
+
Copyright Holder. This restriction only applies to the primary font name as
|
| 66 |
+
presented to the users.
|
| 67 |
+
|
| 68 |
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
| 69 |
+
Software shall not be used to promote, endorse or advertise any
|
| 70 |
+
Modified Version, except to acknowledge the contribution(s) of the
|
| 71 |
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
| 72 |
+
permission.
|
| 73 |
+
|
| 74 |
+
5) The Font Software, modified or unmodified, in part or in whole,
|
| 75 |
+
must be distributed entirely under this license, and must not be
|
| 76 |
+
distributed under any other license. The requirement for fonts to
|
| 77 |
+
remain under this license does not apply to any document created
|
| 78 |
+
using the Font Software.
|
| 79 |
+
|
| 80 |
+
TERMINATION
|
| 81 |
+
This license becomes null and void if any of the above conditions are
|
| 82 |
+
not met.
|
| 83 |
+
|
| 84 |
+
DISCLAIMER
|
| 85 |
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
| 86 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
| 87 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
| 88 |
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
| 89 |
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
| 90 |
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
| 91 |
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
| 92 |
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
| 93 |
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
assets/fonts/licenses/patrickhand-OFL.txt
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Copyright (c) 2010-2012 Patrick Wagesreiter (mail@patrickwagesreiter.at)
|
| 2 |
+
|
| 3 |
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
| 4 |
+
This license is copied below, and is also available with a FAQ at:
|
| 5 |
+
http://scripts.sil.org/OFL
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
-----------------------------------------------------------
|
| 9 |
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
| 10 |
+
-----------------------------------------------------------
|
| 11 |
+
|
| 12 |
+
PREAMBLE
|
| 13 |
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
| 14 |
+
development of collaborative font projects, to support the font creation
|
| 15 |
+
efforts of academic and linguistic communities, and to provide a free and
|
| 16 |
+
open framework in which fonts may be shared and improved in partnership
|
| 17 |
+
with others.
|
| 18 |
+
|
| 19 |
+
The OFL allows the licensed fonts to be used, studied, modified and
|
| 20 |
+
redistributed freely as long as they are not sold by themselves. The
|
| 21 |
+
fonts, including any derivative works, can be bundled, embedded,
|
| 22 |
+
redistributed and/or sold with any software provided that any reserved
|
| 23 |
+
names are not used by derivative works. The fonts and derivatives,
|
| 24 |
+
however, cannot be released under any other type of license. The
|
| 25 |
+
requirement for fonts to remain under this license does not apply
|
| 26 |
+
to any document created using the fonts or their derivatives.
|
| 27 |
+
|
| 28 |
+
DEFINITIONS
|
| 29 |
+
"Font Software" refers to the set of files released by the Copyright
|
| 30 |
+
Holder(s) under this license and clearly marked as such. This may
|
| 31 |
+
include source files, build scripts and documentation.
|
| 32 |
+
|
| 33 |
+
"Reserved Font Name" refers to any names specified as such after the
|
| 34 |
+
copyright statement(s).
|
| 35 |
+
|
| 36 |
+
"Original Version" refers to the collection of Font Software components as
|
| 37 |
+
distributed by the Copyright Holder(s).
|
| 38 |
+
|
| 39 |
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
| 40 |
+
or substituting -- in part or in whole -- any of the components of the
|
| 41 |
+
Original Version, by changing formats or by porting the Font Software to a
|
| 42 |
+
new environment.
|
| 43 |
+
|
| 44 |
+
"Author" refers to any designer, engineer, programmer, technical
|
| 45 |
+
writer or other person who contributed to the Font Software.
|
| 46 |
+
|
| 47 |
+
PERMISSION & CONDITIONS
|
| 48 |
+
Permission is hereby granted, free of charge, to any person obtaining
|
| 49 |
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
| 50 |
+
redistribute, and sell modified and unmodified copies of the Font
|
| 51 |
+
Software, subject to the following conditions:
|
| 52 |
+
|
| 53 |
+
1) Neither the Font Software nor any of its individual components,
|
| 54 |
+
in Original or Modified Versions, may be sold by itself.
|
| 55 |
+
|
| 56 |
+
2) Original or Modified Versions of the Font Software may be bundled,
|
| 57 |
+
redistributed and/or sold with any software, provided that each copy
|
| 58 |
+
contains the above copyright notice and this license. These can be
|
| 59 |
+
included either as stand-alone text files, human-readable headers or
|
| 60 |
+
in the appropriate machine-readable metadata fields within text or
|
| 61 |
+
binary files as long as those fields can be easily viewed by the user.
|
| 62 |
+
|
| 63 |
+
3) No Modified Version of the Font Software may use the Reserved Font
|
| 64 |
+
Name(s) unless explicit written permission is granted by the corresponding
|
| 65 |
+
Copyright Holder. This restriction only applies to the primary font name as
|
| 66 |
+
presented to the users.
|
| 67 |
+
|
| 68 |
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
| 69 |
+
Software shall not be used to promote, endorse or advertise any
|
| 70 |
+
Modified Version, except to acknowledge the contribution(s) of the
|
| 71 |
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
| 72 |
+
permission.
|
| 73 |
+
|
| 74 |
+
5) The Font Software, modified or unmodified, in part or in whole,
|
| 75 |
+
must be distributed entirely under this license, and must not be
|
| 76 |
+
distributed under any other license. The requirement for fonts to
|
| 77 |
+
remain under this license does not apply to any document created
|
| 78 |
+
using the Font Software.
|
| 79 |
+
|
| 80 |
+
TERMINATION
|
| 81 |
+
This license becomes null and void if any of the above conditions are
|
| 82 |
+
not met.
|
| 83 |
+
|
| 84 |
+
DISCLAIMER
|
| 85 |
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
| 86 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
| 87 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
| 88 |
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
| 89 |
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
| 90 |
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
| 91 |
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
| 92 |
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
| 93 |
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
assets/fonts/nunito-latin-wght-italic.woff2
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6cfcc3786d5ba3b5c3a41797f95272e57f4290ccbd283a4bfd0033a3d857e64c
|
| 3 |
+
size 41760
|
assets/fonts/nunito-latin-wght.woff2
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ba344451eab25b217a165363b1982048a5e5830a0daf36577973955a04cac793
|
| 3 |
+
size 39128
|
assets/fonts/patrickhand-latin-400.woff2
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ac5bc9033b2572bf84d39f7150c1634e37ed16e8dbee632d6d0bceac0bbf0199
|
| 3 |
+
size 23944
|
assets/img/Case.png
ADDED
|
Git LFS Details
|
assets/img/acc_cost.png
ADDED
|
Git LFS Details
|
assets/img/banner.png
ADDED
|
Git LFS Details
|
assets/img/benchmark_sunburst.png
ADDED
|
Git LFS Details
|
assets/img/casestudy_pseudo_tool_call.png
ADDED
|
Git LFS Details
|
assets/img/casestudy_rubric_leakage.png
ADDED
|
Git LFS Details
|
assets/img/examples/task_agentvista_09.png
ADDED
|
Git LFS Details
|
assets/img/examples/task_charxiv_01.jpg
ADDED
|
Git LFS Details
|
assets/img/examples/task_hle_02.png
ADDED
|
Git LFS Details
|
assets/img/examples/task_medxpertqa_02.jpg
ADDED
|
Git LFS Details
|
assets/img/examples/task_mmsearchplus_00.png
ADDED
|
Git LFS Details
|
assets/img/examples/task_simplevqa_08.jpg
ADDED
|
Git LFS Details
|
assets/img/favicon.svg
ADDED
|
|
assets/img/overview.png
ADDED
|
Git LFS Details
|
assets/img/social-card.png
ADDED
|
Git LFS Details
|
assets/js/content.js
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Hero, motivation, overview, findings, case study, cite, footer.
|
| 2 |
+
Every number is read from window.OSB; prose here paraphrases or quotes the paper. */
|
| 3 |
+
(function () {
|
| 4 |
+
'use strict';
|
| 5 |
+
var U = window.U, D = U.D, h = U.h, S = D.stats, M = D.meta;
|
| 6 |
+
|
| 7 |
+
function finding(key) { return D.findings.filter(function (x) { return x.key === key; })[0]; }
|
| 8 |
+
|
| 9 |
+
/* ---------------- hero ---------------- */
|
| 10 |
+
function hero() {
|
| 11 |
+
var pill = U.$('#hero-arxiv');
|
| 12 |
+
pill.textContent = 'arXiv:' + M.arxivId + ' · ' + M.arxivCategory + ' · ' + M.arxivDate;
|
| 13 |
+
|
| 14 |
+
var ul = U.$('#authors');
|
| 15 |
+
ul.textContent = ''; /* replace the static no-JS fallback */
|
| 16 |
+
M.authors.forEach(function (a, i) {
|
| 17 |
+
var li = h('li', null, a.name);
|
| 18 |
+
var sup = h('sup', { text: a.affils.join(',') });
|
| 19 |
+
if (a.equalContribution) sup.appendChild(h('span', { class: 'mark', text: M.authorNotes.equalSymbol, attrs: { title: M.authorNotes.equalContribution } }));
|
| 20 |
+
if (a.corresponding) sup.appendChild(h('span', { class: 'mark', text: M.authorNotes.correspondingSymbol, attrs: { title: M.authorNotes.corresponding } }));
|
| 21 |
+
li.appendChild(sup);
|
| 22 |
+
if (i < M.authors.length - 1) li.appendChild(document.createTextNode(','));
|
| 23 |
+
ul.appendChild(li);
|
| 24 |
+
});
|
| 25 |
+
var ol = U.$('#affils');
|
| 26 |
+
ol.textContent = '';
|
| 27 |
+
M.affiliations.forEach(function (af) { ol.appendChild(h('li', null, h('sup', { text: String(af.id) }), af.name)); });
|
| 28 |
+
var an = U.$('#author-notes');
|
| 29 |
+
an.textContent = '';
|
| 30 |
+
an.appendChild(h('span', { class: 'nowrap', text: M.authorNotes.equalSymbol + ' ' + M.authorNotes.equalContribution }));
|
| 31 |
+
an.appendChild(document.createTextNode(' '));
|
| 32 |
+
an.appendChild(h('span', { class: 'nowrap', text: M.authorNotes.correspondingSymbol + ' ' + M.authorNotes.corresponding }));
|
| 33 |
+
|
| 34 |
+
var tiles = [
|
| 35 |
+
{ v: U.int(S.tasks), l: 'agent tasks', sub: U.int(S.textTasks) + ' text · ' + U.int(S.mmTasks) + ' multimodal', icon: 'i-paper', bg: 'var(--sec-blue-fill)', c: 'var(--sec-blue-ink)' },
|
| 36 |
+
{ v: U.int(S.sources), l: 'source benchmarks', sub: 'selected and adapted', icon: 'i-compass', bg: 'var(--sec-blue-fill)', c: 'var(--sec-blue-ink)' },
|
| 37 |
+
{ v: U.matrixLabel(), l: 'workload matrix', sub: 'modality × execution form', icon: 'i-token', bg: 'var(--sec-green-fill)', c: 'var(--sec-green-ink)' },
|
| 38 |
+
{ v: U.int(S.models), l: 'models evaluated', sub: U.int(S.apiModels) + ' API + ' + U.int(S.localModels) + ' local', icon: 'i-server', bg: 'var(--sec-green-fill)', c: 'var(--sec-green-ink)' },
|
| 39 |
+
{ v: U.int(S.runs), l: 'model–task runs', sub: 'in one shared OpenClaw runtime', icon: 'i-loop', bg: 'var(--sec-orange-fill)', c: 'var(--sec-orange-ink)' },
|
| 40 |
+
{ v: U.int(S.unsupportedRemoved), l: 'unsupported positive scores removed', sub: 'by the evidence-based audit', icon: 'i-eye', bg: 'var(--sec-purple-fill)', c: 'var(--sec-purple-ink)', burst: 'BUSTED!' }
|
| 41 |
+
];
|
| 42 |
+
var box = U.$('#stat-tiles');
|
| 43 |
+
tiles.forEach(function (t) {
|
| 44 |
+
var ic = h('span', { class: 'stat__icon', style: { background: t.bg, color: t.c } }, U.icon(t.icon));
|
| 45 |
+
var li = h('li', { class: 'stat' + (t.burst ? ' stat--burst' : '') }, ic, h('span', { class: 'stat__value', text: t.v }), h('span', { class: 'stat__label', text: t.l }), h('span', { class: 'stat__sub', text: t.sub }));
|
| 46 |
+
if (t.burst) li.appendChild(U.burst(t.burst, 'red'));
|
| 47 |
+
box.appendChild(li);
|
| 48 |
+
});
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
/* ---------------- why ---------------- */
|
| 52 |
+
function why() {
|
| 53 |
+
U.$('#why-lead').textContent = 'As language models become general-purpose agents, evaluation has to look beyond static answer correctness. The paper argues that a benchmark used to choose and deploy an agent model has to answer three questions:';
|
| 54 |
+
var art = { interpretable: ['ic-grid', 'theme-blue'], attributable: ['ic-bowl', 'theme-green'], trustworthy: ['ic-shield', 'theme-orange'] };
|
| 55 |
+
var list = U.$('#why-grid');
|
| 56 |
+
M.why.forEach(function (w) {
|
| 57 |
+
var a = art[w.key] || ['ic-shield', 'theme-blue'];
|
| 58 |
+
var word = w.key.charAt(0).toUpperCase() + w.key.slice(1) + '?';
|
| 59 |
+
list.appendChild(h('li', { class: 'why reveal ' + a[1] },
|
| 60 |
+
h('div', { class: 'why__top' },
|
| 61 |
+
h('span', { class: 'why__art' }, U.icon(a[0])),
|
| 62 |
+
h('h3', { class: 'why__q' }, h('span', { class: 'why__word', text: word }), w.question)),
|
| 63 |
+
h('p', { class: 'why__problem', text: w.problem }),
|
| 64 |
+
h('p', { class: 'why__answer' }, h('strong', { text: M.shortName + '’s answer' }), w.answer)));
|
| 65 |
+
});
|
| 66 |
+
var tl = U.$('#tldr-list');
|
| 67 |
+
[M.taglines[1], M.taglines[2], M.taglines[3]].forEach(function (t) { tl.appendChild(h('li', { text: t })); });
|
| 68 |
+
U.$('#abstract-text').textContent = M.abstract;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
/* ---------------- overview ---------------- */
|
| 72 |
+
function overview() {
|
| 73 |
+
var f2 = U.fig('fig2');
|
| 74 |
+
U.$('#overview-lead').textContent = 'The pipeline turns heterogeneous source benchmarks into comparable, auditable reports: tasks are curated and classified, every model executes them in the same agent runtime, scores are computed and audited, and results are summarized per workload together with tokens and cost.';
|
| 75 |
+
var img = U.$('#overview-img');
|
| 76 |
+
img.src = U.IMG + f2.file; img.alt = f2.alt;
|
| 77 |
+
var cap = U.$('#overview-cap');
|
| 78 |
+
cap.appendChild(h('b', { text: f2.label + '. ' }));
|
| 79 |
+
cap.appendChild(document.createTextNode(f2.caption));
|
| 80 |
+
U.$('#overview-zoom').addEventListener('click', function () { U.lightbox(U.IMG + f2.file, f2.alt, f2.label + '. ' + f2.caption); });
|
| 81 |
+
|
| 82 |
+
var sc = S.scoring, rt = S.runtime;
|
| 83 |
+
var stages = [
|
| 84 |
+
{ cls: 'blue', art: 'ic-chest', title: 'Construct',
|
| 85 |
+
text: U.int(S.tasks) + ' tasks are selected and adapted from ' + U.int(S.sources) + ' source benchmarks through feasibility, difficulty and representativeness filters, then organized into a ' + U.matrixLabel() + ' workload matrix by input modality and execution form.',
|
| 86 |
+
chips: [U.int(S.textTasks) + ' text', U.int(S.mmTasks) + ' multimodal'] },
|
| 87 |
+
{ cls: 'green', art: 'cr-octopus', title: 'Execute',
|
| 88 |
+
text: 'Every model runs in one shared OpenClaw environment (common agent loop, tool interface, workspace and logging) with web search, web fetch and ' + rt.clawhubSkillsInPaper + ' Clawhub skills. A task contract fixes the workspace, tools, artifact, scorer and time budget.',
|
| 89 |
+
chips: ['OpenClaw ' + rt.openclaw] },
|
| 90 |
+
{ cls: 'orange', art: 'ic-scale', title: 'Score & audit',
|
| 91 |
+
text: 'Each task is scored by automated checks, an LLM judge, or a weighted hybrid. Post-hoc rules flag suspicious positive scores, and a meta-judge from a different model family checks them against the evidence.',
|
| 92 |
+
chips: [sc.auto + ' auto · ' + sc.judge + ' judge · ' + sc.hybrid + ' hybrid tasks'] },
|
| 93 |
+
{ cls: 'purple', art: 'ic-board', title: 'Report',
|
| 94 |
+
text: 'Audited accuracy overall and per workload group, tokens per task, and reference cost from public API prices, with accuracy–cost Pareto frontiers for API models drawn separately for text and multimodal workloads.',
|
| 95 |
+
chips: [U.int(S.models) + ' models', U.int(S.runs) + ' runs'] }
|
| 96 |
+
];
|
| 97 |
+
var ol = U.$('#stages');
|
| 98 |
+
stages.forEach(function (s) {
|
| 99 |
+
var chips = h('div', { class: 'stage__chips' });
|
| 100 |
+
s.chips.forEach(function (c) { chips.appendChild(h('span', { class: 'pill', text: c })); });
|
| 101 |
+
ol.appendChild(h('li', { class: 'stage reveal stage--' + s.cls },
|
| 102 |
+
U.icon(s.art, 'stage__art'), h('h3', { text: s.title }), h('p', { text: s.text }), chips));
|
| 103 |
+
});
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
/* ---------------- findings ---------------- */
|
| 107 |
+
function findings() {
|
| 108 |
+
var meta = {
|
| 109 |
+
'workload-winners': { icon: 'i-crown', cls: 'fi-blue', wide: true, jump: '#leaderboard', jl: 'Explore the leaderboard', lb: { deploy: 'all', track: 'full' } },
|
| 110 |
+
'open-weight-gap': { icon: 'i-server', cls: 'fi-green', jump: '#leaderboard', jl: 'Show local models in the leaderboard', lb: { deploy: 'local', track: 'full' } },
|
| 111 |
+
'pareto': { icon: 'i-frontier', cls: 'fi-orange', jump: '#cost', jl: 'See the frontiers' },
|
| 112 |
+
'tokens-vs-dollars': { icon: 'i-coins', cls: 'fi-orange', jump: '#tokens-card', jl: 'Compare tokens and dollars' },
|
| 113 |
+
'judge-hallucination': { icon: 'i-eye', cls: 'fi-purple', jump: '#reliability', jl: 'Inside the audit' },
|
| 114 |
+
'deployment-failures': { icon: 'i-loop', cls: 'fi-purple', jump: '#pattern-grid', jl: 'Hallucination patterns' },
|
| 115 |
+
'model-evolution': { icon: 'i-sprout', cls: 'fi-green', jump: '#leaderboard', jl: 'Show local models in the leaderboard', lb: { deploy: 'local', track: 'full' } },
|
| 116 |
+
'local-tokens': { icon: 'i-token', cls: 'fi-green', jump: '#taxonomy', jl: 'PPPA in the failure taxonomy' },
|
| 117 |
+
'failure-taxonomy': { icon: 'i-compass', cls: 'fi-blue', jump: '#taxonomy', jl: 'Failure taxonomy' }
|
| 118 |
+
};
|
| 119 |
+
var order = ['workload-winners', 'open-weight-gap', 'pareto', 'tokens-vs-dollars', 'local-tokens', 'judge-hallucination', 'deployment-failures', 'model-evolution', 'failure-taxonomy'];
|
| 120 |
+
var grid = U.$('#findings-grid');
|
| 121 |
+
order.forEach(function (key, idx) {
|
| 122 |
+
var f = finding(key);
|
| 123 |
+
if (!f) return;
|
| 124 |
+
var m = meta[key];
|
| 125 |
+
var card = h('article', { class: 'finding reveal ' + m.cls + (m.wide ? ' finding--wide' : ''), attrs: { 'aria-labelledby': 'f-' + key } },
|
| 126 |
+
h('div', { class: 'finding__top' }, h('span', { class: 'finding__icon' }, U.icon(m.icon)), h('span', { class: 'finding__sec', text: f.section })),
|
| 127 |
+
h('h3', { text: f.title, attrs: { id: 'f-' + key } }));
|
| 128 |
+
if (key === 'workload-winners') card.appendChild(winners());
|
| 129 |
+
if (key === 'open-weight-gap') card.appendChild(gapVisual(f));
|
| 130 |
+
if (key === 'tokens-vs-dollars') card.appendChild(chainVisual(f));
|
| 131 |
+
if (key === 'judge-hallucination') card.appendChild(auditVisual(f));
|
| 132 |
+
var body = h('p', { class: 'finding__text', attrs: { id: 'ft-' + key } }, U.emphNums(f.statement));
|
| 133 |
+
card.appendChild(body);
|
| 134 |
+
var more = null;
|
| 135 |
+
if (f.statement.length > 230 && !m.wide) {
|
| 136 |
+
more = h('button', { class: 'finding__more', attrs: { type: 'button', 'aria-expanded': 'false', 'aria-controls': 'ft-' + key } }, 'Read the full finding');
|
| 137 |
+
more.addEventListener('click', function () {
|
| 138 |
+
var open = card.classList.toggle('is-open');
|
| 139 |
+
more.setAttribute('aria-expanded', String(open));
|
| 140 |
+
more.textContent = open ? 'Show less' : 'Read the full finding';
|
| 141 |
+
});
|
| 142 |
+
card.classList.add('is-clampable');
|
| 143 |
+
}
|
| 144 |
+
var a = h('a', { class: 'jump', attrs: { href: m.jump } }, m.jl, U.icon('i-arrow'));
|
| 145 |
+
if (m.lb) a.addEventListener('click', function () { if (U.lbSet) U.lbSet(m.lb); });
|
| 146 |
+
card.appendChild(h('div', { class: 'finding__actions' }, more || null, a));
|
| 147 |
+
grid.appendChild(card);
|
| 148 |
+
});
|
| 149 |
+
}
|
| 150 |
+
function winners() {
|
| 151 |
+
var box = h('div', { class: 'winners', attrs: { role: 'table', 'aria-label': 'Best model per workload group (Table 1)' } });
|
| 152 |
+
var forms = [];
|
| 153 |
+
U.GROUPS.forEach(function (g) { if (forms.indexOf(g.form) < 0) forms.push(g.form); });
|
| 154 |
+
var formLabel = { 'single-step': 'Single-step', 'multi-step': 'Multi-step', 'multi-step+tools': 'Multi-step + tools' };
|
| 155 |
+
var hr = h('div', { attrs: { role: 'row' }, style: { display: 'contents' } });
|
| 156 |
+
hr.appendChild(h('span', { attrs: { role: 'columnheader' }, class: 'winners__h' }));
|
| 157 |
+
forms.forEach(function (f) { hr.appendChild(h('span', { class: 'winners__h', text: formLabel[f] || f, attrs: { role: 'columnheader' } })); });
|
| 158 |
+
box.appendChild(hr);
|
| 159 |
+
['text', 'multimodal'].forEach(function (mod) {
|
| 160 |
+
var row = h('div', { attrs: { role: 'row' }, style: { display: 'contents' } });
|
| 161 |
+
row.appendChild(h('span', { class: 'winners__r', attrs: { role: 'rowheader' } }, h('span', { class: 'lg-only', text: mod === 'text' ? 'Text' : 'Multimodal' }), h('span', { class: 'sm-only', text: mod === 'text' ? 'Text' : 'MM', attrs: { 'aria-hidden': 'true' } })));
|
| 162 |
+
forms.forEach(function (f) {
|
| 163 |
+
var g = U.GROUPS.filter(function (x) { return x.modality === mod && x.form === f; })[0];
|
| 164 |
+
row.appendChild(h('span', { class: 'winner', style: { '--c': U.wlVar(g.key) }, attrs: { role: 'cell', title: g.longLabel } },
|
| 165 |
+
h('b', { text: g.best.model }), h('span', null, h('span', { class: 'lg-only', text: g.label + ' · ' }), U.pct(g.best.acc))));
|
| 166 |
+
});
|
| 167 |
+
box.appendChild(row);
|
| 168 |
+
});
|
| 169 |
+
return box;
|
| 170 |
+
}
|
| 171 |
+
/* deployment gap: for each tool-mediated group the paper compares (§4.2), the best local score
|
| 172 |
+
next to the best API score it states */
|
| 173 |
+
function gapVisual(f) {
|
| 174 |
+
var groups = [], by = {};
|
| 175 |
+
f.numbers.forEach(function (n) {
|
| 176 |
+
if (!n.group || n.acc == null) return;
|
| 177 |
+
if (!by[n.group]) { by[n.group] = []; groups.push(n.group); }
|
| 178 |
+
by[n.group].push(n);
|
| 179 |
+
});
|
| 180 |
+
var box = h('div', { class: 'mini-bars mini-bars--gap' });
|
| 181 |
+
var bars = [];
|
| 182 |
+
groups.forEach(function (key) {
|
| 183 |
+
var g = U.group(key);
|
| 184 |
+
box.appendChild(h('p', { class: 'mini-bars__h', text: g.longLabel }));
|
| 185 |
+
by[key].forEach(function (n) {
|
| 186 |
+
var m = U.model(n.model), dep = m && m.deployment === 'local' ? 'local' : 'api', depLab = dep === 'local' ? 'Local' : 'API';
|
| 187 |
+
var bar = h('div', { class: 'mini-bar', attrs: { role: 'img', 'aria-label': n.model + ' (' + depLab + '): ' + g.label + ' ' + U.pct(n.acc) + ' percent (stated in ' + f.section + ')' } },
|
| 188 |
+
h('span', { class: 'mini-bar__n', text: m ? m.shortName : n.model, attrs: { 'aria-hidden': 'true' } }),
|
| 189 |
+
h('span', { class: 'mini-bar__t', attrs: { 'aria-hidden': 'true' } }, h('span', { class: 'mini-bar__f', style: { width: n.acc + '%', background: 'var(--series-' + dep + ')' } })),
|
| 190 |
+
h('span', { class: 'mini-bar__v', text: U.pct(n.acc), attrs: { 'aria-hidden': 'true' } }));
|
| 191 |
+
U.hoverTip(bar, function () {
|
| 192 |
+
return { title: n.model, rows: [{ label: g.longLabel + ' accuracy', value: U.pct(n.acc) + '%', color: U.css('--series-' + dep) }],
|
| 193 |
+
note: (m ? m.vendor + ' · ' : '') + depLab + ' · stated in the paper (' + f.section + ')' };
|
| 194 |
+
});
|
| 195 |
+
bars.push(bar);
|
| 196 |
+
box.appendChild(bar);
|
| 197 |
+
});
|
| 198 |
+
});
|
| 199 |
+
if (!bars.length) return h('span');
|
| 200 |
+
U.roving(bars);
|
| 201 |
+
var legend = h('div', { class: 'legend mini-legend' });
|
| 202 |
+
[['var(--series-local)', 'best local'], ['var(--series-api)', 'best API']].forEach(function (x) {
|
| 203 |
+
legend.appendChild(h('span', { class: 'legend__item' }, h('span', { class: 'legend__sw', style: { background: x[0] } }), x[1]));
|
| 204 |
+
});
|
| 205 |
+
return h('div', { class: 'mini-wrap' }, legend, box);
|
| 206 |
+
}
|
| 207 |
+
/* token use vs dollars: the four extremes the paper names in §4.2 (Text Avg per task) are four
|
| 208 |
+
different models */
|
| 209 |
+
function chainVisual(f) {
|
| 210 |
+
function ext(field, max) {
|
| 211 |
+
var xs = f.numbers.filter(function (n) { return n[field] != null; });
|
| 212 |
+
return xs.sort(function (a, b) { return max ? b[field] - a[field] : a[field] - b[field]; })[0];
|
| 213 |
+
}
|
| 214 |
+
var cells = [['fewest tokens', ext('tokensText'), function (n) { return U.tok(n.tokensText); }],
|
| 215 |
+
['most tokens', ext('tokensText', true), function (n) { return U.tok(n.tokensText); }],
|
| 216 |
+
['cheapest', ext('costText'), function (n) { return '$' + n.costText.toFixed(3); }],
|
| 217 |
+
['most expensive', ext('costText', true), function (n) { return '$' + n.costText.toFixed(3); }]];
|
| 218 |
+
if (cells.some(function (c) { return !c[1]; })) return h('span');
|
| 219 |
+
var list = h('ul', { class: 'xchips' });
|
| 220 |
+
cells.forEach(function (c) {
|
| 221 |
+
list.appendChild(h('li', { class: 'vs-chip' }, h('span', { class: 'xchips__k', text: c[0] }), h('b', { text: c[1].model }), h('span', { class: 'vs-chip__big', text: c[2](c[1]) })));
|
| 222 |
+
});
|
| 223 |
+
return h('div', { class: 'mini-wrap' }, list, h('p', { class: 'xchips__note', text: 'Text Avg, per task' }));
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
/* judge hallucination: the audit counts and the MAE change, as stated in §4.3 / Appendix C */
|
| 227 |
+
function auditVisual(f) {
|
| 228 |
+
var n = Array.isArray(f.numbers) ? f.numbers[0] : f.numbers;
|
| 229 |
+
var steps = [[U.int(n.judgeCalls), 'judge calls'], [U.int(n.flagged), 'flagged'], [U.int(n.confirmed), 'removed']];
|
| 230 |
+
var row = h('div', { class: 'mini-funnel', attrs: { role: 'img', 'aria-label': steps.map(function (x) { return x[0] + ' ' + x[1]; }).join(', then ') } });
|
| 231 |
+
steps.forEach(function (x, i) {
|
| 232 |
+
if (i) row.appendChild(U.icon('i-arrow', 'mini-funnel__arr'));
|
| 233 |
+
row.appendChild(h('span', { class: 'mini-funnel__s' + (i === steps.length - 1 ? ' is-final' : '') }, h('b', { text: x[0] }), h('span', { text: x[1] })));
|
| 234 |
+
});
|
| 235 |
+
return h('div', { class: 'mini-wrap' }, row,
|
| 236 |
+
h('p', { class: 'mini-mae' }, 'MAE vs. human experts: ', h('b', { text: n.maeJudge.toFixed(3) }), ' → ', h('b', { text: n.maeMeta.toFixed(3) }), h('span', { class: 'scribble scribble--sm', text: ' about half' })));
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
/* ---------------- case study (Fig. 3) ---------------- */
|
| 240 |
+
/* §4.4 of the paper, quoted verbatim (sentences 2–5). */
|
| 241 |
+
var PAPER_4_4 = 'The task requires filtering foods by two visual constraints before retrieving their glycemic-index values. Qwen3.5-9B misreads the chart and retains Avocado despite the CO2 threshold; this early error changes the candidate set and leads to the wrong answer. It also relies on unverified sources. In contrast, Claude Opus 4.8 applies both constraints and checks retrieved values against authoritative sources.';
|
| 242 |
+
function caseStudy() {
|
| 243 |
+
var f = U.fig('fig3');
|
| 244 |
+
var box = U.$('#case-study');
|
| 245 |
+
var parts = f.caption.split(/\.\s+(?=Example Task:)/);
|
| 246 |
+
var title = parts[0];
|
| 247 |
+
var task = (parts[1] || '').replace(/^Example Task:\s*/, '');
|
| 248 |
+
var t = D.tasks.filter(function (x) { return x.id === f.taskId; })[0];
|
| 249 |
+
var g = t ? U.group(t.group) : null;
|
| 250 |
+
box.appendChild(h('div', { class: 'case__fig' }, U.zoomable(U.IMG + f.file, f.alt, f.label + '. ' + f.caption, f.label)));
|
| 251 |
+
var chips = h('p', { class: 'case__chips' });
|
| 252 |
+
if (t) {
|
| 253 |
+
chips.appendChild(h('span', { class: 'pill', text: U.source(t.source).name }));
|
| 254 |
+
chips.appendChild(h('span', { class: 'pill' }, h('span', { class: 'dot', style: { background: U.wlVar(g.key) } }), g.label));
|
| 255 |
+
}
|
| 256 |
+
box.appendChild(h('figcaption', null,
|
| 257 |
+
h('p', { class: 'case__label', text: 'Case study · ' + f.label + ' (' + f.section + ')' }),
|
| 258 |
+
h('h3', { text: title }),
|
| 259 |
+
h('div', { class: 'case__task' }, h('span', { class: 'case__tag', text: 'Example task' }), h('p', { text: task })),
|
| 260 |
+
h('blockquote', { class: 'case__quote' }, h('p', { text: PAPER_4_4 }), h('footer', { text: 'Paper, ' + f.section })),
|
| 261 |
+
chips));
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
/* ---------------- cite + footer ---------------- */
|
| 265 |
+
function cite() {
|
| 266 |
+
U.$('#bibtex').textContent = M.bibtex;
|
| 267 |
+
var links = h('div', { class: 'cite__links' },
|
| 268 |
+
h('span', { class: 'btn-pair' },
|
| 269 |
+
h('a', { class: 'btn btn--sm btn--navy', attrs: { href: M.arxivUrl, rel: 'noopener' } }, U.icon('i-paper'), 'arXiv ' + M.arxivId),
|
| 270 |
+
h('a', { class: 'btn btn--sm btn--ghost', attrs: { href: M.pdfUrl, rel: 'noopener' } }, U.icon('i-pdf'), 'PDF')),
|
| 271 |
+
h('span', { class: 'btn-pair' },
|
| 272 |
+
h('a', { class: 'btn btn--sm btn--ghost', attrs: { href: M.github, rel: 'noopener' } }, U.icon('i-github'), 'Code'),
|
| 273 |
+
M.hfDataset ? h('a', { class: 'btn btn--sm btn--ghost', attrs: { href: M.hfDataset, rel: 'noopener', title: M.shortName + ' on Hugging Face' } }, U.icon('i-data'), 'HF Dataset') : null));
|
| 274 |
+
U.$('.cite__body').appendChild(links);
|
| 275 |
+
U.$$('[data-copy-target]').forEach(function (b) {
|
| 276 |
+
b.addEventListener('click', function () { U.copy(document.getElementById(b.getAttribute('data-copy-target')).textContent, b); });
|
| 277 |
+
});
|
| 278 |
+
var fa = U.$('#footer-affils');
|
| 279 |
+
M.affiliations.forEach(function (a) { fa.appendChild(h('li', { text: a.name, attrs: { value: String(a.id) } })); });
|
| 280 |
+
U.$('#footer-ack').textContent = M.shortName + ' runs every model in the OpenClaw agent runtime (version ' + S.runtime.openclaw + ' in the paper). Its ' + U.int(S.tasks) + ' tasks are selected and adapted from ' + U.int(S.sources) + ' public source benchmarks, and we gratefully acknowledge their authors:';
|
| 281 |
+
var fs = U.$('#footer-srcs');
|
| 282 |
+
fs.textContent = '';
|
| 283 |
+
D.sources.forEach(function (s, i) {
|
| 284 |
+
fs.appendChild(h('span', { class: 'src-i', text: s.name + (i < D.sources.length - 1 ? ' ·' : '') }));
|
| 285 |
+
if (i < D.sources.length - 1) fs.appendChild(document.createTextNode(' '));
|
| 286 |
+
});
|
| 287 |
+
U.$('#footer-base').textContent = 'All numbers on this page follow the ' + M.shortName + ' paper. Illustrations are original; figures are reproduced from the paper.';
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
U.initContent = function () { hero(); why(); overview(); findings(); caseStudy(); cite(); };
|
| 291 |
+
})();
|
assets/js/cost.js
ADDED
|
@@ -0,0 +1,531 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Accuracy–cost scatter (the paper's Fig. 1: plotted models and frontiers exactly as drawn)
|
| 2 |
+
and the tokens-vs-dollars small multiples (Table 2). */
|
| 3 |
+
(function () {
|
| 4 |
+
'use strict';
|
| 5 |
+
var U = window.U, D = U.D, h = U.h, s = U.s;
|
| 6 |
+
var mode = 'text';
|
| 7 |
+
var tokSort = 'tokens';
|
| 8 |
+
|
| 9 |
+
function field() { return mode === 'text' ? 'textAvg' : 'mmAvg'; }
|
| 10 |
+
function acc(m) { return mode === 'text' ? m.textAvg : m.mmAvg; }
|
| 11 |
+
function cost(m) { return m.cost[field()]; }
|
| 12 |
+
function costTxt(m) { return m.costText[field()]; }
|
| 13 |
+
function tok(m) { return m.tokens[field()]; }
|
| 14 |
+
function modeColor() { return mode === 'text' ? U.css('--series-text') : U.css('--series-mm'); }
|
| 15 |
+
function modeLabel() { return mode === 'text' ? 'Text' : 'Multimodal'; }
|
| 16 |
+
function plotted() { return D.pareto.fig1Models[mode].map(U.model); }
|
| 17 |
+
function frontier() { return D.pareto[mode].map(U.model); }
|
| 18 |
+
function isFront(m) { return D.pareto[mode].indexOf(m.name) >= 0; }
|
| 19 |
+
function apiModels() { return D.models.filter(function (m) { return m.deployment === 'api' && cost(m) != null && tok(m) != null; }); }
|
| 20 |
+
function finding(k) { return D.findings.filter(function (x) { return x.key === k; })[0]; }
|
| 21 |
+
/* models the paper names in its §4.2 prose: always labelled when plotted */
|
| 22 |
+
function namedInProse(m) {
|
| 23 |
+
var txt = [finding('pareto').statement, finding('tokens-vs-dollars').statement].join(' ');
|
| 24 |
+
var re = new RegExp(m.name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '(?![\\w.-]*\\w)');
|
| 25 |
+
return re.test(txt);
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
function tipSpec(m) {
|
| 29 |
+
return { title: m.name, rows: [
|
| 30 |
+
{ label: modeLabel() + ' accuracy', value: U.pct(acc(m)) + '%', color: isFront(m) ? U.css('--pareto-hi') : U.css('--pareto-muted') },
|
| 31 |
+
{ label: 'Cost per task', value: U.usd(costTxt(m)) },
|
| 32 |
+
{ label: 'Tokens per task', value: U.tok(tok(m)) }
|
| 33 |
+
], note: m.vendor + (isFront(m) ? ' · on the Pareto frontier drawn in Fig. 1' : '') };
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
/* ---------------- scatter ---------------- */
|
| 37 |
+
function drawScatter() {
|
| 38 |
+
var box = U.$('#scatter-box');
|
| 39 |
+
var W = Math.max(280, Math.round(box.clientWidth));
|
| 40 |
+
var narrow = W < 560;
|
| 41 |
+
var H = W >= 900 ? 500 : narrow ? 540 : 460;
|
| 42 |
+
var m = { l: narrow ? 42 : 54, r: 10, t: 14, b: 54 };
|
| 43 |
+
var pw = W - m.l - m.r, ph = H - m.t - m.b;
|
| 44 |
+
var pts = plotted();
|
| 45 |
+
var costs = pts.map(cost), accs = pts.map(acc);
|
| 46 |
+
var lo = Math.log10(Math.min.apply(null, costs) / 1.7), hi = Math.log10(Math.max.apply(null, costs) * (narrow ? 1.7 : 3.2));
|
| 47 |
+
var ylo = Math.floor((Math.min.apply(null, accs) - 2) / 5) * 5, yhi = Math.ceil((Math.max.apply(null, accs) + 2) / 5) * 5;
|
| 48 |
+
function X(c) { return m.l + (Math.log10(c) - lo) / (hi - lo) * pw; }
|
| 49 |
+
function Y(a) { return m.t + (1 - (a - ylo) / (yhi - ylo)) * ph; }
|
| 50 |
+
|
| 51 |
+
box.textContent = '';
|
| 52 |
+
var svg = s('svg', { width: W, height: H, viewBox: '0 0 ' + W + ' ' + H, role: 'group', 'aria-label': modeLabel() + ' accuracy versus cost per task for ' + pts.length + ' API models. One Tab stop: use the arrow keys to move between models in order of cost.' }, box);
|
| 53 |
+
var g = s('g', { class: 'axis', 'aria-hidden': 'true' }, svg);
|
| 54 |
+
U.ticks(ylo, yhi, 5).forEach(function (v) {
|
| 55 |
+
s('line', { class: 'grid-line', x1: m.l, x2: W - m.r, y1: Y(v), y2: Y(v) }, g);
|
| 56 |
+
var t = s('text', { x: m.l - 8, y: Y(v) + 4, 'text-anchor': 'end' }, g); t.textContent = String(v);
|
| 57 |
+
});
|
| 58 |
+
var xt = [];
|
| 59 |
+
for (var e = Math.floor(lo); e <= Math.ceil(hi); e++) [1, 2, 5].forEach(function (k) { var v = k * Math.pow(10, e); if (Math.log10(v) >= lo && Math.log10(v) <= hi) xt.push({ v: v, k: k, x: X(v) }); });
|
| 60 |
+
xt.forEach(function (o) { s('line', { class: 'grid-line', x1: o.x, x2: o.x, y1: m.t, y2: m.t + ph }, g); });
|
| 61 |
+
/* tick labels: 1s first, then 5s and 2s only where they do not collide */
|
| 62 |
+
U.fitTicks(xt, U.usdTick, 0, W, '400 12.5px Nunito', 10).forEach(function (o) {
|
| 63 |
+
var t = s('text', { x: o.x, y: m.t + ph + 18, 'text-anchor': 'middle' }, g); t.textContent = U.usdTick(o.v);
|
| 64 |
+
});
|
| 65 |
+
s('line', { class: 'axis-line', x1: m.l, x2: W - m.r, y1: m.t + ph, y2: m.t + ph }, g);
|
| 66 |
+
var xtitle = s('text', { class: 'axis-title', x: m.l + pw / 2, y: H - 10, 'text-anchor': 'middle' }, g); xtitle.textContent = 'Cost per task (USD, log scale)';
|
| 67 |
+
var ytitle = s('text', { class: 'axis-title', transform: 'translate(' + 13 + ' ' + (m.t + ph / 2) + ') rotate(-90)', 'text-anchor': 'middle' }, g); ytitle.textContent = modeLabel() + ' accuracy (%)';
|
| 68 |
+
|
| 69 |
+
/* frontier: dashed, as in the paper's Fig. 1 */
|
| 70 |
+
var fr = frontier().slice().sort(function (a, b) { return cost(a) - cost(b); });
|
| 71 |
+
s('path', { class: 'frontier', 'aria-hidden': 'true', d: fr.map(function (p, i) { return (i ? 'L' : 'M') + X(cost(p)).toFixed(1) + ' ' + Y(acc(p)).toFixed(1); }).join(' '),
|
| 72 |
+
fill: 'none', stroke: U.css('--pareto-hi'), 'stroke-width': 2.2, 'stroke-dasharray': '7 5', 'stroke-linecap': 'round', 'stroke-linejoin': 'round' }, svg);
|
| 73 |
+
|
| 74 |
+
var nodes = pts.map(function (p) {
|
| 75 |
+
var front = isFront(p);
|
| 76 |
+
return { m: p, x: X(cost(p)), y: Y(acc(p)), r: front ? 6.5 : 5.5, front: front, must: namedInProse(p) };
|
| 77 |
+
});
|
| 78 |
+
var leadLayer = s('g', { class: 'leaders', 'aria-hidden': 'true' }, svg);
|
| 79 |
+
var ptLayer = s('g', { 'aria-hidden': 'true' }, svg);
|
| 80 |
+
nodes.slice().sort(function (a, b) { return (a.front ? 1 : 0) - (b.front ? 1 : 0); }).forEach(function (n) {
|
| 81 |
+
n.dot = s('circle', { class: 'pt', cx: n.x, cy: n.y, r: n.r, fill: n.front ? U.css('--pareto-hi') : U.css('--pareto-muted'), stroke: '#fff', 'stroke-width': 2 }, ptLayer);
|
| 82 |
+
});
|
| 83 |
+
|
| 84 |
+
/* ---- label placement: every model where it fits; leader lines when the near slots are taken.
|
| 85 |
+
Greedy by priority (frontier, then models the paper names, then the rest; crowded points first),
|
| 86 |
+
with an ambiguity check, and up to three retries that promote any unlabelled priority point. ---- */
|
| 87 |
+
var labLayer = s('g', { 'aria-hidden': 'true' }, svg);
|
| 88 |
+
var baseObs = nodes.map(function (n) { return { x1: n.x - n.r - 2, y1: n.y - n.r - 2, x2: n.x + n.r + 2, y2: n.y + n.r + 2, owner: n }; });
|
| 89 |
+
for (var fi = 1; fi < fr.length; fi++) {
|
| 90 |
+
var ax = X(cost(fr[fi - 1])), ay = Y(acc(fr[fi - 1])), bx = X(cost(fr[fi])), by = Y(acc(fr[fi]));
|
| 91 |
+
var steps = Math.max(2, Math.round(Math.hypot(bx - ax, by - ay) / 8));
|
| 92 |
+
for (var si = 1; si < steps; si++) { var px = ax + (bx - ax) * si / steps, py = ay + (by - ay) * si / steps; baseObs.push({ x1: px - 3, y1: py - 3, x2: px + 3, y2: py + 3 }); }
|
| 93 |
+
}
|
| 94 |
+
var bounds = { x1: m.l + 2, y1: 2, x2: W - 2, y2: m.t + ph - 3 };
|
| 95 |
+
var fs = narrow ? 10.5 : 12;
|
| 96 |
+
function rectDist(b, x, y) { var dx = Math.max(b.x1 - x, 0, x - b.x2), dy = Math.max(b.y1 - y, 0, y - b.y2); return Math.hypot(dx, dy); }
|
| 97 |
+
|
| 98 |
+
function layout(order) {
|
| 99 |
+
var obstacles = baseObs.slice(), out = [];
|
| 100 |
+
function hit(b, self) {
|
| 101 |
+
if (b.x1 < bounds.x1 || b.x2 > bounds.x2 || b.y1 < bounds.y1 || b.y2 > bounds.y2) return true;
|
| 102 |
+
/* never on top of its own dot either (its padded obstacle is skipped, its bounding box is not) */
|
| 103 |
+
if (self && b.x1 + 2 < self.x + self.r && b.x2 - 2 > self.x - self.r && b.y1 + 1 < self.y + self.r && b.y2 - 1 > self.y - self.r) return true;
|
| 104 |
+
for (var i = 0; i < obstacles.length; i++) {
|
| 105 |
+
var o = obstacles[i];
|
| 106 |
+
if (o.owner && o.owner === self) continue;
|
| 107 |
+
if (b.x1 < o.x2 && b.x2 > o.x1 && b.y1 < o.y2 && b.y2 > o.y1) return true;
|
| 108 |
+
}
|
| 109 |
+
return false;
|
| 110 |
+
}
|
| 111 |
+
function ambiguous(b, self, led) {
|
| 112 |
+
var own = rectDist(b, self.x, self.y);
|
| 113 |
+
var bx = (b.x1 + b.x2) / 2, by = (b.y1 + b.y2) / 2, ownC = Math.hypot(bx - self.x, by - self.y);
|
| 114 |
+
for (var i = 0; i < nodes.length; i++) {
|
| 115 |
+
var o = nodes[i];
|
| 116 |
+
if (o === self) continue;
|
| 117 |
+
var d = rectDist(b, o.x, o.y);
|
| 118 |
+
if (d < own + 3) return true;
|
| 119 |
+
/* centre penalty (labels next to their dot; a leader line already shows ownership): a label that
|
| 120 |
+
runs over or right next to another dot and whose centre is nearer that dot than its own reads as
|
| 121 |
+
the other model's label (e.g. Claude-Opus-4.8 over the Claude-Opus-4.6 dot) */
|
| 122 |
+
if (!led && d < 22 && Math.hypot(bx - o.x, by - o.y) < ownC) return true;
|
| 123 |
+
}
|
| 124 |
+
return false;
|
| 125 |
+
}
|
| 126 |
+
function segClear(x0, y0, x1, y1, self) {
|
| 127 |
+
var len = Math.hypot(x1 - x0, y1 - y0), n = Math.max(2, Math.ceil(len / 3));
|
| 128 |
+
for (var i = 1; i < n; i++) {
|
| 129 |
+
var px = x0 + (x1 - x0) * i / n, py = y0 + (y1 - y0) * i / n;
|
| 130 |
+
if (hit({ x1: px - 1, y1: py - 1, x2: px + 1, y2: py + 1 }, self)) return false;
|
| 131 |
+
}
|
| 132 |
+
return true;
|
| 133 |
+
}
|
| 134 |
+
function keep(n, c, b, text, bold, lead) {
|
| 135 |
+
obstacles.push(b);
|
| 136 |
+
if (lead) {
|
| 137 |
+
var len = Math.hypot(lead[2] - lead[0], lead[3] - lead[1]), k = Math.max(2, Math.ceil(len / 4));
|
| 138 |
+
for (var i = 1; i < k; i++) { var px = lead[0] + (lead[2] - lead[0]) * i / k, py = lead[1] + (lead[3] - lead[1]) * i / k; obstacles.push({ x1: px - 1.5, y1: py - 1.5, x2: px + 1.5, y2: py + 1.5 }); }
|
| 139 |
+
}
|
| 140 |
+
out.push({ n: n, c: c, b: b, text: text, bold: bold, lead: lead });
|
| 141 |
+
return true;
|
| 142 |
+
}
|
| 143 |
+
function place(n) {
|
| 144 |
+
var bold = n.front;
|
| 145 |
+
var text = n.m.shortName + (n.front && !narrow ? ' [' + U.tok(tok(n.m)) + ']' : '');
|
| 146 |
+
var font = (bold ? '800 ' : '700 ') + (bold ? fs + 0.5 : fs) + 'px Nunito';
|
| 147 |
+
var w = Math.ceil(U.textWidth(text, font)), hh = fs + 3, r = n.r;
|
| 148 |
+
var near = [
|
| 149 |
+
[n.x + r + 4, n.y + 4, 'start'], [n.x - r - 4, n.y + 4, 'end'],
|
| 150 |
+
[n.x, n.y - r - 5, 'middle'], [n.x, n.y + r + hh, 'middle'],
|
| 151 |
+
[n.x + r + 1, n.y - r - 2, 'start'], [n.x - r - 1, n.y - r - 2, 'end'],
|
| 152 |
+
[n.x + r + 1, n.y + r + hh - 2, 'start'], [n.x - r - 1, n.y + r + hh - 2, 'end']
|
| 153 |
+
];
|
| 154 |
+
if (n.front) near = [near[2], near[4], near[5], near[0], near[1], near[3], near[6], near[7]];
|
| 155 |
+
/* near the plot edges: a label centred above/below its dot may slide sideways to stay inside,
|
| 156 |
+
as long as it still spans its own dot */
|
| 157 |
+
[[n.x, n.y - r - 5], [n.x, n.y + r + hh]].forEach(function (p) {
|
| 158 |
+
if (p[0] - w / 2 - 2 < bounds.x1 && bounds.x1 + 2 + w - 6 > n.x) near.push([bounds.x1 + 2, p[1], 'start']);
|
| 159 |
+
if (p[0] + w / 2 + 2 > bounds.x2 && bounds.x2 - 2 - w + 6 < n.x) near.push([bounds.x2 - 2, p[1], 'end']);
|
| 160 |
+
});
|
| 161 |
+
function boxFor(c) {
|
| 162 |
+
var x1 = c[2] === 'start' ? c[0] : c[2] === 'end' ? c[0] - w : c[0] - w / 2;
|
| 163 |
+
var fsz = bold ? fs + 0.5 : fs;
|
| 164 |
+
return { x1: x1 - 2, y1: c[1] - fsz * 1.02 - 1, x2: x1 + w + 2, y2: c[1] + fsz * 0.37 + 1 };
|
| 165 |
+
}
|
| 166 |
+
for (var i = 0; i < near.length; i++) {
|
| 167 |
+
var b = boxFor(near[i]);
|
| 168 |
+
if (!hit(b, n) && !ambiguous(b, n)) return keep(n, near[i], b, text, bold, null);
|
| 169 |
+
}
|
| 170 |
+
var angles = [0, 180, -30, -150, 30, 150, -60, -120, 60, 120, -90, 90, -15, -165, 15, 165];
|
| 171 |
+
/* short leaders only (a long leader across the cloud reads as someone else's label) */
|
| 172 |
+
var dists = narrow ? [16, 22, 28, 36, 46, 58] : [22, 30, 40, 52, 66];
|
| 173 |
+
for (var di = 0; di < dists.length; di++) {
|
| 174 |
+
for (var ai = 0; ai < angles.length; ai++) {
|
| 175 |
+
var a = angles[ai] * Math.PI / 180, cx = Math.cos(a), cy = Math.sin(a);
|
| 176 |
+
var lx = n.x + cx * dists[di], ly = n.y + cy * dists[di];
|
| 177 |
+
var anchor = cx > 0.3 ? 'start' : cx < -0.3 ? 'end' : 'middle';
|
| 178 |
+
var c = [lx, ly + (cy < -0.3 ? -2 : cy > 0.3 ? hh - 2 : 4), anchor];
|
| 179 |
+
var bb = boxFor(c);
|
| 180 |
+
var ex = Math.max(bb.x1, Math.min(n.x, bb.x2)), ey = Math.max(bb.y1, Math.min(n.y, bb.y2));
|
| 181 |
+
var sx = n.x + cx * (r + 2), sy = n.y + cy * (r + 2);
|
| 182 |
+
/* the label must still sit closer to its own dot than to any other dot */
|
| 183 |
+
if (!hit(bb, n) && !ambiguous(bb, n, true) && segClear(sx, sy, ex, ey, n)) return keep(n, c, bb, text, bold, [sx, sy, ex, ey]);
|
| 184 |
+
}
|
| 185 |
+
}
|
| 186 |
+
return false;
|
| 187 |
+
}
|
| 188 |
+
order.forEach(place);
|
| 189 |
+
return out;
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
nodes.forEach(function (n) { n.crowd = nodes.filter(function (o) { return o !== n && Math.hypot(o.x - n.x, o.y - n.y) < 70; }).length; });
|
| 193 |
+
function byCrowd(a, b) { return b.crowd - a.crowd || acc(b.m) - acc(a.m); }
|
| 194 |
+
/* phones: label only the frontier and the models the paper names; the rest are in the tooltip and table */
|
| 195 |
+
var tiers = [nodes.filter(function (n) { return n.front; }),
|
| 196 |
+
nodes.filter(function (n) { return !n.front && n.must; }).sort(byCrowd),
|
| 197 |
+
narrow ? [] : nodes.filter(function (n) { return !n.front && !n.must; }).sort(byCrowd)];
|
| 198 |
+
var result = layout([].concat(tiers[0], tiers[1], tiers[2]));
|
| 199 |
+
for (var attempt = 0; attempt < 3; attempt++) {
|
| 200 |
+
var got = result.map(function (x) { return x.n; });
|
| 201 |
+
var missingPri = tiers[0].concat(tiers[1]).filter(function (n) { return got.indexOf(n) < 0; });
|
| 202 |
+
if (!missingPri.length) break;
|
| 203 |
+
tiers.forEach(function (t, ti) { tiers[ti] = missingPri.filter(function (n) { return t.indexOf(n) >= 0; }).concat(t.filter(function (n) { return missingPri.indexOf(n) < 0; })); });
|
| 204 |
+
var next = layout([].concat(tiers[0], tiers[1], tiers[2]));
|
| 205 |
+
var nextMissing = tiers[0].concat(tiers[1]).filter(function (n) { return next.map(function (x) { return x.n; }).indexOf(n) < 0; }).length;
|
| 206 |
+
if (nextMissing < missingPri.length || (nextMissing === missingPri.length && next.length > result.length)) result = next;
|
| 207 |
+
}
|
| 208 |
+
result.forEach(function (L) {
|
| 209 |
+
if (L.lead) s('line', { class: 'leader', x1: L.lead[0].toFixed(1), y1: L.lead[1].toFixed(1), x2: L.lead[2].toFixed(1), y2: L.lead[3].toFixed(1) }, leadLayer);
|
| 210 |
+
var t = s('text', { class: 'pt-label' + (L.bold ? '' : ' pt-label--muted'), x: L.c[0].toFixed(1), y: L.c[1].toFixed(1), 'text-anchor': L.c[2], style: 'font-size:' + (L.bold ? fs + 0.5 : fs) + 'px' }, labLayer);
|
| 211 |
+
var i2 = L.text.indexOf(' [');
|
| 212 |
+
if (L.bold && i2 > 0) {
|
| 213 |
+
t.appendChild(document.createTextNode(L.text.slice(0, i2)));
|
| 214 |
+
var ts = s('tspan', { class: 'pt-label__tok' }, t); ts.textContent = L.text.slice(i2);
|
| 215 |
+
} else t.textContent = L.text;
|
| 216 |
+
L.n.labelled = true;
|
| 217 |
+
});
|
| 218 |
+
/* ---- points that did not get a name get a small number next to their dot, keyed under the chart,
|
| 219 |
+
placed with the same rules (no collisions; the number sits closer to its own dot than to any other) ---- */
|
| 220 |
+
var obs2 = baseObs.slice();
|
| 221 |
+
result.forEach(function (L) {
|
| 222 |
+
obs2.push(L.b);
|
| 223 |
+
if (L.lead) { var len = Math.hypot(L.lead[2] - L.lead[0], L.lead[3] - L.lead[1]), k = Math.max(2, Math.ceil(len / 4)); for (var i = 1; i < k; i++) { var px = L.lead[0] + (L.lead[2] - L.lead[0]) * i / k, py = L.lead[1] + (L.lead[3] - L.lead[1]) * i / k; obs2.push({ x1: px - 1.5, y1: py - 1.5, x2: px + 1.5, y2: py + 1.5 }); } }
|
| 224 |
+
});
|
| 225 |
+
var keyed = [], nfs = 10.5;
|
| 226 |
+
/* near-coincident unnamed points (< 8 px apart) share one tag such as "3/4" */
|
| 227 |
+
var groups = [];
|
| 228 |
+
nodes.filter(function (n) { return !n.labelled; }).sort(function (a, b) { return a.x - b.x || a.y - b.y; }).forEach(function (n) {
|
| 229 |
+
var g = groups.filter(function (gr) { return gr.some(function (o) { return Math.hypot(o.x - n.x, o.y - n.y) < 8; }); })[0];
|
| 230 |
+
if (g) g.push(n); else groups.push([n]);
|
| 231 |
+
});
|
| 232 |
+
groups.forEach(function (grp) {
|
| 233 |
+
var nums = grp.map(function (n, i) { return keyed.length + i + 1; });
|
| 234 |
+
var txt = nums.join('/'), w = Math.ceil(U.textWidth(txt, '800 ' + nfs + 'px Nunito'));
|
| 235 |
+
var cx = grp.reduce(function (a, n) { return a + n.x; }, 0) / grp.length, cy = grp.reduce(function (a, n) { return a + n.y; }, 0) / grp.length;
|
| 236 |
+
var r = Math.max.apply(null, grp.map(function (n) { return n.r + Math.hypot(n.x - cx, n.y - cy); }));
|
| 237 |
+
var cand = [];
|
| 238 |
+
[0, 4].forEach(function (d) {
|
| 239 |
+
cand.push([cx + r + 3 + d, cy + 4, 'start'], [cx - r - 3 - d, cy + 4, 'end'], [cx, cy - r - 3 - d, 'middle'], [cx, cy + r + nfs + 1 + d, 'middle'],
|
| 240 |
+
[cx + r + 2 + d, cy - r - 1 - d, 'start'], [cx - r - 2 - d, cy - r - 1 - d, 'end'], [cx + r + 2 + d, cy + r + nfs - 1 + d, 'start'], [cx - r - 2 - d, cy + r + nfs - 1 + d, 'end']);
|
| 241 |
+
});
|
| 242 |
+
for (var i = 0; i < cand.length; i++) {
|
| 243 |
+
var c = cand[i], x1 = c[2] === 'start' ? c[0] : c[2] === 'end' ? c[0] - w : c[0] - w / 2;
|
| 244 |
+
var b = { x1: x1 - 1.5, y1: c[1] - nfs * 1.08 - 1, x2: x1 + w + 1.5, y2: c[1] + nfs * 0.37 + 1 };
|
| 245 |
+
if (b.x1 < bounds.x1 || b.x2 > bounds.x2 || b.y1 < bounds.y1 || b.y2 > bounds.y2) continue;
|
| 246 |
+
if (grp.some(function (n) { return b.x1 < n.x + n.r && b.x2 > n.x - n.r && b.y1 < n.y + n.r && b.y2 > n.y - n.r; })) continue;
|
| 247 |
+
var clash = obs2.some(function (o) { return grp.indexOf(o.owner) < 0 && b.x1 < o.x2 && b.x2 > o.x1 && b.y1 < o.y2 && b.y2 > o.y1; });
|
| 248 |
+
if (clash) continue;
|
| 249 |
+
var own = Math.max.apply(null, grp.map(function (n) { return rectDist(b, n.x, n.y); }));
|
| 250 |
+
if (nodes.some(function (o) { return grp.indexOf(o) < 0 && rectDist(b, o.x, o.y) < own + 3; })) continue;
|
| 251 |
+
obs2.push(b);
|
| 252 |
+
var t = s('text', { class: 'pt-num', x: c[0].toFixed(1), y: c[1].toFixed(1), 'text-anchor': c[2], style: 'font-size:' + nfs + 'px' }, labLayer);
|
| 253 |
+
t.textContent = txt;
|
| 254 |
+
grp.forEach(function (n) { keyed.push(n); n.labelled = true; });
|
| 255 |
+
return;
|
| 256 |
+
}
|
| 257 |
+
});
|
| 258 |
+
if (keyed.length) {
|
| 259 |
+
var key = h('p', { class: 'pt-key' }, h('span', { class: 'legend__title', text: 'Numbered points:' }));
|
| 260 |
+
keyed.forEach(function (n, i) { key.appendChild(h('span', { class: 'pt-key__i' }, h('b', { text: String(i + 1) }), ' ' + n.m.shortName)); });
|
| 261 |
+
box.appendChild(key);
|
| 262 |
+
}
|
| 263 |
+
var unl = nodes.filter(function (n) { return !n.labelled; }).length;
|
| 264 |
+
|
| 265 |
+
/* ---- interaction: nearest-point hover + one Tab stop with arrow keys (ordered by cost) ---- */
|
| 266 |
+
var hitLayer = s('g', null, svg);
|
| 267 |
+
var active = null;
|
| 268 |
+
function activate(n, ev) {
|
| 269 |
+
if (active && active !== n) deactivate();
|
| 270 |
+
active = n;
|
| 271 |
+
n.dot.setAttribute('r', n.r + 2.5);
|
| 272 |
+
n.dot.setAttribute('stroke', U.css('--ink'));
|
| 273 |
+
n.dot.setAttribute('stroke-width', 2.5);
|
| 274 |
+
if (ev) U.tip.show(tipSpec(n.m), ev.clientX, ev.clientY, svg);
|
| 275 |
+
}
|
| 276 |
+
function deactivate() {
|
| 277 |
+
if (!active) return;
|
| 278 |
+
active.dot.setAttribute('r', active.r);
|
| 279 |
+
active.dot.setAttribute('stroke', '#fff');
|
| 280 |
+
active.dot.setAttribute('stroke-width', 2);
|
| 281 |
+
active = null;
|
| 282 |
+
}
|
| 283 |
+
var byCost = nodes.slice().sort(function (a, b) { return cost(a.m) - cost(b.m) || acc(a.m) - acc(b.m); });
|
| 284 |
+
byCost.forEach(function (n) {
|
| 285 |
+
n.hit = s('circle', { class: 'pt-hit', cx: n.x, cy: n.y, r: 13, role: 'img',
|
| 286 |
+
'aria-label': n.m.name + ': ' + modeLabel().toLowerCase() + ' accuracy ' + U.pct(acc(n.m)) + ' percent, ' + U.usd(costTxt(n.m)) + ' per task, ' + U.tok(tok(n.m)) + ' tokens per task' + (n.front ? ', on the Pareto frontier drawn in Fig. 1' : '') }, hitLayer);
|
| 287 |
+
n.hit.addEventListener('focus', function () { activate(n); U.tip.focus(function () { return tipSpec(n.m); }, n.hit); });
|
| 288 |
+
n.hit.addEventListener('blur', function () { deactivate(); U.tip.blur(n.hit); });
|
| 289 |
+
});
|
| 290 |
+
U.roving(byCost.map(function (n) { return n.hit; }));
|
| 291 |
+
svg.addEventListener('pointermove', function (e) {
|
| 292 |
+
var r = svg.getBoundingClientRect(), px = e.clientX - r.left, py = e.clientY - r.top;
|
| 293 |
+
var best = null, bd = 30 * 30;
|
| 294 |
+
nodes.forEach(function (n) { var d = (n.x - px) * (n.x - px) + (n.y - py) * (n.y - py); if (d < bd) { bd = d; best = n; } });
|
| 295 |
+
if (best) activate(best, e); else { deactivate(); U.tip.hide(svg); }
|
| 296 |
+
});
|
| 297 |
+
svg.addEventListener('pointerleave', function () { deactivate(); U.tip.hide(svg); });
|
| 298 |
+
|
| 299 |
+
var capNote = D.pareto.note.replace(/^.*?\(caption\)\.\s*/, '');
|
| 300 |
+
U.$('#scatter-cap').textContent = capNote + (unl ? ' ' + unl + (unl === 1 ? ' point is' : ' points are') + ' unlabeled at this width; hover, focus or use the table view.' : '');
|
| 301 |
+
}
|
| 302 |
+
|
| 303 |
+
function scatterMeta() {
|
| 304 |
+
var n = plotted().length;
|
| 305 |
+
U.$('#scatter-title').textContent = (mode === 'text' ? '(a) Text' : '(b) Multimodal') + ': accuracy vs. cost per task';
|
| 306 |
+
U.$('#scatter-sub').textContent = 'The ' + n + ' API models plotted in the paper’s Fig. 1' + (mode === 'text' ? '(a)' : '(b)') + '. Accuracy is the Table 1 ' + (mode === 'text' ? 'Text Avg' : 'MM Avg') + '; cost is the Table 2 reference cost. On wider screens, frontier labels show tokens per task, as in the paper.';
|
| 307 |
+
var lg = U.$('#scatter-legend');
|
| 308 |
+
lg.textContent = '';
|
| 309 |
+
lg.appendChild(h('span', { class: 'legend__item' }, h('span', { class: 'legend__line legend__line--dash' }), 'Pareto frontier (dashed, as drawn in Fig. 1)'));
|
| 310 |
+
lg.appendChild(h('span', { class: 'legend__item' }, h('span', { class: 'legend__dot', style: { background: 'var(--pareto-muted)' } }), 'Other API models'));
|
| 311 |
+
var rows = plotted().slice().sort(function (a, b) { return cost(a) - cost(b); });
|
| 312 |
+
U.tableView(U.$('#scatter-table'), U.table([
|
| 313 |
+
{ label: 'Model', get: modelCell },
|
| 314 |
+
{ label: 'Vendor', cls: 'col-vendor', get: function (m) { return m.vendor; } },
|
| 315 |
+
{ label: 'Accuracy (%)', num: true, get: function (m) { return U.pct(acc(m)); } },
|
| 316 |
+
{ label: 'Cost / task', num: true, get: function (m) { return U.usd(costTxt(m)); } },
|
| 317 |
+
{ label: 'Tokens / task', num: true, get: function (m) { return U.tok(tok(m)); } },
|
| 318 |
+
{ label: 'Frontier (Fig. 1)', get: function (m) { return isFront(m) ? 'Yes' : ''; } }
|
| 319 |
+
], rows, modeLabel() + ': accuracy and cost of the models in Fig. 1, sorted by cost'));
|
| 320 |
+
}
|
| 321 |
+
/* table views: on phones the Vendor column folds into a second line of the model cell */
|
| 322 |
+
function modelCell(m) { return [m.name, h('span', { class: 'cell-sub', text: m.vendor })]; }
|
| 323 |
+
|
| 324 |
+
function notes() {
|
| 325 |
+
var aside = U.$('#cost-notes');
|
| 326 |
+
aside.textContent = '';
|
| 327 |
+
var chain = h('ol', { class: 'chain' });
|
| 328 |
+
D.pareto[mode].map(U.model).forEach(function (m) {
|
| 329 |
+
chain.appendChild(h('li', null, h('b', { text: m.shortName }), h('span', { class: 'num', text: U.usd(costTxt(m)) + ' · ' + U.pct(acc(m)) + '%' })));
|
| 330 |
+
});
|
| 331 |
+
aside.appendChild(h('div', { class: 'note-card' },
|
| 332 |
+
h('h3', null, U.icon('i-frontier'), (mode === 'text' ? 'Text' : 'Multimodal') + ' frontier, cheapest first'),
|
| 333 |
+
chain));
|
| 334 |
+
var f = finding('pareto');
|
| 335 |
+
aside.appendChild(h('div', { class: 'note-card' }, h('h3', { text: 'What the paper observes' }), h('p', null, U.emphNums(f.statement))));
|
| 336 |
+
var lt = finding('local-tokens');
|
| 337 |
+
if (lt) aside.appendChild(h('div', { class: 'note-card' }, h('h3', null, U.icon('i-server'), 'And the local models? (' + lt.section + ')'), h('p', null, U.emphNums(lt.statement))));
|
| 338 |
+
}
|
| 339 |
+
|
| 340 |
+
/* ---------------- tokens vs dollars: shared rows, token bars (linear) + cost dots (log) ---------------- */
|
| 341 |
+
function drawTokens() {
|
| 342 |
+
var box = U.$('#tokens-box');
|
| 343 |
+
var W = Math.max(260, Math.round(box.clientWidth));
|
| 344 |
+
/* phones: two full-width panels (tokens, then cost) in the same row order, names above the marks,
|
| 345 |
+
so each plot keeps the full card width instead of ~50 px beside a name column */
|
| 346 |
+
var stacked = W < 600, wide = W >= 820, compact = W < 700;
|
| 347 |
+
var list = apiModels();
|
| 348 |
+
var rows = list.slice().sort(tokSort === 'tokens'
|
| 349 |
+
? function (a, b) { return tok(a) - tok(b) || cost(a) - cost(b); }
|
| 350 |
+
: function (a, b) { return cost(a) - cost(b) || tok(a) - tok(b); });
|
| 351 |
+
var byTok = list.slice().sort(function (a, b) { return tok(a) - tok(b); });
|
| 352 |
+
var byCost = list.slice().sort(function (a, b) { return cost(a) - cost(b); });
|
| 353 |
+
var tags = {};
|
| 354 |
+
function tag(m, t) { (tags[m.name] = tags[m.name] || []).push(t); }
|
| 355 |
+
tag(byTok[0], 'fewest tokens'); tag(byTok[byTok.length - 1], 'most tokens');
|
| 356 |
+
tag(byCost[0], 'cheapest'); tag(byCost[byCost.length - 1], 'most expensive');
|
| 357 |
+
var maxTok = tok(byTok[byTok.length - 1]);
|
| 358 |
+
var cLo = Math.log10(cost(byCost[0]) / 1.4), cHi = Math.log10(cost(byCost[byCost.length - 1]) * 1.25);
|
| 359 |
+
var color = modeColor();
|
| 360 |
+
var fs = stacked ? 12 : compact ? 11.5 : 12.5;
|
| 361 |
+
var tickFont = '400 12.5px Nunito';
|
| 362 |
+
|
| 363 |
+
box.textContent = '';
|
| 364 |
+
var hits = [], rowEls = {};
|
| 365 |
+
function hot(m, on) { (rowEls[m.name] || []).forEach(function (g) { g.classList.toggle('is-hot', on); }); }
|
| 366 |
+
function rightRound(x, y, w, h) {
|
| 367 |
+
/* bar with a rounded data end (radius <= half the width, so short bars stay proportional) */
|
| 368 |
+
var r = Math.min(4, w / 2, h / 2);
|
| 369 |
+
return 'M' + x + ' ' + y + ' h' + (w - r) + ' a' + r + ' ' + r + ' 0 0 1 ' + r + ' ' + r + ' v' + (h - 2 * r) + ' a' + r + ' ' + r + ' 0 0 1 -' + r + ' ' + r + ' h-' + (w - r) + ' z';
|
| 370 |
+
}
|
| 371 |
+
function costTicks(x0, x1, CX) {
|
| 372 |
+
var t = [];
|
| 373 |
+
for (var e = Math.floor(cLo); e <= Math.ceil(cHi); e++) [1, 2, 5].forEach(function (k) {
|
| 374 |
+
var v = k * Math.pow(10, e);
|
| 375 |
+
if (Math.log10(v) >= cLo && Math.log10(v) <= cHi) t.push({ v: v, k: k, x: CX(v) });
|
| 376 |
+
});
|
| 377 |
+
return { all: t, labelled: U.fitTicks(t, U.usdTick, x0, x1, tickFont, 10) };
|
| 378 |
+
}
|
| 379 |
+
function label(m) {
|
| 380 |
+
return m.name + ': ' + U.tok(tok(m)) + ' tokens per task, ' + U.usd(costTxt(m)) + ' per task' + (tags[m.name] ? ' (' + tags[m.name].join(', ') + ')' : '');
|
| 381 |
+
}
|
| 382 |
+
function wire(hitR, m, focusable) {
|
| 383 |
+
hitR.addEventListener('pointermove', function (ev) { hot(m, true); U.tip.show(tipSpec(m), ev.clientX, ev.clientY, hitR); });
|
| 384 |
+
hitR.addEventListener('pointerleave', function () { hot(m, false); U.tip.hide(hitR); });
|
| 385 |
+
if (!focusable) return;
|
| 386 |
+
hitR.addEventListener('focus', function () { hot(m, true); U.tip.focus(function () { return tipSpec(m); }, hitR); });
|
| 387 |
+
hitR.addEventListener('blur', function () { hot(m, false); U.tip.blur(hitR); });
|
| 388 |
+
hits.push(hitR);
|
| 389 |
+
}
|
| 390 |
+
var svg, ax, H;
|
| 391 |
+
|
| 392 |
+
if (stacked) {
|
| 393 |
+
var rowH = 27, head = 46, pgap = 30;
|
| 394 |
+
var panelH = head + rows.length * rowH;
|
| 395 |
+
H = panelH * 2 + pgap;
|
| 396 |
+
var barMax = W - 2;
|
| 397 |
+
var CXs = function (c) { return 6 + (Math.log10(c) - cLo) / (cHi - cLo) * (W - 12); };
|
| 398 |
+
svg = s('svg', { width: W, height: H, viewBox: '0 0 ' + W + ' ' + H, role: 'group', 'aria-label': 'API models ' + (tokSort === 'tokens' ? 'sorted by tokens per task' : 'sorted by cost per task') + ': first panel, token bars on a linear scale; second panel, cost dots on a log scale, in the same row order. One Tab stop: use the arrow keys to move between models.' }, box);
|
| 399 |
+
ax = s('g', { class: 'axis', 'aria-hidden': 'true' }, svg);
|
| 400 |
+
var hdr = function (y, txt) { var t = s('text', { class: 'chains-head', x: 0, y: y }, ax); t.textContent = txt; };
|
| 401 |
+
var tickTxt = function (x, y, txt, anchor) { var t = s('text', { class: 'tick', x: x, y: y, 'text-anchor': anchor }, ax); t.textContent = txt; };
|
| 402 |
+
/* panel 1: tokens */
|
| 403 |
+
hdr(16, 'Tokens per task');
|
| 404 |
+
var tstep = maxTok > 300 ? 200 : 100;
|
| 405 |
+
for (var tv = 0; tv <= maxTok; tv += tstep) {
|
| 406 |
+
var tx = tv / maxTok * barMax;
|
| 407 |
+
s('line', { class: 'grid-line', x1: tx, x2: tx, y1: head - 6, y2: panelH }, ax);
|
| 408 |
+
tickTxt(tx, head - 12, tv === 0 ? '0' : tv + 'k', tv === 0 ? 'start' : 'middle');
|
| 409 |
+
}
|
| 410 |
+
/* panel 2: cost (log) */
|
| 411 |
+
var y2 = panelH + pgap;
|
| 412 |
+
hdr(y2 + 16, 'Cost per task (USD, log scale)');
|
| 413 |
+
var ct = costTicks(0, W, CXs);
|
| 414 |
+
ct.all.forEach(function (o) { s('line', { class: 'grid-line', x1: o.x, x2: o.x, y1: y2 + head - 6, y2: H }, ax); });
|
| 415 |
+
ct.labelled.forEach(function (o) { tickTxt(o.x, y2 + head - 12, U.usdTick(o.v), 'middle'); });
|
| 416 |
+
rows.forEach(function (m, i) {
|
| 417 |
+
rowEls[m.name] = [];
|
| 418 |
+
[0, 1].forEach(function (panel) {
|
| 419 |
+
var y = (panel ? y2 : 0) + head + i * rowH;
|
| 420 |
+
var gr = s('g', { class: 'tk-row' + (tags[m.name] ? ' is-key' : ''), transform: 'translate(0 ' + y + ')', 'aria-hidden': 'true' }, svg);
|
| 421 |
+
rowEls[m.name].push(gr);
|
| 422 |
+
s('rect', { class: 'tk-band', x: -4, y: 0, width: W + 8, height: rowH - 1, rx: 6 }, gr);
|
| 423 |
+
var nm = s('text', { class: 'nm', x: 0, y: 11.5, style: 'font-size:' + fs + 'px' }, gr); nm.textContent = m.shortName;
|
| 424 |
+
var val = s('text', { class: 'val', x: W, y: 11.5, 'text-anchor': 'end', style: 'font-size:' + (fs - 0.5) + 'px' }, gr);
|
| 425 |
+
if (panel === 0) {
|
| 426 |
+
val.textContent = U.tok(tok(m));
|
| 427 |
+
s('path', { d: rightRound(0, 15, Math.max(1, tok(m) / maxTok * barMax), 8), fill: color }, gr);
|
| 428 |
+
} else {
|
| 429 |
+
val.textContent = U.usd(costTxt(m));
|
| 430 |
+
s('line', { class: 'tk-stem', x1: 0, x2: CXs(cost(m)), y1: 19, y2: 19 }, gr);
|
| 431 |
+
s('circle', { cx: CXs(cost(m)), cy: 19, r: 5, fill: color, stroke: '#fff', 'stroke-width': 2 }, gr);
|
| 432 |
+
}
|
| 433 |
+
var hitR = s('rect', { class: 'tk-hit', x: 0, y: y, width: W, height: rowH, rx: 6 }, svg);
|
| 434 |
+
if (panel === 0) { hitR.setAttribute('role', 'img'); hitR.setAttribute('aria-label', label(m)); }
|
| 435 |
+
else hitR.setAttribute('aria-hidden', 'true');
|
| 436 |
+
wire(hitR, m, panel === 0);
|
| 437 |
+
});
|
| 438 |
+
});
|
| 439 |
+
} else {
|
| 440 |
+
var nameW = Math.ceil(Math.max.apply(null, list.map(function (m) { return U.textWidth(m.shortName, '800 ' + fs + 'px Nunito'); }))) + 10;
|
| 441 |
+
var valW = compact ? 46 : 52, tagW = wide ? 150 : 0, gap = compact ? 16 : 22;
|
| 442 |
+
var panelW = (W - nameW - valW - tagW - gap * 2) / 2;
|
| 443 |
+
var tokX = nameW + 6, tokValPad = compact ? 36 : 40, tokBarMax = panelW - tokValPad;
|
| 444 |
+
var costX = tokX + panelW + gap, costW = panelW;
|
| 445 |
+
var rowH2 = compact ? 24 : 26, head2 = 54;
|
| 446 |
+
H = head2 + rows.length * rowH2 + 8;
|
| 447 |
+
var CX = function (c) { return costX + 6 + (Math.log10(c) - cLo) / (cHi - cLo) * (costW - 12); };
|
| 448 |
+
svg = s('svg', { width: W, height: H, viewBox: '0 0 ' + W + ' ' + H, role: 'group', 'aria-label': 'API models ' + (tokSort === 'tokens' ? 'sorted by tokens per task' : 'sorted by cost per task') + ': token bars on a linear scale and cost dots on a log scale. One Tab stop: use the arrow keys to move between rows.' }, box);
|
| 449 |
+
ax = s('g', { class: 'axis', 'aria-hidden': 'true' }, svg);
|
| 450 |
+
var headText = function (x, y, txt, cls, anchor) { var t = s('text', { class: cls, x: x, y: y, 'text-anchor': anchor || 'start' }, ax); t.textContent = txt; return t; };
|
| 451 |
+
headText(tokX, 16, 'Tokens per task', 'chains-head');
|
| 452 |
+
headText(costX, 16, compact ? 'Cost per task (log)' : 'Cost per task (USD, log)', 'chains-head');
|
| 453 |
+
var tstep2 = maxTok > 300 ? 200 : 100;
|
| 454 |
+
for (var tv2 = 0; tv2 <= maxTok; tv2 += tstep2) {
|
| 455 |
+
var x = tokX + tv2 / maxTok * tokBarMax;
|
| 456 |
+
s('line', { class: 'grid-line', x1: x, x2: x, y1: head2 - 6, y2: H - 6 }, ax);
|
| 457 |
+
headText(x, head2 - 12, tv2 === 0 ? '0' : tv2 + 'k', 'tick', tv2 === 0 ? 'start' : 'middle');
|
| 458 |
+
}
|
| 459 |
+
var ct2 = costTicks(costX, costX + costW, CX);
|
| 460 |
+
ct2.all.forEach(function (o) { s('line', { class: 'grid-line', x1: o.x, x2: o.x, y1: head2 - 6, y2: H - 6 }, ax); });
|
| 461 |
+
ct2.labelled.forEach(function (o) { headText(o.x, head2 - 12, U.usdTick(o.v), 'tick', 'middle'); });
|
| 462 |
+
rows.forEach(function (m, i) {
|
| 463 |
+
var y = head2 + i * rowH2;
|
| 464 |
+
var gr = s('g', { class: 'tk-row' + (tags[m.name] ? ' is-key' : ''), transform: 'translate(0 ' + y + ')', 'aria-hidden': 'true' }, svg);
|
| 465 |
+
rowEls[m.name] = [gr];
|
| 466 |
+
s('rect', { class: 'tk-band', x: 0, y: 1, width: W, height: rowH2 - 2, rx: 6 }, gr);
|
| 467 |
+
var cy = rowH2 / 2;
|
| 468 |
+
var nm = s('text', { class: 'nm', x: nameW - 4, y: cy + 4.5, 'text-anchor': 'end', style: 'font-size:' + fs + 'px' }, gr); nm.textContent = m.shortName;
|
| 469 |
+
var bw = Math.max(1, tok(m) / maxTok * tokBarMax);
|
| 470 |
+
var bh = Math.min(12, rowH2 - 12);
|
| 471 |
+
s('path', { d: rightRound(tokX, cy - bh / 2, bw, bh), fill: color }, gr);
|
| 472 |
+
var tvt = s('text', { class: 'val', x: tokX + bw + 5, y: cy + 4.5, style: 'font-size:' + (fs - 0.5) + 'px' }, gr); tvt.textContent = U.tok(tok(m));
|
| 473 |
+
s('line', { class: 'tk-stem', x1: costX + 6, x2: CX(cost(m)), y1: cy, y2: cy }, gr);
|
| 474 |
+
s('circle', { cx: CX(cost(m)), cy: cy, r: 5.5, fill: color, stroke: '#fff', 'stroke-width': 2 }, gr);
|
| 475 |
+
var cvt = s('text', { class: 'val', x: W - tagW - 2, y: cy + 4.5, 'text-anchor': 'end', style: 'font-size:' + (fs - 0.5) + 'px' }, gr); cvt.textContent = U.usd(costTxt(m));
|
| 476 |
+
if (wide && tags[m.name]) {
|
| 477 |
+
var tg = s('text', { class: 'tk-tag', x: W - tagW + 12, y: cy + 5 }, gr);
|
| 478 |
+
tg.textContent = '← ' + tags[m.name].join(', ');
|
| 479 |
+
}
|
| 480 |
+
var hitR = s('rect', { class: 'tk-hit', x: 0, y: y, width: W, height: rowH2, role: 'img', 'aria-label': label(m) }, svg);
|
| 481 |
+
wire(hitR, m, true);
|
| 482 |
+
});
|
| 483 |
+
}
|
| 484 |
+
U.roving(hits);
|
| 485 |
+
|
| 486 |
+
U.$('#tokens-sub').textContent = 'Tokens and reference cost per task for the ' + list.length + ' API models in Table 2 (' + (mode === 'text' ? 'Text Avg' : 'MM Avg') + (stacked ? '), in the same row order in both panels. ' : '), on shared rows. ') +
|
| 487 |
+
(tokSort === 'tokens' ? 'Rows are sorted by tokens: if tokens predicted cost, the dots would climb steadily to the right.' : 'Rows are sorted by cost: if cost predicted tokens, the bars would grow steadily.');
|
| 488 |
+
var cap = U.$('#tokens-cap');
|
| 489 |
+
cap.textContent = '';
|
| 490 |
+
var ext = h('p', { class: 'tokens-ext' });
|
| 491 |
+
[['fewest tokens', byTok[0], U.tok(tok(byTok[0]))], ['most tokens', byTok[byTok.length - 1], U.tok(tok(byTok[byTok.length - 1]))],
|
| 492 |
+
['cheapest', byCost[0], U.usd(costTxt(byCost[0]))], ['most expensive', byCost[byCost.length - 1], U.usd(costTxt(byCost[byCost.length - 1]))]].forEach(function (x) {
|
| 493 |
+
ext.appendChild(h('span', { class: 'tokens-ext__i' }, h('span', { class: 'scribble scribble--sm', text: x[0] }), h('b', { text: x[1].shortName }), ' ' + x[2]));
|
| 494 |
+
});
|
| 495 |
+
cap.appendChild(ext);
|
| 496 |
+
cap.appendChild(h('p', { class: 'note' }, U.emphNums(finding('tokens-vs-dollars').statement)));
|
| 497 |
+
|
| 498 |
+
U.tableView(U.$('#tokens-table'), U.table([
|
| 499 |
+
{ label: 'Model', get: modelCell },
|
| 500 |
+
{ label: 'Vendor', cls: 'col-vendor', get: function (m) { return m.vendor; } },
|
| 501 |
+
{ label: 'Tokens / task', num: true, get: function (m) { return U.tok(tok(m)); } },
|
| 502 |
+
{ label: 'Cost / task', num: true, get: function (m) { return U.usd(costTxt(m)); } },
|
| 503 |
+
{ label: 'Accuracy (%)', num: true, get: function (m) { return U.pct(acc(m)); } }
|
| 504 |
+
], rows, modeLabel() + ': API models (Table 2), ' + (tokSort === 'tokens' ? 'sorted by tokens per task' : 'sorted by cost per task')));
|
| 505 |
+
}
|
| 506 |
+
|
| 507 |
+
function renderAll() { scatterMeta(); drawScatter(); notes(); drawTokens(); }
|
| 508 |
+
|
| 509 |
+
U.initCost = function () {
|
| 510 |
+
U.$('#cost-lead').textContent = 'Reference cost per task comes from public API prices, so the paper analyzes accuracy–cost trade-offs for API models. Text and multimodal workloads trace different Pareto frontiers, and the models that use the fewest tokens are not the ones that cost the least.';
|
| 511 |
+
U.seg(U.$('#cost-mode'), [
|
| 512 |
+
{ value: 'text', label: 'Text', dot: 'var(--series-text)' },
|
| 513 |
+
{ value: 'mm', label: 'Multimodal', dot: 'var(--series-mm)' }
|
| 514 |
+
], mode, function (v) { mode = v; renderAll(); });
|
| 515 |
+
U.seg(U.$('#tokens-sort'), [
|
| 516 |
+
{ value: 'tokens', label: 'Sort by tokens' },
|
| 517 |
+
{ value: 'cost', label: 'Sort by cost' }
|
| 518 |
+
], tokSort, function (v) { tokSort = v; drawTokens(); });
|
| 519 |
+
var f1 = U.fig('fig1');
|
| 520 |
+
U.$('#fig1-btn-lab').textContent = 'Paper’s ' + f1.label;
|
| 521 |
+
U.$('#fig1-btn').setAttribute('aria-label', 'Open the paper’s ' + f1.label + ' (accuracy–cost plot) in a larger view');
|
| 522 |
+
U.$('#fig1-btn').addEventListener('click', function () { U.lightbox(U.IMG + f1.file, f1.alt, f1.label + '. ' + f1.caption); });
|
| 523 |
+
renderAll();
|
| 524 |
+
/* labels are measured with the web font: redraw once it has loaded */
|
| 525 |
+
if (document.fonts && document.fonts.ready) document.fonts.ready.then(function () { drawScatter(); drawTokens(); });
|
| 526 |
+
U.onResize(U.$('#scatter-box'), function () { drawScatter(); });
|
| 527 |
+
U.onResize(U.$('#tokens-box'), function () { drawTokens(); });
|
| 528 |
+
document.addEventListener('viewtoggle', function (e) { if (!e.detail.table) { if (e.detail.target === 'scatter') drawScatter(); if (e.detail.target === 'tokens') drawTokens(); } });
|
| 529 |
+
};
|
| 530 |
+
U.costMode = function () { return mode; };
|
| 531 |
+
})();
|
assets/js/leaderboard.js
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Interactive leaderboard: paper Table 1 (audited accuracy), every model in data.js.
|
| 2 |
+
Column order follows Table 1 (Text groups, Text Avg, MM groups, MM Avg) plus Overall (Eq. 11). */
|
| 3 |
+
(function () {
|
| 4 |
+
'use strict';
|
| 5 |
+
var U = window.U, D = U.D, h = U.h, S = D.stats;
|
| 6 |
+
var state = { track: 'full', deploy: 'all', style: 'bars', sort: 'overall', dir: 'desc' };
|
| 7 |
+
var segs = {};
|
| 8 |
+
/* heat mode: four bins on teal steps 400-700, the subset that passes the ordinal checks
|
| 9 |
+
(light end 2.16:1 on white; validate_palette --ordinal). Thresholds are display scaffolding. */
|
| 10 |
+
var BINS = [40, 60, 80];
|
| 11 |
+
var STEPS = [400, 500, 600, 700];
|
| 12 |
+
var compact = false; // summary columns first + swipe hint: used whenever the full layout overflows
|
| 13 |
+
var FORM_SHORT = { 'single-step': 'Single', 'multi-step': 'Multi', 'multi-step+tools': 'Multi+Tools' };
|
| 14 |
+
|
| 15 |
+
function isStated(m) { return /^paper prose/.test(m.overallSource || ''); }
|
| 16 |
+
function colDefs() {
|
| 17 |
+
var c = [];
|
| 18 |
+
U.TEXT_GROUPS.forEach(function (g) { c.push({ key: g.key, label: g.label, short: FORM_SHORT[g.form], long: g.longLabel, group: g.key, mod: 'text', get: function (m) { return m.acc[g.key]; } }); });
|
| 19 |
+
c.push({ key: 'textAvg', label: 'Text Avg', short: 'Avg', long: 'Text average (Table 1, task-weighted)', avg: true, mod: 'text', get: function (m) { return m.textAvg; } });
|
| 20 |
+
if (state.track === 'full') {
|
| 21 |
+
U.MM_GROUPS.forEach(function (g) { c.push({ key: g.key, label: g.label, short: FORM_SHORT[g.form], long: g.longLabel, group: g.key, mod: 'mm', get: function (m) { return m.acc[g.key]; } }); });
|
| 22 |
+
c.push({ key: 'mmAvg', label: 'MM Avg', short: 'Avg', long: 'Multimodal average (Table 1, task-weighted)', avg: true, mod: 'mm', get: function (m) { return m.mmAvg; } });
|
| 23 |
+
c.push({ key: 'overall', label: 'Overall', short: 'Overall', long: 'Overall accuracy over all applicable tasks (Eq. 11)', avg: true, overall: true, mod: 'all', get: function (m) { return m.textOnly ? null : m.overall; } });
|
| 24 |
+
}
|
| 25 |
+
if (compact) {
|
| 26 |
+
/* the table overflows its card: summary columns first so they are visible without swiping */
|
| 27 |
+
var avgs = c.filter(function (x) { return x.avg; }).sort(function (a, b) { return (b.overall ? 1 : 0) - (a.overall ? 1 : 0); });
|
| 28 |
+
var groups = c.filter(function (x) { return !x.avg; });
|
| 29 |
+
if (groups.length) groups[0].sep = true;
|
| 30 |
+
return avgs.concat(groups);
|
| 31 |
+
}
|
| 32 |
+
c.forEach(function (x) { if (x.overall || (x.mod === 'mm' && x.group === U.MM_GROUPS[0].key)) x.sep = true; });
|
| 33 |
+
return c;
|
| 34 |
+
}
|
| 35 |
+
function depOk(m) { return state.deploy === 'all' || m.deployment === state.deploy; }
|
| 36 |
+
function step(v) { var i = 0; while (i < BINS.length && v >= BINS[i]) i++; return STEPS[i]; }
|
| 37 |
+
function overallNote(m) {
|
| 38 |
+
if (isStated(m)) return 'Stated in the paper (' + m.overallSource.replace(/^paper prose\s*\(?/, '').replace(/\)$/, '') + ')';
|
| 39 |
+
return 'Derived with the paper’s definition: task-count-weighted over ' + m.overallTasks + ' tasks (Eq. 11), from the Table 1 Text Avg (' + S.textTasks + ' tasks) and MM Avg (' + S.mmTasks + ' tasks)';
|
| 40 |
+
}
|
| 41 |
+
function barColor(c) { return c.overall ? 'var(--series-overall)' : c.mod === 'text' ? 'var(--series-text)' : 'var(--series-mm)'; }
|
| 42 |
+
|
| 43 |
+
/* Render in the full layout; if the table then overflows its scroller, re-render compact. */
|
| 44 |
+
function render() {
|
| 45 |
+
compact = false;
|
| 46 |
+
draw();
|
| 47 |
+
var sc = U.$('#lb-table').parentNode, t = U.$('#lb-table');
|
| 48 |
+
if (t.getBoundingClientRect().width > sc.clientWidth + 1) { compact = true; draw(); }
|
| 49 |
+
overflowUi();
|
| 50 |
+
}
|
| 51 |
+
var FADE = 40; // the right-edge fade of an overflowing table (style.css mask, 36 px) plus a little air
|
| 52 |
+
function overflowUi() {
|
| 53 |
+
var sc = U.$('#lb-table').parentNode, card = sc.closest('.lb');
|
| 54 |
+
var over = sc.scrollWidth > sc.clientWidth + 1;
|
| 55 |
+
card.classList.toggle('is-overflow', over);
|
| 56 |
+
sc.classList.toggle('at-end', !over || sc.scrollLeft + sc.clientWidth >= sc.scrollWidth - 2);
|
| 57 |
+
/* the visible width of the scroller: the full-width notice row wraps inside it instead of running
|
| 58 |
+
past the right edge */
|
| 59 |
+
sc.style.setProperty('--lb-vis', sc.clientWidth + 'px');
|
| 60 |
+
/* keyboard focus never lands under the sticky Rank · Model column or the right-edge fade (WCAG 2.4.11) */
|
| 61 |
+
var st = U.$('#lb-table thead th.c-model');
|
| 62 |
+
sc.style.scrollPaddingLeft = over && st ? st.offsetWidth + 'px' : '';
|
| 63 |
+
sc.style.scrollPaddingRight = over ? FADE + 'px' : '';
|
| 64 |
+
}
|
| 65 |
+
/* fallback for browsers that ignore scroll-padding when focus scrolls: bring the focused control
|
| 66 |
+
fully into the part of the scroller that the sticky column and the fade do not cover */
|
| 67 |
+
function revealFocused(e) {
|
| 68 |
+
var el = e.target, sc = U.$('#lb-table').parentNode;
|
| 69 |
+
if (!el || !el.classList || !el.classList.contains('sort-btn') || !sc.contains(el)) return;
|
| 70 |
+
var st = U.$('#lb-table thead th.c-model');
|
| 71 |
+
var s = sc.getBoundingClientRect(), r = el.getBoundingClientRect();
|
| 72 |
+
var left = s.left + (st ? st.getBoundingClientRect().width : 0), right = s.left + sc.clientWidth - (sc.scrollWidth > sc.clientWidth + 1 ? FADE : 0);
|
| 73 |
+
if (r.left < left) sc.scrollLeft -= left - r.left;
|
| 74 |
+
else if (r.right > right) sc.scrollLeft += Math.min(r.right - right, r.left - left);
|
| 75 |
+
}
|
| 76 |
+
function draw() {
|
| 77 |
+
var C = colDefs();
|
| 78 |
+
var main, extra = [];
|
| 79 |
+
if (state.track === 'full') {
|
| 80 |
+
main = D.models.filter(function (m) { return !m.textOnly && depOk(m); });
|
| 81 |
+
extra = D.models.filter(function (m) { return m.textOnly && depOk(m); });
|
| 82 |
+
} else {
|
| 83 |
+
main = D.models.filter(depOk);
|
| 84 |
+
}
|
| 85 |
+
var sortCol = C.filter(function (c) { return c.key === state.sort; })[0];
|
| 86 |
+
if (!sortCol) { state.sort = state.track === 'full' ? 'overall' : 'textAvg'; state.dir = 'desc'; sortCol = C.filter(function (c) { return c.key === state.sort; })[0]; }
|
| 87 |
+
var ranks = U.rank(main, sortCol.get);
|
| 88 |
+
function cmp(a, b) {
|
| 89 |
+
var va = sortCol.get(a), vb = sortCol.get(b);
|
| 90 |
+
if (va == null && vb == null) return 0; if (va == null) return 1; if (vb == null) return -1;
|
| 91 |
+
var d = vb - va;
|
| 92 |
+
if (d === 0) d = D.models.indexOf(a) - D.models.indexOf(b); // ties keep Table 1 order
|
| 93 |
+
return state.dir === 'desc' ? d : -d;
|
| 94 |
+
}
|
| 95 |
+
main.sort(cmp); extra.sort(cmp);
|
| 96 |
+
/* best value per column among every row shown (text-only rows included for text columns, as Table 1 marks places) */
|
| 97 |
+
var best = {};
|
| 98 |
+
C.forEach(function (c) { var mx = null; main.concat(extra).forEach(function (m) { var v = c.get(m); if (v != null && (mx == null || v > mx)) mx = v; }); best[c.key] = mx; });
|
| 99 |
+
|
| 100 |
+
var t = U.$('#lb-table');
|
| 101 |
+
t.textContent = '';
|
| 102 |
+
t.className = 'lb-table style-' + state.style + (state.track === 'text' ? ' lb-table--text' : '');
|
| 103 |
+
t.appendChild(h('caption', { class: 'sr-only', attrs: { id: 'lb-caption' } },
|
| 104 |
+
'Leaderboard, ' + (state.track === 'full' ? 'full track (text and multimodal)' : 'text track') + ', ' +
|
| 105 |
+
(state.deploy === 'all' ? 'all models' : state.deploy === 'api' ? 'API models' : 'local models') + ', sorted by ' + sortCol.long + ' ' + (state.dir === 'desc' ? 'descending' : 'ascending') + '. Audited accuracy in percent.'));
|
| 106 |
+
|
| 107 |
+
var thead = h('thead');
|
| 108 |
+
var gr = h('tr', { class: 'lb-groups' + (compact ? ' is-hidden-row' : '') });
|
| 109 |
+
gr.appendChild(h('td', { class: 'c-model sticky' }));
|
| 110 |
+
var nText = C.filter(function (c) { return c.mod === 'text'; }).length, nMM = C.filter(function (c) { return c.mod === 'mm'; }).length;
|
| 111 |
+
gr.appendChild(h('th', { attrs: { colspan: String(nText), scope: 'colgroup' }, class: 'grp grp--text' }, h('span', { class: 'gdot', style: { background: 'var(--series-text)' } }), 'Text'));
|
| 112 |
+
if (nMM) gr.appendChild(h('th', { attrs: { colspan: String(nMM), scope: 'colgroup' }, class: 'grp grp--mm' }, h('span', { class: 'gdot', style: { background: 'var(--series-mm)' } }), 'Multimodal'));
|
| 113 |
+
if (state.track === 'full') gr.appendChild(h('th', { attrs: { scope: 'col' }, class: 'grp grp--all', text: 'All' }));
|
| 114 |
+
thead.appendChild(gr);
|
| 115 |
+
|
| 116 |
+
var hr = h('tr');
|
| 117 |
+
hr.appendChild(h('th', { attrs: { scope: 'col' }, class: 'c-model sticky' }, h('span', { class: 'c-model__h', text: 'Rank · Model' })));
|
| 118 |
+
C.forEach(function (c) {
|
| 119 |
+
var th = h('th', { class: (c.avg ? 'is-avg' : '') + (c.overall ? ' is-overall' : '') + (c.sep ? ' is-sep' : ''), attrs: { scope: 'col', 'aria-sort': c.key === state.sort ? (state.dir === 'desc' ? 'descending' : 'ascending') : 'none' } });
|
| 120 |
+
/* accessible name starts with the visible label (WCAG 2.5.3); th[aria-sort] carries the sort state */
|
| 121 |
+
var b = h('button', { class: 'sort-btn', attrs: { type: 'button', 'data-col': c.key } });
|
| 122 |
+
var inner = h('span', { class: 'sort-btn__lab' });
|
| 123 |
+
if (c.group) inner.appendChild(h('span', { class: 'gtick', style: { background: U.wlVar(c.group) } }));
|
| 124 |
+
inner.appendChild(h('span', { class: 'lab-lg', text: c.label }));
|
| 125 |
+
inner.appendChild(h('span', { class: 'sr-only', text: 'sort by ' + c.long }));
|
| 126 |
+
b.appendChild(inner);
|
| 127 |
+
b.appendChild(h('span', { class: 'arr', attrs: { 'aria-hidden': 'true' }, text: c.key === state.sort ? (state.dir === 'desc' ? '▼' : '▲') : '▽' }));
|
| 128 |
+
b.addEventListener('click', function () {
|
| 129 |
+
if (state.sort === c.key) state.dir = state.dir === 'desc' ? 'asc' : 'desc';
|
| 130 |
+
else { state.sort = c.key; state.dir = 'desc'; }
|
| 131 |
+
render();
|
| 132 |
+
var again = U.$('#lb-table thead .sort-btn[data-col="' + c.key + '"]');
|
| 133 |
+
if (again) again.focus();
|
| 134 |
+
var line = U.$('#lb-bubble .narrator-bubble__line');
|
| 135 |
+
U.$('#live').textContent = 'Sorted by ' + c.long + ', ' + (state.dir === 'desc' ? 'highest first' : 'lowest first') + '. ' + (line ? line.textContent : '');
|
| 136 |
+
});
|
| 137 |
+
th.appendChild(b);
|
| 138 |
+
hr.appendChild(th);
|
| 139 |
+
});
|
| 140 |
+
thead.appendChild(hr);
|
| 141 |
+
t.appendChild(thead);
|
| 142 |
+
|
| 143 |
+
var tb = h('tbody');
|
| 144 |
+
main.forEach(function (m) { tb.appendChild(row(m, C, ranks.get(m), best, sortCol)); });
|
| 145 |
+
t.appendChild(tb);
|
| 146 |
+
if (extra.length) {
|
| 147 |
+
var tb2 = h('tbody', { class: 'lb-extra' });
|
| 148 |
+
var btn = h('button', { class: 'linkish', attrs: { type: 'button' } }, 'Compare them in the Text track');
|
| 149 |
+
btn.addEventListener('click', function () { U.lbSet({ track: 'text' }); var r = U.$('#lb-track [aria-checked="true"]'); if (r) r.focus(); });
|
| 150 |
+
tb2.appendChild(h('tr', { class: 'lb-divider' }, h('td', { attrs: { colspan: String(C.length + 1) } },
|
| 151 |
+
h('span', { class: 'lb-divider__in' }, U.icon('i-info'), h('span', null, 'Text-only models: evaluated on the ' + U.int(S.textTasks) + ' text tasks only, so they have no multimodal scores and no Overall here. Not ranked in this track. ', btn)))));
|
| 152 |
+
extra.forEach(function (m) { tb2.appendChild(row(m, C, null, best, sortCol)); });
|
| 153 |
+
t.appendChild(tb2);
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
notes(main, extra);
|
| 157 |
+
legend();
|
| 158 |
+
bubble(sortCol, main);
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
function row(m, C, r, best, sortCol) {
|
| 162 |
+
var tr = h('tr', { class: m.textOnly && state.track === 'full' ? 'is-extra' : '' });
|
| 163 |
+
var rc;
|
| 164 |
+
if (r == null) rc = h('span', { class: 'c-rank c-rank--none', attrs: { 'aria-hidden': 'true' } });
|
| 165 |
+
else if (r <= 3) rc = h('span', { class: 'medal medal--' + r, text: String(r), attrs: { title: 'Rank ' + r + ' by ' + sortCol.label + ' in this view' } });
|
| 166 |
+
else rc = h('span', { class: 'c-rank', text: String(r) });
|
| 167 |
+
var meta = h('span', { class: 'm-meta' },
|
| 168 |
+
h('span', { class: 'm-dep m-dep--' + m.deployment, text: m.deployment === 'api' ? 'API' : 'Local' }),
|
| 169 |
+
h('span', { class: 'm-vendor', text: m.vendor }));
|
| 170 |
+
if (m.textOnly) meta.appendChild(h('span', { class: 'm-tag', text: 'text-only' }));
|
| 171 |
+
tr.appendChild(h('th', { class: 'c-model sticky', attrs: { scope: 'row' } }, h('div', { class: 'c-model__in' }, rc, h('div', null, h('span', { class: 'm-name', text: m.name }), meta))));
|
| 172 |
+
C.forEach(function (c) {
|
| 173 |
+
var v = c.get(m);
|
| 174 |
+
var td = h('td', { class: 'cellv' + (c.avg ? ' is-avg' : '') + (c.overall ? ' is-overall' : '') + (c.key === state.sort ? ' is-sorted' : '') + (c.sep ? ' is-sep' : ''), data: { m: m.name, c: c.key } });
|
| 175 |
+
if (v == null) {
|
| 176 |
+
td.classList.add('is-na');
|
| 177 |
+
td.appendChild(h('span', { attrs: { 'aria-hidden': 'true' }, text: '—' }));
|
| 178 |
+
td.appendChild(h('span', { class: 'sr-only', text: m.textOnly ? 'not evaluated (text-only model)' : 'not available' }));
|
| 179 |
+
tr.appendChild(td); return;
|
| 180 |
+
}
|
| 181 |
+
var isBest = v === best[c.key];
|
| 182 |
+
var cell = h('span', { class: 'cell' });
|
| 183 |
+
if (isBest) { td.classList.add('is-best'); cell.appendChild(U.icon('i-crown', 'crown')); }
|
| 184 |
+
cell.appendChild(h('span', { class: 'v', text: U.pct(v) }));
|
| 185 |
+
if (c.overall && isStated(m)) cell.appendChild(h('span', { class: 'stated', attrs: { title: 'Value stated in the paper’s text' }, text: '◆' }));
|
| 186 |
+
if (state.style === 'heat') {
|
| 187 |
+
var s = step(v);
|
| 188 |
+
td.style.background = 'var(--seq-' + s + ')';
|
| 189 |
+
td.style.color = 'var(--seq-' + s + '-on)';
|
| 190 |
+
} else {
|
| 191 |
+
cell.appendChild(h('span', { class: 'cbar', attrs: { 'aria-hidden': 'true' } }, h('span', { style: { width: v + '%', background: barColor(c) } })));
|
| 192 |
+
}
|
| 193 |
+
td.appendChild(cell);
|
| 194 |
+
if (isBest) td.appendChild(h('span', { class: 'sr-only', text: ' (best in column)' }));
|
| 195 |
+
if (c.overall && isStated(m)) td.appendChild(h('span', { class: 'sr-only', text: ' (stated in the paper)' }));
|
| 196 |
+
tr.appendChild(td);
|
| 197 |
+
});
|
| 198 |
+
return tr;
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
function notes(main, extra) {
|
| 202 |
+
var textOnly = D.models.filter(function (m) { return m.textOnly; }).length;
|
| 203 |
+
var note = U.$('#lb-note');
|
| 204 |
+
note.textContent = '';
|
| 205 |
+
note.appendChild(U.icon('i-info'));
|
| 206 |
+
if (state.track === 'full') {
|
| 207 |
+
note.appendChild(h('span', { text: 'Full track: the ' + S.multimodalModels + ' multimodal-capable models, ranked over all ' + S.tasks + ' tasks. The ' + textOnly + ' text-only models were not evaluated on multimodal tasks; they are listed below the ranking and compete in the Text track (' + S.textTasks + ' text tasks).' }));
|
| 208 |
+
} else {
|
| 209 |
+
note.appendChild(h('span', { text: 'Text track: all ' + S.models + ' models on the ' + S.textTasks + ' text tasks, ranked by the paper’s Text Avg by default. Text-only models are tagged.' }));
|
| 210 |
+
}
|
| 211 |
+
var foot = U.$('#lb-foot');
|
| 212 |
+
foot.textContent = '';
|
| 213 |
+
var stated = D.models.filter(isStated);
|
| 214 |
+
foot.appendChild(h('p', null, h('strong', { text: 'Audited scores. ' }), 'Every accuracy is computed from audited task scores, ' + D.audit.rule.replace(/\.$/, '') + '. Group accuracies and the Text/MM averages are the paper’s Table 1 values (averages are task-count-weighted).'));
|
| 215 |
+
if (state.track === 'full') {
|
| 216 |
+
foot.appendChild(h('p', null, h('strong', { text: 'Overall. ' }),
|
| 217 |
+
'Table 1 has no Overall column. Overall is the task-count-weighted mean over each model’s applicable tasks (Eq. 11). Values the paper states in its text are shown as stated and marked ',
|
| 218 |
+
h('span', { class: 'stated', text: '◆' }), ' (' + stated.map(function (m) { return m.shortName + ' ' + U.pct(m.overall); }).join(', ') + '); the others are derived from Table 1 with the same definition.'));
|
| 219 |
+
}
|
| 220 |
+
foot.appendChild(h('p', null, h('strong', { text: 'Places. ' }), 'Table 1 marks first to third place within each deployment mode. Here the medals follow the current track, filter and sort column (competition ranking; ties share a place), and a crown marks the best value in each column among the rows shown.'));
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
function legend() {
|
| 224 |
+
var lg = U.$('#lb-legend');
|
| 225 |
+
lg.textContent = '';
|
| 226 |
+
if (state.style === 'heat') {
|
| 227 |
+
var ramp = h('span', { class: 'ramp', attrs: { role: 'img', 'aria-label': 'Accuracy color scale in ' + STEPS.length + ' bins: ' + STEPS.map(function (s, i) { return i === 0 ? 'below ' + BINS[0] : i === STEPS.length - 1 ? BINS[BINS.length - 1] + ' and above' : BINS[i - 1] + ' to ' + BINS[i]; }).join(', ') } });
|
| 228 |
+
STEPS.forEach(function (s, i) {
|
| 229 |
+
var lab = i === 0 ? '<' + BINS[0] : i === STEPS.length - 1 ? '≥' + BINS[BINS.length - 1] : BINS[i - 1] + '–' + BINS[i];
|
| 230 |
+
ramp.appendChild(h('span', { text: lab, style: { background: 'var(--seq-' + s + ')', color: 'var(--seq-' + s + '-on)' } }));
|
| 231 |
+
});
|
| 232 |
+
lg.appendChild(h('span', { class: 'legend__item' }, h('span', { class: 'legend__title', text: 'Accuracy (%)' }), ramp));
|
| 233 |
+
} else {
|
| 234 |
+
lg.appendChild(h('span', { class: 'legend__item' }, h('span', { class: 'legend__title', text: 'Bar length = accuracy (0–100):' })));
|
| 235 |
+
[['var(--series-text)', 'Text'], ['var(--series-mm)', 'Multimodal'], ['var(--series-overall)', 'Overall (all tasks)']].forEach(function (x) {
|
| 236 |
+
if (state.track === 'text' && x[1] !== 'Text') return;
|
| 237 |
+
lg.appendChild(h('span', { class: 'legend__item' }, h('span', { class: 'legend__bar', style: { background: x[0] } }), x[1]));
|
| 238 |
+
});
|
| 239 |
+
}
|
| 240 |
+
lg.appendChild(h('span', { class: 'legend__item' }, h('span', { class: 'best-chip' }, U.icon('i-crown', 'crown')), 'best in column'));
|
| 241 |
+
if (state.track === 'full') lg.appendChild(h('span', { class: 'legend__item' }, h('span', { class: 'stated', text: '◆' }), 'Overall stated in the paper'));
|
| 242 |
+
lg.appendChild(h('span', { class: 'legend__item' }, h('span', { class: 'legend__title', text: 'Deployment:' }), h('span', { class: 'm-dep m-dep--api', text: 'API' }), h('span', { class: 'm-dep m-dep--local', text: 'Local' })));
|
| 243 |
+
}
|
| 244 |
+
|
| 245 |
+
/* narrator: the mascot names the leader of the current sort column */
|
| 246 |
+
function bubble(sortCol, main) {
|
| 247 |
+
var host = U.$('#lb-bubble');
|
| 248 |
+
host.textContent = '';
|
| 249 |
+
var valid = main.filter(function (m) { return sortCol.get(m) != null; });
|
| 250 |
+
if (!valid.length) { host.textContent = 'No models match this filter.'; return; }
|
| 251 |
+
var top = valid.slice().sort(function (a, b) { return sortCol.get(b) - sortCol.get(a); });
|
| 252 |
+
var lead = top.filter(function (m) { return sortCol.get(m) === sortCol.get(top[0]); });
|
| 253 |
+
var v = sortCol.get(lead[0]);
|
| 254 |
+
host.appendChild(h('span', { class: 'narrator-bubble__lab', text: sortCol.group ? sortCol.long : sortCol.label }));
|
| 255 |
+
var line = h('span', { class: 'narrator-bubble__line' }, h('b', { text: lead.map(function (m) { return m.name; }).join(' & ') }), (lead.length > 1 ? ' lead with ' : ' leads with ') + U.pct(v));
|
| 256 |
+
if (sortCol.overall && !isStated(lead[0])) { line.appendChild(document.createTextNode(' ')); line.appendChild(h('span', { class: 'nowrap', text: '(derived, Eq. 11)' })); }
|
| 257 |
+
line.appendChild(document.createTextNode('.'));
|
| 258 |
+
host.appendChild(line);
|
| 259 |
+
host.appendChild(h('span', { class: 'narrator-bubble__hint', text: 'Sort by another column and watch the gold medal move.' }));
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
function tooltips() {
|
| 263 |
+
var t = U.$('#lb-table');
|
| 264 |
+
t.addEventListener('pointermove', function (e) {
|
| 265 |
+
var td = e.target.closest ? e.target.closest('td.cellv') : null;
|
| 266 |
+
if (!td || td.classList.contains('is-na')) { U.tip.hide(); return; }
|
| 267 |
+
var m = U.model(td.dataset.m), key = td.dataset.c;
|
| 268 |
+
var c = colDefs().filter(function (x) { return x.key === key; })[0];
|
| 269 |
+
if (!c) return;
|
| 270 |
+
var v = c.get(m);
|
| 271 |
+
var rowsSpec = [{ label: c.long, value: U.pct(v) + '%', color: c.group ? U.css('--wl-' + c.group) : null }];
|
| 272 |
+
var note = m.vendor + ' · ' + (m.deployment === 'api' ? 'API' : 'Local') + (m.textOnly ? ' · text-only' : '');
|
| 273 |
+
if (td.classList.contains('is-best')) note += ' · best in this column';
|
| 274 |
+
if (c.overall) note += '. ' + overallNote(m) + '.';
|
| 275 |
+
else note += '. Paper Table 1.';
|
| 276 |
+
U.tip.show({ title: m.name, rows: rowsSpec, note: note }, e.clientX, e.clientY, t);
|
| 277 |
+
});
|
| 278 |
+
t.addEventListener('pointerleave', function () { U.tip.hide(); });
|
| 279 |
+
}
|
| 280 |
+
|
| 281 |
+
U.initLeaderboard = function () {
|
| 282 |
+
U.$('#lb-lead').textContent = 'Audited accuracy (%) of ' + S.apiModels + ' commercial API models and ' + S.localModels + ' locally deployed open-weight models on each workload group, from the paper’s Table 1. Positive scores that the meta-judge confirmed as unsupported were set to zero before averaging. Sort any column: the leader changes with the workload.';
|
| 283 |
+
segs.track = U.seg(U.$('#lb-track'), [
|
| 284 |
+
{ value: 'full', label: 'Full (text + MM)', title: 'Multimodal-capable models on all tasks' },
|
| 285 |
+
{ value: 'text', label: 'Text track (all ' + S.models + ')', title: 'All models on the text tasks' }
|
| 286 |
+
], state.track, function (v) { state.track = v; state.sort = v === 'full' ? 'overall' : 'textAvg'; state.dir = 'desc'; render(); });
|
| 287 |
+
segs.deploy = U.seg(U.$('#lb-deploy'), [
|
| 288 |
+
{ value: 'all', label: 'All' },
|
| 289 |
+
{ value: 'api', label: 'API' },
|
| 290 |
+
{ value: 'local', label: 'Local' }
|
| 291 |
+
], state.deploy, function (v) { state.deploy = v; render(); });
|
| 292 |
+
U.seg(U.$('#lb-style'), [
|
| 293 |
+
{ value: 'bars', label: 'Bars' },
|
| 294 |
+
{ value: 'heat', label: 'Heat' }
|
| 295 |
+
], state.style, function (v) { state.style = v; render(); });
|
| 296 |
+
tooltips();
|
| 297 |
+
render();
|
| 298 |
+
var sc = U.$('#lb-table').parentNode;
|
| 299 |
+
sc.addEventListener('scroll', function () { overflowUi(); }, { passive: true });
|
| 300 |
+
sc.addEventListener('focusin', function (e) { requestAnimationFrame(function () { revealFocused(e); }); });
|
| 301 |
+
/* re-decide the layout when the card width changes (keeps focus on the active sort button) */
|
| 302 |
+
U.onResize(sc, function () {
|
| 303 |
+
var a = document.activeElement, col = a && a.classList && a.classList.contains('sort-btn') ? a.dataset.col : null;
|
| 304 |
+
render();
|
| 305 |
+
if (col) { var again = U.$('#lb-table thead .sort-btn[data-col="' + col + '"]'); if (again) again.focus(); }
|
| 306 |
+
});
|
| 307 |
+
if (document.fonts && document.fonts.ready) document.fonts.ready.then(render);
|
| 308 |
+
};
|
| 309 |
+
U.lbState = state;
|
| 310 |
+
U.lbSet = function (o) {
|
| 311 |
+
if (o.track && o.track !== state.track) { state.track = o.track; state.sort = o.track === 'full' ? 'overall' : 'textAvg'; state.dir = 'desc'; segs.track.select(o.track); }
|
| 312 |
+
if (o.deploy) { state.deploy = o.deploy; segs.deploy.select(o.deploy); }
|
| 313 |
+
render();
|
| 314 |
+
};
|
| 315 |
+
})();
|
assets/js/main.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Bootstrap: bindings, sections (each isolated in try/catch), navigation, reveal-on-scroll. */
|
| 2 |
+
(function () {
|
| 3 |
+
'use strict';
|
| 4 |
+
var U = window.U;
|
| 5 |
+
|
| 6 |
+
function nav() {
|
| 7 |
+
var toggle = U.$('.nav__toggle'), menu = U.$('#nav-menu');
|
| 8 |
+
function setOpen(open) {
|
| 9 |
+
toggle.setAttribute('aria-expanded', String(open));
|
| 10 |
+
menu.classList.toggle('is-open', open);
|
| 11 |
+
}
|
| 12 |
+
toggle.addEventListener('click', function () { setOpen(toggle.getAttribute('aria-expanded') !== 'true'); });
|
| 13 |
+
U.$$('a', menu).forEach(function (a) { a.addEventListener('click', function () { setOpen(false); }); });
|
| 14 |
+
document.addEventListener('keydown', function (e) { if (e.key === 'Escape' && menu.classList.contains('is-open')) { setOpen(false); toggle.focus(); } });
|
| 15 |
+
document.addEventListener('click', function (e) { if (menu.classList.contains('is-open') && !menu.contains(e.target) && !toggle.contains(e.target)) setOpen(false); });
|
| 16 |
+
/* keyboard: tabbing out of the open menu closes it, so it never covers the newly focused control */
|
| 17 |
+
menu.addEventListener('focusout', function (e) {
|
| 18 |
+
var to = e.relatedTarget;
|
| 19 |
+
if (menu.classList.contains('is-open') && to && !menu.contains(to) && to !== toggle) setOpen(false);
|
| 20 |
+
});
|
| 21 |
+
|
| 22 |
+
var links = U.$$('.nav__links a');
|
| 23 |
+
var ids = links.map(function (a) { return a.getAttribute('href').slice(1); });
|
| 24 |
+
var secs = U.$$('main > section');
|
| 25 |
+
var bar = U.$('.nav__progress span');
|
| 26 |
+
var ticking = false, lastY = window.scrollY, header = U.$('.nav');
|
| 27 |
+
header.addEventListener('focusin', function () { header.classList.remove('is-hidden'); });
|
| 28 |
+
function update() {
|
| 29 |
+
ticking = false;
|
| 30 |
+
var y = window.scrollY;
|
| 31 |
+
if (menu.classList.contains('is-open') || header.contains(document.activeElement) || y < 240) header.classList.remove('is-hidden');
|
| 32 |
+
else if (y > lastY + 6) header.classList.add('is-hidden');
|
| 33 |
+
else if (y < lastY - 6) header.classList.remove('is-hidden');
|
| 34 |
+
lastY = y;
|
| 35 |
+
var probe = window.innerHeight * 0.35;
|
| 36 |
+
var cur = null;
|
| 37 |
+
secs.forEach(function (s) { var r = s.getBoundingClientRect(); if (r.top <= probe && r.bottom > probe) cur = s.id; });
|
| 38 |
+
links.forEach(function (a, i) { if (ids[i] === cur) a.setAttribute('aria-current', 'true'); else a.removeAttribute('aria-current'); });
|
| 39 |
+
var max = document.documentElement.scrollHeight - window.innerHeight;
|
| 40 |
+
bar.style.transform = 'scaleX(' + (max > 0 ? Math.min(1, window.scrollY / max) : 0) + ')';
|
| 41 |
+
}
|
| 42 |
+
window.addEventListener('scroll', function () { if (!ticking) { ticking = true; requestAnimationFrame(update); } }, { passive: true });
|
| 43 |
+
window.addEventListener('resize', update);
|
| 44 |
+
update();
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
function reveal() {
|
| 48 |
+
var els = U.$$('.reveal');
|
| 49 |
+
if (!('IntersectionObserver' in window)) return;
|
| 50 |
+
document.documentElement.classList.add('js-reveal');
|
| 51 |
+
var io = new IntersectionObserver(function (entries) {
|
| 52 |
+
entries.forEach(function (en) { if (en.isIntersecting) { en.target.classList.add('is-in'); io.unobserve(en.target); } });
|
| 53 |
+
}, { rootMargin: '0px 0px -8% 0px', threshold: 0.05 });
|
| 54 |
+
els.forEach(function (e) { io.observe(e); });
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
/* Ambient animations (fish, bubbles, kelp, bobbing art) only run while their section is on screen. */
|
| 58 |
+
function pauseOffscreen() {
|
| 59 |
+
if (!('IntersectionObserver' in window)) return;
|
| 60 |
+
var io = new IntersectionObserver(function (entries) {
|
| 61 |
+
entries.forEach(function (en) { en.target.classList.toggle('is-offscreen', !en.isIntersecting); });
|
| 62 |
+
}, { rootMargin: '80px 0px' });
|
| 63 |
+
U.$$('main > section, footer').forEach(function (el) { io.observe(el); });
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
/* In-page pause for the ambient loops (WCAG 2.2.2), remembered across visits. */
|
| 67 |
+
function motionToggle() {
|
| 68 |
+
var btn = U.$('#motion-toggle'), root = document.documentElement, KEY = 'omnistepbench-motion-paused';
|
| 69 |
+
if (!btn) return;
|
| 70 |
+
function set(paused, store) {
|
| 71 |
+
root.classList.toggle('motion-paused', paused);
|
| 72 |
+
btn.setAttribute('aria-pressed', String(paused));
|
| 73 |
+
if (store) { try { localStorage.setItem(KEY, paused ? '1' : '0'); } catch (e) { /* storage unavailable (file://, private mode) */ } }
|
| 74 |
+
}
|
| 75 |
+
var saved = null;
|
| 76 |
+
try { saved = localStorage.getItem(KEY); } catch (e) { saved = null; }
|
| 77 |
+
set(saved === '1', false);
|
| 78 |
+
btn.addEventListener('click', function () { set(btn.getAttribute('aria-pressed') !== 'true', true); });
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
function start() {
|
| 82 |
+
U.bindAll(document);
|
| 83 |
+
var steps = [
|
| 84 |
+
['content', U.initContent], ['workloads', U.initWorkloads], ['leaderboard', U.initLeaderboard],
|
| 85 |
+
['cost', U.initCost], ['reliability', U.initReliability], ['quickstart', U.initQuickstart]
|
| 86 |
+
];
|
| 87 |
+
steps.forEach(function (s) {
|
| 88 |
+
try { s[1](); } catch (e) { console.error('[' + U.D.meta.shortName + '] ' + s[0] + ' failed:', e); }
|
| 89 |
+
});
|
| 90 |
+
[['toggles', U.initViewToggles], ['lightbox', U.initLightbox], ['nav', nav], ['reveal', reveal], ['motion', pauseOffscreen], ['motion-toggle', motionToggle]].forEach(function (s) {
|
| 91 |
+
try { s[1](); } catch (e) { console.error('[' + U.D.meta.shortName + '] ' + s[0] + ' failed:', e); }
|
| 92 |
+
});
|
| 93 |
+
}
|
| 94 |
+
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start); else start();
|
| 95 |
+
})();
|
assets/js/quickstart.js
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Quick start (README, verbatim) and the annotated task-file anatomy. */
|
| 2 |
+
(function () {
|
| 3 |
+
'use strict';
|
| 4 |
+
var U = window.U, D = U.D, h = U.h, Q = D.quickstart, A = D.taskAnatomy;
|
| 5 |
+
|
| 6 |
+
function codeBlock(code, lang, label) {
|
| 7 |
+
var pre = h('pre', { attrs: { tabindex: '0', 'aria-label': (lang || 'code') + ' snippet' } });
|
| 8 |
+
code.split('\n').forEach(function (line, i, arr) {
|
| 9 |
+
var span;
|
| 10 |
+
if (/^\s*#/.test(line) && lang !== 'python') span = h('span', { class: 'c-com', text: line });
|
| 11 |
+
else {
|
| 12 |
+
span = h('span');
|
| 13 |
+
var m = line.match(/^(\s*)(\S+)(.*)$/);
|
| 14 |
+
if (m && lang === 'bash') { span.appendChild(document.createTextNode(m[1])); span.appendChild(h('span', { class: 'c-cmd', text: m[2] })); span.appendChild(document.createTextNode(m[3])); }
|
| 15 |
+
else span.textContent = line;
|
| 16 |
+
}
|
| 17 |
+
pre.appendChild(span);
|
| 18 |
+
if (i < arr.length - 1) pre.appendChild(document.createTextNode('\n'));
|
| 19 |
+
});
|
| 20 |
+
if (label) pre.setAttribute('aria-label', label);
|
| 21 |
+
return h('div', { class: 'codeblock' }, U.copyButton(function () { return code; }, 'Copy: ' + (label || 'code')), pre);
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
function steps() {
|
| 25 |
+
var ol = U.$('#qs-steps');
|
| 26 |
+
/* 1. OpenClaw + skills (README) */
|
| 27 |
+
ol.appendChild(h('li', { class: 'step' }, h('h3', { text: Q.step1.title }), codeBlock(Q.step1.code, Q.step1.lang, 'install commands for OpenClaw and Clawhub skills')));
|
| 28 |
+
/* 2. clone */
|
| 29 |
+
ol.appendChild(h('li', { class: 'step' }, h('h3', { text: Q.clone.title }), codeBlock(Q.clone.code, Q.clone.lang, 'clone commands')));
|
| 30 |
+
/* 3. judge */
|
| 31 |
+
ol.appendChild(h('li', { class: 'step' }, h('h3', { text: Q.judge.title }), h('p', null, U.mdCode(Q.judge.text)), codeBlock(Q.judge.code, Q.judge.lang, 'judge model setting'),
|
| 32 |
+
h('p', { class: 'note', style: { 'margin-top': '10px', 'margin-bottom': '0' }, text: 'In the paper, the primary judge is ' + D.audit.primaryJudge + ' and the meta-judge is ' + D.audit.metaJudge + '.' })));
|
| 33 |
+
/* 4. run */
|
| 34 |
+
var runBox = h('div');
|
| 35 |
+
var seg = h('div', { class: 'seg run-tabs', attrs: { role: 'radiogroup', 'aria-label': 'Run mode' } });
|
| 36 |
+
function draw(i) {
|
| 37 |
+
runBox.textContent = '';
|
| 38 |
+
var r = Q.run[i];
|
| 39 |
+
runBox.appendChild(h('p', { class: 'run-title', text: r.title }));
|
| 40 |
+
runBox.appendChild(codeBlock(r.code, 'bash', r.mode + ' run command'));
|
| 41 |
+
runBox.appendChild(h('p', { class: 'note', style: { 'margin-top': '10px', 'margin-bottom': '0' } }, U.mdCode(r.note)));
|
| 42 |
+
}
|
| 43 |
+
U.seg(seg, Q.run.map(function (r, i) { return { value: i, label: r.mode.charAt(0).toUpperCase() + r.mode.slice(1), title: r.title }; }), 0, draw);
|
| 44 |
+
draw(0);
|
| 45 |
+
ol.appendChild(h('li', { class: 'step' }, h('h3', { text: 'Run the benchmark' }), seg, runBox));
|
| 46 |
+
|
| 47 |
+
/* what every model gets in the paper (§4.1, §A.2) */
|
| 48 |
+
U.$('#qs-tools-lead').textContent = 'In the paper, all models share the same tools with identical visibility and permissions (§4.1, §A.2).';
|
| 49 |
+
var tools = U.$('#qs-tools');
|
| 50 |
+
var base = h('ul', { class: 'tool-base' },
|
| 51 |
+
h('li', null, U.icon('i-code'), h('span', null, h('b', { text: 'Default OpenClaw tool suite' }), ' — file I/O, shell execution, agent-loop control')),
|
| 52 |
+
h('li', null, U.icon('i-search'), h('span', null, h('code', { text: 'web_search' }), ' (Brave Search)')),
|
| 53 |
+
h('li', null, U.icon('i-globe'), h('span', null, h('code', { text: 'web_fetch' }), ' (URL-to-markdown)')));
|
| 54 |
+
tools.appendChild(base);
|
| 55 |
+
var groups = [];
|
| 56 |
+
Q.paperSkills.forEach(function (sk) { if (groups.indexOf(sk.group) < 0) groups.push(sk.group); });
|
| 57 |
+
tools.appendChild(h('p', { class: 'tool-h', text: Q.paperSkills.length + ' Clawhub skills integrated in the paper’s runs' }));
|
| 58 |
+
groups.forEach(function (gname) {
|
| 59 |
+
var dl = h('div', { class: 'tool-group' }, h('p', { class: 'tool-group__h', text: gname }));
|
| 60 |
+
var ul2 = h('ul', { class: 'tool-skills' });
|
| 61 |
+
Q.paperSkills.filter(function (sk) { return sk.group === gname; }).forEach(function (sk) {
|
| 62 |
+
var li = h('li', { class: 'tool-skill', attrs: { tabindex: '0' } }, h('code', { text: sk.name }));
|
| 63 |
+
U.hoverTip(li, function () { return { title: sk.name, rows: [], note: sk.description }; });
|
| 64 |
+
li.setAttribute('aria-label', sk.name + ': ' + sk.description);
|
| 65 |
+
ul2.appendChild(li);
|
| 66 |
+
});
|
| 67 |
+
dl.appendChild(ul2);
|
| 68 |
+
tools.appendChild(dl);
|
| 69 |
+
});
|
| 70 |
+
|
| 71 |
+
/* requirements */
|
| 72 |
+
var req = U.$('#qs-reqs');
|
| 73 |
+
Q.requirements.forEach(function (r) {
|
| 74 |
+
var li = h('li');
|
| 75 |
+
var m = r.match(/^(.*)\((https?:\/\/[^)]+)\)(.*)$/);
|
| 76 |
+
if (m) { li.appendChild(U.mdCode(m[1])); li.appendChild(h('a', { text: m[2].replace(/^https?:\/\//, ''), attrs: { href: m[2], rel: 'noopener' } })); li.appendChild(U.mdCode(m[3])); }
|
| 77 |
+
else li.appendChild(U.mdCode(r));
|
| 78 |
+
req.appendChild(li);
|
| 79 |
+
});
|
| 80 |
+
/* flags */
|
| 81 |
+
var dl = U.$('#qs-flags');
|
| 82 |
+
Q.flags.forEach(function (f) {
|
| 83 |
+
var dd = h('dd', null, U.mdCode(f.description));
|
| 84 |
+
U.$$('code', dd).forEach(function (c) {
|
| 85 |
+
var parts = c.textContent.split('/');
|
| 86 |
+
if (parts.length < 2) { c.classList.add('nowrap'); return; }
|
| 87 |
+
c.textContent = '';
|
| 88 |
+
parts.forEach(function (p, i) {
|
| 89 |
+
c.appendChild(h('span', { class: 'seg-n', text: p + (i < parts.length - 1 ? '/' : '') }));
|
| 90 |
+
if (i < parts.length - 1) c.appendChild(document.createElement('wbr'));
|
| 91 |
+
});
|
| 92 |
+
});
|
| 93 |
+
dl.appendChild(h('div', null, h('dt', null, U.mdCode(f.flagMarkdown)), dd));
|
| 94 |
+
});
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
/* ---------------- anatomy ---------------- */
|
| 98 |
+
function symNode(sym) {
|
| 99 |
+
var f = document.createDocumentFragment();
|
| 100 |
+
if (sym === 'W0') { f.appendChild(h('span', { class: 'math', text: 'W' })); f.appendChild(h('sup', { text: '0' })); }
|
| 101 |
+
else if (sym === 't_max') { f.appendChild(h('span', { class: 'math', text: 't' })); f.appendChild(h('sup', { text: 'max' })); }
|
| 102 |
+
else f.appendChild(h('span', { class: 'math', text: sym }));
|
| 103 |
+
return f;
|
| 104 |
+
}
|
| 105 |
+
var lineEls = [], tupleBtns = {}, pinned = 'p';
|
| 106 |
+
|
| 107 |
+
function anatomy() {
|
| 108 |
+
U.$('#anat-sub').textContent = 'A task file from the repository (' + A.file + '), mapped to the paper’s task tuple. Select a component to highlight where it lives.';
|
| 109 |
+
var cap = U.$('#anat-cap');
|
| 110 |
+
if (cap) cap.textContent = A.note;
|
| 111 |
+
U.$('#anat-file').textContent = A.file;
|
| 112 |
+
/* equation */
|
| 113 |
+
var eq = U.$('#anat-eq');
|
| 114 |
+
eq.appendChild(h('span', { class: 'math', text: 'τ' }));
|
| 115 |
+
eq.appendChild(document.createTextNode(' = ('));
|
| 116 |
+
A.tuple.forEach(function (t, i) {
|
| 117 |
+
eq.appendChild(symNode(t.symbol));
|
| 118 |
+
if (i < A.tuple.length - 1) eq.appendChild(document.createTextNode(', '));
|
| 119 |
+
});
|
| 120 |
+
eq.appendChild(document.createTextNode(')'));
|
| 121 |
+
|
| 122 |
+
/* build lines */
|
| 123 |
+
var L = [];
|
| 124 |
+
function add(text, cls, syms) { L.push({ text: text, cls: cls || '', syms: syms || [] }); }
|
| 125 |
+
add('---', 'fm');
|
| 126 |
+
A.frontmatter.split('\n').forEach(function (ln) {
|
| 127 |
+
var syms = [];
|
| 128 |
+
if (/^(environment:|\s+type:|\s+requirements:|workspace_files:)/.test(ln)) syms.push('W0');
|
| 129 |
+
if (/^(grading_type:|grading_weights:|\s+automated:|\s+llm_judge:)/.test(ln)) syms.push('G');
|
| 130 |
+
if (/^timeout_seconds:/.test(ln)) syms.push('t_max');
|
| 131 |
+
add(ln, 'fm', syms);
|
| 132 |
+
});
|
| 133 |
+
add('---', 'fm');
|
| 134 |
+
add('');
|
| 135 |
+
add('## Prompt', 'h2', ['p']);
|
| 136 |
+
A.prompt.split('\n').forEach(function (ln) {
|
| 137 |
+
var syms = ['p'];
|
| 138 |
+
if (/answer\.txt/.test(ln)) syms.push('C');
|
| 139 |
+
if (/tools or skills/.test(ln)) syms.push('T');
|
| 140 |
+
if (/complete the task in/.test(ln)) syms.push('t_max');
|
| 141 |
+
add(ln, '', syms);
|
| 142 |
+
});
|
| 143 |
+
add('');
|
| 144 |
+
add('## Expected Behavior', 'h2');
|
| 145 |
+
A.expectedBehavior.split('\n').forEach(function (ln) { add(ln); });
|
| 146 |
+
add('');
|
| 147 |
+
add('## Grading Criteria', 'h2', ['G']);
|
| 148 |
+
A.gradingCriteria.split('\n').forEach(function (ln) { add(ln, /^\[withheld/.test(ln) ? 'withheld' : '', /answer_written/.test(ln) ? ['G', 'C'] : ['G']); });
|
| 149 |
+
add('');
|
| 150 |
+
add('## Automated Checks', 'h2', ['G', 'C']);
|
| 151 |
+
add('```python', '', ['G']);
|
| 152 |
+
A.automatedChecks.split('\n').forEach(function (ln) { add(ln, '', /answer_file|answer_written|answer\.txt/.test(ln) ? ['G', 'C'] : ['G']); });
|
| 153 |
+
add('```', '', ['G']);
|
| 154 |
+
add('');
|
| 155 |
+
add('## LLM Judge Rubric', 'h2', ['G']);
|
| 156 |
+
A.rubric.split('\n').forEach(function (ln) { add(ln, /^\[withheld/.test(ln) ? 'withheld' : /\[REDACTED\]/.test(ln) ? 'redact' : '', ['G']); });
|
| 157 |
+
|
| 158 |
+
var pre = U.$('#anat-code');
|
| 159 |
+
L.forEach(function (l) {
|
| 160 |
+
var el = h('span', { class: 'ln ' + l.cls, text: l.text === '' ? '' : l.text });
|
| 161 |
+
el._syms = l.syms;
|
| 162 |
+
lineEls.push(el);
|
| 163 |
+
pre.appendChild(el);
|
| 164 |
+
});
|
| 165 |
+
|
| 166 |
+
/* tuple list */
|
| 167 |
+
var list = U.$('#anat-tuple');
|
| 168 |
+
A.tuple.forEach(function (t) {
|
| 169 |
+
var b = h('button', { class: 'sym-' + t.symbol, attrs: { type: 'button', 'aria-pressed': String(t.symbol === pinned), 'aria-controls': 'anat-code', 'aria-label': t.name + ' (' + t.symbol.replace('_', ' ') + '): highlight its lines in the task file. ' + t.value } },
|
| 170 |
+
h('span', { class: 'tuple__sym' }, h('span', null, symNode(t.symbol))),
|
| 171 |
+
h('span', { class: 'tuple__name', text: t.name }),
|
| 172 |
+
h('span', { class: 'tuple__where', text: t.where }),
|
| 173 |
+
h('span', { class: 'tuple__val', text: t.value }));
|
| 174 |
+
b.addEventListener('click', function () { pinned = t.symbol; sync(); highlight(t.symbol, true); });
|
| 175 |
+
b.addEventListener('pointerenter', function () { highlight(t.symbol, false); });
|
| 176 |
+
b.addEventListener('pointerleave', function () { highlight(pinned, false); });
|
| 177 |
+
b.addEventListener('focus', function () { highlight(t.symbol, true); });
|
| 178 |
+
tupleBtns[t.symbol] = b;
|
| 179 |
+
list.appendChild(h('li', null, b));
|
| 180 |
+
});
|
| 181 |
+
list.parentNode.insertBefore(h('p', { class: 'tuple-val', attrs: { id: 'anat-val', 'aria-live': 'polite' } }), list.nextSibling);
|
| 182 |
+
sync();
|
| 183 |
+
highlight(pinned, false);
|
| 184 |
+
}
|
| 185 |
+
function sync() {
|
| 186 |
+
Object.keys(tupleBtns).forEach(function (k) { tupleBtns[k].setAttribute('aria-pressed', String(k === pinned)); });
|
| 187 |
+
var t = A.tuple.filter(function (x) { return x.symbol === pinned; })[0], cap = U.$('#anat-val');
|
| 188 |
+
if (t && cap) { cap.textContent = ''; cap.appendChild(h('b', { text: t.name + ' · ' })); cap.appendChild(h('span', { class: 'tuple-val__where', text: t.where + ' — ' })); cap.appendChild(document.createTextNode(t.value)); }
|
| 189 |
+
}
|
| 190 |
+
function highlight(sym, scroll) {
|
| 191 |
+
var pre = U.$('#anat-code'), first = null;
|
| 192 |
+
pre.className = 'codefile__body sym-' + sym;
|
| 193 |
+
lineEls.forEach(function (el) {
|
| 194 |
+
var on = el._syms.indexOf(sym) >= 0;
|
| 195 |
+
el.classList.toggle('is-hl', on);
|
| 196 |
+
if (on && !first) first = el;
|
| 197 |
+
});
|
| 198 |
+
if (scroll && first) pre.scrollTo({ top: Math.max(0, first.offsetTop - 24), behavior: U.reduceMotion ? 'auto' : 'smooth' });
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
U.initQuickstart = function () {
|
| 202 |
+
steps(); anatomy();
|
| 203 |
+
var fl = U.$('#qs-flags-box');
|
| 204 |
+
if (fl && window.matchMedia && window.matchMedia('(max-width: 720px)').matches) fl.removeAttribute('open');
|
| 205 |
+
};
|
| 206 |
+
})();
|
assets/js/reliability.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Evidence-based audit: funnel, judges, MAE, hallucination patterns (Table 3),
|
| 2 |
+
paper figures 5/6, and the failure taxonomy (Tables 4/5). */
|
| 3 |
+
(function () {
|
| 4 |
+
'use strict';
|
| 5 |
+
var U = window.U, D = U.D, h = U.h, A = D.audit, S = D.stats;
|
| 6 |
+
var DEP = [
|
| 7 |
+
{ key: 'api', label: 'API', color: 'var(--series-api)', cssVar: '--series-api' },
|
| 8 |
+
{ key: 'local', label: 'Local', color: 'var(--series-local)', cssVar: '--series-local' }
|
| 9 |
+
];
|
| 10 |
+
var ART = { 'deadlock-loop': 'cr-crab', 'rubric-leakage': 'cr-fish', 'pseudo-tool-call-credulity': 'cr-hermit', 'output-instability': 'cr-jelly', 'timeout-with-credit': 'cr-snail' };
|
| 11 |
+
|
| 12 |
+
function depLegend(host) {
|
| 13 |
+
host.textContent = '';
|
| 14 |
+
DEP.forEach(function (d) { host.appendChild(h('span', { class: 'legend__item' }, h('span', { class: 'legend__sw', style: { background: d.color } }), d.label)); });
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
/* keep a parenthetical such as "(score set to 0)" on one line */
|
| 18 |
+
function nowrapParens(text) {
|
| 19 |
+
var frag = document.createDocumentFragment();
|
| 20 |
+
String(text).split(/(\([^)]*\))/).forEach(function (part) {
|
| 21 |
+
if (!part) return;
|
| 22 |
+
frag.appendChild(part.charAt(0) === '(' ? h('span', { class: 'nowrap', text: part }) : document.createTextNode(part));
|
| 23 |
+
});
|
| 24 |
+
return frag;
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
function lead() {
|
| 28 |
+
var w = D.meta.why.filter(function (x) { return x.key === 'trustworthy'; })[0];
|
| 29 |
+
U.$('#rel-lead').textContent = w.problem + ' ' + D.meta.shortName + ' applies deterministic post-hoc rules to every score that involves the primary judge; flagged cases go to a meta-judge from a different model family, which decides whether the execution evidence supports the awarded positive score.';
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
/* Audit funnel as step cards: every number is printed, no bars (the stages differ by
|
| 33 |
+
orders of magnitude, so bars on one scale would hide the last two steps, and bars on
|
| 34 |
+
per-stage scales would mislead). */
|
| 35 |
+
function funnel() {
|
| 36 |
+
var ol = U.$('#funnel');
|
| 37 |
+
var sub = {
|
| 38 |
+
runs: 'every applicable model–task pair, in one shared OpenClaw runtime',
|
| 39 |
+
judgeCalls: 'scores that involve the primary judge (judge or hybrid tasks)',
|
| 40 |
+
flagged: 'suspicious positive scores routed to the meta-judge',
|
| 41 |
+
confirmed: 'positive credit that the trajectory and artifacts do not support'
|
| 42 |
+
};
|
| 43 |
+
A.funnel.forEach(function (st, i) {
|
| 44 |
+
var last = i === A.funnel.length - 1;
|
| 45 |
+
var li = h('li', { class: 'astep' + (last ? ' astep--final' : '') },
|
| 46 |
+
h('span', { class: 'astep__n', attrs: { 'aria-hidden': 'true' }, text: String(i + 1) }),
|
| 47 |
+
h('div', { class: 'astep__body' },
|
| 48 |
+
h('span', { class: 'astep__v', text: U.int(st.value) }),
|
| 49 |
+
h('span', { class: 'astep__l' }, nowrapParens(st.label)),
|
| 50 |
+
sub[st.key] ? h('span', { class: 'astep__s', text: sub[st.key] }) : null));
|
| 51 |
+
if (last) li.appendChild(U.burst('BUSTED!', 'red'));
|
| 52 |
+
ol.appendChild(li);
|
| 53 |
+
});
|
| 54 |
+
var rule = U.$('#audit-rule');
|
| 55 |
+
rule.appendChild(h('p', { class: 'funnel__rule-h', text: 'Audited score (Eq. 10)' }));
|
| 56 |
+
rule.appendChild(h('code', { text: A.rule }));
|
| 57 |
+
var feats = h('div', { class: 'feats' }, h('span', { class: 'note', text: 'Rule features (Appendix C):' }));
|
| 58 |
+
A.triggerFeatures.forEach(function (f) { feats.appendChild(h('code', { text: f })); });
|
| 59 |
+
rule.appendChild(feats);
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
function judges() {
|
| 63 |
+
var c = U.$('#judge-chain');
|
| 64 |
+
function node(icon, bg, title, sub) {
|
| 65 |
+
return h('div', { class: 'jnode' }, h('span', { class: 'jnode__icon', style: { background: bg } }, U.icon(icon)), h('div', null, h('b', { text: title }), h('span', { text: sub })));
|
| 66 |
+
}
|
| 67 |
+
c.appendChild(node('i-bubble', 'var(--sec-orange-fill)', 'Primary judge: ' + A.primaryJudge, 'Scores judge and hybrid tasks against a task-level rubric.'));
|
| 68 |
+
c.appendChild(h('span', { class: 'jarrow' }, U.icon('i-down'), 'rule-flagged positive scores'));
|
| 69 |
+
c.appendChild(node('i-eye', 'var(--sec-purple-fill)', 'Meta-judge: ' + A.metaJudge, 'A different model family. Sees the prompt, trajectory, artifacts, rubric and the primary judge’s rationale.'));
|
| 70 |
+
c.appendChild(h('span', { class: 'jarrow' }, U.icon('i-down'), 'verdict'));
|
| 71 |
+
c.appendChild(node('i-check', 'var(--sec-green-fill)', 'Unsupported → score set to zero', 'Otherwise the original score is kept.'));
|
| 72 |
+
|
| 73 |
+
var mae = U.$('#mae');
|
| 74 |
+
mae.appendChild(h('h4', { class: 'sr-only', text: 'Agreement with human experts' }));
|
| 75 |
+
mae.appendChild(h('div', { class: 'mae__tiles' },
|
| 76 |
+
h('div', { class: 'mae__tile' }, h('div', { class: 'mae__v', text: A.mae.primaryJudge.toFixed(3) }), h('div', { class: 'mae__l', text: 'MAE, primary judge' })),
|
| 77 |
+
h('div', { class: 'mae__mid' }, h('span', { class: 'scribble scribble--sm', text: 'about half' }), U.icon('i-arrow', 'mae__arrow')),
|
| 78 |
+
h('div', { class: 'mae__tile mae__tile--after' }, h('div', { class: 'mae__v', text: A.mae.afterMetaJudge.toFixed(3) }), h('div', { class: 'mae__l', text: 'MAE, after meta-judge' }))));
|
| 79 |
+
/* the sample size goes in brackets only when the definition does not already state it */
|
| 80 |
+
var def = A.mae.definition.replace(/\.$/, ''), nTxt = String(A.mae.n);
|
| 81 |
+
mae.appendChild(h('p', { class: 'mae__cap', text: def + (new RegExp('\\b' + nTxt + '\\b').test(def) ? '.' : ' (n = ' + nTxt + ').') + ' Lower is better; the paper notes the corrected error is approximately half that of the primary judge (Appendix C).' }));
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
function patterns() {
|
| 85 |
+
U.$('#patterns-sub').textContent = 'Unsupported positive scores confirmed by the meta-judge, split by deployment mode (Table 3): ' + A.totals.total + ' in total, ' + A.totals.local + ' from local and ' + A.totals.api + ' from API models.';
|
| 86 |
+
depLegend(U.$('#patterns-legend'));
|
| 87 |
+
var max = 0;
|
| 88 |
+
A.patterns.forEach(function (p) { max = Math.max(max, p.api, p.local); });
|
| 89 |
+
var grid = U.$('#pattern-grid');
|
| 90 |
+
var patternRows = [];
|
| 91 |
+
A.patterns.forEach(function (p) {
|
| 92 |
+
var bars = h('div', { class: 'pbars' });
|
| 93 |
+
DEP.forEach(function (d) {
|
| 94 |
+
var v = p[d.key];
|
| 95 |
+
var track = h('span', { class: 'pbar__track' },
|
| 96 |
+
h('span', { class: 'pbar__fill', style: { width: 'calc((100% - 30px) * ' + (v / max) + ')', background: d.color, 'min-width': v ? '3px' : '0' } }),
|
| 97 |
+
h('span', { class: 'pbar__v', text: String(v), style: { left: 'calc((100% - 30px) * ' + (v / max) + ' + ' + (v ? 6 : 0) + 'px)' } }));
|
| 98 |
+
var row = h('div', { class: 'pbar', attrs: { role: 'img', 'aria-label': p.name + ', ' + d.label + ': ' + v } }, h('span', { text: d.label, attrs: { 'aria-hidden': 'true' } }), track);
|
| 99 |
+
U.hoverTip(row, function () {
|
| 100 |
+
return { title: p.name, rows: DEP.map(function (x) { return { label: x.label, value: String(p[x.key]), color: U.css(x.cssVar) }; }), note: 'Table 3, confirmed unsupported positive scores' };
|
| 101 |
+
});
|
| 102 |
+
patternRows.push(row);
|
| 103 |
+
bars.appendChild(row);
|
| 104 |
+
});
|
| 105 |
+
grid.appendChild(h('li', { class: 'pattern reveal' },
|
| 106 |
+
U.icon(ART[p.key] || 'cr-crab', 'pattern__art'),
|
| 107 |
+
h('div', { class: 'pattern__txt' }, h('h4', { text: p.name }), h('p', { text: p.definition })),
|
| 108 |
+
bars));
|
| 109 |
+
});
|
| 110 |
+
/* one Tab stop for the chart; arrow keys move between bars, each with its tooltip */
|
| 111 |
+
U.roving(patternRows);
|
| 112 |
+
var rows = A.patterns.concat([{ name: 'Total', definition: '', local: A.totals.local, api: A.totals.api, total: A.totals.total }]);
|
| 113 |
+
U.tableView(U.$('#patterns-table'), U.table([
|
| 114 |
+
{ label: 'Pattern', get: function (p) { return p.name; } },
|
| 115 |
+
{ label: 'Definition', get: function (p) { return p.definition; } },
|
| 116 |
+
{ label: 'API', num: true, get: function (p) { return String(p.api); } },
|
| 117 |
+
{ label: 'Local', num: true, get: function (p) { return String(p.local); } },
|
| 118 |
+
{ label: 'Total', num: true, get: function (p) { return String(p.total); } }
|
| 119 |
+
], rows, 'Hallucination patterns (Table 3)'));
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
function figs() {
|
| 123 |
+
var box = U.$('#audit-figs');
|
| 124 |
+
A.figures.forEach(function (k) {
|
| 125 |
+
var f = U.fig(k);
|
| 126 |
+
if (!f) return;
|
| 127 |
+
var parts = f.caption.split(/\.\s+(?=Task:)/);
|
| 128 |
+
box.appendChild(h('figure', { class: 'afig card card--blob' },
|
| 129 |
+
U.zoomable(U.IMG + f.file, f.alt, f.label + '. ' + f.caption, f.label),
|
| 130 |
+
h('figcaption', null,
|
| 131 |
+
h('p', { class: 'afig__label', text: f.label + ' · ' + f.section }),
|
| 132 |
+
h('h4', { text: parts[0] }),
|
| 133 |
+
h('p', { text: parts[1] ? parts[1] : '' }))));
|
| 134 |
+
});
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
/* ---------- failure taxonomy (Tables 4/5) ---------- */
|
| 138 |
+
function taxonomy() {
|
| 139 |
+
var T = D.errorTaxonomy;
|
| 140 |
+
U.$('#tax-sub').textContent = T.note + ' Counts of failure codes among ' + T.totals.api.sampled + ' API and ' + T.totals.local.sampled + ' local sampled failures (Table 5 totals).';
|
| 141 |
+
depLegend(U.$('#tax-legend'));
|
| 142 |
+
var host = U.$('#tax-box');
|
| 143 |
+
host.textContent = '';
|
| 144 |
+
var max = 0;
|
| 145 |
+
T.codes.forEach(function (c) { max = Math.max(max, T.totals.api[c.code], T.totals.local[c.code]); });
|
| 146 |
+
var list = h('ul', { class: 'taxrows' });
|
| 147 |
+
var taxRows = [];
|
| 148 |
+
T.codes.forEach(function (c) {
|
| 149 |
+
var bars = h('div', { class: 'pbars' });
|
| 150 |
+
DEP.forEach(function (d) {
|
| 151 |
+
var v = T.totals[d.key][c.code];
|
| 152 |
+
var track = h('span', { class: 'pbar__track' },
|
| 153 |
+
h('span', { class: 'pbar__fill', style: { width: 'calc((100% - 30px) * ' + (v / max) + ')', background: d.color, 'min-width': v ? '3px' : '0' } }),
|
| 154 |
+
h('span', { class: 'pbar__v', text: String(v), style: { left: 'calc((100% - 30px) * ' + (v / max) + ' + ' + (v ? 6 : 0) + 'px)' } }));
|
| 155 |
+
var row = h('div', { class: 'pbar', attrs: { role: 'img', 'aria-label': c.code + ' (' + c.name + '), ' + d.label + ': ' + v + '. ' + c.definition } }, h('span', { text: d.label, attrs: { 'aria-hidden': 'true' } }), track);
|
| 156 |
+
U.hoverTip(row, function () {
|
| 157 |
+
return { title: c.code + ' · ' + c.name, rows: DEP.map(function (x) { return { label: x.label, value: String(T.totals[x.key][c.code]), color: U.css(x.cssVar) }; }), note: c.definition };
|
| 158 |
+
});
|
| 159 |
+
taxRows.push(row);
|
| 160 |
+
bars.appendChild(row);
|
| 161 |
+
});
|
| 162 |
+
list.appendChild(h('li', { class: 'taxrow' },
|
| 163 |
+
h('div', { class: 'taxrow__lab' }, h('b', { text: c.code }), h('span', { text: c.name })),
|
| 164 |
+
bars));
|
| 165 |
+
});
|
| 166 |
+
host.appendChild(list);
|
| 167 |
+
U.roving(taxRows);
|
| 168 |
+
U.tableView(U.$('#tax-table'), U.table([
|
| 169 |
+
{ label: 'Code', get: function (c) { return c.code; } },
|
| 170 |
+
{ label: 'Name', get: function (c) { return c.name; } },
|
| 171 |
+
{ label: 'Definition', get: function (c) { return c.definition; } },
|
| 172 |
+
{ label: 'API', num: true, get: function (c) { return String(T.totals.api[c.code]); } },
|
| 173 |
+
{ label: 'Local', num: true, get: function (c) { return String(T.totals.local[c.code]); } },
|
| 174 |
+
{ label: 'All', num: true, get: function (c) { return String(T.totals.all[c.code]); } }
|
| 175 |
+
], T.codes, 'Failure taxonomy (Table 4) with Table 5 totals'));
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
U.initReliability = function () { lead(); funnel(); judges(); patterns(); figs(); taxonomy(); };
|
| 179 |
+
})();
|
assets/js/util.js
ADDED
|
@@ -0,0 +1,431 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* OmniStepBench project page: shared helpers. Classic script (works over file://).
|
| 2 |
+
Every number rendered on the page is read from window.OSB (assets/data/data.js). */
|
| 3 |
+
(function () {
|
| 4 |
+
'use strict';
|
| 5 |
+
var D = window.OSB;
|
| 6 |
+
var U = (window.U = {});
|
| 7 |
+
U.D = D;
|
| 8 |
+
U.IMG = 'assets/'; // data.js image paths (img/...) live under assets/
|
| 9 |
+
|
| 10 |
+
var SVGNS = 'http://www.w3.org/2000/svg';
|
| 11 |
+
|
| 12 |
+
U.$ = function (s, r) { return (r || document).querySelector(s); };
|
| 13 |
+
U.$$ = function (s, r) { return Array.prototype.slice.call((r || document).querySelectorAll(s)); };
|
| 14 |
+
|
| 15 |
+
/* Element builder. attrs: class, text, attrs{}, data{}, on{}, style{}; children: nodes/strings. */
|
| 16 |
+
U.h = function (tag, o) {
|
| 17 |
+
var el = document.createElement(tag);
|
| 18 |
+
o = o || {};
|
| 19 |
+
if (o.class) el.className = o.class;
|
| 20 |
+
if (o.text != null) el.textContent = o.text;
|
| 21 |
+
if (o.attrs) for (var k in o.attrs) if (o.attrs[k] != null && o.attrs[k] !== false) el.setAttribute(k, o.attrs[k] === true ? '' : o.attrs[k]);
|
| 22 |
+
if (o.data) for (var d in o.data) el.dataset[d] = o.data[d];
|
| 23 |
+
if (o.style) for (var st in o.style) el.style.setProperty(st, o.style[st]);
|
| 24 |
+
if (o.on) for (var ev in o.on) el.addEventListener(ev, o.on[ev]);
|
| 25 |
+
for (var i = 2; i < arguments.length; i++) U.append(el, arguments[i]);
|
| 26 |
+
return el;
|
| 27 |
+
};
|
| 28 |
+
U.append = function (el, c) {
|
| 29 |
+
if (c == null || c === false) return el;
|
| 30 |
+
if (Array.isArray(c)) { c.forEach(function (x) { U.append(el, x); }); return el; }
|
| 31 |
+
el.appendChild(typeof c === 'string' || typeof c === 'number' ? document.createTextNode(String(c)) : c);
|
| 32 |
+
return el;
|
| 33 |
+
};
|
| 34 |
+
U.s = function (tag, attrs, parent) {
|
| 35 |
+
var el = document.createElementNS(SVGNS, tag);
|
| 36 |
+
if (attrs) for (var k in attrs) if (attrs[k] != null) el.setAttribute(k, attrs[k]);
|
| 37 |
+
if (parent) parent.appendChild(el);
|
| 38 |
+
return el;
|
| 39 |
+
};
|
| 40 |
+
/* <svg><use href="#id"/></svg> icon */
|
| 41 |
+
U.icon = function (id, cls) {
|
| 42 |
+
var svg = document.createElementNS(SVGNS, 'svg');
|
| 43 |
+
svg.setAttribute('aria-hidden', 'true');
|
| 44 |
+
svg.setAttribute('focusable', 'false');
|
| 45 |
+
if (cls) svg.setAttribute('class', cls);
|
| 46 |
+
var use = document.createElementNS(SVGNS, 'use');
|
| 47 |
+
use.setAttribute('href', '#' + id);
|
| 48 |
+
svg.appendChild(use);
|
| 49 |
+
return svg;
|
| 50 |
+
};
|
| 51 |
+
|
| 52 |
+
/* ---- data access ---- */
|
| 53 |
+
U.get = function (path) {
|
| 54 |
+
return String(path).split('.').reduce(function (o, k) { return o == null ? o : o[k]; }, D);
|
| 55 |
+
};
|
| 56 |
+
var byName = {};
|
| 57 |
+
D.models.forEach(function (m) { byName[m.name] = m; byName[m.shortName] = m; });
|
| 58 |
+
U.model = function (n) { return byName[n]; };
|
| 59 |
+
U.group = function (k) { return D.groups.filter(function (g) { return g.key === k; })[0]; };
|
| 60 |
+
U.source = function (k) { return D.sources.filter(function (s) { return s.key === k; })[0]; };
|
| 61 |
+
U.GROUPS = D.groupOrder.map(U.group);
|
| 62 |
+
U.TEXT_GROUPS = U.GROUPS.filter(function (g) { return g.modality === 'text'; });
|
| 63 |
+
U.MM_GROUPS = U.GROUPS.filter(function (g) { return g.modality !== 'text'; });
|
| 64 |
+
U.wlVar = function (k) { return 'var(--wl-' + k + ')'; };
|
| 65 |
+
U.css = function (name) { return getComputedStyle(document.documentElement).getPropertyValue(name).trim(); };
|
| 66 |
+
|
| 67 |
+
/* ---- formatting (display only; never recomputes paper values) ---- */
|
| 68 |
+
U.int = function (n) { return Number(n).toLocaleString('en-US'); };
|
| 69 |
+
U.pct = function (n) { return n == null ? '—' : Number(n).toFixed(1); };
|
| 70 |
+
U.tok = function (k) { return k == null ? '—' : k + 'k'; };
|
| 71 |
+
U.usd = function (txt) { return txt == null ? '—' : (txt.charAt(0) === '<' ? '<$' + txt.slice(1) : '$' + txt); };
|
| 72 |
+
U.modalityCount = function () {
|
| 73 |
+
var m = {}, f = {};
|
| 74 |
+
D.groups.forEach(function (g) { m[g.modality] = 1; f[g.form] = 1; });
|
| 75 |
+
return [Object.keys(m).length, Object.keys(f).length];
|
| 76 |
+
};
|
| 77 |
+
U.matrixLabel = function () { var mc = U.modalityCount(); return mc[0] + '×' + mc[1]; };
|
| 78 |
+
U.scoringLabel = { auto: 'Auto', judge: 'Judge', hybrid: 'Hybrid' };
|
| 79 |
+
U.SCORING_ORDER = ['auto', 'hybrid', 'judge']; // ordinal: increasing reliance on the LLM judge
|
| 80 |
+
U.scoringVar = function (k) { return 'var(--score-' + k + ')'; };
|
| 81 |
+
|
| 82 |
+
/* Competition ranking (1,2,2,4) by value descending */
|
| 83 |
+
U.rank = function (items, val) {
|
| 84 |
+
var sorted = items.slice().sort(function (a, b) { return val(b) - val(a); });
|
| 85 |
+
var ranks = new Map();
|
| 86 |
+
sorted.forEach(function (it, i) {
|
| 87 |
+
if (i > 0 && val(it) === val(sorted[i - 1])) ranks.set(it, ranks.get(sorted[i - 1]));
|
| 88 |
+
else ranks.set(it, i + 1);
|
| 89 |
+
});
|
| 90 |
+
return ranks;
|
| 91 |
+
};
|
| 92 |
+
|
| 93 |
+
/* Wrap numbers in a sentence with <b> (text built with DOM nodes, not innerHTML) */
|
| 94 |
+
U.emphNums = function (text) {
|
| 95 |
+
/* Bold standalone numbers only (not digits inside names such as GPT-5.4 or Qwen3.6-27B). */
|
| 96 |
+
var frag = document.createDocumentFragment();
|
| 97 |
+
var re = /(^|[\s(~+\u2248\u2192:;,])((?:\$|<\$?|[+\u2212])?\d[\d,]*(?:\.\d+)?(?:k|%|\u00d7)?)(?![\w\-.]*\w)/g, last = 0, m;
|
| 98 |
+
while ((m = re.exec(text))) {
|
| 99 |
+
var start = m.index + m[1].length;
|
| 100 |
+
if (start > last) frag.appendChild(document.createTextNode(text.slice(last, start)));
|
| 101 |
+
frag.appendChild(U.h('b', { text: m[2] }));
|
| 102 |
+
last = start + m[2].length;
|
| 103 |
+
}
|
| 104 |
+
if (last < text.length) frag.appendChild(document.createTextNode(text.slice(last)));
|
| 105 |
+
return frag;
|
| 106 |
+
};
|
| 107 |
+
/* Render `code` spans from README markdown */
|
| 108 |
+
U.mdCode = function (text) {
|
| 109 |
+
var frag = document.createDocumentFragment();
|
| 110 |
+
String(text).split(/(`[^`]+`)/g).forEach(function (part) {
|
| 111 |
+
if (!part) return;
|
| 112 |
+
if (part.charAt(0) === '`' && part.charAt(part.length - 1) === '`') frag.appendChild(U.h('code', { text: part.slice(1, -1) }));
|
| 113 |
+
else frag.appendChild(document.createTextNode(part));
|
| 114 |
+
});
|
| 115 |
+
return frag;
|
| 116 |
+
};
|
| 117 |
+
|
| 118 |
+
/* ---- bindings ---- */
|
| 119 |
+
U.bindAll = function (root) {
|
| 120 |
+
U.$$('[data-bind]', root).forEach(function (el) {
|
| 121 |
+
var v = U.get(el.getAttribute('data-bind'));
|
| 122 |
+
if (v != null) el.textContent = v;
|
| 123 |
+
});
|
| 124 |
+
U.$$('[data-href]', root).forEach(function (el) {
|
| 125 |
+
var v = U.get(el.getAttribute('data-href'));
|
| 126 |
+
if (v) { el.setAttribute('href', v); el.setAttribute('rel', 'noopener'); }
|
| 127 |
+
});
|
| 128 |
+
};
|
| 129 |
+
|
| 130 |
+
/* ---- tooltip ---- */
|
| 131 |
+
var tip, tipOwner = null;
|
| 132 |
+
U.tip = {
|
| 133 |
+
el: function () { return tip || (tip = document.getElementById('tip')); },
|
| 134 |
+
/* spec: {title, rows:[{label, value, color}], note} */
|
| 135 |
+
show: function (spec, x, y, owner) {
|
| 136 |
+
var t = U.tip.el();
|
| 137 |
+
t.textContent = '';
|
| 138 |
+
if (spec.title) t.appendChild(U.h('div', { class: 'tip__title', text: spec.title }));
|
| 139 |
+
(spec.rows || []).forEach(function (r) {
|
| 140 |
+
var key = U.h('span', { class: 'tip__key' });
|
| 141 |
+
if (r.color) key.style.borderTopColor = r.color; else key.style.borderTopColor = 'transparent';
|
| 142 |
+
t.appendChild(U.h('div', { class: 'tip__row' }, key, U.h('span', { class: 'tip__lab', text: r.label }), U.h('span', { class: 'tip__val', text: r.value })));
|
| 143 |
+
});
|
| 144 |
+
if (spec.note) t.appendChild(U.h('div', { class: 'tip__note', text: spec.note }));
|
| 145 |
+
t.hidden = false;
|
| 146 |
+
tipOwner = owner || null;
|
| 147 |
+
var w = t.offsetWidth, hgt = t.offsetHeight, vw = window.innerWidth, vh = window.innerHeight;
|
| 148 |
+
var left = x + 16, top = y + 16;
|
| 149 |
+
if (left + w > vw - 8) left = Math.max(8, x - w - 16);
|
| 150 |
+
if (top + hgt > vh - 8) top = Math.max(8, y - hgt - 16);
|
| 151 |
+
t.style.left = left + 'px';
|
| 152 |
+
t.style.top = top + 'px';
|
| 153 |
+
},
|
| 154 |
+
showAt: function (spec, el) {
|
| 155 |
+
var r = el.getBoundingClientRect();
|
| 156 |
+
U.tip.show(spec, r.left + r.width / 2, r.top + r.height / 2, el);
|
| 157 |
+
},
|
| 158 |
+
hide: function (owner) {
|
| 159 |
+
if (owner && tipOwner && owner !== tipOwner) return;
|
| 160 |
+
var t = U.tip.el(); if (t) t.hidden = true; tipOwner = null;
|
| 161 |
+
},
|
| 162 |
+
/* keyboard focus: show next to the element and remember it, so the tooltip can be
|
| 163 |
+
re-anchored after a scroll instead of floating detached from its owner */
|
| 164 |
+
focus: function (specFn, el) {
|
| 165 |
+
focusOwner = { el: el, spec: specFn };
|
| 166 |
+
U.tip.showAt(specFn(), el);
|
| 167 |
+
},
|
| 168 |
+
blur: function (el) {
|
| 169 |
+
if (focusOwner && focusOwner.el === el) focusOwner = null;
|
| 170 |
+
U.tip.hide(el);
|
| 171 |
+
}
|
| 172 |
+
};
|
| 173 |
+
var focusOwner = null, scrollTimer = null;
|
| 174 |
+
/* Attach hover + focus tooltip to an element; specFn returns the spec */
|
| 175 |
+
U.hoverTip = function (el, specFn) {
|
| 176 |
+
el.addEventListener('pointermove', function (e) { U.tip.show(specFn(), e.clientX, e.clientY, el); });
|
| 177 |
+
el.addEventListener('pointerleave', function () { U.tip.hide(el); });
|
| 178 |
+
el.addEventListener('focus', function () { U.tip.focus(specFn, el); });
|
| 179 |
+
el.addEventListener('blur', function () { U.tip.blur(el); });
|
| 180 |
+
};
|
| 181 |
+
window.addEventListener('scroll', function () {
|
| 182 |
+
U.tip.hide();
|
| 183 |
+
clearTimeout(scrollTimer);
|
| 184 |
+
scrollTimer = setTimeout(function () {
|
| 185 |
+
if (!focusOwner || document.activeElement !== focusOwner.el) { focusOwner = null; return; }
|
| 186 |
+
var r = focusOwner.el.getBoundingClientRect();
|
| 187 |
+
if (r.bottom > 0 && r.top < window.innerHeight) U.tip.showAt(focusOwner.spec(), focusOwner.el);
|
| 188 |
+
}, 160);
|
| 189 |
+
}, { passive: true });
|
| 190 |
+
/* Escape dismisses the tooltip for good: forget the focus owner so a later scroll does not re-open it */
|
| 191 |
+
document.addEventListener('keydown', function (e) { if (e.key === 'Escape') { focusOwner = null; U.tip.hide(); } });
|
| 192 |
+
|
| 193 |
+
/* ---- chart <-> table toggles ---- */
|
| 194 |
+
U.initViewToggles = function () {
|
| 195 |
+
U.$$('.view-toggle').forEach(function (btn) {
|
| 196 |
+
var t = btn.getAttribute('data-target');
|
| 197 |
+
var chart = document.getElementById(t + '-chart'), table = document.getElementById(t + '-table');
|
| 198 |
+
if (!chart || !table) return;
|
| 199 |
+
/* the visible label says what the button will show next ("View as table" / "View as chart"),
|
| 200 |
+
so no aria-pressed: a changing name plus a pressed state would double-signal */
|
| 201 |
+
btn.removeAttribute('aria-pressed');
|
| 202 |
+
btn.setAttribute('aria-controls', t + '-chart ' + t + '-table');
|
| 203 |
+
btn.addEventListener('click', function () {
|
| 204 |
+
var showTable = table.hidden;
|
| 205 |
+
btn.classList.toggle('is-on', showTable);
|
| 206 |
+
chart.hidden = showTable; table.hidden = !showTable;
|
| 207 |
+
btn.querySelector('span').textContent = showTable ? 'View as chart' : 'View as table';
|
| 208 |
+
var use = btn.querySelector('use'); if (use) use.setAttribute('href', showTable ? '#i-chart' : '#i-table');
|
| 209 |
+
U.tip.hide();
|
| 210 |
+
document.dispatchEvent(new CustomEvent('viewtoggle', { detail: { target: t, table: showTable } }));
|
| 211 |
+
});
|
| 212 |
+
});
|
| 213 |
+
};
|
| 214 |
+
|
| 215 |
+
/* Build a simple data table: cols [{label, num?, cls?, get(row)->string|node}] */
|
| 216 |
+
U.table = function (cols, rows, caption) {
|
| 217 |
+
var t = U.h('table', { class: 'data-table' });
|
| 218 |
+
if (caption) t.appendChild(U.h('caption', { text: caption }));
|
| 219 |
+
var thead = U.h('thead'), tr = U.h('tr');
|
| 220 |
+
cols.forEach(function (c) { tr.appendChild(U.h('th', { class: c.num ? 'num' : (c.cls || ''), text: c.label, attrs: { scope: 'col' } })); });
|
| 221 |
+
thead.appendChild(tr); t.appendChild(thead);
|
| 222 |
+
var tb = U.h('tbody');
|
| 223 |
+
rows.forEach(function (r) {
|
| 224 |
+
var row = U.h('tr');
|
| 225 |
+
cols.forEach(function (c, i) {
|
| 226 |
+
var v = c.get(r);
|
| 227 |
+
var cell = U.h(i === 0 && c.rowHeader !== false ? 'th' : 'td', { class: c.num ? 'num' : (c.cls || '') });
|
| 228 |
+
if (i === 0 && c.rowHeader !== false) cell.setAttribute('scope', 'row');
|
| 229 |
+
U.append(cell, v == null ? '—' : v);
|
| 230 |
+
row.appendChild(cell);
|
| 231 |
+
});
|
| 232 |
+
tb.appendChild(row);
|
| 233 |
+
});
|
| 234 |
+
t.appendChild(tb);
|
| 235 |
+
return t;
|
| 236 |
+
};
|
| 237 |
+
|
| 238 |
+
/* Put a U.table into a chart's table view (host = the .view--table element), replacing what was there.
|
| 239 |
+
The caption moves above the scroller so it never scrolls away with the columns; the scroller is a
|
| 240 |
+
named, focusable region (keyboard users can scroll it with the arrow keys), and while it overflows a
|
| 241 |
+
"swipe" hint shows and the right edge fades until the last column is reached. */
|
| 242 |
+
U.tableView = function (host, table) {
|
| 243 |
+
host.textContent = '';
|
| 244 |
+
host.classList.add('tview');
|
| 245 |
+
var capEl = table.querySelector('caption'), capId = host.id + '-cap';
|
| 246 |
+
var cap = U.h('p', { class: 'tview__cap', text: capEl ? capEl.textContent : '', attrs: { id: capId } });
|
| 247 |
+
if (capEl) capEl.parentNode.removeChild(capEl);
|
| 248 |
+
table.setAttribute('aria-labelledby', capId);
|
| 249 |
+
var sc = U.h('div', { class: 'table-scroll', attrs: { tabindex: '0', role: 'region', 'aria-labelledby': capId } }, table);
|
| 250 |
+
sc.addEventListener('scroll', function () { tviewState(host, sc); }, { passive: true });
|
| 251 |
+
host.appendChild(cap);
|
| 252 |
+
host.appendChild(U.h('p', { class: 'tview__swipe', text: 'swipe the table sideways →', attrs: { 'aria-hidden': 'true' } }));
|
| 253 |
+
host.appendChild(sc);
|
| 254 |
+
tviewState(host, sc);
|
| 255 |
+
return sc;
|
| 256 |
+
};
|
| 257 |
+
function tviewState(host, sc) {
|
| 258 |
+
var over = sc.scrollWidth > sc.clientWidth + 1;
|
| 259 |
+
host.classList.toggle('is-over', over);
|
| 260 |
+
sc.classList.toggle('at-end', !over || sc.scrollLeft + sc.clientWidth >= sc.scrollWidth - 2);
|
| 261 |
+
}
|
| 262 |
+
function tviewAll() {
|
| 263 |
+
U.$$('.tview').forEach(function (host) { var sc = U.$('.table-scroll', host); if (sc) tviewState(host, sc); });
|
| 264 |
+
}
|
| 265 |
+
var tviewTimer;
|
| 266 |
+
window.addEventListener('resize', function () { clearTimeout(tviewTimer); tviewTimer = setTimeout(tviewAll, 80); });
|
| 267 |
+
document.addEventListener('viewtoggle', tviewAll);
|
| 268 |
+
if (document.fonts && document.fonts.ready) document.fonts.ready.then(tviewAll);
|
| 269 |
+
|
| 270 |
+
/* ---- segmented radio control ---- */
|
| 271 |
+
U.seg = function (container, options, value, onChange) {
|
| 272 |
+
container.textContent = '';
|
| 273 |
+
var btns = options.map(function (o) {
|
| 274 |
+
var b = U.h('button', { attrs: { type: 'button', role: 'radio', 'aria-checked': String(o.value === value), tabindex: o.value === value ? '0' : '-1' } });
|
| 275 |
+
if (o.dot) b.appendChild(U.h('span', { class: 'dot', style: { background: o.dot } }));
|
| 276 |
+
b.appendChild(document.createTextNode(o.label));
|
| 277 |
+
if (o.title) b.title = o.title;
|
| 278 |
+
b.addEventListener('click', function () { select(o.value, true); });
|
| 279 |
+
container.appendChild(b);
|
| 280 |
+
return b;
|
| 281 |
+
});
|
| 282 |
+
function select(v, fire) {
|
| 283 |
+
options.forEach(function (o, i) {
|
| 284 |
+
var on = o.value === v;
|
| 285 |
+
btns[i].setAttribute('aria-checked', String(on));
|
| 286 |
+
btns[i].tabIndex = on ? 0 : -1;
|
| 287 |
+
});
|
| 288 |
+
if (fire) onChange(v);
|
| 289 |
+
}
|
| 290 |
+
container.addEventListener('keydown', function (e) {
|
| 291 |
+
var idx = btns.indexOf(document.activeElement);
|
| 292 |
+
if (idx < 0) return;
|
| 293 |
+
var n = null;
|
| 294 |
+
if (e.key === 'ArrowRight' || e.key === 'ArrowDown') n = (idx + 1) % btns.length;
|
| 295 |
+
if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') n = (idx - 1 + btns.length) % btns.length;
|
| 296 |
+
if (n != null) { e.preventDefault(); btns[n].focus(); btns[n].click(); }
|
| 297 |
+
});
|
| 298 |
+
return { select: select };
|
| 299 |
+
};
|
| 300 |
+
|
| 301 |
+
/* ---- copy to clipboard ---- */
|
| 302 |
+
U.copy = function (text, btn) {
|
| 303 |
+
function done(ok) {
|
| 304 |
+
var span = btn.querySelector('span');
|
| 305 |
+
var prev = span.textContent;
|
| 306 |
+
span.textContent = ok ? 'Copied' : 'Press Ctrl+C';
|
| 307 |
+
btn.classList.toggle('is-done', ok);
|
| 308 |
+
var use = btn.querySelector('use'); if (use && ok) use.setAttribute('href', '#i-check');
|
| 309 |
+
var live = document.getElementById('live'); if (live) live.textContent = ok ? 'Copied to clipboard' : 'Copy failed';
|
| 310 |
+
setTimeout(function () { span.textContent = prev === 'Copied' ? 'Copy' : prev; btn.classList.remove('is-done'); if (use) use.setAttribute('href', '#i-copy'); }, 1600);
|
| 311 |
+
}
|
| 312 |
+
function fallback() {
|
| 313 |
+
var ta = U.h('textarea', { attrs: { readonly: true, 'aria-hidden': 'true' }, style: { position: 'fixed', left: '-9999px', top: '0' } });
|
| 314 |
+
ta.value = text; document.body.appendChild(ta); ta.select();
|
| 315 |
+
var ok = false; try { ok = document.execCommand('copy'); } catch (e) { ok = false; }
|
| 316 |
+
document.body.removeChild(ta); done(ok);
|
| 317 |
+
}
|
| 318 |
+
if (navigator.clipboard && window.isSecureContext) navigator.clipboard.writeText(text).then(function () { done(true); }, fallback);
|
| 319 |
+
else fallback();
|
| 320 |
+
};
|
| 321 |
+
U.copyButton = function (getText, label) {
|
| 322 |
+
var b = U.h('button', { class: 'copy-btn', attrs: { type: 'button', 'aria-label': label || 'Copy to clipboard' } }, U.icon('i-copy'), U.h('span', { text: 'Copy', attrs: { 'aria-hidden': 'true' } }));
|
| 323 |
+
b.addEventListener('click', function () { U.copy(getText(), b); });
|
| 324 |
+
return b;
|
| 325 |
+
};
|
| 326 |
+
|
| 327 |
+
/* ---- lightbox ---- */
|
| 328 |
+
U.lightbox = function (src, alt, caption) {
|
| 329 |
+
var dlg = document.getElementById('lightbox');
|
| 330 |
+
var img = document.getElementById('lightbox-img');
|
| 331 |
+
/* on phones, show the figure near its natural size inside a pannable box */
|
| 332 |
+
var pan = window.matchMedia && window.matchMedia('(max-width: 720px)').matches;
|
| 333 |
+
dlg.classList.toggle('is-pan', !!pan);
|
| 334 |
+
img.style.width = '';
|
| 335 |
+
img.onload = function () { if (pan) img.style.width = Math.min(img.naturalWidth, 1400) + 'px'; };
|
| 336 |
+
img.src = src; img.alt = alt || '';
|
| 337 |
+
if (pan && img.complete && img.naturalWidth) img.style.width = Math.min(img.naturalWidth, 1400) + 'px';
|
| 338 |
+
document.getElementById('lightbox-cap').textContent = caption || '';
|
| 339 |
+
if (typeof dlg.showModal === 'function') dlg.showModal(); else dlg.setAttribute('open', '');
|
| 340 |
+
};
|
| 341 |
+
U.initLightbox = function () {
|
| 342 |
+
var dlg = document.getElementById('lightbox');
|
| 343 |
+
document.getElementById('lightbox-close').addEventListener('click', function () { dlg.close ? dlg.close() : dlg.removeAttribute('open'); });
|
| 344 |
+
dlg.addEventListener('click', function (e) { if (e.target === dlg) dlg.close(); });
|
| 345 |
+
};
|
| 346 |
+
U.fig = function (key) { return D.caseStudy.figures.filter(function (f) { return f.key === key; })[0]; };
|
| 347 |
+
/* zoomable figure button */
|
| 348 |
+
U.zoomable = function (src, alt, caption, label, opts) {
|
| 349 |
+
opts = opts || {};
|
| 350 |
+
var img = U.h('img', { attrs: { src: src, alt: alt || '', loading: opts.eager ? null : 'lazy', decoding: 'async' } });
|
| 351 |
+
var b = U.h('button', { class: 'zoomable', attrs: { type: 'button', 'aria-label': 'Enlarge ' + (label || 'figure') } }, img,
|
| 352 |
+
U.h('span', { class: 'zoomable__hint' }, U.icon('i-zoom'), 'Enlarge'));
|
| 353 |
+
b.addEventListener('click', function () { U.lightbox(src, alt, caption); });
|
| 354 |
+
return b;
|
| 355 |
+
};
|
| 356 |
+
|
| 357 |
+
/* ---- resize ---- */
|
| 358 |
+
U.onResize = function (el, fn) {
|
| 359 |
+
var last = 0, t;
|
| 360 |
+
var ro = new ResizeObserver(function (entries) {
|
| 361 |
+
var w = Math.round(entries[0].contentRect.width);
|
| 362 |
+
if (w === last || w === 0) return;
|
| 363 |
+
last = w; clearTimeout(t); t = setTimeout(function () { fn(w); }, 60);
|
| 364 |
+
});
|
| 365 |
+
ro.observe(el);
|
| 366 |
+
};
|
| 367 |
+
U.reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
| 368 |
+
|
| 369 |
+
/* Nice linear ticks */
|
| 370 |
+
U.ticks = function (lo, hi, n) {
|
| 371 |
+
var span = hi - lo, step = Math.pow(10, Math.floor(Math.log10(span / n))), err = span / n / step;
|
| 372 |
+
if (err >= 7.5) step *= 10; else if (err >= 3.5) step *= 5; else if (err >= 1.5) step *= 2;
|
| 373 |
+
var out = [], v = Math.ceil(lo / step) * step;
|
| 374 |
+
for (; v <= hi + 1e-9; v += step) out.push(Math.round(v * 1e6) / 1e6);
|
| 375 |
+
return out;
|
| 376 |
+
};
|
| 377 |
+
|
| 378 |
+
|
| 379 |
+
/* Log-axis tick labels (1-2-5 per decade) without collisions: 1s first, then 5s, then 2s;
|
| 380 |
+
a label is kept only if it clears every kept label by `gap` px and stays inside [x0, x1].
|
| 381 |
+
ticks: [{v, k, x}] -> returns the subset whose labels should be drawn. */
|
| 382 |
+
U.fitTicks = function (ticks, fmt, x0, x1, font, gap) {
|
| 383 |
+
gap = gap == null ? 8 : gap;
|
| 384 |
+
var kept = [];
|
| 385 |
+
[1, 5, 2].forEach(function (k) {
|
| 386 |
+
ticks.filter(function (t) { return t.k === k; }).forEach(function (t) {
|
| 387 |
+
var w = U.textWidth(fmt(t.v), font || '400 12.5px Nunito');
|
| 388 |
+
var a = t.x - w / 2, b = t.x + w / 2;
|
| 389 |
+
if (a < x0 - 1 || b > x1 + 1) return;
|
| 390 |
+
for (var i = 0; i < kept.length; i++) if (a < kept[i].b + gap && b > kept[i].a - gap) return;
|
| 391 |
+
kept.push({ a: a, b: b, t: t });
|
| 392 |
+
});
|
| 393 |
+
});
|
| 394 |
+
return kept.map(function (x) { return x.t; });
|
| 395 |
+
};
|
| 396 |
+
U.usdTick = function (v) { var dec = Math.max(0, -Math.floor(Math.log10(v) + 1e-9)); return '$' + v.toFixed(dec); };
|
| 397 |
+
|
| 398 |
+
/* ---- roving focus: one Tab stop for a set of marks, arrow keys move between them ----
|
| 399 |
+
items: array of focusable elements (in navigation order). onFocus(i) is called when
|
| 400 |
+
an item receives focus. Returns {set(i)} to move the tab stop programmatically. */
|
| 401 |
+
U.roving = function (items, onFocus, opts) {
|
| 402 |
+
opts = opts || {};
|
| 403 |
+
var cur = Math.max(0, Math.min(items.length - 1, opts.start || 0));
|
| 404 |
+
items.forEach(function (el, i) {
|
| 405 |
+
el.setAttribute('tabindex', i === cur ? '0' : '-1');
|
| 406 |
+
el.addEventListener('focus', function () { cur = i; items.forEach(function (x, j) { x.setAttribute('tabindex', j === i ? '0' : '-1'); }); if (onFocus) onFocus(i); });
|
| 407 |
+
el.addEventListener('keydown', function (e) {
|
| 408 |
+
var n = null;
|
| 409 |
+
if (e.key === 'ArrowRight' || e.key === 'ArrowDown') n = Math.min(items.length - 1, i + 1);
|
| 410 |
+
else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') n = Math.max(0, i - 1);
|
| 411 |
+
else if (e.key === 'Home') n = 0;
|
| 412 |
+
else if (e.key === 'End') n = items.length - 1;
|
| 413 |
+
if (n != null) { e.preventDefault(); items[n].focus(); }
|
| 414 |
+
});
|
| 415 |
+
});
|
| 416 |
+
return { set: function (i) { cur = i; items.forEach(function (x, j) { x.setAttribute('tabindex', j === i ? '0' : '-1'); }); } };
|
| 417 |
+
};
|
| 418 |
+
|
| 419 |
+
/* ---- comic starburst accent (decorative; the number it sits next to is real text) ---- */
|
| 420 |
+
U.burst = function (text, variant) {
|
| 421 |
+
return U.h('span', { class: 'burst' + (variant ? ' burst--' + variant : ''), attrs: { 'aria-hidden': 'true' } }, U.h('span', { class: 'burst__t', text: text }));
|
| 422 |
+
};
|
| 423 |
+
|
| 424 |
+
/* Text width measurement for SVG label layout */
|
| 425 |
+
var measureCtx;
|
| 426 |
+
U.textWidth = function (text, font) {
|
| 427 |
+
measureCtx = measureCtx || document.createElement('canvas').getContext('2d');
|
| 428 |
+
measureCtx.font = font || '800 12.5px Nunito';
|
| 429 |
+
return measureCtx.measureText(text).width;
|
| 430 |
+
};
|
| 431 |
+
})();
|
assets/js/workloads.js
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Workload matrix, cell detail, source composition, task explorer. */
|
| 2 |
+
(function () {
|
| 3 |
+
'use strict';
|
| 4 |
+
var U = window.U, D = U.D, h = U.h;
|
| 5 |
+
var FORM_LABEL = { 'single-step': 'Single-step', 'multi-step': 'Multi-step', 'multi-step+tools': 'Multi-step + tools' };
|
| 6 |
+
var MOD_LABEL = { text: 'Text', multimodal: 'Multimodal' };
|
| 7 |
+
var selected = null, cellBtns = {}, exampleIdx = {};
|
| 8 |
+
|
| 9 |
+
function forms() { var f = []; U.GROUPS.forEach(function (g) { if (f.indexOf(g.form) < 0) f.push(g.form); }); return f; }
|
| 10 |
+
function mods() { var m = []; U.GROUPS.forEach(function (g) { if (m.indexOf(g.modality) < 0) m.push(g.modality); }); return m; }
|
| 11 |
+
function groupAt(mod, form) { return U.GROUPS.filter(function (g) { return g.modality === mod && g.form === form; })[0]; }
|
| 12 |
+
|
| 13 |
+
function mixbar(scoring, lg) {
|
| 14 |
+
var bar = h('span', { class: 'mixbar' + (lg ? ' mixbar--lg' : ''), attrs: { 'aria-hidden': 'true' } });
|
| 15 |
+
U.SCORING_ORDER.forEach(function (k) {
|
| 16 |
+
if (!scoring[k]) return;
|
| 17 |
+
bar.appendChild(h('span', { style: { background: U.scoringVar(k), flex: scoring[k] + ' 1 0' } }));
|
| 18 |
+
});
|
| 19 |
+
return bar;
|
| 20 |
+
}
|
| 21 |
+
function mixText(scoring) {
|
| 22 |
+
return U.SCORING_ORDER.filter(function (k) { return scoring[k]; }).map(function (k) { return scoring[k] + ' ' + U.scoringLabel[k].toLowerCase(); }).join(', ');
|
| 23 |
+
}
|
| 24 |
+
function scoringLegend() {
|
| 25 |
+
var lg = h('div', { class: 'legend' }, h('span', { class: 'legend__title', text: 'Scoring' }));
|
| 26 |
+
U.SCORING_ORDER.forEach(function (k) {
|
| 27 |
+
lg.appendChild(h('span', { class: 'legend__item' }, h('span', { class: 'legend__sw', style: { background: U.scoringVar(k) } }), U.scoringLabel[k]));
|
| 28 |
+
});
|
| 29 |
+
return lg;
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
/* ---------------- matrix ---------------- */
|
| 33 |
+
function buildMatrix() {
|
| 34 |
+
var host = U.$('#matrix');
|
| 35 |
+
var grid = h('div', { class: 'matrix__grid' });
|
| 36 |
+
grid.appendChild(h('span', { class: 'matrix__corner', text: 'input ↓ / execution →' }));
|
| 37 |
+
forms().forEach(function (f) { grid.appendChild(h('span', { class: 'matrix__col', text: FORM_LABEL[f] || f })); });
|
| 38 |
+
grid.appendChild(h('span', { class: 'matrix__axis', attrs: { 'aria-hidden': 'true' } }, h('span', { text: 'increasing execution complexity' })));
|
| 39 |
+
mods().forEach(function (mod) {
|
| 40 |
+
grid.appendChild(h('span', { class: 'matrix__row', text: MOD_LABEL[mod] || mod }));
|
| 41 |
+
forms().forEach(function (f) {
|
| 42 |
+
var g = groupAt(mod, f);
|
| 43 |
+
var srcNames = g.sources.map(function (k) { return U.source(k).name; });
|
| 44 |
+
/* the accessible name is the visible text plus a hidden gloss, so it contains the visible label (WCAG 2.5.3) */
|
| 45 |
+
var btn = h('button', {
|
| 46 |
+
class: 'wcell', style: { '--c': U.wlVar(g.key) },
|
| 47 |
+
attrs: { type: 'button', 'aria-pressed': 'false', 'aria-controls': 'cell-detail' }
|
| 48 |
+
},
|
| 49 |
+
h('span', { class: 'wcell__count', text: String(g.count) }),
|
| 50 |
+
h('span', { class: 'wcell__unit', text: 'tasks' }),
|
| 51 |
+
h('span', { class: 'wcell__label', text: g.label }),
|
| 52 |
+
h('span', { class: 'wcell__sr', text: ' (' + g.longLabel + ')' }),
|
| 53 |
+
h('span', { class: 'wcell__src', text: srcNames.join(', ') }),
|
| 54 |
+
h('span', { class: 'wcell__sr', text: ' Scoring: ' + mixText(g.scoring) + '.' }),
|
| 55 |
+
mixbar(g.scoring));
|
| 56 |
+
btn.addEventListener('click', function () { select(g.key, true); });
|
| 57 |
+
U.hoverTip(btn, function () {
|
| 58 |
+
return { title: g.longLabel, rows: [{ label: 'Tasks', value: String(g.count), color: U.css('--wl-' + g.key) }].concat(U.SCORING_ORDER.filter(function (k) { return g.scoring[k]; }).map(function (k) {
|
| 59 |
+
return { label: U.scoringLabel[k] + ' scoring', value: String(g.scoring[k]), color: U.css('--score-' + k) };
|
| 60 |
+
})), note: srcNames.join(', ') };
|
| 61 |
+
});
|
| 62 |
+
cellBtns[g.key] = btn;
|
| 63 |
+
grid.appendChild(btn);
|
| 64 |
+
});
|
| 65 |
+
});
|
| 66 |
+
host.appendChild(grid);
|
| 67 |
+
host.appendChild(h('div', { class: 'matrix__foot' }, scoringLegend(), h('span', { class: 'matrix__hint', text: 'select a cell to dive in' })));
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
function select(key, focusDetail) {
|
| 71 |
+
selected = key;
|
| 72 |
+
Object.keys(cellBtns).forEach(function (k) { cellBtns[k].setAttribute('aria-pressed', String(k === key)); });
|
| 73 |
+
renderDetail(key);
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
function renderDetail(key) {
|
| 77 |
+
var g = U.group(key), box = U.$('#cell-detail');
|
| 78 |
+
box.textContent = '';
|
| 79 |
+
box.appendChild(h('div', { class: 'cd__head' },
|
| 80 |
+
h('span', { class: 'cd__sw', style: { background: U.wlVar(key) } }),
|
| 81 |
+
h('h3', { class: 'cd__title', text: g.longLabel }),
|
| 82 |
+
h('span', { class: 'cd__count', text: g.count + ' tasks · ' + g.applicableModels + ' models' })));
|
| 83 |
+
|
| 84 |
+
var grid = h('div', { class: 'cd__grid' });
|
| 85 |
+
/* sources + scoring */
|
| 86 |
+
var left = h('div', { class: 'cd__block' }, h('h4', { text: 'Sources' }));
|
| 87 |
+
var srcs = h('div', { class: 'cd__srcs' });
|
| 88 |
+
g.sources.forEach(function (k) {
|
| 89 |
+
var s = U.source(k);
|
| 90 |
+
srcs.appendChild(h('span', { class: 'pill', attrs: { title: s.capability } }, s.name, h('span', { class: 'chip__n', text: String(s.count) })));
|
| 91 |
+
});
|
| 92 |
+
left.appendChild(srcs);
|
| 93 |
+
left.appendChild(h('h4', { text: 'Scoring modes', style: { 'margin-top': '14px' } }));
|
| 94 |
+
var mixRows = h('div', { class: 'cd__mixrows' });
|
| 95 |
+
U.SCORING_ORDER.forEach(function (k) {
|
| 96 |
+
if (!g.scoring[k]) return;
|
| 97 |
+
mixRows.appendChild(h('span', null, h('span', { class: 'legend__sw', style: { background: U.scoringVar(k) } }), g.scoring[k] + ' ' + U.scoringLabel[k].toLowerCase()));
|
| 98 |
+
});
|
| 99 |
+
left.appendChild(h('div', { class: 'cd__mix' }, mixbar(g.scoring, true), mixRows));
|
| 100 |
+
grid.appendChild(left);
|
| 101 |
+
|
| 102 |
+
/* top models (Table 1) */
|
| 103 |
+
var right = h('div', { class: 'cd__block' }, h('h4', { text: 'Top models (audited accuracy, %)' }));
|
| 104 |
+
var models = D.models.filter(function (m) { return m.acc[key] != null; });
|
| 105 |
+
var ranks = U.rank(models, function (m) { return m.acc[key]; });
|
| 106 |
+
var top = models.filter(function (m) { return ranks.get(m) <= 3; }).sort(function (a, b) { return b.acc[key] - a.acc[key]; });
|
| 107 |
+
var max = 100;
|
| 108 |
+
var ol = h('ol', { class: 'top3' });
|
| 109 |
+
var items = [];
|
| 110 |
+
top.forEach(function (m) {
|
| 111 |
+
var r = ranks.get(m);
|
| 112 |
+
var li = h('li', null,
|
| 113 |
+
h('span', { class: 'medal medal--' + r + ' top3__rank' }, h('span', { class: 'sr-only', text: 'Rank ' }), String(r)),
|
| 114 |
+
h('span', { class: 'top3__name' }, m.name, h('span', { class: 'top3__vendor', text: m.vendor + ' · ' + (m.deployment === 'api' ? 'API' : 'Local') })),
|
| 115 |
+
h('span', { class: 'top3__val', text: U.pct(m.acc[key]) }),
|
| 116 |
+
h('span', { class: 'top3__bar', attrs: { 'aria-hidden': 'true' }, style: { width: (m.acc[key] / max * 100) + '%', background: U.wlVar(key) } }));
|
| 117 |
+
U.hoverTip(li, function () {
|
| 118 |
+
return { title: m.name, rows: [{ label: g.longLabel + ' accuracy', value: U.pct(m.acc[key]) + '%', color: U.css('--wl-' + key) }],
|
| 119 |
+
note: m.vendor + ' · ' + (m.deployment === 'api' ? 'API' : 'Local') + ' · rank ' + r + ' of ' + models.length + ' models (Table 1, audited accuracy)' };
|
| 120 |
+
});
|
| 121 |
+
items.push(li);
|
| 122 |
+
ol.appendChild(li);
|
| 123 |
+
});
|
| 124 |
+
/* one Tab stop for the mini chart; arrow keys move between its bars */
|
| 125 |
+
if (items.length) U.roving(items);
|
| 126 |
+
right.appendChild(ol);
|
| 127 |
+
var locals = models.filter(function (m) { return m.deployment === 'local'; }).sort(function (a, b) { return b.acc[key] - a.acc[key]; });
|
| 128 |
+
if (locals.length) right.appendChild(h('p', { class: 'cd__local' }, 'Best local model: ', h('b', { text: locals[0].shortName }), ' (' + U.pct(locals[0].acc[key]) + ')'));
|
| 129 |
+
grid.appendChild(right);
|
| 130 |
+
box.appendChild(grid);
|
| 131 |
+
|
| 132 |
+
/* example task */
|
| 133 |
+
var exs = D.examples.filter(function (e) { return e.group === key; });
|
| 134 |
+
if (exs.length) {
|
| 135 |
+
var idx = exampleIdx[key] || 0;
|
| 136 |
+
var ex = h('div', { class: 'example' });
|
| 137 |
+
var tabs = h('div', { class: 'example__tabs' }, h('h4', { text: 'Example task from the repo' }));
|
| 138 |
+
var seg = h('div', { class: 'seg', attrs: { role: 'radiogroup', 'aria-label': 'Example task' } });
|
| 139 |
+
tabs.appendChild(seg);
|
| 140 |
+
ex.appendChild(tabs);
|
| 141 |
+
var body = h('div');
|
| 142 |
+
ex.appendChild(body);
|
| 143 |
+
U.seg(seg, exs.map(function (e, i) { return { value: i, label: e.sourceName }; }), idx, function (v) { exampleIdx[key] = v; drawExample(body, exs[v]); });
|
| 144 |
+
drawExample(body, exs[idx]);
|
| 145 |
+
box.appendChild(ex);
|
| 146 |
+
}
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
function drawExample(body, e) {
|
| 150 |
+
body.textContent = '';
|
| 151 |
+
var card = h('div', { class: 'example__card example__card--taped' + (e.imageFile ? ' has-img' : '') });
|
| 152 |
+
if (e.imageFile) {
|
| 153 |
+
var zb = U.zoomable(U.IMG + e.imageFile, e.imageAlt || '', e.imageAlt || '', 'task image for ' + e.id);
|
| 154 |
+
card.appendChild(h('div', { class: 'example__img' }, zb));
|
| 155 |
+
}
|
| 156 |
+
var txt = h('div');
|
| 157 |
+
txt.appendChild(h('p', { class: 'example__prompt', text: e.promptExcerpt, attrs: { lang: /[一-鿿]/.test(e.promptExcerpt) ? 'zh' : null } }));
|
| 158 |
+
if (e.englishGloss) txt.appendChild(h('p', { class: 'example__gloss', text: 'English wording in the paper: “' + e.englishGloss + '”' }));
|
| 159 |
+
/* a translation made for the page (the paper does not give one): labelled as such */
|
| 160 |
+
else if (e.englishTranslation) txt.appendChild(h('p', { class: 'example__gloss', text: 'In English (our translation): “' + e.englishTranslation + '”' }));
|
| 161 |
+
var meta = h('div', { class: 'example__meta' },
|
| 162 |
+
h('span', { class: 'pill pill--soft example__id', text: e.id }),
|
| 163 |
+
h('span', { class: 'pill', text: e.scoring + ' scoring' }),
|
| 164 |
+
h('span', { class: 'pill', text: e.timeoutSeconds + ' s budget' }),
|
| 165 |
+
h('span', { class: 'pill', text: 'artifact: ' + e.artifact }));
|
| 166 |
+
txt.appendChild(meta);
|
| 167 |
+
var notes = [e.excerptNote];
|
| 168 |
+
if (e.paperRef) notes.push(e.paperRef + '.');
|
| 169 |
+
txt.appendChild(h('p', { class: 'example__note', text: notes.join(' ') }));
|
| 170 |
+
card.appendChild(txt);
|
| 171 |
+
body.appendChild(card);
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
/* ---------------- sources ---------------- */
|
| 175 |
+
var chipBtns = {}, segEls = {}, pinned = null;
|
| 176 |
+
function buildSources() {
|
| 177 |
+
U.$('#sources-sub').textContent = D.stats.sources + ' public benchmarks contribute ' + D.stats.tasks + ' tasks. Bar width is the number of tasks each source contributes; color shows its workload group.';
|
| 178 |
+
/* the paper's task-composition sunburst (appendix), opened in the lightbox like the Fig. 1 button */
|
| 179 |
+
var sb = U.fig('fig-sunburst');
|
| 180 |
+
if (sb) {
|
| 181 |
+
var sbBtn = h('button', { class: 'btn btn--sm btn--ghost', attrs: { type: 'button', id: 'sunburst-btn', 'aria-label': 'Paper’s figure: task composition (' + sb.section + '), opens a larger view' } }, U.icon('i-image'), h('span', { text: 'Paper’s figure' }));
|
| 182 |
+
sbBtn.addEventListener('click', function () { U.lightbox(U.IMG + sb.file, sb.alt, sb.caption + ' (' + sb.section + ')'); });
|
| 183 |
+
var btns = U.$('#sources-btns');
|
| 184 |
+
btns.insertBefore(sbBtn, btns.firstChild);
|
| 185 |
+
}
|
| 186 |
+
var lg = U.$('#sources-legend');
|
| 187 |
+
U.GROUPS.forEach(function (g) {
|
| 188 |
+
lg.appendChild(h('span', { class: 'legend__item' }, h('span', { class: 'legend__sw', style: { background: U.wlVar(g.key) } }), g.label));
|
| 189 |
+
});
|
| 190 |
+
var bar = U.$('#compbar');
|
| 191 |
+
D.sources.forEach(function (s) {
|
| 192 |
+
var g = U.group(s.group);
|
| 193 |
+
/* pointer-only view of the composition: the source chips below are the keyboard and
|
| 194 |
+
screen-reader equivalent (same tooltip, same pin action), so the bar is aria-hidden */
|
| 195 |
+
var seg = h('div', { class: 'compbar__seg', style: { background: U.wlVar(s.group), flex: s.count + ' 1 0', 'min-width': '0' } });
|
| 196 |
+
seg.addEventListener('pointermove', function (e) { U.tip.show(srcTip(s), e.clientX, e.clientY, seg); });
|
| 197 |
+
seg.addEventListener('pointerleave', function () { U.tip.hide(seg); });
|
| 198 |
+
seg.addEventListener('pointerenter', function () { hot(s.key, true); });
|
| 199 |
+
seg.addEventListener('pointerleave', function () { hot(s.key, false); });
|
| 200 |
+
seg.addEventListener('click', function () { pin(s.key); });
|
| 201 |
+
segEls[s.key] = seg;
|
| 202 |
+
bar.appendChild(seg);
|
| 203 |
+
});
|
| 204 |
+
var wall = U.$('#chipwall');
|
| 205 |
+
U.GROUPS.forEach(function (g) {
|
| 206 |
+
/* lane title breaks only between "modality · form", never inside a part; the count never splits */
|
| 207 |
+
var title = h('span', { class: 'lane__title' });
|
| 208 |
+
g.longLabel.split(' · ').forEach(function (part, i, arr) { title.appendChild(h('span', { class: 'nowrap', text: part + (i < arr.length - 1 ? ' ·' : '') })); if (i < arr.length - 1) title.appendChild(document.createTextNode(' ')); });
|
| 209 |
+
var lane = h('div', { class: 'lane' }, h('div', { class: 'lane__head' }, h('span', { class: 'legend__sw', style: { background: U.wlVar(g.key) } }), title, h('small', { text: g.count + ' tasks' })));
|
| 210 |
+
var chips = h('div', { class: 'lane__chips' });
|
| 211 |
+
g.sources.forEach(function (k) {
|
| 212 |
+
var s = U.source(k);
|
| 213 |
+
var c = h('button', { class: 'chip', attrs: { type: 'button', 'aria-pressed': 'false', 'aria-controls': 'source-info', 'aria-label': s.name + ', ' + s.count + ' tasks' } }, s.name, h('span', { class: 'chip__n', text: String(s.count) }));
|
| 214 |
+
U.hoverTip(c, function () { return srcTip(s); });
|
| 215 |
+
c.addEventListener('pointerenter', function () { hot(k, true); });
|
| 216 |
+
c.addEventListener('pointerleave', function () { hot(k, false); });
|
| 217 |
+
c.addEventListener('click', function () { pin(k); });
|
| 218 |
+
chipBtns[k] = c;
|
| 219 |
+
chips.appendChild(c);
|
| 220 |
+
});
|
| 221 |
+
lane.appendChild(chips);
|
| 222 |
+
wall.appendChild(lane);
|
| 223 |
+
});
|
| 224 |
+
U.$('#source-info').appendChild(h('p', { class: 'source-info__empty', text: 'select a benchmark to read what it tests' }));
|
| 225 |
+
|
| 226 |
+
/* a named, focusable scroller with the caption above it, like the other table views */
|
| 227 |
+
U.tableView(U.$('#sources-table'), U.table([
|
| 228 |
+
{ label: 'Benchmark', get: function (s) { return s.name; } },
|
| 229 |
+
{ label: 'Capability', get: function (s) { return s.capability; } },
|
| 230 |
+
{ label: '# Tasks', num: true, get: function (s) { return String(s.count); } },
|
| 231 |
+
{ label: 'Group', get: function (s) { return U.group(s.group).label; } },
|
| 232 |
+
{ label: 'Scoring', get: function (s) { return s.scoring; } }
|
| 233 |
+
], D.sources, 'Source benchmarks (Table 11)'));
|
| 234 |
+
}
|
| 235 |
+
function srcTip(s) {
|
| 236 |
+
var g = U.group(s.group);
|
| 237 |
+
return { title: s.name, rows: [
|
| 238 |
+
{ label: 'Tasks', value: String(s.count), color: U.css('--wl-' + s.group) },
|
| 239 |
+
{ label: 'Group', value: g.label },
|
| 240 |
+
{ label: 'Scoring', value: s.scoring }
|
| 241 |
+
], note: s.capability };
|
| 242 |
+
}
|
| 243 |
+
function hot(k, on) {
|
| 244 |
+
if (chipBtns[k]) chipBtns[k].classList.toggle('is-hot', on);
|
| 245 |
+
if (segEls[k]) segEls[k].classList.toggle('is-hot', on);
|
| 246 |
+
}
|
| 247 |
+
function pin(k) {
|
| 248 |
+
pinned = pinned === k ? null : k;
|
| 249 |
+
Object.keys(chipBtns).forEach(function (x) { chipBtns[x].setAttribute('aria-pressed', String(x === pinned)); });
|
| 250 |
+
var box = U.$('#source-info');
|
| 251 |
+
box.textContent = '';
|
| 252 |
+
if (!pinned) { box.appendChild(h('p', { class: 'source-info__empty', text: 'select a benchmark to read what it tests' })); return; }
|
| 253 |
+
var s = U.source(pinned), g = U.group(s.group);
|
| 254 |
+
var cite = s.citation || {};
|
| 255 |
+
box.appendChild(h('div', { class: 'source-info__card' },
|
| 256 |
+
h('h4', { text: s.fullName && s.fullName !== s.name ? s.name + ' — ' + s.fullName : s.name }),
|
| 257 |
+
h('div', { class: 'source-info__meta' },
|
| 258 |
+
h('span', { class: 'pill' }, h('span', { class: 'dot', style: { background: U.wlVar(s.group) } }), g.label),
|
| 259 |
+
h('span', { class: 'pill', text: s.count + ' tasks' }),
|
| 260 |
+
h('span', { class: 'pill', text: s.scoring }),
|
| 261 |
+
h('span', { class: 'pill pill--soft', text: s.capability })),
|
| 262 |
+
h('p', { text: s.description }),
|
| 263 |
+
cite.title ? h('p', { class: 'source-info__cite', text: (cite.text ? cite.text + '. ' : '') + cite.title + (cite.venue ? '. ' + cite.venue : '') }) : null));
|
| 264 |
+
}
|
| 265 |
+
|
| 266 |
+
/* ---------------- explorer ---------------- */
|
| 267 |
+
function buildExplorer() {
|
| 268 |
+
U.$('#explorer-sub').textContent = D.tasks.length + ' tasks · id and name, source, group, scoring, level and time budget';
|
| 269 |
+
var fg = U.$('#f-group'), fs = U.$('#f-source'), fsc = U.$('#f-scoring'), fq = U.$('#f-q');
|
| 270 |
+
fg.appendChild(h('option', { text: 'All groups', attrs: { value: '' } }));
|
| 271 |
+
U.GROUPS.forEach(function (g) { fg.appendChild(h('option', { text: g.label, attrs: { value: g.key } })); });
|
| 272 |
+
fs.appendChild(h('option', { text: 'All sources', attrs: { value: '' } }));
|
| 273 |
+
D.sources.forEach(function (s) { fs.appendChild(h('option', { text: s.name, attrs: { value: s.key } })); });
|
| 274 |
+
fsc.appendChild(h('option', { text: 'All modes', attrs: { value: '' } }));
|
| 275 |
+
['Auto', 'Hybrid', 'Judge'].forEach(function (s) { fsc.appendChild(h('option', { text: s, attrs: { value: s } })); });
|
| 276 |
+
var table = U.$('#task-table');
|
| 277 |
+
table.appendChild(h('caption', { class: 'sr-only', text: 'Task metadata from the repository (no prompts or answers)' }));
|
| 278 |
+
var thead = h('thead', null, h('tr', null,
|
| 279 |
+
h('th', { text: 'Task id · name', attrs: { scope: 'col' } }), h('th', { text: 'Source', attrs: { scope: 'col' } }),
|
| 280 |
+
h('th', { text: 'Group', attrs: { scope: 'col' } }), h('th', { text: 'Scoring', attrs: { scope: 'col' } }),
|
| 281 |
+
h('th', { text: 'Level', attrs: { scope: 'col' } }), h('th', { class: 'num', text: 'Time budget (s)', attrs: { scope: 'col' } })));
|
| 282 |
+
var tb = h('tbody');
|
| 283 |
+
table.appendChild(thead); table.appendChild(tb);
|
| 284 |
+
function draw() {
|
| 285 |
+
var q = fq.value.trim().toLowerCase();
|
| 286 |
+
var rows = D.tasks.filter(function (t) {
|
| 287 |
+
return (!fg.value || t.group === fg.value) && (!fs.value || t.source === fs.value) && (!fsc.value || t.scoring === fsc.value) &&
|
| 288 |
+
(!q || t.id.toLowerCase().indexOf(q) >= 0 || (t.name || '').toLowerCase().indexOf(q) >= 0);
|
| 289 |
+
});
|
| 290 |
+
tb.textContent = '';
|
| 291 |
+
var frag = document.createDocumentFragment();
|
| 292 |
+
rows.forEach(function (t) {
|
| 293 |
+
var g = U.group(t.group);
|
| 294 |
+
frag.appendChild(h('tr', null,
|
| 295 |
+
h('th', { class: 'mono', attrs: { scope: 'row' } }, t.id, t.name ? h('span', { class: 'task-name', text: t.name }) : null),
|
| 296 |
+
h('td', { text: U.source(t.source).name }),
|
| 297 |
+
h('td', null, h('span', { class: 'legend__item' }, h('span', { class: 'legend__sw', style: { background: U.wlVar(t.group), width: '10px', height: '10px' } }), g.label)),
|
| 298 |
+
h('td', { text: t.scoring }),
|
| 299 |
+
h('td', { text: t.level || '—' }),
|
| 300 |
+
h('td', { class: 'num', text: String(t.timeoutSeconds) })));
|
| 301 |
+
});
|
| 302 |
+
tb.appendChild(frag);
|
| 303 |
+
U.$('#explorer-count').textContent = 'Showing ' + rows.length + ' of ' + D.tasks.length + ' tasks';
|
| 304 |
+
}
|
| 305 |
+
[fg, fs, fsc].forEach(function (el) { el.addEventListener('change', draw); });
|
| 306 |
+
fq.addEventListener('input', draw);
|
| 307 |
+
/* the 233-row table is only built the first time the explorer is opened */
|
| 308 |
+
var ex = U.$('#explorer'), built = false;
|
| 309 |
+
function ensure() { if (!built && ex.open) { built = true; draw(); } }
|
| 310 |
+
ex.addEventListener('toggle', ensure);
|
| 311 |
+
ensure();
|
| 312 |
+
}
|
| 313 |
+
|
| 314 |
+
U.initWorkloads = function () {
|
| 315 |
+
buildMatrix();
|
| 316 |
+
select(D.groupOrder[0]);
|
| 317 |
+
buildSources();
|
| 318 |
+
buildExplorer();
|
| 319 |
+
};
|
| 320 |
+
})();
|
index.html
ADDED
|
@@ -0,0 +1,1142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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="color-scheme" content="light">
|
| 7 |
+
<meta name="theme-color" content="#FFF8EC">
|
| 8 |
+
<title>OmniStepBench: Deployment-Aware Agent Evaluation across Modalities and Task Complexity</title>
|
| 9 |
+
<meta name="description" content="OmniStepBench is a benchmark for deployment-aware agent evaluation across modalities and task complexity: 233 tasks from 22 source benchmarks in a 2×3 workload matrix, one shared OpenClaw runtime with task contracts, and an evidence-based audit of LLM-judge scores.">
|
| 10 |
+
<meta name="author" content="Yu Liu, Zhilin Liu, Zhiwei Yang, Shaojie Zhang, Zheyuan Deng, Tingwei Huang, Zhenbo Luo, Lei Jiang, Yanbing Liu, Pei Fu">
|
| 11 |
+
|
| 12 |
+
<!-- Open Graph / social cards. Image URLs are absolute (this Space's static host, see DEPLOY.md). -->
|
| 13 |
+
<meta property="og:type" content="website">
|
| 14 |
+
<meta property="og:site_name" content="OmniStepBench">
|
| 15 |
+
<meta property="og:title" content="OmniStepBench: Deployment-Aware Agent Evaluation across Modalities and Task Complexity">
|
| 16 |
+
<meta property="og:description" content="A benchmark for deployment-aware agent evaluation across modalities and task complexity. No model dominates all six workload groups.">
|
| 17 |
+
<meta property="og:image" content="https://seerray-lab-omnistepbench.static.hf.space/assets/img/social-card.png">
|
| 18 |
+
<meta property="og:image:width" content="1200">
|
| 19 |
+
<meta property="og:image:height" content="630">
|
| 20 |
+
<meta property="og:image:alt" content="OmniStepBench project card with the lobster evaluator mascot">
|
| 21 |
+
<meta name="twitter:card" content="summary_large_image">
|
| 22 |
+
<meta name="twitter:title" content="OmniStepBench: Deployment-Aware Agent Evaluation across Modalities and Task Complexity">
|
| 23 |
+
<meta name="twitter:description" content="A benchmark for deployment-aware agent evaluation across modalities and task complexity.">
|
| 24 |
+
<meta name="twitter:image" content="https://seerray-lab-omnistepbench.static.hf.space/assets/img/social-card.png">
|
| 25 |
+
|
| 26 |
+
<!-- Google Scholar -->
|
| 27 |
+
<meta name="citation_title" content="OmniStepBench: Deployment-Aware Agent Evaluation across Modalities and Task Complexity">
|
| 28 |
+
<meta name="citation_author" content="Liu, Yu">
|
| 29 |
+
<meta name="citation_author" content="Liu, Zhilin">
|
| 30 |
+
<meta name="citation_author" content="Yang, Zhiwei">
|
| 31 |
+
<meta name="citation_author" content="Zhang, Shaojie">
|
| 32 |
+
<meta name="citation_author" content="Deng, Zheyuan">
|
| 33 |
+
<meta name="citation_author" content="Huang, Tingwei">
|
| 34 |
+
<meta name="citation_author" content="Luo, Zhenbo">
|
| 35 |
+
<meta name="citation_author" content="Jiang, Lei">
|
| 36 |
+
<meta name="citation_author" content="Liu, Yanbing">
|
| 37 |
+
<meta name="citation_author" content="Fu, Pei">
|
| 38 |
+
<meta name="citation_publication_date" content="2026/09/05">
|
| 39 |
+
<meta name="citation_arxiv_id" content="2609.06059">
|
| 40 |
+
<meta name="citation_abstract_html_url" content="https://arxiv.org/abs/2609.06059">
|
| 41 |
+
<meta name="citation_pdf_url" content="https://arxiv.org/pdf/2609.06059">
|
| 42 |
+
|
| 43 |
+
<link rel="canonical" href="https://seerray-lab.github.io/OmniStepBench/">
|
| 44 |
+
<link rel="icon" href="assets/img/favicon.svg" type="image/svg+xml">
|
| 45 |
+
<link rel="stylesheet" href="assets/fonts/fonts.css" id="fonts-css">
|
| 46 |
+
<script>
|
| 47 |
+
/* Firefox gives every file:// page its own origin and can refuse web fonts loaded from files.
|
| 48 |
+
Only in that case, swap in the same fonts embedded as data URIs (fonts.inline.css). */
|
| 49 |
+
if (location.protocol === 'file:' && /firefox/i.test(navigator.userAgent)) document.getElementById('fonts-css').href = 'assets/fonts/fonts.inline.css';
|
| 50 |
+
</script>
|
| 51 |
+
<script>
|
| 52 |
+
/* Hugging Face shows this Space inside a sandboxed frame that cannot navigate the whole window, and sites such as
|
| 53 |
+
GitHub refuse to be framed. Only while framed, open links to other sites in a new tab. */
|
| 54 |
+
if (window.self !== window.top) document.addEventListener('click', function (e) {
|
| 55 |
+
var a = e.target && e.target.closest ? e.target.closest('a[href]') : null;
|
| 56 |
+
if (a && /^https?:$/.test(a.protocol) && a.host !== location.host) a.target = '_blank';
|
| 57 |
+
}, true);
|
| 58 |
+
</script>
|
| 59 |
+
<link rel="stylesheet" href="assets/css/palette.css">
|
| 60 |
+
<link rel="stylesheet" href="assets/css/style.css">
|
| 61 |
+
</head>
|
| 62 |
+
<body>
|
| 63 |
+
<a class="skip-link" href="#main">Skip to content</a>
|
| 64 |
+
<svg xmlns="http://www.w3.org/2000/svg" class="sprite" aria-hidden="true" focusable="false" style="position:absolute;width:0;height:0;overflow:hidden">
|
| 65 |
+
<defs>
|
| 66 |
+
<!-- ============ CAMEO CREATURES (viewBox 0 0 120 120) ============ -->
|
| 67 |
+
|
| 68 |
+
<!-- Crab walking in circles: "deadlock loop" -->
|
| 69 |
+
<symbol id="cr-crab" viewBox="0 0 120 120">
|
| 70 |
+
<path d="M60 12 A 48 48 0 1 1 22 30" fill="none" stroke="#7FB8C9" stroke-width="3.5" stroke-linecap="round" stroke-dasharray="2 9"/>
|
| 71 |
+
<path d="M14 22 L 22 31 L 31 24" fill="none" stroke="#1E3450" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
|
| 72 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 73 |
+
<g fill="none" stroke-width="3.5">
|
| 74 |
+
<path d="M36 76 L 24 84 L 22 94"/><path d="M38 84 L 28 94 L 28 102"/>
|
| 75 |
+
<path d="M84 76 L 96 84 L 98 94"/><path d="M82 84 L 92 94 L 92 102"/>
|
| 76 |
+
<path d="M38 66 L 26 56"/><path d="M82 66 L 94 56"/>
|
| 77 |
+
<path d="M52 58 L 48 44"/><path d="M68 58 L 72 44"/>
|
| 78 |
+
</g>
|
| 79 |
+
<ellipse cx="60" cy="74" rx="28" ry="19" fill="#F08A4B" stroke-width="3"/>
|
| 80 |
+
<path d="M44 66 Q 60 58 76 66" fill="none" stroke="#FFFFFF" stroke-width="3" opacity=".5"/>
|
| 81 |
+
<path d="M14 52 C 10 40, 18 32, 27 34 L 25 43 L 33 39 C 36 48, 30 57, 21 58 C 17 58, 15 56, 14 52 Z" fill="#F08A4B" stroke-width="3"/>
|
| 82 |
+
<path d="M106 52 C 110 40, 102 32, 93 34 L 95 43 L 87 39 C 84 48, 90 57, 99 58 C 103 58, 105 56, 106 52 Z" fill="#F08A4B" stroke-width="3"/>
|
| 83 |
+
<circle cx="47" cy="40" r="8" fill="#FFFFFF" stroke-width="3"/>
|
| 84 |
+
<circle cx="73" cy="40" r="8" fill="#FFFFFF" stroke-width="3"/>
|
| 85 |
+
<circle cx="50" cy="42" r="3.4" fill="#1E3450" stroke="none"/>
|
| 86 |
+
<circle cx="76" cy="42" r="3.4" fill="#1E3450" stroke="none"/>
|
| 87 |
+
<path d="M53 80 Q 60 76 67 80" fill="none" stroke-width="3"/>
|
| 88 |
+
<path d="M44 88 Q 47 84 50 88 M 70 88 Q 73 84 76 88" fill="none" stroke-width="2" opacity=".45"/>
|
| 89 |
+
</g>
|
| 90 |
+
</symbol>
|
| 91 |
+
|
| 92 |
+
<!-- Fish peeking at the rubric: "rubric leakage" -->
|
| 93 |
+
<symbol id="cr-fish" viewBox="0 0 120 120">
|
| 94 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 95 |
+
<g transform="rotate(8 92 58)">
|
| 96 |
+
<rect x="74" y="30" width="36" height="46" rx="5" fill="#FFFFFF" stroke-width="3"/>
|
| 97 |
+
<path d="M81 42 L 103 42 M 81 51 L 100 51 M 81 60 L 96 60" fill="none" stroke-width="2.6" opacity=".55"/>
|
| 98 |
+
<path d="M92 67 L 104 67" fill="none" stroke="#7A55C4" stroke-width="3"/>
|
| 99 |
+
</g>
|
| 100 |
+
<path d="M86 82 C 86 88, 92 88, 92 82 C 92 78, 89 76, 89 74 C 89 76, 86 78, 86 82 Z" fill="#9B7BD8" stroke-width="2.2"/>
|
| 101 |
+
<path d="M95 96 C 95 101, 100 101, 100 96 C 100 93, 97.5 91, 97.5 89 C 97.5 91, 95 93, 95 96 Z" fill="#9B7BD8" stroke-width="2.2"/>
|
| 102 |
+
<path d="M22 64 L 4 48 Q 2 64 4 80 Z" fill="#F2B84B" stroke-width="3"/>
|
| 103 |
+
<ellipse cx="44" cy="64" rx="30" ry="23" fill="#FFCF5C" stroke-width="3"/>
|
| 104 |
+
<path d="M36 44 Q 46 30 58 44" fill="#F2B84B" stroke-width="3"/>
|
| 105 |
+
<path d="M30 60 Q 34 66 30 72 M 38 58 Q 42 66 38 74" fill="none" stroke-width="2.2" opacity=".35"/>
|
| 106 |
+
<circle cx="58" cy="58" r="10" fill="#FFFFFF" stroke-width="3"/>
|
| 107 |
+
<circle cx="62" cy="57" r="4.5" fill="#1E3450" stroke="none"/>
|
| 108 |
+
<circle cx="63.5" cy="55" r="1.6" fill="#FFFFFF" stroke="none"/>
|
| 109 |
+
<path d="M66 72 Q 70 74 72 70" fill="none" stroke-width="3"/>
|
| 110 |
+
<path d="M40 84 Q 44 92 50 86" fill="#F2B84B" stroke-width="2.6"/>
|
| 111 |
+
</g>
|
| 112 |
+
</symbol>
|
| 113 |
+
|
| 114 |
+
<!-- Hermit crab in a cardboard "tool" shell: "pseudo-tool-call credulity" -->
|
| 115 |
+
<symbol id="cr-hermit" viewBox="0 0 120 120">
|
| 116 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 117 |
+
<g fill="none" stroke-width="3.2">
|
| 118 |
+
<path d="M42 88 L 34 100"/><path d="M52 90 L 48 102"/><path d="M62 90 L 64 102"/>
|
| 119 |
+
</g>
|
| 120 |
+
<rect x="46" y="30" width="62" height="56" rx="6" fill="#EBC792" stroke-width="3" stroke-dasharray="7 5"/>
|
| 121 |
+
<path d="M46 44 L 108 44" fill="none" stroke-width="2.4" stroke-dasharray="5 5" opacity=".6"/>
|
| 122 |
+
<path d="M68 70 L 86 52 M 82 50 C 84 46, 90 45, 93 48 L 88 53 L 91 56 L 96 51 C 99 54, 98 60, 94 62 M 72 66 C 70 70, 64 72, 62 68 L 67 63 L 64 60 L 59 65 C 56 62, 57 56, 61 54" fill="none" stroke-width="3" stroke-dasharray="5 4"/>
|
| 123 |
+
<path d="M22 86 C 16 70, 26 56, 46 58 L 48 88 Z" fill="#F08A4B" stroke-width="3"/>
|
| 124 |
+
<path d="M30 60 L 26 44 M 40 58 L 40 42" fill="none" stroke-width="3"/>
|
| 125 |
+
<circle cx="25" cy="39" r="7" fill="#FFFFFF" stroke-width="3"/>
|
| 126 |
+
<circle cx="40" cy="37" r="7" fill="#FFFFFF" stroke-width="3"/>
|
| 127 |
+
<circle cx="27" cy="41" r="3" fill="#1E3450" stroke="none"/>
|
| 128 |
+
<circle cx="42" cy="39" r="3" fill="#1E3450" stroke="none"/>
|
| 129 |
+
<path d="M8 78 C 4 68, 10 60, 18 62 L 17 69 L 24 66 C 26 73, 22 80, 15 81 C 11 81, 9 80, 8 78 Z" fill="#F08A4B" stroke-width="3"/>
|
| 130 |
+
<path d="M30 76 Q 34 79 38 76" fill="none" stroke-width="2.6"/>
|
| 131 |
+
</g>
|
| 132 |
+
</symbol>
|
| 133 |
+
|
| 134 |
+
<!-- Wobbly jellyfish: "output instability" -->
|
| 135 |
+
<symbol id="cr-jelly" viewBox="0 0 120 120">
|
| 136 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 137 |
+
<g fill="none" stroke-width="3">
|
| 138 |
+
<path d="M40 66 C 34 76, 46 82, 40 92 C 36 98, 42 104, 40 108"/>
|
| 139 |
+
<path d="M54 68 L 50 78 M 52 84 L 56 94 M 53 100 L 50 108"/>
|
| 140 |
+
<path d="M68 68 C 74 78, 62 84, 68 94 C 72 100, 66 104, 68 110"/>
|
| 141 |
+
<path d="M82 66 L 86 76 M 84 82 L 80 92"/>
|
| 142 |
+
</g>
|
| 143 |
+
<path d="M28 64 C 26 34, 94 30, 94 64 Q 86 70 78 64 Q 70 70 61 64 Q 52 70 44 64 Q 36 70 28 64 Z" fill="#CDB8F5" stroke-width="3"/>
|
| 144 |
+
<path d="M40 44 Q 48 36 58 38" fill="none" stroke="#FFFFFF" stroke-width="4" opacity=".8"/>
|
| 145 |
+
<circle cx="50" cy="54" r="3.4" fill="#1E3450" stroke="none"/>
|
| 146 |
+
<circle cx="72" cy="54" r="3.4" fill="#1E3450" stroke="none"/>
|
| 147 |
+
<path d="M54 60 L 58 57 L 62 61 L 66 57" fill="none" stroke-width="2.6"/>
|
| 148 |
+
<path d="M100 30 L 106 26 M 102 40 L 110 40 M 12 34 L 18 38" fill="none" stroke="#9B7BD8" stroke-width="3"/>
|
| 149 |
+
</g>
|
| 150 |
+
</symbol>
|
| 151 |
+
|
| 152 |
+
<!-- Snail with a clock shell and a gold star: "timeout-with-credit" -->
|
| 153 |
+
<symbol id="cr-snail" viewBox="0 0 120 120">
|
| 154 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 155 |
+
<path d="M10 92 C 10 78, 20 70, 30 70 L 34 70 C 36 82, 46 88, 60 88 L 100 88 C 108 88, 110 96, 102 98 L 18 98 C 12 98, 10 96, 10 92 Z" fill="#9ED3A0" stroke-width="3"/>
|
| 156 |
+
<path d="M22 72 L 16 52 M 30 70 L 30 50" fill="none" stroke-width="3"/>
|
| 157 |
+
<circle cx="16" cy="48" r="5" fill="#FFFFFF" stroke-width="2.6"/>
|
| 158 |
+
<circle cx="30" cy="46" r="5" fill="#FFFFFF" stroke-width="2.6"/>
|
| 159 |
+
<circle cx="17" cy="49" r="2.2" fill="#1E3450" stroke="none"/>
|
| 160 |
+
<circle cx="31" cy="47" r="2.2" fill="#1E3450" stroke="none"/>
|
| 161 |
+
<path d="M18 84 Q 22 87 26 84" fill="none" stroke-width="2.4"/>
|
| 162 |
+
<circle cx="66" cy="60" r="28" fill="#F2B84B" stroke-width="3"/>
|
| 163 |
+
<circle cx="66" cy="60" r="20" fill="#FFFFFF" stroke-width="2.6"/>
|
| 164 |
+
<path d="M66 46 L 66 60 L 76 66" fill="none" stroke-width="3.2"/>
|
| 165 |
+
<path d="M66 42 L 66 44 M 84 60 L 82 60 M 66 78 L 66 76 M 48 60 L 50 60" fill="none" stroke-width="2.6"/>
|
| 166 |
+
<path d="M100 14 L 104 24 L 115 25 L 107 32 L 110 43 L 100 37 L 90 43 L 93 32 L 85 25 L 96 24 Z" fill="#FFD166" stroke-width="2.6"/>
|
| 167 |
+
</g>
|
| 168 |
+
</symbol>
|
| 169 |
+
|
| 170 |
+
<!-- Octopus juggling tools: "shared execution" -->
|
| 171 |
+
<symbol id="cr-octopus" viewBox="0 0 120 130">
|
| 172 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 173 |
+
<path d="M22 24 A 44 30 0 0 1 98 24" fill="none" stroke="#9FC9D6" stroke-width="2.6" stroke-dasharray="2 7"/>
|
| 174 |
+
<g transform="translate(10 18) rotate(-20)">
|
| 175 |
+
<path d="M0 10 L 14 -4 M 12 -8 C 13 -12, 19 -13, 21 -10 L 17 -6 L 20 -3 L 24 -7 C 27 -4, 26 1, 22 3" fill="none" stroke-width="3"/>
|
| 176 |
+
</g>
|
| 177 |
+
<rect x="46" y="2" width="28" height="20" rx="4" fill="#1E3450" stroke-width="2.6"/>
|
| 178 |
+
<path d="M51 9 L 55 12 L 51 15 M 58 16 L 66 16" fill="none" stroke="#FFFFFF" stroke-width="2.4"/>
|
| 179 |
+
<circle cx="100" cy="22" r="11" fill="#BFE9F3" stroke-width="2.6"/>
|
| 180 |
+
<path d="M89 22 L 111 22 M 100 11 C 94 16, 94 28, 100 33 M 100 11 C 106 16, 106 28, 100 33" fill="none" stroke-width="2"/>
|
| 181 |
+
<g fill="#B28BE3" stroke-width="3">
|
| 182 |
+
<path d="M40 92 C 34 104, 22 104, 18 96 C 26 98, 30 92, 32 84 Z"/>
|
| 183 |
+
<path d="M80 92 C 86 104, 98 104, 102 96 C 94 98, 90 92, 88 84 Z"/>
|
| 184 |
+
<path d="M48 96 C 46 110, 40 120, 32 118 C 38 112, 40 104, 40 94 Z"/>
|
| 185 |
+
<path d="M72 96 C 74 110, 80 120, 88 118 C 82 112, 80 104, 80 94 Z"/>
|
| 186 |
+
<path d="M56 98 C 56 112, 54 122, 48 124 C 52 116, 52 108, 50 98 Z"/>
|
| 187 |
+
<path d="M64 98 C 64 112, 66 122, 72 124 C 68 116, 68 108, 70 98 Z"/>
|
| 188 |
+
</g>
|
| 189 |
+
<path d="M34 50 C 20 44, 14 32, 18 24" fill="none" stroke-width="9"/>
|
| 190 |
+
<path d="M34 50 C 20 44, 14 32, 18 24" fill="none" stroke="#B28BE3" stroke-width="4.5"/>
|
| 191 |
+
<path d="M86 50 C 100 44, 106 34, 104 30" fill="none" stroke-width="9"/>
|
| 192 |
+
<path d="M86 50 C 100 44, 106 34, 104 30" fill="none" stroke="#B28BE3" stroke-width="4.5"/>
|
| 193 |
+
<path d="M30 78 C 24 46, 40 30, 60 30 C 80 30, 96 46, 90 78 C 88 92, 32 92, 30 78 Z" fill="#B28BE3" stroke-width="3"/>
|
| 194 |
+
<ellipse cx="46" cy="46" rx="9" ry="5" transform="rotate(-30 46 46)" fill="#FFFFFF" opacity=".45" stroke="none"/>
|
| 195 |
+
<circle cx="50" cy="64" r="7" fill="#FFFFFF" stroke-width="2.6"/>
|
| 196 |
+
<circle cx="70" cy="64" r="7" fill="#FFFFFF" stroke-width="2.6"/>
|
| 197 |
+
<circle cx="51.5" cy="62" r="3.2" fill="#1E3450" stroke="none"/>
|
| 198 |
+
<circle cx="71.5" cy="62" r="3.2" fill="#1E3450" stroke="none"/>
|
| 199 |
+
<path d="M54 76 Q 60 81 66 76" fill="none" stroke-width="2.6"/>
|
| 200 |
+
<ellipse cx="42" cy="74" rx="5" ry="3" fill="#FF9EB5" opacity=".7" stroke="none"/>
|
| 201 |
+
<ellipse cx="78" cy="74" rx="5" ry="3" fill="#FF9EB5" opacity=".7" stroke="none"/>
|
| 202 |
+
</g>
|
| 203 |
+
</symbol>
|
| 204 |
+
|
| 205 |
+
<!-- Treasure chest of task cards: "construct" -->
|
| 206 |
+
<symbol id="ic-chest" viewBox="0 0 120 120">
|
| 207 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 208 |
+
<g transform="rotate(-12 44 40)"><rect x="30" y="18" width="30" height="38" rx="4" fill="#FFFFFF" stroke-width="2.6"/><path d="M36 28 L 54 28 M 36 36 L 50 36" fill="none" stroke-width="2.2" opacity=".5"/></g>
|
| 209 |
+
<g transform="rotate(10 78 38)"><rect x="62" y="14" width="30" height="40" rx="4" fill="#EAF2FD" stroke-width="2.6"/><path d="M68 24 L 86 24 M 68 32 L 82 32" fill="none" stroke-width="2.2" opacity=".5"/></g>
|
| 210 |
+
<rect x="46" y="10" width="30" height="42" rx="4" fill="#FDF0E2" stroke-width="2.6"/>
|
| 211 |
+
<path d="M52 20 L 70 20 M 52 28 L 66 28 M 52 36 L 68 36" fill="none" stroke-width="2.2" opacity=".5"/>
|
| 212 |
+
<path d="M16 56 C 16 42, 104 42, 104 56 L 104 60 L 16 60 Z" fill="#B97A3E" stroke-width="3"/>
|
| 213 |
+
<rect x="16" y="58" width="88" height="46" rx="6" fill="#D9964F" stroke-width="3"/>
|
| 214 |
+
<path d="M16 72 L 104 72" fill="none" stroke-width="2.6" opacity=".5"/>
|
| 215 |
+
<path d="M34 58 L 34 104 M 86 58 L 86 104" fill="none" stroke="#8B5A2B" stroke-width="5"/>
|
| 216 |
+
<rect x="52" y="64" width="16" height="18" rx="4" fill="#F2B84B" stroke-width="2.6"/>
|
| 217 |
+
<circle cx="60" cy="72" r="2.6" fill="#1E3450" stroke="none"/>
|
| 218 |
+
<path d="M104 18 L 104 26 M 100 22 L 108 22 M 14 28 L 14 34 M 11 31 L 17 31" fill="none" stroke="#F2B84B" stroke-width="3"/>
|
| 219 |
+
</g>
|
| 220 |
+
</symbol>
|
| 221 |
+
|
| 222 |
+
<!-- Balance scale with gear (auto) and speech bubble (judge): "score" -->
|
| 223 |
+
<symbol id="ic-scale" viewBox="0 0 120 120">
|
| 224 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 225 |
+
<path d="M60 22 L 60 100" fill="none" stroke-width="4"/>
|
| 226 |
+
<path d="M40 104 L 80 104 C 80 96, 40 96, 40 104 Z" fill="#9AA8B8" stroke-width="3"/>
|
| 227 |
+
<path d="M20 30 L 100 30" fill="none" stroke-width="4"/>
|
| 228 |
+
<circle cx="60" cy="22" r="6" fill="#F2B84B" stroke-width="3"/>
|
| 229 |
+
<path d="M20 30 L 8 64 M 20 30 L 32 64 M 100 30 L 88 64 M 100 30 L 112 64" fill="none" stroke-width="2.4"/>
|
| 230 |
+
<path d="M4 64 L 36 64 C 34 76, 6 76, 4 64 Z" fill="#EAF2FD" stroke-width="3"/>
|
| 231 |
+
<path d="M84 64 L 116 64 C 114 76, 86 76, 84 64 Z" fill="#FDF0E2" stroke-width="3"/>
|
| 232 |
+
<g transform="translate(20 52)"><circle r="7" fill="#9AA8B8" stroke-width="2.6"/><circle r="2.5" fill="#FFFFFF" stroke-width="2"/><path d="M0 -10 L 0 -7 M 0 7 L 0 10 M -10 0 L -7 0 M 7 0 L 10 0 M -7 -7 L -5 -5 M 5 5 L 7 7 M -7 7 L -5 5 M 5 -5 L 7 -7" fill="none" stroke-width="2.6"/></g>
|
| 233 |
+
<path d="M90 44 L 110 44 C 113 44, 114 46, 114 48 L 114 56 C 114 58, 112 60, 110 60 L 98 60 L 93 64 L 94 60 L 90 60 C 88 60, 86 58, 86 56 L 86 48 C 86 46, 88 44, 90 44 Z" fill="#FFFFFF" stroke-width="2.6"/>
|
| 234 |
+
<path d="M92 52 L 108 52" fill="none" stroke-width="2.2" opacity=".6"/>
|
| 235 |
+
</g>
|
| 236 |
+
</symbol>
|
| 237 |
+
|
| 238 |
+
<!-- Report board with bars + frontier curve: "report" -->
|
| 239 |
+
<symbol id="ic-board" viewBox="0 0 120 120">
|
| 240 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 241 |
+
<path d="M60 86 L 60 110" fill="none" stroke="#8B5A2B" stroke-width="7"/>
|
| 242 |
+
<path d="M60 86 L 60 110" fill="none" stroke-width="2" opacity="0"/>
|
| 243 |
+
<path d="M44 112 Q 60 104 76 112" fill="#F2D9A6" stroke-width="3"/>
|
| 244 |
+
<rect x="10" y="14" width="100" height="74" rx="10" fill="#FFFFFF" stroke-width="3"/>
|
| 245 |
+
<path d="M24 74 L 98 74" fill="none" stroke-width="2.4" opacity=".5"/>
|
| 246 |
+
<rect x="28" y="54" width="10" height="20" rx="2" fill="#4A7AE4" stroke-width="2.4"/>
|
| 247 |
+
<rect x="44" y="44" width="10" height="30" rx="2" fill="#CC580B" stroke-width="2.4"/>
|
| 248 |
+
<rect x="60" y="36" width="10" height="38" rx="2" fill="#4A7AE4" stroke-width="2.4"/>
|
| 249 |
+
<rect x="76" y="48" width="10" height="26" rx="2" fill="#CC580B" stroke-width="2.4"/>
|
| 250 |
+
<path d="M26 44 Q 44 30, 60 28 T 96 22" fill="none" stroke="#B51C79" stroke-width="3.4"/>
|
| 251 |
+
<circle cx="60" cy="28" r="3.6" fill="#B51C79" stroke="#FFFFFF" stroke-width="1.6"/>
|
| 252 |
+
<circle cx="96" cy="22" r="3.6" fill="#B51C79" stroke="#FFFFFF" stroke-width="1.6"/>
|
| 253 |
+
</g>
|
| 254 |
+
</symbol>
|
| 255 |
+
|
| 256 |
+
<!-- Fishbowl with three fish: "attributable / shared runtime" -->
|
| 257 |
+
<symbol id="ic-bowl" viewBox="0 0 120 120">
|
| 258 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 259 |
+
<path d="M36 20 L 84 20 L 84 26 C 104 36, 112 58, 104 80 C 96 102, 24 102, 16 80 C 8 58, 16 36, 36 26 Z" fill="#E8F7FB" stroke-width="3"/>
|
| 260 |
+
<path d="M18 56 C 40 50, 80 62, 102 54 C 108 70, 104 84, 96 92 C 80 104, 40 104, 24 92 C 16 84, 12 70, 18 56 Z" fill="#BFE6EF" stroke="none"/>
|
| 261 |
+
<path d="M36 20 L 84 20 L 84 26 C 104 36, 112 58, 104 80 C 96 102, 24 102, 16 80 C 8 58, 16 36, 36 26 Z" fill="none" stroke-width="3"/>
|
| 262 |
+
<path d="M30 40 Q 26 50 28 60" fill="none" stroke="#FFFFFF" stroke-width="4" opacity=".9"/>
|
| 263 |
+
<g transform="translate(40 66)"><path d="M-12 0 L -18 -6 L -18 6 Z" fill="#F08A4B" stroke-width="2.2"/><ellipse rx="10" ry="7" fill="#F08A4B" stroke-width="2.4"/><circle cx="4" cy="-1" r="1.8" fill="#1E3450" stroke="none"/></g>
|
| 264 |
+
<g transform="translate(76 60) scale(-1 1)"><path d="M-12 0 L -18 -6 L -18 6 Z" fill="#FFCF5C" stroke-width="2.2"/><ellipse rx="10" ry="7" fill="#FFCF5C" stroke-width="2.4"/><circle cx="4" cy="-1" r="1.8" fill="#1E3450" stroke="none"/></g>
|
| 265 |
+
<g transform="translate(62 84)"><path d="M-12 0 L -18 -6 L -18 6 Z" fill="#B28BE3" stroke-width="2.2"/><ellipse rx="10" ry="7" fill="#B28BE3" stroke-width="2.4"/><circle cx="4" cy="-1" r="1.8" fill="#1E3450" stroke="none"/></g>
|
| 266 |
+
<circle cx="86" cy="42" r="3" fill="#FFFFFF" stroke-width="1.8"/>
|
| 267 |
+
<circle cx="92" cy="32" r="2" fill="#FFFFFF" stroke-width="1.6"/>
|
| 268 |
+
</g>
|
| 269 |
+
</symbol>
|
| 270 |
+
|
| 271 |
+
<!-- Grid under a magnifier: "interpretable" -->
|
| 272 |
+
<symbol id="ic-grid" viewBox="0 0 120 120">
|
| 273 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 274 |
+
<rect x="8" y="22" width="26" height="26" rx="6" fill="#18B6F2" stroke-width="2.6"/>
|
| 275 |
+
<rect x="38" y="22" width="26" height="26" rx="6" fill="#4A7AE4" stroke-width="2.6"/>
|
| 276 |
+
<rect x="68" y="22" width="26" height="26" rx="6" fill="#2C45AE" stroke-width="2.6"/>
|
| 277 |
+
<rect x="8" y="52" width="26" height="26" rx="6" fill="#E29805" stroke-width="2.6"/>
|
| 278 |
+
<rect x="38" y="52" width="26" height="26" rx="6" fill="#CC580B" stroke-width="2.6"/>
|
| 279 |
+
<rect x="68" y="52" width="26" height="26" rx="6" fill="#922B01" stroke-width="2.6"/>
|
| 280 |
+
<path d="M86 88 L 108 110" fill="none" stroke-width="11"/>
|
| 281 |
+
<path d="M86 88 L 108 110" fill="none" stroke="#8B5A2B" stroke-width="6"/>
|
| 282 |
+
<circle cx="72" cy="72" r="24" fill="#F2B84B" stroke-width="3"/>
|
| 283 |
+
<circle cx="72" cy="72" r="17" fill="#EAF7FB" fill-opacity=".85" stroke-width="2.6"/>
|
| 284 |
+
<path d="M62 66 Q 64 60 70 58" fill="none" stroke="#FFFFFF" stroke-width="3.4"/>
|
| 285 |
+
</g>
|
| 286 |
+
</symbol>
|
| 287 |
+
|
| 288 |
+
<!-- Shield with check and tiny magnifier: "trustworthy" -->
|
| 289 |
+
<symbol id="ic-shield" viewBox="0 0 120 120">
|
| 290 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 291 |
+
<path d="M56 10 C 70 20, 84 22, 98 20 C 100 58, 90 90, 56 108 C 22 90, 12 58, 14 20 C 28 22, 42 20, 56 10 Z" fill="#DCEFD8" stroke-width="3"/>
|
| 292 |
+
<path d="M56 20 C 66 27, 78 30, 89 29 C 89 58, 80 82, 56 97 Z" fill="#B9DFB1" stroke="none"/>
|
| 293 |
+
<path d="M36 58 L 50 72 L 78 42" fill="none" stroke="#2E7D46" stroke-width="7"/>
|
| 294 |
+
<path d="M96 96 L 110 110" fill="none" stroke-width="8"/>
|
| 295 |
+
<path d="M96 96 L 110 110" fill="none" stroke="#8B5A2B" stroke-width="4"/>
|
| 296 |
+
<circle cx="88" cy="88" r="13" fill="#F2B84B" stroke-width="2.6"/>
|
| 297 |
+
<circle cx="88" cy="88" r="8" fill="#EAF7FB" stroke-width="2.2"/>
|
| 298 |
+
</g>
|
| 299 |
+
</symbol>
|
| 300 |
+
|
| 301 |
+
<!-- Clam with a pearl: "cite" -->
|
| 302 |
+
<symbol id="ic-clam" viewBox="0 0 120 120">
|
| 303 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 304 |
+
<path d="M14 70 C 14 40, 106 40, 106 70 Z" fill="#F7B7A6" stroke-width="3" transform="rotate(-14 60 70)"/>
|
| 305 |
+
<path d="M40 60 L 44 44 M 60 56 L 60 38 M 80 60 L 76 44" fill="none" stroke-width="2.4" opacity=".45" transform="rotate(-14 60 70)"/>
|
| 306 |
+
<path d="M12 72 L 108 72 C 108 100, 12 100, 12 72 Z" fill="#F4A08C" stroke-width="3"/>
|
| 307 |
+
<path d="M36 76 L 38 92 M 60 76 L 60 96 M 84 76 L 82 92" fill="none" stroke-width="2.4" opacity=".45"/>
|
| 308 |
+
<circle cx="60" cy="66" r="12" fill="#FFFFFF" stroke-width="3"/>
|
| 309 |
+
<circle cx="56" cy="62" r="3.6" fill="#EAF2FD" stroke="none"/>
|
| 310 |
+
<path d="M98 30 L 98 38 M 94 34 L 102 34" fill="none" stroke="#F2B84B" stroke-width="3"/>
|
| 311 |
+
</g>
|
| 312 |
+
</symbol>
|
| 313 |
+
|
| 314 |
+
<!-- Terminal with bubbles: "quick start" -->
|
| 315 |
+
<symbol id="ic-terminal" viewBox="0 0 120 120">
|
| 316 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 317 |
+
<rect x="10" y="26" width="92" height="70" rx="10" fill="#14293F" stroke-width="3"/>
|
| 318 |
+
<path d="M10 40 L 102 40" fill="none" stroke="#3A4F66" stroke-width="3"/>
|
| 319 |
+
<circle cx="20" cy="33" r="2.6" fill="#EC624A" stroke="none"/>
|
| 320 |
+
<circle cx="29" cy="33" r="2.6" fill="#F2B84B" stroke="none"/>
|
| 321 |
+
<circle cx="38" cy="33" r="2.6" fill="#7BC47F" stroke="none"/>
|
| 322 |
+
<path d="M24 56 L 34 64 L 24 72" fill="none" stroke="#7FE0E0" stroke-width="4"/>
|
| 323 |
+
<path d="M42 74 L 62 74" fill="none" stroke="#FFFFFF" stroke-width="4"/>
|
| 324 |
+
<circle cx="104" cy="16" r="6" fill="#FFFFFF" stroke-width="2.4"/>
|
| 325 |
+
<circle cx="112" cy="30" r="3.6" fill="#FFFFFF" stroke-width="2"/>
|
| 326 |
+
</g>
|
| 327 |
+
</symbol>
|
| 328 |
+
|
| 329 |
+
<!-- ============ DECOR ============ -->
|
| 330 |
+
<symbol id="dc-star" viewBox="0 0 60 60">
|
| 331 |
+
<path d="M30 4 C 33 16, 36 20, 56 22 C 42 30, 40 34, 46 54 C 36 44, 30 42, 16 54 C 20 38, 18 32, 4 22 C 22 22, 26 16, 30 4 Z" fill="#F7A072" stroke="#1E3450" stroke-width="2.6" stroke-linejoin="round"/>
|
| 332 |
+
<circle cx="30" cy="30" r="2" fill="#1E3450"/><circle cx="24" cy="26" r="1.5" fill="#FFFFFF" opacity=".8"/><circle cx="36" cy="36" r="1.5" fill="#FFFFFF" opacity=".8"/>
|
| 333 |
+
</symbol>
|
| 334 |
+
<symbol id="dc-shell" viewBox="0 0 60 60">
|
| 335 |
+
<path d="M30 8 C 50 10, 58 34, 52 48 L 8 48 C 2 34, 10 10, 30 8 Z" fill="#FBD3C4" stroke="#1E3450" stroke-width="2.6" stroke-linejoin="round"/>
|
| 336 |
+
<path d="M30 12 L 30 48 M 18 16 L 22 48 M 42 16 L 38 48 M 10 28 L 16 48 M 50 28 L 44 48" fill="none" stroke="#1E3450" stroke-width="2" opacity=".4" stroke-linecap="round"/>
|
| 337 |
+
<path d="M22 48 L 26 56 L 34 56 L 38 48" fill="#FBD3C4" stroke="#1E3450" stroke-width="2.6" stroke-linejoin="round"/>
|
| 338 |
+
</symbol>
|
| 339 |
+
<symbol id="dc-weed" viewBox="0 0 60 200">
|
| 340 |
+
<path d="M30 200 C 20 170, 42 150, 30 120 C 18 90, 42 70, 30 40 C 24 24, 30 10, 34 2" fill="none" stroke="#1E3450" stroke-width="13" stroke-linecap="round"/>
|
| 341 |
+
<path d="M30 200 C 20 170, 42 150, 30 120 C 18 90, 42 70, 30 40 C 24 24, 30 10, 34 2" fill="none" stroke="#4E9F63" stroke-width="8" stroke-linecap="round"/>
|
| 342 |
+
<path d="M31 150 C 44 142, 52 130, 50 118 M 29 96 C 16 88, 8 76, 10 64" fill="none" stroke="#1E3450" stroke-width="9" stroke-linecap="round"/>
|
| 343 |
+
<path d="M31 150 C 44 142, 52 130, 50 118 M 29 96 C 16 88, 8 76, 10 64" fill="none" stroke="#6BBF7A" stroke-width="4.5" stroke-linecap="round"/>
|
| 344 |
+
</symbol>
|
| 345 |
+
<symbol id="dc-fish" viewBox="0 0 60 40">
|
| 346 |
+
<path d="M14 20 L 2 10 L 3 30 Z" fill="#FFCF5C" stroke="#1E3450" stroke-width="2.4" stroke-linejoin="round"/>
|
| 347 |
+
<ellipse cx="32" cy="20" rx="20" ry="13" fill="#FFCF5C" stroke="#1E3450" stroke-width="2.4"/>
|
| 348 |
+
<path d="M26 10 Q 32 4 38 10" fill="#F2B84B" stroke="#1E3450" stroke-width="2.2"/>
|
| 349 |
+
<circle cx="42" cy="17" r="3.4" fill="#1E3450"/><circle cx="43" cy="16" r="1.2" fill="#FFFFFF"/>
|
| 350 |
+
<path d="M22 14 Q 25 20 22 26" fill="none" stroke="#1E3450" stroke-width="1.8" opacity=".4"/>
|
| 351 |
+
</symbol>
|
| 352 |
+
|
| 353 |
+
<!-- Logo: lobster face in a bubble -->
|
| 354 |
+
<symbol id="logo" viewBox="0 0 64 64">
|
| 355 |
+
<circle cx="32" cy="32" r="30" fill="#DDF3F8" stroke="#1E3450" stroke-width="2.5"/>
|
| 356 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 357 |
+
<path d="M27 24 C 24 14, 18 10, 12 10 M 37 24 C 40 14, 46 10, 52 10" fill="none" stroke-width="2.4"/>
|
| 358 |
+
<path d="M10 38 C 6 30, 10 22, 16 22 L 17 29 L 21 23 C 26 26, 26 34, 22 38 C 18 42, 12 42, 10 38 Z" fill="#EC624A" stroke-width="2.2"/>
|
| 359 |
+
<path d="M54 38 C 58 30, 54 22, 48 22 L 47 29 L 43 23 C 38 26, 38 34, 42 38 C 46 42, 52 42, 54 38 Z" fill="#EC624A" stroke-width="2.2"/>
|
| 360 |
+
<path d="M32 26 C 44 26, 46 36, 46 42 C 46 52, 40 56, 32 56 C 24 56, 18 52, 18 42 C 18 36, 20 26, 32 26 Z" fill="#EC624A" stroke-width="2.4"/>
|
| 361 |
+
<circle cx="26" cy="22" r="6" fill="#FFFFFF" stroke-width="2.2"/>
|
| 362 |
+
<circle cx="38" cy="22" r="6" fill="#FFFFFF" stroke-width="2.2"/>
|
| 363 |
+
<circle cx="27.5" cy="23" r="2.6" fill="#1E3450" stroke="none"/>
|
| 364 |
+
<circle cx="39.5" cy="23" r="2.6" fill="#1E3450" stroke="none"/>
|
| 365 |
+
<path d="M27 42 Q 32 47 37 42" fill="none" stroke-width="2.2"/>
|
| 366 |
+
</g>
|
| 367 |
+
</symbol>
|
| 368 |
+
|
| 369 |
+
<!-- ============ UI ICONS (24x24 line, currentColor) ============ -->
|
| 370 |
+
<symbol id="i-arrow" viewBox="0 0 24 24"><path d="M5 12h14M13 6l6 6-6 6" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
| 371 |
+
<symbol id="i-down" viewBox="0 0 24 24"><path d="M12 5v14M6 13l6 6 6-6" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
| 372 |
+
<symbol id="i-paper" viewBox="0 0 24 24"><path d="M7 3h7l5 5v12a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/><path d="M14 3v5h5M9 13h6M9 17h6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></symbol>
|
| 373 |
+
<symbol id="i-pdf" viewBox="0 0 24 24"><path d="M7 3h7l5 5v12a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/><path d="M12 10v7M9 14l3 3 3-3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
| 374 |
+
<symbol id="i-code" viewBox="0 0 24 24"><path d="M8 7l-5 5 5 5M16 7l5 5-5 5M14 4l-4 16" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
| 375 |
+
<symbol id="i-github" viewBox="0 0 24 24"><path d="M12 2a10 10 0 0 0-3.2 19.5c.5.1.7-.2.7-.5v-1.7c-2.8.6-3.4-1.3-3.4-1.3-.5-1.2-1.1-1.5-1.1-1.5-.9-.6.1-.6.1-.6 1 .1 1.5 1 1.5 1 .9 1.5 2.4 1.1 3 .8.1-.6.4-1.1.6-1.3-2.2-.3-4.6-1.1-4.6-5 0-1.1.4-2 1-2.7-.1-.3-.4-1.3.1-2.7 0 0 .8-.3 2.8 1a9.6 9.6 0 0 1 5 0c1.9-1.3 2.8-1 2.8-1 .5 1.4.2 2.4.1 2.7.6.7 1 1.6 1 2.7 0 3.9-2.4 4.7-4.6 5 .4.3.7.9.7 1.9V21c0 .3.2.6.7.5A10 10 0 0 0 12 2z" fill="currentColor"/></symbol>
|
| 376 |
+
<symbol id="i-data" viewBox="0 0 24 24"><ellipse cx="12" cy="6" rx="7" ry="3" fill="none" stroke="currentColor" stroke-width="2"/><path d="M5 6v12c0 1.66 3.13 3 7 3s7-1.34 7-3V6M5 12c0 1.66 3.13 3 7 3s7-1.34 7-3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
| 377 |
+
<symbol id="i-trophy" viewBox="0 0 24 24"><path d="M8 4h8v5a4 4 0 0 1-8 0V4zM8 6H5a3 3 0 0 0 3 4M16 6h3a3 3 0 0 1-3 4M12 13v4M8 20h8M9 17h6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
| 378 |
+
<symbol id="i-quote" viewBox="0 0 24 24"><path d="M6 17c-1.5 0-3-1.2-3-3.5C3 9 6 6.5 9 6l.5 1.2C7.5 8 6.5 9.5 6.5 11c2 0 3.5 1.2 3.5 3s-1.7 3-4 3zm10 0c-1.5 0-3-1.2-3-3.5C13 9 16 6.5 19 6l.5 1.2c-2 .8-3 2.3-3 3.8 2 0 3.5 1.2 3.5 3s-1.7 3-4 3z" fill="currentColor"/></symbol>
|
| 379 |
+
<symbol id="i-copy" viewBox="0 0 24 24"><rect x="8" y="8" width="12" height="12" rx="2.5" fill="none" stroke="currentColor" stroke-width="2"/><path d="M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2" fill="none" stroke="currentColor" stroke-width="2"/></symbol>
|
| 380 |
+
<symbol id="i-check" viewBox="0 0 24 24"><path d="M5 12.5l4.5 4.5L19 7.5" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
| 381 |
+
<symbol id="i-table" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="16" rx="2.5" fill="none" stroke="currentColor" stroke-width="2"/><path d="M3 9.5h18M3 15h18M9 4v16" fill="none" stroke="currentColor" stroke-width="2"/></symbol>
|
| 382 |
+
<symbol id="i-chart" viewBox="0 0 24 24"><path d="M4 20V4M4 20h16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><circle cx="9" cy="14" r="1.8" fill="currentColor"/><circle cx="13" cy="10" r="1.8" fill="currentColor"/><circle cx="18" cy="7" r="1.8" fill="currentColor"/></symbol>
|
| 383 |
+
<symbol id="i-close" viewBox="0 0 24 24"><path d="M6 6l12 12M18 6L6 18" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"/></symbol>
|
| 384 |
+
<symbol id="i-menu" viewBox="0 0 24 24"><path d="M4 7h16M4 12h16M4 17h16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"/></symbol>
|
| 385 |
+
<symbol id="i-zoom" viewBox="0 0 24 24"><circle cx="10.5" cy="10.5" r="6.5" fill="none" stroke="currentColor" stroke-width="2.2"/><path d="M15.5 15.5L20 20M10.5 7.5v6M7.5 10.5h6" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></symbol>
|
| 386 |
+
<symbol id="i-crown" viewBox="0 0 24 24"><path d="M3 8l4.5 4L12 5l4.5 7L21 8l-2 11H5L3 8z" fill="currentColor" stroke="#1E3450" stroke-width="1.6" stroke-linejoin="round"/></symbol>
|
| 387 |
+
<symbol id="i-info" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="2"/><path d="M12 11v6M12 7.5v.5" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"/></symbol>
|
| 388 |
+
<symbol id="i-gear" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3.2" fill="none" stroke="currentColor" stroke-width="2"/><path d="M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M5.6 18.4l2.1-2.1M16.3 7.7l2.1-2.1" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></symbol>
|
| 389 |
+
<symbol id="i-bubble" viewBox="0 0 24 24"><path d="M5 5h14a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-8l-4 3v-3H5a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></symbol>
|
| 390 |
+
<symbol id="i-mix" viewBox="0 0 24 24"><circle cx="8" cy="12" r="5" fill="none" stroke="currentColor" stroke-width="2"/><circle cx="16" cy="12" r="5" fill="none" stroke="currentColor" stroke-width="2"/></symbol>
|
| 391 |
+
<symbol id="i-server" viewBox="0 0 24 24"><rect x="4" y="4" width="16" height="7" rx="2" fill="none" stroke="currentColor" stroke-width="2"/><rect x="4" y="13" width="16" height="7" rx="2" fill="none" stroke="currentColor" stroke-width="2"/><path d="M8 7.5h.01M8 16.5h.01" stroke="currentColor" stroke-width="3" stroke-linecap="round"/></symbol>
|
| 392 |
+
<symbol id="i-cloud" viewBox="0 0 24 24"><path d="M7 18a4 4 0 0 1-.5-8A6 6 0 0 1 18 9a4.5 4.5 0 0 1-.5 9H7z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></symbol>
|
| 393 |
+
<symbol id="i-coins" viewBox="0 0 24 24"><ellipse cx="9" cy="7" rx="6" ry="3" fill="none" stroke="currentColor" stroke-width="2"/><path d="M3 7v5c0 1.7 2.7 3 6 3s6-1.3 6-3V7M9 15v2.5c0 1.4 2.7 2.5 6 2.5s6-1.1 6-2.5V12c0-1.4-2.7-2.5-6-2.5" fill="none" stroke="currentColor" stroke-width="2"/></symbol>
|
| 394 |
+
<symbol id="i-frontier" viewBox="0 0 24 24"><path d="M3 21h18M3 21V3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><path d="M6 15l5-6 4-2 5-1" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/><circle cx="6" cy="15" r="1.8" fill="currentColor"/><circle cx="11" cy="9" r="1.8" fill="currentColor"/><circle cx="20" cy="6" r="1.8" fill="currentColor"/></symbol>
|
| 395 |
+
<symbol id="i-eye" viewBox="0 0 24 24"><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/><circle cx="12" cy="12" r="3" fill="none" stroke="currentColor" stroke-width="2"/></symbol>
|
| 396 |
+
<symbol id="i-loop" viewBox="0 0 24 24"><path d="M20 12a8 8 0 1 1-2.3-5.7M20 4v5h-5" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
| 397 |
+
<symbol id="i-sprout" viewBox="0 0 24 24"><path d="M12 21V11M12 11C12 7 9 5 5 5c0 4 3 6 7 6zM12 13c0-4 3-6 7-6 0 4-3 6-7 6z" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
| 398 |
+
<symbol id="i-compass" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="2"/><path d="M15.5 8.5l-2 5-5 2 2-5 5-2z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></symbol>
|
| 399 |
+
<symbol id="i-token" viewBox="0 0 24 24"><rect x="4" y="4" width="7" height="7" rx="2" fill="none" stroke="currentColor" stroke-width="2"/><rect x="13" y="4" width="7" height="7" rx="2" fill="none" stroke="currentColor" stroke-width="2"/><rect x="4" y="13" width="7" height="7" rx="2" fill="none" stroke="currentColor" stroke-width="2"/></symbol>
|
| 400 |
+
<symbol id="i-search" viewBox="0 0 24 24"><circle cx="10.5" cy="10.5" r="6.5" fill="none" stroke="currentColor" stroke-width="2.2"/><path d="M15.5 15.5L20 20" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></symbol>
|
| 401 |
+
|
| 402 |
+
<!-- ============ NEW (final page) ============ -->
|
| 403 |
+
<!-- Mascot peeking over a card edge. The flat bottom of the head sits on y=92 (the card's top edge);
|
| 404 |
+
the claws hang over the edge. viewBox 0 0 160 104 -->
|
| 405 |
+
<symbol id="mascot-peek" viewBox="0 0 160 104">
|
| 406 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 407 |
+
<path d="M70 58 C 62 34, 46 16, 22 10 C 12 8, 8 16, 14 20" fill="none" stroke-width="7"/>
|
| 408 |
+
<path d="M70 58 C 62 34, 46 16, 22 10 C 12 8, 8 16, 14 20" fill="none" stroke="#D9533B" stroke-width="3.2"/>
|
| 409 |
+
<path d="M90 58 C 98 34, 114 16, 138 10 C 148 8, 152 16, 146 20" fill="none" stroke-width="7"/>
|
| 410 |
+
<path d="M90 58 C 98 34, 114 16, 138 10 C 148 8, 152 16, 146 20" fill="none" stroke="#D9533B" stroke-width="3.2"/>
|
| 411 |
+
<path d="M34 92 C 34 50, 126 50, 126 92 Z" fill="#EC624A" stroke-width="3"/>
|
| 412 |
+
<ellipse cx="62" cy="66" rx="12" ry="6" transform="rotate(-24 62 66)" fill="#FFFFFF" opacity=".35" stroke="none"/>
|
| 413 |
+
<path d="M68 60 L 62 40" fill="none" stroke-width="11"/>
|
| 414 |
+
<path d="M68 60 L 62 40" fill="none" stroke="#EC624A" stroke-width="6"/>
|
| 415 |
+
<path d="M92 60 L 98 40" fill="none" stroke-width="11"/>
|
| 416 |
+
<path d="M92 60 L 98 40" fill="none" stroke="#EC624A" stroke-width="6"/>
|
| 417 |
+
<circle cx="60" cy="31" r="15" fill="#FFFFFF" stroke-width="3"/>
|
| 418 |
+
<circle cx="100" cy="31" r="15" fill="#FFFFFF" stroke-width="3"/>
|
| 419 |
+
<circle cx="62" cy="37" r="7" fill="#1E3450" stroke="none"/>
|
| 420 |
+
<circle cx="102" cy="37" r="7" fill="#1E3450" stroke="none"/>
|
| 421 |
+
<circle cx="64.5" cy="34" r="2.4" fill="#FFFFFF" stroke="none"/>
|
| 422 |
+
<circle cx="104.5" cy="34" r="2.4" fill="#FFFFFF" stroke="none"/>
|
| 423 |
+
<path d="M46 14 Q 56 9, 68 13 M 92 13 Q 104 9, 114 14" fill="none" stroke-width="2.6"/>
|
| 424 |
+
<ellipse cx="54" cy="82" rx="8" ry="4.5" fill="#FF8A8A" opacity=".8" stroke="none"/>
|
| 425 |
+
<ellipse cx="106" cy="82" rx="8" ry="4.5" fill="#FF8A8A" opacity=".8" stroke="none"/>
|
| 426 |
+
<path d="M72 80 Q 80 87 88 80" fill="none" stroke-width="2.6"/>
|
| 427 |
+
<path d="M8 102 C 2 90, 8 78, 18 76 L 20 86 L 26 77 C 36 80, 38 92, 32 100 C 26 107, 12 108, 8 102 Z" fill="#EC624A" stroke-width="3"/>
|
| 428 |
+
<path d="M152 102 C 158 90, 152 78, 142 76 L 140 86 L 134 77 C 124 80, 122 92, 128 100 C 134 107, 148 108, 152 102 Z" fill="#EC624A" stroke-width="3"/>
|
| 429 |
+
</g>
|
| 430 |
+
</symbol>
|
| 431 |
+
|
| 432 |
+
<!-- Narrator bust (head + bow tie) for speech bubbles. viewBox 0 0 120 120 -->
|
| 433 |
+
<symbol id="mascot-bust" viewBox="0 0 120 120">
|
| 434 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 435 |
+
<path d="M50 46 C 44 26, 32 14, 16 10 C 8 8, 4 14, 9 18" fill="none" stroke-width="6.5"/>
|
| 436 |
+
<path d="M50 46 C 44 26, 32 14, 16 10 C 8 8, 4 14, 9 18" fill="none" stroke="#D9533B" stroke-width="3"/>
|
| 437 |
+
<path d="M70 46 C 76 26, 88 14, 104 10 C 112 8, 116 14, 111 18" fill="none" stroke-width="6.5"/>
|
| 438 |
+
<path d="M70 46 C 76 26, 88 14, 104 10 C 112 8, 116 14, 111 18" fill="none" stroke="#D9533B" stroke-width="3"/>
|
| 439 |
+
<path d="M60 44 C 90 44, 102 66, 102 86 C 102 106, 84 116, 60 116 C 36 116, 18 106, 18 86 C 18 66, 30 44, 60 44 Z" fill="#EC624A" stroke-width="3"/>
|
| 440 |
+
<ellipse cx="42" cy="64" rx="10" ry="5" transform="rotate(-28 42 64)" fill="#FFFFFF" opacity=".35" stroke="none"/>
|
| 441 |
+
<path d="M52 50 L 48 34 M 68 50 L 72 34" fill="none" stroke-width="9"/>
|
| 442 |
+
<path d="M52 50 L 48 34 M 68 50 L 72 34" fill="none" stroke="#EC624A" stroke-width="4.5"/>
|
| 443 |
+
<circle cx="46" cy="27" r="12" fill="#FFFFFF" stroke-width="2.8"/>
|
| 444 |
+
<circle cx="74" cy="27" r="12" fill="#FFFFFF" stroke-width="2.8"/>
|
| 445 |
+
<circle cx="49" cy="29" r="5.5" fill="#1E3450" stroke="none"/>
|
| 446 |
+
<circle cx="77" cy="29" r="5.5" fill="#1E3450" stroke="none"/>
|
| 447 |
+
<circle cx="51" cy="26.5" r="1.9" fill="#FFFFFF" stroke="none"/>
|
| 448 |
+
<circle cx="79" cy="26.5" r="1.9" fill="#FFFFFF" stroke="none"/>
|
| 449 |
+
<ellipse cx="38" cy="80" rx="7" ry="4" fill="#FF8A8A" opacity=".8" stroke="none"/>
|
| 450 |
+
<ellipse cx="82" cy="80" rx="7" ry="4" fill="#FF8A8A" opacity=".8" stroke="none"/>
|
| 451 |
+
<path d="M50 76 Q 60 88 70 76 Q 60 81 50 76 Z" fill="#7A2A1C" stroke-width="2.4"/>
|
| 452 |
+
<path d="M60 100 L 46 93 Q 42 100 46 107 Z" fill="#7A55C4" stroke-width="2.4"/>
|
| 453 |
+
<path d="M60 100 L 74 93 Q 78 100 74 107 Z" fill="#7A55C4" stroke-width="2.4"/>
|
| 454 |
+
<rect x="55" y="95" width="10" height="10" rx="3" fill="#5E3FA3" stroke-width="2.4"/>
|
| 455 |
+
</g>
|
| 456 |
+
</symbol>
|
| 457 |
+
|
| 458 |
+
<!-- Small UI glyphs -->
|
| 459 |
+
<symbol id="i-star" viewBox="0 0 24 24"><path d="M12 2.8l2.7 5.6 6.1.9-4.4 4.3 1 6.1L12 16.8l-5.4 2.9 1-6.1-4.4-4.3 6.1-.9z" fill="currentColor" stroke="#1E3450" stroke-width="1.5" stroke-linejoin="round"/></symbol>
|
| 460 |
+
<symbol id="i-wrench" viewBox="0 0 24 24"><path d="M14.5 5.5a4 4 0 0 0 4.9 4.9l-9 9a2 2 0 0 1-2.8-2.8l9-9a4 4 0 0 0-4.9-4.9l2.3 2.3-.5 2.2-2.2.5z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></symbol>
|
| 461 |
+
<symbol id="i-globe" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="2"/><path d="M3 12h18M12 3c3 3.2 3 14.8 0 18M12 3c-3 3.2-3 14.8 0 18" fill="none" stroke="currentColor" stroke-width="2"/></symbol>
|
| 462 |
+
<symbol id="i-sort" viewBox="0 0 24 24"><path d="M7 4v16M7 20l-3-3M7 20l3-3M17 20V4M17 4l-3 3M17 4l3 3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
| 463 |
+
<symbol id="i-pause" viewBox="0 0 24 24"><path d="M8 5v14M16 5v14" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"/></symbol>
|
| 464 |
+
<symbol id="i-play" viewBox="0 0 24 24"><path d="M8 5.5v13l10.5-6.5z" fill="currentColor" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/></symbol>
|
| 465 |
+
<symbol id="i-image" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="16" rx="2.5" fill="none" stroke="currentColor" stroke-width="2"/><circle cx="9" cy="10" r="2" fill="currentColor"/><path d="M4 18l5-5 4 4 3-3 4 4" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></symbol>
|
| 466 |
+
</defs>
|
| 467 |
+
</svg>
|
| 468 |
+
|
| 469 |
+
|
| 470 |
+
<header class="nav" id="top">
|
| 471 |
+
<div class="nav__inner wrap">
|
| 472 |
+
<a class="nav__brand" href="#hero" aria-label="OmniStepBench, back to top">
|
| 473 |
+
<svg class="nav__logo" aria-hidden="true"><use href="#logo"/></svg>
|
| 474 |
+
<span class="nav__word">Omni<span class="nav__s">Step</span><span>Bench</span></span>
|
| 475 |
+
</a>
|
| 476 |
+
<button class="nav__toggle" type="button" aria-expanded="false" aria-controls="nav-menu">
|
| 477 |
+
<svg aria-hidden="true"><use href="#i-menu"/></svg><span class="sr-only">Menu</span>
|
| 478 |
+
</button>
|
| 479 |
+
<nav class="nav__menu" id="nav-menu" aria-label="Sections">
|
| 480 |
+
<ul class="nav__links">
|
| 481 |
+
<li><a href="#overview">Overview</a></li>
|
| 482 |
+
<li><a href="#workloads">Workloads</a></li>
|
| 483 |
+
<li><a href="#leaderboard">Leaderboard</a></li>
|
| 484 |
+
<li><a href="#cost">Cost</a></li>
|
| 485 |
+
<li><a href="#reliability">Reliability</a></li>
|
| 486 |
+
<li><a href="#quickstart">Quick Start</a></li>
|
| 487 |
+
<li><a href="#cite">Cite</a></li>
|
| 488 |
+
</ul>
|
| 489 |
+
<div class="nav__cta">
|
| 490 |
+
<a class="btn btn--sm btn--ghost" data-href="meta.arxivUrl" href="https://arxiv.org/abs/2609.06059" rel="noopener"><svg aria-hidden="true"><use href="#i-paper"/></svg>Paper</a>
|
| 491 |
+
<a class="btn btn--sm btn--navy" data-href="meta.github" href="https://github.com/SeerRay-Lab/OmniStepBench" rel="noopener"><svg aria-hidden="true"><use href="#i-github"/></svg>GitHub</a>
|
| 492 |
+
</div>
|
| 493 |
+
</nav>
|
| 494 |
+
</div>
|
| 495 |
+
<div class="nav__progress" aria-hidden="true"><span></span></div>
|
| 496 |
+
</header>
|
| 497 |
+
|
| 498 |
+
<noscript>
|
| 499 |
+
<p class="noscript">This page draws the benchmark tables and charts with JavaScript. Please enable it, or read the paper directly on <a href="https://arxiv.org/abs/2609.06059">arXiv</a> and the code on <a href="https://github.com/SeerRay-Lab/OmniStepBench">GitHub</a>.</p>
|
| 500 |
+
</noscript>
|
| 501 |
+
|
| 502 |
+
<main id="main">
|
| 503 |
+
|
| 504 |
+
<!-- ================= HERO ================= -->
|
| 505 |
+
<section id="hero" class="hero" aria-labelledby="hero-title">
|
| 506 |
+
<div class="hero__scene" aria-hidden="true">
|
| 507 |
+
<svg class="hero__sun" viewBox="0 0 120 120"><g class="sun-rays" stroke="#F2B84B" stroke-width="4" stroke-linecap="round"><path d="M60 6v10M60 104v10M6 60h10M104 60h10M22 22l7 7M91 91l7 7M22 98l7-7M91 29l7-7"/></g><circle cx="60" cy="60" r="44" fill="#FFE7B0" opacity=".6"/><circle cx="60" cy="60" r="30" fill="#FFD27A" stroke="#1E3450" stroke-width="2.5"/><path d="M50 60 Q 60 70 70 60" fill="none" stroke="#1E3450" stroke-width="2.5" stroke-linecap="round"/><circle cx="51" cy="53" r="2.6" fill="#1E3450"/><circle cx="69" cy="53" r="2.6" fill="#1E3450"/></svg>
|
| 508 |
+
<svg class="hero__cloud hero__cloud--a" viewBox="0 0 160 60"><path d="M24 50 C 6 50, 6 28, 24 28 C 26 12, 52 8, 60 22 C 70 6, 104 8, 106 28 C 128 22, 146 34, 136 50 Z" fill="#FFFFFF" stroke="#1E3450" stroke-width="2.5" stroke-linejoin="round"/><path d="M40 40 Q 50 34 60 38" fill="none" stroke="#DDEFF4" stroke-width="3" stroke-linecap="round"/></svg>
|
| 509 |
+
<svg class="hero__cloud hero__cloud--b" viewBox="0 0 160 60"><path d="M24 50 C 6 50, 6 28, 24 28 C 26 12, 52 8, 60 22 C 70 6, 104 8, 106 28 C 128 22, 146 34, 136 50 Z" fill="#FFFFFF" stroke="#1E3450" stroke-width="2.5" stroke-linejoin="round"/></svg>
|
| 510 |
+
<svg class="hero__gull" viewBox="0 0 60 24"><path d="M4 16 Q 16 4, 30 14 Q 44 4, 56 16" fill="none" stroke="#1E3450" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
| 511 |
+
<svg class="hero__surface" viewBox="0 0 1440 48" preserveAspectRatio="none">
|
| 512 |
+
<path d="M0 22 C 120 6, 240 6, 360 22 S 600 38, 720 22 S 960 6, 1080 22 S 1320 38, 1440 22 L 1440 48 L 0 48 Z" fill="#D9F1F6"/>
|
| 513 |
+
<path d="M0 22 C 120 6, 240 6, 360 22 S 600 38, 720 22 S 960 6, 1080 22 S 1320 38, 1440 22" fill="none" stroke="#1E3450" stroke-width="2.5" vector-effect="non-scaling-stroke"/>
|
| 514 |
+
<path d="M0 30 C 120 16, 240 16, 360 30 S 600 44, 720 30 S 960 16, 1080 30 S 1320 44, 1440 30" fill="none" stroke="#FFFFFF" stroke-width="3" opacity=".8" vector-effect="non-scaling-stroke"/>
|
| 515 |
+
</svg>
|
| 516 |
+
<svg class="hero__rays" viewBox="0 0 1000 700" preserveAspectRatio="xMidYMin slice">
|
| 517 |
+
<defs><linearGradient id="ray" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#FFFFFF" stop-opacity=".55"/><stop offset="1" stop-color="#FFFFFF" stop-opacity="0"/></linearGradient></defs>
|
| 518 |
+
<path d="M180 0 L 250 0 L 120 700 L 20 700 Z" fill="url(#ray)"/>
|
| 519 |
+
<path d="M390 0 L 420 0 L 360 700 L 300 700 Z" fill="url(#ray)" opacity=".7"/>
|
| 520 |
+
<path d="M600 0 L 680 0 L 700 700 L 560 700 Z" fill="url(#ray)" opacity=".8"/>
|
| 521 |
+
<path d="M830 0 L 860 0 L 960 700 L 900 700 Z" fill="url(#ray)" opacity=".6"/>
|
| 522 |
+
</svg>
|
| 523 |
+
<svg class="hero__fish hero__fish--a"><use href="#dc-fish"/></svg>
|
| 524 |
+
<svg class="hero__fish hero__fish--b"><use href="#dc-fish"/></svg>
|
| 525 |
+
<svg class="hero__fish hero__fish--c"><use href="#dc-fish"/></svg>
|
| 526 |
+
<div class="bubbles">
|
| 527 |
+
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
|
| 528 |
+
</div>
|
| 529 |
+
<svg class="kelp kelp--l" viewBox="0 0 160 420" preserveAspectRatio="xMidYMax meet">
|
| 530 |
+
<g class="sway sway--a"><path d="M40 420 C 20 360, 60 320, 40 260 C 22 206, 62 170, 44 110 C 34 76, 44 40, 52 20" fill="none" stroke="#1E3450" stroke-width="17" stroke-linecap="round"/><path d="M40 420 C 20 360, 60 320, 40 260 C 22 206, 62 170, 44 110 C 34 76, 44 40, 52 20" fill="none" stroke="#4E9F63" stroke-width="11" stroke-linecap="round"/><path d="M42 300 C 64 290, 76 272, 74 252 M 40 196 C 18 186, 8 168, 12 148 M 46 132 C 66 122, 74 104, 72 88" fill="none" stroke="#1E3450" stroke-width="11" stroke-linecap="round"/><path d="M42 300 C 64 290, 76 272, 74 252 M 40 196 C 18 186, 8 168, 12 148 M 46 132 C 66 122, 74 104, 72 88" fill="none" stroke="#6BBF7A" stroke-width="5.5" stroke-linecap="round"/></g>
|
| 531 |
+
<g class="sway sway--b"><path d="M100 420 C 84 380, 118 350, 100 300 C 86 262, 116 236, 104 196" fill="none" stroke="#1E3450" stroke-width="15" stroke-linecap="round"/><path d="M100 420 C 84 380, 118 350, 100 300 C 86 262, 116 236, 104 196" fill="none" stroke="#3E8C55" stroke-width="9" stroke-linecap="round"/><path d="M102 330 C 124 322, 136 306, 134 288" fill="none" stroke="#1E3450" stroke-width="10" stroke-linecap="round"/><path d="M102 330 C 124 322, 136 306, 134 288" fill="none" stroke="#6BBF7A" stroke-width="5" stroke-linecap="round"/></g>
|
| 532 |
+
</svg>
|
| 533 |
+
<svg class="kelp kelp--r" viewBox="0 0 160 420" preserveAspectRatio="xMidYMax meet">
|
| 534 |
+
<g class="sway sway--b"><path d="M110 420 C 130 360, 92 320, 112 260 C 128 212, 96 176, 112 124 C 120 96, 112 60, 104 40" fill="none" stroke="#1E3450" stroke-width="17" stroke-linecap="round"/><path d="M110 420 C 130 360, 92 320, 112 260 C 128 212, 96 176, 112 124 C 120 96, 112 60, 104 40" fill="none" stroke="#4E9F63" stroke-width="11" stroke-linecap="round"/><path d="M110 290 C 88 282, 76 264, 78 244 M 114 200 C 136 190, 146 172, 142 152" fill="none" stroke="#1E3450" stroke-width="11" stroke-linecap="round"/><path d="M110 290 C 88 282, 76 264, 78 244 M 114 200 C 136 190, 146 172, 142 152" fill="none" stroke="#6BBF7A" stroke-width="5.5" stroke-linecap="round"/></g>
|
| 535 |
+
<g class="sway sway--a"><path d="M52 420 C 66 384, 36 356, 52 316 C 64 284, 44 262, 52 236" fill="none" stroke="#1E3450" stroke-width="15" stroke-linecap="round"/><path d="M52 420 C 66 384, 36 356, 52 316 C 64 284, 44 262, 52 236" fill="none" stroke="#3E8C55" stroke-width="9" stroke-linecap="round"/></g>
|
| 536 |
+
</svg>
|
| 537 |
+
<svg class="coral" viewBox="0 0 200 170">
|
| 538 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 539 |
+
<path d="M100 168 L 100 110 C 100 90, 84 80, 72 60 M 100 124 C 110 104, 130 96, 138 70 M 84 84 C 72 80, 62 70, 58 52 M 128 88 C 142 84, 152 74, 156 58 M 100 110 C 100 90, 104 72, 102 46" fill="none" stroke-width="20"/>
|
| 540 |
+
<path d="M100 168 L 100 110 C 100 90, 84 80, 72 60 M 100 124 C 110 104, 130 96, 138 70 M 84 84 C 72 80, 62 70, 58 52 M 128 88 C 142 84, 152 74, 156 58 M 100 110 C 100 90, 104 72, 102 46" fill="none" stroke="#F4A08C" stroke-width="14"/>
|
| 541 |
+
<circle cx="72" cy="60" r="3" fill="#FFFFFF" stroke="none" opacity=".7"/><circle cx="138" cy="70" r="3" fill="#FFFFFF" stroke="none" opacity=".7"/>
|
| 542 |
+
<path d="M30 168 C 26 140, 50 124, 76 130 C 96 118, 128 124, 132 146 C 150 142, 170 154, 170 168 Z" fill="#9AA8B8" stroke-width="3"/>
|
| 543 |
+
<path d="M50 146 Q 60 140 70 146 M 110 140 Q 118 136 124 140" fill="none" stroke-width="2.4" opacity=".4"/>
|
| 544 |
+
</g>
|
| 545 |
+
</svg>
|
| 546 |
+
<svg class="hero__sand" viewBox="0 0 1440 140" preserveAspectRatio="none">
|
| 547 |
+
<path d="M0 52 C 180 20, 360 30, 540 48 S 900 70, 1080 44 S 1340 24, 1440 40 L 1440 140 L 0 140 Z" fill="#F3DCA8"/>
|
| 548 |
+
<path d="M0 52 C 180 20, 360 30, 540 48 S 900 70, 1080 44 S 1340 24, 1440 40" fill="none" stroke="#1E3450" stroke-width="2.5" vector-effect="non-scaling-stroke"/>
|
| 549 |
+
<path d="M0 76 C 200 60, 420 68, 640 82 S 1040 92, 1440 70 L 1440 140 L 0 140 Z" fill="#EFD198" opacity=".7"/>
|
| 550 |
+
</svg>
|
| 551 |
+
<svg class="hero__decor hero__decor--star"><use href="#dc-star"/></svg>
|
| 552 |
+
<svg class="hero__decor hero__decor--shell"><use href="#dc-shell"/></svg>
|
| 553 |
+
</div>
|
| 554 |
+
|
| 555 |
+
<div class="wrap hero__grid">
|
| 556 |
+
<div class="hero__copy">
|
| 557 |
+
<div class="hero__meta">
|
| 558 |
+
<span class="pill pill--glass" id="hero-arxiv"></span>
|
| 559 |
+
<button class="motion-toggle" type="button" id="motion-toggle" aria-pressed="false"><svg class="i-pause" aria-hidden="true"><use href="#i-pause"/></svg><svg class="i-play" aria-hidden="true"><use href="#i-play"/></svg><span>Pause animations</span></button>
|
| 560 |
+
</div>
|
| 561 |
+
<h1 id="hero-title" class="wordmark" aria-label="OmniStepBench"><span class="wordmark__a" aria-hidden="true">Omni</span><span class="wordmark__s" aria-hidden="true">Step</span><wbr><span class="wordmark__b" aria-hidden="true">Bench</span></h1>
|
| 562 |
+
<p class="hero__expansion" data-bind="meta.expansion">Deployment-Aware Agent Evaluation across Modalities and Task Complexity</p>
|
| 563 |
+
<p class="hero__tagline" data-bind="meta.taglines.2">No model dominates all six workload groups.</p>
|
| 564 |
+
<ul class="authors" id="authors" aria-label="Authors"><li>Yu Liu,</li><li>Zhilin Liu,</li><li>Zhiwei Yang,</li><li>Shaojie Zhang,</li><li>Zheyuan Deng,</li><li>Tingwei Huang,</li><li>Zhenbo Luo,</li><li>Lei Jiang,</li><li>Yanbing Liu,</li><li>Pei Fu</li></ul>
|
| 565 |
+
<ol class="affils" id="affils" aria-label="Affiliations"><li>Institute of Information Engineering, Chinese Academy of Sciences</li><li>School of Cyber Security, University of Chinese Academy of Sciences</li><li>MiLM Plus, Xiaomi Inc.</li><li>Department of Computer Science, Brown University</li></ol>
|
| 566 |
+
<p class="author-notes" id="author-notes"></p>
|
| 567 |
+
<div class="hero__btns">
|
| 568 |
+
<span class="btn-pair">
|
| 569 |
+
<a class="btn btn--navy" data-href="meta.arxivUrl" href="https://arxiv.org/abs/2609.06059" rel="noopener"><svg aria-hidden="true"><use href="#i-paper"/></svg>arXiv</a>
|
| 570 |
+
<a class="btn btn--ghost" data-href="meta.pdfUrl" href="https://arxiv.org/pdf/2609.06059" rel="noopener"><svg aria-hidden="true"><use href="#i-pdf"/></svg>PDF</a>
|
| 571 |
+
</span>
|
| 572 |
+
<span class="btn-pair">
|
| 573 |
+
<a class="btn btn--ghost" data-href="meta.github" href="https://github.com/SeerRay-Lab/OmniStepBench" rel="noopener"><svg aria-hidden="true"><use href="#i-github"/></svg>Code</a>
|
| 574 |
+
<a class="btn btn--ghost" data-href="meta.hfDataset" href="https://huggingface.co/datasets/SeerRay-Lab/OmniStepBench" rel="noopener" title="OmniStepBench on Hugging Face"><svg aria-hidden="true"><use href="#i-data"/></svg>HF Dataset</a>
|
| 575 |
+
</span>
|
| 576 |
+
<span class="btn-pair">
|
| 577 |
+
<a class="btn btn--coral" href="#leaderboard"><svg aria-hidden="true"><use href="#i-trophy"/></svg>Leaderboard</a>
|
| 578 |
+
<a class="btn btn--ghost" href="#cite"><svg aria-hidden="true"><use href="#i-quote"/></svg>BibTeX</a>
|
| 579 |
+
</span>
|
| 580 |
+
</div>
|
| 581 |
+
</div>
|
| 582 |
+
<div class="hero__mascot">
|
| 583 |
+
<p class="hero__bubble" aria-hidden="true">checking the evidence…</p>
|
| 584 |
+
<svg viewBox="0 0 440 580" class="mascot-svg" role="img" aria-labelledby="mascot-title">
|
| 585 |
+
<title id="mascot-title">Cartoon lobster evaluator holding a magnifying glass and a clipboard</title>
|
| 586 |
+
<defs>
|
| 587 |
+
<radialGradient id="lob-body" cx="38%" cy="32%" r="75%">
|
| 588 |
+
<stop offset="0" stop-color="#F7876F"/>
|
| 589 |
+
<stop offset="0.55" stop-color="#EC624A"/>
|
| 590 |
+
<stop offset="1" stop-color="#D84B33"/>
|
| 591 |
+
</radialGradient>
|
| 592 |
+
<linearGradient id="lens-glass" x1="0" y1="0" x2="1" y2="1">
|
| 593 |
+
<stop offset="0" stop-color="#F4FCFE"/>
|
| 594 |
+
<stop offset="1" stop-color="#BFE9F3"/>
|
| 595 |
+
</linearGradient>
|
| 596 |
+
</defs>
|
| 597 |
+
<!-- rock the lobster stands on (its base hides behind the stat tiles) -->
|
| 598 |
+
<g stroke="#1E3450" stroke-linejoin="round" stroke-linecap="round">
|
| 599 |
+
<path d="M40 580 C 34 520, 70 468, 150 458 C 200 450, 262 450, 310 460 C 380 474, 414 520, 408 580 Z" fill="#A9B7C6" stroke-width="3.5"/>
|
| 600 |
+
<path d="M70 520 C 110 490, 170 482, 226 484 M 300 490 C 330 496, 360 512, 372 530" fill="none" stroke="#FFFFFF" stroke-width="5" opacity=".45"/>
|
| 601 |
+
<path d="M120 540 Q 140 530 160 540 M 250 530 Q 268 520 288 530 M 330 556 Q 346 548 362 556" fill="none" stroke-width="2.5" opacity=".35"/>
|
| 602 |
+
<circle cx="96" cy="552" r="5" fill="#8C9BAC" stroke="none"/><circle cx="210" cy="560" r="4" fill="#8C9BAC" stroke="none"/>
|
| 603 |
+
<path d="M384 500 C 380 480, 392 466, 396 452 M 392 502 C 398 486, 410 478, 418 468" fill="none" stroke="#4E9F63" stroke-width="5"/>
|
| 604 |
+
</g>
|
| 605 |
+
<!-- ground shadow -->
|
| 606 |
+
<ellipse cx="222" cy="462" rx="120" ry="12" fill="#1E3450" opacity=".16"/>
|
| 607 |
+
<g class="mascot-bob">
|
| 608 |
+
<g stroke="#1E3450" stroke-linecap="round" stroke-linejoin="round">
|
| 609 |
+
<!-- antennae: outline + fill strokes -->
|
| 610 |
+
<path d="M200 150 C 186 96, 160 58, 118 42 C 96 34, 84 50, 96 60" fill="none" stroke-width="9"/>
|
| 611 |
+
<path d="M200 150 C 186 96, 160 58, 118 42 C 96 34, 84 50, 96 60" fill="none" stroke="#D9533B" stroke-width="4.5"/>
|
| 612 |
+
<path d="M240 150 C 254 96, 282 58, 324 42 C 346 34, 358 50, 346 60" fill="none" stroke-width="9"/>
|
| 613 |
+
<path d="M240 150 C 254 96, 282 58, 324 42 C 346 34, 358 50, 346 60" fill="none" stroke="#D9533B" stroke-width="4.5"/>
|
| 614 |
+
<!-- small antennules -->
|
| 615 |
+
<path d="M208 150 C 202 128, 196 118, 186 112" fill="none" stroke-width="6"/>
|
| 616 |
+
<path d="M208 150 C 202 128, 196 118, 186 112" fill="none" stroke="#F58A72" stroke-width="2.5"/>
|
| 617 |
+
<path d="M232 150 C 238 128, 244 118, 254 112" fill="none" stroke-width="6"/>
|
| 618 |
+
<path d="M232 150 C 238 128, 244 118, 254 112" fill="none" stroke="#F58A72" stroke-width="2.5"/>
|
| 619 |
+
|
| 620 |
+
<!-- tail fan -->
|
| 621 |
+
<path d="M186 404 L 254 404 L 284 446 Q 270 462 254 450 Q 242 468 228 454 Q 220 470 212 454 Q 198 468 186 450 Q 170 462 156 446 Z" fill="#E4583F" stroke-width="3.5"/>
|
| 622 |
+
<path d="M212 408 L 212 452 M 228 408 L 232 450 M 196 408 L 190 448 M 242 408 L 256 446 M 182 410 L 168 442" fill="none" stroke-width="2" opacity=".45"/>
|
| 623 |
+
<!-- abdomen segments (bottom first) -->
|
| 624 |
+
<rect x="178" y="384" width="84" height="30" rx="15" fill="#E65B42" stroke-width="3.5"/>
|
| 625 |
+
<rect x="168" y="360" width="104" height="32" rx="16" fill="#EA6149" stroke-width="3.5"/>
|
| 626 |
+
<rect x="158" y="334" width="124" height="34" rx="17" fill="#EC654D" stroke-width="3.5"/>
|
| 627 |
+
|
| 628 |
+
<!-- walking legs (behind body) -->
|
| 629 |
+
<g fill="none">
|
| 630 |
+
<path d="M156 292 L 118 306 L 108 334" stroke-width="10"/>
|
| 631 |
+
<path d="M156 292 L 118 306 L 108 334" stroke="#E4583F" stroke-width="5"/>
|
| 632 |
+
<path d="M160 312 L 126 332 L 120 356" stroke-width="10"/>
|
| 633 |
+
<path d="M160 312 L 126 332 L 120 356" stroke="#E4583F" stroke-width="5"/>
|
| 634 |
+
<path d="M284 292 L 322 306 L 332 334" stroke-width="10"/>
|
| 635 |
+
<path d="M284 292 L 322 306 L 332 334" stroke="#E4583F" stroke-width="5"/>
|
| 636 |
+
<path d="M280 312 L 314 332 L 320 356" stroke-width="10"/>
|
| 637 |
+
<path d="M280 312 L 314 332 L 320 356" stroke="#E4583F" stroke-width="5"/>
|
| 638 |
+
</g>
|
| 639 |
+
|
| 640 |
+
<!-- arms -->
|
| 641 |
+
<g fill="none">
|
| 642 |
+
<path d="M160 246 C 132 238, 112 222, 100 196" stroke-width="24"/>
|
| 643 |
+
<path d="M160 246 C 132 238, 112 222, 100 196" stroke="#E95E46" stroke-width="17"/>
|
| 644 |
+
<path d="M280 246 C 306 244, 322 236, 334 222" stroke-width="24"/>
|
| 645 |
+
<path d="M280 246 C 306 244, 322 236, 334 222" stroke="#E95E46" stroke-width="17"/>
|
| 646 |
+
</g>
|
| 647 |
+
|
| 648 |
+
<!-- carapace -->
|
| 649 |
+
<path d="M220 140 C 278 140, 312 188, 312 246 C 312 304, 272 342, 220 342 C 168 342, 128 304, 128 246 C 128 188, 162 140, 220 140 Z" fill="url(#lob-body)" stroke-width="3.5"/>
|
| 650 |
+
<!-- belly plate -->
|
| 651 |
+
<path d="M160 300 Q 220 326 280 300" fill="none" stroke-width="2.5" opacity=".3"/>
|
| 652 |
+
<path d="M176 318 Q 220 336 264 318" fill="none" stroke-width="2.5" opacity=".22"/>
|
| 653 |
+
<!-- highlight -->
|
| 654 |
+
<ellipse cx="180" cy="184" rx="26" ry="13" transform="rotate(-28 180 184)" fill="#FFFFFF" opacity=".35" stroke="none"/>
|
| 655 |
+
<!-- spots -->
|
| 656 |
+
<circle cx="276" cy="210" r="5" fill="#D84B33" stroke="none" opacity=".7"/>
|
| 657 |
+
<circle cx="288" cy="232" r="3.5" fill="#D84B33" stroke="none" opacity=".7"/>
|
| 658 |
+
<circle cx="160" cy="232" r="4" fill="#D84B33" stroke="none" opacity=".6"/>
|
| 659 |
+
|
| 660 |
+
<!-- eye stalks -->
|
| 661 |
+
<path d="M200 160 L 190 122" fill="none" stroke-width="15"/>
|
| 662 |
+
<path d="M200 160 L 190 122" fill="none" stroke="#EC624A" stroke-width="9"/>
|
| 663 |
+
<path d="M240 160 L 250 122" fill="none" stroke-width="15"/>
|
| 664 |
+
<path d="M240 160 L 250 122" fill="none" stroke="#EC624A" stroke-width="9"/>
|
| 665 |
+
<!-- eyes -->
|
| 666 |
+
<circle cx="186" cy="102" r="27" fill="#FFFFFF" stroke-width="3.5"/>
|
| 667 |
+
<circle cx="254" cy="102" r="27" fill="#FFFFFF" stroke-width="3.5"/>
|
| 668 |
+
<g class="mascot-pupils" stroke="none">
|
| 669 |
+
<circle cx="193" cy="108" r="12.5" fill="#1E3450"/>
|
| 670 |
+
<circle cx="261" cy="108" r="12.5" fill="#1E3450"/>
|
| 671 |
+
<circle cx="198" cy="102" r="4.5" fill="#FFFFFF"/>
|
| 672 |
+
<circle cx="266" cy="102" r="4.5" fill="#FFFFFF"/>
|
| 673 |
+
<circle cx="189" cy="113" r="2" fill="#FFFFFF"/>
|
| 674 |
+
<circle cx="257" cy="113" r="2" fill="#FFFFFF"/>
|
| 675 |
+
</g>
|
| 676 |
+
<!-- brows -->
|
| 677 |
+
<path d="M168 68 Q 184 60, 200 66" fill="none" stroke-width="3.5"/>
|
| 678 |
+
<path d="M240 66 Q 256 60, 272 68" fill="none" stroke-width="3.5"/>
|
| 679 |
+
|
| 680 |
+
<!-- face -->
|
| 681 |
+
<ellipse cx="176" cy="226" rx="14" ry="8" fill="#FF8A8A" opacity=".75" stroke="none"/>
|
| 682 |
+
<ellipse cx="264" cy="226" rx="14" ry="8" fill="#FF8A8A" opacity=".75" stroke="none"/>
|
| 683 |
+
<path d="M200 218 Q 220 244 240 218 Q 220 228 200 218 Z" fill="#7A2A1C" stroke-width="3"/>
|
| 684 |
+
<path d="M211 232 Q 220 238 229 232 Q 220 229 211 232 Z" fill="#FF8A8A" stroke="none"/>
|
| 685 |
+
|
| 686 |
+
<!-- bow tie -->
|
| 687 |
+
<path d="M220 266 L 196 254 Q 190 266 196 278 Z" fill="#7A55C4" stroke-width="3"/>
|
| 688 |
+
<path d="M220 266 L 244 254 Q 250 266 244 278 Z" fill="#7A55C4" stroke-width="3"/>
|
| 689 |
+
<rect x="212" y="258" width="16" height="16" rx="5" fill="#5E3FA3" stroke-width="3"/>
|
| 690 |
+
|
| 691 |
+
<!-- magnifying glass (left claw) -->
|
| 692 |
+
<path d="M92 170 L 66 124" fill="none" stroke-width="15"/>
|
| 693 |
+
<path d="M92 170 L 66 124" fill="none" stroke="#8B5A2B" stroke-width="9"/>
|
| 694 |
+
<circle cx="52" cy="96" r="34" fill="#F2B84B" stroke-width="3.5"/>
|
| 695 |
+
<circle cx="52" cy="96" r="25" fill="url(#lens-glass)" stroke-width="3"/>
|
| 696 |
+
<path d="M36 86 Q 40 74, 52 72" fill="none" stroke="#FFFFFF" stroke-width="5" opacity=".95"/>
|
| 697 |
+
<!-- left claw -->
|
| 698 |
+
<path d="M70 196 C 62 172, 70 150, 88 144 L 94 168 L 104 146 C 124 150, 132 176, 122 198 C 112 218, 80 218, 70 196 Z" fill="#EC624A" stroke-width="3.5"/>
|
| 699 |
+
<path d="M84 206 Q 96 212 110 206" fill="none" stroke-width="2.5" opacity=".4"/>
|
| 700 |
+
<circle cx="80" cy="180" r="3" fill="#D84B33" stroke="none"/>
|
| 701 |
+
|
| 702 |
+
<!-- clipboard (right claw) -->
|
| 703 |
+
<g transform="rotate(9 370 214)">
|
| 704 |
+
<rect x="322" y="150" width="96" height="124" rx="11" fill="#D9964F" stroke-width="3.5"/>
|
| 705 |
+
<rect x="331" y="166" width="78" height="100" rx="5" fill="#FFFFFF" stroke-width="2.5"/>
|
| 706 |
+
<rect x="352" y="140" width="36" height="20" rx="6" fill="#9AA8B8" stroke-width="3"/>
|
| 707 |
+
<!-- rows -->
|
| 708 |
+
<rect x="339" y="180" width="13" height="13" rx="3" fill="#FFFFFF" stroke-width="2.2"/>
|
| 709 |
+
<path d="M341 186 L 345 190 L 352 180" fill="none" stroke="#2E8B57" stroke-width="3.2"/>
|
| 710 |
+
<path d="M358 187 L 399 187" fill="none" stroke-width="2.4" opacity=".55"/>
|
| 711 |
+
<rect x="339" y="204" width="13" height="13" rx="3" fill="#FFFFFF" stroke-width="2.2"/>
|
| 712 |
+
<path d="M341 210 L 345 214 L 352 204" fill="none" stroke="#2E8B57" stroke-width="3.2"/>
|
| 713 |
+
<path d="M358 211 L 392 211" fill="none" stroke-width="2.4" opacity=".55"/>
|
| 714 |
+
<rect x="339" y="228" width="13" height="13" rx="3" fill="#FFFFFF" stroke-width="2.2"/>
|
| 715 |
+
<path d="M341 230 L 350 239 M 350 230 L 341 239" fill="none" stroke="#E0533D" stroke-width="3"/>
|
| 716 |
+
<path d="M358 235 L 396 235" fill="none" stroke-width="2.4" opacity=".55"/>
|
| 717 |
+
<path d="M339 254 L 380 254" fill="none" stroke-width="2.4" opacity=".3"/>
|
| 718 |
+
</g>
|
| 719 |
+
<!-- right claw gripping the clipboard edge -->
|
| 720 |
+
<path d="M318 246 C 306 226, 312 204, 330 198 L 338 220 L 348 202 C 368 208, 372 234, 360 250 C 348 266, 326 264, 318 246 Z" fill="#EC624A" stroke-width="3.5"/>
|
| 721 |
+
<path d="M330 256 Q 342 262 354 256" fill="none" stroke-width="2.5" opacity=".4"/>
|
| 722 |
+
</g>
|
| 723 |
+
</g>
|
| 724 |
+
</svg>
|
| 725 |
+
|
| 726 |
+
</div>
|
| 727 |
+
</div>
|
| 728 |
+
<div class="wrap hero__stats-wrap">
|
| 729 |
+
<ul class="stat-tiles" id="stat-tiles" aria-label="OmniStepBench at a glance"></ul>
|
| 730 |
+
</div>
|
| 731 |
+
</section>
|
| 732 |
+
|
| 733 |
+
<!-- ================= WHY ================= -->
|
| 734 |
+
<section id="why" class="sec sec--sand" aria-labelledby="why-title">
|
| 735 |
+
<div class="wrap">
|
| 736 |
+
<div class="sec-head">
|
| 737 |
+
<div class="sec-head__text">
|
| 738 |
+
<p class="kicker">Motivation</p>
|
| 739 |
+
<h2 id="why-title">What deployment-oriented agent evaluation must <span class="squiggle">answer</span></h2>
|
| 740 |
+
<p class="lead" id="why-lead"></p>
|
| 741 |
+
</div>
|
| 742 |
+
</div>
|
| 743 |
+
<ol class="why-grid" id="why-grid"></ol>
|
| 744 |
+
<div class="tldr card card--blob">
|
| 745 |
+
<div class="tldr__head">
|
| 746 |
+
<p class="tldr__label">TL;DR</p>
|
| 747 |
+
</div>
|
| 748 |
+
<ul class="tldr__list" id="tldr-list"></ul>
|
| 749 |
+
<details class="abstract">
|
| 750 |
+
<summary><span>Read the abstract</span></summary>
|
| 751 |
+
<p id="abstract-text"></p>
|
| 752 |
+
</details>
|
| 753 |
+
</div>
|
| 754 |
+
</div>
|
| 755 |
+
</section>
|
| 756 |
+
|
| 757 |
+
<!-- ================= OVERVIEW ================= -->
|
| 758 |
+
<section id="overview" class="sec sec--sea" aria-labelledby="overview-title">
|
| 759 |
+
<svg class="wave" viewBox="0 0 1440 64" preserveAspectRatio="none" aria-hidden="true"><path class="wave__back" d="M0 40 C 200 10, 380 10, 560 32 S 940 60, 1120 30 S 1360 14, 1440 26 L 1440 64 L 0 64 Z"/><path class="wave__front" d="M0 44 C 240 24, 420 60, 700 40 S 1100 16, 1440 44 L 1440 64 L 0 64 Z"/></svg>
|
| 760 |
+
<div class="wrap">
|
| 761 |
+
<div class="sec-head">
|
| 762 |
+
<div class="sec-head__text">
|
| 763 |
+
<p class="kicker">Overview</p>
|
| 764 |
+
<h2 id="overview-title">From source benchmarks to deployment <span class="squiggle">reports</span></h2>
|
| 765 |
+
<p class="lead" id="overview-lead"></p>
|
| 766 |
+
</div>
|
| 767 |
+
<svg class="sec-head__art" aria-hidden="true"><use href="#cr-octopus"/></svg>
|
| 768 |
+
</div>
|
| 769 |
+
<figure class="figure-frame card card--blob">
|
| 770 |
+
<button class="zoomable" type="button" id="overview-zoom" aria-label="Enlarge Figure 2: overview of OmniStepBench">
|
| 771 |
+
<img id="overview-img" alt="" width="2157" height="944" decoding="async">
|
| 772 |
+
<span class="zoomable__hint"><svg aria-hidden="true"><use href="#i-zoom"/></svg><span class="lg-only">Click to enlarge</span><span class="sm-only">Tap to enlarge and pan</span></span>
|
| 773 |
+
</button>
|
| 774 |
+
<figcaption id="overview-cap"></figcaption>
|
| 775 |
+
</figure>
|
| 776 |
+
<ol class="stages" id="stages"></ol>
|
| 777 |
+
</div>
|
| 778 |
+
</section>
|
| 779 |
+
|
| 780 |
+
<!-- ================= WORKLOADS ================= -->
|
| 781 |
+
<section id="workloads" class="sec sec--sand" aria-labelledby="workloads-title">
|
| 782 |
+
<svg class="wave" viewBox="0 0 1440 64" preserveAspectRatio="none" aria-hidden="true"><path class="wave__back" d="M0 30 C 220 56, 420 56, 640 34 S 1040 8, 1240 30 S 1400 44, 1440 36 L 1440 64 L 0 64 Z"/><path class="wave__front" d="M0 42 C 260 60, 520 20, 780 38 S 1200 58, 1440 38 L 1440 64 L 0 64 Z"/></svg>
|
| 783 |
+
<div class="wrap">
|
| 784 |
+
<div class="sec-head">
|
| 785 |
+
<div class="sec-head__text">
|
| 786 |
+
<p class="kicker">Workload matrix</p>
|
| 787 |
+
<h2 id="workloads-title">Tasks organized by what the agent has to <span class="squiggle">do</span></h2>
|
| 788 |
+
<p class="lead">Instead of reporting by source benchmark, OmniStepBench groups tasks along two workload dimensions: input modality (text or multimodal) and execution form (single-step, multi-step, or multi-step with tools). Each source benchmark maps to exactly one group. Select a cell to see its sources, scoring modes, an example prompt and the strongest models.</p>
|
| 789 |
+
</div>
|
| 790 |
+
<svg class="sec-head__art" aria-hidden="true"><use href="#ic-grid"/></svg>
|
| 791 |
+
</div>
|
| 792 |
+
|
| 793 |
+
<div class="matrix-layout">
|
| 794 |
+
<div class="matrix card card--blob" id="matrix" role="group" aria-label="Workload matrix"></div>
|
| 795 |
+
<div class="cell-detail card card--blob" id="cell-detail" aria-live="polite"></div>
|
| 796 |
+
</div>
|
| 797 |
+
|
| 798 |
+
<div class="sources card card--blob" id="sources-block">
|
| 799 |
+
<div class="card-head">
|
| 800 |
+
<div>
|
| 801 |
+
<h3 id="sources-title">Source benchmarks</h3>
|
| 802 |
+
<p class="card-sub" id="sources-sub"></p>
|
| 803 |
+
</div>
|
| 804 |
+
<div class="card-head__btns" id="sources-btns">
|
| 805 |
+
<button class="btn btn--sm btn--ghost view-toggle" type="button" data-target="sources"><svg aria-hidden="true"><use href="#i-table"/></svg><span>View as table</span></button>
|
| 806 |
+
</div>
|
| 807 |
+
</div>
|
| 808 |
+
<div class="view view--chart" id="sources-chart">
|
| 809 |
+
<div class="legend" id="sources-legend"></div>
|
| 810 |
+
<div class="compbar" id="compbar" aria-hidden="true"></div>
|
| 811 |
+
<div class="chipwall" id="chipwall"></div>
|
| 812 |
+
<div class="source-info" id="source-info" aria-live="polite"></div>
|
| 813 |
+
</div>
|
| 814 |
+
<div class="view view--table" id="sources-table" hidden></div>
|
| 815 |
+
</div>
|
| 816 |
+
|
| 817 |
+
<details class="explorer card card--blob" id="explorer">
|
| 818 |
+
<summary>
|
| 819 |
+
<span class="explorer__title">Browse every task file</span>
|
| 820 |
+
<span class="explorer__sub" id="explorer-sub"></span>
|
| 821 |
+
</summary>
|
| 822 |
+
<div class="explorer__body">
|
| 823 |
+
<div class="filters" role="group" aria-label="Task filters">
|
| 824 |
+
<label>Group <select id="f-group"></select></label>
|
| 825 |
+
<label>Source <select id="f-source"></select></label>
|
| 826 |
+
<label>Scoring <select id="f-scoring"></select></label>
|
| 827 |
+
<label class="filters__search">Search id or name <input id="f-q" type="search" autocomplete="off" spellcheck="false"></label>
|
| 828 |
+
</div>
|
| 829 |
+
<p class="explorer__count" id="explorer-count" aria-live="polite"></p>
|
| 830 |
+
<div class="table-scroll table-scroll--tall" tabindex="0" role="region" aria-label="Task metadata table">
|
| 831 |
+
<table class="data-table" id="task-table"></table>
|
| 832 |
+
</div>
|
| 833 |
+
<p class="note">Metadata only (from the task files' frontmatter). Group and scoring follow the paper's source mapping; prompts, answers and rubrics are not shown.</p>
|
| 834 |
+
</div>
|
| 835 |
+
</details>
|
| 836 |
+
</div>
|
| 837 |
+
</section>
|
| 838 |
+
|
| 839 |
+
<!-- ================= LEADERBOARD ================= -->
|
| 840 |
+
<section id="leaderboard" class="sec sec--sea" aria-labelledby="leaderboard-title">
|
| 841 |
+
<svg class="wave" viewBox="0 0 1440 64" preserveAspectRatio="none" aria-hidden="true"><path class="wave__back" d="M0 40 C 200 10, 380 10, 560 32 S 940 60, 1120 30 S 1360 14, 1440 26 L 1440 64 L 0 64 Z"/><path class="wave__front" d="M0 44 C 240 24, 420 60, 700 40 S 1100 16, 1440 44 L 1440 64 L 0 64 Z"/></svg>
|
| 842 |
+
<div class="wrap">
|
| 843 |
+
<div class="sec-head">
|
| 844 |
+
<div class="sec-head__text">
|
| 845 |
+
<p class="kicker">Leaderboard</p>
|
| 846 |
+
<h2 id="leaderboard-title">No model <span class="squiggle">dominates</span> all six workload groups</h2>
|
| 847 |
+
<p class="lead" id="lb-lead"></p>
|
| 848 |
+
</div>
|
| 849 |
+
</div>
|
| 850 |
+
|
| 851 |
+
<div class="lb card card--blob has-peek">
|
| 852 |
+
<svg class="peek" aria-hidden="true"><use href="#mascot-peek"/></svg>
|
| 853 |
+
<div class="lb__top">
|
| 854 |
+
<div class="lb__top-left">
|
| 855 |
+
<div class="controls" role="group" aria-label="Leaderboard controls">
|
| 856 |
+
<div class="seg" role="radiogroup" aria-label="Track" id="lb-track"></div>
|
| 857 |
+
<div class="seg" role="radiogroup" aria-label="Deployment" id="lb-deploy"></div>
|
| 858 |
+
<div class="seg" role="radiogroup" aria-label="Cell style" id="lb-style"></div>
|
| 859 |
+
</div>
|
| 860 |
+
<p class="lb__note" id="lb-note"></p>
|
| 861 |
+
<div class="lb__legend" id="lb-legend"></div>
|
| 862 |
+
</div>
|
| 863 |
+
<p class="narrator-bubble" id="lb-bubble"></p>
|
| 864 |
+
</div>
|
| 865 |
+
<p class="lb__swipe" aria-hidden="true">swipe the table sideways →</p>
|
| 866 |
+
<div class="table-scroll" tabindex="0" role="region" aria-labelledby="lb-caption">
|
| 867 |
+
<table class="lb-table" id="lb-table"></table>
|
| 868 |
+
</div>
|
| 869 |
+
<div class="lb__foot" id="lb-foot"></div>
|
| 870 |
+
</div>
|
| 871 |
+
</div>
|
| 872 |
+
</section>
|
| 873 |
+
|
| 874 |
+
<!-- ================= COST ================= -->
|
| 875 |
+
<section id="cost" class="sec sec--sand" aria-labelledby="cost-title">
|
| 876 |
+
<svg class="wave" viewBox="0 0 1440 64" preserveAspectRatio="none" aria-hidden="true"><path class="wave__back" d="M0 30 C 220 56, 420 56, 640 34 S 1040 8, 1240 30 S 1400 44, 1440 36 L 1440 64 L 0 64 Z"/><path class="wave__front" d="M0 42 C 260 60, 520 20, 780 38 S 1200 58, 1440 38 L 1440 64 L 0 64 Z"/></svg>
|
| 877 |
+
<div class="wrap">
|
| 878 |
+
<div class="sec-head">
|
| 879 |
+
<div class="sec-head__text">
|
| 880 |
+
<p class="kicker">Accuracy & cost</p>
|
| 881 |
+
<h2 id="cost-title">Text and multimodal workloads have different <span class="squiggle">frontiers</span></h2>
|
| 882 |
+
<p class="lead" id="cost-lead"></p>
|
| 883 |
+
</div>
|
| 884 |
+
<svg class="sec-head__art" aria-hidden="true"><use href="#ic-chest"/></svg>
|
| 885 |
+
</div>
|
| 886 |
+
|
| 887 |
+
<div class="controls controls--bar" role="group" aria-label="Cost view controls">
|
| 888 |
+
<div class="seg" role="radiogroup" aria-label="Modality" id="cost-mode"></div>
|
| 889 |
+
<p class="controls__hint">Scopes every chart and note in this section.</p>
|
| 890 |
+
</div>
|
| 891 |
+
|
| 892 |
+
<div class="cost-grid">
|
| 893 |
+
<figure class="chart-card card card--blob" id="scatter-card">
|
| 894 |
+
<div class="card-head">
|
| 895 |
+
<div>
|
| 896 |
+
<h3 id="scatter-title"></h3>
|
| 897 |
+
<p class="card-sub" id="scatter-sub"></p>
|
| 898 |
+
</div>
|
| 899 |
+
<div class="card-head__btns">
|
| 900 |
+
<button class="btn btn--sm btn--ghost" type="button" id="fig1-btn"><svg aria-hidden="true"><use href="#i-image"/></svg><span id="fig1-btn-lab">Paper's figure</span></button>
|
| 901 |
+
<button class="btn btn--sm btn--ghost view-toggle" type="button" data-target="scatter"><svg aria-hidden="true"><use href="#i-table"/></svg><span>View as table</span></button>
|
| 902 |
+
</div>
|
| 903 |
+
</div>
|
| 904 |
+
<div class="view view--chart" id="scatter-chart">
|
| 905 |
+
<div class="legend" id="scatter-legend"></div>
|
| 906 |
+
<div class="chart-box" id="scatter-box"></div>
|
| 907 |
+
</div>
|
| 908 |
+
<div class="view view--table" id="scatter-table" hidden></div>
|
| 909 |
+
<figcaption class="note" id="scatter-cap"></figcaption>
|
| 910 |
+
</figure>
|
| 911 |
+
<aside class="cost-notes" id="cost-notes" aria-label="Frontier notes"></aside>
|
| 912 |
+
</div>
|
| 913 |
+
|
| 914 |
+
<figure class="chart-card card card--blob" id="tokens-card">
|
| 915 |
+
<div class="card-head">
|
| 916 |
+
<div>
|
| 917 |
+
<h3 id="tokens-title">Tokens and dollars rank models differently</h3>
|
| 918 |
+
<p class="card-sub" id="tokens-sub"></p>
|
| 919 |
+
</div>
|
| 920 |
+
<div class="card-head__btns">
|
| 921 |
+
<div class="seg seg--sm" role="radiogroup" aria-label="Sort rows" id="tokens-sort"></div>
|
| 922 |
+
<button class="btn btn--sm btn--ghost view-toggle" type="button" data-target="tokens"><svg aria-hidden="true"><use href="#i-table"/></svg><span>View as table</span></button>
|
| 923 |
+
</div>
|
| 924 |
+
</div>
|
| 925 |
+
<div class="view view--chart" id="tokens-chart">
|
| 926 |
+
<div class="chart-box" id="tokens-box"></div>
|
| 927 |
+
</div>
|
| 928 |
+
<div class="view view--table" id="tokens-table" hidden></div>
|
| 929 |
+
<figcaption class="tokens-cap" id="tokens-cap"></figcaption>
|
| 930 |
+
</figure>
|
| 931 |
+
</div>
|
| 932 |
+
</section>
|
| 933 |
+
|
| 934 |
+
<!-- ================= RELIABILITY ================= -->
|
| 935 |
+
<section id="reliability" class="sec sec--sea" aria-labelledby="reliability-title">
|
| 936 |
+
<svg class="wave" viewBox="0 0 1440 64" preserveAspectRatio="none" aria-hidden="true"><path class="wave__back" d="M0 40 C 200 10, 380 10, 560 32 S 940 60, 1120 30 S 1360 14, 1440 26 L 1440 64 L 0 64 Z"/><path class="wave__front" d="M0 44 C 240 24, 420 60, 700 40 S 1100 16, 1440 44 L 1440 64 L 0 64 Z"/></svg>
|
| 937 |
+
<div class="wrap">
|
| 938 |
+
<div class="sec-head">
|
| 939 |
+
<div class="sec-head__text">
|
| 940 |
+
<p class="kicker">Evidence-based audit</p>
|
| 941 |
+
<h2 id="reliability-title">Removing credit the <span class="squiggle">evidence</span> does not support</h2>
|
| 942 |
+
<p class="lead" id="rel-lead"></p>
|
| 943 |
+
</div>
|
| 944 |
+
<svg class="sec-head__art" aria-hidden="true"><use href="#ic-shield"/></svg>
|
| 945 |
+
</div>
|
| 946 |
+
|
| 947 |
+
<div class="audit-grid">
|
| 948 |
+
<div class="funnel card card--blob has-peek">
|
| 949 |
+
<svg class="peek peek--left" aria-hidden="true"><use href="#mascot-peek"/></svg>
|
| 950 |
+
<h3>The audit funnel</h3>
|
| 951 |
+
<ol class="audit-steps" id="funnel"></ol>
|
| 952 |
+
<div class="funnel__rule" id="audit-rule"></div>
|
| 953 |
+
</div>
|
| 954 |
+
<div class="judges card card--blob">
|
| 955 |
+
<h3>Two judges, two model families</h3>
|
| 956 |
+
<div class="judges__chain" id="judge-chain"></div>
|
| 957 |
+
<div class="mae" id="mae"></div>
|
| 958 |
+
</div>
|
| 959 |
+
</div>
|
| 960 |
+
|
| 961 |
+
<div class="patterns card card--blob">
|
| 962 |
+
<div class="card-head">
|
| 963 |
+
<div>
|
| 964 |
+
<h3>Hallucination patterns caught by the audit</h3>
|
| 965 |
+
<p class="card-sub" id="patterns-sub"></p>
|
| 966 |
+
</div>
|
| 967 |
+
<button class="btn btn--sm btn--ghost view-toggle" type="button" data-target="patterns"><svg aria-hidden="true"><use href="#i-table"/></svg><span>View as table</span></button>
|
| 968 |
+
</div>
|
| 969 |
+
<div class="view view--chart" id="patterns-chart">
|
| 970 |
+
<div class="legend" id="patterns-legend"></div>
|
| 971 |
+
<ul class="pattern-grid" id="pattern-grid"></ul>
|
| 972 |
+
</div>
|
| 973 |
+
<div class="view view--table" id="patterns-table" hidden></div>
|
| 974 |
+
</div>
|
| 975 |
+
|
| 976 |
+
<div class="audit-figs" id="audit-figs"></div>
|
| 977 |
+
</div>
|
| 978 |
+
</section>
|
| 979 |
+
|
| 980 |
+
<!-- ================= FINDINGS ================= -->
|
| 981 |
+
<section id="findings" class="sec sec--sand" aria-labelledby="findings-title">
|
| 982 |
+
<svg class="wave" viewBox="0 0 1440 64" preserveAspectRatio="none" aria-hidden="true"><path class="wave__back" d="M0 30 C 220 56, 420 56, 640 34 S 1040 8, 1240 30 S 1400 44, 1440 36 L 1440 64 L 0 64 Z"/><path class="wave__front" d="M0 42 C 260 60, 520 20, 780 38 S 1200 58, 1440 38 L 1440 64 L 0 64 Z"/></svg>
|
| 983 |
+
<div class="wrap">
|
| 984 |
+
<div class="sec-head">
|
| 985 |
+
<div class="sec-head__text">
|
| 986 |
+
<p class="kicker">Key findings</p>
|
| 987 |
+
<h2 id="findings-title">What the results say about <span class="squiggle">choosing</span> an agent model</h2>
|
| 988 |
+
<p class="lead" data-bind="meta.taglines.3">Deployment decisions should rest on workload profiles, deployment mode, and accuracy–cost trade-offs rather than a single aggregate score.</p>
|
| 989 |
+
</div>
|
| 990 |
+
<svg class="sec-head__art" aria-hidden="true"><use href="#ic-scale"/></svg>
|
| 991 |
+
</div>
|
| 992 |
+
<div class="findings-grid" id="findings-grid"></div>
|
| 993 |
+
|
| 994 |
+
<div class="taxonomy card card--blob" id="taxonomy">
|
| 995 |
+
<div class="card-head">
|
| 996 |
+
<div>
|
| 997 |
+
<h3>Where agents fail</h3>
|
| 998 |
+
<p class="card-sub" id="tax-sub"></p>
|
| 999 |
+
</div>
|
| 1000 |
+
<button class="btn btn--sm btn--ghost view-toggle" type="button" data-target="tax"><svg aria-hidden="true"><use href="#i-table"/></svg><span>View as table</span></button>
|
| 1001 |
+
</div>
|
| 1002 |
+
<div class="view view--chart" id="tax-chart">
|
| 1003 |
+
<div class="legend" id="tax-legend"></div>
|
| 1004 |
+
<div class="chart-box" id="tax-box"></div>
|
| 1005 |
+
</div>
|
| 1006 |
+
<div class="view view--table" id="tax-table" hidden></div>
|
| 1007 |
+
</div>
|
| 1008 |
+
|
| 1009 |
+
<figure class="case card card--blob" id="case-study"></figure>
|
| 1010 |
+
</div>
|
| 1011 |
+
</section>
|
| 1012 |
+
|
| 1013 |
+
<!-- ================= QUICK START ================= -->
|
| 1014 |
+
<section id="quickstart" class="sec sec--sea" aria-labelledby="quickstart-title">
|
| 1015 |
+
<svg class="wave" viewBox="0 0 1440 64" preserveAspectRatio="none" aria-hidden="true"><path class="wave__back" d="M0 40 C 200 10, 380 10, 560 32 S 940 60, 1120 30 S 1360 14, 1440 26 L 1440 64 L 0 64 Z"/><path class="wave__front" d="M0 44 C 240 24, 420 60, 700 40 S 1100 16, 1440 44 L 1440 64 L 0 64 Z"/></svg>
|
| 1016 |
+
<div class="wrap">
|
| 1017 |
+
<div class="sec-head">
|
| 1018 |
+
<div class="sec-head__text">
|
| 1019 |
+
<p class="kicker">Quick start</p>
|
| 1020 |
+
<h2 id="quickstart-title">Evaluate your <span class="squiggle">own</span> model</h2>
|
| 1021 |
+
<p class="lead">The commands below are taken verbatim from the repository README. The repository holds the task files, graders and run scripts; by default, runs go through an OpenClaw agent runtime, as in the paper.</p>
|
| 1022 |
+
</div>
|
| 1023 |
+
<svg class="sec-head__art" aria-hidden="true"><use href="#ic-terminal"/></svg>
|
| 1024 |
+
</div>
|
| 1025 |
+
<div class="card card--blob reqs reqs--strip">
|
| 1026 |
+
<h3>Requirements</h3>
|
| 1027 |
+
<ul id="qs-reqs"></ul>
|
| 1028 |
+
</div>
|
| 1029 |
+
<div class="qs-grid">
|
| 1030 |
+
<ol class="steps" id="qs-steps"></ol>
|
| 1031 |
+
<aside class="qs-side">
|
| 1032 |
+
<div class="card card--blob tools-card">
|
| 1033 |
+
<h3>What every model gets in the paper</h3>
|
| 1034 |
+
<p class="card-sub" id="qs-tools-lead"></p>
|
| 1035 |
+
<div id="qs-tools"></div>
|
| 1036 |
+
</div>
|
| 1037 |
+
<details class="card card--blob flags" id="qs-flags-box" open>
|
| 1038 |
+
<summary><h3>Command-line flags</h3></summary>
|
| 1039 |
+
<dl class="flaglist" id="qs-flags"></dl>
|
| 1040 |
+
</details>
|
| 1041 |
+
</aside>
|
| 1042 |
+
</div>
|
| 1043 |
+
|
| 1044 |
+
<div class="anatomy card card--blob">
|
| 1045 |
+
<div class="card-head">
|
| 1046 |
+
<div>
|
| 1047 |
+
<h3>Anatomy of a task file</h3>
|
| 1048 |
+
<p class="card-sub" id="anat-sub"></p>
|
| 1049 |
+
</div>
|
| 1050 |
+
</div>
|
| 1051 |
+
<p class="anatomy__eq" id="anat-eq"></p>
|
| 1052 |
+
<div class="anatomy__grid">
|
| 1053 |
+
<ul class="tuple" id="anat-tuple" aria-label="Task tuple components"></ul>
|
| 1054 |
+
<div class="codefile">
|
| 1055 |
+
<div class="codefile__bar"><span class="codefile__dots" aria-hidden="true"><i></i><i></i><i></i></span><span id="anat-file"></span></div>
|
| 1056 |
+
<pre class="codefile__body" id="anat-code" tabindex="0" aria-label="Task file contents"></pre>
|
| 1057 |
+
</div>
|
| 1058 |
+
</div>
|
| 1059 |
+
<p class="anat-cap" id="anat-cap"></p>
|
| 1060 |
+
</div>
|
| 1061 |
+
</div>
|
| 1062 |
+
</section>
|
| 1063 |
+
|
| 1064 |
+
<!-- ================= CITE ================= -->
|
| 1065 |
+
<section id="cite" class="sec sec--sand" aria-labelledby="cite-title">
|
| 1066 |
+
<svg class="wave" viewBox="0 0 1440 64" preserveAspectRatio="none" aria-hidden="true"><path class="wave__back" d="M0 30 C 220 56, 420 56, 640 34 S 1040 8, 1240 30 S 1400 44, 1440 36 L 1440 64 L 0 64 Z"/><path class="wave__front" d="M0 42 C 260 60, 520 20, 780 38 S 1200 58, 1440 38 L 1440 64 L 0 64 Z"/></svg>
|
| 1067 |
+
<div class="wrap cite-wrap">
|
| 1068 |
+
<div class="cite__art" aria-hidden="true">
|
| 1069 |
+
<p class="cite__bubble">thanks for diving in!</p>
|
| 1070 |
+
<svg><use href="#mascot-bust"/></svg>
|
| 1071 |
+
</div>
|
| 1072 |
+
<div class="cite__body">
|
| 1073 |
+
<p class="kicker">Cite</p>
|
| 1074 |
+
<h2 id="cite-title">If OmniStepBench helps your <span class="squiggle">work</span></h2>
|
| 1075 |
+
<p class="lead">Please cite the paper:</p>
|
| 1076 |
+
<div class="codeblock">
|
| 1077 |
+
<button class="copy-btn" type="button" data-copy-target="bibtex" aria-label="Copy BibTeX"><svg aria-hidden="true"><use href="#i-copy"/></svg><span>Copy</span></button>
|
| 1078 |
+
<pre id="bibtex" tabindex="0" aria-label="BibTeX entry"></pre>
|
| 1079 |
+
</div>
|
| 1080 |
+
</div>
|
| 1081 |
+
</div>
|
| 1082 |
+
</section>
|
| 1083 |
+
|
| 1084 |
+
</main>
|
| 1085 |
+
|
| 1086 |
+
<footer id="footer" class="footer">
|
| 1087 |
+
<svg class="footer__wave" viewBox="0 0 1440 90" preserveAspectRatio="none" aria-hidden="true"><path d="M0 50 C 180 20, 360 30, 540 48 S 900 70, 1080 44 S 1340 24, 1440 40 L 1440 90 L 0 90 Z" fill="#F3DCA8"/><path d="M0 50 C 180 20, 360 30, 540 48 S 900 70, 1080 44 S 1340 24, 1440 40" fill="none" stroke="#1E3450" stroke-width="2.5" vector-effect="non-scaling-stroke"/></svg>
|
| 1088 |
+
<div class="footer__floor">
|
| 1089 |
+
<svg class="footer__weed footer__weed--l" aria-hidden="true"><use href="#dc-weed"/></svg>
|
| 1090 |
+
<svg class="footer__weed footer__weed--r" aria-hidden="true"><use href="#dc-weed"/></svg>
|
| 1091 |
+
<svg class="footer__decor footer__decor--star" aria-hidden="true"><use href="#dc-star"/></svg>
|
| 1092 |
+
<svg class="footer__decor footer__decor--shell" aria-hidden="true"><use href="#dc-shell"/></svg>
|
| 1093 |
+
<div class="wrap footer__grid">
|
| 1094 |
+
<div class="footer__brand">
|
| 1095 |
+
<a class="nav__brand" href="#hero"><svg class="nav__logo" aria-hidden="true"><use href="#logo"/></svg><span class="nav__word">Omni<span class="nav__s">Step</span><span>Bench</span></span></a>
|
| 1096 |
+
<p data-bind="meta.expansion">Deployment-Aware Agent Evaluation across Modalities and Task Complexity</p>
|
| 1097 |
+
<p class="footer__links">
|
| 1098 |
+
<a data-href="meta.arxivUrl" href="https://arxiv.org/abs/2609.06059" rel="noopener">arXiv</a>
|
| 1099 |
+
<a data-href="meta.pdfUrl" href="https://arxiv.org/pdf/2609.06059" rel="noopener">PDF</a>
|
| 1100 |
+
<a data-href="meta.htmlUrl" href="https://arxiv.org/html/2609.06059" rel="noopener">HTML</a>
|
| 1101 |
+
<a data-href="meta.github" href="https://github.com/SeerRay-Lab/OmniStepBench" rel="noopener">GitHub</a>
|
| 1102 |
+
<a data-href="meta.hfDataset" href="https://huggingface.co/datasets/SeerRay-Lab/OmniStepBench" rel="noopener">HF Dataset</a>
|
| 1103 |
+
</p>
|
| 1104 |
+
</div>
|
| 1105 |
+
<div class="footer__col">
|
| 1106 |
+
<h2 class="footer__h">Affiliations</h2>
|
| 1107 |
+
<ol class="footer__affils" id="footer-affils"></ol>
|
| 1108 |
+
</div>
|
| 1109 |
+
<div class="footer__col footer__col--wide">
|
| 1110 |
+
<h2 class="footer__h">Acknowledgements</h2>
|
| 1111 |
+
<p id="footer-ack"></p>
|
| 1112 |
+
<p class="footer__srcs" id="footer-srcs"></p>
|
| 1113 |
+
</div>
|
| 1114 |
+
</div>
|
| 1115 |
+
<div class="wrap footer__base">
|
| 1116 |
+
<p id="footer-base"></p>
|
| 1117 |
+
<a class="footer__top" href="#hero"><svg aria-hidden="true"><use href="#i-down"/></svg>Back to the surface</a>
|
| 1118 |
+
</div>
|
| 1119 |
+
</div>
|
| 1120 |
+
</footer>
|
| 1121 |
+
|
| 1122 |
+
<div class="tip" id="tip" role="tooltip" hidden></div>
|
| 1123 |
+
<dialog class="lightbox" id="lightbox" aria-labelledby="lightbox-cap">
|
| 1124 |
+
<div class="lightbox__inner">
|
| 1125 |
+
<button class="lightbox__close btn btn--sm btn--ghost" type="button" id="lightbox-close"><svg aria-hidden="true"><use href="#i-close"/></svg>Close</button>
|
| 1126 |
+
<div class="lightbox__img"><img id="lightbox-img" alt="" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"></div>
|
| 1127 |
+
<p id="lightbox-cap" class="lightbox__cap"></p>
|
| 1128 |
+
</div>
|
| 1129 |
+
</dialog>
|
| 1130 |
+
<div class="sr-only" id="live" aria-live="polite"></div>
|
| 1131 |
+
|
| 1132 |
+
<script src="assets/data/data.js"></script>
|
| 1133 |
+
<script src="assets/js/util.js"></script>
|
| 1134 |
+
<script src="assets/js/content.js"></script>
|
| 1135 |
+
<script src="assets/js/workloads.js"></script>
|
| 1136 |
+
<script src="assets/js/leaderboard.js"></script>
|
| 1137 |
+
<script src="assets/js/cost.js"></script>
|
| 1138 |
+
<script src="assets/js/reliability.js"></script>
|
| 1139 |
+
<script src="assets/js/quickstart.js"></script>
|
| 1140 |
+
<script src="assets/js/main.js"></script>
|
| 1141 |
+
</body>
|
| 1142 |
+
</html>
|