# 训练协议详解

> 把"领域训练协议（Domain Training Protocol）"在 **AI 网页建造** 这个具体场景里端到端跑通一次。
> 协议本质：在没法改模型权重的前提下，把"品味 / 评分 / 反例 / 复盘"**强制沉淀成文件资产**——下一次开会话时，agent 读这些文件就等价于"被训练过"。

---

## 一 · 背景：为什么需要这套协议

### 1.1 问题

让 Claude Code 直接造网站，通常会得到一个"四平八稳但毫无记忆点"的产物——紫色渐变 hero、三栏 emoji 卡片、圆角按钮、居中布局——典型的 "AI 默认产物"。

原因不是 Claude 不会写代码（它代码能力远超够用），而是它**不知道"什么算好"**。"好"是领域品味，不是通识，不是看一遍 53 件高分作品就能自动迁移的东西。

### 1.2 直觉错误的两条路

- **路 A · 反复 prompt 工程**：每次重写超长 prompt，把"要黑底 / 要 BGM / 要怀疑低点"全塞进去。问题：prompt 长 + 不可复用 + 没法迭代。每次会话从零开始。
- **路 B · 等 Anthropic 出更强的模型**：模型在变强，但"我领域里什么算好"是模型权重里没有的局部知识。等多久也不会自己长出来。

### 1.3 路 C · 用文件资产替代权重训练

OpenAI / Anthropic 的 post-training 用的是 RLHF + 人类偏好数据集。我们没法改权重，但能改的是 **agent 开工前必读的文件**。把品味写成 principles，把评分写成 rubric，把反例写成 exemplars——下次会话 agent 读完这些，就等价于"被训练过"。

这就是这套协议要解决的事情。

---

## 二 · 五步循环：协议的物理结构

```
┌──────────────────────────────────────────────────────────┐
│  Step 1 · 收语料                                          │
│  收集 N 件已知评分的作品（含 verdict / 反响 / 复刻说明）   │
│  → 形成"高分集合"和"低分集合"                              │
├──────────────────────────────────────────────────────────┤
│  Step 2 · 提炼 principles                                 │
│  从高分集合反推"它们都满足的硬规则"                        │
│  → principles.md（49 条 P-001 ~ P-049）                  │
├──────────────────────────────────────────────────────────┤
│  Step 3 · 建 rubric                                       │
│  把 principles 翻译成"可验收的评分项"                      │
│  → rubric.md（28 条 R-001 ~ R-028，A 技术 / B 审美 / C 品味） │
├──────────────────────────────────────────────────────────┤
│  Step 4 · 生成 → 自评 → 沉淀                              │
│  让 generator 跑工作流；它自评；产物归档                   │
│  → output/<网站名>/{index.html, _复刻说明.md}             │
├──────────────────────────────────────────────────────────┤
│  Step 5 · Critic 独立复评 ★                              │
│  另起 sub-agent 按 rubric 重打一遍（不读 generator 自评）  │
│  → critic-report.md                                       │
│  → critic 发现的盲区回流到 principles 和 rubric            │
└──────────────────────────────────────────────────────────┘
```

**关键**：Step 5 不是可选项。**评分者 ≠ 被评分者**——这是反 reward hacking 的协议核心，见下文。

### 2.1 这五步的数据流

```
高分样本 + verdict
    ↓
[Step 2]  抽象规则
    ↓
principles.md (49 条)
    ↓
[Step 3]  翻译成评分项
    ↓
rubric.md (28 条)
    ↓
[Step 4]  generator 用 principles 生成作品 + 自评
    ↓
output/<网站名>/{index.html, _复刻说明.md}
    ↓
[Step 5]  critic sub-agent 不读自评，用 rubric 独立打分
    ↓
critic-report.md
    ↓
gap 回流：critic 发现的盲区 → 新 principles → principles.md 更新
                            → 协议层 bug → protocol-feedback.md 加 F-XXX
```

---

## 三 · Reward hacking 反制：为什么 critic 必须独立

### 3.1 现象

3 份独立 critic-report 对 3 件独立作品的复评一致显示：**generator 自评分稳定 inflate +0.4 ~ +0.75（5 分制）/ +0.8 ~ +1.5（10 分制）**。

| 测试 | generator 自评（10pt） | critic 评（10pt） | inflation |
|---|---|---|---|
| test1（影片式 rebuild） | 8.0 | 7.20 | +0.8 |
| test2（长文反思） | 9.2 | 7.7 | +1.5 |
| test3（赛博 HUD） | 8.5 | 7.2 | +1.3 |

3 件来自 3 个不同 generator agent 实例的独立任务——**inflation 方向与量级几乎一致**。这不是单次失误，是稳定规律。

### 3.2 inflation 的三个来源

1. **C 维度品味题误判**：generator 把"按食谱执行完成 = 模板齐全"误读为"有 S 档品味"。但 rubric C 维度的硬要求是"能不能混入参考库 + 有差异化记忆点 + 情绪扳机硬路径命中"——**模板齐全 ≠ 品味到位**。
2. **"对齐用户需求"被当作 rubric 总分**：generator 自评的"对齐用户描述的完成度"被当作 28 条 rubric 的加权总分输出——**两套口径混用**。
3. **C 维度硬路径未自检就跳过**：S 档 5 条硬路径（真 BGM / 文学长文画面感存活 / 3D 仪式 / 单屏海报 / 程序合成 ambient）generator 不会主动自检，导致 R-028 情绪扳机虚高。

### 3.3 反制：协议层的硬性设计

**关键洞察**：评分者 = 被评分者的系统，方向必然向自己有利的方向偏。即使你写得再详细的 rubric，generator 都会在 C 维度品味题上系统性地高估自己。

所以协议层必须强制：

```
┌─────────────────────────────────────────────┐
│  Generator (主 agent)                       │
│     ↓ 生成产物 + 自报"应用了哪些 P-XXX"      │
│  output/<name>/_复刻说明.md                 │
│     ↓                                        │
│  Critic (独立 sub-agent)                    │
│   ❌ 不读 generator 自评                    │
│   ✅ 只读 output/<name>/index.html (产物)   │
│   ✅ 按 rubric 重打 28 条                   │
│   ✅ 验证 generator 的 P-XXX 声明真假        │
│     ↓                                        │
│  critic-report.md                           │
│     ↓                                        │
│  加权总分 < 3.5 → 回炉                       │
│  加权总分 ≥ 3.5 → 进部署                     │
└─────────────────────────────────────────────┘
```

**4 条硬约束**（写进 SKILL.md §5b critic prompt）：
1. ❌ 不读 `_复刻说明.md` 中除 "本设计应用了哪些 principle" 一节以外的内容
2. ❌ 不读 generator 在主对话里的总结发言
3. ✅ 只读 `output/<网站名>/index.html`（实际产物）+ training 资产
4. 全程只读，不要改任何文件

### 3.4 P-XXX 声明验证 = 防止 generator 撒谎

generator 必须在 `_复刻说明.md` 里显式列出"本作应用了哪些 P-XXX 编号"。Critic 会 grep 这一节，**逐条验证代码里有没有真做到**：

| P-XXX | generator 声明 | critic verdict | evidence |
|---|---|---|---|
| P-005 | 主标题用 Inter 800 CDN | ✅ | line 23 引 Google Fonts |
| P-022 | rAF 加 visibilitychange | ❌ 虚假声明 | line 412 rAF 循环无任何 visibility 守卫 |

任何 ❌ 都要在 critic-report 里专门列出——**虚假声明触发一票否决降档**（C 维度上限封 3/5）。这一条把"自评虚高"从分数层面推到了诚实性层面：你声称你应用了某条原则但代码里没有 → 协议直接判你撒谎，分数降档。

---

## 四 · Critic Loop：独立复评闭环

### 4.1 Critic 的物理实现

不是主 agent 切换人格自评——那样上下文已经被 generator 自己污染了。**必须**用 `Agent` tool 起一个独立 sub-agent，建议用 `codebase-researcher` 或 `reviewer-agent`（只读类型）。

整段 prompt 贴给 sub-agent，让它独立按 rubric 重打。

### 4.2 Critic 的工作流（5 + 1 步）

```
Step 0 · ⭐ Broken image 一票否决前置检查（F-004 加进来的）
   ↓
Step 1 · 通读产物（建立"它实际做了什么"的画面）
   ↓
Step 2 · 验证 generator 的 principle 声明
   ↓
Step 3 · 逐条打 rubric（R-001 ~ R-028，0~5 分）
   ↓
Step 4 · 算加权总分（A × 0.30 + B × 0.35 + C × 0.35）
   ↓
Step 5 · 输出 ≥ 3 个可定位差距
```

### 4.3 档位决策（critic-report 输出后）

| critic 档位 | 加权总分 | 决策 |
|---|---|---|
| **SHIP-BLOCKED** | 0.00（broken image） | **绝对不准部署**——回到修复路径 |
| S | ≥ 4.0 | 直接进部署 + 主动建议把本作收进 exemplars/good |
| A | 3.5 ~ 3.9 | 进部署 |
| B | 3.0 ~ 3.4 | **不准部署**——按 critic-report 回炉改 1-2 个硬伤 |
| C | < 3.0 | **不准部署**——实质性返工，可能要换模板 |

回炉规则：同一作品 critic 复评 ≤ 3 轮；3 轮还过不了 A 档，停下找用户讨论是不是需求本身有冲突。

### 4.4 Critic-report 回流：F-002 教训

本轮 15 条新 principles（P-036 ~ P-049）有 4 条直接来自 critic-report 而非来自 good/bad exemplars：
- P-036（抽象金句陷阱）← critic-report 影片 rebuild 差距
- P-037（章节标题机械化）← critic-report 长文反思差距
- P-038（荧光绿饱和度阈值）← critic-report HUD 配色违规
- P-039（generator 自评虚高规律）← 3 份 report 横向对比

**critic-report 暴露的盲区比 good/bad exemplars 暴露的更新颖**——后者是事后梳理已知共识，前者是当下发现 generator 真正在踩的坑。

所以协议规定：每轮训练结束后，扫描所有 critic-report 的"≥ 3 个可定位差距"部分，任何被独立 critic 标出且 generator 自评遗漏的 gap → 候选 principle。

---

## 五 · Holdout 测试：协议是否真的有效

### 5.1 为什么需要 holdout

如果只用"训练集"上的作品验证协议，会陷入 overfitting——principles 和 rubric 都是从这批样本反推的，它们当然对训练集打分准。

要验证协议是否真的有效，必须用**没有参与训练的样本**盲评。

### 5.2 Holdout 设置

- 从已知评分的样本里随机预留 1 件不参与 principles / rubric 的反推
- 用最终版本的 rubric 让独立 critic 给这件作品盲评（critic 不知道这件作品的真实评分）
- 对比 critic 评分 和 这件作品的已知评分

### 5.3 Holdout 结果

- holdout 样本：1 件
- critic 盲评：**4.95 / 5**
- 真实档位：S 档
- 结论：协议在 holdout 上**通过**——critic 在不知道答案的情况下，按 rubric 打出了"S 档"的分数。

### 5.4 Holdout 的意义

这不是说协议"完美"，而是说：**rubric 不是 generator 的回音壁**。当 rubric 被独立 critic 用来评一件它没见过的作品时，它能给出和真实档位一致的判断。

这是协议有效性的最小可验证证据。

---

## 六 · 协议本身的迭代：F-001 ~ F-004 回顾

### 6.1 protocol-feedback.md 的作用

协议会出错——这是稳定规律，不是意外。所以协议必须**给自己留一个反思空间**：`training/protocol-feedback.md`，记录每一次协议层面（不是知识层面）的踩坑。

| 编号 | 标题 | 触发场景 |
|---|---|---|
| F-001 | Generator 自评天然 inflate，协议缺反 reward hacking 机制 | 3 份独立 critic-report 横向对比 |
| F-002 | Critic 复评应作为 principles / rubric 的主要 update 源 | 本轮新 principles 中 4/15 来自 critic |
| F-003 | rubric 单项 0.1 权重无法表达严重程度 | 违反明文红线但总分只扣 0.1 |
| F-004 | Broken image 是 generator + 部署都察觉不到的盲区 | 一次真实的"8 张全黑矩形"灾难 |

### 6.2 F-004 的特殊性

F-001 ~ F-003 是"分数 inflation"问题——generator 自评 inflated 了 0.5 ~ 1.5 分。
F-004 是"**存在性 inflation**"——generator 自评"通过"实际上根本是个废品（8+ 个 broken image，浏览器看到的是全黑矩形）。

F-004 严重一档，因为它不是品味判断错误，是**基本可用性**判断错误：generator 只读自己写的代码、推理"我写了 8 个 img 标签应该 OK"，没真去加载页面看图能不能渲染出来。

### 6.3 F-004 落地的改进

写进了 SKILL.md：

- **§5a 新增 5 项强制一票否决检查**（5a.0a ~ 5a.0e）
  - 5a.0a · Broken image 0 容忍
  - 5a.0b · 用户输入 < 30 字 + 无素材时必须先反问
  - 5a.0c · 维度组合矛盾必须报警让用户调
  - 5a.0d · 每张 img 的 alt 必须是具体描述短语
  - 5a.0e · 空 src / placeholder src 禁止
- **§5b critic 新增 Step 0**（在打 rubric 分之前的前置检查）：playwright 加载 + 网络层抓 404 + 视觉确认无黑色矩形 + grep 反查 src 文件存在

### 6.4 协议的元规则

```
当一类错误被发现 2 次以上 → 写进 protocol-feedback.md
当一条 F-XXX 触发的改进被实施 → 在 F-XXX 下记录"已落地的改进"
协议每隔 N 轮 → 扫描所有 F-XXX，看哪些已经永久解决、哪些还在反复触发
反复触发的 F-XXX → 说明改进不彻底，需要协议结构性调整
```

---

## 七 · 协议在 ip-website-studio 这个场景的数字

| 资产 | 体量 |
|---|---|
| principles.md | **49 条** P-001 ~ P-049 |
| rubric.md | **28 条** R-001 ~ R-028 |
| exemplars/good | **6 件** S 档样本（已抽象化对外） |
| protocol-feedback | **4 条** F-001 ~ F-004 |
| holdout 盲评得分 | **4.95 / 5** |
| critic-report 累计 | ≥ 3 份 |

这些数字本身不重要，重要的是**比例关系**：49 条 P 用 6 件高分样本 + 3 份 critic-report 反推出来；28 条 R 是 49 条 P 的可验收映射；4 条 F 是协议本身的迭代记录。

数字会增长——但这套结构（principles → rubric → exemplars → critic loop → protocol feedback → holdout）是稳定的，可以迁移到任何领域。

---

## 八 · 如何 fork 这套协议到你自己的领域

1. **明确你的领域**：写一段话，描述"什么算这个领域里的好作品 / 好产出"——这是 principles 的起点。
2. **收 6 ~ 10 件高分样本**：必须是你领域里大家公认的好作品，且**带 verdict（为什么好）**。
3. **提炼 principles**：从这些样本反推 30 ~ 50 条"它们都满足的硬规则"。每条规则要有反例。
4. **建 rubric**：把 principles 翻译成"可验收的评分项"。分 A 客观（可程序化检查）/ B 半客观 / C 品味，加权出总分。
5. **写 SKILL.md**：把你领域的工作流写成 6 步主线 + critic 分支。**关键**：必须包含 §5b critic 独立复评步骤。
6. **跑第一轮 generator + critic**：看 critic 发现什么 gap，回流到 principles 和 rubric。
7. **预留 1 件 holdout 样本**：不参与 principles 反推，最后用它做盲评——是协议有效性的最小证据。
8. **持续迭代**：每轮 critic-report 都保留，每发现一个协议层 bug 写进 protocol-feedback.md。

---

## 九 · 这套协议在做什么 (一句话总结)

> 把模型权重无法承载的"局部领域品味"，强制沉淀成"开工前必读的文件资产"——
> 用 principles 表达品味、用 rubric 度量品味、用 exemplars 锚定品味、用 critic loop 防止评分者把品味偷偷往自己有利的方向偏。
>
> 这是 prompt engineering 之后的下一层抽象。
