变更审查
该技能审查的是变更,而非截图。它会解析变更范围,将受影响的文件扩展至它们所影响的界面表面,读取差异的两侧,并对每个发现项进行分类。
范围是该技能独立处理的。领域规则归属于 better-* 系列技能。严重性、整合、覆盖率、上限和最终判定则归属于 better-interface 技能,该技能会接手此次审查结果。
正确性、测试、安全性和性能归属于项目的常规代码审查。仅提及一次相关问题,然后继续。
审查的是变更,而非代码库
作者在问“我是否让情况变得更糟了?”。报告变更所导致的问题,并对其仅仅触及的部分保持相对沉默。提供三个预先存在的发现项是礼貌;三十个则是另一场审查,且无人要求。
在形成观点之前先阅读变更。所述意图决定了哪些内容算作不完整,而粗略浏览差异会产生关于代码的发现,而下个 hunk 可能已经修复了这些代码。
核心原则
1. 先解析变更范围
整个调用就是目标,因此 /interface-review pr 482 会审查拉取请求 482。范围解析 包含可接受的目标及其各自的解析方式。
若未提供目标,则按以下顺序解析,并在第一次匹配时停止:
HEAD领先于git merge-base origin/<默认分支> HEAD:该范围 加上 任何未提交的变更,并分别说明提交次数和未提交的文件数量。- 工作树有未提交的修改:未提交的变更。
- 两者都不是:没有要审查的变更。停止并提问,遵循“无变更时,提问而非凭空创造”。
顺序很重要。首先检查工作树,一个偶然的格式编辑可能会掩盖一个包含十二次提交的分支,而报告仍声称具有完整覆盖率。
排除锁定文件、快照、生成的输出、供应商代码和二进制文件,并说明你排除了哪些。排除后范围为空,则会通过不同的路径达到相同的结果。
2. 无变更时,提问而非凭空创造
干净的工作树且没有领先于合并基础的提交,意味着用户要求审查一个不存在的变更。切勿自行回退到 HEAD~1..HEAD。最后一次提交是恰好落地的,通常是合并,通常是别人的工作,而关于它的报告与用户意图的报告难以区分。
陈述你发现的仓库事实,然后提供选项并等待。无内容可审查 包含了要收集的事实:
- 最后一次提交,
HEAD~1..HEAD,通过短 SHA 和主题命名,以便用户在选择前能看到他们将会得到什么。 - 他们命名的目标:
pr <n>、一个分支、一个引用或一个范围,按“先解析变更范围”解析。 - 全仓库界面审查,这不是变更审查。将其交给
better-interface作为仓库范围审查,不附带此技能的范围块、状态或预先存在的部分。无变更时,每个发现项都是预先存在的,分类不具意义。
在询问前,检查当前分支是否存在开放的拉取请求,并优先提供此选项。其提交已合并的分支解析为无变更,但其拉取请求仍然正是用户想要的。
如果排除后范围为空,说明哪些文件被排除,并以相同方式询问。切勿将无内容的审查报告为“批准”。
3. 差异不是界面表面
被更改的文件是证据,而非审查主题。它的影响范围是其渲染到的表面集合;审查那些表面。
默认将影响范围扩展一跳:直接导入者和调用者。仅对设计令牌、主题值和共享原语扩展第二跳,因为一行更改可能影响整个产品。
最多审查五个消费者,按范围解析中的规则排序,然后说明你未扩展的数量。无界限的扫描无法支撑其所声称的覆盖率,而未说明的截止点会被解读为完整性。
4. 阅读删除的行
回归在变更后的状态中是看不见的。对照移除的信号阅读每个 hunk 的 - 侧。
信号是线索,不是发现项。移除只有在变更中没有内容替换它时才是回归,且该判断由领域技能负责。将每个不匹配的移除路由给其所有者,仅报告该技能确认的内容,并将其状态标记为“回归”。这会告诉作者他们破坏了之前能工作的东西,而不是犯了新错误。
5. 对每个发现项进行分类
为每个发现项赋予一个状态:
引入:变更创建了它。回归:变更削弱了先前正确的内容。预先存在:存在于被触及的代码中但非由此变更引起。
根据差异触及的行,而非它所在的文件来分类:变更从未触及的行,即使距离 hunk 只有三行,也是“预先存在”。必要时对照基础引用确认:
git blame -L <行号>,<行号> "$BASE" -- 路径/到/文件
将每个发现项及其状态一起传递,让 better-interface 应用其上限和判定规则。
6. 根据声明意图衡量变更
阅读拉取请求的标题和正文、关联的 issue 以及提交信息,然后审查界面是否实现了他们所声称的内容。
这揭示了不完整的变更。界面表面审查无法看到这一点,因为它检查的是存在的状态,而这里的重点是缺失的状态:
- 应用于某些状态但非全部状态的新变体、尺寸或主题:悬停、聚焦、激活、禁用、加载、选中。
- 新的面向用户的字符串,但项目维护的翻译目录中没有对应条目。
- 没有空、加载、错误、禁用或窄宽度状态的新组件。
- 添加到一个表面但未添加到已承载其同级控件的兄弟表面的控件。
不要报告范围蔓延。变更是否做得过多是流程问题,而非界面问题。
7. 将审查移交给 better-interface
将范围块、受影响的表面以及每个发现项的状态移交给 better-interface。它会路由到领域技能,应用严重性,整合,强制执行上限并发布判定。
如果 better-interface 不可用,则报告解析后的范围和文件清单,将此技能标记为缺失并停止。不要发明严重性等级、上限或判定。
8. 切勿修改工作树
变更审查是只读的,包括检出操作。拉取拉取请求引用;切勿检出它们。git fetch 仅写入 .git,是允许的。gh pr checkout、git checkout、git switch 和 git stash 会重写作者打开的文件。它们会在用户有本地编辑时失败或丢弃它们,因此绝不允许。
渲染验证是可选的。将视觉和运行时声明标记为未验证,除非项目提供了便宜的预览方式或用户要求进行渲染审查。当用户要求时,使用隔离的工作树(git worktree add /tmp/review-<n> refs/remotes/pr/<n>)并在完成后移除。
完成前检查
| 错误 | 修复 |
|---|---|
| 一个偶然的修改被审查,而不是整个分支 | 在检查工作树之前检查 merge-base,并报告两者的计数 |
| 因为无变更而审查了最后一次提交 | 陈述事实,并提供最后一次提交、命名目标或仓库审查 |
| 审查了 hunk 而未检查其消费者 | 扩展一跳,令牌和原语扩展两跳,并说明跳过了什么 |
仅阅读了差异的 + 侧 | 搜索 - 侧中移除的可访问性、聚焦、运动和文本信号 |
| 等效的替换被报告为回归 | 将移除路由给其所有者;仅报告其确认的内容 |
| 移除被报告为新错误 | 将其状态标记为“回归”,以便作者知道它之前是工作的 |
| hunk 附近的行被标记为“引入” | 根据差异触及的行进行分类,并用 git blame 对照基础引用确认 |
| 检出拉取请求以进行审查 | 获取引用并就地审查 |
| 引用了审查引用上不存在的行号 | 对照范围块中命名的头部引用进行引用 |
| 在此处重复严重性等级或发现上限 | 委托给 better-interface |
| 报告中出现正确性、测试或安全问题 | 提及一次相关问题,指向项目的代码审查,然后放弃 |
审查输出格式
以范围块开头:
| 字段 | 值 |
|---|---|
| 目标 | 分支、工作树、暂存区、pr 482 或输入的范围 |
| 基础引用 | origin/main at a1b2c3d |
| 头部引用 | refs/remotes/pr/482 at e4f5g6h |
| 提交次数 | 7 次已提交,2 个文件未提交 |
| 范围内文件 | 排除后 12 个 |
| 已排除 | pnpm-lock.yaml、src/__snapshots__/:锁定文件和快照 |
| 扩展的界面表面 | CheckoutPage、SettingsPanel;未扩展 3 个进一步的 Button 消费者 |
紧随其后的是覆盖率表格。变更范围内无证据的领域显示为“未审查:变更范围内无证据”,这是覆盖率声明而非空白。
然后是发现项,带有一个“状态”列,遵循“对每个发现项进行分类”:
| 严重性 | 领域 | 状态 | 位置 | 变更前 | 变更后 | 原因 |
|---|---|---|---|---|---|---|
| 高 | 可访问性 | 回归 | src/Dialog.tsx:42 | 此变更移除了 aria-label="Close" | 在仅图标控件上恢复 aria-label="Close" | 关闭控件在此变更前具有可访问名称,现在没有了 |
如果没有“引入”或“回归”发现,则省略表格并说明“此变更中无可操作的界面发现项”。
然后是“预先存在”的发现项,最多三个,按最高严重性优先排序,明确说明这不是此变更的责任。如果没有,则省略该部分。
| 严重性 | 领域 | 位置 | 问题 |
|---|---|---|---|
| 中 | 排版 | src/Toolbar.tsx:7 | 数字徽章使用了比例数字;早于此变更 |
上限和判定仅涵盖“引入”和“回归”。“预先存在”的发现项位于上限之外,因此触及遗留文件不会变成全文件审查。它们也位于判定之外,因此仅包含预先存在发现的变更是“批准”。
当存在任何“高”严重性发现时,以“阻止”结尾,否则以“批准”结尾,将剩余的发现项留在表中作为待完成工作。当 better-interface 可用时,严重性等级和上限来自它。