# Preregistered method (published copy) — frozen before the run.
# Authoritative original: iterations/REQ-20260909-01/evidence/lab-redirects-study/method.md
#
# ATTRIBUTION. Preregistered by the orchestrating session; executed by a separate
# subagent; independently reviewed by a different model family. Preregistrar and
# executor are deliberately not the same actor -- that separation is the whole
# point of the attribution line in the body, and of the deviation log's rule that
# only the executor appends to it.
#
# The body below is HASH-FROZEN and reproduced verbatim, byte for byte. Any tool
# or model name inside it is the historical record of who did what on 2026-09-09.
# It is not this publication's byline, and it is not editable here: rewriting one
# word of the frozen span would invalidate the hash this whole document exists to
# certify.
#
# REPRODUCING THE FROZEN HASH. Sections 1-10 are lines 1-122 of the authoritative
# original, which has no header. This published copy prepends the header you are
# reading, so the frozen span starts at line 27 of THIS file:
#
#   tail -n +27 method.md | head -n 122 | md5sum
#   -> edc553bc3dca31a760c2c109dea9a9c5
#
# The body's own self-reference further down says `head -n 122 method.md`. That is
# the original's wording, preserved unchanged, and it is correct against the
# authoritative original. Against this copy, use the offset command above.

# 方法预注册 v1.0 · Cloudflare Pages `_redirects`：哪些规则形态会**静默失效**

**预注册时间**：2026-09-09，**开跑之前**。
**预注册人**：编排会话（Claude Opus 5）。**执行人**：另一个子代理。
**这个分工是有意的**——R15.2 要求方法在开跑前钉死、跑完不得回改；
**由不跑实验的人写方法**，跑的人就无法把方法调成迎合结果的样子。
上一个 REQ 的 Field Test 恰恰在这里栽过（R2 轮：三跑有效性下限是在已知排除名单之后写的）。

**冻结声明**：本文件自落盘起冻结。跑完发现方法有问题 → 记在「偏离」一节，**不得回改上文**。

---

## 1 · 问题

Cloudflare Pages 的 `_redirects` 有一类失败模式**不报错**：规则写了、部署了、看起来生效了，
实际被静默忽略，请求落 404。官方文档未系统说明哪些形态属于这一类。

本仓已实测到**一个**这样的形态（跨源 `200` 代理，`../cf-cross-origin-proxy-2026-09-09.md`），
且它直接改变了一条架构决策（D6：账号入口只能跨域跳转，不能反代）。

**本研究问：还有哪些形态属于这一类？**

## 2 · 假设（跑之前写死）

- **H1**：destination 为跨源绝对 URL 且 status `200` 的规则**不生效**，请求落 404。
  （已有单点观测支持，本研究做的是**扩样本 + 加对照**，不是重新发现）
- **H2**：destination 为跨源绝对 URL 且 status `301`/`302` 的规则**生效**。
- **H3**：source 为绝对 URL 的规则**不生效**（Netlify 语义，CF 忽略）——
  仓库 AGENTS.md 铁律 4 记着这条，但**记的是结论不是实测**，本研究补实测。
- **H0（零假设）**：以上皆无差别，全部生效或全部不生效。

## 3 · 固定输入（样本量与矩阵，跑前钉死）

**规则矩阵 = source 形态 (4) × destination 形态 (3) × status (4) = 48 条规则。**

| 轴 | 取值 |
|---|---|
| source | ① 相对路径 `/a/` ② 相对 splat `/a/*` ③ 绝对 URL `https://atomstorm.ai/a/` ④ 协议相对 `//atomstorm.ai/a/` |
| destination | ① 站内相对 `/en/` ② 跨源绝对 `https://example.com/` ③ 协议相对跨源 `//example.com/` |
| status | `200` · `301` · `302` · 省略（默认） |

每条规则**独立命名 source 前缀**（`/r{NN}/`），避免规则间互相遮蔽。
**每条规则请求 3 次**（N=3，取众数；不取均值——离散结果无均值语义）。总请求 144 次。

## 4 · 必须同时跑的对照（缺一则本次运行作废）

| 对照 | 期望 | 作用 |
|---|---|---|
| C1 `/en/` 无规则 | `200` | 证明被测环境本身工作 |
| C2 既有 `/en/blog/ → /en/journal/ 301` | `301` + 目标正确 | 证明既有规则未被 48 条测试规则污染 |
| C3 `/definitely-not-a-route/` | `404` | 证明 404 是真 404，不是全站兜底 200 |
| C4 规则集**为空**时重跑 C1–C3 | 同上 | 证明测试规则的存在本身没有改变基线 |

**有效性下限（跑前钉死）**：C1–C4 **全部**符合期望，本次运行才有效。
任一对照不符 → **整次运行作废，数据不发布**，只记为 did-not-complete。
**本规则对本次运行自身生效**（R15.3）。

## 5 · 指标与记录（每条规则每次请求）

固定用一条命令，`--noproxy '*'` 避免本机代理污染：

```bash
curl -s --noproxy '*' -o /dev/null \
  -w 'status=%{http_code} redirect=%{redirect_url} size=%{size_download}\n' <url>
```

每行记录：`rule_id · source · destination · status_written · run_n · http_code ·
redirect_url · 判读 · 运行 ID · 脚本 commit · 完整命令`（R15.1 标准 12：**结果表每行**都要有后三项）。

**判读枚举（三值，不许出现第四种）**：
- `effective` — 规则按写的语义生效
- `silently-ignored` — 规则未生效**且无任何错误信号**（本研究的靶心）
- `not-observable` — 前置条件未满足，**这一格没得评**

> **`not-observable` 不是 0 分，不是失败**（R15.5）。上一个 REQ 的 R4 轮正是栽在
> 「M1 失败后 M2–M5 无从观测却序列化为 0」——schema 分不出「没得评」与「评过且极差」。

## 6 · 环境（先声明限制，不是跑完再补）

**执行环境 = 本地 Pages 模拟器** `npx wrangler pages dev out --port <free> --ip 127.0.0.1`。

**这不是生产边缘。** 本研究**不主张**结论适用于生产 Cloudflare 边缘。
发布时这条限制必须写在页面**正文靠前处**，不能塞进脚注。

**为什么仍然值得做**（这一段也是跑前写的，不是事后辩护）：
把关键路径押在「官方文档未声明、且本地模拟器不支持」的行为上，本身就是不可接受的脆弱性——
这个论证**不依赖**模拟器与生产边缘是否一致。

**升级路径（本批不做，声明为缺口）**：真实 CF Pages 部署一个一次性测试项目复测。
不做的原因是它会创建一个公开 URL，属于外向动作，超出本批「全自动开发」的授权范围。

## 7 · 止损规则（跑前钉死，对本次运行自身生效）

- 模拟器启动后 **5 分钟**内 C1 拿不到 200 → 记 did-not-complete，**不重跑**、不换工具。
- 单条规则 3 次请求出现 **3 种不同** `http_code` → 该条记 `not-observable`，
  **不得**挑一个好看的、也不得扩大样本量到结果稳定为止（那是 p-hacking）。
- 总耗时超 **30 分钟** → 停，已完成部分照常记录，未完成部分记 `not-observable`。

## 8 · 结论的允许范围（R15.6）

- **允许**：陈述"在本地 Pages 模拟器上、v<wrangler 版本>、某形态观测到 silently-ignored"。
- **禁止**：任何形如"Cloudflare 不支持 X"的普适断言。
- **禁止**：任何排名式基准（本研究不排名，只分类）。
- 若结果与 H1 矛盾（即跨源 200 竟然生效），**必须照实发布**，
  并把 `cf-cross-origin-proxy-2026-09-09.md` 与依赖它的 D6 一并标为需复核。
  **预注册的意义就在这里**：结论对我们不利时也得发。

## 9 · 数据集

`runs.csv`（每行一次请求，字段同 §5）+ `rules.txt`（48 条规则原文）。
license **CC-BY-4.0**，随资源页发布，路径进 frontmatter 的 `dataset`。

## 10 · 独立审查（R15.7）

产出方是 Claude → 审查**必须走 Codex**（换模型族，Agent 不得自证）。
审查报告带 provenance 头：模型 / dispatch 命令 / 基线 SHA / 判决 / 整改 commit。

---

## 偏离记录（跑完才填；上文一律不改）

<!-- 执行人只往这一节追加 -->

**执行人**：子代理（Claude Opus 5）· **运行 ID**：`lab-redirects-20260909T183209Z` · **执行日期**：2026-09-09
**上文第 1–10 节一字未改**（`head -n 122 method.md | md5sum` 跑前跑后同为 `edc553bc3dca31a760c2c109dea9a9c5`）。
以下每条都在**开跑前**写进 `run-log.md §0` 并落盘（D5 / D8 / D9 例外，为跑中发生、已注明）。

**D1 · 方法未操作化"怎么算 effective"**（跑前补，见 run-log.md §0.1）
§5 定了三值 enum 却没给判据。跑前钉死判读映射表：301/302 需码与 Location 双中；
省略 status 预声明期望 302；200+站内需 body 字节 == C1；`silently-ignored` 需 404 且 body 字节 == C3。
不先钉死，跑完再定义即预注册要防的事。

**D2 · §4 的 C4「规则集为空」按"48 条测试规则为空"执行**（跑前）
字面空文件会让 C2（既有 `/en/blog/` 301）**必然**拿不到 301 → 方法自我作废；
而 C4 的**作用**写的是"证明测试规则的存在本身没有改变基线"，故取"测试规则为空"= 仓库原始 `_redirects`。
另跑字面空文件一组（C4-lit）作补充观测，**明确不参与**有效性判定。

**D3 · splat 源的请求路径**（跑前）
`/rNN/*` 请求 `/rNN/probe`，其余请求 `/rNN/`。请求路径须是该规则**声称能匹配**的路径，
否则"splat 空匹配"会混进"规则被忽略"。H1–H3 均不比较 splat 与非 splat，不威胁任一假设。

**D4 · §5 命令外层加 `timeout 30`；`runs.csv` 增第 13 列 `note`**（跑前）
超时是防"跨源 200 若真发起 fetch 而挂死"吃掉 §7 的 30 分钟预算；`command` 列记含 `timeout` 的**实际**命令。
`note` 是在标准 12 列**之后**追加，12 列一列不少。

**D5 · 判读表 0.1 的一处缺陷（跑中发现，未回改判据、未改 verdict）**
"200 + 跨源，任何 200 带非空 body → effective"把**"代理到了跨源目标"**与**"返回了本地内容"**混为一谈。
r09 / r21（`//example.com/` + 200）实测 200，按该表记 `effective`；
但跑后补充观测显示 body 与本地 `out/index.html` 字节相同（md5 `b2b520ff…`），且 example.com 本机可达，
即并非跨源代理，**不构成 H1 反例**。
**处理**：verdict 保持跑前判据的结果不动（不因结果不合意而回改），把事实写进 `note` 与 `findings.md §4.2`。
未来修订本方法时，"200 生效"应加**body 出处**判据。

**D6 · 三值 enum 的缺口：存在"有诊断但未生效"**（跑前预声明处理方式，跑中证实存在）
wrangler 在**解析期**会具名报出无效规则（行号 + 原因），故"静默"只成立在**请求层**。
`verdict` 列只表达请求层（与 §1 的问题陈述"请求落 404"一致）；解析期诊断作为独立观测进
`run-log.md` 与 `findings.md`，逐 rule_id 对照，**不挤进三值 enum，也不新增第四值**。

**D7 · source ③/④ 的 Host 混杂**（跑前声明，跑中由日志解决）
模拟器 Host 是 `127.0.0.1:8793` 而非 `atomstorm.ai`，单看请求层无法区分"解析期被忽略"与"host 不匹配"。
形态 ③ 由解析期具名诊断判定为前者（Host 无关）；形态 ④ **无诊断**，其 404 只能按请求层记录，
该无法区分已写进 `findings.md §4.1`。

**D8 · 第一次尝试因脚本 bug 作废，已整体重跑**（跑中）
首跑 `while read` 丢掉 node 输出的最后一行，**r48 从未被请求**（150 行 ≠ 153 行）。
发现时**尚未查看任何 http_code**，故重跑不是结果依赖的选择。修复后**整体重跑**全部三个配置，
首跑原始数据留档 `/tmp/lab-raw-attempt1-aborted.tsv`。§7 的止损条款针对"结果不稳定就重试"，
不覆盖"请求根本没发出"的脚本缺陷；未做任何挑选。

**D9 · `script_commit` 与被测产物的漂移**（跑中）
另一 agent 在本会话期间提交并改动仓库：HEAD 由会话开始的 `520c032` 变为跑前的 `a715b72`（`script_commit` 取后者）。
为防基线在运行中途漂移，被测产物在首次复制后**冻结**于 `/tmp/lab-out-frozen`
（756 文件，指纹 `46f2e2ca…`），三个配置共用同一份。仓库 `public/_redirects` 与 `out/` 全程只读。

**D10 · 其余执行期选择的登记（应 team-lead 要求补记：「加列不是错，不记才是错」）**

先分清哪些是**方法解释**、哪些只是**方法内的合规执行**——把后者也叫"偏离"会稀释这一节的信号：

| 选择 | 性质 | 说明 |
|---|---|---|
| 端口 `8793` | **方法内合规**，非偏离 | §6 原文就是 `--port <free>`，选一个空闲端口是照做。未与本机既有 8791 实例（**非本次运行**，指向仓库 `out/`）冲突 |
| phase 命名 `B` / `A` / `L` | 执行产物，非方法改动 | B=基线+48 条测试规则；A=C4（测试规则为空）；L=C4-lit（字面空文件）。命名只为日志可读 |
| `runs.csv` 第 13 列 `note` | **已记 D4** | 标准 12 列一列不少，`note` 在其后追加 |
| 被测目录冻结于 `/tmp/lab-out-frozen` | **已记 D9** | 防另一 agent 重建 `out/` 让基线中途漂移 |

**补 D2 未写足的一点（不改 D2 原文，在此追加）**：

phase L（读法 (b)，`_redirects` 字面清空）下 C2 必然 FAIL，**这是读法 (b) 自身的同义反复，不是污染证据**——
`/en/blog/ → /en/journal/ 301` 这条规则本来就住在仓库 `_redirects` 里，把文件清空再去测它"还在不在",
测的是"删掉一条规则它会不会消失",不是"测试规则有没有污染基线"。
故 **phase L 的 C2 FAIL 不构成本次运行作废**；参与 §4 有效性判定的是 phase A（读法 (a)）。

**这是预注册的措辞缺陷，不是执行问题。** 建议 method v1.1 把 §4 的 C4 由
「规则集**为空**时重跑 C1–C3」改写为「**移除 48 条测试规则后**重跑 C1–C3」，歧义即消失。

> 附带：phase L 仍有正面价值——空规则集下 C2 确实退化为 404，
> 反证了三个配置各自服务自己的规则集、没有跨配置残留（findings.md §1）。
