
AIに任せたレガシーシステムのモダナイズで、仕様の移行漏れに気づけないのはなぜか
はじめに
データ事業本部の荒木です。
レガシーシステムのモダナイズにAIを使ってみて、出てきた成果物をそのまま信じてよいか迷ったことはありませんか。
AIにソースコードを読ませれば設計書が作れますし、別の言語やフレームワークへの変換もある程度は任せられます。実際に試すと、設計書も変換後のコードも、人手で書くより短い時間で形になります。
ただ、出来上がったものを現行システムと突き合わせると、現行にあった機能や画面の要素が抜けていることがあります。そして抜けていることに、作った側はなかなか気づけません。
今回は、実際に移行を進める段階でどんな問題が起きるのかを、私が得た知識の範囲でまとめたいと思います。
結論
AIに任せた移行は、現行のソースコードの読み込み、現行の資料の読み込み、画面移行の3つで仕様が漏れてしまうことがよく発生しました。
いずれもAIの精度が低いから起きるのではなく、何をどこまで読むかをAI自身が決めてしまい、その判断が人から見えないために起きます。漏れを防ぐには、ソースコードや資料を渡して読ませるのではなく、読む範囲を人の側で確定して漏れなく読ませる仕組みが必要です。
以前、ソースコードを解析してドキュメントを自動生成するモダナイズ支援サービスとして、クラスメソッドのtenseiサービスを紹介しました。
tenseiは、この仕様が漏れてしまう問題を現行の仕様を漏れなく把握したうえで移行を進めるやり方を実践しているサービスとなります。
本記事では、そのtenseiから得られた知見として、なぜAIでのモダナイズに漏れがでるのか、なぜ気づけないのか、気づいた後に何が起きるのか、漏れを減らすには何を用意しておくべきかについてお話しできればと思います。
AIに任せたモダナイズでは、どこで仕様が漏れるのか
移行作業をAIに任せたときに繰り返し出会った漏れについて、原因ごとに3つ挙げます。
| 何を入力したとき | 何が漏れるか | なぜ気づけないか | |
|---|---|---|---|
| 漏れ1 | 現行のソースコード | 開かれなかったファイル、移行対象として拾われなかった処理 | AIはどこを読んでいないかを報告しない |
| 漏れ2 | 現行の設計書・仕様書 | 読まれなかった資料に書かれていた仕様 | 資料を読んだ結果の0件と、開いていない0件が同じ見た目になる |
| 漏れ3 | 現行の画面 | 見た目、画面とAPIのつなぎ込み、画面間の動線 | 移行後の画面が動いてしまうため、欠けていても気づかない |
漏れ1: AIは現行のソースコードを最後まで読み切れない
1つ目は現行のソースコードの読み込みです。AIにソースコードを渡して仕様を整理させたり変換させたりすると、返ってくる成果物は一式そろって見えます。ファイルの一覧も処理の説明も並んでいて、現行を読み切ったうえで書かれたもののように見えます。
ところが現行と突き合わせると、AIが開いていないファイルや、開いてはいるが移行対象として拾われなかった処理が残っています。AIは渡されたソースコードのうち、どこを読んでどこを読んでいないかを正確には報告しません。
原因は、ソースコードを渡して読ませるという指示だけでは、どこまで読むかをAI自身が決めてしまうことにあります。全体を眺めて関係のありそうな箇所を選び、そこを読んで報告する。この選び方は人からは見えず、選ばれなかったファイルはAIにとって存在しないのと同じ扱いになります。
漏れ2: AIは現行の設計書・仕様書を読み飛ばす
2つ目は現行のドキュメントの読み込みです。漏れ1と似ていますが、現行の設計書や仕様書をAIに渡して仕様を整理させると、きれいにまとまった一覧が返ってきます。表も揃っていて、根拠も添えられていて、完成品に見えます。
ところが実際には、AIが渡した資料の一部しか読んでいないことがあります。厄介なのは、AIが資料を読み落としたかどうかを、出てきた一覧から判断するのに苦労することです。0件という結果には、次の2つの意味が混ざります。
- 資料を読んだうえで、該当する仕様が無かった
- その資料をそもそも開いていない
この2つは、一覧の見た目が同じになります。
「読みました」「該当ありませんでした」という報告は、AIの自己申告です。その報告が正しいことを別の手段で裏付けない限り、読み落としがあっても気づけません。
資料を読み落とすのと同じことは、AIに調べさせる対象を絞り込むときにも起きます。ファイル名やディレクトリの階層で調査対象を絞ると、仕様が一番多く書かれているファイル群が調査範囲から外れることがあります。
それでもAIは「指示された範囲はすべて調べました」と報告し、その報告は正しいままです。調査範囲から外れたファイルに書かれた仕様は、漏れとして数えられないからです。

漏れ3: 画面のモダナイズでは構造以外が漏れる
3つ目は画面移行です。移行の対象の中で、画面移行が一番、現行の画面と別物になりやすいと感じています。
画面をモダナイズするとき、コンポーネントの構造は比較的ちゃんと移行できます。漏れるのは、コンポーネントの構造以外の部分です。漏れやすい箇所として、以下のようなものがあります。
- 見た目: 独自に書かれたCSS、アイコンの実体、独自に描画している部品は自動では移らず、移行後のコードにはクラス名だけが付いて、そのクラスに対応するスタイルが定義されていない状態になります。結果として、要素の配置はそれらしいのに、色も余白も枠線も無い画面ができます
- 画面とAPIのつなぎ込み: 移行先に実装されているのに、画面から一度も呼ばれていないAPIが数十本見つかったことがあります。API側だけを見ても、画面側だけを見ても、この漏れは出てきません
- 画面から画面への動線: 編集機能自体は移行先に実装されているのに、一覧画面から編集画面へ進むボタンが無く、URLを直接入力しないと開けない状態になっていたことがあります。それでも自動テストは通っていました。テストが一覧画面を経由せず、編集画面のURLを直接開いて確認していたためです
3つに共通しているのは、部品そのものではなく部品のつながりが移らないことです。UIライブラリを新しいものに載せ替える作業と、現行の見た目や画面のつながりを移す作業は別物です。
移行対象の画面をどの単位で数えるかも、漏れが起きやすい箇所です。1つの画面を一覧の1行として管理すると、その画面の中にある要素がまとめられてしまいます。
| 数え方 | 一覧に載る記述 | 一覧から消える要素 |
|---|---|---|
| 1画面を1行として数える | 「編集はダイアログで行う」 | モーダル、ドロワー、種別を選ぶと入力欄が切り替わるフォーム、ウィザードの各ステップ |
| 画面内の要素まで細かく数える | 上記の要素がそれぞれ1行として残る | (まとめられる要素が無い) |
1行にまとめられて一覧に残らなかった要素は、移行対象としてドキュメントに残したとしても誰も認識できません。そのため移行先に作られなくても気づけません。

3つの漏れは、AIがドキュメントを読む仕組みから生まれる
ここまでの3つの漏れは、AIの読み方そのものに理由があると考えています。Claude Codeを例に、公式ドキュメントに書かれている仕様を3つ挙げます。
使うツールによって、AIの手元に届くものが違う
同じ「読む」でも、ツールごとに親のコンテキストへ届くものが変わります。
- Readは、ファイルの中身を行番号付きでそのまま返します
- WebFetchは、取得したページをMarkdownに変換したうえで、小さく速いモデルにプロンプトを渡し、そのモデルの答えがClaudeに届きます。ページの原文は届きません
- サブエージェントは独立したコンテキストで動き、親には最終的な結果のテキストが1つ返るだけです。途中のツール呼び出しや出力は親から見えません
WebFetchについて、公式ドキュメントは設計上そもそも情報が失われる(lossy by design)と明記しています。そのうえで、ページにその記述が無いという結果は、抽出プロンプトがそれについて尋ねなかっただけかもしれない、とも書かれています。読んだ結果の0件と、そもそも見ていない0件が区別できないという話は、ツールの仕様として公式に説明されているものです。
Readを使っても全文が入るとは限らない
原文が入る経路であるReadにも制限があります。ファイル全体の読み込みがトークンの上限を超えると、先頭の一部だけが返り、部分的な表示であるという注記が付きます。続きはoffsetとlimitで範囲を指定して読み直す必要があります。
上限は行数ではなくトークン数で決まるため、何行まで入ったかはファイルの中身によって変わります。
コンテキストに入れた情報が増えるほど、思い出す精度は落ちる
コンテキストに入れさえすれば把握される、というわけでもありません。Anthropicは、コンテキストウィンドウのトークン数が増えるほど、そこから情報を正確に思い出す能力が落ちる現象をcontext rotと呼んでいます。
渡して読ませるだけでは、漏れは防げない
移行作業では、この3つが重なります。原文が届かない経路を通り、届いた原文も一部で、入れた情報は量が増えるほど効きにくくなります。それでもAIは、渡された範囲について作業を終えたと報告します。

ここから言えるのは、ソースコードや資料を渡して読ませるだけでは漏れは防げない、ということです。何をどこまで読むかをAIの判断に任せている限り、読み落としは起き続けます。必要なのは、読む対象の範囲を人の側で確定し、その全部を原文が届く経路で読ませ、読んだ結果を1件ずつ記録させる仕組みです。読ませ方そのものを仕組みにして初めて、漏れを防げます。
なぜモダナイズの仕様の漏れに気づけないのか
AIに任せた移行で起きる3つの漏れに共通しているのは、成果物を見ても漏れが分からないことです。理由は2つあります。
理由1: 現行システムを完全に理解している人がいない
現行を隅々まで把握している人がその場にいれば「この機能が無い」と指摘できます。ただしモダナイズを検討する時点で、そういう人がいないことのほうが多いはずです。
現行の中身が分からないという状態は、モダナイズを決断できない理由であると同時に、移行後の漏れに気づけない理由にもなります。
理由2: 成果物はどれも完成品に見える
AIが出した成果物は、現行システムを知らない人から見ればどれも完成品に見えます。仕様の一覧は行が揃っています。移行後の画面も動きます。テストも成功します。それでいて、現行にあった機能や画面の要素が抜けています。
何が書かれているかは読めば分かりますが、何が書かれていないかは読んでも分かりません。
移行後のコードにテストを足しても漏れは見つからない
抜けを見つけるために移行後のコードに対するテストを足しても、同じ問題が起きます。移行後のコードを対象にテストを書けば、カバレッジは100%になります。
ただしその100%は「自分が書いたコードは全部テストした」という意味です。移行先に作らなかった機能は、カバレッジの分母に入っていません。何をテストするかの基準を移行先のコードに置く限り、移していない機能は最後まで見えません。
つまりカバレッジの数字に意味があるかどうかは、テストの分母を現行システム側に置いているか、移行先のコード側に置いているかで決まります。この違いが、後述する漏れの減らし方につながります。

仕様の漏れに気づいた後は、後追いの修正を繰り返すことになる
漏れに気づくのは、たいていモダナイズ後の動作確認の場面です。画面を操作してエラーが出たり、現行システムと結果が違ったりして、初めて何かが足りないと分かります。
修正できるのは、動作確認で見つかった1件だけ
漏れが見つかってから直すまでの流れは次のとおりです。
- 動作確認でエラーまたは現行との差分を見つける
- 原因を調べ、現行のソースコードの該当箇所を改めてAIに読ませる
- AIがその箇所の仕様を漏れとして把握し、エラーを解消するコードを書く
これで1件は直ります。ただし直るのは、動作確認で見つかった1件だけです。同じ手順を、エラーや差分が出るたびに繰り返すことになります。
この進め方では、AIに自律的にモダナイズを任せることはできません。人がエラーを見つけ、原因を特定し、AIに該当箇所を渡す、という作業が毎回必要になるためです。AIと対話しながらその場で出た不具合を直していく、いわゆるバイブコーディングで変換を進めているのと変わりません。

仕様の漏れを減らすには、テストの分母を現行システム側に置く
漏れに気づいてから直す進め方では、大量に仕様漏れがある場合に大変なので漏れそのものを減らす必要があります。そのために用意するのは、現行システムの動きを記録した一覧のようなドキュメントと、その動作を確認するためのテストコードです。モダナイズでは移行後のコードが現行と同じ動きをすることを確認しなければならないので、現行の仕様とテストコードは必ず必要になります。
用意の仕方は、現行システムにテストコードがあるかどうかで変わります。

現行にテストコードがあれば、それも一緒にモダナイズする
移行後に現行と同じテストケースを動かせるので、結果が一致するかを機械的に確認できます。現行の動きを記録したものがすでにある状態なので、移行の判定基準を新しく作らずに済みます。
この形であれば、移行後のコードで達成したカバレッジ100%に意味が出てきます。テストケースが現行から持ってきたものなので、カバレッジの分母が現行システム側にあるためです。少なくともそのテストが確認している範囲については、現行と同じ動きをすると言える根拠になります。
ただし、テストコードの移行そのものに漏れがないかは別に確認が必要です。テストケースが減っていれば、その減った分だけ確認されない機能が生まれます。
移行後にテストがすべて成功しても、テストの本数が現行より少なければ、成功したという事実は現行と同じ動きをする根拠になりません。移行前後でテストケースの数と内容を突き合わせておく必要があります。
現行にテストコードが無ければ、まず現行の仕様を漏れなく把握する
テストコードが無い場合は、まずテストコードを作ることになります。何をテストするかを決めるには、現行システムが何をしているかが分かっていなければなりません。
必要になるのは、現行システムが持っている機能と画面の要素を、細かい単位で漏れなく書き出した一覧です。この一覧がテストケースの元になり、同時に移行の判定基準にもなります。
移行の進捗も完了も、移行先のコードではなくこの一覧を基準に判定します。基準を現行側に置いておけば、移行先に作らなかった機能は「まだ移していない」という状態でこの一覧に残り続けます。
AIをうまく使うために必要なのは、より賢いAIではなく、AIが出した成果物を突き合わせる相手になる現行の仕様です。
この一覧を人が注意しながら書き出すのでは現実的な時間で終わらないので、現行のソースコードから機械的に作る必要があります。
そしてこの一覧を作る工程こそ、AIに読ませる作業そのものです。ここで読み落とせば、一覧に載らなかった機能はテストもされず、移行の判定基準からも外れます。一覧を作る段階から、読む範囲をAIに決めさせない仕組みで進める必要があります。
tenseiについて
クラスメソッドでは、この現行仕様の把握から移行までを、モダナイズ支援サービスのtenseiとして提供しています。
tenseiは、ブラックボックス化したレガシーシステムをAIで解析し、ソースコードを渡すだけでドキュメントを自動生成するモダナイズ支援サービスです。
ドキュメントを出して終わりではなく、現状分析から移行計画、実装、その後の運用保守までを一貫して支援するSIソリューションも提供しています。

まとめ
レガシーシステムのモダナイズにAIを使うと仕様の漏れが出ることを、現行のソースコードの読み込み、資料の読み込み、画面移行の3つに分けて書きました。どの漏れも、AIが出した成果物は完成品に見えるのに、現行システムと突き合わせると機能や画面の要素が抜けている、という形で表れます。
現行を完全に理解している人がいない状態では、抜けていること自体に気づけません。気づいた後も動作確認で見つかるたびに後追いで直すことになるため、AIに自律的に任せる形にはなりません。
この漏れを減らすには、テストの分母を移行先のコードではなく現行システム側に置く必要がありました。現行にテストコードがあればそれも一緒にモダナイズするのが最も確実で、無い場合は現行のソースコードから仕様を漏れなく把握してテストコードを作ることになります。いずれの場合も、ソースコードや資料を渡して読ませるだけでは足りず、読む範囲をAIに決めさせない仕組みが必要になってくるのではと考えています。
モダナイズを検討していて、現行の仕様が分からないまま移行を始めることに不安がある方の参考になれば幸いです。
レガシーシステムのモダナイズを検討しているけど、何から始めたらいいかわからないという方、現行システムの中身が分からないまま移行を進めることに不安がある方は、tenseiサービスページからお問い合わせください!











