MF Blogs 便利ツール
チェック項目とOKマークが並ぶ受け入れ条件チェックリストの抽象イラスト

記事

Claude Codeの成功率を上げる制約条件と受け入れ条件の作り方:実装・UI・テスト別の書き方

Claude Codeに曖昧な依頼で失敗されないために、実装・UI・テスト・レビューの観点別に「制約条件」と「受け入れ条件」をどう書くかを整理します。コピペ可能な例を多めに紹介します。

0:00 0:00

結論:依頼文に「制約条件」と「受け入れ条件」を必ず両方書く

Claude Codeの成功率を一気に上げる方法は、難しい設定ではなく**「制約条件」と「受け入れ条件」を依頼文の中で明確に分けて書くこと**です。

  • 制約条件(Constraints): 作業中に守るべきルール。「触ってはいけない」「使ってはいけない」「変えてはいけない」を扱います。
  • 受け入れ条件(Acceptance Criteria): 完了判定の基準。「何が満たされたら終わりか」を、できる限りコマンドや観測可能な結果で表現します。

公式のベストプラクティスでは「Give Claude a way to verify its work(検証手段を与える)」が最も効果が高い1点と明言されています。受け入れ条件はこれを依頼文の中で強制するための仕組みです。

依頼文の基本構造(目的・背景・制約・完了条件などの7ブロック)はプロンプトの基本構造で扱っています。本記事はその中の「制約」と「完了条件」だけを掘り下げます。

「制約」と「受け入れ条件」を分けるとなぜ効くか

両者を混ぜると、Claude Codeはどこを守ればよいのかが曖昧になります。たとえば「テストが緑になればOK。ただしモック禁止」と1行に書くより、次のように分けると判断がブレません。

## 制約
- モックは使わない
- 既存の `__mocks__/` を増やさない
- 環境変数や秘密情報をテストに書かない

## 受け入れ条件
- `npm test -- src/services/order` が緑
- 追加テストが3件以上
- 公開関数のシグネチャは変更されていない

制約はプロセス、受け入れ条件は結果を扱います。レビューの観点も自然に分かれます。

制約条件の書き方(種類別)

制約は次の5カテゴリで考えると漏れにくいです。

1. スコープ制約(触ってよい / 触らない範囲)

- 触ってよい: src/services/order/ と test/services/order/
- 触ってはいけない: src/services/order/repository.ts(次回タスク)
- 他ディレクトリの便乗修正は禁止

範囲指定がないと、Claude Codeは関連ファイルまで「ついでに」直しがちです。これは公式ドキュメントの「Scope the task」項目で明示されています。

2. 依存制約(パッケージ・外部サービス)

- 新規 npm パッケージの追加は禁止
- 既存の lodash・date-fns を使ってよい
- 外部API呼び出しは追加しない
- DB スキーマやマイグレーションは変更しない

依存追加を黙認すると、package.json差分が紛れて事故になります。

3. 互換制約(後方互換・公開API)

- 公開関数のシグネチャは変更しない
- 戻り値の型・例外の種類・キー名は維持する
- 破壊的変更が必要なら、計画段階で明示してから承認を待つ

リファクタリング系では特に重要です。詳しくは既存コードを壊さずリファクタリングする依頼文を参照してください。

4. 品質制約(コーディング規約)

- 既存のコーディング規約(ESLint)に従う
- 新規ファイルは TypeScript の strict 設定で書く
- 一関数あたり50行以下、ネスト3段以下を目安にする
- console.log は本番コードに残さない(テストは可)

規約はチームごとに違うため、共通分はCLAUDE.mdに書いておけば毎回の依頼文が短くなります。CLAUDE.mdの整備は最初に作るべきCLAUDE.mdの書き方を参照してください。

5. セキュリティ制約

- 環境変数や秘密情報をコードに直書きしない
- ログに個人情報を出力しない
- ユーザー入力は必ずバリデーションを通す
- SQL は必ずパラメータ化クエリで書く

これは依頼ごとに書くより、CLAUDE.mdに共通制約として書く運用が現実的です。

受け入れ条件の書き方(種類別)

受け入れ条件は観測可能・自動検証可能であるほどよい依頼文になります。観点別に整理します。

A. 自動テストで検証できる条件

- `npm test -- src/services/order` が緑(追加テスト3件以上)
- `npx tsc --noEmit` でエラーなし
- `npm run lint` で新規警告なし
- 既存テストの期待値は書き換えない

検証コマンドを書くと、Claude Codeは実装後に自分で実行して結果を確認します。

B. UI・デザインで検証できる条件

- スクリーンショットを取り、添付した design.png と比較
- ブレークポイント 375px / 768px / 1280px の3種で崩れがない
- ダークモードでも文字色とのコントラストが WCAG AA 以上
- フォーカスリングが見える(キーボード操作可能)

公式ドキュメントのVerify UI changes visuallyにあるように、スクリーンショット比較を依頼文に組み込むと、UIタスクの精度が上がります。Chrome連携が利用できる環境ではClaude in Chromeも組み合わせられます。

C. 振る舞い・パフォーマンスで検証できる条件

- 1万件入力で 200ms 以内にレスポンスが返る(手元の Macbook で)
- メモリ使用量が処理前後で 100MB 以内に収まる
- 連続 100 リクエストでエラー率 0%

数値を入れると、Claude Codeは計測スクリプトを書いて自分で確認します。

D. ドキュメント・コメント条件

- 公開関数には JSDoc を1〜2行で付与
- README に新コマンドの使い方を3行追記
- BREAKING CHANGE がある場合は CHANGELOG に1行追記

書きすぎ注意です。「書く必要のないドキュメントを増やさない」ことも制約として書いておくと過剰生成を防げます。

E. レビュー前提条件

- 1コミット = 1意図
- 1PRあたり 300 行以下を目安(超える場合は分割案を出す)
- コミットメッセージは "feat(scope): summary" の形式
- PR 説明に 「変更点・テスト方法・スクリーンショット」を3節で書く

公開前のレビュー負荷を下げる効果があります。

タスク種類別:制約+受け入れ条件のセット例

例1: 入力バリデーションの追加

## 目的
@src/forms/signup.ts のメール入力に、空文字・@不在・ドメイン不正のバリデーションを追加する。

## 制約
- 触ってよい: src/forms/signup.ts と test/forms/signup.test.ts
- 触ってはいけない: 他フォーム(src/forms/login.ts など)
- 新規依存は不可(zod は既に入っているので利用可)
- 公開関数 validateSignup のシグネチャは変えない

## 受け入れ条件
- `npm test -- src/forms/signup` が緑、追加テスト3件以上
- `npx tsc --noEmit` でエラーなし
- 不正入力時のエラーメッセージが日本語で1文以内

例2: API のページング対応

## 目的
@src/api/users.ts の GET /users をカーソル方式ページングに対応させる。

## 制約
- 既存の offset 方式は維持(破壊的変更にしない)
- 新規依存は不可
- DBスキーマは変更しない

## 受け入れ条件
- 新パラメータ cursor / limit を受け付ける
- limit のデフォルトは 20、最大は 100
- カーソル無効時は 400 を返す
- `npm test -- src/api/users` が緑(cursor 系テスト4件以上)
- `curl 'http://localhost:3000/users?limit=20'` の結果に next_cursor が含まれる

例3: バグ修正

## 目的
セッションタイムアウト後に画面が真っ白になる問題を直す。

## 制約
- 触ってよい: src/auth/ と関連テスト
- 触ってはいけない: src/api/ 配下(次回タスク)
- 暫定対応(catch して隠す)はしない。根本原因を直す

## 受け入れ条件
- 失敗テスト(10分放置→画面遷移→真っ白を再現)を先に書き、緑になることを確認
- 実際の動作で再ログイン画面に遷移する
- `npm test -- src/auth` が緑

公式ドキュメントのAddress root causes, not symptomsに対応する書き方です。「暫定対応はしない」と明示するのが鍵になります。

例4: UI改善

## 目的
@src/components/Card.tsx の余白とフォントサイズを、design.png に合わせる。

## 制約
- 触ってよい: src/components/Card.tsx と関連 stories
- 既存のデザイントークン(src/styles/tokens.ts)を使う
- インラインスタイルではなく既存の className 体系で書く

## 受け入れ条件
- 修正後のスクリーンショットを取り、design.png と比較して差分が「余白とフォントサイズ」だけになる
- ブレークポイント 375px / 1280px で崩れない
- ダークモードでもコントラスト AA 以上

「受け入れ条件にできない」場合の代替

検証コマンドが用意できないときは、観測可能な状態で言語化します。

検証手段がないとき代わりに書くこと
自動テストがない「手動テスト手順を3〜5ステップで報告して」
UIスクショが取りにくい「変更前後の DOM スナップショットを diff として要約して」
計測ツールがない「処理時間を console.time で1回計測し、結果を要約して」
環境が立ち上がらない「動作確認はせず、計画と差分の説明だけ報告」

「検証できない=受け入れ条件を書かない」ではなく、人間が確認するための観測情報を必ず1つは書きます。

チェックリスト:依頼前の確認

依頼文を投げる前に、次のチェックを通します。

  • スコープ制約を1個以上書いたか
  • 依存制約(追加可否)を書いたか
  • 互換制約(公開API・DB・キー名)を書いたか
  • 受け入れ条件にコマンド(テスト・ビルド・型・lint)を1個以上書いたか
  • UI・性能・観測可能な状態のいずれかを1個書いたか
  • 「テストの期待値は書き換えない」を含めたか(リファクタ系のみ)
  • 中断条件(テスト2回失敗で停止など)を書いたか

このチェックを通すと、依頼文は短くても「Claude Codeが自分で完了判定できる」状態になります。

検証用のCommandを直接渡すパターン

依頼の最後に、検証コマンドそのものを渡すと精度がさらに上がります。

## 受け入れ条件
- 下記コマンドが全て成功する:
npm test -- src/services/order
npx tsc --noEmit
npm run lint -- src/services/order

依頼文の中にコピーして実行できるコマンドを埋め込むと、Claude Codeはそのまま実行して結果を確認します。フラグや実行環境については基本コマンドを参照してください。

まとめ:制約と受け入れ条件は「分けて」「コマンドで」書く

依頼文の精度は、テクニックではなく型と検証手段で決まります。

  • 制約条件は5カテゴリ(スコープ・依存・互換・品質・セキュリティ)で漏らさない
  • 受け入れ条件はテスト・UI・性能・観測情報のいずれかで自動検証可能にする
  • 「テスト期待値は書き換えない」は受け入れ条件と矛盾しないように制約側に書く
  • 共通の制約はCLAUDE.mdに集約し、依頼文を短く保つ

次のステップとしては、プロンプトの基本構造で7ブロック構成を整理し、計画してから実装させるプロンプト例で計画フェーズに制約・受け入れ条件を組み込み、最初の機能追加の手順で通しの実装フローに当てはめてみてください。