Caveman cavecrew-reviewer 实战解析:低 Token 代码审查子代理的严重度分级、输出契约与模型覆盖机制
cavecrew-reviewer 是 Caveman 项目中 cavecrew 三件套(investigator / builder / reviewer)里负责代码审查的子代理规范文件,其核心目标是用"每条发现一行、带严重度标签、零客套话"的压缩格式,让审查结果回到主线程时占用的上下文 Token 远少于常规 Code Reviewer 的散文式输出。读完本文,你将完整掌握该子代理的 frontmatter 配置、四级严重度体系、严格输出契约、工具权限边界与自动清晰(Auto-clarity)规则,并能理解 CAVECREW_REVIEWER_MODEL 模型覆盖机制的源码实现方式。
一、规范文件结构与 frontmatter 逐项拆解
cavecrew-reviewer 的完整定义位于 agents/cavecrew-reviewer.md,作为 Claude Code 子代理文件被插件分发,其安装副本与源码同路径同内容(见 plugins/caveman/agents/cavecrew-reviewer.md)。文件由 YAML frontmatter 与正文两部分组成,frontmatter 每一项都有明确的运行时含义:
---
name: cavecrew-reviewer
description: >
Diff/branch/file reviewer. One line per finding, severity-tagged, no praise,
no scope creep. Output format `path:line: <emoji> <severity>: <problem>. <fix>.`
Use for "review this PR", "review my diff", "audit this file". Skips
formatting nits unless they change meaning.
tools: [Read, Grep, Bash]
model: haiku
---
name:子代理注册名。主线程通过名字派发任务,如"用 cavecrew-reviewer 审查这个 PR"。description:这是写给主线程(以及用户)的"路由说明书",承担触发判断职责。它明确了三组触发短语——"review this PR"、"review my diff"、"audit this file"——并预先声明了输出格式(path:line: <emoji> <severity>: <problem>. <fix>.)与两条行为红线(不夸奖、不扩大范围)。skills/cavecrew/SKILL.md 中的决策矩阵也与之呼应:审查 diff/分支/文件的 bug 用cavecrew-reviewer;想要带理由、带替代方案的深度评审则用原生Code Reviewer;只想要一两句话的直接留在主线程。tools: [Read, Grep, Bash]:权限白名单。对比同系列的 agents/cavecrew-builder.md(有Edit/Write但无Bash)和 agents/cavecrew-investigator.md(无Edit/Write,另有Glob),reviewer 的权限设计是"可读、可查、可跑 git 只读命令、但无文件写入工具",从工具层面保证了审查过程绝不改动代码。model: haiku:默认绑定轻量模型。代码审查是高频、结构化任务,skills/cavecrew/README.md 说明这是刻意选择:reviewer 与 investigator 默认钉住haiku,builder 则不写model:行(跟随会话默认模型)。这一行可以被环境变量覆盖,见后文第四节。
二、正文基调:Caveman-ultra 审查纪律
正文第一行即立下总基调:
Caveman-ultra. Findings only. No "looks good", no "I'd suggest", no preamble.
这条规则针对的是 LLM 代码审查中最典型的浪费源:寒暄、总体评价、"可以考虑优化"之类的模糊建议。规范强制 reviewer 只输出**发现(findings)**本身,每条发现自包含"问题 + 修复动作"。这也是它与原生 Code Reviewer 的根本差异:后者返回散文与架构意见,reviewer 返回的是可直接执行、可被 grep 定位的结论。
三、四级严重度体系:Emoji 即协议
规范定义了四级严重度表格,Emoji 不是装饰而是机器可解析的协议标记:
| Emoji | 等级 | 适用范围 |
|---|---|---|
| 🔴 | bug | 错误输出、崩溃、安全漏洞、数据丢失 |
| 🟡 | risk | 边界情况、竞态、泄漏、性能悬崖、缺失防护 |
| 🔵 | nit | 风格、命名、微性能——仅当用户明确要求彻底(thorough)审查时才输出 |
| ❓ | question | 需要作者意图才能判断的问题 |
两个值得注意的设计点:
- 🔵 nit 默认静默。常规审查只报 bug 与 risk;只有用户显式要求"thorough"时才追加 nit。这一条直接压低了审查输出的噪声 Token,同时保留了"用户可升级审查深度"的旋钮。
- ❓ 是"不猜测"的出口。当判断需要作者意图时(例如"为什么这里重复
.trim()?"),reviewer 不强行下结论,而是输出一行疑问,把判断权交还作者。这与第四节边界条款中"Need more context → 追加引用,不要猜"一脉相承。
四、输出契约:一行一发现 + 汇总行
规范给出了一份可直接照抄的输出样例:
path/to/file.ts:42: 🔴 bug: token expiry uses `<` not `<=`. Off-by-one allows expired tokens 1 tick.
path/to/file.ts:118: 🟡 risk: pool not closed on error path. Add `try/finally`.
src/utils.ts:7: ❓ question: why duplicate `.trim()` here?
totals: 1🔴 1🟡 1❓
契约规则逐条解析:
- 行格式
path:line: <emoji> <severity>: <problem>. <fix>.:文件路径在前、行号紧随,问题句和修复句各占一句。这种"路径优先"布局让主线程可以按 skills/cavecrew/SKILL.md 所述用path:\d+直接grep解析全部发现——输出对机器是友好的结构化数据,而非对人类友好的散文。 - 排序规则:跨文件按文件顺序(file order),同一文件内按行号升序。确定性排序意味着同一 diff 两次审查的产出可以逐行 diff 对比,便于回归验证。
- 零发现语义:无任何问题时输出固定短语
No issues.——空结果也有显式契约,主线程不需要猜测"空输出=没跑还是没问题"。 - 汇总行
totals: N🔴 N🟡 N🔵 N❓:把分级计数压成一行,主线程据此即可决策"有无 🔴 需要阻断合并",而无需回读全部条目。
五、边界条款:把"范围蔓延"写进规范
- Review only what's in front of you. No "while we're here".
- No big-refactor proposals.
- Need more context → append `(see L<n> in <file>)`. Don't guess.
- Formatting nits skipped unless they change meaning.
这四条边界条款分别堵住了 LLM 审查的四个典型失守模式:
- "顺手改"倾向(while we're here):只审眼前的 diff/分支/文件,发现与本次变更无关的问题也不顺带提出;
- 重构建议:禁止大重构提案——那是主线程或架构角色的职责,reviewer 只做单点定位;
- 无据推断:上下文不足时不猜,而是追加
(see L<n> in <file>)形式的精确指引,把后续核查动作留给持有上下文的调用方; - 格式噪声:纯格式化 nit 一律跳过,除非它改变了语义(如规范文档自身强调的
path:line布局只服务可解析性)。
六、工具限制:Bash 仅用于 git 只读三件套
规范对 Bash 工具做了进一步收窄:
`Bash` only for `git diff`/`git log -p`/`git show`. No mutating commands.
frontmatter 里虽然声明了 Bash,但正文将其用途限定为三个 git 只读命令:git diff(看变更)、git log -p(带 patch 的历史)、git show(单个提交内容)。任何会修改工作区或仓库状态的命令(git commit、git push、文件写操作)均被禁止。这与 docs/technical/exploration-and-delegation.md 中 cavecrew 的权限总表一致——Reviewer 的授权范围就是"Compact findings / Diff or file review",且整个 cavecrew 系列对宿主工作树是只读审计语义。
七、Auto-clarity:安全发现自动切换英文
Security findings → state risk in plain English first sentence, then caveman fix line.
Auto-clarity 是 cavecrew 全系列继承的规则(skills/cavecrew/SKILL.md 在"Auto-clarity (inherited)"一节有统一定义):当输出生成安全警告时,先输出第一句平实英文说明风险本身,随后再回到压缩格式给出修复行。其设计逻辑是:碎片化、去冠词、去填充词的 caveman 压缩语,用于普通发现可以省 Token,但用于安全语义时歧义代价过高——"token expiry uses < not <="这类表述若再叠加安全后果描述,一旦误读会造成真实的越权/失效风险。因此安全类发现在契约层面被强制"降压缩、保清晰"。
八、在 cavecrew 委派体系中的位置
单看 reviewer 只是一个子代理文件,放进 cavecrew 体系中它承担的是"locate → fix → verify" 最常见链路中的终点验证角色:
cavecrew-investigator(只读)返回站点清单(path:line+ 符号 + 短注);- 主线程挑出 1–2 个站点,把精确路径交给
cavecrew-builder做外科手术式编辑(builder 硬拒 3 文件以上范围); cavecrew-reviewer审计 builder 产出的 diff,返回上述压缩发现清单。
skills/cavecrew/SKILL.md 同时给出了不该用它的负面清单,对落地很有参考价值:
- 不要问 reviewer 要"general feedback"——它只返回发现,没有架构观点;
- 不要期待散文,cavecrew 输出刻意做到"结构化到近乎晦涩",若最终产物要给人直接读,需转述。
该文档还解释了压缩存在的真实动机:子代理的工具结果会逐字注入主上下文,一次返回 2k Token 散文的委派就等于烧掉主线程 2k 预算;同类发现经压缩后可显著缩水。因此官方措辞很克制——"效果取决于任务、代理与委派次数",不宣称普适压缩率。
九、源码纵深:CAVECREW_REVIEWER_MODEL 模型覆盖是怎么落地的
reviewer 的 model: haiku 并非不可变。Caveman 的 SessionStart 钩子在启动早期调用 src/hooks/cavecrew-model-overrides.js,从环境变量读取覆盖值并原地修补已安装代理文件的 frontmatter。机制拆解如下:
1. 环境变量到文件的路由表(该文件 L23–L27 的 AGENT_ENV_MAP):
| 环境变量 | 修补目标 |
|---|---|
CAVECREW_REVIEWER_MODEL |
agents/cavecrew-reviewer.md |
CAVECREW_BUILDER_MODEL |
agents/cavecrew-builder.md |
CAVECREW_INVESTIGATOR_MODEL |
agents/cavecrew-investigator.md |
2. 修补逻辑(patchFrontmatterModel,L49–L85):
- 值含换行或控制字符(
[\x00-\x1f\x7f])→ 直接拒绝,防止 frontmatter 注入; - 已有
model:行 → 正则^model:[ \t]*.*$原位替换; - 无
model:行(如 builder)→ 优先插在tools:行之后,否则插到 frontmatter 闭合---之前; - 保留原换行风格(检测 CRLF/LF),避免在 Windows 上产生混合换行;
- 只动
model:一行,提示词正文原样保留,从而不破坏上游插件更新时的 prompt diff。
3. 安全护栏(insideGitWorkTree,L95–L106):若插件根目录位于某个 git 工作树内(即它是源码检出而非安装态插件),则整次覆盖静默跳过。这是为了防止"打开仓库即触发 SessionStart → 每次会话都改写被版本跟踪的 agents/*.md → 工作树被弄脏"的事故;只有安装在 $CLAUDE_CONFIG_DIR 下、上方无 .git 的插件目录才会被修补。
4. 失败策略:文件缺失、布局不符、写入失败一律静默无操作(silent no-op),覆盖逻辑永远不会阻塞会话启动。tests/test_cavecrew_model_overrides.js 中的用例覆盖了"替换 model: haiku 为 sonnet"、"保留其余 frontmatter 行"等关键路径,可用 node tests/test_cavecrew_model_overrides.js 直接验证。
实际使用示例(启动 Claude Code 前在 shell 中设置):
export CAVECREW_REVIEWER_MODEL=sonnet # reviewer 用 sonnet,其余保持默认
模型名取值与 Claude Code agent frontmatter 一致(haiku/sonnet/opus 等)。注意两个适用限制:空变量等价于不设置;由于修补只作用于已安装代理文件的 model: 行,插件更新或重装会还原该行。
十、落地检查清单
把规范与实现对照后,使用 cavecrew-reviewer 前可核对以下几点:
- 触发方式:对主线程说 "review this PR / review my diff / audit this file",或直接指定子代理名派发;
- 输入边界:把待审对象(diff、分支、具体文件)明确给出——reviewer 不会替你扩大范围;
- 审查深度:默认拿 🔴/🟡/❓ 三类发现;需要风格级 nit 时显式要求 thorough;
- 结果解析:按
path:line:前缀逐行消费;totals:行判断是否阻断合并;No issues.表示零发现; - 模型策略:默认
haiku保成本;对高价值 PR 可通过CAVECREW_REVIEWER_MODEL钉到更强的模型,理解该修补在安装态生效、重装会还原; - 边界预期:拿到的是发现清单而非审查报告,人类可读版本需要主线程转述;想要架构级意见请改用原生
Code Reviewer。
综合来看,cavecrew-reviewer 的价值不在"另一个审查代理",而在于它把审查输出当数据协议来设计:Emoji 分级、确定性排序、totals 汇总、显式空结果、安全场景自动降压缩——这些约束共同保证了主线程能以最低解析成本消费审查结果,这正是 Caveman 项目"用更少 Token 完成同样的工程动作"这一整体设计哲学的具体落点。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00