AIにコードを書かせているのに、人間は仕様確認と差し戻しに追われている。そんな状態になっていないでしょうか。
例えば、実装は終わった。テストも通った。それでも確認すると、「承認した後は変更できないはず」「その操作は管理者しかできないはず」という話になる。
このとき見直したいのは、コードだけではありません。そもそも、何を正解として実装を始めたのかです。
AIエージェントを使ったソフトウェア開発で、私がとにかく大事だと考えているのが、DoR(実装に着手できる状態の基準)とGherkin(期待する振る舞いをシナリオで書く言語)です。
ただし、単に「Gherkinでシナリオを書いておく」「DoRのチェック欄を埋める」という話ではありません。
私が重視しているのは、Readyにする前に、シナリオを徹底的にチェックすることです。一つひとつの記述が具体的かだけでなく、シナリオ同士に矛盾はないか、他の要件と整合しているか、つなげたときに業務全体が成立するかまで確認します。
指摘を洗い出し、必要な判断を済ませ、関連するシナリオを修正して再チェックする。そのうえでDoRを満たした仕事をAIに実装させ、合意したシナリオを基準に検証します。
AIの作業を人間が後から追いかけ続けるのではなく、任せられる仕事を作ってから任せる。そのために、この二つをセットで使います。
DoRとは?「実装を始めてよい状態」を定義する
DoRはDefinition of Readyの略で、日本語では「準備完了の定義」と呼ばれます。バックログ項目、つまりこれから取り組む個々の仕事について、「実装に着手できる状態とは何か」をチームで定める基準です。目的や範囲、受け入れ条件、依存関係、必要な情報などを確認します。出典:Atlassian
「何を作るのか」「どうなれば要求を満たすのか」「先に決めるべきことや、準備すべきものが残っていないか」が整理され、合意した条件を満たした仕事をReadyとして扱います。条件の内容は、仕事の性質やチームの運用に合わせて定めます。
似た用語にDoD(Definition of Done/完了の定義)があります。DoRは「始めてよいか」、DoDは「完了したと判断してよいか」の基準です。実装後にレビューやテストを行うことと、実装前に準備が整っているかを確認することは、役割が異なります。出典:AtlassianのDoRとDoDの比較
本稿で提案するのは、このDoRの判定に、シナリオの徹底した精査を組み込むことです。シナリオ単体だけでなく、関連するシナリオや共通ルールとの矛盾、業務全体のつながりまで確認し、実装を左右する未解決の指摘が残る仕事はReadyにしません。単にチケットのチェック欄を埋めることとは違います。
Gherkinは、DoRで精査するシナリオを具体化する
Gherkinは、システムに期待する振る舞いを「前提・もし・ならば」で具体的なシナリオとして記述するための言語です。「どんな状態で、何が起きたら、どうなるべきか」を表します。出典:Cucumber
基本構文と具体的な書き方は、Gherkin入門:前提・もし・ならばの書き方と具体例で解説しています。本稿では、そのシナリオを実装の基準にする前に、どこまでチェックするかを扱います。
Gherkinで期待する振る舞いを具体化し、DoRの判定では、そのシナリオを個別にも横断的にも精査したうえで、着手できる状態かを確認する。この記事で提案するのは、この使い分けです。
例えば「申請を編集できること」と書くだけでは、どんな申請を誰が編集できるのか分かりません。Gherkinで具体化し、関連する仕様との矛盾や未決定事項を解消する。そのうえで、依存関係や検証方法も確認してReadyにします。
Gherkinが書いてあるからReadyなのでも、DoRのチェック欄が埋まっているから仕様が正しいのでもありません。
実装とテストが、同じ誤解を共有することがある
ここからは、説明用の架空の申請システムで考えます。
「担当者が申請金額を修正できるようにしてほしい」という依頼があったとします。承認後も修正できるのか、他の担当者の申請も対象なのかは、まだ決まっていません。
この依頼をもとに、AIが「担当者は自分の申請を、承認後も修正できる」と解釈したらどうなるでしょうか。
その前提で実装し、同じ前提で「承認後に修正できること」を確認するテストを作れば、実装とテストは一致します。しかし、業務上の正解が「承認後は修正不可」なら、求められていた機能とは違います。
この例でテストが確認しているのは、採用した解釈と実装が一致していることです。その解釈が、業務上正しいことまでは確認できていません。
実装担当とテスト担当を別のAIにしても、同じ未確定の前提を採用すれば、この問題は残ります。
だから、コードとは別に、何を正解とするかを合意しておきたい。その基準を具体的に残すために、Gherkinを使います。
Gherkinを書くと、決めていなかったことが見える
次のような記述でも、「前提・もし・ならば」の形にはなっています。
# language: ja
機能: 申請の編集
シナリオ: 担当者が申請を編集する
前提 担当者がログインしている
もし 申請内容を編集する
ならば 適切に更新される
しかし、これでは「適切」が何を指すのか分かりません。
自分が作成した申請だけなのか。申請済みや承認済みでも編集できるのか。編集できない場合は、何が起こり、何が変わらないべきなのか。
Gherkinの価値は、文章を三つに分けることではありません。具体的な場面を考える過程で、こうした判断を表に出せることです。
ここでは、一般の担当者による金額修正について、「編集できるのは自分が作成した下書きだけ」「保存時点で下書きでなければ変更を拒否する」と合意したとします。申請の状態は、説明を簡単にするため、下書き・申請済み・承認済みの三つだけとします。
日本語のキーワードはGherkinで正式にサポートされています。以下では# language: jaを指定しています。出典:Cucumberの日本語キーワード
# language: ja
機能: 担当者による申請金額の修正
シナリオ: 自分が作成した下書きの金額を修正できる
前提 担当者がログインしている
かつ 自分が作成した金額1000円の下書きの申請がある
もし その申請の金額を1500円に変更して保存する
ならば 保存完了が通知される
かつ 申請を再表示すると金額は1500円である
シナリオアウトライン: 下書きではない申請は修正できない
前提 担当者がログインしている
かつ 自分が作成した金額1000円の「<状態>」の申請がある
もし その申請の金額を1500円に変更する要求を送る
ならば 変更は拒否される
かつ 申請を再表示すると金額は1000円のままである
例:
| 状態 |
| 申請済み |
| 承認済み |
シナリオ: 別の担当者が作成した下書きは修正できない
前提 担当者がログインしている
かつ 別の担当者が作成した金額1000円の下書きの申請がある
もし その申請の金額を1500円に変更する要求を送る
ならば 変更は拒否される
かつ 申請者が申請を再表示すると金額は1000円のままである
シナリオ: 編集画面を開いた後に申請済みになった場合も修正できない
前提 担当者の編集画面には自分の下書きの申請が表示されている
かつ その申請は別の操作で申請済みになっており金額は1000円である
もし 古い編集画面から金額を1500円に変更して保存する
ならば 変更は拒否される
かつ 申請を再表示すると金額は1000円のままである
正常に保存できることだけでなく、変更してはいけない条件と、拒否したときに元の金額が維持されることまで確認できます。最後の例では、画面を開いた時点ではなく、保存時点の状態で判断する必要も読み取れます。
もちろん、これだけで申請システム全体の仕様が揃うわけではありません。金額の入力範囲、通信失敗時の表示、二重送信なども、今回の変更範囲とリスクに応じて検討します。
また、業務シナリオには、原則として利用者や外部システムから確認できる結果を書きます。内部関数の名前やデータベースのテーブル名は、実装側に分けておく方が、業務担当者と確認しやすくなります。Cucumberの公式リファレンスでも、期待結果には観測可能な出力を使うことが説明されています。出典:Cucumber
DoRで見るのは、シナリオの有無ではなく、全体として成立しているか
シナリオを書き終えたところから、チェックが始まります。
「正常系がある」「異常系も書いた」「前提・もし・ならばが埋まっている」。これらは、記述が存在することの確認です。内容が妥当で、システム全体として整合することの確認とは違います。
私は、少なくとも次の三つの範囲でシナリオをレビューしたいと考えています。
レビューの範囲 | 確認すること |
|---|---|
シナリオ単体 | 前提は実際に成立するか。操作する人・対象・状態が明確か。期待結果を観測できるか。失敗したとき、変えてよいものと変えてはいけないものが決まっているか |
シナリオ同士 | 同じ条件で成功と拒否を要求していないか。権限、状態、用語、期限の扱いが揃っているか。あるシナリオの結果が、別のシナリオの前提を壊していないか |
業務・システム全体 | 一連の業務を最後まで進められるか。例外から復帰できるか。画面・API・バッチ・外部連携の扱いが食い違わないか。共通の業務ルールや非機能要件に反しないか、冪等性などは問題ないか |
単体のレビューでは、文章の意味が分かるかだけでなく、その場面が成立するかまで見ます。「退会済みの利用者がログインして操作する」という前提なら、そもそも退会後にログインできる設計なのかを確かめる必要があります。
シナリオ同士のレビューでは、別のユーザーストーリーに書かれた条件も突き合わせます。編集機能だけを読めば正しく見えても、承認機能の状態変更によって編集条件が変わることがあります。関連する仕様が別のIssueにあるからといって、確認対象から外してはいけません。
全体のレビューでは、業務を最初から最後までたどります。登録できる、承認できる、取消できる。それぞれが書かれていても、取消後にどの状態へ戻り、誰が何をできるのかがつながっていなければ、業務の途中で行き止まりになります。
同じ操作を繰り返した場合、途中で失敗した場合、別の人の操作と重なった場合も、対象の業務に応じて検討します。単にケースを増やすのではなく、状態や権限の組み合わせ、業務のつながりを確かめるためのチェックです。
個別には読めても、三つをつなぐと矛盾する
先ほどの架空の申請システムに、承認を取り消す機能を追加するとします。説明用に、次の三つのシナリオが記述された状態を考えます。
シナリオ | 記述された振る舞い |
|---|---|
A:申請の編集制限 | 担当者が申請済みの申請の金額変更を送信したら、変更を拒否する |
B:承認の取消 | 管理者が承認を取り消したら、申請の状態を申請済みに戻す |
C:取消後の修正 | 承認取消の直後、申請済みに戻った申請に対して担当者が金額変更を送信したら、変更を保存する |
それぞれの文章の意味は分かります。しかし、つなげて確認すると、Cで保存しようとしている変更をAでは拒否しています。同じ担当者・同じ状態・同じ操作に対して、期待結果が食い違っています。
ここで必要なのは、「編集のシナリオも取消のシナリオもあるからReady」とすることではありません。
承認を取り消したら下書きに戻すのか。申請済みでも取消後だけ編集できる例外を設けるのか。それとも、直接編集ではなく別の修正手続きを用意するのか。業務として採用するルールを決める必要があります。
決定後は、指摘された一文だけを直して終わりにしません。編集条件、取消後の状態、再申請や再承認など、影響するシナリオをそろえて見直し、修正が別の矛盾を生んでいないかを再チェックします。
これが、DoRで重視したい全体整合性の確認です。一つのチケットの中がきれいでも、他の機能と組み合わせたときに破綻するなら、実装してよい状態とは考えません。
矛盾を見つけたら、判断・修正・再チェックまで行う
シナリオ同士の違いが、すべて矛盾とは限りません。対象者や契約プラン、適用時期が異なるなら、期待結果が違うことはあり得ます。その区別が前提として明示されているかを確かめます。
一方で、前提の区別がないまま結果だけが異なるなら、AIに都合のよい例外を補わせて解消したことにしてはいけません。例外があるのか、古い記述が残っているのか、本当に方針が決まっていないのかを、根拠になった要求や決定と照合します。
単に投稿日時が新しいという理由だけで、正式な決定より優先しないことも大切です。現在の実装も現状把握のために確認しますが、それが正しい仕様だとは決めつけません。今回直す不具合なら、既存の挙動と異なること自体は問題ではありません。
レビュー結果は、例えば次のように残します。これも説明用の記入例です。
判定:Readyにしない。
対象:シナリオA・B・C。
指摘:Bで申請済みに戻った申請への金額変更を、Aは拒否し、Cは保存する。
確認事項:承認取消後の状態と、担当者が修正できる条件を業務責任者に確認する。
修正範囲:決定内容に応じて、編集・取消・再申請・再承認の関連シナリオを更新する。
再確認:更新したシナリオを共通の状態遷移・権限ルールと突き合わせ、矛盾が解消されたかを確認する。
「確認が必要」というコメントを付けたり、担当者と期限を決めたりしただけでは、指摘は解消していません。今回の実装を左右する判断なら、回答を仕様とシナリオに反映し、再チェックするまではReadyにしません。影響しない部分を先に進めるなら、仕事を分割します。
また、「矛盾なし」という結論だけでなく、何を確認したのかを残します。対象のシナリオIDと版、照合した共通ルール、見つけた指摘と解消理由、未確認の範囲が分かることが必要です。関連資料を取得できなかった状態と、取得してレビューした結果、問題が見つからなかった状態を混ぜません。
レビューで未知の欠陥までなくなったと証明するわけではありません。それでも、必要な範囲を確認していないのに「指摘が出なかったからReady」とすることは避けられます。
AIに渡す前に確認したいDoRの条件
ここまでの考え方を運用に落とすなら、私は次のような条件から始めます。一般的なDoRの唯一の正解ではなく、AIエージェントに実装を任せるための運用例です。
確認すること | Readyと判断するための状態 |
|---|---|
目的と範囲 | 誰の何を解決するのか、今回作る範囲と対象外が分かり、照合すべき関連仕様が特定されている |
シナリオ単体のレビュー | 前提・操作・期待結果を具体的に検討し、必要な正常系・異常系・境界条件の不足を補っている |
シナリオ横断のレビュー | 関連するストーリーのシナリオも含め、権限・状態・データ・用語などの既知の矛盾が解消されている |
業務全体のレビュー | 業務の入口から完了までと、必要な例外・復帰経路がつながり、共通ルールや非機能要件との整合を確認している |
判断と再チェック | 実装を左右する未決定事項が解消され、合意した修正を関連シナリオに反映し、修正後の整合性も再確認している |
実行・検証の条件 | 依存関係、作業権限、必要な環境・データ、検証方法が整理され、採用する仕様の版とレビューの根拠を参照できる |
Gherkinにすべてを詰め込む必要はありません。状態遷移表や権限表、構成上の制約、性能試験の条件などは別の資料に置き、シナリオと突き合わせられるようにします。重要なのは資料の数ではなく、記述同士が整合し、実装と検証の基準として使えることです。
Readyにする作業にもAIを使う
DoRを重視するというと、人間に細かい書類仕事を増やす話に聞こえるかもしれません。私がやりたいのは、逆です。
実装前の整理にもAIを使い、人間が判断しなければならない点を絞りたい。
まず、会話や議事録から、決定事項と未確定事項を分けます。要求を具体例にし、Gherkinのたたき台を作る。その後、文章を整える作業とは分けて、シナリオ単体・シナリオ同士・業務全体のレビューを行います。
AIに依頼する際も、「問題がないか確認して」だけで終わらせず、どのシナリオのどの条件が衝突するのか、どの業務経路が成立しないのかを、参照先とともに挙げさせます。共通の状態や権限は表でも照合し、不足する例外や境界条件を検討します。確認が必要な部分は、業務担当者が答えられる質問にします。
例えば「状態遷移後の更新可否を定義してください」ではなく、「申請を送信した後に金額の誤りに気づいた場合、そのまま修正してよいですか」と聞く。その回答を、要件とシナリオへ反映します。
ただし、AIの提案は決定事項ではありません。AIが補った前提と、関係者が合意した内容を混ぜないことが重要です。参照した根拠や、未確認の資料も分かるようにしておきます。
AIがシナリオを作り、そのAI自身が「問題ありません」と言っただけで完了にせず、元の要求、共通ルール、業務担当者の判断に照らして確認します。別のAIによるレビューを加える場合も、独立した正解が自動的に得られるわけではありません。指摘を根拠で検討し、修正後の関連シナリオまで再チェックする工程が必要です。
社内でも、DoRを満たすまで要件を固め、精査してから実装を進める方針を共有しています。単に作業を止める条件を増やすのではなく、Readyな仕事を用意する工程を作るということです。
そのうえで、Readyになったものから、優先度と依存関係を見て実装へ送ります。Readyであることと、無条件に並列実行してよいことは別です。同じ部分を変更する作業や、先行する変更が必要な作業は、順序を調整します。
Gherkinを、実装・PR・テストまで切らさない
実装前に合意したGherkinも、実装担当やレビュアーが参照しなければ基準として使えません。
だから、仕事を渡すときには、対象のシナリオとその版を明示します。PR、つまりコード変更のレビュー単位からも、対応するシナリオをたどれるようにします。私自身、PRにタスクのGherkinを載せる案を社内で出しています。
ここで一つ、誤解しやすい点があります。Gherkinを書いただけで、自動テストが実行できるわけではありません。
Cucumberでは、各ステップを実際の操作や検証を行うコードに結び付ける「ステップ定義」が必要です。シナリオに書いた期待結果を、本当に検証しているかも確認しなければなりません。出典:Cucumberのステップ定義
例えば「変更が拒否される」と書いたのに、テストがエラーメッセージの表示だけを確認し、金額が書き換わっていないかを確認していなければ、検証が足りません。
私は、シナリオのIDと版、対象の変更、テスト環境、実行結果、必要な証拠を対応させたいと考えています。未実行やスキップは、合格とは分けて記録します。基本的この辺の情報は自動テストに埋め込んで追えるようにしています。
自動化しない確認があっても構いません。その場合も、どのシナリオを、どの環境で、誰がどう確認したのかを残します。
また、テストを通すために、実装に合わせてシナリオの期待結果を弱めてはいけません。仕様を変える必要があるなら、実装の都合とは分けて判断し、合意を更新します。
全仕様を最初に固定する話ではない
DoRを重視することと、プロジェクト全体の仕様を最初に確定することは別です。
Readyにするのは、次に取り組む仕事です。ただし、Readyと判定する単位が一件でも、レビューする範囲をその一件に閉じてよいわけではありません。その仕事が影響する機能や共通ルールまで確認します。
作ってみないと分からないことがあるなら、「本番機能を完成させる仕事」と混ぜず、「何を確かめるための試作か」を決めて切り出します。
調査や試作なら、確認したい問い、試す範囲、終了条件、結果を受けて判断する人を明確にし、必要な環境や権限も確認します。すべての仕事に、同じ量のGherkinや資料を要求したいわけではありません。
実装中に前提が変わった場合も同じです。
「承認後でも一度だけ修正できる」に変更するなら、拒否するシナリオ、再承認の扱い、権限、関連テストを見直します。影響する仕事は、以前Readyだったからといって、そのまま進めません。
DoRは一度押したら終わりの承認印ではなく、今参照している仕様で着手できるかを確かめるために使います。こんな感じで自分はループの設計して何サイクルも回して仕上げています。大事なのはDoRをひたすらチェックし続けることですかね。
最初は、次にAIへ渡す一件から始める
導入のために、最初から管理ツールを入れ替える必要はありません。私なら、まず既存のIssueやドキュメントで、次の一件を整理します。
誰が、どんな状態で、何をしたら、どうなるのかを書く。正常な場合だけでなく、拒否すべき場合や境界も考える。そして、そのシナリオを単体でも、関連するシナリオとつないでもチェックする。矛盾や業務の行き止まりが見つかったら、判断を求め、関連する記述を修正し、もう一度確認します。
このレビューを経て、実装に影響する指摘を解消し、実行と検証に必要な条件が揃った仕事をReadyにします。「書いた」からではなく、「実装の基準として使えるところまで精査した」から着手する、という順番です。
実装後は、そのシナリオをもう一度開き、期待した結果になっているかを確認します。
AIにコードを書かせる前に、「この仕事は何をもって正解とするのか」「今、本当に始められるのか」を揃える。
Gherkinで期待する振る舞いを具体化する。DoRの判定では、そのシナリオの矛盾と全体整合性を徹底的にチェックする。判断・修正・再チェックを済ませた基準を、実装・レビュー・テストまでつなげる。
AIエージェントに開発を任せるほど、大事なのはシナリオを書く量ではなく、実装前にどこまで内容を精査したかだと考えています。
自分はこの辺の作業めんどくさいので、mcpで問題あるシナリオある?とか自社で作ったpm on railsという管理osエージェントと壁打ちしながら進めています。宣伝ではなく便利です。https://pmonrails.com/ グラフデータベースで関係追えるようにしてるので、全体での抜け漏れチェックしやすいんですよね。issueとかjiraだとこの辺がきついですね。