はじめに
第1回(概要編)で考え方を、第2回(環境構築編)で環境を用意しました。
第3回の今回は、いよいよエージェントに仕事をしてもらいます。テストを作る前に、O11 のモデルを読ませて業務ルールと突き合わせ、仕様と実装の食い違いを見つけさせます。
| 回 | 内容 |
|---|---|
| 1. 概要編 | なぜ独立した検証が必要か、考え方の核、全体の構成 |
| 2. 環境構築編 | Service Studio の MCP と mabl MCP を Claude Code につなぐ |
| 3. 仕様とモデルの突き合わせ編(この記事) | AIに仕様と実装の食い違いを見つけさせる |
| 4. テスト作成・実行編 | 仕様どおりの期待値で mabl のテストを作る |
| 5. 修正ループ編 | AIが直し、人が Compare and Merge で取り込む |
| 6. メンテナンス編 | 同期コマンドとバージョン管理で回し続ける |
題材のアプリ
題材は、O11 で作った経費申請アプリです。申請者が経費を申請し、承認者が承認または差し戻します。
| ロール | できること |
|---|---|
| Requester(申請者) | 申請の作成・編集・申請 |
| Approver(承認者) | 申請中の申請の承認・差戻し |
承認者は申請者のロールも持っていて、自分でも申請できます。この設定が、後で問題になります。
画面からは見えない業務ルール
このアプリには、画面を触るだけでは分からない業務ルールが15項目あります。実際の会社であれば、経費精算規程などに書かれている内容です。リポジトリの business-rules.md に、テストの期待値の正本として書いてあります。
| 分類 | ルール |
|---|---|
| 入力 | R1 タイトル、カテゴリ、利用日は必須 / R2 金額は1〜1,000,000円 / R3 未来の日付は不可 / R4 接待費、または50,000円以上は説明が必須 |
| ステータス | S1 ステータスの遷移と取り下げ / S2 差戻し後は再申請できる / S3 承認済の申請は編集できない |
| 承認 | A1 Approver ロールが必要 / A2 承認は申請中のみ / A3 差戻しは申請中のみ / A4 差戻しはコメント必須 / A5 自分の申請は承認できない |
| 参照範囲 | V1 申請一覧は自分の申請だけ / V2 承認待ちは申請中のすべて |
デモのために、このうち2つの実装に、よくある種類の不具合をわざと入れてあります。どれかは、エージェントに見つけてもらいます。
突き合わせのプロンプト
依頼は、プロンプトをファイルにしてリポジトリに置き、Claude Code にはそのファイルを実行するように頼みます。
Claude Code への依頼は、次の2行だけです。
prompts/analysis/spec-vs-model.md のプロンプトを実行してください。
終わったら、判定結果の表をこの画面にも表示してください。
プロンプトファイルの本体は、次のとおりです。
# 仕様と O11 モデルの突き合わせ
業務ルール(business-rules.md)と、O11 モデルの実装を比較し、食い違いと、
それを検出する mabl テストの計画を作るプロンプトです。
## 前提
- Service Studio で対象モジュール(例: ExpenseApp)を開き、MCP サーバーを起動しておく。
- `servicestudio` と `mabl` の MCP に接続済みであること。
## プロンプト
Service Studio で開いている ExpenseApp モジュールを `servicestudio` MCP で読み取り、
apps/ExpenseApp/business-rules.md の各ルールについて、実装を確認してください。
1. ルールごとに、対応する画面・Server Action・条件式を特定してください。
2. 実装がルールどおりか判定し、次の表にまとめてください。
| ルール | 実装箇所 | 判定(一致 / 不一致 / 実装なし) | 根拠 |
3. 不一致・実装なしのものについて、mabl のテストで検出するための手順と期待結果を書いてください。
期待結果は必ず business-rules.md に合わせてください。
4. 結果を `results/analysis/YYYY-MM-DD_spec-vs-model.md` に保存してください。
## 注意
- O11 モデルは変更しないでください。
- 実装を正として business-rules.md を書き換えないでください。
いちばん大事なのは、「期待結果は必ず business-rules.md に合わせる」と「実装を正として business-rules.md を書き換えない」の2か所です。エージェントは食い違いを見つけると、気を利かせて仕様の側を実装に合わせようとすることがあります。それを防ぐために、はっきり書いておきます。
プロンプトをファイルにしておくと、誰が実行しても同じ依頼になり、後から内容を見直すこともできます。
エージェントが Service Studio のモデルを読む
実行すると、エージェントは servicestudio の MCP ツールを使って、Server Action を1つずつ読んでいきます。
画面の内容をスクリーンショットで推測するのではなく、モデルそのもの(Server Action のフロー、If の条件、画面のウィジェット、ロールの設定)を読んでいるのがポイントです。
判定結果
15項目のうち、2つの食い違いが見つかりました。
R4 は不一致でした。ValidateExpenseRequest の「説明必須チェック」の条件が Amount > 50000(超)になっていて、仕様の「50,000円以上」と合いません。50,000円ちょうどだと、説明なしで申請できてしまいます。
A5 は実装なしでした。ApproveRequest の Description には「承認者は自分の申請を承認できない」と書かれているのに、申請者本人かどうかを確かめるチェックがロジックにありません。
わざと入れた2つの不具合(境界値の勘違いと、権限の確認漏れ)を、どちらも正確に見つけ、どの Server Action のどの条件かまで特定しています。
分からないことは、分からないと書く
判定結果の表で、もう1つ感心したところがあります。R3(未来の日付は不可)の行で、エージェントは「Server Action 内の UsageDate > CurrDate() で判定している。サーバーが UTC かどうかはモデルからは確認できない」と書いていました。
第2回で書いたとおり、個人環境のサーバーは実際に UTC で動いています。モデルから読み取れないことを推測で埋めず、確認できないと明記してくれるのは、判定の結果を信用するうえで大事な性質です。
仕様の曖昧さまで指摘してくれる
判定の表とは別に、エージェントは「仕様に書かれていない点」も挙げてきました。
| 指摘 | 内容 |
|---|---|
| 差戻しから下書きへの遷移 | 実装では、差戻しの申請を下書き保存すると下書きに戻る。S1 にはこの遷移が書かれていない |
| 申請時のチェックの順序 | 申請では入力の検証が承認済のチェックより先に行われる。承認済の申請を不正な入力のまま送ると、S3 ではなく R1〜R4 のメッセージが返る |
| 申請者の上書き | 下書き保存と申請で、申請者が操作したユーザーに上書きされる |
実際の仕様書にも、曖昧な箇所は必ずあります。テストを作る前にそれが見つかるのは、仕様のレビューとしても価値があります。どう決めるかは、人が判断します。
直すのは仕様か、実装か
食い違いが見つかっても、いつも実装の側が間違っているとは限りません。
実は、最初に突き合わせを実行したときは、R1 も「不一致」と判定されていました。
当時の仕様は「タイトル、カテゴリ、金額、利用日は必須」で、エージェントは「必須チェックに金額が入っていない。金額を入れずに申請すると、R1 ではなく R2 のメッセージ(金額は1円以上)が出る」と指摘しました。あわせて、仕様の確認事項として「O11 の数値入力は空欄だと0になる。0を入力したときに R1 と R2 のどちらのメッセージを出すかを、仕様で決めておく必要がある」とも挙げていました。
確認してみると、これは仕込んだ不具合ではなく、仕様を書いた側の誤りでした。実装では、金額が未入力だと0になるので、もともと R2 の金額範囲のチェックで扱う設計です。それなのに、仕様を書くときに R1 の必須項目にも金額を入れてしまっていました。エージェントが確認事項で挙げた「未入力と0の区別」も、同じ問題を指していたことになります。
そこで、実装ではなく仕様を直すことにし、Claude Code に次のように依頼しました。
business-rules.md を次のように更新してください。
- R1 の必須項目から金額を外し、R2 に「金額の未入力は 0 として扱い、このルールで判定する」と追記する。
- S1 に「申請中の申請は、下書き保存すると取り下げとなり、下書きに戻る」と追記する。
- 最後に「今回のデモの対象外」の節を追加し、URL を直接指定して他ユーザーの申請を開く・保存する問題を対象外とする。
更新したら、分析結果のファイルも新しい仕様に合わせて更新してください。
commit はしないでください。
確認事項の残り2つ(申請中の申請を下書き保存したときの扱い、他のユーザーの申請を URL で開ける問題)も、このときに仕様として決めています。更新後の判定は、一致13、不一致1(R4)、実装なし1(A5)となり、仕込んだ2つだけが残りました。
| AI の指摘 | 人の判断 | |
|---|---|---|
| R1 | 金額を空にすると、R1 ではなく R2 のメッセージが出る | 仕様を書いた側の誤り。仕様を直す |
| R4 | 条件が「超」になっていて、仕様の「以上」と合わない | 実装の不具合として直す(第5回) |
| A5 | 本人かどうかのチェックがない | 実装の不具合として直す(第5回) |
AI は食い違いを見つけて指摘しますが、仕様と実装のどちらを直すかは人が決めます。プロンプトで「仕様を書き換えない」と指示しているのは、この判断をエージェントに勝手にさせないためです。
Description も、ずれることがある
この R1 の件には続きがあります。仕様を直した後、ValidateExpenseRequest の Description には「タイトル、カテゴリ、金額、利用日は必須」と古い内容が残っていました。第6回で紹介する同期のコマンドが、この食い違いを見つけてくれました。
A5 の件と合わせると、Description は次のどちらのずれ方もすることが分かります。
- Description には書いてあるのに、実装にはない(A5)
- 仕様を直したのに、Description だけ古いまま(R1)
Description はエージェントにとって大事な手がかりですが、正本にはせず、実装とは別に書かれた仕様と突き合わせるのがよいと考えています。
まとめ
| やったこと | ポイント |
|---|---|
| プロンプトをファイルにして実行 | 「期待結果は仕様に合わせる」「仕様を書き換えない」を明記 |
| エージェントがモデルを読む | Server Action やロールなど、モデルそのものから判定する |
| 判定結果 | 仕込んだ2つの不具合を、場所まで特定して指摘 |
| 仕様の曖昧さ | 仕様に書かれていない点も挙げてくる |
| 直す側の判断 | 仕様と実装のどちらを直すかは人が決める |
次回は、この突き合わせの結果をもとに、仕様どおりの期待値で mabl のテストを作り、実行します。
この記事は個人の検証結果をまとめたものです。所属する組織の公式な見解ではありません。mabl に関する記述は、公開されている製品情報とドキュメントにもとづいています。







