0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

昨年から積極的に AI を触っておりますが今年に入ってからの進化が目覚ましく、AI の研究と実業を兼ねて自社SaaS を構築するプロジェクトを開始しました。某プレイガイドの設計・開発に携わっていた経験を活かしてチケット販売プラットフォーム「CoMuse Ticket」を立ち上げました。設計から本番運用までコードのほぼ全量を AI に書かせています。

この度このサービスを立ち上げるまでの9か月にわたる作業記録を一部公開することにしました。AI 駆動開発黎明期の今こそ知見を自社に留めず多くの人と共有したいと思っています。
先端で活躍されている方々には既に当然の内容になっていると思いますが、これからAI 駆動開発に取り組もうとされている方々に「ふーん」と思っていただけると嬉しいです。

「上に説明するための材料」になるかも?

AI 駆動開発をやっていて一番しんどいのは、たぶん技術ではありません。経営層・マネジメント層との認識のズレを、現場のエンジニアが自分の言葉で埋めにいく作業のほうだと思っています。
ここから当分は完全に私見です。自社の1プロジェクトとその周辺の会話から感じていることなので、業界一般に通用するかは分かりません。

誰が言うか 言われること 私が感じていること
経営・マネジメント層 AI に任せれば人が介在しなくなる 介在はなくならない。なくなるのではなく、場所が変わるのではないか
システム部門の現場 AI に仕事を奪われて職を失う 奪われるというより職能が変わるだけではないか。業務知識と障害対応の勘はむしろ効く

面白いもので、この2つは私の理解とは正反対の方向に誤解されているように感じています。
ケースバイケースだとは思いますが、少なくとも自分たちのプロジェクトではどちらも起きませんでした。厄介なのはこれを現場が口で言っても ポジショントークに聞こえてしまう ことです。
なので、プロジェクトで計測した実測値丸ごと置いておくことにしました。 第1部は非エンジニアが読めるように書いてあり、コードは一つも出していません。「うちの上を説得する材料がほしい」という方は、第1部のURLを投げてください。それが一番の使い道だと思っています。(伝わるといいなぁ……)


プロジェクトの実測値

ここから先は私見ではなく、git 履歴とイシュートラッカーからの実測です。

  • 本編にあたる約4か月半で、コミット約 5,750 / 完了イシュー 2,067件
  • コード規模 約 41万行、そのほぼ全量を AI が書いた
  • それでも人間は毎日介在し続けた

本編の前には、約5か月ぶんの「作っては壊し、そもそも何を作るかを延々とブレストしていた」時期があります。一度は全部作り直しました。その5か月が、後の速度の土台になっています。
恐らくこの記事に辿り着いた方の中には私と同じような暗中模索を繰り返されている方もいるのではないかと思います。
人間が使った時間の内訳の大半は、要件と完了条件の定義、検証と差し戻し、AI の失敗パターンの観察とルール化、本番と金銭の最終判断でした。それをAIが読める状態にして設定した仕組みが hooks 24本・rules 10ファイル・メモリ三層でした。**「人の判断をAIが読める状態にして常に守らせた証拠」**として数えています。


踏んだ地雷から3つ

記録では失敗事例を12件、独立したカードにしています。多くはAI駆動開発を始めると高確率で踏む地雷だと思いますが、ここでは3件だけ。

1. migrate diff --shadow-database-url に実DBを渡して開発DBが飛んだ

Prisma の migrate diff は「差分を出すだけ」に見えますが、--shadow-database-url に渡した DB は破壊的にリセットされます。全テーブル DROP して replay する挙動です。そこに実際に使っている開発DBの接続文字列を渡しました。
同じ日、本番DBのフルバックアップが約19日間サイレント失敗していたことも発覚しています。原因は cron の env 未伝播と、鮮度監視スクリプト自体が本番に配備されていなかったこと。検知する仕組みを用意していても、適切なタイミングで実行されるように配備されていなければ意味がありません。

無人化には、実行権限・env伝播・配備同期・鮮度監視・通知到達の5層が要る。

2. スカッシュマージで実装済みコードが静かに消えた

小さな機能追加PRの直後、71ファイルを変更する大規模リファクタPRが同じファイルを編集してマージされ、先のPRのページと導線ボタンが上書き消失しました。エラーも警告も出ません。気づいたのは翌日です。
スカッシュは個別コミットのコンフリクト解決の漏れが履歴上追えず、並行PRの変更を静かに消滅させてしまいます。AI 駆動でマージ頻度が上がると、この「大型リファクタと小型機能の並行」が日常的に起きます。
対策はスカッシュ禁止と「PRはテスト完了後すぐマージ、オープン放置禁止」。ただし --squash を直接ブロックする検査はまだ追加していません。このあたりは少し柔軟性を保たせています。

3. 1日10回デプロイして GitHub Actions の無料枠が枯れた

開発の真っ最中、 master への push ごとにフルビルドが走って月前半で約80回、追い打ちで1日10回の staging デプロイ(1回およそ15分)。翌日、無料枠 2,000分/月を使い切って CI 全体が停止しました。シークレットスキャンも止まります。

AI は教えなければ他サービスの従量課金・無料枠の概念を考慮しません。

「push したら自動ビルド」は教科書どおりです。ところが AI 駆動でマージ頻度が人間の数倍になった瞬間、無駄の主要源に変わります。push トリガーを撤去して手動 dispatch のみにし、完了イシューはキューに貯めて一括デプロイする運用を既定にしました。
他には、タイムスタンプの解釈間違いで集計が9時間ずれた話、私が否定済みの過去の設計案を AI が何度も何度も再提案し続けたループなどがあります。。。


事故 → ルール → 機械的強制

やったことは毎回同じ形でした。最後の1手が肝です。ルールは書いただけでは守られません。

CLAUDE.md は増えて、減って、また増えた

時点 行数 何が起きたか
初追加 15 散文のメモ
約1か月後 477 指示の書き足しで肥大(ピーク)
その翌週 47 大凝縮。詳細を .claude/rules/ 7本へ分散
4か月後 179 行動原則と入口リンクだけに純化

一番大事なのは CLAUDE.md の記述を「増やした日」ではなく**「減らした日」**でした。毎セッション必ず読まれる唯一の文書に全部を書くと、結局どれも守られなくなります。

hooks は3.5か月で24本、全て稼働中

時点 累積 その月の増分テーマ
開始月末 0 規律は散文のみ
+1か月 7 ブラウザテスト強制・マージ手順・test skip 検知・Doneガード
+2か月 11 言行一致・デプロイ監視・記憶インフラ
+3か月 17 出力書式三層・ロール注入・テーマトークン・禁止API
+4か月 24 doc陳腐化・タスクモード契約・本番/stagingデプロイガード

作成した hooks は一つも削除することはありませんでした。そして**「フック整備プロジェクト」を立てたことは一度もありません。** 作成した hooks は全て事故の復元PRや是正コミットで得た教訓を元に作成させました。
実物を1本。「確認して」と指示したセッションでは AI がリポジトリ内を編集できなくなります。明示的に「編集して」「着手して」などと指示しない限りファイルを編集しないようにしたのは、AI が人間が思っている以上におせっかいで調査だけ依頼したつもりなのに勝手に編集をしてしまうからです。

#!/bin/bash
# PreToolUse(Edit|Write): 確認モード中のリポジトリ内ファイル編集をブロックする。
# 停止は exit 2 + stderr。stdout の {"decision":"block"} は今も効くが公式な停止手段
# ではない。契約から外れた形は「黙って通る」方向に壊れる。
DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
# stdin は判定より先に読み切る。読まずに exit すると呼び出し側が EPIPE を踏む
INPUT=$(cat)
[ "$(cat "$DIR/.claude/task-mode" 2>/dev/null)" = "investigate" ] || exit 0
FILE=$(printf '%s' "$INPUT" | python3 -c \
  'import json,sys; print(json.load(sys.stdin).get("tool_input",{}).get("file_path",""))' \
  2>/dev/null) || FILE=""
# リポジトリ外(スクラッチ等)への書き出しは調査の一部として許す
case "$FILE" in "$DIR"/*) ;; *) exit 0 ;; esac
echo "[task-mode] 確認モード中のため編集をブロックしました。" >&2
exit 2

こだわった点が3つ。

  1. 判定と実行を別フックに分ける(モードを決めるのは UserPromptSubmit、止めるのは PreToolUse。片方が壊れてももう片方は生きています)。
  2. fail-open(フックが何らかの問題を生じた場合は承認扱いとする)。
  3. バイパスは痕跡が残る形にする(環境変数ではなく引数で実行することで記録を残し、なぜ通したのかが後から分かるようにする)。

書いたのは AI です。人間が出したのは、どうあるべきかの原則と、事故の認定と、後始末をどうするかの承認だけでした。

統治コードは製品コード41万行の0.9%

「規律を足すと AI の処理が遅くなるのでは」という不安を調査するために実測値を洗い出しました。

  • CLAUDE.md 179行
  • rules 10本 1,334行
  • hooks 24本 1,438行
  • settings.json 190行
  • agents・skills ほか約714行

で、合計 約3,855行。製品コード約41万行に対して約0.9%、うち約4割が散文ではなく実行可能なシェルによる強制です。

この 0.9% が残り 99.1% の SaaS 本体の生産を支えました。規律は開発速度の足かせではなく、むしろ 人が見ていない時間帯にも安心して AI を走らせるための前提条件 となりました。


事故対応以外にやっていたこと

9か月の時間の多くは「どうすればもっと速く安全に回るか」に使いました。

実装手順ではなく検証手順を重点的に

1イシュー完了の手順は3か月で 16 → 20.5 ステップに増えました。 実装手順の手数や内容はほとんど変更していません。手厚くなったのは検証手順だけ です。dev で確認 → PR → 通常マージ → デプロイ → staging で確認の2段検証、テストが落ちたらイシューを新規起票して戻るという入れ子のイテレーション、そして イシューの完了は staging のブラウザテスト完了後(マージ時点では Done にしない)。

骨格が固まったのは staging 実機を建てた直後のわずか5日間でした。検証の場が生まれた瞬間に検証の型が定義されたことになります。

AI にブラウザによるテストを依頼すると横着をして URL 直打ちで開けてしまいます。しかし画面上に導線がなければ不合格です。また人間が横着して「ノンストップで作業できるイシューを連続して着手して」と指示したら 12PR 連続マージ中に AI も横着をして検証を省略してしまい、3PR が差戻に。 「ノンストップの意味するところはタスク間の待機ゼロであって、検証省略の意味ではない」 というルールを作成することになりました。

レビュー観点は「自分が事故った順」に固定する

サブエージェントは「並列で速くなる道具」として語られがちですが、弊社のプロジェクトで一番効いたのは レビュー観点を、そのプロジェクトで実際に事故った順に固定できること でした。汎用の観点より、自分の失敗履歴から作った観点リストのほうが検出率が高くなります。
結果として優先順は、

  1. バグの有無
  2. 金銭を扱うロジックの絶対制約(否定済み設計の再導入検知)
  3. 許可している権限の越境行為
  4. デザイントークン
  5. DB規約
  6. UI文言
  7. スコープ規律(1PR = 1レイヤー)

となりました。

このレビューを担当させるエージェントは ツールから書き込み系を外して読み取り専用 にしました。構成でそうしておくと「レビューのついでに勝手に直す」事故が構造的に起きません。テスト生成側で効いた契約は**「金額は成分別に assertion する」**です。合計値だけの assert は、成分同士の誤差相殺を見逃します。

記憶は三層に分けてイシュー管理ツールを活用する

AI の記憶は書きすぎると壊れます。長文の蓄積で recall 出力が 151KB を超えてツールが止まったのと、「コミット成功」に見えるのに中身が引き継がれていなかったのと、2通りの壊れ方をしました。後者は SQLite の WAL です。書き込みが -wal に滞留するので git add memory.db では無変更に見えて取りこぼします。

設計するのは「何を覚えさせるか」ではなく**「何を、どこに書くか」**でした。

層 実体 書くもの
① 自動メモリ markdown 群(リポジトリ外) 横断ルール・是正の教訓・設計正本へのポインタ
② 記憶DB リポジトリ内 SQLite(git で端末間共有) caveat / learning / 引き継ぎ要点(1500字以内)
③ イシュー管理 イシューのコメント 実装詳細・変更ファイル・検証結果(正本)

肝は③です。イシュー管理ツールは、AI の記憶を補って余りある外部記憶になります。 詳細は追跡可能な正本へ押し出し、記憶側には入口だけを残す。この連携の設計が体感で一番効きました。

デプロイフローは4世代作り直した

手動SSH → スクリプト化 + 完了マーカー → 非同期起動 + watchdog + 状態ポーリング → CIビルド先行 + ローカル一括ラッパー。世代の境目には必ず事故があります。

3世代目の原因分析が一番汎用的でした。根本は**「処理中」と「ハング」を区別する完了マーカーが存在しない**ことです。対策は、全 curl にタイムアウト、PID付き開始マーカー、exit code 付き完了マーカー、非同期ランチャーの4点セットでした。

その watchdog は導入直後に誤発火して正常ビルドを kill しています。「アラートを設定した」と「アラートが鳴る」は別物です。


AI 駆動開発の現在地

まだAI 駆動開発の歴史は始まったばかりです。
Java の誕生、インターネットの誕生などをリアルタイムで見てきた感想として 黎明期が一番面白い と感じています。だから AI 駆動開発は今とても面白いです。
こんな弊社のドタバタは以下にもまとめていますのでご興味あればご覧ください。

AI駆動開発の実運用ノート

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?