ハーネスレーシング
最初に 2 つのハーネスを同じ概要で競わせるとき、Codex と Claude Code のどちらが自分のコードベースに強いかが決められないという理由で行うでしょう。2 回目は、Aider が 40% 速くて diff も綺麗だったから — どのハーネスがどの種類のタスクで勝つかを知りたくなる。10 回目には、推測するより安いから競わせています。
SprintLoop における ハーネス は、概要を実行するエージェントランタイムです: Claude Code、Codex CLI、Cursor Compose、Aider、Devin、または harness adapter API 経由で接続する任意のハーネス。レーシング とは、同じ概要を兄弟レーン内で複数のハーネスに並列ディスパッチし、すべてに走らせ(あるいは最初の sign-off で止まり)、雰囲気ではなく diff comparator で勝者を選ぶことです。
なぜそもそも競わせるのか
真面目なコスト分析を生き延びる 3 つの理由:
- 品質。 ハーネスごとに違うミスをします。Claude はコミットメッセージで過剰説明し、エッジケースのテストが薄くなる傾向。Codex はコメントが少なく、リファクタが過剰になる傾向。Aider は速くて外科的だが、曖昧な概要では停滞する。winner picker はそうしたスタイルの違いを気にしません — diff サイズ、テストカバレッジの差分、lint pass、Review Committee の判定で採点します。重要なランでフィールドのベストを得られます。
- 速度。 レーシングディスパッチは、最初のハーネスがフロア(CI green、ブロッカー判定なし)を超える diff を出した時点で完了します。並列な作業では、ハーネスを直列に走らせ片方が失敗したらフォールバックするより、通常 30–50% 速くなります。
- コスト抑制。 直感に反するのはここです。レーシングは N 倍のコストになると思いますよね。実際は 2 位のハーネスは予算の大半を使う前に殺されます — 我々のテレメトリで cancel された中央値のレーンは、勝者のトークンの 18% しか使いません。よって 3 ウェイレースは通常、単一ディスパッチの 1.4–1.6× で、3× にはなりません。
レーシングに反対する立場は、概要が瑣末(「この変数をリネーム」)なときや、特定の種類の作業で 1 つのハーネスを信頼するとき(「このリポジトリの小さなリファクタは常に Aider が勝つ」)には無駄だ、というものです。それで問題ありません — レーシングはディスパッチごとに opt-in で、ワークスペースはどの概要を競わせたか、競わせなかったかを覚えています。
comparator がどう勝者を選ぶか
レース内で終了した各レーンは スコア と共に exit します。スコアは以下の線形結合です。
| シグナル | ウェイト | ソース |
|---|---|---|
| CI green | 0.30 | GitHub / GitLab status checks |
| Reviewer verdict | 0.25 | Review Committee (Architect, Security, QA) |
| Diff size delta | 0.15 | 概要見積もりに対する LOC 追加/削減 |
| Test coverage delta | 0.15 | カバレッジツール出力 (jest, pytest, go test) |
| Lint clean | 0.08 | リポジトリが宣言する linter |
| Wall time | 0.07 | First-to-finish ボーナス (90 秒で減衰) |
ウェイトはワークスペースごとに Settings → Racing から設定できます。上記のデフォルトは、約 14,000 レースにわたる 6 か月の内部テレメトリでチューニングされています。規制業界に出荷するチームは通常、reviewer verdict のウェイトを上げ、diff size のウェイトを下げます。
comparator は、レース内の最初のレーンが「ready for review」を合図した時点で走ります。タイ(5% 以内)は picker を表示します — 人間のディスパッチャーが side-by-side diff ビューを得て選びます。タイバンドの外側は勝者を自動昇格し、負けた兄弟をキャンセルします。
何がキャンセルされ、何が残るか
comparator が勝者を選ぶと、兄弟レーンは canceled に遷移し、スコープクレームは即座に解放されます。彼らの tool log と署名済みエントリは監査台帳に永久に残り — 紙の跡なしのレーシングは最悪の無駄なので — キャンセルされたレーンの diff を後で開いて、敗者が試したことを確認できます。
キャンセルされた兄弟について 2 つ知っておくこと:
- 彼らのコミットは push されません。 キャンセルされたレーンは PR を開きません。ブランチは SprintLoop ワーカー上でローカルに存在し、アーカイブされ、タグ付けしない限り 30 日で purge されます。
- 彼らのツールコールとモデル消費は請求に残ります。 キャンセルが防ぐのは 新規 のトークン消費で、すでに消費されたものの遡及回収ではありません。だから comparator の first-to-finish ボーナスが効いてきます — 速い敗者は遅い敗者より安い。
よくあるレースと使いどころ
頻繁に見るレースのセット:
- 機能実装で Claude Code vs. Codex。 非自明な作業のデフォルト。2 つのハーネスには意味のある強みの違いがあり — Claude はアーキテクチャに、Codex はタイトでイディオマティックな実装に — comparator が綺麗にタイを破ります。
- 小さなリファクタで Aider vs. Codex。 機械的な作業と分かっているとき、Aider の小さな surface area が速さで勝つことが多く、Codex がリファクタがドリフトしていないかの sanity check を提供します。
- やっかいなバグで 3 ウェイ。 Claude Code、Codex、Cursor Compose。控えめに使う — 通常、単一ハーネスのディスパッチがすでに失敗した後。
- 1 つのハーネス、2 つのプロンプト。 同じハーネス、違う概要。主にプロンプトエンジニアリングの実験に使います — 役立ちますが、勝つプロンプトを選んだら止めるべきです。
実際に見るコスト
200 行の機能に対する 3 ウェイレースは、現在のモデル価格で典型的に $0.40–$1.20 のレンジに収まります — 競わせるハーネスと maxTokens 設定の積極性によります。負けレーンは勝者の CI シグナルから数秒で comparator に殺されるので、トークン消費の long tail は bounded です。
ワークスペース設定には日次レーシング予算が含まれます。超過すると、以降のレースは単一ハーネスディスパッチに degrade し、バナーを表示します。これは soft control で — インラインでオーバーライドできます — デフォルトを残したまま誰もが概要をレース化する暴走ループから何度かチームを救ってきました。
最初のレースのセットアップ
Cmd+N でディスパッチダイアログを開きます。ハーネスピッカーの下で Race をトグル。2 つか 3 つのハーネスを選びます(それぞれにキーが必要 — Get started を参照)。ワークスペースに予算上限があれば設定。Dispatch。
ディスパッチは N の兄弟レーン ID を返します。各々が Lanes パネルで自分のカードとしてレンダリングされ、カードは視覚的に “Race” ヘッダの下にグループ化され、ライブの勝者表示が付きます。どのカードをクリックしても、そのレーンの tool log と diff にドロップインできます。
勝者が選ばれると、レースヘッダは勝者のレーンカードに collapse し、残りは “Canceled siblings” disclosure にアーカイブされます。後でクリックして任意のレーンを inspect できます。