weather-card-benchmark

Methodology

One prompt, every model, the same weather fixture. Here is exactly how the numbers are produced, how community votes are counted, and what a patch is and is not.

1Similarity metrics are measurements, not quality scores. The channels below quantify how alike two cards are — we don't convert that into a judgment of which model is better.
2Community vote standings are a UI preference — which cards people prefer to look at. Vote counts are visible; they are not a model-capability benchmark.
3Everything is deterministic and reproducible. Every batch is anchored to a manifest_hash you can recompute; the measured pixels are the exact pixels the algorithms read.

The task

Every card on this site was produced from exactly this text — no system prompt, no follow-up, no retry with hints. Both variants are handed to every model identically.

prompt (verbatim)
download
Build a weather card as a single complete HTML file.

Output only the raw HTML file content — no markdown fences, no commentary before or after.

Rules:
- All CSS and JS inline. No external resources; no network requests other than the two API paths below.
- Desktop viewport, 1280x800.
- Read URL query parameters: `lat`, `lon`, `name` (location label), `date` (YYYY-MM-DD). Defaults: 52.52, 13.405, Berlin, today (UTC).
- Fetch weather data from the same-origin API (Open-Meteo compatible, no key):
  - `/api/om/forecast` — parameters and response format identical to api.open-meteo.com/v1/forecast (today and future dates)
  - `/api/om/archive` — identical to archive-api.open-meteo.com/v1/archive (past dates)
- Request with query parameters: `latitude`, `longitude`, `daily=temperature_2m_max,temperature_2m_min,weather_code`, `hourly=temperature_2m`, `timezone=UTC`, `temperature_unit=celsius`, and `start_date`/`end_date` both set to the requested date.
- Display, in Celsius: the location name, the date, that date's maximum and minimum temperature, the weather condition, and the hourly temperatures for that date.
- If the data cannot be loaded, the page must say so.
P-min is the bare task; P-q adds a short quality clause. Each manifest pins the sha256 of the bytes below.sha256 6901ad22fb318de2

How similarity is measured

Each model draws a single-file HTML weather card from the same prompt against a frozen weather snapshot, rendered in a pinned Chromium at a fixed viewport and frozen virtual clock. Similarity is computed only between valid outputs, per pair, per channel — there is no composite score. The pipeline runs in four layers:

L1
single-card descriptors
Per-card scalars: byte and DOM/CSS/JS structure, visual measures (colorfulness, brightness, contrast, whitespace, frame-change), and a fixed-grid Lab palette. Plus a versioned data-fidelity check against the snapshot.
L2
similarity channels
Visual (phash/dhash/color/palette/layout/edge/ssim), code (shingle/winnow/feature/ast-js/css-prop), and DOM (geom/text/pqgram) channels — each a distinct, frozen definition. No composite is computed or shown; a null pair stays null.
L3
statistics
Descriptive only, N is small (3–5 slots). Means and IQRs over valid pairs, self-consistency, LORO sensitivity, and one randomization paired test for prompt-variant sensitivity. Intervals are descriptive, not inferential.
L4
behavior probes
Contract-level pass/indeterminate/fail on network discipline and error handling, plus out-of-contract observed/not-observed notes (loading states, console errors, no-JS fallback).

Each batch freezes both prompt hashes, the weather-snapshot hash, the city/date set, the render environment, and the pipeline commit into a manifest whose SHA-256 is the manifest_hash. Recompute it to verify — reproducibility is the point.

Patch policy

A broken model card may be hand-fixed so it renders, with an honest, visible note; the original is always preserved and served by default. Four invariants hold, without exception:

A patch NEVER changes slot state, validCount, or any coverage status. A broken slot stays broken in every count; the patch only adds a viewable repaired rendering.
All metrics — similarity, fidelity, shot.webp, telemetry — derive from the ORIGINAL output. The card page states: "metrics refer to the original output".
Arena and every voting / preference surface serve ONLY the original card.html. Vote rows carry patched_served (always 0; an audit column).
The category enum is closed; the hard rule is "a patch may only make the card render, never improve its content or design". The stored unified diff makes this auditable.

Patches applied

Every patch in the data root is listed here — config, category, and a link to the exact original→patched diff — so the whole layer is auditable on one page.

configslotcategoryreasondiff
mimo-v2.5-free--zen-free--devP-q · #1render-fixIn the SVG hourly-chart point loop the index bracket and call paren were transposed: `sy(temps[i)]` instead of `sy(temps[i])`, a JavaScript SyntaxError ('Unexpected token )'). The inline script failed to parse and the card stayed stuck on its '⏳ Loading weather…' placeholder. Fix: transpose the two characters back to `temps[i])`. Two-character syntax repair — no content, data, or design changed.diff ↗
qwen3.7-plus--cli--opencode--devP-q · #0render-fixThe weather-code map WC had a malformed, duplicated '63' entry whose value was written as a bare string instead of a [label, emoji] array (`'63':'Moderate rain','\uD83C\uDF27']`), producing a JavaScript SyntaxError ('Unexpected token ]'). The entire inline script failed to parse and the card rendered fully blank. Fix: insert the single missing '[' so it becomes `'63':['Moderate rain','\uD83C\uDF27']`, matching the model's own correctly-formed '63' entry on the very next line. One-character syntax repair — no content, data, or design changed.diff ↗

How votes are counted

Community UI preference — which cards people prefer to look at; not a capability measure.

Votes are cast blind: identities never reach the browser before a vote is recorded (opaque single-use tokens, original HTML only, qualified-grade cards only).

  1. Bradley–Terry (a simple iterative MM fit) runs over pair votes only, per angle × variant.
  2. A tie counts one half to each side.
  3. both_bad is excluded from Bradley–Terry (otherwise it becomes a suppression lever) and reported separately as each config's bothBadRate — itself honest community data.
  4. Gate votes (source=gate — the coerced unlock votes) are excluded from the default aggregation as the lowest-quality rows; they remain in the CSV export, labeled. Arena and share votes count.
  5. prefRate carries a Wilson confidence interval; maxSingleVoterShare is shown for concentration transparency (anti-brigade sunlight).
  6. A config is marked insufficient when it has fewer than 20 votes or fewer than 8 distinct voters — such rows carry no numbers and no position on any axis.
Unauthenticated, localStorage-identity web votes — trivially gameable; treat as community signal, not measurement.

Contributing runs — the zero-trust path

You can help fill coverage gaps by supplying an API key for the exact cells you pick. The key handling rules, verbatim:

  1. Your API key stays in memory only — never persisted, never logged.
  2. It is used solely for the runs you selected, then discarded.
  3. The runner is open source; you can read exactly what it does.
  4. Zero-trust alternative: run the batch locally and open a pull request — no key ever leaves your machine.

A contributed run lands in the gallery immediately with an "unreviewed community" badge, and never enters the arena voting pool until a maintainer reviews it. Contributed output is committed to a community/<jobId> branch and never pushed to the default branch without human review.

Provenance — measurement sessions

Each batch is one frozen, append-only run against one fixture. Batches are provenance now, not a way to browse the gallery. Similarity numbers are only comparable within a single session — same fixture, same snapshot.

36 measurement sessions, newest first.
sessiondateconfigsvariantsmanifest_hash
2026-07-20--refill4-oc-qwen3.7-max
2026-07-161P-minP-q
bc1bc204396a8f9bc3aee05e67b0356573d379c48fd9ae1f91d95e1622358cc7
2026-07-20--refill4-oc-grok-4.5
2026-07-161P-minP-q
7a0fc32c070377e2c0f598c6a37d80ae4699521b8d138e72cecd6e5e16fe9543
2026-07-20--refill4-oc-glm-5.1
2026-07-161P-minP-q
0226a043bd54b1ae8c165875535e61149ead5b493d7675310b4379644c561405
2026-07-20--refill4-kiro-claude-opus-4-8-eff-max-eff-max
2026-07-161P-minP-q
3fe9f4838b04f75886e794eeab7236fe672ab7edc2eb7d6471ec03f78b480290
2026-07-20--refill4-kiro-claude-opus-4-7-eff-max-eff-max
2026-07-161P-minP-q
41b74f829fea1d5c991fc3e313e44c8ff0a4f4414aa2394dc5f09ff10ded193a
2026-07-20--refill4-go-qwen3.7-max
2026-07-161P-minP-q
9cec256ebfec677c7cbb525055b47edd8d9c15065381ba25494235419af89615

Full comparison scheme

The frozen technical reference — the deterministic similarity scheme exactly as authored during the trial. The site's presentation follows the positioning above.

Expand the full comparison schemeCOMPARISON-SCHEME-v12.md

横向对比方案 v12(r11 修订版,自包含;grok r9/r10/r11 三轮连续 SATISFIED)

v12 变更(GPT r11 3 blockers + 双方 r11 建议):max/min 三分支前置统一规则 E=∅ → not-found;hourly 单射比较键改定长 per-label 向量(未绑定元素有定义,signature 由其派生);config 顺序统一 = 持久化数组顺序(config_ids/mask_h 构建时按 NFC UTF-8 字节序排定,使用处禁止重排);附录 leftmost-longest 全句、lock 清单补 schema hash/version、cities 判重 NFC 先行、单侧键距离=二元组、schema required/additionalProperties:false/uniqueItems(NFC 后)、文本坐标=归一化文本累计码点长度(节点间无分隔符)。

0. 硬约束

  1. 全确定性:所有相似度与统计指标是经典算法,同输入必同输出;非确定性观测(double-render 不一致等)显式分栏 non-deterministic observational,不进 verify hash。
  2. 不打分:无总分、无排名、禁价值化话术(附录 A lint 词表);similarity ≠ quality 页脚常驻。
  3. 描述统计优先:N=3–5,无推断性宣称;区间一律 descriptive, exploratory;唯一检验 = §5 随机化配对检验(实验设计见 §9)。
  4. 任务形态:oneshot 单文件 HTML,1280×800 逻辑视口,同源缓存 API,事件驱动跑批。

1. 采样设计

1.1 Run slots

每 config × 变体每批 N=5 slot(最低 3)。预算单位 = 已发送的模型请求。终态五分:

  • valid:完整响应 + 有效 HTML(fence 剥离后完整 → valid + fence 旗标)。
  • model-failed:完整响应但无有效 HTML(拒答/自身截断无 </html>/空输出)。终态,禁止重试替换。
  • infra-failed:请求被供应商接受(响应头/request id 存在)但中途死。消耗 slot,不补跑,单列基建健康页。
  • acceptance-unknown:请求字节已发送但接受状态不可证明(响应头前超时/断连)。消耗 slot,禁止补跑,单列——已发送即可能计费。
  • unreachable:可证明请求未发送(连接拒绝/DNS/TLS 失败于请求写出前)的重试 5 次耗尽。
  • rate-limited(v12.1 增补,Leo 2026-07-16):供应商在模型处理前明确拒绝且不计费——HTTP 429 / quota-exceeded / gateway 过载(503 overloaded)等有确定性未计费信号者。不占 slot,按指数退避重试;退避预算(次数上限 + 总时长上限,批前冻结)耗尽 → 终态 rate-limited-exhausted,列入基建健康页,不计为 model-failed。与 acceptance-unknown 的判别:后者无法证明未计费 → 保守占 slot;rate-limited 须有确定性未计费证据(明确的 429/quota 状态码)才走此路,含糊情形一律归 acceptance-unknown。

不占 slot 重试仅限两类路径:①"可证明未发送"(unreachable);②"可证明模型处理前未计费拒绝"(rate-limited)。成本硬上界 = N 次实际送达模型的请求/config/变体。m = count(valid);相似度 pair 仅在 valid 之间;其余终态分列展示;m/N 全局角标。gallery 卡 = 最小 slot 号 valid。

1.2 批内冻结与执行

  • 冻结:双 prompt hash(prompt_min_sha256 / prompt_q_sha256)、天气 snapshot hash(canary 数值,如 max 27.4°/min 13.9°/code 61,期望值表随 extractor 版本落盘)、城市/日期集、渲染环境、管道 commit。harness 总是显式传 ?date=(UTC)。
  • P-min/P-q 配对随机化(Ω 编码钉死):每 base config N 个时间 block(下标 0..N−1),每 block 各跑一次 P-min 与 P-q;分配 = block 内执行顺序,bit 0 = min→q,bit 1 = q→min;n₀=#{bit=0},n₁=#{bit=1},合法分配 |n₀−n₁|≤1(奇数 N → {⌊N/2⌋,⌈N/2⌉});Ω_c = 全部合法 bit 串 b∈{0,1}^N,编号 = 将 b 视为 N-bit 无符号整数(b[0]=MSB)按升序 rank 0..|Ω_c|−1;观测分配 ω_obs 用同一编号。观测分配的抽取(v9 钉死):批前冻结全批统一 N∈{3,4,5}。manifest = 批内冻结清单的唯一字节流(v11):固定 JSON Schema(键名强制,schema 文件本身的 SHA256 与 schema_version 冻结入 lock),字段:prompt_min_sha256prompt_q_sha256(两个 prompt 文件原始字节各自的 SHA256)、snapshot_sha256cities(元素形态固定为 {city, date, lat, lon};排序 = 各元素规范 JSON (JCS) 的字节序;重复 (city,date) 拒绝)、config_ids(NFC UTF-8 字节序排序,重复拒绝)、Nenv_digestpipeline_commit(要求工作树干净,dirty 直接拒绝跑批,无 source_digest 兜底);生成时点 = 任何分配抽取之前;排除一切分配结果、seed、时间戳等运行时字段;序列化 = RFC 8785 (JCS) 规范 JSON,所有字符串先 NFC;非整数一律规范十进制字符串,语法:禁指数、禁前导 +、禁前导零(0.x 除外)、禁尾随小数零、禁 −0(归一算法:decimal 化→去尾零→最简形式字符串);manifest_hash = SHA256(该字节流) 小写 hex,落盘入 lock。mask_h 的列表 hash 同样 = 该 config_id 数组规范 JSON 的 SHA256。schema 使用 required + additionalProperties:false,数组 uniqueItems 在 NFC 归一之后检查(cities 判重 (city,date) 亦先 NFC 再比)。config 顺序统一规则(v12):config_ids 与各 mask_h 数组在构建时按 NFC UTF-8 字节序排定并持久化;此后一切使用处(config/block 遍历、pooled PRNG 抽样映射、mask 迭代)直接采用持久化数组顺序,禁止按任何本地"字典序"重排seed_assign(config) = uint64_le(SHA256(b"assign\0" ‖ bytes.fromhex(manifest_hash) ‖ b"\0" ‖ NFC(config_id).encode("utf-8") ‖ b"\0" ‖ uint8(N))[0:8])(字段有边界,无拼接碰撞);每 config 用独立 Generator(PCG64(seed_assign)) 恰好调用一次 integers(0,|Ω_c|) 选 rank;config/block 遍历顺序 = config_ids 持久化数组顺序 × block 下标升序,冻结落盘;分配表/顺序/时间戳落盘。重随机化时 outcome 粘在 (block, 时间位次) 上不动,按 ω 的 bit 串重新解释哪次是 min/q。Ω_c 即 §5 检验的随机化空间本体。

2. 渲染与截图协议

2.1 就绪状态机

  1. 目标 API response finished;2. document.fonts.ready;3. DOM mutation 静默窗 500ms(墙钟);
  2. 内容就绪谓词(按场景选定,不同时评估):正常场景仅评估 READY_NORMAL := 可见 DOM 存在 ≥1 个 §3 温度候选(有意弱于保真:就绪≠数值正确,保真截图后独立判定);错误注入场景仅评估 READY_ERROR := 页面非空白 ∧ 错误词表命中。未命中 → 补等 2×rAF+250ms → 打 content-not-ready[data-ready] 仅诊断。谓词与 extractor 版本入 JSON Schema;
  3. 冻结(§2.2)→ 稳定性确认:250ms 虚拟间隔双时刻像素 hash 一致;不一致重试 3 次,仍不一致打 unstable-after-freeze 并截最后一次比对的第二时刻帧。硬上限 15s,旗标卡照常入库。

2.2 主截图(冻结通道)

init script:Date 冻结 snapshot fetched_at;Math.random=mulberry32(0xC0FFEE);CDP virtual time 推进 t_v=5000ms;CSS/Web Animations 冻结相位(v12.3 修正):对 document.getAnimations() 每个动画——有限次(iterations 有限)→ pause() + currentTime = max(0, delay+activeDuration−1ms)(定格在活动期末端,1ms 回退保证 fill 无关地保留末态样式);无限循环 → pause() + currentTime=0(固定相位)。rAF/timer 随虚拟时钟。相似度只用冻结主截图。(v12.3 修订记录:原规则统一 currentTime=0 会把入场动画 rewind 到未开始态——实测 Kimi K3 P-q 卡内容全部 opacity:0,截图成纯背景而 meta 仍 valid;定格活动期末端 = 用户在 t_v=5s 时实际所见。12 轮评审后的实现期修正,首个正式批 lock 前生效。)

2.3 frame-change(全 virtual time)

第二次渲染,不 pause 动画,虚拟时钟推进 t_v+{700,1300,2100,3400}ms 采帧;相邻帧像素变化率 median/max 进 L1。getAnimations/timer 计数降为纯诊断字段(不入 L1、不入 hypothesis 清单;采样与 instrumentation 待独立规格)。

2.4 渲染 determinism 验证

double-render(两全新 context,像素比对,不一致 → non-deterministic-render,一致率进 profile 默认层);reference fixture 每批全流程跑、跨批比对;环境钉死落盘;metrics/stats 重跑 hash(声明只覆盖计算层)。

3. L1 单卡描述量

体积/结构标量(bytes 拆分、DOM/CSS/JS 统计)、视觉标量(colorfulness、亮度、对比度、留白率、frame-change)、主色板(Lab 固定网格 + 占比权重;top-8 swatch:仅非零权重 bin,最多 8 个,排序键 (−weight, Lab bin C-order 索引);bin 边界为半开区间 [lo,hi),各维最末 bin 闭合 [lo,hi])。

数据保真判定器(extractor_version 版本化;文本归一 = NFC+trim+空白折叠+casefold 前置;字段态 {match,mismatch,ambiguous,not-found} 与 hourly 点态 {match,mismatch,not-shown} 两个独立枚举):

  • name:候选=全部可见文本节点(选择器清单版本化);任一候选含期望 name 子串(直接子串)→ match;否则 not-found(无 mismatch 态);reason code:no-visible-text / text-present-no-name-hit
  • date:ISO + 版本化 locale 模板表解析为 UTC 日;命中 → match;他日 → mismatch;不可解析 → not-found;多候选冲突 → ambiguous。
  • 候选身份 = occurrence(v10 精化):matcher 在归一化可见文本上产生原始命中 (node, start, end, pattern_id)(pattern 逐个版本化;start/end = 节点内 Unicode 码点偏移;实现注记:JS 侧禁用 UTF-16 code unit 的 string index);相同 (node,start,end) span 的命中合并并汇总类别;重叠不同 span 仲裁 = leftmost-longest:按 (start 升序, length 降序, pattern_id 字典序) 排序后贪心取与已选不重叠者;最终 occurrence ID = (node 先序号, start, end),按 namespace(温度候选 / max-min label / 小时 label…)分池;一个文本节点可产生多个 occurrence("Max 27° / Min 14°" 产生独立的 Max 与 Min label occurrence);occurrence 序 = ID 三元组字典序;canonical、hourly 扣除、signature 全部作用在该 ID 上。
  • 距离 = 二元组(v10,修复同节点绑反):dist(L,T) = (父元素经 LCA 的 DOM 边数, |文本坐标(L) − 文本坐标(T)|);文本坐标 = 全部可见文本节点按 DOM 先序、以同一归一化函数处理后的文本累计码点长度定位(节点之间不插分隔符),取 occurrence 的 start;"总距离" = 两分量各自求和的二元组;一切 max/min、单侧、hourly tie-break 中的距离键均按此二元组(先第一分量后第二分量)展开比较。
  • 温度候选:可见文本「数字+度符号/单位」模式的 occurrence;f_max = 全部温度候选 occurrence 的父元素 computed font-size(px) 的最大值(无候选 → E 为空);同显著度 = (f_max−f)/f_max < 0.10。
  • max/min 绑定(全局一对一分配,v12 分支全闭合): 前置统一规则:E=∅ → max/min 均 not-found(reason: no-temperature-candidate),不产生 canonical,不进入任何分支;以下分支均假定 |E|≥1。
    1. 先固定同显著度温度候选集 E((f_max−f)/f_max<0.10 内的温度候选;低于该带的候选忽略);label 逐 occurrence 分类为 max-类 / min-类:仅当同一合并 span 的类别汇总同时含 max 与 min 才作废该 occurrence 并记录;同一文本节点内的不同 occurrence 各自独立保留;下述"存在 label"均指作废后的有效 label occurrence 集;
    2. 双类有效 label 均存在:|E|=1 → 均 ambiguous(reason: insufficient-distinct-temperature-nodes);|E|≥2 → 枚举全部合法组合 (L_max→T_max, L_min→T_min),T_max≠T_min 指 occurrence 互异(值相等由步骤 4 处理),按字典序 (总距离, max 侧距离, min 侧距离, T_max occurrence 序, T_min occurrence 序, L_max occurrence 序, L_min occurrence 序)(距离一律为 §3 二元组展开)取唯一最小组合。不降级到单 label/无 label 路径;
    3. 仅一类有效 label(先行:|E|≥3 → max/min 均 ambiguous):该侧按单侧字典序键 (距离(§3 二元组), T occurrence 序, L occurrence 序) 取唯一绑定;另一侧对剩余候选按数值规则取绑定(大者=max/小者=min;"唯一"指值唯一,同值多 occurrence 绑定该值并取 occurrence 序最小者为 canonical occurrence);剩余候选为空 → ambiguous;
    4. 无有效 label(先行:|E|≥3 → 均 ambiguous):数值规则(大者=max 小者=min;canonical occurrence 同上);
    5. max 绑定值 = min 绑定值 → ambiguous;决策路径落盘。距离 = §3 二元组定义(DOM 边数, |文本坐标差|);occurrence 序 = ID (node 先序, start, end) 三元组字典序(DOM 先序 = 先序遍历,同父按 child 下标)。
    6. canonical 发布条件(v10 措辞精化):仅当两个 canonical occurrence 均已产生且 ID 互异,且 max 与 min 字段终态均非 ambiguous 时才发布 canonical(供 hourly 扣除);步骤 4 的同值分支与任何 ambiguous/not-found 终态不发布 → hourly 预分流按"canonical 未全部发布"→ 整字段 ambiguous。
  • 数值匹配:按候选显示小数位 d 对期望值 decimal quantize ROUND_HALF_UP(ties away from zero)后精确相等;禁裸 round(JS 侧必须 decimal 字符串量化)。
  • hourly(v8:预分流 + 全序单射):
    • 预分流(label 分支前统一):存在任何温度候选但两个 daily canonical occurrence 未全部成功产生 → 整字段 ambiguous(禁止 daily 数值混入 hourly);无任何温度候选 → not-found;
    • hourly_temperature_candidates = 全部温度候选 occurrence − max/min 两个 canonical occurrence;
    • 小时 label 解析器:版本化模板表(HH:00 / HH:mm / h AM·PM / HHh / 本地化变体),解析为 UTC 0–23;
    • 有 label(全局最大基数单射,v12 定长键):枚举 label→hourly 候选 occurrence 的最大基数单射,比较键 = (①绑定数降序;②总距离(仅累计已绑定边,§3 二元组分量各自求和);③定长 per-label 向量字典序);定长向量 = 按全部 label occurrence 序,每 label 一个元素:已绑定 = (0, dom_dist, text_dist, T_id),未绑定 = (1, 0, 0, sentinel_id),sentinel_id=(2³¹−1, 2³¹−1, 2³¹−1)(声明:合法 occurrence ID 各分量恒 < 2³¹−1,signature 无哨兵碰撞可能);取键最小的唯一解(逐 label 独立最近邻不是本规则);assignment signature 即该定长向量的 T_id 分量序列(由键派生,不另立规则);重复小时 label 绑不同值 → 整字段 ambiguous;未获绑定的期望小时 = 点态 not-shown;
    • 无 label:hourly 候选恰好 24 个 occurrence → 按 occurrence 序(DOM 先序+节点内偏移)排列后与 UTC hour 0..23 有序逐位对齐;≠24(含 >24 与 <24)→ 整字段 ambiguous(禁 prefix/禁猜窗);
    • 点态 match/mismatch 判定 = 对绑定值套用与 max/min 相同的 decimal quantize ROUND_HALF_UP 相等规则;
    • 字段态汇总(优先级):结构冲突 → ambiguous;无任何候选 → not-found;否则设 X=#点态 mismatch、M=#点态 match:X≥1 → mismatch;X=0∧M≥1 → match(coverage M/24 常驻展示);X=0∧M=0 → not-found。判定路径落盘。canvas/SVG 无文本局限公开,数据取回由请求侧校验覆盖。
  • condition:WMO 多语词表 text 匹配;icon-only → not-found + icon-only 注记。
  • 请求侧硬校验:network log 逐键校验契约 query(endpoint、latitude/longitude ±0.01、start_date/end_date、daily/hourly 字段集、timezone=UTC、temperature_unit=celsius);mismatch 与字段态表并列。
  • 候选、显著度、绑定决策、判定原因全部落盘。

4. L2 相似度通道

合成视图不存在(预计算/UI 均无);零向量/空集/空 bag → 该 pair 该通道 S=null(双空亦 null);golden fixtures 期望值独立预先写定(手算或冻结时独立参考实现,禁被测代码自生成)。

视觉:v-phash / v-dhash / v-color / v-palette / v-layout / v-edge / v-ssim;代码:c-shingle / c-winnow / c-feature / c-ast-js / c-css-prop / c-ncd(诊断);DOM:d-geom / d-text / d-pqgram / d-tagpath(诊断)。全部定义唯一化于附录 A。

通道去留(开发集审计,v8:观测单位钉死):42 卡语料 = 与正式批隔离的开发集;Spearman 观测单位 = 开发集全部 C(42,2)=861 个无序 card pair,通道向量 = 各 pair 的 S 值;pairwise-complete = 任一通道该 pair 为 null 则剔除,分母 = 完整 pair 数;midrank ties;完整 pair <20 → 该审计值 null;任一通道在完整子集上零方差 → ρ=null(v10)**。**贪心降级仅由"已定义且 |ρ|>0.95"触发;一切 null(样本不足/零方差)不触发降级c-ncd 与 d-tagpath 永久为诊断通道,不参与贪心去留,不进正式通道集/统计/hypothesis family(v9 钉死);通道全序(15 通道,不含诊断)预冻结(附录 A);贪心:按全序遍历,与全部已保留通道 |ρ|≤0.95 则保留,否则降诊断。最近邻一致率:逐卡,每通道最近邻 = 非 null S 最大者(并列取 slug NFC UTF-8 字节序最小;该卡在该通道全 null → 该卡剔除);一致率 = 两通道最近邻相同的卡数 / 两通道均有最近邻的卡数;分母为 0 → 一致率 = null(展示为 null,不触发降级)。审计后冻结 lock 文件(通道清单、golden、Holm family + hypothesis ID、全部词表、READY 谓词、extractor_version),先于任何正式跑批。

5. L3 统计

pair 集枚举(一切统计的底座):self pair 集 = {(i,j) | 1≤i<j≤m}(C(m,2) 无序);cross pair 集 = A×B 全笛卡尔(m_A·m_B,不对称不加倍)。n_eff = 该集上该通道 S≠null 的个数;mean = 该集非 null 值的算术平均

汇总资格(只在完整数据上检查):mean/IQR/LORO 需 n_eff≥4,cross 另需 m_A≥2 ∧ m_B≥2;不满足 → raw-only(展示非 null 原始点);m=1 → self=null;m=0 → 缺席。self-consistency := 该 config self pair 集上非 null 相似度的 mean(资格同上)。bootstrap band 已全套删除——LORO 是唯一的敏感性量。

  • LORO:逐一剔除 run(self:剔除后剩余 run≥2;cross:两侧非空),且剔除后剩余非 null pair≥1 才算有效剔除;报 LORO min–max 与有效剔除数;剔除后不再查 n_eff≥4。
  • separation(A) = mean(intra A) − mean over B of sim(A,B):资格 = self n_eff≥4 ∧ B 集非空;B 集 = 除 A 外全部达 cross 资格的预注册 config,等权;覆盖率 = |B 集| / (预注册 config 总数 − 1),分母为 0 → null;覆盖率 <80% → null。
  • distinctiveness(A) = 1 − max over B of sim(A,B),B 集与 separation 完全相同(资格/覆盖率/null 规则同);随附最近邻名,并列时取 NFC UTF-8 字节序最小的 config_id。exploratory 折叠。
  • style-vs-implementation 散点:x = code 类某通道 self-consistency,y = visual 类某通道 self-consistency(通道由 UI 选定,值即 §5 已定义量,无新统计);仅展示有资格值。exploratory 折叠。
  • 因子(family/effort/protocol)描述差值:移入未冻结探索项(水平/contrast/权重/null 资格未独立规格前不进 v1.0 报告),无 p 值。
  • 随机化配对检验(quality-instruction sensitivity 专用):
    • 统一检验统计量 T_{config,h}:h ∈ 通道集 ∪ L1 标量集。通道:T = self-consistency_q − self-consistency_min(self 按本节 pair/n_eff 规则,任一侧无资格 → null);L1 标量:T = mean_q − mean_min(valid run 上均值差,任一侧 valid run 数为 0 → null)。重随机化 = 在 Ω_c 内重抽分配(§1.2 编码),按 (block, 时间位次) 重标注 outcome 后从头重算 T
    • 逐 config 探索检验:Ω_c 精确全枚举(N=5 → |Ω_c|=20,无 MC);双侧 p = #{ω∈Ω: |T(ω)|≥|T_obs|}/|Ω|(观测含于 Ω);T_obs=null 或任一 ω∈Ω 下 T(ω)=null → p=null;粒度 1/|Ω_c|(仅 N=5 时为 1/20)如实标注。
    • pooled 主检验:每个 pooled hypothesis 的 mask_h = 冻结入 lock 的完整 config_id 列表(构建时 NFC UTF-8 字节序 + 列表 hash;缺失/失败 config 留在 mask 内按严格 null 传播,不得事后移除);config 顺序 = 持久化数组顺序(§1.2,禁重排);Ω_c 按 §1.2 整数升序 rank 编号;每个 hypothesis h 使用独立 PRNG 流:seed_h = uint64_le(SHA256(b"perm\0" ‖ NFC(hypothesis_id).encode("utf-8"))[0:8]) XOR 20260716,Generator(PCG64(seed_h)).integers(0, |Ω_c|)(任何其他随机过程用 "boot\0" 等独立域派生,流之间零共享);每轮 j(1..B_perm=10000)按 config 序依次抽索引(独立均匀有放回)组成 ω_j;T_pool(ω) = 预注册 mask 内 T_{config,h}(ω) 的等权 mean;观测不注入;b = Σ_j 1[|T_pool(ω_j)|≥|T_pool(ω_obs)|];p = (b+1)/(B_perm+1)
    • null 传播(严格,对每个 h 同规则;v11 穷举预检):MC 抽样前,对 mask_h 内全部 config × 全部 ω∈Ω_c 穷举计算 T_{config,h}(ω)(|Ω_c|≤20,代价可忽略);任一为 null → 该 pooled hypothesis p=null,不执行抽样;全部有定义才跑 B_perm=10000。(T_pool(ω_obs)=null ⇔ T_obs 无定义,自动被预检覆盖。)
    • hypothesis ID 清单(层级 × config/池 × h)与 Holm family 冻结入 lock,未锁死不得出 p;Holm 处理 p=null:null 假设不参与排序,step-down 分母仍按完整预注册 family 大小 k(保守)
  • 通道审计(通道间 Spearman、最近邻一致率、null 率)仅展示,不 gate。

未冻结探索项(不在 v1.0 lock,不出现在正式报告):层次聚类、dendrogram、cophenetic 相关、bootstrap-of-runs subtree support、因子(family/effort/protocol)描述差值对比——待独立规格(linkage/tie/重采样单位/对比水平与权重全部钉死)后另行冻结加入;在此之前任何展示只能出现在明确标注 unfrozen exploratory 的开发页。

6. L4 行为探针

契约内(pass/indeterminate/fail;错误态三值语言无关:pass=非空白∧无 canary 数据∧词表命中,indeterminate=非空白∧无 canary∧词表未命中(附截图),fail=空白或呈现伪造数据;参数正确性=URL 串行断言,提取 ambiguous/not-found → indeterminate)。

网络管控:白名单 = 恰好一次 harness 初始文档 URL + 同源 GET 精确 /api/om/forecast/api/om/archive;重定向逐跳校验;ws/wss 显式拦截;service worker 禁用;浏览器缓存禁用;data:/blob: 合法;其余一切请求(含同源静态资源)= violation 并阻断。

契约外(中性 observed/not-observed/n-a,不进通过率):loading 中间态(?delay=3000,t=1s 帧)、in-page 竞态(检测到切换控件才跑)、console 错误、无 JS 兜底。

7. 呈现

反排行榜硬规则:slug 字典序默认、禁默认排序表、固定 [0,1] 中性单调色域、null 格显式、m/N 与 n_eff 角标、exploratory 默认折叠、禁语 lint 进 build(违者 fail)、similarity≠quality 页脚。profile 默认层:原始分布 strip、逐通道值、探针结果、double-render 一致率、旗标(violation/fence/content-not-ready/…)、请求侧保真;保真 = 逐字段态表不聚合。前端零计算。

8. 管道

run(N slots × configs × {P-min,P-q} 配对随机化;§1.1 终态五分)
  → outputs/*.html + attempts.json
build_cards → cards.json
shoot(Docker;§2.1 状态机;§2.2 冻结主图;§2.3 frame-change;§2.4 double-render;
      §6 探针;reference fixture)
  → screenshots/ + probes.json + flags.json
metrics → scalars.json + matrices.json(逐通道 run 级;golden 自检先行)
stats  → stats.json(§5;seed 按 §5/附录 A 域派生,无全局共享流)
report → 静态 HTML(§7;lint)
verify → metrics/stats 重跑 hash + fixture 漂移比对

attempts/flags/字段态/stats 全部配版本化 JSON Schema(枚举、null 语义、READY 谓词、终态五分在 schema 层锁死)。批目录:双 prompt hash、snapshot hash、镜像 digest、commit、extractor_version、分配表、manifest(原文+hash)。

9. Prompt 变体(v5 prompt)

  • P-min = prompt-v5-min.txt:中性最小信息契约(name/date/max/min/condition/hourly,Celsius,错误须声明)+ 契约 query 写死(daily/hourly 字段、timezone=UTC、temperature_unit=celsius、start_date/end_date)+ fence 禁令 + today=UTC。
  • P-q = P-min + 末行 "Pay particular attention to visual design quality.";构建时字节断言 q_bytes == min_bytes + fixed_suffix
  • 实验 = quality-instruction sensitivity:测输出特征变化,不宣称质量提升;配对随机化(§1.2);检验(§5);分析默认 within-variant。
  • "weather card" 措辞保留(项目身份),记录为任务定义一部分。

10. 已知局限(公开)

  • 截图外行为(hover/滚动/响应式)不可见;探针覆盖有限交互。
  • render 噪声与采样噪声未分解(double-render 一致率单列,self-consistency 两者混合,须并读)。
  • hourly 对 canvas/SVG 无文本呈现常 not-found;数据取回由请求侧校验兜底。
  • agent/cli 协议 system prompt 注入为已知混杂(字段落盘),不矫正。
  • m/N 条件化:相似度基于 valid 输出,终态分布必须一起读。
  • content-not-ready 率含墙钟调度噪声,与 double-render 分读。
  • acceptance-unknown 保守耗预算(可能实际未计费,宁少跑不超支)。
  • 逐 config 检验 p 粒度 1/|Ω_c|(N=5 → 1/20),仅探索;主推 pooled。
  • 除 §5 随机化实验外无任何检验;一切区间是描述性敏感度。

11. 上线前验证清单

  1. 42 卡开发集通道冗余审计 → 全序贪心定稿 → lock 冻结(通道清单、golden、Holm family + hypothesis ID、manifest_hash、manifest schema 文件 SHA256 + schema_version、各 pooled hypothesis 的 mask_h(config_id 列表+hash)、词表、READY 谓词、extractor_version)。
  2. golden fixtures(期望独立写定)入 CI。
  3. reference fixture 跨两机两日漂移实测。
  4. 保真判定器 42 卡人工抽查(≥10:图表-only、非英语、无 label 部分 hourly、多 label)。
  5. JSON Schema 定稿。
  6. P-min/P-q 各 N=5 × 3 config 试跑(配对随机化、slot 五终态记账、状态机旗标率)。

附录 A:算法常量与版本表(合并全表,实现唯一依据,禁 latest)

环境与时序

渲染 Chromium(Playwright 钉版,批目录记录);--font-render-hinting=none;软件渲染;DSF=1;UTC;en-US;字体清单落盘;service worker 禁用;HTTP cache 禁用
虚拟时间 t_v=5000ms;frame-change t_v+{700,1300,2100,3400}ms;稳定性间隔 250ms、重试 3 次、unstable 截最后一次比对第二时刻帧;动画相位(v12.3):有限次 → delay+activeDuration−1ms;无限循环 → 0
就绪 mutation 静默窗 500ms(墙钟);补等 2×rAF+250ms;硬上限 15s;READY_NORMAL=∃可见温度候选;READY_ERROR=非空白∧错误词表命中;按场景选定不双评;[data-ready] 仅诊断
随机 Math.random=mulberry32(0xC0FFEE);统计 PRNG:每 hypothesis 独立流 seed_h=uint64_le(SHA256(b"perm\0" ‖ NFC(hypothesis_id).encode("utf-8"))[0:8]) XOR 20260716,Generator(PCG64(seed_h));其他随机过程用独立域(b"boot\0" 等)派生;B_perm=10000;p=(b+1)/(B_perm+1);pooled MC 前穷举预检 mask×Ω 全部 T,任一 null→p=null 不抽样;bootstrap band 不存在
Date 冻结 snapshot fetched_at
slot 终态 valid/model-failed/infra-failed/acceptance-unknown/unreachable;m=count(valid);未发送重试上限 5

图像预处理:Pillow 钉版(lockfile);resize=LANCZOS;灰度=Rec.601(0.299,0.587,0.114);alpha 白底合成;色彩转换 sRGB(IEC 61966-2-1)→XYZ→CIELAB,D65。

L1 视觉标量公式(输入 128×80 float64,除注明外)

公式
colorfulness Hasler–Süsstrunk:rg=R−G,yb=(R+G)/2−B;M=√(σ²_rg+σ²_yb)+0.3·√(μ²_rg+μ²_yb)(σ=总体标准差 ddof=0)
亮度 mean(Rec.601 灰度),[0,255]
对比度 灰度总体标准差(ddof=0)
留白率 v-color 同款 64-bin 量化后最频 bin(并列取 bin 索引最小)的像素占比
frame-change §2.3:相邻虚拟帧逐像素变化(任一通道差>0 计变)占比的 median/max

视觉通道

通道 定义
v-phash 灰度 LANCZOS→32×32,float64;scipy.fft.dctn(type=2, norm="ortho")(scipy 钉版);取 [0:8,0:8] 含 DC,C-order 展平为 64 系数;阈值=numpy.median(64 值,偶数取中二均值);bit=1 若系数>中位数,=中位数→0;sim=1−hamming/64
v-dhash 灰度 17×16,水平相邻差分(右>左→1)→256 bit;sim=1−hamming/256
v-color 128×80 RGB,每通道 >>6(4 级),64 bin 直方图,占比归一,cosine
v-palette Lab bins:L∈[0,100]×4;a,b clip [−110,110] 各×6;bin=半开区间 [lo,hi),各维最末 bin 闭合 [lo,hi];bin 索引=C-order (L,a,b);代表点=bin 中心;K_ij=exp(−‖c_i−c_j‖²/2σ²),σ=10(ΔE76);S=h₁ᵀKh₂/√(h₁ᵀKh₁·h₂ᵀKh₂)(PSD 有证,S∈[0,1]);L1 swatch:仅非零 bin,≤8,排序键 (−weight, bin 索引)
v-layout 32×20 灰度展平,cosine
v-edge 输入 320×200 灰度 float64;gx=scipy.ndimage.sobel(img, axis=1, mode="reflect"),gy=scipy.ndimage.sobel(img, axis=0, mode="reflect");θ=atan2(gy,gx)·180/π,映射 ((θ mod 180)+180) mod 180 ∈[0,180);幅值=√(gx²+gy²);硬分箱 [0,22.5),…,[157.5,180) 8 bins(角度升序 bin 0..7),幅值加权;4×4 cells(每 cell 80×50 px);cell 内 L1 归一(全零 cell 保持全零);拼接序 = cell 行主序(上→下,行内左→右)× cell 内 bin 0..7,128 维 cosine
v-ssim 输入 320×200 灰度 uint8;skimage.metrics.structural_similarity 钉版:win_size=7,gaussian_weights=False,data_range=255,channel_axis=None,K1=0.01,K2=0.03,use_sample_covariance=True;raw=函数返回标量(含库内边界裁剪语义);正式通道值 v-ssim=clip((raw+1)/2, 0, 1);raw 仅作诊断字段;统计/golden/报告一律用映射值

代码通道

通道 定义
c-shingle normalize=去注释+压空白+小写;k=5 字符 shingle,Jaccard
c-winnow 词法化(标识符→ID、class→CLS、数字→NUM、字符串→STR);k=5 token-gram,winnow w=4;指纹 Jaccard
c-feature 特征集 Jaccard(CSS 属性/tag/JS API 词表版本化/class token)
c-ast-js acorn-loose 钉版,ecmaVersion=2023,先 script 后 module;前序遍历相邻 node-type 对 bigram 直方图 cosine;解析失败→token-bigram,成对一致
c-css-prop postcss 钉版;property 名频次分布 cosine
c-ncd 诊断;C=len(lzma.compress(FORMAT_XZ, preset=6, 单流));输入 UTF-8 NFC;拼接=无分隔字节串联;NCD(x,y)=(C(x∘y)−min(C(x),C(y)))/max(C(x),C(y));NCD_sym=均值双序;sim=1−clamp(NCD_sym,0,1),未 clamp 并存

DOM 通道

通道 定义
d-geom 可见元素(rect∩viewport ∧ display/visibility 非隐藏 ∧ opacity>0.05);满幅排除(v12.2 修正):元素与视口裁剪后盒面积 ≥ 0.99 × 视口面积(1280×800 下即 ≥1013760 px²)者不参与占格——含 html/body 与满幅背景包装元素;网格 32×20(cell=40×40 px on 1280×800);占用 o(cell)=min(1, Σ_elem area(rect∩cell)/area(cell));weighted IoU = Σ_cell min(o₁,o₂) / Σ_cell max(o₁,o₂);双侧全零 → S=null。(v12.2 修订记录:实现期 §11 审计发现原谓词退化——html/body/满幅包装使全部 640 格恒饱和 → 全对 S≡1.0 零方差;排除满幅元素后恢复区分信号(开发集实测 0.74–0.81)。本条为 12 轮评审后的实现期修正,首个正式批 lock 前生效。)
d-text 可见文本剔除动态字段;k=5 token shingle,Jaccard
d-pqgram p=2,q=3,label=tag;sim=2·Σ_g min(cnt₁(g),cnt₂(g)) / (|bag₁|+|bag₂|),|bag_i| := Σ_g cnt_i(g)(多重度总质量);dist=1−sim;空 bag→S=null
d-tagpath 诊断;root→leaf tag 路径集合 Jaccard

统一规则

零向量/空集/空 bag 任一侧 → 该 pair S=null(双空亦 null);null 不进 mean
pair 集 self={(i,j)|i<j}(C(m,2) 无序);cross=A×B 全笛卡尔;n_eff=非 null pair 数;mean=非 null 算术平均
汇总资格 n_eff≥4,cross 另需两侧 m≥2;LORO 有效剔除=self 剩余 run≥2 / cross 两侧非空,且剩余非 null pair≥1;资格只查完整数据
separation 资格=self n_eff≥4 ∧ B 集非空;覆盖率=|B|/(预注册 config 数−1),分母 0→null,<80%→null
分位数 linear interpolation;IQR=P75−P25
随机化 bit 0=min→q、1=q→min;合法 |n₀−n₁|≤1;编码=N-bit 无符号整数(b[0]=MSB)升序 rank;outcome 粘 (block,时间位次);**观测分配:批冻结统一 N;manifest=规范 JSON(见 §1.2,排除运行时字段),manifest_hash=SHA256 小写 hex 入 lock;seed_assign=uint64_le(SHA256(b"assign\0"‖bytes.fromhex(manifest_hash)‖b"\0"‖NFC(config_id).utf8‖b"\0"‖uint8(N))[0:8]),每 config 独立 PCG64 恰一次 integers(0,|Ω_c|);遍历序=config_ids 持久化数组顺序(构建时 NFC UTF-8 字节序,使用处禁重排)×block 升序;pooled mask_h=lock 内冻结 config_id 列表(构建序+hash,失败 config 不移除);逐 config 精确枚举(粒度 1/|Ω_c|,N=5→1/20),T_obs=null 或任一 ω 下 T=null → p=null;pooled=持久化数组序 × rank 编号 × seed_h 独立流有放回逐 config 抽索引 × B_perm=10000,MC 前穷举预检 mask×Ω;双侧 |T(ω)|≥|T_obs|;T_{config,h}:通道 h → self_q−self_min,L1 标量 h → mean_q−mean_min(任一侧无资格/无 valid → null),重标注后从头重算;null 严格传播(对每个 h 同规则)→p=null;Holm:null 不参与排序,分母按完整 family 大小 k
通道全序(贪心去留) 15 通道(c-ncd、d-tagpath 永久诊断,不参与):v-dhash, v-color, v-layout, c-shingle, c-feature, v-phash, v-ssim, v-palette, v-edge, c-winnow, c-ast-js, c-css-prop, d-geom, d-text, d-pqgram;阈值 |ρ|≤0.95;Spearman 观测单位=开发集全部 C(42,2)=861 无序 card pair,midrank ties,pairwise-complete(任一通道 null 剔除该 pair),完整 pair<20→null 不降级;NN 一致率=逐卡最近邻(非 null S 最大,并列 slug NFC UTF-8 字节序最小,全 null 剔卡)相同数/双通道均有 NN 卡数,分母 0→null

保真

文本归一 NFC+trim+空白折叠+casefold
数值 decimal quantize ROUND_HALF_UP(ties away from zero);显示位数 d 对齐;禁裸 round
显著度 (f_max−f)/f_max<0.10
绑定 候选/label = occurrence:原始命中 (node,start,end,pattern_id) 于归一化文本(码点偏移;JS 禁用 UTF-16 index);同 span 合并汇总类别(汇总含两类才作废);重叠不同 span 仲裁=按 (start 升序, length 降序, pattern_id 字典序) 排序后贪心取与已选不重叠者;ID=(node 先序,start,end),按 namespace 分池,occ 序=ID 字典序;距离=二元组(父元素 LCA 边数, |文本坐标差|)(文本坐标=可见文本按 DOM 先序、归一化后累计码点长度,节点间无分隔符;总距离=分量各自求和,字典序比较);f_max=全部温度候选 occ 父元素 font-size 最大值;max/min:前置 E=∅→均 not-found(no-temperature-candidate)不发布 canonical,分支假定 |E|≥1;E=同显著度候选集;双类有效 label:|E|=1→ambiguous,|E|≥2→全局一对一枚举取字典序最小(总距离,max 距离,min 距离,T_max occ 序,T_min occ 序,L_max occ 序,L_min occ 序;T 互异指 occurrence),不降级;单/无 label 路径先行 |E|≥3→ambiguous,单侧键=(距离,T occ 序,L occ 序);canonical=同值 occ 序最小,仅当两 canonical 均产生且 ID 互异、max/min 终态均非 ambiguous 才发布;hourly:预分流(有候选但双 canonical 未全发布→ambiguous;无候选→not-found);候选集=温度 occ−两 canonical occ;label 解析(UTC 模板表)→最大基数单射,比较键=(绑定数降序,总距离(仅已绑定边),定长 per-label 向量:按全 label occ 序,已绑定=(0,dom_dist,text_dist,T_id)、未绑定=(1,0,0,sentinel=(2³¹−1,2³¹−1,2³¹−1));signature=该向量 T_id 序列派生);无 label 恰 24 occ→按 occ 序对齐 UTC 0..23,≠24→ambiguous
词表(全部版本化) WMO 多语 condition、错误态多语、max/min label、小时 label 模板、date locale 模板、可见文本节点选择器
容差 lat/lon ±0.01
禁语 lint 显著/最强/更好/胜出/best/wins/significant/strongest…(版本化)

A note on language

This site ships in English and 简体中文. Model ids, effort tokens, arm names, grade labels, channel names, and config slugs stay in English on both — they are instrument labels, not prose, and CJK on them would break the mono-instrument read. Everything else is authored per language rather than machine-translated, and numbers are formatted for the active locale.