ocra

工作原理

从 diff 到带行号的审查结果,整条审查流水线。

ocra 结合了两种经过验证的设计:按领域分工的专项审查员加一个负责协调的裁决者,以及把所有不能出错的步骤交给确定性的工程代码。

Ingest → Select → Triage → Bundle → Matrix → Execute → Anchor → Filter → Verify → Judge → Report
阶段做什么
Ingest通过代码托管平台适配器读取改动和仓库规范。
Select逐个文件决定:审查,或者排除并记录原因(二进制、密钥、生成代码、过大……)。
Triage根据改动规模和 auth/、PasswordHasher.cs、CI workflow 这类敏感路径,给出风险档位(trivial、lite、full)。
Bundle把相关文件分到一组。改动少时合成一组;改动多时由 light 模型按文件编号分组。没有这一步的分组时,20 个文件以内每个文件一个任务,更多时按目录分组。
Matrix根据风险档位和每个审查员的适用范围,决定哪个审查员审查哪个分组(例如只看代码的审查员不会收到文档)。被跳过的组合会写进报告。
Execute每个计划好的(分组,审查员)组合作为一个隔离的 agent 任务运行,只有只读工具。
Anchor把每条问题引用的代码解析成准确的行号。
Filter去掉仓库记忆里已接受的问题和审查者驳回的问题,并与同一 PR 的上一次评审对比;这一步在任何模型调用之前完成,不为这些问题花钱。
Verify由 standard 档位的模型,对照每个文件的 diff 和问题附近的代码逐条核查。只有当代码能证明某条问题是错的,它才会被丢弃;拿不准的保留,核查失败也保留。被丢弃的问题和原因会写进报告。
Judge一次 top 档位的调用看到所有问题:合并不同审查员对同一根因的报告,丢弃臆测和吹毛求疵,校准严重程度,并写一段简短总结。每一项调整都会在报告里附上原因。

结论(verdict)

结论由一套固定规则根据最终的问题列表决定,而不是由模型决定,因此相同的问题总会得到相同的结论:

问题结论
没有问题approved
只有 suggestion,或少于三个 warningapproved_with_comments
三个及以上 warning,或未经核查确认的 criticalminor_issues
任何经核查确认的 criticalsignificant_concerns

每条问题都会标明核查(Verify)的结果:已确认、不确定,或未核查(核查被跳过、调用失败或预算不足)。未经确认的 critical 照常显示为 critical 并标为未核实,但结论最高只到 minor_issues,一个模型未经核查的判断不能单独拦下改动。如果本该核查、却因调用失败或预算不足没能核查某条 critical,这次运行算作不完整(退出码 3),不会被当成通过;配置了 verify: false 时不算。Judge 既不能丢弃、也不能降级已确认的 critical;这类尝试会被忽略,并记入警告。

如果 Judge 被关闭、没有配置 top 模型或调用失败,问题会不经裁决直接报告,结论规则照样适用。

结论只是参考意见,不是安全门禁。流水线里的每个模型都会读到被审查的改动,改动里埋下的文字可能诱导审查员漏报问题,或说服 Judge 丢掉问题。ocra 用来辅助审查者,不能替代必需的人工审查和安全检查。

模式

默认模式偏重准确率。--ultra 用成本换召回率:

默认--ultra
审查员按风险档位和适用范围所有审查员在所有档位都运行,包括通过 reviewers.<id>.minTier 设置的档位(超出审查员适用范围的文件仍会跳过,enabled: false 仍然生效)
采样每个审查员、每个分组跑一次跑两次,按 fingerprint 合并
计划只针对大分组(5 个文件及以上,或 diff 超过 40,000 字符)每个任务都有。先用一次简短的模型调用列出优先要查的地方;失败时任务照常运行
调用方审查员自己搜索把分组里定义或改动的符号在分组之外的用法提供给审查员
Judge丢掉臆测和吹毛求疵保留它们并标为低置信度,不计入结论
成本基准约两倍或更多,外加每个任务一次计划调用

两种模式下的核查(Verify)完全一样。

审查员与工具

审查员是一个带有专门提示词的 agent,有自己的规则,以及告诉 Matrix 在哪里值得运行的适用范围:

审查员关注运行档位跳过
correctness逻辑错误、契约被破坏、错误处理所有档位无
security能被不可信输入触达、可被利用的问题:注入、授权、密钥、加密、不安全的解析、CIlite 和 full文档、测试
performance重要路径上可度量的性能退化:复杂度、N+1、阻塞操作、内存lite 和 full文档、测试、配置数据、CI workflow
docs被这次改动弄错的文档:被删除或改名的参数、配置项、接口或默认值,而 README、文档或帮助文字还在描述旧的(用 light 模型)lite 和 full测试
agents-mdAGENTS.md 里被这次改动弄错的内容:命令、目录结构、模块职责、需要的工具和环境变量(用 light 模型;仅当仓库有 AGENTS.md 时运行)lite 和 full测试

每个审查员只看自己的领域,并且明确知道哪些不该报。所有审查员都只能读:read_file、read_diff 和 code_search 返回的都是被审查的那个版本(在区间或单个 commit 模式下是对应的 commit,而不是你的工作区),问题通过 report_finding 提交。这些工具的返回有上限(每行 2,000 字符、每次 50,000 字符、每个文件最多读 2 MB),压缩过的打包文件不会塞满模型的上下文。它不能修改文件、执行命令或访问网络。

行号定位

模型给出的行号并不可靠,所以让模型引用代码,由 ocra 来解析:

  1. 在该文件改动过的代码段里做规范化匹配;
  2. 在整个文件里匹配;
  3. 在其他改动文件里匹配(模型写错了文件),只接受整行引用,而且只能在一处找到;
  4. 把问题和该文件的 diff 交给 light 模型,让它指出对应的代码行,再像普通引用一样去匹配(每条没匹配上的问题一次小调用);
  5. 以上都不行,问题就挂在它自己的文件上,作为文件级问题。

如果问题最终落到审查员分组之外的文件上,会被丢弃并记一条警告:那个审查员并没有看到这个文件。

优先按整行匹配。引用只是某一行的一部分时,只有长度不少于 12 个字符、并且只有一行包含它,才算匹配;否则像 err 这样的片段会落到第一个碰巧包含它的行上。如果一段引用同样适合多个位置(比如三行一样的 return err;),就不挑具体的行:问题显示在文件级别,并计入 anchoring.ambiguous。JSON 报告(--format json、会话的 report.json)会给出整次运行的 anchoring:每种方式(hunk、file、cross_file、relocated、file_level)锚定了多少问题、其中有歧义的数量,以及重新定位调用了几次。

稳定性

  • 单个任务和整次运行都有超时,即使模型不再响应也照样生效。某个任务的 agent 如果五分钟没有任何进展(没有新的步骤、文字或工具调用),会提前停止,交给模型链里的下一个模型。
  • 某个任务失败不会导致整次运行失败,它负责的文件会被标记为 failed。
  • 每个层级都有模型降级链,每个模型都有熔断器(反复失败后打开,冷却后放行一次试探)。
  • 遇到限流会等待:供应商要求短时间后重试(最多 90 秒)时,所有任务都会暂停使用这个模型,等完再重试。如果限流标明是按天计算、等待时间更长或没有给出,或者连续第四次被限流,这个模型在本次运行里就不再使用,ocra 也就不再发送注定被拒的请求。
  • 每个审查 agent 最多执行 30 步,因为每一步都会把整个对话重新发送一遍;大多数任务在 15 步左右就结束。
  • 审查 agent 如果没做完就停下(没有发出完成信号、没有给出结论、步数也没用完),会在同一个会话里被提示一次,把还没审的文件审完;进度行会写"resumed after stopping early"。
在 GitHub 上编辑

本页目录