仕組みにしたのに、まだ漏れた ── AI開発で見落としていた「受入の分母」
この記事について
対象読者
AIに、既存コードの移行や作り直しを任せている方
要件や受入条件を作っているのに、なぜか一部が漏れると感じる方
古い仕組みを新しい環境へ移すとき、「まず同じように動かす」方針を取っている方
要点
AIへのお願いは薄れていくので、仕組みに置く。そこまでは前回書きました。
ただ、受入の仕組みがあっても、その受入が見るべき分母が粗ければ、やはり漏れる。古くなったWebアプリを、まず同じように動く形で新しい環境へ移そうとして、そのことを思い知りました。
前回、私は「仕組みにした」と書いた
以前、Claude Codeへのお願いは、会話が続くうちに薄れていく、という記事を書きました。
最初は丁寧に伝えたつもりでも、作業が長くなり、文脈が増え、例外が積み重なるうちに、だんだん効かなくなっていく。だから、お願いとして言い続けるのではなく、ファイルやルールやチェックの形にして、仕組み側に置く。
その考え自体は、今も変わっていません。
AIに毎回「気をつけて」と言うより、気をつけなくても外れにくい形を作る。人間の注意力に頼るのではなく、作業の入口や出口に、確認の仕掛けを置く。
たぶん、AIエージェントと長く付き合うほど、この方向には寄っていくのだと思います。
前回の記事で紹介したPRIMERは、その入口として考えていたものでした。
初心者が小さな開発を始めるときに、まず迷わず進めるための足場です。最初から大きなものを安全に動かすための、重い統制の仕組みというより、小さく始め、作業の流れを崩しにくくするための型でした。
一方で、自分用には、もう少し重めの仕組みも持っていました。
Claude CodeやAnthropicの公式ドキュメントなどを参考にしつつ、自分の開発で痛い目を見ながら増やしてきた、自分なりのベストプラクティス集に近いものです。
要件を整理し、判断を記録し、作業を分け、勝手に進みすぎないようにする。ある程度まとまった開発でも、流れが崩れにくいようにするための開発キットでした。
この二つを手元に置いて、ある個人開発に入りました。
古いWebアプリを、新しい環境へ移す作業です。
最初から機能追加や大きな作り直しをするつもりはありませんでした。古くなった実行環境や周辺技術の都合で、そのまま動かし続けるのがだんだん難しくなっていたからです。
だからまずは、今ある振る舞いを新しい環境へ移す。そのうえで、要件の追加や見直しは後続フェーズで扱う。
そういう方針でした。
いきなり移行と改善を混ぜると、何が元からの挙動で、何が今回変えた差分なのか分かりにくくなります。なので、まずはできるだけ同じように動かす。その判断自体は、今でも大きく間違っていたとは思っていません。
ただ、その方針を取るなら、本当はなおさら、旧側の振る舞いを細かく並べる必要がありました。
ここで、ひとつ見立てを誤りました。
自分用の重めの仕組みは、主に新規開発を想定して育ててきたものでした。今回のような移行作業に、そのまま向いているのかは、最初の時点では少し分かりませんでした。
そのうえ、移す対象は、すでに動いているものでした。新しく仕様を起こすわけではないのだから、そこまで構えなくてもいいだろう。
そう考えて、最初から重い台帳やチェックを、がっつり入れませんでした。
問題は、前回紹介したPRIMERそのものに穴があったことではありません。
また、自分用の重めの仕組みを持っていなかった、という話でもありません。
今回の反省は、仕組みの有無ではなく、どの作業にどの粒度の仕組みを当てるべきかを見誤ったことでした。
仕組みにしたはずの人間が、別の場所では、仕組みの射程を見誤っていました。
移すだけなら、AIは得意だと思っていた
最初の手応えは、悪くありませんでした。
古いWebアプリのソースをAIに読ませると、画面の構造も、処理の流れも、かなりのところまで拾ってくれました。新しい環境に置き換える作業も、思っていたより速く進みました。
画面ができる。
処理が動く。
エラーが消える。
テストも一部通る。
見た目には、ちゃんと前に進んでいるように見えました。
だから、少し安心していました。
今回、古いソースは全部ありました。すでに動いているものがある。画面もある。処理もある。
人間から見ると、移行は「同じものを作り直す」作業に見えます。新しい仕様を考えるというより、今あるものを読んで、別の形で再現する。
だから、ゼロから考えるよりAIに向いている。そう思っていました。
実際、かなり進みました。
ただ、あとから対応表のようなものを作り直してみると、見え方が変わりました。
古い側にはあるのに、新しい側では対応がはっきりしない行がある。
実装したように見えるけれど、テストと結びついていないものがある。
画面や処理はできているのに、例外時の分岐や、裏側の更新が追いきれていないものがある。
そのとき、ようやく分かりました。
「ソースが全部ある」ことと、「受入で見るべきものが全部並んでいる」ことは、別でした。
ソースがあるから大丈夫、ではありませんでした。
古いものの中から、何を再現すべきなのか。何が変わると困るのか。どこまで確認できたら同じと言えるのか。
そこを先に決めておかないと、AIはかなり進んでくれるのに、あとから空欄が見つかります。
私は、その空欄をかなり後になってから見ることになりました。
受入がなかったのではなく、分母が粗かった
ここは、誤解しないように書いておきたいところです。
受入の考え方がなかったわけではありません。
何を作るか。どうなったら完成か。そこを書き出して、あとで照らし合わせる考え方は、すでに持っていました。
前回の記事でも、「できた」の判定を口約束に任せず、書いておいた基準と照らし合わせる話を書きました。
自分用の重めの開発キットにも、その考え方は入れていました。
それでも漏れました。
なぜか。
今回の移行で足りなかったのは、受入そのものというより、その一段手前でした。
古い仕組みの中にある分岐や副作用を、確認すべき行として並べ切れていなかった。
受入表はありました。
でも、その受入表が見るべき分母を、移行に必要な粒度まで作れていませんでした。
通常の新規開発なら、「この機能がこう動く」「この画面でこう入力したらこうなる」という受入条件を置くことで、少なくとも今回作るものの輪郭は見やすくなります。
でも、古いWebアプリの移行では、それだけでは足りませんでした。
この違いは、受入条件が「正しさ」を決めているのか、写しているのか、にありました。
新規開発では、受入条件そのものが正しさを決めています。挙げていない分岐は、「作らないと決めたもの」です。だから荒くても、作るものが荒いだけで、内側では辻褄が合います。
でも移行は、「まず同じように動かす」と決めた時点で、正しさがこちら側を離れます。基準は、すでに動いている旧システムの挙動そのもので、受入条件はそれを写し取る近似にすぎません。
だから挙げていない分岐は、「要らないと決めたもの」ではなく、「旧システムにあるのに写し損ねたもの」になります。
普通に入力されたとき。空の値が来たとき。古いデータが混ざっていたとき。保存に成功したとき。失敗したとき。画面には見えないけれど、裏側で状態が変わるとき。
そういう細かい振る舞いが、古い仕組みの中に残っています。
それらを「確認する行」として並べていなければ、受入で見ようとしても見えません。
受入はあっても、受入が見る分母が粗ければ、漏れは残ります。
今回の空欄は、そこから出てきたのだと思います。
空欄は、実装漏れというより確認漏れだった
最初、その空欄を見たときは、単純な実装漏れだと思いました。
ここがまだできていない。ここを追加すればよい。次にここを直せばよい。
そう考えれば、いつもの開発の続きに見えます。
でも、少し違いました。
問題は、AIがサボったことではありませんでした。
もちろん、AIが完璧だったわけではありません。見落としもありましたし、途中で変な方向に進みかけたこともありました。
ただ、それ以前に、人間側の置き方が粗かったのだと思います。
対応表を作る前は、「この機能を移す」「この画面を作る」という単位で見ていました。
けれど、その中には、いくつもの分岐があります。
そして、その分岐は、名前をつけて行にしない限り、確認の対象になりません。
行がなければ、チェックもできません。
チェックできなければ、「やったつもり」と「まだ見ていない」の区別もつきません。
AIは、目の前にあるコードや指示をもとに、かなり器用に進めてくれます。
でも、確認すべき行そのものが用意されていなければ、そこを勝手に完全な台帳へ変えてくれるわけではありません。
ここで、漏れの見え方が変わりました。
これは単に、あとから実装を足せば済む話ではありませんでした。
漏れは、実装の途中ではなく、確認する単位を作る時点で始まっていました。
そう考えると、後から見つかった空欄にも、別の意味が出てきます。
それは「AIがうまく作れなかった場所」だけではありません。
そもそも私が、「ここは確認対象です」と明示できていなかった場所でもありました。
途中から型を入れても、すぐには収束しなかった
途中で、さすがにまずいと思いました。
最初は軽く見ていた作業でしたが、だんだん管理しきれないものが増えてきました。どこまで移したのか。何がまだなのか。テストしたものはどれか。見つかったけれど、まだ扱っていない課題はどれか。
頭の中と会話の流れだけでは、追いきれなくなっていました。
そこで、後から自分用の重めの開発キットを入れました。
作業の記録を残す。判断を残す。勝手に先へ進まないようにする。やったことと、残っていることを見えるようにする。
これで、ある程度は落ち着くはずだと思っていました。
実際、効いた部分はありました。
会話だけで流れていた判断が、記録に残るようになりました。途中で勝手に進みすぎることも、前よりは抑えられました。作業の状態も、少しずつ見えるようになりました。
ただ、それでもすぐには収束しませんでした。
なぜかというと、入れた型の多くは、作業を安全に進めるためのものでした。
それは大事です。
でも、そのとき本当に足りていなかったのは、受入の分母を作り直すことでした。
作業を安全に進める型と、移行差分を細かく並べる台帳は、似ているようで違います。
前者は、勝手に進みすぎないようにするものです。
後者は、そもそも何を確認対象にするのかを決めるものです。
私は、そこを少し混同していました。
型を入れたぶん、前より安全にはなりました。でも、それと今回の漏れ方が止まることは、別でした。
あとから公式ドキュメントを読み返しても、この違いは大事だと感じます。
Claude Codeのドキュメントでは、CLAUDE.mdやメモリは強制設定ではなく、Claudeが参照するコンテキストとして扱われ、判断に関係なく止めたい操作はPreToolUse hookで止める、と説明されています。
OpenAIのCodexのドキュメントでも、完了条件として「何が真なら完了か」を具体的に決め、検証やlint、pre-commitのチェックを含めることが勧められています。
つまり、ルールが書いてあることと、それが実際に止めてくれることは違います。受入があることと、必要な粒度まで分解されていることも、同じではありません。
その型は、今回の漏れ方を止めるところまでは、まだ届いていませんでした。
ここに気づくまで、少し時間がかかりました。
仕組みにも、射程がある
今回いちばん大きかった気づきは、ここでした。
仕組みは、入れれば何でも守ってくれるわけではありません。
何かしらのルールがある。記録も残している。チェックも動いている。だから、以前よりは安全になっている。
そう思うと、その仕組みが何を守っていて、何を守っていないのかを、見なくなります。
でも、仕組みにも射程があります。

作業を安全に進める型は、作業の流れは守ってくれます。けれど、「どの分岐がまだ未対応か」「どこまで確認したか」までは、それだけでは分けてくれません。
前回の記事では、お願いを仕組みに置き換えることを書きました。
今回は、その続きの話なのだと思います。
お願いではなく、仕組みにする。
そこまでは大事です。
でも、仕組みにしたあとで、その仕組みがどこまで届いているのかを見る必要がある。
今回の個人開発で漏れたのは、受入がなかったからではありませんでした。
受入の分母を、私が粗く見積もっていたからでした。
次からは、受入の分母を先に作る
今回のあと、考え方を少し変えました。
仕組みを入れること自体は、これからも続けます。
AIに毎回お願いするより、作業の中にルールや確認を置く。その方向は、やはり必要だと思っています。
ただ、次からは「受入があるか」だけでは見ないようにします。
その受入は、何を分母にしているのか。
どこまでは確認対象に入っていて、どこから先は入っていないのか。
そこを先に見る必要がありました。
いまなら、まず三つを見ると思います。
これは、何を確認対象にしているのか。
外れたときに、本当に止まるのか。
途中から型を入れた場合、過去の作業もその台帳に載っているのか。
この三つです。
特に、三つ目は見落としやすいところでした。
すでに走っている作業には、過去のメモや判断や未対応が散らばっています。あとから型を入れても、それらが自動で整理されるわけではありません。
型を入れたことと、その型の上に既存の作業が乗ったことは別です。
ここも、少し甘く見ていました。
こう書くと、少し面倒に見えます。
実際、面倒です。
でも、AIにある程度まとまった開発を任せるなら、この面倒さを先に払うか、あとから漏れとして払うかの違いなのだと思います。
前回は、お願いを仕組みに置く話を書きました。
今回は、その受入にも分母がある、という話でした。
「受入があるから大丈夫」ではなく、「この受入は、何をどこまで確認対象にしているのか」を見る。
たぶん、次に必要なのはそれでした。
参考
本記事は執筆時点の情報に基づきます。各社のデータ利用ポリシーは頻繁に改定されるため、実運用前に必ず公式の最新規約をご確認ください。オプトアウト設定は「将来の学習に使わない」という契約上の約束であり、短期データ保持・安全性目的の人間レビュー・アカウント侵害等による漏洩リスクをゼロにするものではありません。業務で機密情報を扱う場合は Consumer プランのオプトアウトに依存せず、法人向け契約下での利用を推奨します。契約だけでなく、技術統制と運用ルールを組み合わせた多層的な設計が実務的です。所属組織に AI 利用ポリシーがある場合はそれに従ってください。本記事は個人アカウントでの業務機密情報の取り扱い(Shadow AI)を推奨するものではありません。
