はじめに
AI コーディングエージェントに「この機能を実装して」と頼むと、実装自体は進みます。しかし、完了の定義が曖昧だと、最後に次の確認が残ります。
- 通常動作は満たしたが、エラー時の動きが未確認
- 認可や利用条件が本文に出てこない
- テストは通ったが、何を確認したテストか分からない
- no-regression の観点が抜けている
この問題を減らすために、実装前に「完成条件」を短く宣言する Sprint Contract(本記事での独自の呼び名)を置くようにしました。
詰まったポイント
AI に実装を頼むと、最初に見える happy path はかなり速く作れます。
一方で、依頼文が薄いと次のような抜けが起きます。
- ログイン済み前提なのに、未ログイン時の扱いがない
- API 失敗時に画面へ何を出すか決まっていない
- 既存の保存形式や設定値との互換性を見ていない
- テストが「正常に保存できる」だけで、重複実行や invalid input を見ていない
実装後にこれを直すと、コードだけでなくテスト、UI 文言、エラー処理まで戻ることになります。
原因
原因は、実装タスクを「作るもの」だけで渡していたことでした。
人間なら会話の中で補完する前提条件でも、AI に渡すときは明示しないと抜けます。特に次の観点は、依頼文に入っていないと後回しになりがちです。
- 通常動作
- 利用前提や認可
- invalid input
- エラー処理
- 重複操作や再実行
- 既存機能の no-regression
そこで、作業開始前にこれらを完成条件として宣言するようにしました。
Sprint Contract の最小テンプレート
自分の運用では、実装前に次の形で書きます。
完成条件: - 通常動作: - 前提条件・認可: - invalid input: - エラー処理: - 重複操作・再実行: - no-regression: 検証: - 手動確認: - 自動テスト: - 実行コマンド:
すべてを埋める必要はありません。該当しないなら
該当なしと書きます。
重要なのは、実装前に「今回は見ない」と決めた観点も明示することです。未定義のまま進めるより、後でレビューしやすくなります。
記入例
たとえば、設定画面に「通知を有効化する」トグルを追加するなら、次のように書けます。
完成条件: - 通常動作: - 設定画面で通知トグルを変更できる - 保存後に再表示しても値が維持される - 前提条件・認可: - ログイン済みユーザーの設定だけを更新する - 他ユーザーの設定 ID を指定しても更新しない - invalid input: - boolean 以外の値はサーバー側で拒否する - エラー処理: - 保存失敗時は画面に短いエラーメッセージを出す - スタックトレースや内部パスは出さない - 重複操作・再実行: - 同じ値で保存しても余計な副作用が出ない - no-regression: - 既存のプロフィール保存が壊れない 検証: - 自動テスト: - 正常保存 - 他ユーザー ID の拒否 - invalid input の拒否 - 実行コマンド: - npm run test - npm run build
この状態で AI に渡すと、実装後の自己チェックやテスト追加の観点が揃います。
テスト観点も先に渡す
テストを後から「いい感じに書いて」と頼むと、happy path だけになることがあります。
実装前に、最低限次を渡します。
テスト観点: - normal: 有効な入力で保存できる - boundary: 空文字、最大長、0件など境界値を扱う - invalid: 不正な型や範囲外の値を拒否する - authorization: 他ユーザーのデータを更新できない - idempotency: 同じ操作を2回しても副作用が増えない - regression: 既存の主要フローが壊れない
全部のテストを毎回書く必要はありません。小さい変更なら normal と regression だけで足りることもあります。
ただし、認可、課金、外部 API、永続データを触る変更では、invalid、authorization、idempotency を省くと後で戻りやすいです。
AIへの依頼文に混ぜる例
実際に頼むときは、完成条件と対象範囲を一緒に渡します。
次の範囲だけ実装してください。 対象: - src/settings/notification.ts - src/settings/notification.test.ts 完成条件: - 通知設定を保存できる - boolean 以外の入力は拒否する - 保存失敗時に内部例外をユーザーへ出さない - 同じ値で2回保存しても結果が変わらない - 既存の設定読み込みテストが通る 検証: - npm run test - npm run build 触らない: - 認証まわり - package.json - unrelated formatting
ここまで書くと、AI は「何を作るか」だけでなく「何を壊してはいけないか」も見ながら作業できます。
注意点
Sprint Contract を細かくしすぎると、実装前の準備だけで重くなります。
自分は次の基準で粒度を変えています。
| 変更の種類 | 完成条件の粒度 |
|---|---|
| 文言修正、単純な表示変更 | 通常動作と no-regression だけ |
| フォーム、設定、保存処理 | invalid input とエラー処理を追加 |
| ユーザーデータ | 認可と所有権チェックを追加 |
| 外部 API | quota、失敗時表示、手動更新との分離を追加 |
| DB migration | rollback ではなく復旧方針、nullability、index、transaction を追加 |
すべてのタスクに最大のチェックリストを使うのではなく、失敗したときの影響が大きい部分に厚く使います。
まとめ
AI に実装を任せる前に完成条件を宣言すると、実装後のレビューが楽になります。
自分の運用では、少なくとも次を先に書くようにしました。
- 通常動作
- 前提条件・認可
- invalid input
- エラー処理
- 重複操作・再実行
- no-regression
- 検証コマンド
AI に「作るもの」だけ渡すのではなく、「完了と見なす条件」まで渡す。これだけで、実装後に戻る回数を減らせました。