tk3.biz
Back to Blog

I Used Only dev-orchestra's Review to Show My Local Changes to Several AIs

Introduction

Last time, I had dev-orchestra review the whole change once more at the end.

dev-orchestra is a plugin for Claude Code / Codex / Antigravity that takes a single-sentence request and runs design, implementation, testing, reviews by multiple AIs, and fixes.

Still, “hand it everything from design onward” is a fairly big step just to try it out. Often I have a half-finished change on my machine and only want a few AIs to look at it.

dev-orchestra’s review works on its own, separately from the other stages. This time I’ll walk through using only the review:

  • Three commands: review snapshot → review run → review show
  • What the snapshot freezes, and what’s left under .ai/
  • The options I use most, and how to choose --base when showing a PR branch
  • An example of reviewing prose (posts on this blog) instead of code

dev-orchestra is open source on GitHub (MIT license). If it looks useful, a star would mean a lot.

→ github.com/istb16/dev-orchestra

Setup

ItemDetails
dev-orchestra1.3.0, preset standard (optimization.level at the default balanced)
Reviewersclaude-general (Claude Opus), codex-general (Codex CLI 0.163.0, gpt-6.1-sol), claude-security (Claude Sonnet), claude-test (Claude Sonnet)
Claude Code2.1.312
EnvironmentWindows 11, Git Bash, Python 3.14.7, Git 2.55.0. The configuration lived in a separate folder (DEV_ORCHESTRA_HOME)

Installation steps are in the Claude Code post and the Codex post. Installation and initial setup are the same when you only use the review.

The Subject: A Branch That Adds Coupons

For this, I made a small Python package, shopcart. main only has a function that returns the cart subtotal, and the branch feature/coupon adds a coupon function.

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

The README says “SAVE500 takes 500 yen off when the subtotal is 3,000 yen or more,” “an unknown code leaves the amount unchanged,” and “codes are case-sensitive (on purpose).” In other words, I planted two bugs on purpose in this code (> should be >=, and an unknown code raises KeyError). All three coupon tests (five with the cart tests) pass.

1. Freeze the Change (review snapshot)

Freeze the change since the branch point (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)

The snapshot step freezes the diff to review into one file so that every reviewer sees the same thing. Editing files after the snapshot doesn’t change the diff that round’s reviewers see. Without --base, it freezes the difference between the working tree and HEAD (your uncommitted changes). New files that aren’t committed yet are included by default.

What it freezes stays under .ai/:

FileContents
review-target.diffThe diff shown to the reviewers
review-target.jsonWhere the diff came from (base, base_commit, head), the list of changed files, lines added and deleted, the diff’s sha256, and files that weren’t sent (withheld)
state.jsonThe record of this piece of work (the workflow)

The sha256 is also written into each reviewer’s report, so you can check afterward that “everyone saw the same diff.”

.ai/ automatically gets a .gitignore containing just *, so you won’t commit it by accident.

With review.context.surrounding: enclosing in the configuration, it also freezes the functions and classes around the diff and passes them to the reviewers (the default is none). Details are in references/reviews.md.

2. Run the Review (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.

It finished in 17 seconds. But only one reviewer looked at it. The first note: says the test-focused reviewer claude-test was made a candidate because “this isn’t a docs-only change.” Even so, only claude-general ran. As the last note: says, under balanced a small change that touches no high-risk path (4 files and 49 lines here) gets cut down to one reviewer. The same thing happened in the measurement post.

The second note: says no test result was recorded. When you only use the review, you can ignore it. If you don’t want to review a change whose tests are failing, record dev-orchestra state record test ok (or failed) first, and it will stop the review when the result is failed.

3. Read the Results (review show)

dev-orchestra review show

Here’s the start of the output and the first finding (the rest is omitted):

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`.

There were three findings: the two planted bugs (F1, the KeyError; F2, the >), and F3, about missing boundary tests. Each finding lists severity, location, problem, impact, evidence, and fix in a fixed format.

With --json you get the same content as JSON, so you can hand it to other tools.

4. Show It to Several AIs (—only)

Cut down to one reviewer, it isn’t “several AIs.” If you name reviewers with --only, the panel isn’t cut. I added the other three on the same snapshot:

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.

The three ran in parallel and finished in 19 seconds. Even when you run only some reviewers with --only, the consolidated result also includes other reviewers’ reports on this snapshot. review show now showed four reviewers and 14 findings:

- Reviewers: 4 ok / 4 total
- Coverage: round complete, change complete
- Findings: 14 (0 duplicate report(s) merged)

Both planted bugs were reported as bugs by three reviewers independently, and claude-test also touched on them as “there’s no test that checks this.” Which of the 14 to accept, and which to mark as duplicates or reject, is the subject of the next post.

If you want all four from the start, list all four in --only, or raise optimization.level. You can also name them by role (general, security, and so on).

5. Options I Use Most

OptionWhen to use it
--only <id or role>Run only some reviewers. This also turns off the cut in reviewer count
--sequentialRun reviewers one at a time, in order. Useful for finding out which reviewer is stuck
--context "…"Give every reviewer the same premise (“the README is the spec,” “this is a blog post,” and so on)
--timeout <seconds>Change the per-reviewer time limit for this run only

Used together, it looks like this. I tried this section and the next one in a copy of the sample repository. I named the workflow pr-check with the environment variable DEV_ORCHESTRA_WORKFLOW (without it, a name like b1627574daa6 is assigned automatically).

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.

Since they ran in order, it took 27 seconds.

6. —base When Showing a PR Branch

--base main takes the difference between main and the current working tree (strategy: git diff main). If main has moved on since you branched, changes added on main show up in the diff as if this branch had deleted them.

To try it, I made a commit on main after branching that adds one line to the README, then froze again with --base main. The diff contained this line:

-- `subtotal` ignores nothing: every item counts

A line this branch never touched is shown to the reviewers as a “deleted line.” Passing the branch point (merge-base) to --base kept this line out:

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)

The sha256 matches the first snapshot, taken before main moved on. A GitHub PR also shows the diff from the branch point, so when showing a PR branch I recommend passing the merge-base. To compare against the remote main, run git fetch and use the merge-base with origin/main (here I tried it with the local main).

7. Lockfile Contents Aren’t Sent (review.exclude)

Upgrading dependencies puts hundreds of lines of diff in the lockfile. No person wrote them, yet they use tokens for every reviewer. By default dev-orchestra doesn’t send the contents of diffs to lockfiles, dist/, vendor/, node_modules/, minified JS and CSS, source maps, and *.snap (review.exclude).

To try it, I put a 306-line package-lock.json standing in for an npm lockfile (a new, uncommitted file) into the copy of the sample, added a one-line comment to cart.py, and took the snapshot without --base (the workflow is named 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

The reviewers are still told the file names and how many lines changed, so nothing is hidden. To send everything, add --no-exclude. I cover tokens and cost in the 17th post of the series (scheduled for November 23, 2026).

8. It Works on Prose, Not Just Code

The diff you review doesn’t have to be code. On this blog, I have review run review posts before they’re published (the “Review” section of docs/blog/series.md). Once I finished writing this post, I had it reviewed together with the next post like this:

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."

The reviewers are asked to review code. So I use --context to say “these are posts, not code” and where to check the facts. I’ve never had a post reviewed without --context, so I haven’t tested what happens if you leave it off (I replaced the home path in the command with ~).

When I had this post and the next one reviewed together, claude-general and codex-general gave six findings. Besides one saying the translations didn’t exist yet (I was still writing), they caught numbers that disagreed between the two posts, such as “the test counts don’t match across the two posts (it should be 3 + 5, not 10)” and “the two posts disagree on how many reviewers found the bugs.” I fixed all of them.

The Downsides

  • The diff is sent to the vendor of each registered reviewer. With the four-reviewer panel, it went to both Anthropic and OpenAI. Reviewers can read surrounding files (read-only), so it may not be just the diff that’s sent. For code that can’t leave your organization, use the approach that makes a local LLM the reviewer
  • Small changes get cut to one reviewer by default. If you want several AIs, you need to set the panel with --only or optimization.level
  • Findings are claims, not facts. Four reviewers gave 14 findings, but many overlap; fixing them as-is means asking for the same fix several times
  • Tokens grow with the number of reviewers. Reviewers run in parallel, so time doesn’t grow much, but you pay for each reviewer

Summary

  • dev-orchestra’s review works on its own, without the design and implementation stages
  • Freeze the diff with review snapshot, review with review run, and read with review show
  • The frozen diff and results stay under .ai/, and .gitignore keeps them out of commits
  • Small changes are cut to one reviewer by default. To show it to several AIs, name them with --only
  • When showing a PR branch, pass the merge-base to --base
  • Contents like lockfiles aren’t sent by default. It also works for reviewing posts, not just code

Next time (scheduled for November 13, 2026), I’ll sort the 14 findings from this post into accepted, rejected, and duplicate, and have the fixer address them.

GitHub: istb16/dev-orchestra (a star would be very encouraging)

All posts in this series are in the list of “dev-orchestra” posts.

Related Posts