PostHog ReviewHog 验证器评分深度解读:Sol @ max(K3)运行的混淆矩阵、判定方法与七条发现的真伪
【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog
导读:KC.score.md是 PostHog ReviewHog(自驱动代码审查流水线)中“验证器(validator)模型评估实验”在 K3 运行(GPT-5.6 Sol 固定为max推理强度)结束后生成的标准评分卡。本文以该评分卡为骨架,结合同目录下的判定数据(KC.json)、真值(KC.truth.json)、簇匹配(KC.match.json)与评分脚本(score_validator.py),完整讲解这套“保持/丢弃 × 真实/不真实”的验证器混淆矩阵评估方法论,逐条复盘 7 个审查发现的真伪判定,并揭示一个贯穿实验的方法学教训:请求层的max固定并未真正到达模型。读完本文,你将掌握 ReviewHog 如何为“AI 审查 AI 的发现”打分,以及如何用同类方法评估任何 LLM 验证环节的精度与召回。
ReviewHog 流水线中的验证器阶段
ReviewHog 是 PostHog 的自驱动 PR 审查产品(架构与词汇见 CONTEXT.md)。一次审查运行由多个阶段串联:评审(review)以多个视角(perspective)与盲区(blind-spot)在沙箱中并行扫描 PR 分块 →去重(dedup)→验证(validation)→ 发布评论。其中验证器阶段是质量闸门:评审器(reviewer)产出的每条 finding 由另一个模型独立复核,输出 keep/drop 裁决,只有通过的 finding 才会发布到 PR 上。
2026-08 实验(PLAN.md)要回答的核心问题:GPT-5.6 Sol(Codex 多轮会话)能否替代 Claude Opus 承担验证器角色,在更低成本与耗时下不损失判定质量?实验复用同一冻结 PR(#75215,heada7fb363)、相同的 pinned chunks 与零评论净室环境,评审器固定为 Sol。K 系列是前三个运行:K1(错误分支)、K2(PR 树、固定xhigh)、K3(PR 树、固定max)——本文聚焦的 KC.score.md 正是 K3 的评分卡。
评分方法:混淆矩阵如何生成
验证器评分本质上是一张二分类混淆矩阵,score_validator.py 实现了全部逻辑。对每条 finding,取两个独立来源做交叉比较:
- 验证器裁决(
findings.json中的is_valid):keep =true,drop =false; - 独立真值(
truth.json中的is_real):该 finding 对应的问题在冻结工作树中是否真实存在。
由此得到四象限并计算三个核心指标:
| 指标 | 定义 | K3(KC)结果 |
|---|---|---|
| 保持即真实(precision) | kept 中真实的比例 = 真阳性 / 全部保持 | 3/6 = 50% |
| 真实被保持(recall) | 真实 finding 中被保持的比例 | 3/3 = 100% |
| 不真实被丢弃 | 不真实 finding 中被丢弃的比例 | 1/4 = 25% |
is_real真值不是模型自评,而是由 build_truth.py 从两条证据路径构建:
- 一致性簇裁决:每条 finding 先由 KC.match.json 匹配到 known_clusters.json 中 76 个已知问题簇。若某簇
n_verified >= 3且全部真实或全部不真实(一致簇),则直接采用簇裁决; - 逐条人工验证(refutation-first):混合簇与新 claim 在冻结工作树上逐条验证(
findings/verify/),并优先复用相同 claim 的历史裁决。
KC 的 7 条全部获得真值(0 unscored),其来源清晰记录在 KC.truth.json:3 条来自一致簇裁决(cluster 3/3、cluster 0/7),4 条来自“verified-same-claim”复用此前 KA/KB 集的同 claim 验证结果。匹配置信度全部为high,且在 KC.match.json 中给出了 runner-up 簇排除理由——例如 KC1 判定为簇 3 的 JSON 布尔强制转换问题,而非簇 5 的“可信 provenance 渲染”问题。
K3 运行:Sol @ max 的实况
K3 的完整运行档案在 runs/K-sol-validator-3-max.md。请求层配置为codex / gpt-5.6-sol / max(TaskRun 状态确认effort=max / full-access),漏斗为:4 chunks → 13 review units → 10 raw → 7 去重后 → 6 通过验证器。各阶段耗时:评审波 35m55s、盲区扫描 2m26s、去重 1m17s、验证 13m50s,全流程墙钟 3095 秒(约 51.6 分钟)。
这里有一个关键细节需要区分:请求的 effort 与模型实际收到的 effort 不一致。K3 在请求层固定为max,但网关在每条gpt-5.6-sol调用上观测到的$ai_effort全部是low(FINAL_REPORT 的“The effort pin never reached Codex”一节)。根因是 Codex 适配器通过collaborationModeForTurn()发送协作模式时只携带{ model },未透传reasoning_effort,Codex 于是回落到内置目录中的模型默认值——Sol 的默认恰好是low。这一点对解读 K3 的结果至关重要:K3 名义上是“max 强度”,实际按 low 强度推理。该缺陷后来由修复 PR #88893(在collaborationModeForTurn().settings中加入reasoning_effort: this._effort)解决,并在本地用 3 轮 Codex smoke(scripts/codex_mts_smoke.py)验证 12 次网关调用全部携带$ai_effort=xhigh(runs/fix-smoke.gateway_events.json)。
成本侧(网关$ai_generation事件,经scripts/kafka_ai_usage.py读取):K3 验证阶段 37 次调用、$1.44,单裁决成本 $0.21。
混淆矩阵逐项解读
KC.score.md 给出的核心矩阵:
| real | not real | |
|---|---|---|
| kept | 3 | 3 |
| dropped | 0 | 1 |
翻译成业务语言:Sol 在 K3 保持了 6/7 的 finding,其中 3 条真实、3 条不真实;唯一丢弃的 1 条恰好是不真实的(正确丢弃)。真正的隐患不在误丢,而在误保:不真实 finding 的丢弃率只有 25%,意味着验证器发布的每两条 finding 中就有一条是假的——而这一切发生在“每个真实 finding 都保住了”的完美召回(100%)背后。
再看每个 finding 的细粒度裁决(sev为真值严重度,prio为评审器自报优先级):
KC1 drop not sev=- prio=must_fix— Validate the gate flag as a JSON booleanKC2 keep not sev=- prio=must_fix— Post-filtering an unscoped task-run lookup can hide the correct runKC3 keep not sev=- prio=should_fix— A broker failure permanently drops the initial reviewKC4 keep not sev=- prio=should_fix— Broker failure can permanently lose the initial reviewKC5 keep REAL sev=consider prio=should_fix— Do not claim that every self-driving PR is a draftKC6 keep REAL sev=must_fix prio=must_fix— The initial review task trusts stale and unverified provenanceKC7 keep REAL sev=should_fix prio=must_fix— Stamphog ignores enabled settings from secondary reviewers
七条发现的真伪与验证器论证
KC.json 保留了每条 finding 的完整正文、建议与验证器论证(validator argumentation),是理解评分卡的关键一手资料。以下路径均为该 finding 记录中引用的冻结工作树位置。
真实被保持(3 条):
- KC6(
must_fix,簇 2,真实):初始审查任务信任队列消息中未经核验的team_id/acting_user_id/signal_report_id/task_run_id/pr_url。验证器论证指出output.pr_url是用户可写的(见products/tasks/backend/temporal/code_workstreams/activities/load_pr_urls.py),而 worker 只解析 URL 仓库与团队配置(products/stamphog/backend/tasks/tasks.py:1130-1153),不校验作者与 head 仓库——与 webhook 路径执行的 bot、repo-native head、任务关联等检查形成对照。真实性与严重度均确认(复用 KA10 裁决),这也是本 PR 已知簇 2(receiver-leg provenance hole)的又一次复现。 - KC7(
should_fix,簇 57,真实):Stamphog 只检查单一“canonical”审查人的开关,忽略已开启功能的次级审查人(products/review_hog/backend/receivers.py:111-127,151-155)。注意prio=must_fix与真值sev=should_fix的错位——评审器自报优先级偏高,这正是 FINAL_REPORT.md 强调“验证器的优先级纠偏在高强度下更重要”的证据。 - KC5(
consider,簇 35,真实):信任提示词无条件声称 PR 是 draft(tools/pr-approval-agent/reviewer.py:696-699),而synchronize事件可在 PR ready 后再次触发自驱动审查,向模型注入虚假的受信上下文。真值严重度为consider(复用 KA7/KB2 同 claim 裁决)。
不真实被保持(3 条)——这是评分卡最值得警惕的部分:
- KC2(簇 39,不真实):
find_task_run未按团队范围查询,facade 事后过滤可能隐藏正确 run。验证器论证在products/tasks/backend/webhooks.py:41-56,68-75与facade/api.py:504-509上复现了查询路径,但真值判定为不真实(复用 KA5 裁决):该查找已按仓库范围限定,且“其他团队 → None”契约有测试覆盖。 - KC3 / KC4(簇 58,均不真实):broker 故障永久丢失初始审查。两条是同一 claim 在接收器端(
products/review_hog/backend/receivers.py:225-234)与 facade 发布点(products/stamphog/backend/facade/api.py:151-157)的两个表述。真值判定不真实(复用 KA13/KB4 裁决):它复制的正是既有 webhook 路径的刻意设计(fire-and-forget + 后续 re-fire 兜底),属于“防御性加固”类 claim,而验证器技能明确要求丢弃此类项。 - 三者的共同特征:验证器读了验证标准 skill(MCP 自 #88697 修复后可用),仍保住了技能明示应丢弃的“防御性加固”类发现。
不真实被丢弃(1 条):
- KC1(簇 3,不真实):
bool()对 JSON 字符串"false"的强转使安全豁免生效。验证器论证完整追踪了 flag 从activities.py:451经logic/reviewer.py:101,131到review_local.py:321的生产调用链,证明字符串/数字/对象值无法通过生产路径到达该行,精确类型校验只防御“损坏的可信调用方”,不满足验证门槛。这是 K3 唯一一次正确的丢弃,也是 7 月实验中被七次反驳的簇 3 的又一次正确排除。
跨运行对比:K3 与 K2 的一致性
将 KC.score.md 与 KB.score.md(K2,xhigh)对照,可以得出本实验最重要的结论:
| 指标 | K2(xhigh) | K3(max) |
|---|---|---|
| 判定 finding 数 | 10 | 7 |
| kept-are-real(precision) | 4/8 = 50% | 3/6 = 50% |
| real-are-kept(recall) | 4/4 = 100% | 3/3 = 100% |
| not-real-dropped | 2/6 = 33% | 1/4 = 25% |
两次运行保持的真实 finding 完全重合(簇 2 的 receiver-leg provenance 漏洞、簇 57 的次级审查人开关、簇 35 的 draft 文案),而保持的错误 finding 也是同一批家族:簇 39(未限定范围的find_task_run)、簇 58(broker 重试加固,每轮报两条)、簇 31(队列时刻的 toggle 信任,K2 的 KB10)。这证明 Sol 的宽松门槛是稳定特性而非运行噪声。盲评(argumentation_judge_K3_vs_K2.json)显示 K3 与 K2 论证中位长度相同(101 词),K2 在 6 对 paired findings 中 5 对论证更优——没有证据表明max带来了更多推理,这与前述 effort 未真正到达模型的发现相互印证。
从评分卡到工程决策
把视角从单张评分卡拉高到整个实验(详见 FINAL_REPORT.md),K3 的结果是系列证据链的一环:
- Sol 不是称职的验证器:即便在修复 effort 后的真实
xhigh运行(M1/M2)中,Sol 依然保持 18/19 与 18/20 的 finding,不真实丢弃率仅 0/7 与 1/7,且运行内部自相矛盾(同一条 toggle claim 一个站点保持、另一个站点丢弃)。K3 的“50% 精度、25% 不真实丢弃率”与之一致。 - Opus 5 是当前验证器答案:同 PR 上保持 11–12/22–23,kept-real 67–82%,不真实丢弃 64–82%,单裁决 $1.06——比 Sol 贵约 30% 但能真正过滤。Sonnet 5 在
xhigh表现与 Sol 相似(保持 16/22 与 22/22,kept-real 50%),更便宜的 Claude 档位同样不是出路。 - “保持更多”不等于“更好”:验证器的核心价值在于不真实丢弃率;K3 的 100% 召回靠的是几乎全盘接受。评估 AI 审查流水线时,这张混淆矩阵比任何单点指标都更能暴露验证器的真实行为。
复现建议:若要在本仓库复现评分过程,可依次执行python scripts/build_truth.py KC(从 match 与 known_clusters 起草真值)、python scripts/score_validator.py findings/KC.json findings/KC.truth.json(生成评分卡),并对照 verify/ 下的逐条验证记录交叉核验。注意known_clusters.json是 7 月评审注册表,实验中的新发现(如 xhigh 运行发现的 LA15/MB17 webhook-facade 授权漏洞)尚未并入其中。
【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考