はじめに
第5回(修正ループ編)では、AIが不具合を直し、人が Compare and Merge で取り込み、mabl のテストで再検証するところまでを紹介しました。
最終回の今回は、この仕組みを回し続けるためのメンテナンスです。アプリもテストも、作った後に変わっていきます。O11 のモデル、mabl のワークスペース、Git リポジトリの3か所の情報を食い違わせずに保つ方法と、いつでも元に戻せるようにするバージョン管理を紹介します。
| 回 | 内容 |
|---|---|
| 1. 概要編 | なぜ独立した検証が必要か、考え方の核、全体の構成 |
| 2. 環境構築編 | Service Studio の MCP と mabl MCP を Claude Code につなぐ |
| 3. 仕様とモデルの突き合わせ編 | AIに仕様と実装の食い違いを見つけさせる |
| 4. テスト作成・実行編 | 仕様どおりの期待値で mabl のテストを作る |
| 5. 修正ループ編 | AIが直し、人が Compare and Merge で取り込む |
| 6. メンテナンス編(この記事) | 同期コマンドとバージョン管理で回し続ける |
3か所の正本と、リポジトリの役割
第2回で書いたとおり、情報の正本は3か所に分かれています。
| 情報 | 正本 | リポジトリに置くもの |
|---|---|---|
| アプリの構造(画面、ウィジェット、ロール、データ) | O11 のモデル | モデルから書き起こした画面やデータの説明 |
| テスト、プラン、環境、クレデンシャル | mabl のワークスペース | ID の対応表、テストのカタログ |
| 業務ルール(期待値) | リポジトリの business-rules.md | business-rules.md そのもの |
リポジトリには、O11 と mabl から書き写した情報があります。エージェントはここを見て作業するので、書き写した情報が古くなると、間違った ID のテストを操作したり、存在しない画面を前提にしたりします。そこで、正本と突き合わせて最新に保つためのコマンドを3つ用意しました。
3つの同期コマンド
Claude Code のカスタムコマンド(.claude/commands/ に置く Markdown ファイル)として作っています。
| コマンド | 正本 | 更新するもの |
|---|---|---|
/sync-workspace |
mabl |
workspace/ 配下のアプリ、環境、クレデンシャル、プランの対応表 |
/sync-catalog |
mabl | テストのカタログ(tests/catalog.md)と、プロンプトファイルのテスト名・ID |
/sync-o11 |
O11 のモデル |
apps/ 配下の画面、ウィジェット、エンティティ、ロールの説明 |
同期するのは事実だけ。仕様は自動で書き換えない
3つのコマンドに共通する、いちばん大事なルールがあります。正本から書き写した「事実」だけを更新し、人が決めた「仕様」には手を付けない、ということです。
| 同期してよいもの | 同期しないもの |
|---|---|
| 名前、ID、画面の構成、ウィジェットの名前と種類、エンティティの属性 | 業務ルール、期待値、画面のメッセージ、説明、テストの観点 |
特に business-rules.md は、どのコマンドでも絶対に変更しません。実装から仕様を書き起こすと、不具合が仕様として固定されてしまうからです。第1回からずっと書いてきた考え方を、メンテナンスの仕組みにもそのまま当てはめています。
/sync-o11 では、さらに Server Action のフローの中身(If の条件や Assign の値)を読まないように指示しています。同期に必要なのは構造の事実だけで、ロジックの中身を読むと、それを「仕様」として書き写したくなるからです。
## 読み取ってよいもの
- 画面、ブロック、ロール、Server Action、エンティティ、静的エンティティの一覧と定義
- 画面のウィジェットの名前と種類、画面タイトル
- エンティティの属性、型、長さ、必須、参照
- 静的エンティティのレコード名、Label、Order
- 各要素の Description
Server Action や Client Action のフローの中身(If の条件、Assign の値など)は読まないでください。
## 更新しないもの
- apps/<アプリ名>/business-rules.md は、読むことはあっても、絶対に変更しないでください。
- 説明、概要、操作と遷移、メッセージ、テスト観点など、人が書いた列や文章は変更しないでください。
## 仕様どうしの食い違い(報告だけ)
O11 モデルの Description と business-rules.md を比べ、内容が食い違っているものを報告してください。
どちらを正とするかはユーザーが判断するので、どちらも変更しないでください。
/sync-o11 が見つけたもの
/sync-o11 を実行すると、ファイルごとに「追加・更新・食い違い」の結果が返ってきます。
最後に、Description と business-rules.md の食い違いと、仕様と関係がありそうな実装上の事実がまとめて報告されます。
今回、実際に見つかったのは次のようなものです。
| 見つかったこと | 内容 | 対応 |
|---|---|---|
| Description の更新漏れ | 第3回で R1 から金額を外したのに、ValidateExpenseRequest の Description は「タイトル、カテゴリ、金額、利用日は必須」のままだった |
O11 の Description を business-rules.md に合わせて直した |
| 取り下げの記載漏れ |
ExpenseRequest と SaveDraft の Description に、申請中の申請を下書き保存すると取り下げになることが書かれていなかった |
同上 |
| 画面のロール | 申請の編集画面に、仕様の Requester のほかに Approver と Registered も付いていた。Registered はログインしたユーザー全員を指すので、申請者のロールがないユーザーでも画面を開ける | 仕様どおり Requester だけにした |
| エンティティの必須設定 | 金額を含む4つの属性に必須(Is Mandatory)が付いていて、「下書き保存では検証しない」という設計と合わない | 必須を外した |
Description の食い違いでは、「どちらを正とするか」はエージェントに決めさせず、報告だけにしています。今回は business-rules.md を正本と決めているので、O11 の Description の側を直しました。
逆に、見つかっても直さなかったものもあります。たとえば TextArea_Description は、名前は TextArea なのに実際の種類はテキストの Input でした。ただ、名前を変えると、この欄を使う mabl のテストが要素を見つけられなくなるおそれがあります。そこで名前は変えず、リポジトリの画面の説明に「名前は TextArea だが、種類はテキストの Input」と備考を書くだけにしました。ウィジェットの名前は、テストにとっては外部との約束になる、ということです。
/sync-catalog と /sync-workspace が見つけたもの
mabl 側の同期でも、次のような食い違いが見つかりました。
| コマンド | 見つかったこと |
|---|---|
/sync-catalog |
テスト 004 を「有効」にすると決めた後、カタログの状態が更新されていなかった |
/sync-workspace |
mabl のアプリケーション名の末尾に、コピー&ペーストで紛れ込んだタブ文字が入っていた |
どれも人の目では見落としやすい、小さな食い違いです。アプリケーション名のタブ文字は、エージェントが名前でアプリケーションを探したり、Agent instructions の適用範囲をアプリケーションで絞ったりするときに、一致しない原因になり得ます。
/sync-catalog では、カタログの「状態」の列は自動で更新せず、食い違いの報告だけにしています。003 と 004 は「不具合を検出して失敗中だが、テストとしては有効」という、mabl の情報だけでは判断できない意味を持たせているからです。あわせて、各テストの直近の実行結果も確かめさせ、カタログで「失敗中」と記録されていないテストが失敗していれば、想定外の失敗として報告させています。
いつ実行するか
デモの前には、次のチェックリストで環境を確かめています。同期のコマンドも、ここで一緒に実行しておくと、テストとカタログ、モデルの状態をまとめて確かめられます。
- [ ] O11 の個人環境が起動している
- [ ] Service Studio で ExpenseApp を開き、MCP サーバーが Running になっている
- [ ] servicestudio と mabl の MCP に接続している
- [ ] 承認待ち一覧に、申請中の申請が残っていない
- [ ] results/analysis/ に、前回の突き合わせの結果が残っていない
- [ ] Smoke プランを実行し、全件成功する
- [ ] Regression プランで、002 が合格し、003 と 004 が失敗する
実際の開発であれば、O11 のアプリを Publish した後や、mabl でテストを追加・変更した後に実行する、という使い方になると思います。
プランで回し続ける
テストは、mabl のプランで定期的に回します。
| プラン | 実行 | 結果の記録 |
|---|---|---|
| Smoke | 24時間ごと(自動)、デモ前(手動) | 失敗したときと、デモ前の手動実行のときだけ |
| Regression | 手動(デモ前、修正後) | 原則として毎回 |
結果の要約は、Claude Code に results/plans/ へ書かせています。ただ、毎日の自動実行の結果をすべて残すとリポジトリが記録で埋まるので、「定期実行のプランは、失敗したときとデモ前の実行だけ記録する」というルールを CLAUDE.md に書いています。
バージョンを控え、いつでも戻せるようにする
AIにモデルを変更させるなら、戻れる場所を先に作っておくことが欠かせません。
O11 の Service Center では、モジュールの過去のバージョンを、いつでも Publish し直せます。今回は、次のように管理しました。
| やったこと | 内容 |
|---|---|
| 基準のバージョンを決める | 不具合の入ったデモ用の状態を「デモ用の初期バージョン」として、番号を控える |
| OML と OAP を保存する | Service Center からダウンロードし、apps/ExpenseApp/releases/ に ExpenseApp_v15.oml のようにバージョン番号を付けて置く |
| 記録を残す |
releases/README.md に、バージョン、公開日時、ファイル、内容を表で書く |
OML も OAP も、このアプリでは数 MB だったので、通常のコミットで管理しています。大きい場合は Git LFS を使うとよいと思います。
なお、/sync-o11 で見つかった食い違い(画面のロール、エンティティの必須、Description)を直したときは、もとのデモ用の初期バージョンに戻してから直し、それを Publish したものを新しい初期バージョン(15)にしました。修正のループのリハーサルで不具合を直した状態のまま直すと、デモで見せたい不具合まで消えてしまうからです。
戻し方
不具合の入った状態に戻すときは、次の手順です。
- Service Center で、ExpenseApp のバージョン一覧から、デモ用の初期バージョン(15)の Publish をクリックする
- Service Studio で ExpenseApp を閉じて、開き直す(開いたままだと、古いモデルのまま作業してしまう)
- Regression プランを実行し、002 が合格し、004 と 003 が失敗することを確かめる
3つ目の確認までが、戻す手順の一部です。戻したつもりで戻っていない、という事故を防げます。
エージェントに答えを見せない
デモ用の環境ならではの注意点もあります。エージェントが読める場所に「答え」を置かないことです。
| 置かないもの | 理由と対応 |
|---|---|
突き合わせの結果(results/analysis/) |
不具合の場所がそのまま書いてある。.gitignore で除外し、デモの前にはリポジトリの外に移す |
releases/README.md の不具合の説明 |
「デモ用の初期バージョン」とだけ書き、どの不具合を含むかは、リポジトリの外の発表者用メモに書く |
| テストのプロンプトファイルの結果メモ | 不具合の中身(どの条件が間違っているか)は書かず、「仕様との食い違いを検出して失敗中」程度にとどめる |
答えが読める場所にあると、エージェントはそれを読んでしまいます。実際の開発でも、「AIに独立して確かめさせたいもの」と「人が知っている答え」を、置き場所で分けておくことは大事だと思います。
ハマりどころのまとめ
シリーズ全体を通して、実際につまずいたことをまとめておきます。
| 場面 | つまずいたこと | 対処 | 回 |
|---|---|---|---|
| 環境 | servicestudio のツールを並列で呼ぶと OML not found になる |
1つずつ呼ぶよう CLAUDE.md に書く | 2 |
| 環境 | 初回のアクセス許可の確認が、Service Studio の後ろに隠れる | Service Studio のウィンドウを確認する | 2 |
| 環境 | 個人環境のサーバーは UTC で動く | 日付のテストは「昨日」を使う | 2、4 |
| テスト | 一覧のページ送りで、作った申請が2ページ目に回る | 検索で絞り込んでから確認する | 4 |
| テスト | AI による判定のアサーションは、毎日の実行で結果がぶれる可能性がある | 決まった値と比べるアサーションにする | 4 |
| 修正 | Compare and Merge の画面が Service Studio の側に開き、気づかずに待ち時間切れになる | マージの段階では Service Studio に切り替える。再実行しない | 5 |
| 修正 | 変更していない画面にも Width だけの差分が出る | 元の側を選ぶ | 5 |
| 修正 | アプリを直すと、テストの後半に隠れていた不具合が見つかる | 期待値は変えずにテストを直す | 5 |
| 同期 | 書き写した情報が古くなる(Description、ロール、カタログの状態など) | 同期コマンドを定期的に実行する。仕様は自動で直さない | 6 |
シリーズのまとめ
6回にわたって、OutSystems 11 の MCP と mabl MCP を Claude Code でつなぎ、E2E テストを作る・回す・直すところまでを紹介しました。最後に、通して伝えたかったことをまとめます。
操作の手がかりはモデルから、期待値は仕様から。
O11 のモデルを読めることで、エージェントはアプリの構造を理解し、壊れにくいテストを作れます。ただし、モデルのロジックは「どこを確かめるべきか」の地図であって、「何が正しいか」の答えではありません。答えは、実装とは別に書かれた仕様から取ります。
AIが読み、人が決め、mabl が確かめる。
| 担い手 | 役割 |
|---|---|
| AIエージェント | モデルと仕様を読み、食い違いを見つけ、テストと修正を提案する |
| 人 | 仕様を決め、AIの指摘や変更を取り込むかどうかを判断する |
| mabl | コードを書いた側とは独立して、仕様どおりに動くかを確かめる |
AIエージェントに開発を任せるほど、作った側とは独立した検証が大事になります。今回の小さなデモアプリでも、AIは仕様と実装の食い違いを見つけ、仕様の書き漏れまで指摘してくれました。一方で、何が正しいかを決めるのは仕様と人であり、それを最後に確かめる仕組みが、作った側とは別にあること。それが、AIエージェントと一緒にアプリを作り続けるための土台になると考えています。
全部を一度に作る必要はありません。影響の大きい業務ルールを1つ選んで、仕様とモデルを突き合わせ、mabl でテストにするところから始めてみてください。
最後まで読んでいただき、ありがとうございました。
この記事は個人の検証結果をまとめたものです。所属する組織の公式な見解ではありません。mabl に関する記述は、公開されている製品情報とドキュメントにもとづいています。


