Vet
把"代码质量"变成有证据、可决策、可修复的 finding。先定范围,再进对应轨道。
定范围
- diff 轨道(默认):写完代码后、提交前、PR/diff review,或用户说 deslop / 清理 / review 刚才的改动。范围按优先级取:用户显式指定 >
git diff(含 staged)> 本次会话改动。走下方 diff 流程。 - repo 轨道:全仓技术债/架构/质量审计、公开发布或开源前的 release preflight。加载
references/repo-audit.md执行。 - 用户只要审查意见时(review-only):不改代码,只输出 findings。
- 不扩散:范围外发现记一句 backlog 即可;内部 CI/tag 检查不触发 release preflight。
共享纪律
- 每个 finding 带
file:line或具体工具证据;拿不到证据就明说,不用猜测填充。 - 先跑项目已有的 lint/typecheck/test 拿基线再动手;修复后重跑同一组,不借红绿模糊蒙混。
- 修复一律 deletion-first:删代码、删抽象、删注释优先于新增;复用仓库已有工具函数;不引入新依赖;patch 保持最小。
- 纯风格好恶(无具体 failure mode)不是 finding;仓库既有约定(命名风格、注释密度、抽象层级)优先于通用口味。
- 幻觉指控先核实再定性:被指控的 API/flag/config key 对本地类型、
--help、lockfile 或文档验证;建议的替代写法同样先验证存在且版本兼容——不以一个幻觉替换另一个幻觉。 - 同一模式出现多次:合并成一条 finding 加代表性例子,不逐条刷屏。
Diff 轨道:deslop 流程
- 锁行为:跑项目快速检查(typecheck + 相关测试)拿基线;已经失败的先记录。
- 读 diff 和上下文:读完整改动块及足够周边代码,弄清已有 invariant 与可复用工具——"重复"和"防御过度"的判断必须锚在真实 invariant 上,不能凭感觉。
- 按 smell 表排查,每条 finding 归类:
delete/consolidate/fix/consider(判断题交给用户)。 - deletion-first 修复,顺序:死代码 → 重复 → 抽象 → 命名/注释 → 错误处理 → 测试。
- 重跑同一组检查,报告删了什么、验证证据是什么。
Smell checklist
| Smell | 检测信号 | 处理 |
|---|---|---|
| Comment slop | 注释复述下一行;docstring 复述签名;无信息的分节符;hedging("this should work") | 删。注释只解释 why;代码需要 what 注释时改写代码本身 |
| Defensive overkill | 内部函数校验已由 invariant 保证的值;catch-log-reraise 零信息;给必需配置兜默认值;边界内层层重复校验 | 删。只在系统边界(用户输入/网络/反序列化/env)校验,内部信任 invariant;必需配置缺失要响亮失败 |
| Over-abstraction | 单实现 interface;纯转发 wrapper;只调一次的 helper;一个操作套 Manager/Service/Factory;为假想需求预留的配置项 | inline 或删。测试 DI、确有多个实现、隔离外部依赖的除外 |
| Hallucination | API/flag/config key/schema 字段"长得像真的"但未核实;从相邻生态抄来的参数;用 try/optional-chain 兜底掩盖不理解 | 按共享纪律核实;删除 invented surface |
| Duplication | 不同文件里近乎相同的实现;sibling 目录下只换了名字的孪生模块 | 收敛到一个实现或参数化差异;新写 helper 前先查仓库是否已有 |
| Generic naming | data/result/temp/handler/manager/utils/helpers/common 出现在非平凡作用域 |
换领域名;utils.* 垃圾抽屉按职责拆 |
| Test theater | mock 掉所有依赖只断言调用次数;镜像实现控制流;snapshot 当唯一断言;只测 happy path | 改为断言行为/规格;mock 留在边界。判断标准:实现以同样方式写错时测试仍绿 = 摆设 |
| Boilerplate | result = f(); return result;return x ? true : false;手写循环替代语言内建 |
用该语言的 idiomatic 短形式 |
语言专属气味(Rust clone 滥用、Python 裸 except、TS any 等)见 references/languages.md,按 diff 实际涉及的语言加载,不涉及的不要套。
审查独立性
写完代码立刻自己宣布"质量很好"等于没审。
- 同会话自查:当作独立一轮——从 diff 重新读起,不依赖写代码时的记忆和假设。
- 有子代理可用:优先把 diff 交给独立子代理做 verifier 式审查,输入是 diff 和本清单;reviewer 只报告,取舍由编排层决定。
- review-only 模式下不动手;修改模式下改完后必须重跑检查收尾,不允许"我改的就是对的"直接宣布通过。
Do not flag
- 安全相关:auth、边界输入校验、TLS、rate limit——即使"看起来防御过度"。
- 框架要求的结构与目录约定。
- 没有具体 failure mode 的口味差异。
Output
- diff 轨道:findings 按
delete/consolidate/consider分组(每条带file:line、smell 类别、一句话理由)+ 最小 patch + 验证证据。 - repo 轨道:按
references/repo-audit.md的输出约定;默认在对话中完成,不生成报告文件。
Stop
- diff:范围内清单过完、修复验证通过即停,不为"还能更完美"追加第二轮。
- repo:见
references/repo-audit.md的停止规则。