Todoアプリの改修を運営者向け画面からAIに頼めるか 優先度追加と修復ループ編
第2回で確定した優先度追加の依頼を、固定した開始点から作る隔離環境へ渡しました。第1回の保存済みAI変更案はリポジトリ内テスト9件中3件と優先度絞り込みの受入条件検査に失敗しましたが、固定修復案を1回適用した後は4種類の検査に合格し、リモートGitHubを変えずにローカルcommitまで作成できました。
要件確定からコード変更へ
このシリーズでは、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回で確定した内容は次のとおりです。
- 優先度は
low、medium、highの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=openとpriority=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作成は行っていません。

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

改修後のTodo画面
検査が通っただけでは、運用担当者が使える画面になったかは分かりません。
修復後のTodoアプリを起動し、Playwrightで優先度高を選びました。
一覧には、高い優先度を持つ1件だけが残りました。
同じ画面に状態の絞り込みもあり、APIではstatusとpriorityの同時指定を検査済みです。
バッジは色だけでなく「優先度 高」という文字を持っています。

第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が一例にすぎないのか、再利用できる仕組みなのかが見えてきます。