Live Forking:同じタスクを並行して複数の道で走らせ、最良を選ぶ
本書は利用シナリオ(いつ使うべきか、いつ使うべきでないか)を扱います。仕組みとたとえ話は技術解説 28-live-forking.md を、完全な設計は RFC-26 を参照してください。
Live Forking は、実行中のタスクをその場で N 個の競合ブランチに分裂させます。各ブランチは別々のアカウント、独立したワークスペースのコピー、それぞれの予算で走り、走り終えたら AI ジャッジ(あるいはあなた自身)が最良の1本を選んでマージし戻します。デフォルトはオフで、エージェント単位に agent.toml [fork] enabled = true で有効化します。
一言で言う違い:普段はタスクが1本の道を進み、間違えたらやり直す。fork をオンにすると、ひとつのタスクが同時に複数の道を進み、どれが良いかを直接比較できます。
ブランチとは何か
Section titled “ブランチとは何か”DuDuClaw のエージェントは claude CLI のサブプロセスとして動くため、「ブランチ」1本は隔離されたサブプロセス実行1回であり、以下を持ちます:
- 自分のワークスペースオーバーレイ(copy-on-write:親ワークスペースは読めるが、書き込みは自分のコピーだけに落ち、互いを汚染しない)
- 自分のアカウント(AccountRotator が別々のアカウントを割り当てるため、ブランチ同士が同じ rate limit にぶつからない)
- 自分の予算上限と任意のステアリングメッセージ(steering:このブランチにどの方向を試すかを伝える)
- 親ワークスペースへの読み取り専用の共有ビュー
各ブランチは走り終えた後、任意で test_command(例:pytest -q)を実行でき、その exit code がジャッジの採点に使われます。
使うべき3つのシナリオ
Section titled “使うべき3つのシナリオ”シナリオ1:複数案を並行させ、最良を選ぶ
Section titled “シナリオ1:複数案を並行させ、最良を選ぶ”ひとつの問題に妥当な解法が複数あり、どれが良いか確信が持てない。1つずつ試して失敗したら戻るより、3本のブランチを一度に開いてそれぞれ別の戦略を走らせ、結果を比較する方が良い。
典型例:「この遅いクエリ、1本はインデックス追加、1本は JOIN の書き換え、1本はキャッシュ追加を試し、実測で最速のものを採用する。」各ブランチは異なる steering を受け取り、ジャッジはテスト通過率と品質で採点し、merge_mode = "auto_with_fallback" は勝者を自動選択しつつ確認ゲートを1つ残します。
シナリオ2:高リスクの変更を、まずブランチの中で試す
Section titled “シナリオ2:高リスクの変更を、まずブランチの中で試す”間違えると厄介なもの(大規模リファクタリング、コア設定の変更、破壊的マイグレーション)を動かす前に、実際にどう変わるのかを見てから着地させるか決めたい。
ブランチの copy-on-write オーバーレイはまさにこのためにあります:ブランチの書き込みはすべて自分のコピーに落ち、親ワークスペースはマージ前に一文字も変わりません。失敗したらそのオーバーレイを捨てれば親は無傷のまま。うまくいったときだけ勝者の書き込みをマージし戻します。失敗した試みがメインラインに一切触れないため、「先に commit してから revert」よりクリーンです。
シナリオ3:AI ジャッジによる評価
Section titled “シナリオ3:AI ジャッジによる評価”「複数の結果から最良の1つを選び、なぜそれを選んだか説明できる」ことが必要で、「結果が出た」だけでは足りない場合。
ジャッジは JudgeVerdict を生成し、信頼度スコアは RFC-26 の式で計算されます:quality_spread·0.4 + test_pass_ratio·0.4 + internal_consistency·0.2。これはまさに会議 §15 で問われたシナリオです:1つのエージェントが複数の結果を出した後、別のエージェントを評価者として派遣する。fail-closed は意図的です:ジャッジが存在しない、判定が parse できない、sandbox が起動しない場合はすべて manual に退避し(全ブランチをあなたに提示します)、黙って適当に1つを選ぶことは決してありません。
使うべきでないとき
Section titled “使うべきでないとき”Fork はデフォルトで開けておくものではありません。以下の場合は使わないでください:
- 決定的な単一タスク:答えが1つしかなくトレードオフの余地がない(フォーマット変換、単純な照会)。ブランチを開いても N 倍のコストを無駄に燃やすだけです。
- コストに敏感:ブランチ N 本 = アカウント N 個、予算 N 個分。サブスクリプション枠や API 費用が逼迫しているとき、fork は消費を増幅します。
[fork] max_branchesとaggregate_budget_usdはハードキャップですが、根本の問いはこのタスクに並行化の価値があるかどうかです。 - 採点の根拠がない:
test_commandが空だと、ジャッジの式のtest_pass_ratioは中立化され、採点は品質と一貫性だけになり、選抜の客観性が落ちます。実行できるテストがないタスクでは、fork の価値は主にシナリオ2(隔離した試行錯誤)にあり、シナリオ1(客観的な選抜)にはありません。 - プロセスをまたいでブランチを強制停止したい:
terminate_branchは同じプロセス内のサブプロセスしか停止できません。別プロセスのブランチサブプロセスを殺すことは、RFC-26 が明記した by-design の除外項目です。
duduclaw eval との関係
Section titled “duduclaw eval との関係”どちらも「AI ジャッジ」を使いますが、用途は正反対です。混同しないでください:
| Live Forking | duduclaw eval |
|
|---|---|---|
| タイミング | 実行時、タスクが走っている最中 | 事後 / CI、オフライン回帰 |
| 目的 | 複数の道からその場で最良の1本を選んで進む | 固定のゴールデンタスクでエージェントが退行していないか検証する |
| 入力 | 生きているタスク1つ + N 種の戦略 | evals/<suite>/<case>.toml の事前記録ケース |
| 出力 | 勝者ブランチをワークスペースにマージ | JSON レポート + 非ゼロ exit で PR をブロック |
実装上、duduclaw eval の LLM ジャッジは duduclaw-fork のジャッジプリミティブを再利用しているため、評価ロジックは同じものです。覚え方:fork は前方への偵察、eval は後からの検収。eval の使い方は evals ガイド を参照してください。
設定とツール
Section titled “設定とツール”agent.toml:
[fork]enabled = false # デフォルトはオフ。エージェント単位で有効化max_branches = 4 # ブランチ数のハードキャップ(アカウント/枠の爆発を防ぐ)default_budget_usd = 0.50 # ブランチごとの上限aggregate_budget_usd = 1.50 # 全ブランチ合計の上限merge_mode = "auto_with_fallback"test_command = "" # 任意。空 ⇒ ジャッジの test_pass_ratio が中立化test_timeout_s = 120MCP ツール(エージェントが [fork] enabled = true を設定したときだけ登録され、すべて Scope::ForkExecute でゲート、fail-closed):
| ツール | 何をするか |
|---|---|
fork_run |
現在のタスクを N 本のブランチに分割 |
inspect_branches |
生きているブランチ + 状態 + 支出を一覧 |
diff_branches |
2本のブランチ間のファイル/出力の差分 |
merge_or_select |
fork を収束させる(ジャッジ判定またはあなたの指定) |
terminate_branch |
暴走したブランチを停止 |
fork_cost |
合計とブランチごとの支出 |
fork の収束はすべて ~/.duduclaw/fork_history.jsonl と Activity Feed に記録され、ダッシュボードには可視化用の ForkPage があります。
Live Forking は、トレードオフがあり、リスクがあり、比較が必要なタスクに向いています。決定的なタスク、コストに敏感なタスク、採点しようのないタスクには向きません。オンにする前にひとつ自問してください:このタスクで、並行して複数の道を走らせて得る品質は、数倍の出費に見合うか。