🧫

Claude Code や Codex をオーケストレーションして自動でレビュー FB ループを回して洗い物をしてる話

に公開2

はじめに

皆さんはもう AI コーディングツールを使っているでしょうか。Claude Code や GitHub Copilot、Cursor など、さまざまなツールが登場して、「AI がコードを書いてくれる時代」がやってきました。

私も例に漏れず、その恩恵に預かろうと意気揚々と AI コーディングを始めました。これまでの生活はプログラミングと家事の二本柱。

AI がコードを書いてくれるなら、プログラミングの時間が圧縮されて、自分の時間が増えるはず。溜まった洗い物や洗濯物を片付ける余裕が生まれるはず。そんな期待を胸に。

ところが現実は違いました。

AI がコードを書いている間、私は画面の前に張り付いていたのです。AI の出力をチェックし、軌道修正し、承認し、またチェックする。気づけば一日中 AI の相手をしていて、洗い物は溜まる一方。プログラミングに費やしていた時間が「AI のお世話」に置き換わり、家事の時間は「AI の後始末」に削られていました。

「洗い物がしたい」

これは冗談ではなく、切実な願いでした。この記事は、その切実な願いをどうやって叶えたかという話です。

私たちは AI のベビーシッターだ

なぜ AI コーディングで自分の時間が増えないのでしょうか。私の経験では、大きく3つの壁がありました。

まず、AI が出すコードの品質が安定しないという問題です。動けばいいという場当たり的なコードを平気で書いてきます。誰も頼んでいない後方互換サポートを勝手に入れたり、DRY(Don't Repeat Yourself、繰り返しを避ける原則)を無視してコピペでロジックを増殖させたり。「フォールバックしまくり」という表現がぴったりの、とにかく動かすことだけを目的としたコードが出てくるのです。

結局、人間が全行レビューしないと使えません。将来的にはレビュー不要になるかもしれませんが、いまはまだその段階ではないと言わざるを得ません。

次に、要件と違う方向に進みがちだという問題があります。指示を解釈違いして関係ない機能を作り始めたり、途中で軌道修正しても既に入った変更の巻き戻しが大変だったり。そもそも要件を満たしていないこともあります。「これじゃない」を伝えるコストが思いのほか高いのです。

そして、AI は頻繁に止まります。たとえばまだ許可を出していないツールを使うために、作業ディレクトリ外にでるために、「許可をください」というダイアログが出てくることもあります。1回の作業で何度も中断されるので、目を離すことができません(bypass permission で避ける方法もありますが、うーん……)。

こうして気づけば一日中 AI の面倒を見るのが仕事になっています。チェック、修正指示、承認、軌道修正の繰り返し。自分の作業に集中できる時間はなく、家事をやる余裕など生まれるはずがない。というか脳が焼ききれそうです。

これはまさに「ベビーシッター」ではないでしょうか。

どうすればいい?

この状況を打開するために、いくつかの選択肢を考えました。

ひとつめは「子守をやめる」です。AI に任せっぱなしにして、出てきたコードをそのまま使う。しかしこれでは動くけど保守できないコードが量産されます。要件と違う実装が紛れ込み、不自然なハックだらけのコードベースになる。長期的に見て破綻するのは目に見えています。

ふたつめは「AI を使わない」です。しかし周りはどんどん AI を活用しています。生産性の差は開いていく一方で、AI 時代に取り残されるリスクがあります。これもなかなか踏み切れません。

みっつめは「畑をたがやす」です。この職業に未来はないと見切りをつけて、まったく別の分野に転身する。でも本当にそこまでの話でしょうか。

どれもイマイチですよね。本当にこれしかないのでしょうか。

AI に AI の子守をさせよう

ここで発想を転換しました。

私たちがやっているベビーシッターの仕事で、一番時間がかかっているのは何でしょうか。それはコードレビューです。AI が書いたコードが要件どおりにできているか、不自然なハックが入り込んでいないか、それを逐一チェックしている。

ならば、このレビューを別の AI にやらせればいいのではないでしょうか。

書く AI とレビューする AI を分離して、AI 同士でフィードバックループを回す。人間がレビューする代わりに、Claude Code にレビューさせるのです。

「え、そんなことできるの?」と思われるかもしれません。また、「なぜ分離するの?」とも思うかもしれません。実はこの分離するというのが今段階の AI を取り扱う上では大事に思うのです。

Lost in the Middle と Context Rot

「分離」にはちゃんとした理由があります。LLM(大規模言語モデル)の特性を知ると、なぜ分けなければならないかが見えてきます。

LLM には「Lost in the Middle」という既知の問題があります。コンテキストの先頭や末尾にある情報はよく参照される一方、中盤に埋もれた情報は注意が薄れてしまうという現象です。たとえば、最初のほうで「フォールバックコードは書かないで」と指示していても、その後にたくさんの会話が積み重なると、その指示が中盤に埋もれていく。結果として、まさに禁止したはずのコードが出てくるわけです。

さらに、実務の現場では「Context Rot」(コンテキストの腐敗)と呼ばれる現象も知られています。長時間の作業を続けるとコンテキストが汚染され、最初に設定したルールや方針が薄まっていく。新しい情報がどんどん積み重なって、古い指示がノイズに埋もれてしまうのです。

つまり、ひとつの AI に実装もレビューも兼ねさせると、どちらも中途半端になってしまいます。実装に集中しているときにレビュー観点が薄れ、レビューしようとしても自分が書いたコードへのバイアスがかかる。

これは人間のコードレビューと同じではないでしょうか。コードを書いた本人はバグに気づきにくい。だから別の人がレビューするのです。AI も同じで、タスクを絞ることで精度が上がります。

「1エージェント1責務」。実装だけ、レビューだけ。コンテキストを分離すれば腐らない。

この考え方に沿って、実装する AI とレビューする AI を分けてフィードバックループを回す仕組みを作ることにしました。

Skill では足りなかった

さて、どのように実現すればよいのでしょうか。

Claude Code には CLAUDE.md(プロジェクトの設定ファイル)や Skill(スキルファイル)といった仕組みがあります。あらかじめルールを書いておけば、AI がそれに従って動いてくれるというものです。最初はこれらの仕組みでレビュープロセスを定義してみました。

しかし、簡単ではありませんでした。

Claude Code には compaction(コンパクション)という仕組みがあります。会話のコンテキストが長くなりすぎると、会話履歴が自動的に要約される機能です。CLAUDE.md やスキルファイルに書いたルール自体はシステムコンテキストとして残るのですが、会話の中でそのルールを強調してきた文脈が要約で薄まってしまいます。結果として、compaction 後に AI がルールを軽視するようになることがありました。せっかく「レビューしてから進め」と書いていても、拘束力が弱まってしまうのです。

プロンプトで直接指示しても、AI が手順をスキップすることがあります。「実装したらレビューしてね」と言っても、「もう大丈夫そうなのでそのまま進みます」と AI が自己判断してしまう。お願いベースでは限界があるのです。

さらに、ユースケースごとにやるべきことが変わるという問題もありました。毎回プロンプトを組み立て直すのは現実的ではありません。

ここで気づいたことがあります。

必要なのは「強制力」と「再現性」だと。

宣言的オーケストレーションという解法

お願いではなく、プログラムで制御する。手順をコードで管理すれば、AI は勝手にステップを飛ばせません。

そしてワークフローを YAML で宣言的に定義すれば、誰が実行しても同じ手順が再現されます。プロンプトではなく構造で制御する。「宣言的(何をするかを記述する)」と「オーケストレーション(複数のコンポーネントを協調させる)」、どちらも既存の技術用語ですが、この2つを組み合わせて「宣言的オーケストレーション」と呼ぶことにしました。

具体的にどういうものか、見てみましょう。

まず、ワークフローをYAML で定義します。

movements:
  - name: implement    # 実装する
  - name: review       # レビューする
  - name: fix          # 修正する

手順をステップとして宣言するだけです。プロンプトではなく構造。これが出発点になります。

次に、レビューに強制力を持たせます。

- name: review
  persona: reviewer
  edit: false              # コードを編集できない
  rules:
    - condition: 問題なし
      next: COMPLETE
    - condition: 修正が必要
      next: fix            # fix に強制遷移

ここがポイントです。edit: false でレビュアーがコードを改ざんすることを防ぎます。レビュアーの仕事はあくまでレビューだけ。そしてルールで次の手順を強制します。レビューの結果「問題なし」なら完了、「修正が必要」なら fix ステップに遷移する。AI にこの判断を委ねつつも、遷移先は YAML で縛っているわけです。

そして、合格するまで繰り返す仕組みです。

- name: fix
  persona: coder
  rules:
    - condition: 修正完了
      next: review         # review に戻る

fix は必ず review に戻ります。レビューを通過しない限り完了できません。

お分かりいただけたでしょうか。この構造によって、AI が勝手にレビューを飛ばすことは不可能になります。実装 → レビュー → 修正 → レビュー → ……というループが、YAML の定義に従って自動的に回り続けるのです。

で、何が嬉しいの?

この仕組み、実際に使ってみたら最高でした。

まず、レビューを飛ばせません。YAML の構造で制御されているので、AI がどんなに「大丈夫そう」と思っても、レビューステップは必ず実行されます。これだけで品質が格段に安定しました。Skill やプロンプトでお願いしていたときとは段違いです。

レビュー観点を定義できるのも嬉しいポイントです。たとえば「フォールバックコードを書いていないか」「不要な後方互換サポートを入れていないか」といった観点を設定しておけば、何度でもその観点でチェックしてくれます。私が毎回気にしていたあの問題、この問題を、AI が代わりに毎回チェックしてくれるのです。人間がレビューするときだって観点リストを持っていたほうが精度が上がりますよね。AI も同じです。

同じ定義で何度でも再現できるのも大きな利点です。毎回プロンプトを組み立て直す必要がありません。YAML ファイルをひとつ用意しておけば、同じプロセスが何度でも走ります。新しいタスクが来たら、同じピース定義を使い回すだけ。

そして何より、放っておいてもループが回り続けます。タスクがある程度複雑だと、30分から2時間ほど AI が自走してくれます。その間、私は画面の前にいなくてもいいのです。たまに通知を見て「まだレビューループ回ってるな」と確認するくらい。

結果どうなったか。

洗い物ができた🤗

AI がコードを書いてレビューして修正してを繰り返している間に、台所がきれいになっている。コードを書いている間に……いや、正確にはコードを書かせている間に、シンクがぴかぴかになっている。これが真の自動化だなぁと、きれいになった台所を見ながらしみじみ思いました。

TAKT を使ってみませんか

このオーケストレーションの仕組みは TAKT というツールとして公開しています。npm でインストールできます。

npm install -g takt

インストールしたその瞬間から、この記事で紹介したような宣言的オーケストレーションを使えます。ビルトインのピース(ワークフロー定義)が含まれているので、セットアップに時間をかけることなくすぐに試せるはずです。YAML を書き換えれば自分好みのワークフローも作れます。

TAKT のコードはこちらです。

https://github.com/nrslib/takt

Discord のコミュニティもあります。使ってみた感想や質問、「こんなピースを作ったよ」という共有など、お気軽にどうぞ。

https://discord.gg/emy8b9dxNK

AI コーディングの「ベビーシッター問題」に悩んでいる皆さん。AI には AI の面倒を見てもらって、私たちは私たちの生活を取り戻しましょう。

さあ、溜まった洗い物を片付けにいきましょう。

Discussion

shuentshuent

AIレビューを手放しに信頼して良いのでしょうか。多少品質上がってもコードに責任を持つ必要があるなら「ベビーシッター」からは抜け出せない。

たっさんたっさん

プレA2A2H(human)を体現されており、
素晴らしいと感じました!
最後のコードに責任を持つのは、
いまだに人間の勤めですから、
そこに至るまでのプロセスが再現性高く
行うためにはどうすれば良いかと言う着想いいと思いました!LGTM!