一个页面目录可以在 default layout 旁边放下兄弟版本。同一条 canonical URL。每个版本都是完整的服务端 HTML,在 arc blocklet build / prerender 时生成。
本页是操作合同,2026-08-21 对照 Web Device 在 arc#4548(token delta)和 arc#4557(Split + Select 理由)之后的实现核验。不是设计随笔;动机见介绍文章。
页面内评审是另一项能力,只是共用 HUD。不要把本页当成页面内评审模式的改写。评审把意见写在内容旁(.review/)。变体是在成品渲染里挑选(.experiment/selection.json 加上 variants/ 树)。
什么时候用
适合:
- agent(或人)能在一轮里为同一条路由做出不止一个成品版本;
- 需要在渲染后的页面上看这些版本,包括并排,再决定访客看不看得到;
- 随后想用同一棵树做 cookie 分流。
不要用来:
- 第二套评审浮层、
?experiment=1模式、或客户端 theme 切换; - 单篇文章 / 单篇文档的备选(collection item URL 不是变体页);
- 单个 slot 或单句实验(这一波没有);
- 指标或显著性产品(不在范围里)。
怎么声明
只有 pages/<name>/ 会生长变体。control layout 必须存在。
pages/index/layout.aup # default / control(必须)
pages/index/variants/aurora/layout.aup # 种类 2:整份 layout 树
pages/index/variants/quiet/tokens.json # 种类 1:只改值,继承 default layout
pages/index/variants/_config # 可选:split= / seed=| 种类 | 差什么 | 放进 variants/<name>/ | 继承什么 |
|---|---|---|---|
| 1 值 | token / 具体 CSS 变量 | 只有 tokens.json | default 的 layout 树 |
| 2 结构 | hero、区块顺序、widget | 完整 layout.aup 或 layout.json | 不继承 control 的 layout |
声明了目录却既没有 layout 也没有合法 tokens.json,是构建失败。种类 2 若同目录里还有 tokens.json,这一波会忽略它;不要混放还指望 token 生效。
_config 一行一个 key=value。格式坏了是构建失败,不是跳过:
split=100,0,0
seed=homepage-choose-2026split 权重和 [default, ...目录名(列举顺序)] 对齐,必须加总为 100。省略 _config(或省略 split)则在所有已声明版本上均分。
要让访客先都停在 default、多出来的版本只给写作期用:第一个权重 100,其余 0。改 seed 会重排每一个访客。
Agent 配方:一轮,几个版本
agent 应该产出这个形状。不要另发明一套 API。
- 先读现有的
pages/<name>/layout.aup(以及它已经绑定的 i18n / sources)。 - 分清备选是值还是结构。值 → 只写
tokens.json。结构 → 完整 layout 文件。不要为了改--accent整份拷 layout。 - 每个备选写进
pages/<name>/variants/<name>/,和 control 同一轮交出来,人只要开一次 review。 - 写
_config。访客还不能进实验:split=100,0,0(0 的个数等于非 default 名字数)。 - 对站点跑
arc dsl lint/validate/blocklet check。坏的split或空变体目录在这里红,不要等到请求期。 - 打开渲染页,加
?review=1。用 Split 比较,用 Select 记下赢家。
目录名必须是普通名字(aurora、b、quiet)。.、..、含 / 的名字会被拒。
/zh/articles/<slug>/ 这类 collection 路由不会长出切换条。实验挂在 pages/index/(或别的 pages/<name>/),不要挂在一篇 markdown 旁边。
在评审 HUD 上比较和选定
注入条件仍然只是 ?review=1(值必须是 1)。没有 ?experiment=1。内层 iframe 走 ?embed=1,所以不会再套一层 HUD。
页面列出至少两个名字(含 default)时:
| 控件 | 做什么 |
|---|---|
| 版本按钮 | location.assign 同一路径,带 review=1 和 variant=<name> |
| Split | review=1&split=1。最多四个 iframe,按声明顺序 |
| 格子标题 / chrome | 退出 split:review=1&variant=<该名>,没有 split |
| Select | POST 到 <page>/.experiment/.actions/select,body { selected, reason } |
reason 是同一层 HUD 里当前的 Page note。空或省略仍然成功,并且不写这个键。最长 8192。
?variant= 压过访客 cookie,不写 cookie,并且强制 noindex。未知名字回落到 default,不是 404。

本站 /zh/?review=1 · 2026-08-21。截取来自 arc#4557 之后的本地 Web Device handler,不是已发布的 CLI 标签。

同一路由上的 ?review=1&split=1。内层没有 HUD。每格按 1280px 桌面宽度布局再缩进格子,所以只在桌面跑的 WebGL hero 仍会画。
匿名 cms-write 调 Select 仍是带原因的 401。Select 从不改写 layout 源文件;记录落在页面旁的 .experiment/selection.json。
访客分配、爬虫、SEO
生产 HTML 按版本静态。被分到某桶的访客拿到的是那一版预渲染文档。输出里不带切换实验的 JavaScript。
| 角色 | 拿到什么 |
|---|---|
| 首次到访的浏览器 | 用 (seed, visitorId) 哈希进桶;种 arc_variant_id cookie |
| 同一访客再来 | 同一桶,直到 seed 改变 |
| 可识别的爬虫 UA | 永远 default,不种 cookie |
?variant=(评审 / QA) | 该名字,noindex,不写 cookie |
canonical、sitemap、hreflang 仍指向那一条 URL。给爬虫非 default 版本就是 cloaking。
改 variants/ 或 _config 需要重新构建。没有运行时改配置,没有按地区/设备定向,也没有显著性看板。
限制
| 主题 | 当前合同 |
|---|---|
| 开启标志 | 只有 ?review=1 注入 HUD;单凭 ?split=1 什么都不做 |
| 第二套浮层 | 没有;没有 data-arc-experiment 脚本 |
| 种类 3(一个 slot / 一句) | 未实现;用整页 split |
| 种类 2 同目录再放 tokens | 这一波忽略 tokens |
| Split 容量 | 最多四个 iframe,声明顺序的前几个名字 |
| Split 格子视口 | 每个 iframe 按 1280×800 CSS px 布局再缩进格子(格子里的 matchMedia(max-width: 760px) 为 false) |
| Collection item | 不是变体页 |
| 指标 | 不在范围 |
| 发布快照 | .experiment/ 是写作期记录;不要教成公开 widget |
检查
arc --version
arc dsl lint blocklets/arcblock
arc dsl validate blocklets/arcblock
arc blocklet check blocklets/arcblock然后打开本地打印出的 URL:
http://<host>:<port>/zh/?review=1
http://<host>:<port>/zh/?review=1&split=1
http://<host>:<port>/zh/?review=1&variant=aurora确认:首页有版本条;Split 能看出不同的成品 hero;内层 iframe 没有 HUD;没有 variants/ 的页面仍有评审 HUD,但没有版本条。