
🎯 学 gstack 的外部审查评论自动分类与回复系统:不是手动检查 Greptile 的每条评论,而是自动抓取、抑制已知误报、分类(真问题/已修复/误报)、根据历史交互升级回复强度——让外部 AI 审查工具真正有用而不是噪音源。 ⏱️ 预计时间:25 分钟
[!quote]- 📖 原Skill精要 技能名称:greptile-triage([[L6-15-PR代码审查|review]] 的子系统) 核心功能:gstack review 的外部 AI 审查评论自动分诊系统。自动抓取 Greptile PR 评论、分类(真问题/已修复/误报/已抑制)、应用升级检测算法决定回复强度(Tier 1 友好 vs Tier 2 坚定)、使用模板化回复(含证据+建议重新排序)、持久化分诊历史到项目和全局存储。 所属体系:gstack 虚拟工程团队 协作关系:是 [[L6-15-PR代码审查|review]] 的 Step 2.5 和 Step 5.8,与审查发现合并输出
1. 课程概览
💡 白话小课堂:Greptile 就像是 GitHub 上的"自动审查机器人"——它会在你的 PR 上自动评论代码问题,但问题是 AI 审查 Bot 会产生噪音:误报、风格 nit、对已修复代码的评论。如果每一条都手动检查——每天 20+ PR 上 35 条评论,40% 是误报,工程师开始忽略所有评论,包括真正的 bug。greptile-triage 的策略不是关掉它(那会错过真问题),也不是盲目信任(那会产生噪音疲劳),而是"智能分诊":自动抓取评论、用抑制历史过滤已知误报、把每条评论分类为真问题/已修复/误报/已抑制、用分级回复策略(Tier 1 友好解释 vs Tier 2 坚定关闭)、并且把分类结果写入抑制历史——让系统"学会"哪些是噪音。
2. Greptile Triage 是什么?
Greptile 是 GitHub PR 上的 AI 代码审查 Bot
Greptile 自动在 PR 上发布代码审查评论。 问题是:AI 审查 Bot 会产生噪音——误报、风格 nit、对已修复代码的评论。
greptile-triage 是 gstack 的应对策略: → 不是忽略 Greptile(会错过真问题) → 也不是盲目信任(会产生噪音疲劳) → 而是——智能分诊:分类、过滤、回复
greptile-triage 被 /review(Step 2.5)和 /ship(Step 3.75)共享引用。
3. 抓取——找到 Greptile 的评论
并行抓取两种评论
PR 上的评论有两种形式:
Line-level 评论(PR review comments)
→ API: repos/$REPO/pulls/$PR_NUMBER/comments → 关联到具体文件的具体行 → 过滤:user.login == "greptile-apps[bot]" AND position != null → position != null 自动跳过因 force push 而过时的评论
Top-level 评论(PR issue comments)
→ API: repos/$REPO/issues/$PR_NUMBER/comments → PR 整体的评论(不关联具体文件/行) → 过滤:user.login == "greptile-apps[bot]"
两个 API 调用并行执行(wait 等待两者完成)。
无 PR 时的处理
→ 无 PR → 跳过整个 Greptile 流程 → API 错误 → 跳过(Greptile 是增值的,审查在无它时也能工作) → 零 Greptile 评论 → 跳过
4. 抑制检查——记住已知误报
不每次都重新判断同一个误报
greptile-triage 维护一个抑制历史文件,记录之前的分类结果。
历史文件格式
→ 每行一个条目: YYYY-MM-DD | owner/repo | type | file-pattern | category
type 取值: → fp — 误报(False Positive) → fix — 已确认为需要修复的真问题 → already-fixed — 已在分支上修复的真问题
category(固定集合): → race-condition, null-check, error-handling, style, type-safety, security, performance, correctness, other
抑制逻辑
对每条抓取到的评论: 1. 匹配 repo = 当前仓库 2. 匹配 type = "fp"(只抑制已知误报——之前确认的真问题不抑制) 3. 匹配 file-pattern = 评论的文件路径 4. 匹配 category = 评论中的问题类型 → 四个条件都匹配 → 标记为 SUPPRESSED → 跳过
双文件策略
→ ~/.gstack/projects/$SLUG/greptile-history.md(项目级抑制) → ~/.gstack/greptile-history.md(全局汇总) → 每次写入同时追加到两个文件 → 抑制检查读取项目级文件
5. 分类——判断每条评论的性质
四类分类
对每条未抑制的评论:
1. VALID & ACTIONABLE — 真问题,代码中存在
→ 是一个真实的 bug、竞态条件、安全问题或正确性问题 → 在当前代码中存在(不在之前 commit 中已修复) → 行动:纳入审查发现,走 Fix-First 流程
2. VALID BUT ALREADY FIXED — 真问题但已经修了
→ 问题真实存在,但在分支的后续 commit 中已被处理 → 需要识别修复的 commit SHA → 行动:自动回复"Already fixed"
3. FALSE POSITIVE — 评论理解错误
→ 评论误解了代码 → 标记的问题在其他地方已处理 → 或纯粹是风格噪音 → 行动:展示给用户确认 → 回复 + 写入历史
4. SUPPRESSED — 已在抑制检查中过滤
→ 之前确认的误报,文件未变更 → 行动:静默跳过
分类过程
- Line-level 评论:读取指示的 path:line 及 ±10 行上下文
- Top-level 评论:读取完整评论正文
- 对照完整 diff (git diff origin/main) 和审查清单交叉验证
- 判定类别
6. 回复模板——分级互动策略
两级回复系统
Tier 1(首次回复)——友好、包含证据
当这是 gstack 第一次回复该评论时使用。
对 FIXES(用户选择修复):
Fixed in commit-sha.
```diff
- old problematic line(s)
- new fixed line(s) ```
Why: 1-sentence explanation
**对 ALREADY FIXED(之前已修复):**
Already fixed in commit-sha.
What was done: 1-2 sentences describing how the existing commit addresses this
**对 FALSE POSITIVES(评论不正确):**
Not a bug. 1 sentence directly stating why
Evidence:
- specific code reference showing the pattern is safe/correct
- e.g., "The nil check is handled by ActiveRecord::FinderMethods#find"
Suggested re-rank: This appears to be a X issue, not a Y. Consider lowering severity.
### Tier 2(Greptile 再次标记)——坚定、压倒性证据
当升级检测发现已有 gstack 回复但 Greptile 又发了同类评论时使用。
This has been reviewed and confirmed as [intentional/already-fixed/not-a-bug].
```diff full relevant diff showing the change or safe pattern ```
Evidence chain:
- file:line permalink showing the safe pattern or fix
- commit SHA where it was addressed, if applicable
- architecture rationale or design decision, if applicable
Suggested re-rank: Please recalibrate — this is a X issue, not Y.
7. 升级检测——知道何时强硬
什么情况触发 Tier 2?
在撰写回复之前,检查是否已有 gstack 回复存在于该评论线程上:
对于 Line-level 评论
→ 获取回复:gh api repos/$REPO/pulls/$PR_NUMBER/comments/$COMMENT_ID/replies → 检查是否有回复包含 gstack 标记:Fixed、Not a bug.、Already fixed
对于 Top-level 评论
→ 扫描评论时间戳之后的 issue comments → 检查是否包含 gstack 标记
升级规则
→ 有已有 gstack 回复 AND Greptile 又发了同类评论 → Tier 2 → 无已有 gstack 回复 → Tier 1 → API 错误或线程不明确 → 默认 Tier 1(永不基于模糊性升级)
为什么需要 Tier 2?
→ 防止无限循环——Greptile 反复标记同一个已确认的问题 → 信号升级——第一次友好解释,第二次用完整证据链关闭讨论 → 保护开发者注意力——不被反复的误报噪音疲劳
8. 回复 API——正确的端点
两种评论类型用不同的 API
Line-level 评论的回复
→ gh api repos/$REPO/pulls/$PR_NUMBER/comments/$COMMENT_ID/replies → POST 带 -f body="reply text" → 这是回复 PR review comment 的方式
Top-level 评论的回复
→ gh api repos/$REPO/issues/$PR_NUMBER/comments → POST 带 -f body="reply text" → 这是对 PR issue comment 的通用回复(发新评论)
容错
→ 如果回复 POST 失败(PR 已关闭、无写权限)→ 警告但继续 → 不让一个失败的回复中断整个审查流程
9. Greptile 集成在审查流程中的位置
/review 中的 Step 2.5
/review 在早期获取 Greptile 评论: → 在关键 pass 之前(Step 4 之前) → 分类结果存储供 Step 5 Fix-First 使用 → VALID & ACTIONABLE 的评论纳入发现列表 → FALSE POSITIVE 的评论在 Step 5 中展示给用户确认
/ship 中的 Step 3.75
/ship 也会运行 Greptile 分诊: → 在合入前的最终检查 → 确保没有新的 Greptile 评论(自 /review 之后) → 如果有新的 VALID & ACTIONABLE → 用户决定是否处理
Greptile 是增值的——审查在没有它时也能工作
→ gh 命令失败 → 静默跳过 → 零 Greptile 评论 → 静默跳过 → Greptile 集成失败 → 不影响审查输出 → 永远不因 Greptile 问题而中断审查
10. 结构拆解:外部 AI 评论分诊 Skill 模板
外部 AI 审查评论分诊型 Skill 模板
核心特征
→ 管理对象 = 外部 AI 代码审查 Bot(如 Greptile)的 PR 评论——过滤噪音、保留信号 → 核心原则 = 增值定位(非必需品,失败静默跳过)+ 抑制优先(抑制历史"学会"噪音)+ 分级回复(Tier 1 友好 / Tier 2 坚定) → 关键设计 = 并行双 API 抓取、四类分类(VALID/ALREADY FIXED/FALSE POSITIVE/SUPPRESSED)、 抑制历史双文件策略、升级检测算法、模板化回复
通用结构
Fetch & Filter(抓取与过滤)
- Line-level 评论(PR review comments API)+ Top-level 评论(issue comments API)
- 并行抓取,过滤 user.login == "greptile-apps[bot]"
- 无 PR / API 错误 / 零评论 → 静默跳过(增值定位)
Suppression Check(抑制检查)
- 四条件匹配:repo + type(fp) + file-pattern + category
- 双文件策略:项目级(~/.gstack/projects/$SLUG/greptile-history.md)+ 全局汇总
- 只抑制 fp(已知误报)——fix 和 already-fixed 不抑制
Classification Pipeline(四类分类)
- VALID & ACTIONABLE → 纳入审查发现,走 Fix-First 流程
- VALID BUT ALREADY FIXED → 自动回复 "Already fixed"
- FALSE POSITIVE → 展示给用户确认 → 回复 + 写入抑制历史
- SUPPRESSED → 静默跳过
Tiered Reply System(两级回复系统)
- Tier 1(首次):友好、包含证据(diff + why + suggested re-rank)
- Tier 2(升级后):坚定、压倒性证据(evidence chain: permalink + commit + rationale)
- 升级检测:已有 gstack 回复标记(Fixed/Not a bug./Already fixed)且 Greptile 又发同类评论 → 升级
Graceful Degradation(优雅降级)
- Greptile 是增值的——API 失败、零评论、无写权限均静默跳过
- 永远不因外部审查问题中断内部审查管道
- /review Step 2.5 + /ship Step 3.75 共享引用
11. 电商 Skill 案例:Greptile 分诊——电商平台 PR 的噪音过滤
🛒 实战案例:某电商App的GitHub仓库启用了Greptile自动代码审查。但Greptile每天在20+个PR上产生约35条评论——其中约40%是误报(False Positive)或风格nit。团队开始"评论疲劳"——对Greptile的评论全部忽略,包括真正的bug发现。用greptile-triage对这些外部评论进行智能分诊,过滤噪音、保留信号。
PR #612分诊实例:8条Greptile评论经分诊后分类如下:
- 评论1 "竞态条件checkout.ts:45" → 审查确认:真正的竞态条件(read-check-write模式),但gstack /review已在CRITICAL pass中发现且后续commit已修复→分类VALID BUT ALREADY FIXED→自动回复"Already fixed in a1b2c3d"。
- 评论2 "考虑用const替代let at order.ts:23" → 审查确认:
let orderTotal在后续代码中确实被重新赋值(应用优惠券后),Greptile只读了第一行就下结论→分类FALSE POSITIVE→写入抑制历史(shop/ecom-platform|fp|src/services/order.ts|style)。- 评论3 "魔数3600 at payment.ts:89" → 审查确认:
const CACHE_TTL = 3600已赋值给命名常量,不是魔数→分类FALSE POSITIVE→写入抑制历史(shop/ecom-platform|fp|src/payment/*|style)。- 评论4 "缺少null检查 at inventory.ts:112" → 审查确认:
const stock = await redis.get(...); if (stock < 0)中redis.get可能返回null,而null < 0在JS中为false→静默跳过了null检查→这是真问题!分类VALID & ACTIONABLE→纳入gstack /review发现列表→Fix-First修复。- 分诊结果:8条评论中2条VALID(已修复1+新发现1)、4条FALSE POSITIVE(风格误报)、2条DUPLICATE(与gstack审查重复)。过滤率75%(6/8条无需人工介入)。
抑制检查机制:第2周PR #704再次修改order.ts时,Greptile再次评论"用const替代let"→抑制检查命中4个条件(repo+type+file-pattern+category全部匹配)→SUPPRESSED→静默跳过。工程师不再看到这条已知误报。
升级检测(Tier 2):Greptile连续3个PR标记不同文件中的"3600魔数"——PR #612(payment.ts)、PR #704(checkout.ts)、PR #891(另一个文件)→第3次触发升级。gstack自动回复Tier 2带证据链:"This has been reviewed and confirmed as intentional. 代码库规约:所有数字字面量必须赋给命名常量。证据:(1)代码库所有数字均已命名,(2)规约已文档化在CLAUDE.md的Coding Standards下,(3)3600含义无歧义。建议rerank:这是低严重度的风格偏好,请将命名数字常量视为非魔数。"
1个月数据价值:Greptile总产生约847条评论→VALID & ACTIONABLE 312条(37%)→VALID BUT ALREADY FIXED 95条(11%)→FALSE POSITIVE 285条(34%)→SUPPRESSED 155条(18%)。噪音过滤率52%(285+155=440条无需关注)。真问题捕获:发现了23个gstack内部审查遗漏的问题,其中2个为CRITICAL(一个跨服务调用超时未处理、一个第三方SDK版本已知漏洞)。开发体验改善:工程师从每天手动检查每条评论(15分钟/天)→只看到分类为VALID的评论(5分钟/天)→20个开发者每天节省200分钟。抑制精准度98%——仅2%的抑制后来被证明是真问题而移除。
🔑 启示:外部AI审查不是"替代"内部审查——两者的价值互补:外部AI"新人视角"可能发现团队习以为常的盲区,内部审查"上下文感知"减少了误报。greptile-triage的角色像是"信号滤波放大器"——过滤掉52%的噪音,放大23个遗漏的关键信号。最有说服力的数字:即使52%是噪音,真问题中仍包含2个内部遗漏的CRITICAL。
12. 掌握检验
Q1:greptile-triage 的四种分类中,"VALID BUT ALREADY FIXED"为什么不被加入库存抑制(只抑制 FALSE POSITIVE)?
- A) 因为已修复的问题不需要追踪
- B) 因为"已修复"是临时状态——代码变更后修复可能被回退,需要重新检查
- C) 因为抑制历史文件不支持"已修复"类型
- D) 因为 Greptile 不会对已修复的代码再次评论
Q2:Tier 2 回复的升级检测中,升级条件是什么?
- A) Greptile 连续评论了同一个文件 3 次
- B) 已有 gstack 回复(Fixed / Not a bug. / Already fixed)但 Greptile 又发了同类评论
- C) Greptile 的评论被用户手动标记为误报
- D) Greptile 评论数量超过 10 条
Q3:抑制检查的四个匹配条件是 repo + type + file-pattern + category。为什么用 file-pattern(如 src/payment/*)而非精确的 file:line?如果在不同文件但相同 pattern 的代码段中 Greptile 再次犯了同类误报,抑制规则应如何处理?
Q4:在电商案例中,Greptile 评论"Magic number 3600"被分类为 FALSE POSITIVE(因为已赋值给命名常量 CACHE_TTL)。请比较 Greptile 和 gstack 对这个问题的判断差异——这种差异揭示了"外部 AI 审查"和"上下文感知审查"之间的什么本质区别?
Q5:Greptile 的"增值"定位——"审查在没有它时也能工作"——是一个深思熟虑的设计选择。为什么把外部 AI 审查定位为"增值"而非"必需品"是一个更好的架构决策?如果用"必需品"定位替代,会引入哪些系统性风险?
Q6:电商案例中 1 个月的数据显示 52% 噪音过滤率,但同时也捕获了 23 个内部审查遗漏的问题(含 2 个 CRITICAL)。请基于这些数据,写一个给 CTO 的 3 句话建议——是否应该继续使用 Greptile,为什么?
13. 答案
点击查看答案
Q1:B —— "已修复"是一个可以被撤销的状态。
Q2:B —— 升级检测扫描 PR 上已有的 gstack 回复标记,如果之前已经回复过(包含 Fixed / Not a bug. / Already fixed)但 Greptile 又发了同类评论,则触发 Tier 2。
Q3:用 file-pattern 而非精确 file:line 是因为同类型误报会在同目录的类似代码中反复出现——比如 Greptile 在 src/payment/checkout.ts 中对命名常量 3600 的误报,很可能也会在 src/payment/callback.ts 中再次出现。使用 file-pattern(如 src/payment/*)可以做目录级抑制,减少人工确认的重复劳动。如果跨目录出现同类误报,应该更新 file-pattern 为更宽的范围——抑制规则本身也可以演化。
Q4:Greptile 的判断是模式匹配("数字字面量 3600 出现在代码中"→ 魔数),gstack 的判断是上下文理解("3600 赋值给了命名常量 CACHE_TTL,且符合 CLAUDE.md 中声明的编码规范")。本质区别:外部 AI 审查看到的是"语法模式",gstack 审查看到的是"语义上下文"。Greptile 擅长高精度的模式匹配(能捕获所有"数字字面量"),但缺乏项目的特定上下文(不知道团队约定"命名常量不算魔数")。这就是分诊的价值——不是抛弃外部审查的模式匹配能力,而是用上下文理解过滤其噪音。
Q5:"增值"定位意味着 Greptile 集成失败不影响核心审查流程——API 错误、零评论、认证失败都静默跳过。如果定位为"必需品":①审查流程的可用性被绑定到外部服务——GitHub API 挂了 = 审查不能继续;②增加了"审查不可用"的单点故障;③Greptile 的评论质量波动(模型升级后突然更多误报)直接拉低审查质量。"增值"定位让 Greptile 是锦上添花,而非功能必需——这在分布式系统中称为"优雅降级"。
Q6:参考建议:"继续使用 Greptile,但将 greptile-triage 作为强制前置——52% 的噪音过滤率证明手工处理不可持续。23 个遗漏问题(含 2 个 CRITICAL)证明外部 AI 审查发现了内部审查的模型盲区——这是跨模型交叉验证的价值,不应关掉。下一步:将 Greptile 分类为 VALID 的发现纳入 learning 系统,逐步充实内部清单以减少对外部审查的依赖。"
(5/6 通过)
延伸阅读
- [[L6-15-PR代码审查|PR代码审查 —— AI帮你把关每一行代码的质量]]
- [[L6-18-审查仪表盘|审查仪表盘 —— 一眼看清你的代码质量在变好还是变差]]
- [[L6-20-自动化测试修复|自动化测试+自动修复 —— 发现bug并顺手帮你修好]]

评论区
共 0 条评论