Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 24 additions & 45 deletions docs/EVIDENCE.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,31 @@

[English](EVIDENCE.md) · [中文](EVIDENCE.zh.md)

`docs/reports/` 里的每个数字都来自某次 run 自己的产物。这页是两者之间的索引:哪些
文件固定了一次 run 的身份,哪些压缩包装着它的原始结果行,以及每个包的 sha256 应该
是多少。
`docs/reports/` 里的每个数字,都来自某次 run 自己留下的产物。这一页就是"报告 ↔ 产物 ↔ 下载包"三者之间的索引:哪些文件固定了一次 run 的身份(给一次 run 打上指纹)、哪些压缩包装着它的原始结果行、每个包的 sha256 校验和应该是多少。

链条是 报告 → 本索引 → Release 资产。小文件随仓库分发,大产物不进 git 历史。
证据链条是:**报告 → 本索引 → Release 发布资产**。小文件跟着仓库一起分发,大产物不进 git 历史。

## 随仓库分发的部分

`docs/evidence/<run_id>/` 放的是给一次 run 打指纹的文件,合计约 4.7 MB,不下载任何
东西就能核对一个已发布的数字是由什么产出的。
`docs/evidence/<run_id>/` 放的是给一次 run 打指纹的文件,合计约 **4.7 MB**。不看报告、不下载任何东西,光凭这些文件就能核对"某个已发布数字到底是由什么产出的"。

| 文件 | 固定了什么 |
|:---|:---|
| `run_manifest.json` | 引擎版本与 sha256、各生态的 driver pin、runner 源码树 / fixture 树 / 每个编译 adapter 的摘要、seed,以及完整 argv |
| `scores.json` | 按评测轴和 subset 的计数、`score_eligible`、failure class 与 failure origin 的统计 |
| `host_summary.json` | 主机遥测的时间窗、采样数,以及机器当时是否被抢占(`polluted`) |
| `resource_summary.json` | 校准后的资源分布、observer-effect 的 A/B 对比,以及 `resource_comparison_eligible`(仅资源轮) |
| `cold_start.jsonl` | 冷启动诊断,与 warm 画像分开保存(仅资源轮) |
| `run_manifest.json` | 引擎版本与 sha256、各生态的 driver pin、runner 源码树 / fixture 树 / 每个编译 adapter 的摘要、seed,以及完整的启动参数 |
| `scores.json` | 按评测维度和子集的计数、`score_eligible`、failure class 与 failure origin 的统计 |
| `host_summary.json` | 主机遥测的时间窗、采样数以及机器当时是否被抢占(`polluted`) |
| `resource_summary.json` | 校准后的资源分布、观测者效应的 A/B 对比以及 `resource_comparison_eligible`(仅资源轮) |
| `cold_start.jsonl` | 冷启动诊断,与热启动画像分开保存(仅资源轮) |

报告里有两张表可以直接对着这些文件核。四引擎的评测轴表里 Chrome 在 L1 是
5214/5220、L2 是 192/192,就是 `scores.json` 里的值;资源卡片里 Chrome 的 CPU 中位数
687 ms,对应 `by_engine.chrome.metrics.cpu_total_ms.median` 的 686.948。
报告里有两张表可以直接对着这些文件核验。例如:四引擎报告的评测轴表里,Chrome 在 L1 是 5214/5220、L2 是 192/192,就是 `scores.json` 里的原值;资源卡片里 Chrome 的 CPU 中位数 687 ms,对应 `by_engine.chrome.metrics.cpu_total_ms.median` 里的 686.948。

头条的任务级通过率需要结果行本身,因为一道题只有所有尝试都通过才算通过。那些行在下
面的压缩包里。
头条的"任务级通过率"需要原始结果行才能算——因为一道题要**所有尝试都通过**才算通过,而这个信息只存在下面的压缩包里。

## Release 资产
## 发布资产

挂在 [evidence-20260812](https://github.com/lexmount/Lexbench-Headless-Browser/releases/tag/evidence-20260812)
上。这个 tag 命名的是采集时间而不是代码状态:这批 run 采集于 2026-08-12 和 08-13,
而 tag 指向的那棵树比它们更晚。
挂在 [evidence-20260812](https://github.com/lexmount/Lexbench-Headless-Browser/releases/tag/evidence-20260812) 这个 Release tag 上。注意:这个 tag 是按**采集时间**而不是代码状态命名的——这批 run 采集于 2026-08-12 和 08-13,而 tag 指向的那棵树比它们更晚。

每个 `evidence-*` 包含一次 run 的 `results.jsonl`、`host_telemetry.jsonl` 和
`scorecard.md`;每个 `artifacts-*` 包含该次 run 每个 attempt 的原始协议日志,第三方
因此可以审计某一次失败的协议交互,而不只是看结果行。
每个 `evidence-*` 包包含某次 run 的 `results.jsonl`、`host_telemetry.jsonl` 和 `scorecard.md`;每个 `artifacts-*` 包则包含该次 run 每一次尝试的**原始协议日志**——第三方因此可以审计某一次失败到底跟浏览器做了什么交互,而不只是看结果行。

| 资产 | 内容 | 下载 | 解压后 |
|:---|:---|---:|---:|
Expand All @@ -47,13 +37,11 @@
| `artifacts-resource_baseline_20260812.tar.gz` | 59,366 个文件 | 7.1 MiB | 111 MiB |
| `artifacts-resource_engine_20260812.tar.gz` | 70,505 个文件 | 13.1 MiB | 171 MiB |

Kitesurf lane 另有两个资产挂在同一个 Release 上,由
[`kitesurf-eval` 分支的 `docs/EVIDENCE.md`](../../../tree/kitesurf-eval/docs/EVIDENCE.md)
索引。
Kitesurf 通道另有两个资产挂在同一个 Release 上,由 [`kitesurf-eval` 分支的 `docs/EVIDENCE.md`](../../../tree/kitesurf-eval/docs/EVIDENCE.md) 索引。

### sha256
### sha256 校验和

```
```text
3052461b458581c8da620d55c3741d18dc50693d78c7a6ebeffb2241251f12f9 evidence-four_engine_full_20260812.tar.gz
55d4f98f4f386ec2f7856d0b96b2c8f9e9838d872f00f03f1589e6e8a94f51a5 evidence-resource_baseline_20260812.tar.gz
935c6232e5598cddd25cebc11ed2c35e03e43b0d3f77c1bc011787f07c0b8162 evidence-resource_engine_20260812.tar.gz
Expand All @@ -62,47 +50,40 @@ dbf474352f8db054cf61870bc8b0792f8b1d48aa38b8e4ee2a31b337e8bd0ab9 artifacts-reso
6c67855929d185d1a41fc59920d32c62e459a15fd2719c86f611582f8b83b349 artifacts-resource_engine_20260812.tar.gz
```

核对下载
核对已下载的文件

```bash
sha256sum -c <<'EOF'
3052461b458581c8da620d55c3741d18dc50693d78c7a6ebeffb2241251f12f9 evidence-four_engine_full_20260812.tar.gz
EOF
```

打包时固定了成员顺序、归属和 mtime,所以同一次 run 重新打包能得到相同的 sha256。
打包时固定了成员的顺序、归属和 mtime(修改时间),所以同一份 run 重新打包能得到相同的 sha256——指纹可复现

## 重新生成报告

把某次 run 的 `evidence-*` 解压到它的 `docs/evidence/<run_id>/` 旁边,让生成器同时看
到结果行和 manifest,然后:
把某次 run 的 `evidence-*` 包解压到它自己的 `docs/evidence/<run_id>/` 旁边,让生成器同时看到结果行和 manifest,然后跑:

```bash
python3 tools/report_four_engine.py runs/four_engine_full_20260812 \
-o docs/reports/four-engine-report-20260812.md
```

两份已发布的报告都用这种方式从 Release 压缩包里重新生成过,输出与仓库里的副本逐字节
相同。五引擎报告在 `kitesurf-eval` 分支生成,它的输入在那边。
两份已发布报告都用这种方式从 Release 压缩包重新生成过,输出与仓库里的副本**逐字节相同**。五引擎报告在 `kitesurf-eval` 分支生成,它的输入在那边。

## 发布前去掉了什么

Run 产物会记录这一轮实际用过的路径和 origin,这是本地审计线索而不是证据。
`tools/scrub_release_paths.py` 在打包时改写三类信息:
Run 产物会记录这一轮实际用过的路径和 origin(来源主机)——这些是**本地审计线索,不是证据**。`tools/scrub_release_paths.py` 会在打包时改写三类信息:

| 信息 | 改写为 |
|:---|:---|
| 产出这次 run 的 checkout 的绝对路径 | `<repo>` |
| 这一轮 fixture 由哪个 host 提供 | `<static-fixture-origin>` 或 `<dynamic-fixture-origin>` |
| 带非 UTC 偏移的 ISO-8601 时间戳 | 同一时刻的 `+00:00` 表示 |

fixture origin 是从产物自身发现的:verification 报告里的 `base_url`、run summary 里
的 `scope.fixture_base_url`,所以这个脚本本身不写死任何 host。
fixture origin 是从产物自身发现的——verification 报告里的 `base_url`、run summary 里的 `scope.fixture_base_url`——所以这个脚本本身不写死任何 host。

指纹链一律不动:引擎和 adapter 的 sha256 保持原样,只有"通向某个二进制的路径"被当作
本地信息处理。四引擎那次 run 改写了 1,338 个文件里的 5,028 处路径,origin 改写为
零,因为它的 fixture 由 `127.0.0.1` 提供。清洗后的树重新生成两份报告仍然逐字节相同,
这就是"改写没有动到证据"的验证方式。
指纹链一律不动:引擎和 adapter 的 sha256 保持原样,只有"指向某个二进制的路径"被当作本地信息处理。四引擎那次 run 一共改写了 **1,338 个文件里的 5,028 处路径**;origin 改写为零,因为它的 fixture 由 `127.0.0.1` 提供。清洗后的树重新生成两份报告仍然逐字节相同——这就是"改写没有动到证据"的验证方式。

随时复查一棵树:

Expand All @@ -111,6 +92,4 @@ python3 tools/scrub_release_paths.py runs/ --check
python3 tools/scrub_release_paths.py build/release-runs/ --check --origins-from runs/
```

第二种形式用来检查已经清洗过的树。origin 是从产物里发现的,而清洗过的产物已经不再
写出任何 origin,所以这种检查需要原始的树来告诉它要找什么。如果让脚本在没有这个参数
的情况下检查一棵已清洗的树,它会拒绝执行,而不是给出一个根本没验过的"干净"结论。
第二种形式用来检查**已经清洗过的**树。origin 是从产物里发现的,而清洗过的产物已经不再写出任何 origin,所以这种检查需要原始的树来告诉它"要去找什么"。如果让脚本在没有 `--origins-from` 的情况下检查一棵已清洗的树,它会**直接拒绝执行**——而不是给出一个根本没验过的"干净"结论。
28 changes: 14 additions & 14 deletions docs/REPRODUCE.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[English](REPRODUCE.md) · [中文](REPRODUCE.zh.md)

报告里的每一个数字都能追溯到三次 run 之一。这一页记录它们的精确参数、一次 run 怎么变成一份报告,以及你的复现结果对不上时该查什么。
报告里的每一个数字,都能追溯到下面三次 run 之一。这一页记录它们的精确参数、一次 run 怎么变成一份报告,以及你的复现结果对不上时该查什么。

## 三次已发布的 run

Expand All @@ -12,9 +12,9 @@
| `resource_baseline_20260812` | 资源 A 轮 | `l1.raw_cdp` + `l2.web_platform`,557 道 | 5 | 1 | 关 |
| `resource_engine_20260812` | 资源 B 轮 | 同一批 557 道 | 5 | 1 | 开 |

运行参数:bench `2026.08.02-v0_4.1`seed `official20260709``--score-mode independent --chrome-baseline best_effort`引擎 `chrome,moli,lightpanda,obscura`。引擎 pin(版本与 sha256)列在各报告的溯源表里,由 `doctor` 强制校验;二进制的获取位置——[Moli](https://github.com/lexmount/moli)、[Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/)、[Lightpanda](https://github.com/lightpanda-io/browser)、[Obscura](https://github.com/h4ckf0r0day/obscura)——与放置路径见 [RUNNING.zh.md](RUNNING.zh.md)。下面的命令逐字取自各 run 的 `run_manifest.json` 中记录的 `argv`。
三次 run 的共同参数:bench 版本 `2026.08.02-v0_4.1`seed `official20260709``--score-mode independent --chrome-baseline best_effort`引擎 `chrome,moli,lightpanda,obscura`。每个引擎的 pin(版本与 sha256)列在各报告最后的溯源表里,由 `doctor` 强制校验;二进制的获取位置——[Moli](https://github.com/lexmount/moli)、[Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/)、[Lightpanda](https://github.com/lightpanda-io/browser)、[Obscura](https://github.com/h4ckf0r0day/obscura)——与放置路径见 [RUNNING.zh.md](RUNNING.zh.md)。下面的命令逐字取自各 run 的 `run_manifest.json` 里记录的 `argv`(实际启动参数)

功能run:
**功能 run:**

```bash
python3 -m runner.run run \
Expand All @@ -24,7 +24,7 @@ python3 -m runner.run run \
--run-id four_engine_full_20260812 --provenance-level minimal
```

资源run,按顺序执行(B 轮必须引用 A 轮):
**资源 run**(必须按顺序执行,B 轮要引用 A 轮):

```bash
python3 -m runner.run run \
Expand All @@ -46,38 +46,38 @@ python3 -m runner.run run \
--run-id resource_engine_20260812 --provenance-level full
```

观测干扰阈值显式设为 `20` 而不是默认的 10:Chrome 的进程树超过一百个进程,每次 attempt 首尾两次全树 PSS 扫描是测量本身的固有成本;报告里记录了这个选择,并给出实际的任务时长干扰 ≤0.87%。
为什么观测干扰阈值用 `20` 而不是默认的 `10`:Chrome 的进程树超过一百个进程,每次尝试首尾各做一次全树 PSS 扫描,本身就是测量负担带来的固有成本。报告里记录了这个选择,并给出实际的任务时长干扰 ≤0.87%。

资源两轮必须在同一台机器上跑,且中途没有其它负载。只有两轮之间机器状态保持不动,A/B 对比才有意义。
**注意:** 资源两轮必须在**同一台机器**上跑,且中途不能有别的负载。只有两轮之间机器状态保持不变,A/B 对比才有意义。

## 从 run 到报告

报告是生成出来的,不是写出来的
报告是**生成**出来的,不是手写出来的

```bash
python3 tools/report_four_engine.py runs/four_engine_full_20260812 \
-o docs/reports/four-engine-report-20260812.md
```

生成器读 `results.jsonl` 并重新计算一切。对同一个 run 目录跑两遍,输出逐字节相同——这也是验证已发布报告没被手改过的方法:重新生成,然后 `diff`。
生成器读 `results.jsonl` 并重新计算一切。对同一个 run 目录跑两遍,输出**逐字节相同**——这也是验证已发布报告没被手改过的方法:重新生成,然后 `diff`。

## 复现凭什么可比

- `--run-id` 逐字命名 run 目录,所有记录的时间戳都是 UTC。
- 每次 attempt 的种子由 `sha256(seed:task_id:attempt)` 推导,与引擎顺序和壁钟时间无关。
- `run_manifest.json` 对 runner 源码树、fixture 树和编译后的 adapter 二进制做了摘要。对比两次 run 之前先对比这些摘要:摘要不同,说明框架本身不同。
- 每次尝试的随机种子由 `sha256(seed:task_id:attempt)` 推导,与引擎顺序和壁钟时间无关。
- `run_manifest.json` 对 runner 源码树、fixture 树和编译后的 adapter 二进制做了摘要。对比两次 run 之前,先对比这些摘要:摘要不同,说明框架本身不同。
- 结果行不含任何主机绝对路径;每次启动的临时目录记录为 `<ephemeral>`。
- `--provenance-level minimal` 保留硬件与内核事实、去掉 cgroup 路径和 CPU 亲和性这类部署指纹。资源两轮用的是 `full`,因为校准审计需要部署细节;功能轮以 `minimal` 发布。

## 证据放在哪

run 目录不入库(`runs/` 在 gitignore 里;三次已发布 run 未压缩合计超过 1 GB)。已发布的证据以压缩包形式挂在仓库的 GitHub Releases 上每个包内含 `results.jsonl`、`run_manifest.json` 和摘要文件,sha256 校验和随包列出。克隆仓库得到框架和报告;要审计或重新生成时再取证据包
run 目录不入库(`runs/` 在 gitignore 里;三次已发布 run 未压缩合计超过 1 GB)。已发布的证据以压缩包形式挂在仓库的 GitHub Releases 上每个包内含 `results.jsonl`、`run_manifest.json` 和摘要文件,sha256 校验和随包列出。克隆仓库得到的是框架和报告;要审计或重新生成结果时,再去取证据包

## 你的数字对不上时

在得出任何关于浏览器的结论之前,先沿这架梯子往下查:

1. 对比 `run_manifest.json` 的摘要和引擎 sha256 与已发布值。pin 不同意味着你测的是不同的软件——这是一个答案,不是一个错误。
1. 对比 `run_manifest.json` 的摘要和引擎 sha256 与已发布值。**pin 不同意味着你测的是不同的软件**——这是一个答案,不是一个错误。
2. 确认 `doctor` 是绿的,并且结果里没有异常数量的 `infra`。身份失败是环境问题。
3. 功能分层面,flake 级的小差异表现为某些题只过了 3 次中的 2 次;全 attempt 通过的规则让 headline 数字对真实的不稳定敏感,这是有意的
4. 资源数字层面,确认你自己的 B 轮里 `resource_comparison_eligible: true`。没过校准门的轮次产出的数字跟任何人的都不可比,包括我们的。资源数字也永远不外推到 557 道之外。
3. 功能分层面,flake 级的小差异表现为某些题只过了 3 次中的 2 次;"所有尝试都通过才算通过"的规则让头条数字对真实的不稳定敏感,这是有意的设计
4. 资源数字层面,确认你自己的 B 轮里 `resource_comparison_eligible: true`。没过校准门的轮次产出的数字,跟任何人的都不可比(包括我们的)。资源数字也永远**不外推**到 557 道之外。
Loading
Loading