ACES エンジニアブログ

ACESのエンジニアブログです。

#4|Pilot-Tower開発を回してみた — 成果と摩擦のリアル

はじめに

こんにちは、株式会社ACES でテックリードをしている福澤 (@fuku_tech) です!

本シリーズでは、AI駆動開発における人間とAIの役割分担を、自動運転になぞらえた4つのPhaseで整理しています(詳細は下図を参照)。前回の記事(以降、「#3」と呼称)では、AIに運転席を譲るPhase 3の設計思想として「Pilot-Tower開発(P&T開発)」を紹介しました。plan.md をSSoTとしたループ構造、AIが判断に迷ったときだけ停止するDecision Required(DR)、そしてAIに任せない領域を定めるガードレール。この3つの仕掛けで自走と統制を両立する、という話でした。

思想については前回語りました。本記事では plan.md、DR、ガードレールなど以下の#3の記事で導入した概念を前提としているため、先にお読みいただくとよりスムーズです。では実際にこの思想で開発を回してみてどうだったか。今回は、P&T開発の実践の手触りと、そこで起きたつまずきを語ります。

tech.acesinc.co.jp

/plan-execute の実際: 1本のPRができるまで

/plan-execute は、plan.md を入力にAIが自律的に実装→品質ゲート(Lint・Tests)→レビュー→PR作成の4フェーズを回すコマンドです。

Phase 1: 実装
  └→ plan.mdに沿って実装
  └→ 適宜worklog.mdに作業のサマリーを記録
  └→ DRが必要なら停止して開発者にエスカレーション(暴走防止)

Phase 2: 品質ゲート
  └→ Lint / Format 自動実行
  └→ テスト自動実行
  └→ 失敗したらまずは自己修正
  └→ 自己修正では解消が難しい場合は別の Codex CLI 等を使って別の LLM に修正を依頼
  └→ エラーがなくなるまで or 上限回数に到達するまで繰り返す

Phase 3: レビュー
  └→ セルフレビュー
  └→ Codex CLI 等の別の LLM にレビューを依頼
  └→ 指摘があれば自動修正
  └→ 修正すべき指摘項目がなくなるまで or 上限回数に到達するまで繰り返す

Phase 4: PR作成
  └→ PRタイトル・説明を自動生成

「張り付き」から「離れられる」へ

シリーズ第二回目の記事(以降、「#2」と呼称)で解説したPhase 2の運用では、コマンド実行→出力レビュー→次のコマンド選択の繰り返しで、AIが動いている間ずっと人間が張り付いている必要がありました。AIの処理待ち時間そのものは短くても、次に何をさせるかを判断して指示を出す工程が常に発生していました。

tech.acesinc.co.jp

Phase 3では、この体験が大きく変わりました。/plan-execute に投げたら30分から2時間は離れられます。会議の裏で仮実装や本実装が進み、戻ってきたらDRに答えるかPRを確認するだけです。/plan-execute コマンドの内部にworklogの記録、DRでの停止、ガードレール領域での報告といった複雑さが隠蔽されたことで、エンジニアの認知負荷が下がりました。「planを作って育てて /plan-execute を実行する」というシンプルな運用に収束しています。

ただし、これは#2で整えたガイドライン・ガードレールという土台があってこそ回っている点は強調しておきたいと思います。

実際の事例

具体的なイメージを持ってもらうために、実際のタスクをベースに一連の流れを追ってみます。題材は、複数のSpeech(文字起こし)テキストを一括更新するAPIの実装です。以下はバックエンド側の plan.md を例に、一連の流れを追っていきます。

最初に人間がやることは、plan.md の「種」を書くことです。この段階ではGoalとざっくりした制約だけで構いません。

## Goal
複数のSpeech(文字起こし)テキストを一括更新するAPIを実装し、
フロントエンドのキーワード一括置換機能を実現する。

## Constraints
- サーバーサイドの実装のみ(フロントエンドは対象外)
- 既存のSpeech単体更新APIには変更を加えない

## Definition of Done
- 一括更新APIが正常に動作し、テストが通ること

この種を /plan-refine でAIと対話しながら育てます。CursorのPlanモードやClaude CodeのPlan機能を使ったことがある方にはおなじみの体験ですが、ポイントはその対話結果が plan.md というファイルに永続化され、後続の /plan-execute が参照するSSoTになることです。以下は /plan-refine を経て育った plan.md の抜粋です(社内固有の情報はマスキングしています)。

## Goal
複数のSpeech(文字起こし)テキストを一括更新するAPIを実装し、
フロントエンドのキーワード一括置換機能を実現する。

## Constraints
- サーバーサイドの実装のみ(フロントエンドは対象外)
- 既存のSpeech単体更新APIには変更を加えない
- 既存のbulk_executeパターンを踏襲
- All-or-Nothing(部分成功なし): 不正が1件でも含まれる場合、
  1件も更新せず4xxを返す

## Definition of Done
- 一括更新サービスが実装されている
- 空文字や最大文字数超過のバリデーションが実装されている
- 存在しないIDが含まれる場合は404を返す
- 他テナントのリソースが指定された場合はテナント隠蔽のため404を返す
- All-or-Nothing: 上記いずれかに該当するIDが1件でも含まれる場合、
  更新を1件も行わない
- DB更新と検索インデックス更新・キャッシュ削除が整合する順序で
  実行される
- 単体テストカバレッジ100%

なお、今回のように実装の方向性が見えている場合は /plan-refine の対話だけで十分ですが、要件レベルでも技術的にもふわっとしていて人間にもイメージがついていない場合は、/plan-spike(仮実装による技術検証)でカジュアルに探索的な実装をさせてみることで、制約やDoDをクリアにしていけます。

/plan-execute を実行すると、AIが自走し、実装→品質ゲート(Lint、Tests)→セルフレビュー→PR作成の一連が人間の介在なしに回ります。途中でAIが判断に迷った場合、DRを発行して停止します。このタスクでは2件のDRが発行されました。

### DR-001: バルク更新の上限件数

- Priority: P0
- Context: 一回のバルクアップデートで更新できる件数の上限
- Options:
  - A: 100件(既存のバルク操作と同じ)
  - B: 1000件(長時間会議に対応)
- Recommendation: B
- Decision: B(1000件)

### DR-002: エンドポイント設計

- Priority: P1
- Context: 新APIを既存の汎用バルク実行エンドポイントに統合するか、
  独立したエンドポイントにするか
- Options:
  - A: 既存のバルク実行エンドポイントに新オペレーションを追加
  - B: 独立した専用エンドポイントを新設
- Recommendation: B
- Decision: A(既存エンドポイントに統合)

DR-001ではAIの推奨(B: 1000件)をそのまま採用し、DR-002ではAIの推奨(B: 独立エンドポイント)とは異なるA(既存エンドポイントに統合)を選択しました。人間はDRを読んでA/Bのどちらかを書き込むだけです。選択肢と推奨案がすでに提示されているので、背景を一から調べる必要がなく、判断のコストが大幅に下がります。DR-002でAIの推奨を覆したのは、既存のバルク処理APIの実装パターンとの一貫性を優先したためです。こうしたプロダクト全体のコンテキストに基づく判断は人間が担う方が適切で、DRの仕組みがあるからこそ判断ポイントが自然に浮上し、見落とされずに済みます。

DRに答えるとAIが再走し、残りの実装を完了させます。

チームで見えてきた変化

この一括置換機能(APIと画面)の開発 (設計からmainブランチへのマージまでの全工程) は、従来であれば2〜3日と見積もっていた規模感でした。P&T開発で回した結果、人間の実稼働時間は2〜3時間で完了しました。これは私個人の体感だけではなく、API認証のClient Credentials対応など他のタスクでも同様の短縮効果がチーム内で報告されています。

AIに自走させている間に別のタスクのplanを作れるようになったことで、2〜3プロジェクトを同時並行で進められるようになったというメンバーもいます。Phase 2では人間がAIに張り付いていたため、基本的に1タスクずつの直列作業でした。Phase 3では人間の役割がDRへの判断回答に絞られたことで、並列度が上がりました。

設計判断が難しい箇所はDRでその都度判断しながら進められるため、後からAIが書いたコードを大きく手戻りさせるといったことがなくなったという実感もあります。#3で「DRのログ蓄積によってAIの自律判断範囲が拡大し、人間の介入がさらに減っていく」と書きましたが、実際にその兆候は出始めています。似たような設計判断が過去のdecision-logに蓄積されることで、以前はDRに上がっていた判断がAI側で自律的に処理されるケースが増えてきました。

エンジニアだけでなく、非エンジニアによる実践事例も出てきています。例えば、PdMがP&T開発を用いてスマホアプリの不具合修正を自ら完結させたケースです。これまでエンジニアの工数を待たなければならなかった微細な修正が、PdMの手によって迅速に解消されるようになりました。この事例における具体的な実装ロジックはほとんどAIの生成結果そのままであり、コードレビューこそエンジニアが最終確認として実施したものの、品質担保の軸は実機での動作確認に置かれていました。P&T開発の仕組みが、個人のコード執筆能力とは別のレイヤーで品質を担保しているからこそ成り立っている、象徴的な事例だと考えています。

つまずきとその乗り越え方

成果だけを並べると順風満帆に聞こえるかもしれませんが、もちろんつまずきもありました。ここでは、実際に起きた失敗エピソードとその対処を率直に共有します。

git reset --hard で数時間分の作業が消えた

初期に起きた分かりやすい失敗です。AIが自走中に git reset --hard を実行し、数時間分の作業が消えました。実際には git reflog で復元できたので事なきを得ましたが、破壊的な操作を勝手に判断して実行されると、心理的にAIに任せにくくなります。

対処はシンプルで、 settings.json に禁止操作として明記しました。ルールに書けば再発しない。AIのやらかしは仕組みで潰す、という原則を最初に教えてくれたエピソードです。

コンテキスト蓄積による精度低下

AIが長時間稼働すると、コンテキストウィンドウに情報が積み上がりすぎて判断精度が落ちるという課題もあります。後半のタスクでガードレール領域に不用意に手を出しそうになったり、前半で合意した方針と矛盾する実装をしたりすることがありました。

現状では、セッションを意図的に切り替えて plan.md で状態を復元する運用と、SubAgentsの活用で緩和しています。plan.md がSSoTとして機能しているからこそ、セッションを切っても文脈を失わずに再開できます。ただ、完全な解はまだ見つかっていません。

「手放す怖さ」をどう越えたか

技術的なつまずき以上に大きかったのは、心理的な壁です。「AIに任せて大丈夫なのか」「本番に出して問題ないのか」という不安は、仕組みの説明だけでは払拭できませんでした。

この不安を越えるために、モブプログラミング会(90分×4回)を実施しました。チームメンバーが実際に一緒にP&T開発を動かす場を設け、DRできちんと停止すること、ガードレール領域に触ったらAIから報告が来ること、Lint→Tests→セルフレビュー→別LLMによるレビューを通過した上でPRが作られること、この一連を目の当たりにしてもらいました。百聞は一見にしかずという諺の通り、品質ゲートが実際に機能する様子を確認できたことで、不安が払拭され大きな手応えを得ることができました。

ここ数ヶ月の運用で、AIの実装に起因するインシデントは0件です。#2で整えた土台(ガイドライン・品質ガードレール・AI向けドキュメント)が効いている結果だと考えています。皮肉なことに、この間にヒヤリハット*1が起きたのはむしろ人間が書いたコードの方でした。

今いちばんの悩み: 巨大PRとレビューの限界

一方で、まだ乗り越えられていない課題もあります。AIが自走してくれるのはいいのですが、1つのPRに大量の変更を詰め込んでくるケースが頻発します。品質ゲート(lint・テスト・セルフレビュー・別LLMレビュー)は通っているものの、変更差分の大きなPRが量産されると、人間側のレビューが追いつきません。「これ本当に出して大丈夫か?」という不安が残り続けます。

暫定策としては、タスクを設計段階で小さく分解してから /plan-execute に渡すことでPR粒度を制御したり、PRを意味のある単位に分割するスラッシュコマンドで事後的に対処したりしています。ただ、これらはいずれも人間の介在を増やす方向の対処です。#1で「人間が運転席に座り続ける限り、AIの稼働時間は人間の稼働時間に縛られる」と書きましたが、タスク分解やレビューについても同じ構造が当てはまります。人間の手数を増やすことでしか品質を担保できない状態では、ボトルネックが別の場所に移るだけで、AIの自律稼働時間を最大化するという当初の目的はスケールしません。

この問題は、タスク分解自体をAIに動的にやらせることで緩和できる可能性もあります。Claude CodeのTask Systemのように、AIが実装中にサブタスクを切り出して並列処理する仕組みを応用すれば、結果的にPRの粒度も小さくなることが期待できます。現在試験的に導入を始めていますが、本格運用はこれからです。

さらに言えば、そもそもこの問題自体が一過性のものかもしれません。GitHub元CEOのThomas Dohmke氏が新会社Entireを立ち上げた際にXで発信していたように、コードを理解してレビューするという行為自体が死にゆくパラダイムだとすれば、意図と成果を検証するワークフローへの移行が進み、人間がコードを逐一レビューする前提自体が変わりうる。そうなれば、PR粒度の問題も構造ごと解消される可能性もあります。

とはいえ、その日まで待つわけにはいきません。本命は、人間の目視に頼らなくても安全にリリースできる仕組みです。「壊れないようにする」だけではなく「壊れても速く直せる」リリース安全網が整えば、レビューで事前に品質を担保しなければならないという不安を感じにくくなる効果があると考えています。次回の#5|AIが書いたコードをどう本番に出すか(2026/03/18公開予定)では、そのアプローチについて語ります。

おわりに

P&T開発を数ヶ月回してみて、planを作って /plan-execute を投げるというシンプルな運用に収束し、人間はAIの自走中に別のタスクを進められるようになりました。一方で、AIの暴走やコンテキスト蓄積、巨大PRのレビュー負荷といったつまずきも経験しました。ルールに書けば再発しないものは仕組みで潰し、構造的に解決できないものは投資先を見極めて手を打つ。そして、その仕組みが本当に機能することをチームで一緒に体験して初めて、次のステップに進めます。その積み重ねが、小さなチームで大きなことをやる力になると考えています。

ACESでは現在、複数のエンジニアポジションで採用を行っています。本シリーズを読んでACESの開発に興味を持っていただけた方は、ぜひカジュアル面談でお話ししましょう!

ACESの採用情報はこちら↓

recruit.acesinc.co.jp

open.talentio.com

*1:デプロイ直後に検知し、影響ユーザー0人で即revert