eo-change-review · git:20260719.f885f1c · 2026-07-19 · sha256 9beb26beb9e47e0c

eo-change-review git:20260719.f885f1cA

Immutable. This exact content is served forever at /api/v1/blob/9beb26beb9e47e0c.

---
name: eo-change-review
description: |
  对 change.md 做方案级审查(AC 质量、TODO↔AC 映射、粒度合规、意图一致性)。触发:审查 change / change 审查 / 审方案 / /eo-change-review。
  NOT FOR: 代码审查(/eo-review)、implement 内的回归审查。
---

# eo-change-review — Change 方案审查

对一个 change 做方案级审查,在 implement 前把牢「方向是否正确、AC 是否可验收、TODO 是否完整、粒度是否合规」。**可选环节**——小 change 可跳过;AC ≥5 条 / 含 §5 技术方案 / type=refactor / 高风险 change 建议跑。

## 与另一种 review 的关系

| Skill | 审查对象 | 问的问题 |
|-------|---------|---------|
| **`eo-change-review`**(本技能) | 某个 change 的 `change.md` | 方案对不对?AC 质量、TODO 完整性? |
| `eo-review` | change 实施后的代码 | 代码对不对?实现 vs AC? |

两者关注点、上下文、回退动作完全不同,**不要混用**。

## 核心原则

1. **方案级审查,不替作者做决定**:只产出报告,修订由用户回 `/eo-change` 执行
2. **AC 是重中之重**:change 的价值密度集中在 §2 验收清单;AC 不可验收,后面全白做
3. **不审实施质量**:此时代码还没写,不审代码质量;但维度 7 的**前提校验落到真实代码**——state 文档可能过期,读码取证不等于审码
4. **固定产出**:`eo-doc/changes/<change-id>/change-review.md`
5. **采样式质检,不是穷尽式收敛**:只有 P0 阻塞流程,P1 移交起草方裁决;复审默认增量核销,不重开全文;累计上限 3 轮,到限升级用户裁决

## 前置条件

- **必须能找到 `.eo-project.json`**。找不到 → 报错退出,提示运行 `/eo-project-init`
- `eo-doc/changes/<change-id>/change.md` 存在,status 为 `draft` 或 `confirmed`(implementing 及之后 → 提示应走 /eo-review)

## 工作流程

### 第零步:轮次与模式判定

- **首轮**(目录下无 change-review.md):全量审查
- **复审轮**(已有 change-review.md):默认**增量**。命中下表任一信号(机械可判,不做主观裁量)→ 自动升级**全量**并向用户播报命中哪条;用户显式指定模式时以用户为准,优先于自动判定

| 升级信号 | 为什么 |
|---------|--------|
| AC 有增删,或既有 AC 语义性改写(非措辞微调) | AC 是映射与覆盖检查的锚,锚动则增量核对失效 |
| §1 已钉决策变动 | 意图层变化使上轮一致性结论作废 |
| 修订触及超过 1/3 的 TODO,或修订量超全文 30% | 波及面超出定点核对范围 |
| finding 台账或处置落点缺失(如跨会话丢上下文) | 增量输入不存在,全量兜底 |

- **全量复审 ≠ 从零**:台账中 `wont-fix` 项在任何轮次、任何模式下豁免,不得重报
- **轮数纪律**:复审累计上限 **3 轮**(升级全量不重置计数);到限仍有未决 P0 → 停止循环,把未决项列给用户裁决(终态措辞见第四步)
- **revision 边界**:轮数与 wont-fix 豁免均以 change.md frontmatter `plan_revision`(缺省视为 1)为界——回炉进入新 revision 后轮数从 1 起算、旧 revision 的 wont-fix 失效(新方案下可重报);新 revision 首轮按全量跑,报告在「速报」前另起 `## Revision R 审查` 分段,旧 revision 内容冻结不改

### 第一步:阅读上下文

**tier: light 的 change 不适用本 skill**(轻档方案审查由探针对齐替代,见 [../eo-shared/granularity.md](../eo-shared/granularity.md) §5)——提示直接 `/eo-implement` 轻模式。

**全量(首轮 / 升级)**:

1. 读目标 change.md 全文(v2 模板:§1 意图 + 已钉决策、§2 AC、§3 TODO、条件节 §4-§8)
2. 读 `eo-doc/changes/INDEX.md` 最近 3 条(避免与在途/已归档 change 冲突或重复)
3. 读 `eo-doc/state/` 相关篇目(系统现状,校验变更前提)
4. frontmatter `type` 缺失或不在枚举(bootstrap/feature/enhance/refactor)→ 直接 P0 报告,**不向用户追问类型归属**
5. 复审轮另加:读 finding 台账,继承 `wont-fix` 豁免与已核销记录

**增量复审**:

- **同会话**:上轮 finding 与修订过程已在上下文,**不重读任何文件**,直接进入核销
- **跨会话**:读 change-review.md(台账 + 上轮报告)→ 按台账「处置」列的改动落点**定点读** change.md 对应段落,不读全文

### 第二步:系统审查

**增量复审只做两件事**,不重开全文:

1. **核销**:逐条验证台账未决 P0/P1 的修复——按处置落点核对,改到位 → `verified`;没改到位 → 保持 `open` 并一句话说明
2. **审增量**:只对本轮修订引入/改动的内容找新 finding。**新 finding 必须能指认「由本轮修订引入」,否则无效**——首轮就该发现的问题不允许复审轮补报(对审查采样噪声的抑制闸)

**全量审查**跑满以下 7 维度:

- **维度 1 · AC 质量(最关键)**:对照 [../eo-shared/ac-spec.md](../eo-shared/ac-spec.md) 逐条检查——用户视角?可独立验证(声明 + 验证栏合读能得出怎么操作、看什么;验证栏按增量制省略不算缺)?技术无关且可度量(无「正常工作」类主观词)?覆盖异常路径(至少 1 条失败/边界 AC)?refactor 类是否写了「行为不变」的回归口径?
- **维度 2 · TODO↔AC 映射**:每条 TODO 标注了对应 AC 且映射成立?每条 AC 至少被一条 TODO 覆盖?出现映射不到 AC 的 TODO(越界)或没有 TODO 的 AC(悬空)→ P0
- **维度 3 · TODO 拆解质量**:三要素齐全(描述/文件/对应 AC)?多条 TODO 对同一 AC 时是否逐条写了完成判据(一对一不要求)?**占位符检测**(「补充错误处理」「后续完善」→ P0)?Batch 分组合理、Batch 1 是可独立验证的 MVP?依赖自洽无循环?
- **维度 4 · 粒度合规**:对照 [../eo-shared/granularity.md](../eo-shared/granularity.md)——TODO 数与全文行数在软标内(超软标 P1 建议拆、超硬标 P0 必须拆);反向检查:是否 trivial 到根本不该开 change(→ P1 建议转直改)
- **维度 5 · 意图一致性**:§1 已钉决策与 §2/§3 是否自洽(TODO 有没有偷偷推翻已钉结论)?`type` 与实际内容匹配(宣称 refactor 却新增用户可见能力 → 应改 feature)?混入多个不相关改动 → 建议拆;AC/TODO 是否超出 §1 意图自行扩面(镀金,见 [../eo-shared/ac-spec.md](../eo-shared/ac-spec.md)「不镀金」)→ P1 建议裁剪或转 backlog
- **维度 6 · 条件节合规**:触发条件满足却缺节(有 TODO 未覆盖的连带文件但无 §4;有新外部依赖但无 §5;有不可逆操作但无 §7)→ P1;触发条件不满足却写了 → P2(瘦身建议);§8 defer 超过 3 条 → P1;change 含 §6 流程图时对照 [../eo-doc-manager/references/mermaid.md](../eo-doc-manager/references/mermaid.md) §5 审查清单核对
- **维度 7 · 前提真实性抽查**:方案前提落到**真实代码**核验(state 文档可能过期,不能只对文档校验)——
  - **机械核验**(全量跑,不占抽样名额):§3 每条 TODO 按文件栏操作类型分型核验——`新增:` 查父目录/模块惯例/命名冲突;`修改:`(含缺省)查对象存在与形态相符;`删除:` 查对象存在与引用面
  - **高风险前提抽样**:候选池 = §1/§4/§5/§7 中对现状事实、兼容性、唯一性、外部契约的断言;按不可逆性 > 数据/权限风险 > 跨模块面排序取 **2-3 条**定点读码核验。每条前提标基线:「变更前事实」审 `base_commit`(首轮审查时即 HEAD;回炉复审用 `git show <base_commit>:<path>`——防被上一轮实施在 HEAD 造出的代码自证);「当前兼容性」读 HEAD + 本 change 未提交 diff
  - 报告固定四栏:断言 / 基线 / 证据(file:line 或命令输出)/ 判定。**前提不成立 → P0(必须附直接证据);证据不足 → P1 要求补证,不猜 P0**

**定级纪律(全模式通用)**:

- **P0 只收客观可判项**:TODO↔AC 映射断裂 / 占位符 / 粒度超硬标 / AC 不可验证(声明与验证栏合读仍不知怎么验)/ type 缺失或不在枚举 / TODO 推翻已钉决策 / **前提不成立(维度 7,附直接证据)**。程度与取舍类判断(粒度软标、条件节取舍、表述质量、意图一致性的程度问题)最高 P1
- **不确定就降级**:拿不准 P0 报 P1,拿不准 P1 报 P2;每条 P0/P1 必须落到具体位置(§X / 条目号)并附可执行修复建议,给不出的不报

### 第三步:撰写报告

- **首轮**:按下方模板写入 `eo-doc/changes/<change-id>/change-review.md`(含 Finding 台账)
- **复审轮**:**不重写报告**——只更新台账状态列,在「速报」节之前追加一节 `## 复审记录(第 N 轮 · 增量/全量 · YYYY-MM-DD)`(核销结果 / 新增 finding / 未决清单),并原地更新「速报」节。「速报」必须始终是文件末节(编排方按"末尾速报"取下一步)

### 第四步:对话速报(硬性——缺速报 = 流程未完成)

```
结论:通过 / 不通过(P0 x 条)[第 N 轮 · 全量/增量]
P0(阻塞 implement):
1. <一句话> — change.md §X
P1(移交起草方裁决,不阻塞循环):
2. <一句话> — change.md §X
P2(可后置):
3. <一句话>
下一步:<见下方终态措辞>
(详细分析见 <change-review.md 路径>)
```

终态措辞**三选一,严禁混用**:

- **通过(P0=0)**:「下一步 `/eo-implement <change-path>`(status 若仍为 draft,先回 /eo-change 对话确认)。未决 P1 已入台账,由起草方裁决:采纳的回 /eo-change 顺手修(**不触发复审**),不采纳的标 wont-fix 附理由。注意:`/eo-review` 是代码审查,要在 implement 之后,现在还不轮到它。」
- **需修订(P0>0 且未到 3 轮)**:「回 `/eo-change <change-path>` 逐条处置:修复的在台账标注改动落点,不认同的标 wont-fix 附理由;然后再跑 `/eo-change-review` 复审(默认增量,锚变动自动升全量),循环到 **P0=0**。当前第 N/3 轮。🚫 不要跳过复审直接 implement,不要跑 /eo-review(代码还没写)。」
- **到限(第 3 轮仍有未决 P0)**:「复审已达 3 轮上限,停止循环。未决 P0:<清单>。请裁决:a) 显式豁免并放行 implement(豁免记录入台账与 change.md §8) b) 指定修复后仅做一次核销复审 c) 回炉重做 change。」

## 固定模板 — change-review.md

```markdown
---
title: <标题> Change 审查报告
change_id: <change-id>
created: YYYY-MM-DD
status: active
summary: >
  一句话审查结论。
---

# <标题> Change 审查报告

> 关联:[change.md](change.md) | 审查日期:YYYY-MM-DD | change status:draft / confirmed

## 审查总结
一段话 + 明确结论:✅ 可进入 implement / ⚠️ 小幅修订后进入 / ❌ 需大幅修订

## Finding 台账

<!-- 状态单一来源:本 skill 建条与核销(open→verified),修订方(/eo-change)填「处置」列。wont-fix 项后续任何轮次不得重报 -->

| ID | 级别 | 摘要 | 位置 | 状态 | 处置(修订方填) |
|----|------|------|------|------|------------------|
| P0-1 | P0 | <一句话> | §3 | open / fixed / verified / wont-fix | <改动落点 或 wont-fix 理由> |

## P0 - 必须修订(阻塞 implement)
### [P0-1] <标题>
- 类型:AC 不可验收 / 映射断裂 / 占位符 / 粒度超硬标 / 类型错配
- 位置:change.md §X | 描述 | 影响 | 建议

## P1 - 建议修订(移交起草方裁决,不阻塞)
### [P1-1] <标题>(类型:粒度超软标 / 条件节缺失 / 异常路径未覆盖 / defer 超限…)

## P2 - 可选优化

## AC 质量检查
| AC | 用户视角 | 可验证 | 技术无关 | 备注 |
|----|---------|--------|---------|------|

## TODO↔AC 映射检查
| TODO | 对应 AC | 状态 |
|------|---------|------|
| TODO-1 | AC-1 | ✅ / ⚠️ / ❌ |

## 粒度检查
TODO 数:N(软标 3-7 / 硬标 10)| 全文:N 行(软标 500 / 硬标 700)| 结论:合规 / 建议拆 / 必须拆

## 前提真实性抽查(维度 7)

<!-- 机械核验全量跑(TODO 文件栏按操作类型),高风险前提抽 2-3 条;前提不成立 → P0 附直接证据 -->

| 断言 | 基线 | 证据 | 判定 |
|------|------|------|------|
| <一句话前提> | base_commit / HEAD | `file:line` 或命令输出 | ✅ 成立 / ❌ 不成立 / ⚠️ 证据不足(P1 补证) |

## 结构完整性
| 节 | 状态 | 备注 |
|----|------|------|
| §1 意图 + 已钉决策 | ✅/⚠️/❌ | |
| §2 验收清单 | ✅/⚠️/❌ | |
| §3 TODO(Batch) | ✅/⚠️/❌ | |
| 条件节 §4-§8 | ✅/⚠️/❌ | 触发条件 vs 实际取舍 |

<!-- 复审轮在「速报」之前追加,不重写上文;回炉进新 revision 时在「速报」前另起
     「## Revision R 审查(YYYY-MM-DD · 全量)」分段,其内轮次从第 1 轮重计,旧 revision 段冻结不改 -->
## 复审记录(第 2 轮 · 增量 · YYYY-MM-DD)

- 核销:P0-1 verified(<落点一句话>);P1-1 wont-fix(<理由>)
- 新增:无 / P0-2 <一句话>(由本轮修订引入:<指认>)
- 未决:无 → 结论:通过

## 速报

结论:通过 / 不通过(P0 x)[第 N 轮 · 全量/增量]
下一步:(通过)status 为 draft 时先回 /eo-change 完成确认 → /eo-implement / (需修订)回 /eo-change 处置后复审(第 N+1/3 轮) / (到限)交用户裁决
```

末尾「速报」节必填——它是报告的机器可读出口(编排方读文件即取下一步),与第四步对话速报同款内容。

## 关键约束

- **不改 change.md**:只产报告,修订归 `/eo-change`
- **P0 精准且客观**:只有阻塞 implement 的客观可判问题才 P0(白名单见第二步定级纪律);不确定就降级
- **只有 P0 阻塞循环**:P1 移交起草方裁决,P1 的修复不触发复审
- **复审不重开全文**:增量为默认;复审轮新 finding 必须指认由本轮修订引入;wont-fix 项永不重报
- **报告追加不覆盖**:复审只更新台账 + 追加复审记录,上轮报告原文保留
- **轮数上限 3 轮**:升级全量不重置计数,到限交用户裁决
- **不审实施质量**(代码质量归 /eo-review;维度 7 读码仅为前提取证)、不审业务方向本身(方向的家在 brainstorming/意图确认)
- **避免触发钩子噪声**:报告中避免使用「关键决策」等字样(可能触发上游配置的记录钩子),用「设计判断」「模式选择」代替
- **可操作**:每个问题的建议必须具体到用户能直接行动