つれづれなる Agent OPS
つれづれなる Agent OPS
AIDD

コードを書く前に要件の矛盾と抜けを確認する

Kiroの要件分析をきっかけに、受入条件の矛盾と未定義の例外経路をコード生成前の確認質問へ変える最小検証を行いました。

Xでシェア
Markdown を表示

AIコーディング支援を使うと、要件から実装の叩き台まで進む速度は大きく上がります。その一方で、要件に含まれていた曖昧さや矛盾も、以前より速くコードになります。

「削除する」と書いたとき、レコードを完全に消すのか、画面から隠して監査用に残すのか。通常経路は書かれているのに、対象が存在しない場合や、利用者が確認を取り消した場合はどうするのか。人間同士でも読み方が分かれるこの部分を、AIはもっともらしい補完で埋めて実装を進めます。コードが動いてから違和感に気づくと、問題は実装バグのように見えますが、起点は要件にあります。

この論点を正面から扱っているのが、Kiroが公開した Requirements analysis: catching requirement bugs before they become code です。同記事は、要件の粒度、曖昧さ、矛盾、完全性を別の問題として捉え、設計・タスク・コードへ進む前に確認する流れを紹介しています。特に良いと思ったのは、検出結果を形式論理のまま見せるのではなく、「どちらを意図したか」という二択の質問へ変える考え方でした。

今回はKiroの内部実装や形式化の仕組みを再現するのではなく、この考え方がAIDDの普段の要件レビューでどこまで役に立つかを、外部APIなしの小さな検証に落とします。

仕様の問題はコードレビューだけでは戻りにくい

コードレビューでは、例外処理、型、テスト、既存実装との整合性を確認できます。しかし、実装者が要件を一つ選んでコードにした後では、「別の読み方もあった」という問題を見つけにくくなります。

たとえば、削除機能に次の受入条件があるとします。

削除を確認した利用者には、物件レコードを完全に削除する。
監査のため、削除済み物件のレコードを保持する。
所有者でない利用者の削除要求は拒否する。

一文ずつ見ると、それほど不自然ではありません。しかし、最初の二つは同じ通常経路に対して「完全に消す」と「保持する」を同時に求めています。実装者が片方を選べば、もう片方を破ることになります。

さらに、次の経路には答えがありません。

  • 有効な契約が残っている物件を削除しようとした場合
  • 対象の物件が存在しない場合
  • 利用者が確認ダイアログを取り消した場合

この状態でAIへ「削除機能を実装して」と渡すと、どの挙動を採用するかはモデルやプロンプト、既存コードの文脈に依存します。動くコードが返ってきても、要件どおりだったとは言えません。

検証では状態ごとに受入条件を当てた

今回の検証用スクリプトは、固定した受入条件と5つの状態を入力にし、同時に適用されるルールの結果を比較します。対象は初期案と、書き直した改善案です。外部LLM API、Kiro、SMTソルバーは呼び出しません。したがって、自然言語を自動で形式化する精度を測る実験ではなく、要件を状態別の振る舞いに落としてから確認する価値を確かめるものです。

npm run verify は公式CLIではなく、この記事のために用意した検証スクリプトです。削除確認、権限、対象の存在、有効な契約の有無という固定入力に対して、受入条件が要求する結果を照合します。同じ状態に複数の結果が出れば矛盾、結果が一つも出なければ未定義経路として失敗させます。

npm run verify

初期案では、通常の削除に hard-deleteretain-for-audit が同時に出ました。また、有効な契約がある場合、対象が存在しない場合、確認を取り消した場合の3経路には結果がありませんでした。改善案では、受入条件を次のように書き直しています。

削除を確認した利用者には、物件を削除済みとして扱い、利用者向け画面から除外する。
削除済み物件は、監査権限を持つ利用者だけが参照できる状態で保持する。
有効な契約がある物件の削除要求は拒否し、理由を表示する。
存在しない物件の削除要求は拒否し、見つからないことを表示する。
削除確認を取り消した利用者には、削除を行わず前の画面へ戻す。

「ソフトデリートを実装する」のように方法を指定するのではなく、誰に何が見えるのか、どの条件で何を返すのかへ寄せています。ここで初めて、実装方法を複数残したままテスト可能な条件になります。

初期案と改善案における矛盾・未定義経路の比較

この画面が示すのは、改善案があらゆる要件バグを自動で防げるということではありません。今回列挙した状態に限れば、相反する結果と無応答の経路をなくせた、という確認です。状態の切り方そのものが不足していれば、この検証にも見えない穴が残ります。

返すべきは修正案より確認質問である

要件分析で最も注意したいのは、AIが自動で要件を「正しく」直したように見えることです。業務上どちらが正しいかは、コードや一般知識だけでは決まりません。

今回の初期案から返すべき質問は、次の二つです。

  1. 削除後のレコードは完全に消すのか、利用者画面から隠して監査用に保持するのか。
  2. 有効な契約がある物件、存在しない物件、確認を取り消した場合はどう振る舞うのか。

この形なら、AIは判断者ではなく、論点を取り出す補助になります。人間が選択し、選択結果を受入条件へ反映してから、設計とコードへ進めます。Kiroの記事でも、要件の正しさを最終的に確定できるのは意図を持つ利用者であり、自動化はその判断に必要な質問を減らすために使う、という位置づけです。

個人的には、この境界がかなり重要です。AIに「曖昧なところをいい感じに決めて」と頼むと、実装は前に進みます。しかし、要件上の意思決定を見えない推測へ預けることになります。質問として返せば、止まる場所は増えますが、後工程での手戻りは小さくできます。

要件レビューを実装前の短いゲートにする

毎回形式手法を導入する必要はありません。まずは、実装前に次の4点だけを見る短いゲートから始めるのが現実的です。

  1. 各受入条件に、入力条件と観測可能な結果が書かれているか
  2. 同じ条件で、相反する結果を要求していないか
  3. 成功以外の主要な経路に、拒否・中止・未存在時の振る舞いがあるか
  4. 実装方法ではなく、利用者や運用者から観測できる振る舞いで書けているか

AIには、この4点で不足箇所を列挙させることができます。ただし、優先順位、業務上許容する例外、どの振る舞いを採用するかは人間が決めます。AIへ渡す前に要件を完璧にすることが目的ではありません。コードを生成する前に、解釈の分岐を一度表へ出すことが目的です。

今回やっていないこと

今回の検証は、Kiroの要件分析機能、LLMによる自動形式化、SMTソルバーによる探索、実プロダクトの要件書に対する精度を検証していません。また、固定した5状態以外の完全性も証明していません。

ここで確認したのはもっと小さなことです。要件を通常経路の文章として読むだけでは見落とす矛盾や抜けを、状態ごとの結果と確認質問へ変換すると、実装前に人間が判断しやすくなることです。実際の導入では、失敗しやすい状態の候補を、障害履歴、問い合わせ、既存テスト、運用担当者のレビューから増やしていく必要があります。

まとめ

AIコーディングが速くなるほど、コードレビューだけで品質を守るのは難しくなります。要件の曖昧さ、矛盾、未定義の例外経路が、短時間で実装へ流れ込むからです。

今回の最小検証では、削除機能の初期案から矛盾を1件、未定義の経路を3件取り出し、観測可能な振る舞いと例外時の応答を明示した改善案で解消を確認しました。これはKiroの仕組みの再現ではありませんが、「AIに実装を頼む前に、人間が答えるべき問いを返す」という要件分析の価値は十分に見えました。

次にAIへ渡す要件では、まず「この条件で相反する結果は出ないか」「失敗時に何が起きるか」を見てみるつもりです。コードを生成する前の数分は、後から戻る数時間を減らせるかもしれません。

DUOps

Author

DUOps(デュオプス)

LLMOps、Agent、MCP、Langfuse、Cloudflare 周辺の実装と運用を、個人で試しながら記録しています。

Xを見る

コメント

Related

AIDD

Todoアプリの改修を運営者向け画面からAIに頼めるか 優先度追加と修復ループ編

第2回で確定した優先度追加の依頼を、固定した開始点から作る隔離環境へ渡しました。第1回の保存済みAI変更案はリポジトリ内テスト9件中3件と優先度絞り込みの受入条件検査に失敗しましたが、固定修復案を1回適用した後は4種類の検査に合格し、リモートGitHubを変えずにローカルcommitまで作成できました。