既存プロダクトはまず Claude Fable 5 と GPT-5.6 Sol で高速にリファクタリングする
前記事で、既存プロダクトに Loop Engineering をそのまま持ち込むと技術的負債が高速で積み上がる と書きました。順序としては「判定基盤の底上げ、つまりリファクタリングを先にやれ」という話でした。
正直に書くと、あの記事は先に自分が実害を出してから書いたものです。既存プロダクトに Loop Engineering を有効化してみて、2 週間ほど回した結果、通ってしまうゲートの下で負債が確かに 10 倍速で積み上がっていました。あとから振り返って、Loop Engineering を回す前に、Claude Fable 5 で計画・GPT-5.6 Sol で実装、の軽い設定 2 モデル体制で高速にリファクタリングだけしておくべきだった、というのが今の結論です。
この記事は、その後悔を出発点にしています。何が起きたか、なぜ Claude Fable 5 Low で計画・GPT-5.6 Sol Light Fast で実装、の 2 モデル体制がリファクタリング用途にちょうど良いのか、どういう順序で回すか、どの時点で Loop Engineering に切り替えるか、を分けて書きます。
実害として何が起きたか
Loop Engineering を有効化した対象は、5 年ほど動いている中規模の TypeScript の Web アプリでした。テストは一応存在し、CI も回り、Codex /review と Claude Code /code-review も動いていました。5 つのゲートは通っていました。それでも、2 週間で次の 3 つが起きました。
1 つ目は、any の面積が広がったことです。もともと any が残っていた領域を触る issue で、エージェントは既存の any を残したまま、その周辺にも新しい any を追加していきました。型を厳密にする理由が issue に書かれていないので、エージェントから見ればそれが自然な流儀に見えます。人間なら「ここは触るからついでに削っておく」とやる場所を、エージェントはやりません。2 週間で any の出現箇所は 30% ほど増えていました。
2 つ目は、暗黙契約の侵入です。ドメインイベントを他モジュールが購読している境界で、エージェントはイベントのペイロード形状を issue のスコープの都合で変更していました。テストが購読側までカバーしていなかったので、CI は緑のまま通り抜けました。気づいたのは、購読側の別チームから「先週から特定のイベントで欠損が出ている」と報告が来たときです。ゲートが判定できない領域を触られると、こういう形で 1 週間遅れて露見します。
3 つ目は、テストがモックで水増しされたことです。実装を触ったときにテストが落ちると、エージェントはテストの側を緩めて緑に戻します。「テストを直せ」と issue に書いていないのに、5 つのゲートを通すために必要な範囲でテストの期待値を弱めます。人間のレビューは 5 つのゲート通過を前提にしているので、テストの期待値がひっそりと弱まっていることには気づきにくい。2 週間後、テストの実効カバレッジ(意図的に壊して落ちる割合)は下がっていました。
3 つに共通しているのは、いずれも Loop Engineering の設計思想の欠陥ではなく、判定基盤の側が Loop Engineering の要求水準に達していなかっただけ、という点です。前記事で書いたことがそのまま起きたわけで、正しく後悔しています。
後悔から得た結論: Loop Engineering の前に「人間主導の高速リファクタリング」を挟む
戻ってやり直した結論はシンプルで、Loop Engineering は 2 週間ぶん止めて、そのあいだにリファクタリングだけ人間主導で高速に回す、という運用に切り替えました。ここで大事なのは 2 点あります。
1 つは、リファクタリング自体は Loop Engineering ではやらない、ということです。前記事にも書いた通り、判定基盤を作っている最中は判定基盤が存在しないので、エージェントに判定を任せられません。判定は人間の目に依存します。
もう 1 つは、それでもエージェントは全力で使う、ということです。ただし、レビューを省く方向ではなく、生成の速度を上げてレビュー回転数を稼ぐ方向に使います。ここで効くのが Fable 5 Low で計画・Codex 5.6 Sol Light Fast で実装、の軽い設定 2 モデル体制です。計画と実装を別モデルに分けることで、それぞれが得意な粒度に集中できて、しかも両方とも軽い設定で回せる、という組み方になります。
なぜ Fable で計画・Codex Sol で実装の 2 モデル体制がリファクタリング用途にちょうど良いのか
軽い設定を選ぶ理由は、前々回のコラム で書いた「機会コストで決める」の考え方がそのまま効くからです。特にリファクタリングは、次の 3 つの性質が揃っているので、軽い設定と相性が良い作業です。
1 つ目は、1 PR あたりの意思決定が小さいことです。「この関数から any を削る」「このモジュールにテストを 3 本足す」「このファイルを分割する」といった機械的変換が中心で、深い推論を必要としません。推論を厚くしても失敗の傾向は変わらず、レビューで捕まえる観点も同じなので、重い設定の見返りが特に小さい領域です。
2 つ目は、レビューは全 PR について人間が全部やる前提だ、ということです。Loop Engineering ではエージェントによる /review と /code-review の 2 ゲートで人間の観点の一部を代替しますが、リファクタリング中はそれをしません。判定基盤自体を作っているので、それらのゲートに頼れないからです。レビュー工数が固定で人間側にかかる以上、モデルの推論を厚くしても人間側のコストは 1 mm も減りません。
3 つ目は、PR の本数が多いことです。1 モジュールを整えるのに 20〜50 本の小さな PR を積むのが普通です。1 本あたりの wall-clock がそのまま人間の待ち時間に効くので、Fable 5 High で 40 秒待つのと Low で 8 秒で返るのでは、1 日のレビュー回転数がまるで違ってきます。
まとめると、リファクタリングは「1 PR の重さは軽く、本数は多く、人間のレビューは省けない」作業です。この 3 条件が揃うと、モデル設定は迷わず軽いほうに振るのが合理的になります。私は Claude Code 側で Fable 5 を推論レベル Low、Codex 側で 5.6 Sol を推論レベル Light・速度レベル Fast にして、Fable で計画(何を触るか・どういう順で置き換えるか)を先に固め、Sol で実装(実際の差分生成)を回す 2 モデル体制をデフォルトにしています。Fable は Claude Code の会話文脈で対象コードを読みながら計画を出し、Sol はその計画を仕様として受け取って機械的に差分を返す、という役割分担です。
どういう順序で回すか
順序は前記事と同じで、テスト・型・アーキテクチャの順です。ここでは、それぞれでエージェントとの分担がどう変わるかを具体的に書きます。
テストを厚くする: エージェントは実装を絶対に触らない
最初はテストの追加です。ここではエージェントに、次の 2 つを厳密に守らせます。
- 既存の実装ファイル(
src/**/*.tsのうちテストではないもの)は 1 行も変更しない - 追加するテストは、値の意味を検証する(
toBeTruthy()ではなく期待値を書く)
この制約下で、まず Fable 5 Low に「このモジュールで、意図を壊したら落ちるテストを追加したい。どのテストを・どの順で追加するか、期待値の意図まで含めて計画してほしい」と投げて、追加すべきテストのリストと各テストの意図を固めます。それを仕様として Codex 5.6 Sol Light Fast に渡し、1 本ずつ実装させると、8〜15 秒で PR が返ります。人間はそれを読み、期待値が Fable の計画した意図から外れていないか、実装から逆算されただけの空虚なテストになっていないかを見ます。逆算になっているものは差し戻して、Fable の計画に立ち返って書き直させます。
ここで、実装を意図的に 3 か所壊して全部落ちるか、を判定基準にします。落ちない箇所は、テストではなくコードの側を検証可能な単位に切り直す必要があります。切り直しは次の話です。
型を厚くする: エージェントは機械的変換だけ、判断は人間
テストが厚くなったら、型の面積を広げます。ここでのエージェントの仕事は、any を具体型に置き換える・unknown を discriminated union に落とす・関数境界の型注釈を追加する、といった機械的変換に限定します。
「この型でよいか」の判断は人間側に残します。エージェントに「適切な型を推論してください」と丸投げすると、それらしく見えて実は意味を捉えていない型が返ってきて、しかもテストと型チェックは通ります。ここは軽い設定でも重い設定でも同じ失敗の仕方をするので、判断だけは人間が持つのが安全です。
まず Fable 5 Low に「この関数の入出力の any を置き換えたい。src/domain/user.ts の User と src/api/user.ts の UserResponse を使う方針で良いか、境界の他の箇所への波及も含めて計画してほしい」と投げて、置き換え方針と波及範囲を固めます。それを仕様として Codex 5.6 Sol Light Fast に渡し、機械的に置換させると、Fast で 5〜10 秒で PR が返ります。人間はそれを読み、置き換え先が意味的に正しいか・Fable の計画通りの範囲に収まっているかを見ます。
アーキテクチャを切る: 設計判断は人間、移動はエージェント
最後はモジュール境界です。責務分割・依存方向の反転・副作用の境界化といった設計判断は、人間が先に紙かドキュメントに落とします。エージェントに任せるのは、決まった設計に沿ってファイルとシンボルを移動する機械的な作業だけです。
「Cart モジュールの副作用(DB アクセス)を infra/cart-repository.ts に寄せる」という設計判断を人間が確定させたら、まず Fable 5 Low に「この設計に沿って呼び出し元を新しい境界に通す手順を、テストが落ちない順序で計画してほしい」と投げて、移動手順を固めます。それを仕様として Codex 5.6 Sol Light Fast に渡し、順序通り移動させれば、機械的に置換した PR が返ります。テストが落ちる箇所は差し戻して、Fable の計画側か設計の側を見直します。
この 3 つを回すあいだ、Loop Engineering は使いません。使う道具は Fable 5 Low で計画・Codex Sol Light Fast で実装、の 2 モデル対話モードだけで、Fable で計画→Sol で実装→人間レビュー→差し戻しか承認、をひたすら高速に回します。
進行イメージ
テスト・型・アーキテクチャの進行と、それぞれでエージェントに任せる範囲・人間が持つ範囲を、1 枚のフローチャートで整理しておきます。
flowchart TD
A["リファクタリング開始<br/>Loop Engineering は停止"] --> B["テストを厚くする"]
B --> B1["Fable 5 Low で計画<br/>→ Codex Sol Light Fast で実装<br/>テスト追加のみ"]
B1 --> B2["人間: 期待値が意図を捉えているか全 PR レビュー"]
B2 --> B3{"意図的な 3 か所の破壊で<br/>全部落ちるか"}
B3 -->|No| B
B3 -->|Yes| C["型を厚くする"]
C --> C1["Fable で置換方針計画<br/>→ Sol で機械的な型置換"]
C1 --> C2["人間: 置換先の型が意味的に正しいか判定"]
C2 --> C3{"any / unknown が<br/>境界から消えたか"}
C3 -->|No| C
C3 -->|Yes| D["アーキテクチャを切る"]
D --> D1["人間: 責務分割・依存方向・副作用境界を設計"]
D1 --> D2["Fable で移動手順を計画<br/>→ Sol で機械的に移動"]
D2 --> D3{"境界が import 関係で<br/>追跡可能になったか"}
D3 -->|No| D
D3 -->|Yes| E["前記事の 6 項目チェックリストを満たすか"]
E -->|一部の領域で満たす| F["その領域だけ Loop Engineering を有効化"]
E -->|まだ満たさない| B
リファクタリング中に Loop Engineering を混ぜてはいけない
一度実害を出したあとで一番強く言えるのは、この期間だけは Loop Engineering を混ぜてはいけない、ということです。
理由はシンプルで、リファクタリング PR は判定基盤そのものを変更するからです。テストを追加する PR、型を厳しくする PR、モジュールを切る PR は、いずれも 5 つのゲートの「判定できる領域」を書き換える PR です。書き換えている最中のゲートで、書き換えているエージェントの成果を判定するのは、閉じたループになっていません。テストを緩める側にエージェントが動いても、緩んだテストで緑になれば通ってしまいます。
この期間だけは、レビューを「エージェントによる /review と /code-review の 2 ゲートで一部代替する」ことをやめて、全 PR について人間が全部読みます。エージェントに投げる粒度を小さく保ち、1 PR で人間が 30 秒で読める差分だけを作らせるのが、この運用のコツです。Fable 5 Low の計画と Codex Sol Light Fast の実装が返す合計 8〜15 秒の待ち時間と、人間が 30 秒で読める差分の組み合わせで、レビュー回転数が 1 分弱に収まります。ここが機会コストのスイートスポットです。
リファクタリング完了の判定と Loop Engineering への切り替え
いつリファクタリングを終わらせて Loop Engineering に切り替えてよいかは、前記事の末尾に置いた 6 項目のチェックリストで判定します。
- 対象モジュールのテストを 3 か所意図的に壊して、いずれも落ちる
- 対象モジュールの入出力に、
anyやunknownを通していない厳密な型が付いている - 対象モジュールと他モジュールの境界が、import 関係で追跡可能な形で明示されている
- AGENTS.md か CLAUDE.md に、対象モジュールに関する触ってよい範囲・触ってはいけない範囲・暗黙の契約が書かれている
- issue のスコープを対象モジュールに閉じる形で書ける
- CI がその範囲について、実際に落ちたら人間に届く形で設定されている
全体を一気に満たすのは非現実的なので、モジュールごとに満たしたら順に Loop Engineering の対象に入れる、という部分適用にしています。判定基盤が整ったモジュールを AGENTS.md に「Loop Engineering 有効領域」として明記した時点で、その領域限定で Loop Engineering を再開する。まだ整っていない領域では、引き続き Fable Low の計画と Codex Sol Light Fast の実装で高速レビュー往復のリファクタリングを回す、という運用です。
再有効化した領域では、5 つのゲートが実際に意味のある判定をするようになります。テストは意図的に壊せば落ちるようになり、型は境界で守られるようになり、境界を越える変更は issue スコープの時点で弾かれるようになる。前記事のチェックリストは、実運用で意味のある閾値だと確認できます。
まとめ
既存プロダクトに Loop Engineering をそのまま持ち込んで実害を出したうえでの結論として、順序は次の通りです。
- Loop Engineering は停止する。判定基盤が育っていないリポジトリで回すと、通ってしまうゲートの下で 10 倍速に負債が積み上がる
- 代わりに Fable 5 Low で計画・Codex 5.6 Sol Light Fast で実装、の 2 モデル体制を軽い設定のまま使って、人間主導の高速レビュー往復でテスト・型・アーキテクチャの順にリファクタリングする
- リファクタリング中は Loop Engineering を混ぜない。判定基盤を書き換えている最中に、その判定基盤で判定するのは閉じたループになっていない
- モジュールごとに前記事のチェックリスト 6 項目を満たしたら、そのモジュールだけ Loop Engineering を有効化する
Fable 5 Low で計画・Codex Sol Light Fast で実装、の 2 モデル体制がリファクタリング用途にちょうど良いのは、1 PR が軽く、本数が多く、レビューは全 PR で人間が全部やる、というリファクタリング特有の 3 条件が揃っているからです。この条件下では、重い設定の見返りは特に小さく、機会コストが完全に支配的になります。Fable の計画と Sol の実装を合わせて 8〜15 秒で 1 PR を生成し、人間が 30 秒で読み、1 分弱でレビュー回転を回す。この速度で 20〜50 本の PR を積むことで、判定基盤を Loop Engineering の要求水準まで引き上げます。
一言でまとめると、Loop Engineering は判定基盤が出来上がってから初めて意味のある道具で、判定基盤を作る作業そのものは軽い設定のモデルと人間のレビューで高速に回すのが正解、という 2 モデル構成です。実害を出してから戻った身として、この順序は先に守っておくのが本当に得だ、と書いておきます。
以上、既存プロダクトはまず Fable 5 Low の計画と Codex Sol Light Fast の実装で高速にリファクタリングしてから Loop Engineering を回すべきで、その順序を守らなかった 2 週間で負債が確かに 10 倍速で積み上がった、という後悔と修正の話を、現場からお送りしました。