前言
上一篇让 dev-orchestra 在最后把整个变更又审查了一次。
dev-orchestra 是一个 Claude Code / Codex / Antigravity 的插件,只需一句话的请求,就能跑完设计、实现、测试、多个 AI 的审查和修复。
不过,“从设计开始全部交给它”,作为尝试来说步子有点大。很多时候,手头只是有一个写到一半的改动,只想让几个 AI 帮忙看看。
dev-orchestra 的审查可以脱离其他环节单独使用。这次介绍只用审查的步骤。
- 3 条命令:
review snapshot→review run→review show - snapshot 固定的是什么,
.ai/里会留下什么 - 常用的选项,以及审查 PR 分支时
--base怎么选 - 不审查代码、而是审查文字(本博客的文章)的例子
dev-orchestra 已在 GitHub 上开源(MIT 许可证)。如果觉得有用,欢迎给个 Star。
试用环境
| 项目 | 内容 |
|---|---|
| dev-orchestra | 1.3.0,预设 standard(optimization.level 为默认的 balanced) |
| 审查者 | claude-general(Claude Opus)、codex-general(Codex CLI 0.163.0,gpt-6.1-sol)、claude-security(Claude Sonnet)、claude-test(Claude Sonnet) |
| Claude Code | 2.1.312 |
| 环境 | Windows 11、Git Bash、Python 3.14.7、Git 2.55.0。配置放在与平时不同的文件夹(DEV_ORCHESTRA_HOME)中 |
安装 dev-orchestra 的步骤写在 Claude Code 篇和 Codex 篇中。只用审查时,安装方法和初始设置也一样。
素材:添加了优惠券的分支
为此我做了一个小的 Python 包 shopcart。main 上只有计算购物车小计的函数,分支 feature/coupon 添加了优惠券的函数。
PERCENT_OFF = {"SAVE10": 10, "SAVE20": 20}
AMOUNT_OFF = {"SAVE500": (500, 3000)} # code: (yen off, minimum subtotal)
def apply_coupon(amount, code):
"""Return the amount to pay after applying the coupon `code`."""
if code in PERCENT_OFF:
discount = amount * PERCENT_OFF[code] // 100
return amount - discount
off, minimum = AMOUNT_OFF[code]
if amount > minimum:
return amount - off
return amount
README 里写着:“SAVE500 在小计达到 3,000 日元时减 500 日元”“不认识的代码不改变金额”“代码区分大小写(有意为之)”。也就是说,这段代码里故意埋了 2 个缺陷(> 应该是 >=;不认识的代码会引发 KeyError)。优惠券的 3 个测试(加上购物车的测试共 5 个)全部通过。
1. 固定改动(review snapshot)
固定从分支起点(main)开始的改动。
dev-orchestra review snapshot --base main
Snapshot: .ai/workflows/b1627574daa6/reviews/review-target.diff
strategy: git diff main
files: 4
size: 2249 bytes (sha256 27ff110afa0b)
snapshot 这一步会把要审查的差异固定到 1 个文件中,让所有审查者看到同样的内容。固定之后即使再修改文件,这一轮审查者看到的差异也不会变。不加 --base 时,固定的是工作树与 HEAD 之间的差异(还没有 commit 的改动)。还没有 commit 的新文件默认也会包含在内。
固定的内容会留在 .ai/ 下。
| 文件 | 内容 |
|---|---|
review-target.diff | 给审查者看的差异本身 |
review-target.json | 差异的来源(base、base_commit、head)、改动的文件列表、新增和删除的行数、差异的 sha256、没有发送的文件(withheld) |
state.json | 这次工作(workflow)的记录 |
sha256 也会写进各审查者的报告里,事后可以确认“所有人看的是同一个差异”。
.ai/ 里会自动放一个只写了 * 的 .gitignore,所以不会不小心被 commit。
如果在配置中设置
review.context.surrounding: enclosing,还可以把差异周围的函数和类一起固定下来交给审查者(默认是none)。详情见 references/reviews.md。
2. 运行审查(review run)
dev-orchestra review run
ok claude-general claude opus 3 finding(s)
1 successful, 0 failed
Consolidated: .ai/workflows/b1627574daa6/reviews/consolidated.md
note: claude-test (when: relevance) added: shopcart/__init__.py is not documentation
note: no test result recorded for this change, so the review is running unchecked. `state record test ok` before `review run` lets this stop a review of a red tree.
note: low-risk change (4 file(s), 49 line(s)): 1 reviewer instead of the full panel (claude-general). Cross-model disagreement is what a second reviewer buys; raise optimization.level or the low_risk thresholds to keep it.
17 秒就结束了。不过审查的只有 1 人。第 1 条 note: 是在告知:因为“这不是只改文档的改动”,所以把测试视角的审查者 claude-test 列入了候选。即便如此,实际运行的只有 claude-general。正如最后一条 note: 所说,在 balanced 下,规模小且不涉及高风险路径的改动(这次是 4 个文件、49 行)会把审查者减到 1 人。在测量篇中也发生了同样的事。
第 2 条 note: 是在提示没有记录测试结果。只用审查时可以不用管它。如果不想审查测试失败的改动,可以先记录 dev-orchestra state record test ok(或 failed),结果为 failed 时就会停止审查。
3. 查看结果(review show)
dev-orchestra review show
输出的开头和第 1 个问题如下(之后省略)。
Source: .ai/workflows/b1627574daa6/reviews/consolidated.json
# Consolidated review
- Generated: 2026-10-29T13:19:24Z
- Iteration: 1
- Snapshot: 27ff110afa0b
- Reviewers: 1 ok / 1 total
- Coverage: round complete, change complete
- Findings: 3 (0 duplicate report(s) merged)
## Reviewers
- ok [general] claude-general / claude / opus -- 3 finding(s)
## Findings
### F1 [HIGH] correctness
- Location: `shopcart/coupon.py`:12
- Reported by: claude-general
- Possible duplicate of: none
- Triage: needs-triage
- Problem: Any code missing from `PERCENT_OFF` drops through to `AMOUNT_OFF[code]`, so an unknown code raises `KeyError`. The README says an unknown code should leave the amount unchanged.
- Impact: Checkout crashes when a user enters a mistyped or lowercase code like `save10`. The README calls out lowercase codes as invalid on purpose, so this input is expected.
- Evidence: `off, minimum = AMOUNT_OFF[code]`
- Recommended fix: Add `if code not in AMOUNT_OFF: return amount` before the lookup, or use `AMOUNT_OFF.get(code)` and return `amount` when it is `None`.
问题共 3 个:埋下的 2 个缺陷(F1 的 KeyError、F2 的 >),以及指出缺少边界测试的 F3。每个问题都按固定的格式列出严重程度、位置、问题、影响、依据和修改方法。
加上 --json 可以用 JSON 输出同样的内容,也可以交给其他工具处理。
4. 交给多个 AI 看(—only)
减到 1 人的话,就算不上“多个 AI”了。用 --only 点名审查者,人数就不会被减少。我在同一个 snapshot 上加上了其余 3 人。
dev-orchestra review run --only codex-general claude-security claude-test
ok codex-general codex gpt-6.1-sol 2 finding(s)
ok claude-security claude sonnet 4 finding(s)
ok claude-test claude sonnet 5 finding(s)
3 successful, 0 failed
Consolidated: .ai/workflows/b1627574daa6/reviews/consolidated.md
note: claude-test (when: relevance) added: named by --only
note: no test result recorded for this change, so the review is running unchecked. `state record test ok` before `review run` lets this stop a review of a red tree.
3 人并行运行,19 秒结束。即使用 --only 只运行一部分,汇总结果(consolidated)中也会包含其他审查者对这个 snapshot 的报告。看 review show,变成了 4 人、14 个问题。
- Reviewers: 4 ok / 4 total
- Coverage: round complete, change complete
- Findings: 14 (0 duplicate report(s) merged)
埋下的 2 个缺陷,都有 3 人各自作为缺陷指了出来,claude-test 也以“没有确认它的测试”的形式提到了。14 个问题中哪些采纳、哪些作为重复或驳回,下一篇再讲。
如果一开始就想让 4 人看,可以在 --only 中列出 4 人,或者调高 optimization.level。也可以用角色名(general、security 等)点名。
5. 常用的选项
| 选项 | 用途 |
|---|---|
--only <id 或角色> | 只运行部分审查者。减少人数的机制也会失效 |
--sequential | 一个一个按顺序运行。用于排查哪个审查者卡住了 |
--context "…" | 给所有审查者相同的前提(“README 就是规格”“这是文章”等) |
--timeout <秒> | 仅在这次运行中更改每人的时间限制 |
组合起来使用是这样的。这一节和下一节是在题材仓库的副本中试的。workflow 的名字用环境变量 DEV_ORCHESTRA_WORKFLOW 定为 pr-check(不指定的话,会自动起一个像 b1627574daa6 这样的名字)。
dev-orchestra review run --only claude-general codex-general --sequential --timeout 300 --context "This is a pull request that adds coupons. The README is the spec."
ok claude-general claude opus 3 finding(s)
ok codex-general codex gpt-6.1-sol 2 finding(s)
2 successful, 0 failed
Consolidated: .ai/workflows/pr-check/reviews/consolidated.md
note: no test result recorded for this change, so the review is running unchecked. `state record test ok` before `review run` lets this stop a review of a red tree.
因为是按顺序运行的,花了 27 秒。
6. 审查 PR 分支时的 —base
--base main 取的是 main 与当前工作树之间的差异(strategy: git diff main)。如果建立分支后 main 又往前走了,main 上新增的改动会像是被这个分支删掉了一样出现在差异中。
我试着在建立分支后,往 main 上 commit 了一行 README 的改动,再用 --base main 固定一次。差异里出现了这一行。
-- `subtotal` ignores nothing: every item counts
这个分支没有碰过的行,被当作“删除的行”给审查者看了。把分支的分叉点(merge-base)传给 --base,这一行就不会出现了。
dev-orchestra review snapshot --base $(git merge-base main HEAD)
Snapshot: .ai/workflows/pr-check/reviews/review-target.diff
strategy: git diff 77d4296d87f869eb4af4d5cf1ca41b135cef2b31
files: 4
size: 2249 bytes (sha256 27ff110afa0b)
sha256 与 main 前进之前取的第一个 snapshot 相同。GitHub 的 PR 显示的差异也是从分叉点开始的,所以审查 PR 分支时,推荐传入 merge-base。如果要和远程的 main 比较,就在 git fetch 之后使用与 origin/main 的 merge-base(这次我是用本地的 main 试的)。
7. 不发送 lockfile 的内容(review.exclude)
升级依赖时,lockfile 里会出现几百行的差异。这些不是人写的,却要按审查者的人数消耗 token。dev-orchestra 默认不发送 lockfile、dist/、vendor/、node_modules/、压缩过的 JS 和 CSS、source map、*.snap 的差异内容(review.exclude)。
我试着在题材的副本中放了一个 306 行的 package-lock.json,当作 npm 的 lockfile(尚未 commit 的新文件),又给 cart.py 加了 1 行注释,然后不加 --base 固定了快照(workflow 的名字是 excl)。
Snapshot: .ai/workflows/excl/reviews/review-target.diff
strategy: git diff HEAD
files: 1
size: 311 bytes (sha256 a42cd872c7e8)
withheld: 1 file(s), 306 changed line(s) not sent to reviewers
package-lock.json (package-lock.json)
reviewers are told these changed; --no-exclude sends them in full
文件名和改动的行数会告诉审查者,所以并不是隐瞒。想全部发送时,加上 --no-exclude。token 和费用的话题,我整理在了本系列第 17 篇(预计 2026 年 11 月 23 日发布)中。
8. 不只是代码,文字也能用
要审查的差异不一定是代码。本博客在发布文章之前,会用 review run 审查文章(docs/blog/series.md 中的“审查”一节)。这篇文章写完之后,我也和下一篇文章一起,像下面这样让它审查了。
dev-orchestra review snapshot
dev-orchestra review run --only claude-general codex-general --context "These are two Japanese blog posts (a series on dev-orchestra), not code. Review facts, not style: check that every command, option, output and behaviour described matches dev-orchestra 1.3.0, whose docs are in C:/Projects/dev-orchestra (references/reviews.md, references/cli.md, references/workflow.md) and ~/.claude/plugins/cache/dev-orchestra/dev-orchestra/1.3.0. The outputs quoted were captured from real runs against a small sample repo; flag any claim that contradicts the docs, any internal inconsistency between the two posts, and anything misleading to a reader. Repository rules for posts are in CLAUDE.md and docs/blog/writing.md."
审查者被要求的是审查代码。所以我用 --context 告诉它们“这是文章而不是代码”以及“去哪里核实事实”。我从没在不加 --context 的情况下审查过文章,所以不加会怎样并没有试过(命令中主目录的路径换成了 ~)。
把这篇和下一篇文章一起审查时,claude-general 和 codex-general 提出了 6 个问题。除了“还没有翻译”(因为还在写)之外,还发现了文章之间数字不一致的地方,比如“2 篇文章中的测试数量对不上(应该是 3 个 + 5 个,却写成了 10 个)”“2 篇文章中发现缺陷的人数不一致”,我全都改了。
也写一下缺点
- 差异会被发送给所登记的各审查者所属的厂商。 4 人的配置中,差异被同时发送给了 Anthropic 和 OpenAI。审查者能以只读方式读取周围的文件,所以发送的不一定只有差异。不能拿到公司外的代码,请使用让本地 LLM 当审查者的方法(英文)
- 小改动默认会减到 1 人。 想让多个 AI 看,就需要用
--only或optimization.level定好人数 - 问题只是主张,不是事实。 4 人看了提出 14 个问题,但内容重叠的很多,直接照着改就会把同一个修改请求好几次
- token 与人数成正比增加。 审查者并行运行,所以时间不会延长多少,但费用要按人数付
总结
- dev-orchestra 的审查可以不用设计和实现环节,单独使用
- 用
review snapshot固定差异,用review run审查,用review show查看 - 固定的差异和结果留在
.ai/中,通过.gitignore排除在 commit 之外 - 小改动默认会减到 1 人。想让多个 AI 看,就用
--only点名 - 审查 PR 分支时,把 merge-base 传给
--base - lockfile 等的内容默认不发送。不只是代码,也能用来审查文章
下一篇(预计 2026 年 11 月 13 日发布)会把这次的 14 个问题分成采纳、驳回和重复,再交给修复者去改。
GitHub: istb16/dev-orchestra(给个 Star 就是对我最大的鼓励)
本系列的文章可以在“dev-orchestra”文章列表中集中阅读。
相关文章
我让 dev-orchestra 在最后把整个改动再审查一遍
我在一个小 Python 包上试了 dev-orchestra 1.3.0 新增的“最后审查整个改动”(review.whole_change_recheck)。只看修复的那一轮没有发现问题后,看整个改动的一轮发现了 1 处修复与先前改动之间的冲突。而对于故意制造冲突的修复,只看修复的那一轮就先发现了。
我测了一下 dev-orchestra:每个请求的耗时,以及不同审查者人数下的问题数
我用 dev-orchestra 1.2.1 提了一个小功能的请求,测了耗时(不算等待我批准的时间,约 6 分钟),以及审查者为 1 人、2 人、4 人时提出和采纳的问题数。审查者越多,可采纳的问题也越多,但多出来的都是关于测试的问题。
试着给 dev-orchestra 的每个角色交代固定的指示
我试用了 dev-orchestra 1.2.1 加入的 instructions。把给 implementer 和审查者的固定指示写在仓库里,它们就会进入每一次的提示词。本文用实际的输出确认它们如何显示、放在哪里,以及修改指示的变更会被如何对待。