SwarmForge 徹底レビュー: Uncle Bob のエージェント群は実際どう動くのか
6 つの AI エージェント、6 つの git worktree、1 つの永続キュー、そして善意ではなくシェルコマンドである品質ゲート。tmux の部分は、この中で最も面白くない要素です。
これが解こうとしている問題
1 つのコーディングエージェントに実際の機能を任せると、実装とテストを同じ息づかいで、同じ理解から、同じ盲点を抱えたまま書きます。要求を読み違えていれば、テストはその読み違いをそのまま符号化して緑になります。同じエージェントに自分の成果をレビューさせれば、自分に同意します。コードを生んだ推論がまだコンテキストに残り、いまも妥当に見えるからです。量はこれを改善せず悪化させます。出力はもっともらしく、大量で、安い。だからレビューする人間がボトルネックになり、流し読みを始めます。SwarmForge はこれに対する特定の答えに賭けています。品質は著者からは生まれない。だからレビューする規律ごとに、専用のエージェント、専用のコンテキスト、専用の作業ツリー、そして終了コード 0 を返すか返さないかのチェックを与える、という答えです。
設計の要は並列性ではありません。ロールがコミットされたコードだけを通じて通信することです。レビューするエージェントは「なぜこのコードで問題ないか」という著者の説明を決して見ません。見るのはコミットとタスク名だけで、そこに自分の道具を走らせます。
仕組みとしての実体
SwarmForge は、多くのチームがすでに持つプリミティブを、シェルと Babashka で束ねた harness です。各ロールは tmux のウィンドウで、.worktrees/ 配下の専用 git worktree に対してエージェント CLI を動かします。だから 2 つのエージェントが同じ作業ディレクトリに触れることはありません。振る舞いはプレーンテキストから来ます。他のすべてに優先すると宣言し、起動時と毎タスクで swarmforge/constitution/articles/ のすべてのファイルを読んで従えと指示する constitution.prompt、そして swarmforge/roles/<role>.prompt のロールプロンプトです。共有の記事がエンジニアリング規則・ハンドオフ規則・ワークフローを担い、ローカルの記事でプロジェクトがそれを上書きします。通信は daemon が所有するファイルベースのキューで、エージェントが送れるメッセージ型は git ハンドオフとノートの 2 つだけです。./swarm スクリプトは薄いブートストラップにすぎず、ディレクトリが無ければスクリプトのアーカイブを取得し、あとは swarmforge/scripts/swarmforge.sh に引き渡します。
3 つの群れの形
各ブランチは「そのタスクにどれだけのプロセスが必要か」への異なる答えです。main はドキュメント用で、動くトポロジーは pack ブランチにあります。流れはキューではなくリングです。
two-pack
coder → cleaner → coder
テストファーストで書く coder と、片付け・CRAP と DRY のレビュー・構造修正を担う cleaner。書くことと judge することを分離した最小のループであり、通常業務でコストを正当化しやすい唯一の形です。
four-pack
specifier → coder → refactorer → architect → specifier
Gherkin の受け入れ仕様が先頭に入ります。refactorer が振る舞いを保ったまま整理してカバレッジを補い、architect が構造と依存の向きをレビューしてから、リングは再び仕様へ戻ります。
six-pack
specifier → coder → cleaner → architect → hardener → QA
コードを変異させてテストの盲点を探すハードニングのパスと、ユーザーインターフェース経由で検証する独立した QA ロールが加わります。6 ロールのうち 4 つがバッチモードで動き、ツールのコストを優先度帯全体で償却します。
1 つの変更が実際にリングを回る様子
これは six-pack です。職種の一覧ではなく、終了条件のパイプラインとして読むのが正解です。各行はリポジトリ内のロールプロンプトであり、各終了条件は成功しなければならないコマンドです。
specifier
→ coder- 受け取るもの
- 人間からの依頼。master worktree で受ける
- やること
- Gherkin の受け入れ仕様と、エンドツーエンド QA スイートの仕様を書きます。意図が曖昧なところは質問し、例のパラメータを、受け入れミューテーションに実際に影響する値だけに刈り込みます。
- 終了条件
- 人間が明示的に承認するまでコミットしません。これがリング内で唯一の人間ゲートであり、最も安い先頭に置かれています。
coder
→ cleaner- 受け取るもの
- コミットと安定したタスク名を指す git ハンドオフ
- やること
- 要求された振る舞いを表し、ロールプロンプトの言葉どおり「もっともらしい誤実装なら失敗する」ような焦点の絞られた単体テストを書きます。次に、それを通すのに必要な分だけの製品コードを書きます。生成された受け入れテストを単体テストの代用とすることは明示的に認められていません。
- 終了条件
- ローカル検証が通ること。ミューテーション・CRAP・DRY は走らせません。それらは後続ロールのもので、coder が自分の成果を採点できないようにするためです。
cleaner
→ architect- 受け取るもの
- 同一優先度のハンドオフのバッチ
- やること
- まず CRAP ツールを走らせて複雑度を 6 以下まで下げ、次に DRY ツールで重複を除き、次にミューテーションツールをスキャンと計数モードのみで実行して、変異箇所が 100 を超えるファイルを分割し、妥当な範囲でカバレッジを上げます。
- 終了条件
- 振る舞いは不変、テストは緑のまま、複雑度と重複が減っていること。ミューテーションテストの実行と振る舞いの追加は明示的に禁止です。
architect
→ hardener- 受け取るもの
- 整理済みコミットのバッチ
- やること
- 実質的な境界を持つモジュールへコードを分割し、依存を内向きに保ち、循環とフレームワークの漏れを狩り、アプリケーションのポリシーを UI・ファイルシステム・データベース・ネットワークから隔離します。実用的なら自動アーキテクチャチェックも追加します。
- 終了条件
- 振る舞いを保持し、スイートは緑。git merge の手動実行は禁止で、マージは ready_for_next.sh 経由のみです。
hardener
→ QA- 受け取るもの
- 構造レビュー済みコミットのバッチ
- やること
- 言語のミューテーションツールを 1 ファイルずつ、既存マニフェストに対する差分方式で、最大 8 並列ワーカーで実行し、生存ミュータントを片付けてから次へ進みます。続いて soft レベルの Gherkin 受け入れミューテーション、次に CRAP、次に DRY を、まさにこの順で実行します。
- 終了条件
- チェーン内の各ツールが綺麗になってから次が走ること。テストが本当に何かをテストしているのかを決めるロールです。
QA
→ specifier- 受け取るもの
- ハードニング済みコミットのバッチ
- やること
- 独立した最終検証。受け入れ仕様、API のショートカットを使わずユーザーインターフェースで駆動するエンドツーエンドスイート、単体テストとプロパティテスト、プロジェクトのリリースチェック。失敗はコードを変える前に必ず再現します。
- 終了条件
- 完了前に CRAP と DRY を再実行。QA スイートが Gherkin や単体テストと矛盾する場合は、勝者を決めずに停止して人間に問います。
異質なのは輸送層
多くのエージェント基盤はエージェント同士に会話させます。SwarmForge はそれを意図的に拒みます。配送は daemon が所有し、ファイルシステムがキューであり、tmux は待機中のウィンドウを突くためだけに使われます。
トポロジーは設定ファイル 1 枚
conf同梱の six-pack は全ロールを同じバックエンドに置き、権限バイパスを有効にし、リングの後半すべてをバッチ消費に指定します。ロール名はプロンプトのファイル名と一致しなければならず、このリポジトリでは hardender と綴られています。
# swarmforge/swarmforge.conf
# window-invisible <role> <agent> <worktree> [task|batch] [extra-cli-args...]
window-invisible specifier codex master --yolo
window-invisible coder codex coder --yolo
window-invisible cleaner codex cleaner batch --yolo
window-invisible architect codex architect batch --yolo
window-invisible hardender codex hardender batch --yolo
window-invisible QA codex QA batch --yolo キューはディレクトリであり、置き場所が状態
textデータベースもメモリ上のブローカーもありません。ハンドオフの木の中の位置がそのステータスで、ファイル名が優先度→時刻の順に並び、ヘッダーが監査履歴を担います。落ちた群れはディスクを読んで再開します。
.swarmforge/handoffs/
outbox/
tmp/ # drafts land here, then get renamed in atomically
sent/
failed/ # malformed or undeliverable, with diagnostics
inbox/
new/
in_process/
completed/
# filename sorts the queue for you
<priority>_<timestamp>_<sequence>_from_<sender>_to_<recipients>.handoff
# priority 00-99, lower first; UTC YYYYMMDDTHHMMSSZ エージェントは依頼できるだけで、配送はできない
shエージェントは 4 つのヘッダーだけの下書きを書き、ゲートスクリプトを呼びます。id、from、recipient、各種タイムスタンプは書けません。予約済みだからで、監査される側が監査履歴の出自を偽造できない構造になっています。SHA も打ちません。スクリプトがコミットを実在かつ一意な 10 文字のオブジェクトとして検証し正規化します。
# ./tmp/handoff.txt — drafted inside the assigned worktree
type: git_handoff
to: hardender
priority: 00
task: task-1-cave-setup
# hand it to the protocol gate; the daemon does delivery
swarm_handoff.sh ./tmp/handoff.txt
# receiving side, driven by the role's mode in .swarmforge/roles.tsv
ready_for_next.sh # -> TASK: / BATCH: / NO_TASK, plus the payload
done_with_current.sh # -> stamps completed_at, then pulls the next item hardener が通さねばならないゲート、その順序
shこれが群れを role-play 以上のものにしています。constitution は起動時にこれらのツールを著者自身のリポジトリから新規に導入します。複雑度は crap4go・crap4java・crap4clj、ミューテーションは mutate4go・clj-mutate・mutate4java、重複は dry4* 系。そして実行順はロールプロンプトが固定します。
# hardener: nothing advances until the previous check is clean
mutate4go ./... # one file at a time, differential, <= 8 workers
gherkin-mutator --level soft # mutate the acceptance examples too
crap4go ./... # complexity against coverage
dry4go ./... # duplication
# then, and only then
swarm_handoff.sh ./tmp/handoff.txt # to: QA 各仕組みがその形をしている理由
エンジニアリングとして読めば、奇妙に見える選択のほとんどは、エージェント特有の失敗モードに対する防御です。
メッセージは説明ではなくコミット
git ハンドオフが運ぶのはタスク名と検証済みコミットです。「このコードが良い理由」という著者の主張は運べません。主張は次のエージェントに同意を促してしまうからです。コミットは代わりに検証を促します。このプロジェクトで最も移植しやすいアイデアです。
起こし通知は汎用で、失われてもよい
daemon の tmux 通知は「メールが届いた、待機中なら ready_for_next.sh を実行せよ」だけを伝えます。ファイル名は決して挙げないので、エージェントが面白そうな項目を選んでキュー順を飛ばすことはできず、忙しいエージェントは安全に無視できます。タスク完了時にも次を取りに行くからです。
ノートは 80 文字上限で、しかも推奨されない
エージェントが自由記述のノートを送れるのは、人間・ロールプロンプト・constitution が明示的に指示したときだけです。曖昧さや矛盾に直面したときの指示は、停止して人に尋ねること。これはエージェント同士に要求を交渉させることへの意図的な拒否であり、マルチエージェント構成が静かに壊れるのはまさにそこです。
各ロールにはブランチではなく worktree
分離はファイルシステムのレベルなので、2 つのエージェントが同じファイルを同時に編集するという障害の系統がそもそも起こりえません。作業中の各ロールを独立に検査できることも、群れが何をしたのか調べようとすると想像以上に効いてきます。
リングの後半はバッチで消費する
cleaner、architect、hardener、QA は同一優先度のハンドオフをまとめて 1 単位として受け取ります。ミューテーション実行、カバレッジ実行、アーキテクチャチェックは起動 1 回あたりが高価でファイル 1 つ追加は安価なので、バッチ化は「回すゲート」と「無効化されるゲート」の分かれ目になります。
標準は優先順位が明示されたプロンプトの木
constitution.prompt が権威を主張し、記事が規則を持ち、ローカル記事がプロジェクト向けに上書きし、その上にロールプロンプトが載り、エージェントは毎タスクで全部を読み直すよう指示されます。コーディング標準は仕事についての文書ではなく、仕事への入力になります。
結論
SwarmForge の価値ある半分は constitution とゲートの順序です。単一責務の名前付きロール、実行可能なコマンドである終了条件、そして「変更の著者はそれを採点しない」という硬い規則。この半分は本当に優れており、精神においては言語非依存で、いま使っている CI に今四半期のうちに実装できます。tmux は一切要りません。もう半分、daemon と永続ファイルキューは美しく作られていますが、大半は回避できる問題を解いています。ゲートをプルリクエスト上の CI で走らせるなら、永続性・監査履歴・優先度順は、チームがすでに運用している道具から無料で手に入ります。
採用すべきプラットフォームではなく、ワークフローのリファレンス実装として読んでください。まず two-pack でロール分割が自分たちの仕事に効くかを体感し、ゲートのチェーンはいずれにせよ借用し、6 ロールのリングに手を伸ばすのは、欠陥の費用が 1 変更あたり 6 回のエージェント実行を明らかに上回るときだけにしましょう。
優れている点
- + 品質ゲートがスタイルガイドの形容詞ではなく、しきい値を持つコマンドである(ミューテーション、CRAP、DRY、カバレッジ)
- + レビュアーは著者の推論を決して見ず、コミットだけを見る。エージェントのレビューに価値が生じる唯一の方法である
- + 順序が現実のエンジニアリングの並びと一致する。仕様化、実装、整理、再構築、ハードニング、独立検証
- + worktree による分離が、ロックではなく構造によって同時編集の破損を消している
- + キューの状態はディスク上にあり、監査履歴はエージェントが構造上偽造できない。だからクラッシュから再開でき、実行を再構成できる
- + 唯一の人間承認ゲートが仕様策定時、つまり考えを変える費用が最も安い位置にある
- + すべてが観測可能なプレーンテキスト。読めるウィンドウ、編集できるプロンプト、ls で一覧できるキュー
支払う代償
- − 同梱の設定は全エージェントを権限バイパスで動かす。つまりこの設計全体が、6 つのエージェントに無人でリポジトリ内のコマンド実行を許す前提に立っている
- − 1 変更あたり 6 回のエージェント実行は小さな作業には経済的に不合理で、しかも「このタスクはもっと軽いプロセスでよい」と判断する仕組みはリングにない
- − 実行可能なツールチェーンは著者自身の crap4*・mutate4*・dry4* プロジェクトで、対象は Go・Clojure・Java。これ以外の言語では constitution の起動時の契約が成立せず、等価物は自分で用意することになる
- − それらのツールを毎回 GitHub から新規に入れ直すのは遅く、ネットワーク依存で、しかも自分が背負うサプライチェーンの面になる
- − macOS 上の zsh・tmux・Babashka が幸福な道。Windows は WSL とターミナルアダプタの当て板が必要
- − 転送規則により、ロールは何も変えていなくても下流へ送らねばならない。段が実質何もしなかった場合でもリングはトラフィックを生む
- − ロールプロンプトは強制ではない。自分のゲートを飛ばすのを止めるものは「飛ばすな」と書いた一文だけで、本当の保証は CI にある複製の強さしかない
- − 見た目にも進行中。ダッシュボード、ヒートインジケータ、ウィンドウ watchdog、分岐した pack ブランチがあり、main は意図的に動かない
動かさなくても借用すべきもの
著者に成果を採点させない
- - 品質ツールは、コードを書いた工程とは別の工程、別のコンテキストで走らせる
- - レビュー工程に渡すのは diff とツールであり、著者の言い分ではない
- - エージェントのワークフローではこれは作法ではなく、レビューとゴム印の違いそのものである
すべてのゲートを終了コードにする
- - 複雑度、重複、カバレッジ、生存ミュータントには、いずれも非ゼロを返すツールがある
- - 実行順を固定し、最初に失敗したところでパイプラインを止める
- - エージェントは失敗したコマンドには正しく反応し、助言の段落には曖昧に反応する
ハンドオフは狭く、検証付きで、監査可能に
- - コミット参照と短い 1 行が、意図をコードとメッセージへ押し込む
- - 境界で検証し、壊れた依頼が次段の実行 1 回を無駄にする前に落とす
- - 監査履歴に意味を持たせたいなら、出自のフィールドは送信者の手が届かない場所に置く
標準は仕事が起こる場所に置く
- - プロンプトの記事として書かれた規則は毎タスク読まれる。誰も開かない wiki ページとは違う
- - 共有規則とプロジェクト固有の上書きを分け、あるチームの例外が全体の規則にならないようにする
- - 規則をコードと一緒にバージョン管理し、その変更もコードと同じようにレビューする
ワークフローこそが貢献
tmux も Babashka も tarball インストールも取り除けば、ソフトウェア工学についての 1 つの主張が残ります。コードを住みやすく保つ規律は分離でき、それぞれが自分の指示を持つ自分の番を与えられるべきで、そのどれもコードを書いた当事者が信頼できる形では実行できない、という主張です。これはエージェント以前から真でした。エージェントが変えたのは賭け金です。出力量は増え、レビューする人間は速くなっていません。
だから翻訳に耐える部分を持ち帰りましょう。各パスに名前を与え、1 つの仕事だけを持たせる。すべての終了条件をコマンドにする。人間のゲートを仕様策定時に置く。変更の著者には、その判定における役割を一切与えない。そのパイプラインが 6 つの tmux ウィンドウか、2 人の技術者か、順序付き 5 ジョブの CI ファイルかは、ゲートが存在して実際に走るかどうかに比べれば、はるかに小さな問題です。
関連するエンジニアリング記事
hardener と cleaner のロールは 2 つの実践の上に成り立っています。エージェントが書いたコードを judge するなら、なおさら個別に理解する価値があります。
よくある質問
SwarmForge を動かすには何が必要ですか?
zsh、git、tmux、Babashka に加えて、Claude・Codex・Copilot・Grok などの設定済みエージェント CLI です。クラウドサービスも立ち上げるべきオーケストレーション層もありません。群れは目で追える tmux のウィンドウ、ディスク上のロールごとの worktree、そしてテキストファイルのキューです。
チームはどのブランチから始めるべきですか?
two-pack です。書くことと judge することの分離が自分たちの仕事に効くかを知るにはロール 2 つで足り、それが分かる前に 6 ロールのリングの費用を正当化するのは非常に困難です。main はドキュメント用で、群れは動きません。
権限バイパスでエージェントを動かして安全ですか?
この設計が残す最大の運用上の問いです。同梱の設定は全ロールにバイパスのフラグを渡し、それが無人のリングを成立させています。試すなら使い捨てのクローンか、資格情報のないコンテナで行い、本当の品質ゲートは群れが飛ばせない CI に置いてください。
Go・Clojure・Java 専用ですか?
オーケストレーションは言語非依存ですが、実行可能なゲートはそうではありません。constitution が名指しするのは、その 3 言語向けの著者自身のミューテーション・CRAP・DRY ツールです。他のスタックではロール構造を保ち、等価物に差し替えます。ミューテーションなら Stryker や PIT、CRAP の計算なら複雑度とカバレッジのレポートで足ります。
エージェント群があれば QA は不要になりますか?
なりませんし、この設計もそう主張していません。QA を実行可能なスクリプトを持つ名前付きロールへ昇格させ、QA スイートが仕様と矛盾したら停止して人間に尋ねる規則を明示しています。製品がユーザーに何を負っているかを知る人は依然として必要で、リリースを承認する人も依然として必要です。
最も真似する価値のある 1 つのアイデアは?
コードを書いたエージェントはそのコードの judge として最悪であり、その処方は終了コードを持つツールを備えた別コンテキストである、ということ。リポジトリの他のすべては、この一文の実装詳細です。