首页
/ Traefik 的 AI 代码审查技能:用 SKILL.md 为 AI Review Agent 制定仓库级审查规范

Traefik 的 AI 代码审查技能:用 SKILL.md 为 AI Review Agent 制定仓库级审查规范

2026-09-06 21:42:10作者:齐冠琰

Traefik 仓库在 .claude/skills/review/SKILL.md 中维护了一份面向 AI 代码审查 Agent 的“仓库级附加指导”(Repository-specific guidance for the AI code review agent)。它回答了一个很实际的问题:当 AI Agent 参与开源项目的 Code Review 时,如何在通用审查角色之上,注入只属于这个仓库的领域知识——比如 Traefik 特有的静态/动态配置边界、Kubernetes CRD 结构镜像要求。读完本文,你可以掌握这份技能文件的组织方式、六大审查维度的具体规则,以及 Traefik 源码中与之对应的真实实现证据,并能参考它为自己的项目编写同类审查规范。

一、文档定位:附加而非替代

SKILL.md 的 frontmatter 声明了它的元信息:

---
name: review
description: Repository-specific guidance for the AI code review agent reviewing this repo
user-invocable: true
disable-model-invocation: true
---

正文明确了它的定位边界:

The reviewer already fixes the role, the tools, the severity definitions, the finding mechanics and the output format; this guidance is additive and must not restate them.

也就是说,审查 Agent 的“角色、工具、严重级别定义、发现问题的机制、输出格式”由审查框架预先固定,这份 SKILL.md 只做增量补充,不允许重复框架已有内容。它约定了只记录框架接受的四级严重级别:CRITICALIMPORTANTMINORQUESTION,并要求“按优先级顺序审查,且每一层都保持高标准”。

同一目录下还有一份姊妹技能 .claude/skills/release/SKILL.md,负责准备发版(生成 changelog、升版本号、开 PR),两者共同构成了 Traefik 仓库交给 AI Agent 的“操作规程”体系。本文聚焦其中的 review 技能。

二、六大审查维度与优先级顺序

文档要求按以下顺序审查:Security → Correctness → Breaking changes → Performance → Maintainability,并附一条收尾原则。下面逐条展开,并给出仓库中的源码证据。

1. Security:安全边界

规则要点:

  • 每一次边界跨越处验证认证、授权与信任边界;
  • 追踪不可信输入直到危险汇聚点(exec、SQL、文件 I/O、模板渲染);
  • 禁止硬编码密码、token、API key;日志中不得出现密钥或敏感数据。

对 Traefik 这样的反向代理/负载均衡器而言,“边界跨越”是核心语义——客户端请求经 entrypoint、router、middleware 链最终到达后端服务,每个环节都可能是信任边界的转换点,这条规则正好命中其架构特征。

2. Correctness:正确性(信息密度最高的一节)

这是全文篇幅最长、最“仓库特有”的部分,包含七条具体规则:

(a) 常规缺陷:空指针解引用、竞态条件、差一错误、条件反转、未处理的边缘情况。

(b) 错误包装风格。要求错误用 fmt.Errorf动名词(gerund)形式包装,例如 fmt.Errorf("unmarshalling data: %w", err),且绝不允许用 _ 静默丢弃错误。这在仓库中是普遍遵循的既有模式,例如 pkg/cli/deprecation.go 中:

return false, fmt.Errorf("parsing deprecated config from args: %w", err)

pkg/healthcheck/healthcheck.go 中同样是 fmt.Errorf("parsing health check path: %w", err) 的风格。审查 Agent 据此可以对新增代码做风格一致性检查。

(c) 资源泄漏:未关闭的连接、泄漏的 goroutine、未被传播或取消的 context。

(d) context 作为第一参数:凡是接收 context.Context 的函数,它必须是第一个参数且命名为 ctx

(e) 请求路径禁用 context.Background():请求路径上应从调用方传播 context,而不是新建一个 context.Background()

(f) 自定义 context key 必须是非导出结构体类型type myKey struct{}),绝不用裸字符串或整数——这是 Go 官方推荐的防止 key 冲突的做法。

(g) 静态/动态配置边界。这是 Traefik 特有的正确性规则:

Changes must not blur the static/dynamic configuration boundary: static configuration is read at startup only; dynamic configuration is produced by providers at runtime.

静态配置只在启动时读取;动态配置由 provider 在运行时产出。“启动时读取动态配置”或“把静态配置存进运行时结构”都算正确性缺陷。仓库中这两类配置分别落在 pkg/config/static/pkg/config/dynamic/ 两个包中,包结构本身就是这条边界的体现。

(h) 动态配置选项必须同步到 CRD 镜像。规则指出:凡是向 pkg/config/dynamic 下某个类型新增字段,就必须在 Kubernetes CRD 类型的镜像结构体里同步新增,并接入 CRD 到动态配置的转换逻辑。文档给出了精确的落点:

原文的判定很直接:“A dynamic option that is not exposed on the duplicated CRD struct is a bug.”——动态选项没有暴露到重复的 CRD 结构体上,就是 bug。这条规则把“重复定义的镜像结构必须同步”从一般性建议变成了硬性审查标准,正是“附加指导”价值的典型体现。

3. Breaking changes:破坏性变更

  • 导出的 Go APItraefik.io/v1alpha1 命名空间下的 CRD schema 的破坏性变更要主动标记;
  • 影响现有部署的配置变更也要标记。

这与第 2 节呼应:traefik.io/v1alpha1 既是 CRD 的 API 组版本,也是用户侧已经写进集群 manifests 的稳定契约,改坏它就是生产事故。

4. Performance:性能

标准是克制的:“只有在热路径上、且影响可度量的情况下,才标记超线性算法(线性算法就够用的场景)、可避免的分配或 I/O”。这防止 AI 审查 Agent 对非关键路径吹毛求疵、产生大量低价值噪音。

5. Maintainability:可维护性

这一节集中了 Traefik 团队的 Go 惯用法约定:

  • 接口:倾向单方法、-er 后缀(ReaderWriter 风格)、在使用方(use site)声明;
  • 惯用 Go:早返回与守卫子句;优先标准库(slicesmapscmp)而非过早抽象或第三方辅助包;import 分组排序;导出项必须有以该名称开头的文档注释;
  • 注释:解释 为什么(why)而不是 是什么(what)——“代码已经说明了 what”;且每条注释必须以句号结尾(这是相当少见的显式规范);
  • 测试
    • 新行为必须有测试,使用 testify/asserttestify/require
    • require 用于“必须中止测试”的前置条件,assert 用于相互独立的断言;
    • 测试必须表驱动(table-driven)且调用 t.Parallel()
    • 偏好黑盒测试(package x_test);
    • 不要给 assert/require 调用添加冗长的消息参数——测试名本身已提供上下文。

三、“Do not flag”:审查噪音过滤器

文档专门列出不应被标记的内容,这是控制 AI 审查误报率的关键设计:

类别 匹配规则 原因
生成代码 zz_generated*.go 文件、pkg/provider/kubernetes/crd/generated/ 下所有内容、webui/static/ 生成物不应人工修改或审查,仓库中如 pkg/tls/zz_generated.deepcopy.go 即属此类
测试 mock mock_*.go*_mock.go pkg/healthcheck/mock_test.gopkg/plugins/wasip_mock.go
//nolint: 指令 任意 是有意为之的豁免
集成测试 fixture integration/fixtures/ 下内容 依赖 Docker 的行为无法静态验证
既有模式 全代码库已一致使用的模式 不应要求作者“与不一致的自己保持一致”

四、收尾原则:调用方说了算

文档最后一句是整篇的指导性收束:

Before claiming a change is unsafe, check how the changed functions are used elsewhere in the repository: the call sites decide.

在断言某处变更“不安全”之前,必须先检查被改函数在仓库其余位置如何被使用——调用点(call sites)决定语义。这既符合 Go 生态中“导出即契约”的现实,也约束 AI Agent 不做脱离上下文的静态臆断。

五、方法论总结:如何把这份 SKILL.md 用到自己的项目

从这份 Traefik 审查技能中可以提炼出一套可复用的编写思路:

  1. 只写增量:框架已固定的角色、工具、输出格式一律不重复,只补仓库特有部分(如配置边界、镜像同步要求);
  2. 给规则配可验证的落点:每条“仓库特有规则”都指向具体目录或文件(如 CRD 镜像目录、转换入口文件),让审查 Agent 有据可查;
  3. 用既有代码风格反哺规则:错误包装的动名词风格等规则,实际上是对仓库中已普遍存在模式(见 pkg/cli/deprecation.go 等文件)的成文化,保证新代码与存量代码一致;
  4. 明确“不标记清单”:生成代码、mock、nolint、fixture 等豁免项,是压低误报率最有效的杠杆;
  5. 优先级排序 + 克制标准:Security 优先、Performance 只在可度量的热路径上标记,避免审查 Agent 淹没在高噪音低价值发现里。

对于同样具备“生成代码 + 手写代码混布”“多份镜像结构需要同步”“运行时配置边界”等特征的项目(Kubernetes 生态尤其普遍),这套组织方式可以直接借鉴:先划定边界(Do not flag),再按“安全—正确性—破坏性—性能—可维护性”的固定顺序注入仓库特有条款,最后用“调用点说了算”兜底,就能让 AI 审查输出从“通用 lint”升级为“懂这个仓库的资深评审”。

登录后查看全文
热门项目推荐
相关项目推荐