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

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

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

Xでシェア
Markdown を表示

要件確定からコード変更へ

このシリーズでは、Gitやターミナルを操作しないTodoアプリの運用担当者が、専用Web画面からAIへ改修を頼める仕組みを段階的に作っています。 最終目標は、自然文の依頼から確認質問、要件確定、隔離環境でのコード変更、テスト、GitHubのDraft PR(正式なレビュー前の下書き)までをつなぐことです。 最後に10種類の改修を実行し、既存のコーディングエージェントへ人間が手作業で依頼する方法と比べます。

自然文で改修を依頼

不足事項への質問と要件確定       第2回までに確認

隔離環境でコード変更

固定テストに失敗したら上限内で修復 第3回で確認

合格した変更だけローカルcommit    第3回で確認

GitHubのDraft PR                 第5回で検証予定

第1回では、3社のAI APIを同じ形式へつなぎ、コード変更案が固定テストに失敗したとき、GitHubへ送る前に停止できることを確認しました。 ただし、コード変更案は7ファイルまで作れたものの、テストは9件中3件が失敗したままです。

第2回では、「Todoに優先度を付けたい。見やすくして」という依頼に4件の確認質問を返し、人間が回答、編集、確定したあとにだけ変更ジョブを発行しました。 発行したジョブは次の工程待ちで止まり、コード変更には接続していませんでした。

第3回は、この二つをつなぎます。 確定済みの変更ジョブから第1回の変更案を起動し、失敗結果を修復処理へ渡して、実際のTodoアプリで優先度を絞り込めるところまで進めました。

優先度追加を隔離環境へ渡す

検証計画では、優先度追加を「S01」と記録しています。 S01は「Scenario 01」を省略した管理用IDで、難易度や優先順位を示す番号ではありません。

第2回で確定した内容は次のとおりです。

  • 優先度はlowmediumhighの3段階にする
  • 既存Todoと未指定時の初期値はmediumにする
  • 一覧では色と文字を併用したバッジで表示する
  • 優先度と既存の状態を同時に絞り込めるようにする
  • 許可していない優先度はAPIが400を返す
  • 優先度は色だけに頼らず、文字でも判別できるようにする

「変更ジョブを開始」を押すと、サーバーは人間の確定状態をもう一度検査します。 条件を満たした依頼だけが、固定した開始時点から複製した隔離環境へ渡ります。

モデルに渡すのは、許可したソースと確定済み要件です。 モデルはファイルを直接書き換えず、変更案だけを返します。 書き込みを行う実行器は、マイグレーション、アプリ本体、画面、テストの許可範囲から外れるパスを拒否します。

今回、新しい外部AI API呼び出しは行っていません。 第1回でさくらのAI Engineから得た変更案を保存し、同じ失敗を再現できる入力として使いました。 変更案を作ったときのAPI呼び出しは1回ですが、第3回の再実行におけるAPI呼び出しは0回です。

最初の変更案で落ちた三つのテスト

保存済みの変更案は、優先度用のマイグレーション、入力検査、保存処理、作成フォーム、一覧のバッジ、テストを含む7ファイルでした。 許可パスの検査を通したあと、隔離環境へ適用してテストを実行しました。

結果は、第1回と同じ9件中6件成功、3件失敗です。

失敗したテスト変更案との食い違い
マイグレーション後の列一覧優先度列を追加したのに、追加前の列だけを期待していた
既存Todoの初期優先度検査するTodoを作らず、存在しない行を読んでいた
入力値の整形初期優先度mediumが返るようになったのに、古い期待値のままだった

いずれも、優先度を追加するコードそのものではなく、変更後の契約と同時生成されたテストが食い違った失敗です。 テストを生成したからといって、そのテストが変更後の仕様を正しく表しているとは限りません。

ここで3件の期待値だけを直せば、リポジトリ内テストは通せます。 しかし、それでは「優先度と状態を同時に絞り込める」という確定要件を満たしたことにはなりませんでした。

生成テストが見逃した優先度の絞り込み

最初の変更案は、優先度を保存し、作成フォームから選び、一覧へ文字で表示するところまで実装していました。 一方、APIと画面には優先度の絞り込みがありません。

リポジトリ内テストは、この不足を検出していませんでした。 生成されたコードとテストが、そろって同じ要件を落としていたからです。

そこで、実行器が書き換えない場所へ受入条件検査を置きました。 これは記事用に用意した検証プログラムで、隔離環境のTodo APIへ優先度の異なる3件を登録し、status=openpriority=highを同時に指定したとき、該当する1件だけが返るかを確認します。 許可していない優先度の拒否、既存Todoのmediumへの移行、画面上の文字付きバッジも同じ検査に含めました。

最初の変更案に対する結果は不合格です。 priority=highをAPIへ渡しても無視され、状態だけで絞り込まれた複数件が返りました。

生成されたテストだけを合否判定に使うと、生成側の見落としまで評価側が引き継ぎます。 確定要件を別の検査へ固定したことで、「テストは直せたが、機能は足りない」という成功扱いを避けられました。

修復後の四つの検査

初回の失敗後、実行器は失敗した検査名と終了コードを修復処理へ渡しました。 今回の修復処理は外部AIではなく、同じ結果を繰り返し検証するための固定案です。

修復案では、生成テストの期待値を変更後の契約へ合わせるだけでなく、次の不足も補いました。

  • APIで優先度を検査し、状態と同時に絞り込む
  • 画面へ優先度の絞り込み欄を追加する
  • の文字を持つバッジを追加する
  • 優先度と状態を同時指定するAPIテストを追加する
  • 許可していない優先度の絞り込みを拒否するテストを追加する

修復後は、変更ファイルが7件から10件になりました。 再実行した検査は次の4種類です。

検査結果
リポジトリ内テスト12件中12件成功
JavaScriptの構文と画面部品の検査成功
既存データをmediumへ移す検査成功
優先度機能の受入条件検査成功

すべて成功したあとにだけ、実行器はai/s01-priorityというローカルbranchへcommitしました。 リモートGitHubへのpushとDraft PR作成は行っていません。

最初の変更案はテスト6/9件と受入条件検査に失敗し、固定修復案を1回適用したあとに4種類の検査へ合格した変更ジョブ画面

変更ジョブ画面には、固定した開始点、変更した10ファイル、修復後の検査、ローカルcommitを表示しました。 利用者はターミナルを開かず、初回に何が失敗し、何回修復し、最終的にどの検査へ合格したかを確認できます。

変更した10ファイルと、修復後に4種類の検査がすべて成功したことを表示するコード変更ジョブの結果欄

改修後のTodo画面

検査が通っただけでは、運用担当者が使える画面になったかは分かりません。 修復後のTodoアプリを起動し、Playwrightで優先度を選びました。

一覧には、高い優先度を持つ1件だけが残りました。 同じ画面に状態の絞り込みもあり、APIではstatuspriorityの同時指定を検査済みです。 バッジは色だけでなく「優先度 高」という文字を持っています。

優先度の絞り込みで「高」を選び、文字付きの「優先度 高」バッジを持つTodoが1件だけ表示された改修後のTodoアプリ

第2回で人間が追記した「色に頼らず文字でも判別できる」という受入条件が、ここで初めて実際の画面へ現れました。 要件画面で確定できるだけでは足りず、コード変更後の検査がその文言と結び付いている必要があります。

修復ループをどこで止めるか

修復を無制限に続けると、API利用量と実行時間が増えるだけでなく、同じ原因へ似た修正を重ねる可能性があります。 実行器には、修復を最大3回で止める条件を入れました。

もう一つの停止条件は、同じ検査失敗が2回続くことです。 失敗した検査名と終了コードから識別値を作り、修復前後で同じ値になった場合は、次の修復を始めません。

今回は1回目の修復で全検査が成功したため、停止条件には到達しませんでした。 最大回数と同一失敗の停止については、実行器の単体テストで確認しています。

この挙動を再現するnpm run verify:code-jobは、この記事用に作った検証スクリプトです。 固定した優先度追加の依頼を変更ジョブへ入力し、隔離環境の作成、保存済み変更案の適用、初回検査、固定修復案、再検査、ローカルcommitまでを確認します。

npm run verify:code-job
first pass: 6/9 repository tests, acceptance=failed
repair attempts: 1
final checks: 4/4
changed files: 10
remote GitHub changed: false

固定修復案で残った課題

第3回で、確定済みの依頼から隔離環境を作り、保存済みのAI変更案を適用し、失敗後の修復を経て、動作するTodoアプリのローカルcommitまで到達できました。 第2回まで別々だった要件確定とコード変更が、専用Web画面の一つの操作としてつながっています。

一方、「修復ループが動いた」を「AIが自力で不具合を直せた」と読むことはできません。 修復案は固定しており、失敗ログから修正内容を考えたのは実AIではないからです。 自由な変更依頼に対する修復品質、同じ失敗が続いたときの人間への返し方、別種類の改修でも受入条件検査を用意できるかは未検証です。

したがって、第3回の判断も**Conditional Go(条件付きで継続)**です。 チャットからローカルコード変更までの経路と停止条件は成立しましたが、実AIによる修復と、複数種類の変更に対する再現性はまだ評価できません。

次の判断材料は、優先度追加だけに合わせた固定処理を外したときにも、同じ安全境界を保てるかどうかです。 期限日、タグ、CSV出力、要件不足、危険な依頼を同じ実行器へ通すと、今回の4/4が一例にすぎないのか、再利用できる仕組みなのかが見えてきます。

DUOps

Author

DUOps(デュオプス)

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

Xを見る

コメント

Related