ReviewHog 评估运行深度解析:Sol 中等推理强度评审 + Opus 5 校验的漏斗与裁决实录
【免费下载链接】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
导读
本文基于 PostHog 开源仓库中 ReviewHog 自动 PR 评审产品在 2026-08-26 的一次真实评估运行报告(P-sol-medium-opus5-2),完整还原其运行漏斗、分阶段耗时、按视角拆分的 review unit 明细,以及 15 条 post-dedup 发现的校验裁决(VALID/dismissed)与裁决依据。读者将掌握:如何解读 ReviewHog 评估报告中的 funnel 与 stage timing 表格、四种评审视角(三种 perspective + blind-spot sweep)的协作方式、验证器(validator)如何以文件与行号证据判定每条发现的真伪,以及 Opus 5 校验器在本轮"零误报"(7/7 kept-real、8/8 not-real dropped)表现背后的实现依据。
一、运行背景:这是一次什么评估
P-sol-medium-opus5-2是products/review_hog/eval/experiments/2026-08-validator-model-sol/实验下的第二次 P 组运行(PLAN.md)。该实验回答的核心问题是:gpt-5.6-sol(Codex)能否在更低成本与耗时下替代 Claude Opus 作为 ReviewHog 的校验模型。
本轮运行的关键配置:
| 维度 | 值 |
|---|---|
| 运行标识 | P-sol-medium-opus5-2,report id01a03e30-9ae5-77ba-8869-6125d287bf17 |
| 评审模型(reviewer) | Codex /gpt-5.6-sol/ 推理强度medium |
| 校验模型(validator) | Claude /claude-opus-5/xhigh(生产固定组合) |
| 被评审对象 | 冻结 PR #75215 @ heada7fb363b,4 个固定 chunk,零评论清洁环境 |
| 单 chunk 门限 / chunk 目标 / 软上限新增行 | 400 / 300 / 600 |
| 墙钟总时长 | 2582 s(约 43 分钟),statusidle(run_count 1) |
该实验的对照组与姊妹组说明(来自 FINAL_REPORT.md):评审模型固定为 Sol,校验模型分为 Opus 5(L/P 组)、Sol(M 组)、Sonnet 5(N 组)三档对照;本轮 P2 属于"Sol 评审器降到medium、Opus 5 校验"的下午追加实验,用于验证中等推理强度下的成本-质量折中。
运行前置:实验开始前团队修复了两个关键环境问题——Codex 沙箱多轮会话可用的冒烟验证(
scripts/codex_mts_smoke.py),以及 2026-08-13 起REVIEW_MCP_SCOPES缺user:read导致沙箱无法skill-get拉取技能(#88697 修复)。评估运行带有 4 个实验性 hack(注释 mock、chunk 固定、VALIDATION_*常量覆盖、并发数 4),均在实验结束后回滚。
二、运行漏斗:raw → dedup → validator 的层层收窄
本轮运行的漏斗数据是评估报告的骨架:
| 阶段 | 数量 |
|---|---|
| chunks | 4 |
| review units | 12 |
| raw issues(原始发现) | 18 |
| after dedup(去重后) | 15 |
| passed validator(通过校验) | 7 |
其中review units = 每一个 (perspective 或 blind-spot) × chunk 的沙箱评审,报告明确指出它是"模型持有成本不变"的成本代理(model-held-constant cost proxy):每个 unit 都是一次独立的沙箱 agent 评审调用。
漏斗背后的实现:ReviewHog 单轮流水线
这条漏斗对应 ARCHITECTURE.md 中ReviewPRWorkflow(backend/temporal/workflow.py)编排的 10 步流水线:fetch PR → 生成 schema → 分块 → 并行视角评审 → 盲点扫描 → 合并+作用域清理 → 去重 → 校验 → 构建报告 → 发布。
去重(dedup)为何能把 18 条砍到 15 条:按 ARCHITECTURE.md 第 7 步,dedup 先跑一个确定性位置预过滤(_select_dedup_candidates)——只有与另一条 issue 或任何既有 inline comment 共享文件且行区间重叠的 issue 才可能重复,孤立 issue 不经过 LLM 直接存活;碰撞候选进入单次 one-shot 去重调用(IssueDeduplication,见 models/issue_deduplicator.py)。
三、阶段耗时:校验是时间大头
报告给出的各阶段墙钟耗时:
| 阶段 | 时长 |
|---|---|
| fetch + snapshot | 0s |
| chunking | 0s |
| perspective selection | 16s |
| review wave (perspectives) | 10m 32s |
| blind-spot sweep | 3m 30s |
| dedup (incl. combine/clean) | 47s |
| validation | 26m 52s |
几个值得注意的点:
- fetch/chunking 为 0s是因为 chunk 固定(pinned chunks)与注释 mock 两个实验 hack,使这两个阶段退化为无操作。
- Review stage total(selection → 最后一个 finder unit,含 wave + blind-spot)= 14m 03s,报告明确这是"评审模型速度对比数字"(the reviewer-model speed comparison number)——对比 PLAN.md 中 P1 的 12m32s,
medium推理强度下评审阶段稳定在 12–14 分钟。 - 校验阶段 26m52s 是总时长 43 分钟的大头。这符合架构设计:校验器(validator)为每个 chunk 开一个 warm 多轮会话(每轮一个 verdict),见
validate_chunk_activity与load_run_validations的 resume 机制(backend/temporal/activities.py)。 - 耗时数据派生自 artefact 的
created_at(完成时持久化),报告特别注明:只有对新鲜的、非恢复(non-resumed)的运行才有意义。
成本侧写(来自本轮 gateway 事件)
runs/P-sol-medium-opus5-2.gateway_usage.md记录了本轮 286 条$ai_generation事件的实际开销构成:
| 阶段族 | 模型 | 调用数 | gateway $ | effort |
|---|---|---|---|---|
| review | gpt-5.6-sol | 134 | $8.46 | medium |
| blind-spot | gpt-5.6-sol | 37 | $2.31 | medium |
| validation | claude-opus-5 | 111 | $12.84 | xhigh |
| validation(子 agent) | claude-opus-4-8 | 2 | $1.06 | xhigh |
| dedup / perspective_selection | claude-sonnet-5 | 各 1 | $0.09 | xhigh |
报告正文中的"cache-aware spend: no$ai_generationevents in the window"指本地遥测不可用(PLAN.md 记录本地 ingestion 被 personhog 阻塞),实际成本从 Kafka 主题events_plugin_ingestion_ai直接读取;而dump_result.py(eval/scripts/dump_result.py)正是这套实验报告的标准生成器,负责从ReviewReport与 artefacts 渲染上述所有表格。
四、Per-review-unit 明细:四个视角的分工
本轮 12 个 review unit 的构成(pass 序号 = 视角在PERSPECTIVES注册表中的 1-based 位置,1000 为盲点扫描的保留序号):
| pass | chunk | perspective | raw issues |
|---|---|---|---|
| 1 | 1–3 | review-hog-perspective-contracts-security | 1 / 2 / 1 |
| 2 | 1–3 | review-hog-perspective-logic-correctness | 2 / 3 / 2 |
| 3 | 1–2 | review-hog-perspective-performance-reliability | 2 / 2 |
| 1000 | 1–4 | review-hog-blind-spots-general | 1 / 1 / 0 / 1 |
视角技能是 DB 同步的 LLMA skill,通过 MCP 拉取
三个 perspective + 一个 blind-spot 都以独立 skill 形式存在于 products/review_hog/skills/ 下。关键设计(ARCHITECTURE.md "Prompts" 节):视角焦点不再拼进 prompt,而是通过skill-get(review-hog-perspective-…, version=N)按需拉取——sandbox agent 在 MCP 会话中取回视角技能并应用其关注点。以 contracts-security 为例(SKILL.md),其关注面包括:
- API 契约与破坏性变更(请求/响应格式、字段增删、类型变更、版本兼容、GraphQL/REST 契约)
- 安全漏洞(SQL 注入、XSS、LLM 代码的 prompt-injection、认证/授权、敏感数据暴露)
- 输入验证与边界(入口点验证、sanitization、类型安全、范围与限额、溢出)
- Schema 与接口对齐(DB schema 与模型、前后端类型一致性、迁移兼容)
技能文档还给出具体调查命令(rg "@action\(|@api_view\("找 DRF 端点、rg "validate|sanitize"检查输入验证等),并明确"只报告安全与契约类问题",逻辑正确性与性能问题留给其他视角——这正是多视角并行、重叠留给去重处理的设计前提(SKILL.md 顶部说明)。
Chunk 构成:22 个文件跨 4 个 chunk
- chunk 1(8 文件):review_hog 后端模型、迁移
0019_reviewusersettings_stamphog_review_inbox_prs.py、settings API、receivers 与前端CodeReviewScene.tsx、生成类型 - chunk 2(8 文件):stamphog 的 facade API、inbox_hooks、tasks、temporal activities、reviewer 逻辑,以及 tasks 产品 facade 与
tach.toml - chunk 3(4 文件):
pr-approval-agent包(在仓库中位于 products/stamphog/packages/pr-approval-agent/)的review_pr.py、review_local.py、reviewer.py、version.py - chunk 4(2 文件):stamphog 的
AGENTS.md与README.md
五、Post-dedup 发现的校验裁决全景
本轮 15 条 post-dedup 发现中,Opus 5 校验器保留了7 条(全部真实)、驳回了8 条(全部不真实)——即 PB.score.md 中的满分三项:kept-are-real 7/7、real-are-kept 7/7、not-real-dropped 8/8。
裁决对照(score 文件按 PB 序号):PB1/PB3/PB4/PB11–PB15 驳回,PB2/PB5–PB10 保留。真实性标注来自 76 个已知问题簇(
known_clusters.json)匹配 + 对混合簇/新声明在冻结 worktree 上的"先反驳后验证"(refutation-first verification),相同声明复用已验证结论(PLAN.md 评分协议)。
按裁决与严重度分组如下:
5.1 ✅ VALID(保留,7 条)
| 严重度(原始→调整) | 主题 | 核心结论 |
|---|---|---|
| should_fix→consider · bug | 可信 prompt 可能报告错误的 draft 状态(reviewer.py:695-700) | 既有实现(reviewer.py_format_self_driving)确实只在self_driving标志为真时渲染固定句子 "It is a draft on purpose",从不读取pr.draft |
| must_fix→should_fix · bug | Opt-out 路径可能遗留迟到的 approval(tasks.py:894-898) | _retract_stale_approvals_on_skip只 dismiss 不 supersede,与_retract_approvals_on_base_retarget(先 supersede 全部非终态 run 再 dismiss)形成不对称 |
| must_fix · security | 文档化的 positive-linkage 不变量未被强制(AGENTS.md:84-99) | 初始评审腿(process_inbox_pr_review)只校验 URL 形状、repo 配置、state=="open"与非空 head SHA,从不调用find_signal_implementation_run |
| must_fix · security | 授予 inbox review carve-out 前未校验 PR 来源(receivers.py:126-137,225-231) | receiver 把output.pr_url当作出自 self-driving 任务的证明,而该字段是用户可写的 |
| must_fix · security | 不可信 task output 激活特权评审路径(tasks.py:1110-1112,1157-1182,1222-1229) | set_output仅要求task:writescope 且for_control=True;task_control_q把SIGNAL_REPORT任务的操控权授予任意团队成员 |
| must_fix · security | carve-out 信任未验证的上下文值(review_local.py:321-324) | 真值性(truthiness)半条不成立(服务端以真实 bool 写入),但验证半条成立:初始腿缺少 webhook 腿的_is_bot_authored、head repo 与事件 repo 相等、find_signal_implementation_run三项检查 |
| must_fix · bug | Stamphog gate 忽略已选择加入的次要评审者(receivers.py:111-126,151-155) | 分支版先选一个评审者再查 toggle;origin/master同文件已实现_pick_stamphog_reviewer的"任一 assigned reviewer 选择加入即触发"逻辑 |
5.2 ❌ dismissed(驳回,8 条)
| 严重度 | 主题 | 驳回核心理由 |
|---|---|---|
| should_fix · security | PR URL 解析器接受非 GitHub 与歧义 URL | 解析出的 repository 仅作为StamphogRepoConfig.for_team(team_id)的repository__iexact查找键;GitHub 调用使用 DB 行中的 repository,URL host 被丢弃,无法跨租户读取 |
| should_fix · best_practice | Broker 故障永久丢失初始评审 | 握手并非一次性:receiver 在每次output保存时重新触发(模块 docstring 明确"故意重复触发"),head-keyed 去重使重复安全幂等,恰成天然重试;后续 push 的 webhook carve-out 是第二条独立恢复路径 |
| should_fix · best_practice | Workflow-start 重试耗尽后 run 永久 QUEUED | 该条件产品级普遍存在(webhook 腿同样max_retries=3),新腿反而通过 head-keyed 去重补上了恢复能力;建议的调度恢复 worker 被判定为过度工程 |
| should_fix · code_quality | 先选一个候选再检查 run 资格 | 结果 fail-closed 而非租户隔离漏洞;"无序 first()" 断言不成立——DjangoQuerySet.first()无排序时按 pk 排序,是确定性的 |
| should_fix · bug | 副作用 gate 可能读到过期 TaskRun | 前提不成立:TaskRun不在任何 replica-backed 数据库上(db_routing.yaml仅路由 4 个产品 DB),ReplicaRouter默认返回"default",建议的.using(db_for_write)是无操作 |
| should_fix · best_practice | Broker 故障永久丢弃初始评审(receiver 版本) | 与模块既有契约一致(_start_review同样 fire-and-forget),且origin/master合并版逐字节保留了该形态 |
| should_fix · best_practice | 延迟导入可能逃出保存路径 | transaction.on_commit在无原子块时立即执行,且 stamphog 已在模块顶层硬依赖,导入失败属不可达条件;master 用robust=True通用修复 |
| must_fix · best_practice | 排队中的评审忽略稍后的 opt-out | 这是文档化的有意设计(AGENTS.md 明确 "Dismissal is never preference-gated");且建议的"run 创建前复查"只覆盖排队到取用的几秒窗口,评审耗时数分钟的大头窗口根本不受影响 |
六、裁决方法学:validator 如何"先反驳后验证"
理解这 15 条裁决,需要明白 Opus 5 校验器的工作方式(实现依据见 ARCHITECTURE.md 第 8 步与ValidateIssuesWorkflow):
- warm 多轮会话,每 chunk 一个,每轮一个 verdict:
validate_chunk_activity打开一个沙箱,把该 chunk 的 issue 作为顺序 turn 逐条裁决,load_run_validations把已裁决/待裁决拆开以支持恢复。 - 标准是拉取的,不是烘焙的:prompt 指示 agent
skill-get(review-hog-validation-criteria, version=N)拉取团队拥有的校验标准(skills/review-hog-validation-criteria/SKILL.md 的默认 bar:保留真实的用户影响正确性/安全/数据丢失/契约/性能问题,丢弃过度工程、臆测、防御性偏执、永不会发生的边界与风格问题)。 - argumentation 是"验证增量",不是复述:
IssueValidation.argumentation记录查了什么、在哪个文件哪一行发现了什么、确认的影响与优先级理由——本轮每条 dismissed 裁决都带着具体的文件:行号证据(如products/stamphog/backend/tasks/tasks.py:1130的唯一调用点、products/tasks/backend/webhooks.py:41的过滤条件等)。 - 校验器可覆盖优先级:
IssueValidation.adjusted_priority允许 validator-wins,如第一条 fromshould_fix降到consider、opt-out 竞态从must_fix降到should_fix(ARCHITECTURE.md "Data models" 节)。
本轮裁决的源码证据示例
- draft 状态误报(VALID):
_format_self_driving(reviewer.py)只以cl.get("self_driving")为键,固定渲染 "It is a draft on purpose…",pr.draft在两个运行时都存在(github.py、review_local.py),所以修复成本低——这正是 validator 建议"仅在pr.draft为真时包含该句"的直接依据。 - URL 解析宽松(dismissed):
_parse_pr_url的_PR_URL_RE是无锚点搜索(tasks.py),但下游process_inbox_pr_review现在会先做pr_repository != repository的比对(tasks.py),并用 GitHub 侧的_is_self_driving_pr(bot 身份 + repo-native head)与find_signal_implementation_run(head ref 对 stamped branch)双重绑定。 - 特权评审路径(VALID):
process_inbox_pr_review在 tasks.py 的实参签名只携带team_id/pr_url/repository/acting_user_id/signal_report_id/task_run_id,靠 URL 解析出的 repository 查配置;而 webhook 腿_inbox_rereview_carve_out则执行_is_bot_authored、head repo 相等、find_signal_implementation_run匹配、团队复核与 toggle 复核(tasks.py 附近)。 - stale-approval 不变量:这是 stamphog 的首要不变量——AGENTS.md 开头即声明 "No stamphog approval may remain standing over commits it didn't review",并规定
dismiss_stale_approvals在每次 skip/supersede/abandon 后重跑。多条 dismissed 裁决正是据此判定"无确认后果"。
七、实验结论定位:为什么本轮 Opus 5 满分但整体建议不变
本轮 P2 与姊妹组 P1 一起构成"Sol reviewer @ medium + Opus 5 validator"档位(FINAL_REPORT.md "Sol at medium as reviewer" 节):
- 评审侧:P1/P2 各 14/15 条 dedup 发现、7 条真实(real rate 50%/47%),是 low 档(3–4 条真实)的两倍、xhigh 档(11–13 条)的一半;评审+盲点成本约 $10.5/轮,评审阶段 12.5–14 分钟。但两轮都没有发现注册表中不存在的新真实问题(PB5 = LB20 的重复声明),因此
medium是 xhigh 的成本替补,不是发现力替代。 - 校验侧:Opus 5 在本轮 precision 满分(7/7 kept real、8/8 not-real dropped),但这也部分源于输入面——14–15 条发现中 not-real 的一半是已知的三大家族(broker/重试硬化诉求 cluster 58、无作用域
find_task_run查找 cluster 39、排队时 toggle 信任 cluster 31)。 - 横评结论:真实 xhigh 下的四轮(L1/L2/M1/M2)显示 Sol 校验器保留 18/19–20 条、几乎不丢 not-real(0/7、1/7),每 verdict 成本 $0.72–0.80 仅比 Opus 的 $1.06 便宜约 30%;Sonnet 5 是 Sol 的低价版。最终建议仍是:保留 Opus 作为校验器,同时把 effort 修复(#88893)落地后在生产以 xhigh 运行 Sol 评审器。
八、如何复现与继续深入
- 读取更多运行报告:姊妹运行 P-sol-medium-opus5-1.md、对照组的 M-sol-validator-1.md 与 L-opus5-validator-1.md;
- 评分数据:本轮 PB.truth.json(每条发现的真实性与簇归属)、PB.score.md(三维计分)与 gateway 成本 gateway_usage.md;
- 实验设计:PLAN.md 记录了运行配方(
run_review --pr-url … --team-id 1 --user-id 1)与全部实验 hack; - 产物生成器:eval/scripts/dump_result.py 展示了实验报告的标准生成方式——从
ReviewReport+ReviewReportArtefact(chunk_set、perspective_result、issue_finding、validation_verdict等 artefact 类型)渲染出本报告的全部表格; - 架构总览:ARCHITECTURE.md 与 CONTEXT.md 定义了 pipeline、视角/盲点/校验 skill、report 状态机与术语表;stamphog 侧的不变量记录在 AGENTS.md。
说明:本报告描述的是 2026-08-26 冻结时刻的快照;仓库为只读,文中所有路径均为当前仓库相对路径,读者可据此直接定位对应源码与实验数据继续核查。
【免费下载链接】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),仅供参考