この記事は tk3.biz のブログ からの転載です。
はじめに
前回は、dev-orchestra のプリセットを比べました。プリセットは「マシン全体で、どこにお金をかけるか」をまとめて決めるものです。
今回は、その中身を自分で組み替える方法を書きます。
- 役(ロール)ごとに、どの CLI・どのモデルを使うか
- レビュアーを何人、どの観点で並べるか
- リポジトリに合わせた分野の専門役を、
config suggest-rolesに提案させる
最後に、わざとバグを仕込んだ変更を 9 人のレビュアーに見せて、人数を増やすと何が変わるのかを測ってみました。
この記事の内容は dev-orchestra 1.0.0 で確かめたものです。最新の情報は 設定のドキュメント を見てください。
dev-orchestra は GitHub で公開しています(MIT ライセンス)。役に立ちそうと思ったら、スターを付けてもらえるとうれしいです。
手順
1. 役(ロール)を知る
dev-orchestra には 5 つの役があります。
| 役 | 設定の名前 | やること |
|---|---|---|
| 指揮 | orchestrator |
どの工程が要るかを決め、結果をまとめる |
| 設計 | architect |
調べて計画を書く(読み取り専用) |
| 実装 | implementer |
計画からコードとテストを書く |
| レビュー | reviewers |
同じ差分を、互いの結果を見ずに読む(読み取り専用)。何人でも置ける |
| 修正 | review_fixer |
トリアージで採用した指摘だけを直す |
レビュアー以外の 4 つは 1 人ずつ、レビュアーは何人でも並べられます。
2. モデルは「系列名 + latest」で指定する
dev-orchestra の設定には、モデルの名前(日付入りの ID)を書きません。書くのは系列名と「その系列の最新を使う」という指定です。
implementer:
provider: claude
model:
family: opus # 系列名
version: latest # その系列の最新
こうしておくと、新しいモデルが出ても設定を書き換えずにそのまま追従します。実行するたびに、入っている CLI に「opus の最新はどれか」を確かめてから使うので、存在しないモデル名で動いたつもりになることもありません。確かめられなければ、推測せずに止まります。
使える系列名は dev-orchestra model list で分かります。手元ではこう出ました(抜粋)。
claude: installed
fable family=fable source=cli-help
opus family=opus source=cli-help
sonnet family=sonnet source=cli-help
codex: installed
CLI default (recommended coding model) family=recommended-coding source=cli-default
GPT-6.1-Sol family=gpt-6.1-sol source=cli-catalog
GPT-6-Astra family=gpt-6-astra source=cli-catalog
どうしても 1 つのモデルに固定したいときは、
version: pinnedと ID を書くこともできます。ただし新しいモデルには追従しなくなるので、意図して使います。
3. 役ごとに CLI やモデルを変える
組み替えは、エージェントに頼むのがいちばん簡単です。裏ではこんなコマンドが動きます。
| 頼み方 | 動くコマンド |
|---|---|
| 「実装には Claude の opus を使って」 | config set implementer.model.family opus |
| 「設計は Codex にやらせて」 |
config set architect.provider codex(+ Codex が受け付ける系列名) |
| 「このプロジェクトだけ変えて」 | 書き込むコマンドに --scope project を付ける |
設定はプロジェクト → グローバル → 組み込みの既定値の順に効きます。プリセットの上から、変えたいところだけを上書きする形です。
4. 1 つの役に、安いモデルとセカンドオピニオンを持たせる
model tier(モデルティア)を使うと、1 つの役に別のモデルを予備として持たせられます。
implementer:
provider: claude
model:
family: opus
version: latest
model_tiers:
light: # 1 行の修正などは安いモデルで
model:
family: sonnet
version: latest
second-opinion: # 別の会社の AI でもう一度
provider: codex
どのティアを使うかは、オーケストレーターが依頼の難しさを見て選びます(run implementer --tier light)。存在しないティアを指定するとエラーになり、黙って既定のモデルで走ることはありません。
5. レビュアーの観点を選ぶ
レビュアーには**観点(role)**を持たせます。同じ差分でも、観点によって見るところが変わります。
| 観点 | 主に見るところ |
|---|---|
general |
正しさ、エッジケース、エラー処理など全般 |
security |
認証・認可、インジェクション、秘密情報の扱い |
performance |
計算量、N+1 クエリ、不要な I/O |
test |
変更した挙動のテスト、意味のないアサーション |
architecture |
責務の分け方、結合度、既存の慣習との整合 |
database |
マイグレーションの安全性、ロック、制約、インデックス |
frontend |
状態の扱い、描画、アクセシビリティ |
backend |
API の契約、バリデーション、ステータスコード |
レビュアーの追加・削除・変更は、こうします(これもエージェントに頼めます)。
dev-orchestra reviewer add --provider codex --role security # Codex のセキュリティ担当を足す
dev-orchestra reviewer set 2 --provider codex --role general # 2 番目を差し替える
dev-orchestra reviewer remove performance # 外す
dev-orchestra reviewer list # 確かめる
reviewer set <id> --when high-risk で、危ない変更のときだけ動くレビュアーにすることもできます。
6. 分野の専門役を config suggest-roles に提案させる
ここが今回いちばん紹介したかった機能です。
config suggest-roles は、リポジトリのファイル名を見て、database・frontend・backend の専門役が要るかを判断します。モデルは呼ばないので、トークンを使いません。
記事用に、フロントエンド・API・DB のマイグレーションを持つ小さな TODO アプリのリポジトリを作って試しました。
Proposed:
claude-database claude / sonnet role database
when.paths: migrations/*, */migrations/*, *.sql
evidence: migrations/: 2 files, e.g. db/migrations/001_create_users.sql, db/migrations/002_create_todos.sql
claude-frontend claude / sonnet role frontend
when.paths: *.tsx
evidence: *.tsx: 2 files, e.g. frontend/src/TodoItem.tsx, frontend/src/TodoList.tsx
claude-backend claude / sonnet role backend
when.paths: api/*, */api/*, routes/*, */routes/*
evidence: api/: 3 files, e.g. api/db.py, api/routes/todos.py, api/routes/users.py
Each joins only code rounds touching its paths, and every design review round.
**なぜ提案したのか(evidence)**まで出してくれます。
一方、このブログのリポジトリ(Astro)で動かすと、何も提案されませんでした。
Not proposed:
database: no signal (no migrations/, migrate/, alembic/ or prisma/ directory; fewer than 2 *.sql files; no schema.prisma)
frontend: no signal (fewer than 2 *.tsx, *.jsx, *.vue or *.svelte files)
backend: no signal (no api/, server/, backend/, handlers/, routes/ or controllers/ directory holding 2 files outside a frontend)
Nothing to add.
提案しなかった理由も出るので、「なぜ足されないのか」で迷いません。
提案を受け入れるときは --write を付けます。プロジェクトの設定ファイル(.dev-orchestra.yaml)に、こう追加されました。
reviewers_extra:
- id: claude-database
provider: claude
model:
family: sonnet
version: latest
role: database
when:
paths:
- "migrations/*"
- "*/migrations/*"
- "*.sql"
ポイントは when.paths です。専門役は、コードのレビューにはそのパスのファイルが変わったときだけ加わります。CSS だけを直したときに database の担当が呼ばれることはないので、ふだんのコードレビューは重くなりません。ただし、出力の最後の行にあるとおり、設計のレビューには毎回加わります。設計レビューの費用はそのぶん増えます。
| プリセット | suggest-roles |
|
|---|---|---|
| 何を決めるか | マシン全体の、費用のかけ方 | リポジトリに合わせた専門家の追加 |
| 保存先 | グローバル設定 | プロジェクトの設定 |
| 動くタイミング | いつも | コードレビューはそのパスが変わったときだけ。設計レビューは毎回 |
7. レビュアーを増やすと何が変わるか、測ってみた
最後に、レビュアーの人数で結果がどう変わるかを測りました。
やり方
- 上の TODO アプリに、わざとバグを 6 つ仕込んだ変更を作った(4 ファイル)
-
qualityプリセット(Claude と Codex の 6 人)に、suggest-rolesの専門役 3 人を足した 9 人で、1 回だけレビューした - レビュアーは互いの結果を見ずに動くので、「1 人だけ」「2 社」などの構成の結果は、9 人の結果を組み合わせて数えた
- 指摘はすべて私がトリアージして、仕込んだバグ(B1〜B6)と、仕込んでいないが本物だった問題(E1〜E6)に分けた
| 仕込んだバグ | |
|---|---|
| B1 | 検索語を f-string で SQL に埋め込む(SQL インジェクション) |
| B2 | 削除で持ち主を確かめない(他人の TODO を消せる) |
| B3 | ページ送りの offset に + 1(1 件ずれる) |
| B4 | NOT NULL の列を既定値なしで追加(マイグレーションが失敗する) |
| B5 | タイトルを dangerouslySetInnerHTML で表示(XSS) |
| B6 | 削除のテストが、持ち主の確認を検証していない |
結果
構成ごとにまとめると、こうなりました。
| 構成 | 見つかった問題(全 12) | 指摘の数(重複をまとめる前) |
|---|---|---|
| Claude fable(general)1 人 | 10 | 10 |
| Codex(general)1 人 | 5 | 5 |
| 2 社(上の 2 人) | 10 | 15 |
quality の 6 人 |
12 | 43 |
| 6 人 + 専門役 3 人 | 12 | 60 |
分かったこと
- 分かりやすいバグは、ほぼ全員が見つけた。B1〜B5 は、frontend の専門役(観点がフロントエンド)を除く 8 人全員が見つけた
- 2 人から 6 人に増やすと、見つかる問題が 2 つ増えた(10 → 12)。増えたのは E5 と E6 の 2 つ
- 6 人から 9 人に増やしても、問題は増えず、指摘だけが増えた。6 人で 12 個すべてが見つかり、9 人にすると指摘が 43 件から 60 件になった。dev-orchestra が重複をまとめると、60 件は 51 件になった
- 差が出たのは、仕込んでいない問題のほう。「関数の引数が変わって呼び出し側が壊れる」(E5)は architecture の観点だけ、「検索のテストがない」(E6)は test の観点だけが見つけた
- モデルの差も大きかった。同じ general の観点でも、Claude fable は 1 人で 12 個中 10 個、Codex は 5 個だった。この回では、モデルの違いと観点の違いを切り分けられていない
- Codex の 2 人は、仕込んだバグ 5 つを空振りなしで見つけたが、この回ではほかの人が見つけなかった問題は出さなかった
- 9 人分の費用は、合計で約 11 万トークンだった(差分が 4 ファイルと小さかったため)
これは 1 回だけ、小さなサンプルでの結果です。仕込んだバグは分かりやすいものばかりで、仕込んでいない問題を「本物」とみなしたのも私の判断です。実際の開発の、もっと込み入った変更では、別の会社の AI を混ぜる効果が違って見える可能性があります(以前の記事では、実際のコードで別の傾向が出ています)。
この結果から、自分の使い方としてはこう考えています。
- 人数より、観点の違いを足してみる。この 1 回では、architecture と test が 1 つずつ、ほかの人が見つけなかった問題を出した。ただし general を何人も並べる構成は試していないので、「同じ general を増やすより効く」とまでは言えない
-
専門役は
when.paths付きで足す。コードレビューでは、そのパスが変わったときだけ加わる - 指摘が増えるほどトリアージの量が増える。dev-orchestra が重複をまとめてくれる(今回は 60 件が 51 件になった)が、人数は「多いほどよい」ではない
まとめ
- 役は 5 つ(指揮・設計・実装・レビュー・修正)。レビュアーだけは何人でも並べられる
- モデルは系列名 +
latestで指定する。新しいモデルにそのまま追従し、確かめられない名前では動かない - model tier で、1 つの役に安いモデルやセカンドオピニオンを持たせられる
- レビュアーには 8 つの観点がある。
reviewer add/set/removeで組み替える -
config suggest-rolesは、ファイル名から database・frontend・backend の専門役を提案する。トークンは使わない。コードレビューにはそのパスが変わったときだけ、設計レビューには毎回加わる - 9 人で 1 回だけ測ったら、2 人から 6 人で問題が 2 つ増え、6 人から 9 人では指摘だけが増えた
- この 1 回では、architecture と test が 1 つずつ、ほかの人が見つけなかった問題を出した。同じ general でもモデルによって大きな差があった
次回は、自作のエージェント(ローカル LLM)を dev-orchestra に繋ぐ方法を書きます。
GitHub: istb16/dev-orchestra(スターを付けてもらえると励みになります)