Skip to content

迭代篇

目录


15. 迭代方法论

高质量 skill 不是一次就构建出来的,而是在真实实践中不断暴露问题、定位根因、修复验证后逐步打磨出来的。本章建立系统性改进 skill 的方法论框架。

15.1 两种迭代驱动力

迭代的触发点来自两个渠道,两者互补而非替代:

驱动力 来源 典型触发条件
量化评估驱动 第 10 章的三维度 A/B 对照 评估分数低于阈值、with-skill vs without-skill 差距不足 10%
实践观察驱动 日常使用中的漏报和质量投诉 人工复核发现 AI 未捕获的缺陷、开发者反馈误报过多

评估篇(§10-11)解决的是"如何度量 skill 的当前质量"——建立基线、发现方向。迭代篇解决的是"拿到数据或遭遇漏报之后怎么系统性改进"——根因分类、精准修复、效果验证。两者形成闭环:评估指向方向,迭代完成改进,再评估校验效果。

实践观察驱动是量化评估的重要补充。A/B 测试需要提前设计场景,而真实代码千变万化,总有测试场景未覆盖的遗漏模式。当开发者在代码审查中发现 AI skill 未报出的缺陷时,这是一次高质量的"免费评估"——这个漏报既揭示了 skill 的盲区,也提供了一个可验证改进效果的具体案例。

15.2 迭代循环的四个阶段

每次迭代遵循固定的四阶段结构,跳过任何一步都会降低改进的可信度:

① 实战暴露
   ↓  人工复核发现漏报 / 量化评估低于阈值
② 根因分类
   ↓  判断:checklist 缺失 / 模型执行遗漏 / 领域知识盲区
③ 针对性修复
   ↓  补 checklist / 强化执行规则 / 新增 reference
④ 清上下文验证
   ↓  全新对话,无历史残留,重跑相同案例
   回到 ①

阶段① 的关键是"保留现场":把漏报案例连同被审查代码一起记录下来,构成后续验证的测试输入。

阶段② 是最容易被跳过但最关键的步骤。不做根因分类就直接修改 skill,修改方向往往是错的:把一个"模型执行遗漏"的问题当成"checklist 缺失"处理,只会让 SKILL.md 越来越长,但遗漏率不会下降(见 §15.3 和 §15.4)。

阶段③ 的改进措施必须与根因类型对应,三种根因各有不同的修复路径(见 §15.4)。

阶段④ 是验证的核心约束:必须清除对话上下文,在全新对话中重跑相同案例。在同一对话中验证会携带历史上下文,模型可能"记住"之前的讨论而非真正依赖改进后的 skill。

15.3 根因分类框架

这是迭代方法论的核心。每一处遗漏都必须归入以下三类之一,不同根因的可修复性和修复措施截然不同:

根因类型 定义 可修复性 改进措施 观测修复率
checklist 缺失 SKILL.md 的 checklist 未覆盖该检查项,模型"不知道要查" 确定性 补全 checklist 100%(3/3)
模型执行遗漏 checklist 已覆盖但模型在执行时跳过,"知道但没查" 概率性 强化执行规则 + 措辞加强 67%(2/3)
领域知识盲区 超出通用 checklist 范围的业务场景特定知识 有限 新增 reference 0%(优化建议类)

上表数据来自 go-code-reviewer skill 的 3 个实战案例、8 处遗漏的归因分析(详见 §16.2)。

三类根因的诊断方法

诊断时先回答一个问题:SKILL.md 的 checklist 里是否明确列出了这项检查?

  • → checklist 缺失。在当前 skill 中补全 checklist 即可确定性修复。
  • 是,但模型未执行 → 模型执行遗漏。需要分析遗漏的触发条件(如高缺陷密度、执行规则措辞模糊),然后针对性强化规则。
  • 无法列入通用 checklist(如业务场景特定的性能优化) → 领域知识盲区。可在 reference 文件中补充知识,但效果有限。

一个遗漏可能同时涉及多个根因(见案例二 §16.1),此时按照最高优先级根因处理,同时记录复合因素。

15.4 三类根因的改进策略

15.4.1 checklist 缺失:补全的工程方法

checklist 缺失是三类根因中唯一具有确定性修复效果的。补全 checklist 后,模型在下次执行时会被强制检查该项,修复率在观测案例中达到 100%。

补全 checklist 的工程方法:

第一步:定位插入点。新 checklist 项应插入到逻辑上相关的类别(如"goroutine panic recover"归入 Concurrency & Lifecycle,"指针切片 nil guard"归入 Code Quality),而非统一堆放在末尾。

第二步:控制描述粒度。checklist 项只需描述"查什么",不需要解释"为什么"和"怎么查"——后者放到对应的 reference 文件里。精简前后对比:

项目 精简前(冗长) 精简后(推荐)
goroutine recover "panics inside goroutines are not propagated to the parent goroutine; any unrecovered panic crashes..." (2 行) Goroutine missing defer recover() — unrecovered panic crashes entire process (1 行)
goroutine 数量控制 "spawning one goroutine per item in an unbounded loop causes resource exhaustion..." (2 行) Goroutines created per loop element without concurrency limit (semaphore / errgroup.SetLimit / worker pool) (1 行)

第三步:同步更新 reference 文件。新增的 checklist 项通常需要在对应的 reference 文件中补充 BAD/GOOD 示例和触发条件,帮助模型在执行时正确识别模式。

第四步:监控 SKILL.md 体积。每次补全 checklist 后检查总行数,保持 SKILL.md ≤ 500 行。超出时优先考虑将 anti-examples 或详细说明迁移至 reference 文件(见 §16.1 案例三的瘦身实践)。

15.4.2 模型执行遗漏:规则约束的边界

模型执行遗漏是最棘手的根因类型。checklist 明确列出了检查项,模型却在执行时跳过了——这不是知识问题,而是注意力分配问题。

常见触发条件:

  • 高缺陷密度:存在多个 High 级别缺陷时,模型注意力集中在"能让代码停止运行的错误",系统性忽略较低优先级的检查项。
  • 执行规则措辞模糊:checklist 项只写了模式名称(如 Missing error wrapping),没有明确指向具体的检查动作(如 inspect every return err path),模型执行时缺乏操作锚点。
  • 后置合理化幻觉:模型遗漏某项检查后,遭遇追问时会产生"听起来合理的"后置解释,而非承认遗漏。这是 LLM 推理的固有特性,不能通过措辞改进消除。

改进措施:

  1. 措辞加强:将被动描述改为主动动作指令。例如:

    # 改进前
    - Missing error wrapping context (`%w`)
    
    # 改进后
    - Missing error wrapping context (`%w`) — inspect every `return err` path
    

  2. 增加执行完整性规则:在 Review Discipline 节明确写入"无论已发现多少 High finding,必须继续执行全部 checklist 类别",针对高缺陷密度场景下的注意力竞争。

  3. 前置条件引证规则:应用任何 anti-example 抑制之前,必须在代码中找到具体证据证明前置条件已满足。仅凭"类别匹配"不构成抑制理由。

执行遗漏在规则层只能缓解,无法根本消除。这是一个架构层问题,解法见架构篇(§17-18)。

15.4.3 领域知识盲区:reference 的有限性

领域知识盲区指的是业务场景驱动的、无法列入通用 checklist 的优化建议。典型例子:当函数同时包含 Count + Find 且未分页时,如果业务中大多数用户的记录为空,先执行 Count 并在结果为 0 时提前返回能显著减少 SQL 请求——这是一个需要了解业务访问模式才能提出的建议。

改进措施是在 reference 文件中新增相关知识节(含 BAD/GOOD 示例和适用条件)。但这种改进的效果是有限的

  • Reference 提供的是"知识储备"而非"执行指令"——模型需要自主完成从代码特征到优化建议的推理链。
  • 推理链越长、需要的业务上下文越多,reference 补充的效果越差。
  • 在观测案例中,count-first 优化建议在补充 reference 后仍未被模型自主发现(修复率 0%)。

对于领域知识盲区,更务实的应对策略是: - 将该类建议从"AI 应自动发现"的期望调整为"人工复核重点关注"的范围。 - 如果业务特定模式足够重要且出现频率高,考虑为其单独构建一个专项 skill,而非在通用 skill 中处理。

15.5 验证方法论

验证是迭代循环的闭环环节,设计不当会使整个改进过程失去意义。

核心约束:清除对话上下文,在全新对话中重跑改进前的遗漏案例。不满足这个条件的验证结果不可信。

验证条件检查表

□ 对话上下文已清空(clear context 或新开对话)
□ 模型版本与首次审查一致
□ 审查模式与首次一致(Lite / Standard / Strict)
□ 被审查代码与首次完全相同(原始版本,非修复后版本)
□ 未提供任何提示或引导(不额外告知 "注意检查 X")

量化记录

验证结果应以表格形式记录,逐项对比首次审查和改进后审查,区分"保持"、"修复"、"未修复"、"新发现"四种状态。这份记录既是改进效果的证明,也是后续继续迭代的起点数据。

对部分修复结果的处理:如果某项遗漏在改进后仍未修复,需要重新分类根因——可能初始归因有误,或者根因属于"执行遗漏"而执行规则仍不够强。残留遗漏进入下一轮迭代,而非被忽略。


16. 迭代案例集与迭代边界

理论框架在具体案例中才能被真正理解。本章以两类 skill 的迭代实践为例,展示根因分类框架在真实场景中的应用——方法论本身(分类→修复→验证)不局限于代码审查场景,适用于任何遭遇漏报或质量问题的 Skill。

16.1 三类根因在实践中的应用(以代码审查 Skill 为例)

以下案例均来自 go-code-reviewer 在实际使用中的遗漏记录,作为三类根因分类框架的实证演示。每个案例对应一种(或多种)根因类型,展示不同根因下改进措施的选择逻辑和实际效果。

这是迭代方法论最完整的实证记录:3 个案例、8 处遗漏、系统性归因、针对性改进、清上下文验证。

案例一:ListLayout — 模型执行遗漏 + 后置合理化幻觉

被审查代码(节选)

func (s *LayoutService) ListLayout() (layouts []*db.Layout, total int64, err error) {
    whereClause := fmt.Sprintf("uid = %v and corp_id = %v", s.uid, s.corpId)
    if err := s.orm.Model(&db.Layout{}).Where(whereClause).Order("updated_at desc").Find(&layouts).Error; err != nil {
        return nil, 0, err  // 未包装
    }
    if err := s.orm.Model(&db.Layout{}).Where(whereClause).Count(&total).Error; err != nil {
        return nil, 0, err  // 未包装
    }
    return layouts, total, nil
}

AI 报出:SQL 注入(High)、缺少 ctx(Medium)、Find 无分页(Medium)。共 3 项。

人工复核发现的遗漏

  • 遗漏一:两处 return nil, 0, err 将 GORM 原始错误直接透传,调用方无法区分是哪个查询失败,且原始错误可能携带表名、列名等敏感信息。正确做法:return nil, 0, fmt.Errorf("ListLayout: find layouts: %w", err)
  • 遗漏二:count-first 优化——当 total == 0 时跳过代价更高的 Find 查询,在空结果率高的业务场景下可显著减少 SQL 请求。

根因分析

遗漏 根因类型 分析
错误未包装 模型执行遗漏 SKILL.md Error Handling checklist 明确列出 Missing error wrapping context (%w),但模型未逐条检查每个 return err 路径
count-first 优化 领域知识盲区 业务场景驱动的性能优化,标准 checklist 无法覆盖

追问模型为何遗漏错误包装时,模型声称"误套了 anti-example 里的抑制规则"——但代码里完全没有包装,anti-example 的前置条件显然不成立。这是典型的后置合理化幻觉:模型在遗漏某项检查后,遭遇追问时构造了一个听起来合理的解释,而非承认遗漏。这个现象本身也驱动了改进措施——在执行规则中加入"应用任何 anti-example 抑制之前,必须先引用代码中的具体证据"。

案例二:getBatchUser 串行版本 — checklist 缺失 + 分析视角不对称

被审查代码(节选)

func getBatchUser(ctx context.Context, userKeys []*UserKey) (users []*User, error) {
    userList := make([]*User, len(userKeys))
    for i, u := range userKeys {
        user, err := redis.GetGuest(ctx, u.Id)  // u 可能为 nil → panic
        if err != nil {
            log.WarnContextf(ctx, "no found guest user: %v", u)
            continue
        }
        userList[i] = user
    }
    return userList, nil
}

AI 报出:错误被静默吞噬(High)、结果切片含隐式 nil 条目(Medium)、N+1 Redis 调用(Medium)。共 3 项。

人工复核发现的遗漏userKeys []*UserKey 是指针切片,元素可能为 nil。代码在 u.Id 处直接解引用,若任一元素为 nil 则触发 panic。正确做法:循环内先检查 if u == nil { continue }

根因分析

遗漏 根因类型 分析
指针切片 nil 防御 checklist 缺失 + 分析视角不对称 SKILL.md Code Quality checklist 无此检查项;且模型在同一循环中发现了输出侧 nil(userList[i] 可能为 nil),却未对输入侧u 可能为 nil)应用同样的分析——分析视角不对称

这是一个复合根因案例:即使补全 checklist,输入/输出分析视角不对称的问题仍可能导致遗漏。改进时需要同时补 checklist 并在执行规则中明确"对指针切片需同时检查输入侧和输出侧"。

案例三:getBatchUser 并发版本 — 高缺陷密度下的注意力竞争

被审查代码(节选)

func getBatchUser(ctx context.Context, userKeys []*UserKey) (users []*User, error) {
    userList := make([]*User, 0)  // 未预分配容量
    var wg sync.WaitGroup
    for i, u := range userKeys {
        if u == nil { continue }
        wg.Add(1)
        go func() {
            defer wg.Done()
            // 无 recover,无并发限制
            user, err := redis.GetGuest(ctx, u.Id)
            if err != nil { log.WarnContextf(ctx, "no found guest user: %v", u); continue }
            userList = append(userList, user)  // 数据竞争
        }()
    }
    return userList, nil  // 未等待 goroutine 完成
}

AI 报出(Strict 模式):goroutine 内 continue 编译错误(High)、缺少 wg.Wait()(High)、并发写数据竞争(High)、循环变量捕获(High)、错误静默吞噬(Medium)。共 5 项,其中 4 项 High。

人工复核发现的遗漏

  • 切片未预分配容量make([]*User, 0) 初始容量为 0,len(userKeys) 是已知上界,应预分配:make([]*User, 0, len(userKeys))
  • goroutine 缺少 panic recover:Go 的 panic 不跨 goroutine 边界传播,任意 goroutine 内 panic 导致整个进程崩溃,wg.Done() 也不会执行。
  • 未限制 goroutine 数量len(userKeys) 无上限约束,瞬间启动大量 goroutine 可能导致调度器压力激增、Redis 连接池打满。

根因分析

遗漏 根因类型 分析
切片容量预分配 模型执行遗漏 SKILL.md Performance checklist 明确列出该项,但 4 个 High 并发缺陷占据注意力,Performance 类 checklist 被跳过
goroutine panic recover checklist 缺失 Concurrency checklist 覆盖了并发"正确性",缺少并发"安全性"(未覆盖 recover)
goroutine 数量控制 checklist 缺失 Concurrency checklist 缺少并发"规模安全性"(资源耗尽、调度压力)

三处遗漏的共同模式:在存在多个 High 缺陷时,注意力集中在"能让代码停止运行的错误",系统性漏检了"代码能跑但在生产规模下会崩"的类别

16.2 遗漏归因汇总

3 个案例共 8 处遗漏(含 7 项硬性缺陷、1 项优化建议),归因分布如下:

根因类型 数量 对应遗漏
checklist 缺失 3 goroutine panic recover、goroutine 数量控制、指针切片 nil guard
模型执行遗漏 3 错误未包装、切片容量预分配、高缺陷密度下注意力分散
领域知识盲区 1 count-first 优化(特定场景优化建议)
checklist 缺失 + 模型执行遗漏(复合) 1 指针切片 nil guard(checklist 未覆盖 + 输入/输出分析视角不对称)

改进措施:补充 4 项 checklist 条目、新增 1 个 reference 文件(go-review-anti-examples.md)、强化 2 条执行规则;同时将 SKILL.md 从 502 行优化至 470 行(通过将 anti-examples 迁移至独立 reference 文件)。

验证结果(清上下文后重跑相同案例)

根因类型 改进措施 修复数 未修复数 观测修复率
checklist 缺失 补全 checklist 3/3 0 100%
模型执行遗漏 强化执行规则 2/3 1 67%
领域知识盲区 新增 reference 0/1 1 0%
checklist 缺失 + 执行遗漏(复合) 补全 + 强化规则 1/1 0 100%

总遗漏从 8 项降至 2 项,整体修复率 75%。同时新增发现 6 项此前未报出的问题(如 named return shadowing、日志消息误导性)。

16.3 git-commit Skill 的迭代案例(补充视角)

go-code-reviewer 展示的是"漏报驱动"的迭代路径——由实战中发现的遗漏触发。git-commit skill 则展示了另外两种同样常见的迭代触发类型:误报过多(工具噪音破坏信任)和诚实降级缺失(样本不足时仍输出看似确定的建议)。两种 skill 类型不同,触发点不同,但根因分类和改进路径的逻辑完全相同。

迭代案例一:secret 检测误报控制

发现的问题:secret 检测在实际使用中误报严重。password=token= 等通用模式频繁命中测试文件、文档和示例配置(如 config.example.yml 中的 password=changeme)。初版"命中就阻断"的设计导致开发者频繁被打断。

根因分析:初版把所有 secret 模式平等对待——AKIA0EXAMPLE1234(结构化 token,假阳性极低)和 password=changeme(通用键名,假阳性极高)触发相同的阻断逻辑。这是典型的精度梯度缺失问题。

改进方案

改动 解决的问题
SECRET_PATTERNS 拆为 Tier1(结构化 Token)和 Tier2(通用键名) 区分高低置信模式,分级处置
新增行级内联抑制(# nosec / # git-commit-allow 已确认安全的误报有标准出口
路径过滤扩展至 /examples/.template..dist 覆盖示例配置的常见存放位置
Tier2 命中增加值分析三档处置(忽略/软警告/硬阻断) password=changeme 自动忽略,高熵值才阻断

验证:对示例配置文件的误报从 ~60% 降至 <5%,敏感扫描场景通过率维持 100%。

迭代案例二:scope 发现的诚实降级

发现的问题:skill 通过分析 git log 最近 30 条记录决定 scope 写法。在新仓库或刚切换分支时,历史记录不足,scope 建议变得不稳定——有时加 scope,有时不加,同一模块的 scope 名称也不一致。

根因分析:算法对历史数据的依赖没有设置下限。当样本不足时,统计结果不可靠,但 skill 仍输出了看似确定的建议。这是诚实降级缺失的问题(见进阶篇 §6.7)。

改进方案:当 git log 记录 < 10 条时,scope 改为可选,并提示"历史记录不足,建议手动指定 scope";同时添加 scope 一致性检查,若最近 10 条同模块提交写法不统一,输出警告。

核心原则:Skill 可以拒绝给出不可靠的建议——比"总是给建议但有时是错的"更值得信赖。

16.4 迭代停止信号

不是所有 skill 都需要无限迭代。以下四个信号表明迭代可以暂停或停止:

信号 含义
A/B 测试中 with-skill 与 without-skill 差异 < 10% Skill 的差异化价值不足,考虑简化或合并
连续 3 次迭代未改变评估分数 已接近当前架构的天花板,需要根本性重构或接受现状
实际使用中被跳过的频率 > 30% Skill 与开发者工作流存在摩擦,需要审视定位
Token 消耗持续增长但 ROI 下降 过度复杂化,考虑拆分为多个轻量 skill

停止迭代不等于放弃维护。以下事件应触发重新评估:模型版本升级、业务场景发生重大变化、团队代码规范更新、新案例揭示此前未见的遗漏模式。

Skill 的迭代应遵循与代码相同的版本管理实践:每次改进提交到 Git,附带清晰的 commit message 说明改了什么、为什么改。团队成员可以通过 Git 历史追溯 skill 的演进脉络,理解每个设计决策的背景。每次改动后重跑 scripts/run_regression.sh,确保新的修改没有破坏已有的合约测试和黄金场景测试。

16.5 Skill 完整生命周期与多层防御

结合评估篇(§10-11)的量化框架与本章的迭代实践,skill 的完整生命周期如下:

┌─────────────────────────────────────────────────────────────────┐
│                    Skill 完整生命周期                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ① 构建                                                         │
│  ├── 设计模式(门禁 + 反例 + 渐进式披露 + 结构化输出)              │
│  ├── 合约测试 + 黄金场景测试                                      │
│  └── 回归测试通过                                                │
│       ↓                                                         │
│  ② 量化评估(评估篇 §10)                                         │
│  ├── 触发准确率: 正例/负例查询集 → Recall + Precision              │
│  ├── 实际任务表现: with-skill vs without-skill 对照实验            │
│  └── Token 效费比: 额外成本 vs 开发者时间 ROI                     │
│       ↓                                                         │
│  ③ 数据驱动迭代(本章 §15-16)                                    │
│  ├── 实战漏报 / 评估数据 → 根因分类(§15.3)                       │
│  ├── 针对性修复(§15.4)→ 清上下文验证(§15.5)                    │
│  └── 重复直至达标或触发停止信号(§16.4)                           │
│       ↓                                                         │
│  ④ 融入开发流程(集成篇 §12-14)                                  │
│  ├── 本地: Makefile 驱动的质量门禁                                │
│  ├── CI: Skill 驱动的自动化门禁                                   │
│  └── PR: AI 驱动的代码审查                                       │
│       ↓                                                         │
│  ⑤ 持续监控与再评估                                              │
│  ├── 模型更新 / 新场景 / 团队规范变化 → 触发复评                    │
│  └── 合约测试 + 回归测试守护 skill 不退化                          │
│       ↓                                                         │
│  回到 ② 或 ③                                                    │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

阶段③(本章)在闭环中的位置:以前 skill 从①直接跳到④,中间缺乏验证——好比写了代码不跑测试直接上线。评估篇(②)建立了量化基线,迭代篇(③)建立了系统性改进路径,两者合力让 skill 开发具备与软件开发同等的工程严谨度。

多层防御体系

迭代改进的目标是最大化 AI skill 的效用,但 AI 代码审查存在两个固有边界,不能通过迭代消除:

  1. 注意力竞争边界:高缺陷密度场景下,模型会系统性地忽略较低优先级的检查项。规则约束只能降低概率,无法消除。
  2. 推理链长度边界:需要跨多个信号组合推理的优化模式,即使 reference 提供完整知识,模型也可能无法自主完成推理链。

因此,高质量代码保障体系应当是多层防御的:

┌─────────────────────────────────────────────────────────────────┐
│                    代码质量保障体系                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  第一层:自动化测试                                               │
│  ├── 单元测试(逻辑正确性、边界条件)                              │
│  ├── API 集成测试(接口契约、端到端数据流)                        │
│  └── E2E 端到端测试(用户流程、跨服务交互)                        │
│                                                                 │
│  第二层:AI 代码审查                                              │
│  ├── 静态分析工具(go vet、staticcheck、golangci-lint)            │
│  └── AI Agent skill 审查(模式匹配、缺陷检测)                     │
│                                                                 │
│  第三层:人工代码审查                                              │
│  ├── 业务逻辑合理性(AI 难以判断的领域知识)                        │
│  ├── 架构设计评审(跨模块影响、长期可维护性)                       │
│  └── AI 审查结果复核(发现 AI 遗漏、校准 AI 输出)                  │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

三层之间的关系不是替代,而是互补:

  • 自动化测试捕获回归和行为偏差——代码"能不能跑对"。
  • AI 代码审查捕获模式化缺陷和已知反模式——代码"有没有常见坑"。
  • 人工代码审查捕获业务语义、架构合理性和 AI 盲区——代码"该不该这么写"。

任何单一层都不足以保证代码质量。Skill 迭代的价值在于持续提升第二层的覆盖率和准确率,而非试图用 AI 完全替代第三层。


下一步阅读:集成篇(§12-14)介绍如何将经过迭代验证的 skill 融入 Makefile、CI 流水线和 PR 流程,形成完整的质量管线。