"""Export the numbers behind figures/*.svg and the comparison table into figures/data.json. python tools/export_figure_data.py --src --summary Reads only committed result files of the research checkout (paths below are relative to --src): results/decision-index/board-live.json the live Decision Index 0.2.1 board (official full-suite numbers) results/decision-index/boot021-*.json our paired-bootstrap reads on the 6,948-request stratified sample verticals//runs/*/report.json raw Qwen3.5-4B-Base zero-shot on each vertical's fixed test set and the exported summary (verticals: ours + LoRA / Jev / Wald zero-shot; effort table; serving cost and latency). A read that is not committed yet is taken from PENDING (a number relayed from the run, marked "reported") and is replaced automatically once its bootstrap file exists. Nothing here is recomputed: the script copies and labels. """ from __future__ import annotations import argparse import glob import json import re from pathlib import Path ROOT = Path(__file__).resolve().parents[1] # Our Decision Index rows. boot = (bootstrap file, model key) once committed; reported = relayed number until then. WALD_ROWS = [ # one row: v1.0 = 021A0-f10 at the declared policy (medium, prompt format repeat_state_plain) {"id": "v1.0", "label": "Wald-4B v1.0 · effort medium", "boot": ("boot021-0927-021A0-f10.json", "arrmed"), "reported": {"index": 53.91, "blocklist_adjusted": 53.62, "board_rank": 6}, "reported_areas_file": "figures/reported-areas-v1.0.json"}, ] EFFORT_KEYS = {"none": "g4one", "low": "g4low", "medium": "g4med", "high": "g4high", "high-k4": "g4k4"} QWEN27 = ("boot021-bigbase-0927.json", "q27paren") JEV_SAMPLE = ("boot021-0927.json", "jev") BOARD_NAMES = {"decider_4b": "Decider 4B", "decider_35b": "Decider 35B-A3B"} SUITE = [ # JevBench public 231 (accuracy %) and XL hidden split (XL-Int), zero-shot, same requests {"system": "Wald-4B v1.0 · medium (packaged server)", "public231": round(100 * 204 / 231, 1), "xl_hidden": 63.2, "source": "public 231: packaged wald-serve smoke read of 021A0-f10 09-27 (ledger 197); XL: xl-bench leaderboard.md (hidden split)"}, {"system": "Jev (API, jev-1.13.0)", "public231": 86.6, "xl_hidden": 73.0, "source": "results/external/jev-1.13.0; xl-bench #1"}, {"system": "Cygnet (gemma-4-12B-it + shim)", "public231": None, "xl_hidden": 59.8, "source": "xl-bench #4"}, {"system": "Laya (zero-shot, Jev's wire request)", "public231": 58.0, "xl_hidden": 13.4, "source": "results/external/laya; xl-bench #24"}, {"system": "CLM-8B (zero-shot, same requests, deployment verified)", "public231": 39.0, "xl_hidden": 12.7, "source": "ledger 190 read (results/external/clm-8b); xl-bench #25"}, {"system": "raw Qwen3.5-4B-Base (zero-shot, our readout)", "public231": round(100 * 156 / 231, 1), "xl_hidden": None, "source": "exported lineage summary (public one-pass 156 / 231)"}, ] NC_TASKS = {"WebLINX intent"} COLD_PAIRED_CI = [7.7, 10.0] # paired bootstrap, docs: buyer-demo COLD v3 full test (+8.8) COLD_USD = 1.0 # three COLD arms shared about 1 GPU-hour (about $1) on one RTX PRO 6000 VERTICAL_TASKS = { # summary task name -> vertical directory "When2Call": "when2call", "BANKING77": "banking77", "SGD intent": "sgd-intent", "ToxicChat": "toxicchat", "MetaTool": "metatool", "AndroidControl": "androidcontrol", "WebLINX intent": "weblinx-intent", "RouteLLM routing": "model-routing", "Agent-trajectory safety (hard)": "agent-trajectory-safety-hard", "Mind2Web": "mind2web", "Prompt injection": "prompt-injection", "RewardBench": "rewardbench", } def size_b(base_model: str | None): """Total parameters in billions read from a base model name (35B-A3B -> 35, E4B -> 4); None when absent.""" if not base_model: return None m = re.search(r"(?