16 KiB
16 KiB
description: プロンプトベースで対話的に仕様を策定し、TDD前提のタスクに分解する(ネガティブチェック・認知バイアス除去含む)
argument-hint: "<要望内容>" [--id=custom-id]
allowed-tools: Bash, Read, Write, Edit, Glob, AskUserQuestion
プロンプトベース仕様策定・タスク分解
プロンプトで記述された要望を、対話を通じて網羅的な仕様(正常系・異常系・エッジケース)に昇華し、TDD前提の実装タスクに分解します。
実行モード
/task-spec "ユーザー認証機能を実装したい"
/task-spec "データ検索APIを作りたい" --id=search-api
実行フロー
Phase 1: 網羅的仕様策定(20-30分)
Step 1: 要望分析
# ユーザープロンプト解析
- キーワード抽出(認証、API、UI、データ処理など)
- 既存コードベースとの関連確認
- 初期スコープ推定
Step 2: ポジティブ仕様の明確化(5-8分)
対話形式で以下を確定:
=== Step 2: ポジティブ仕様の明確化 ===
Q1: 入力は何ですか?
(例: ユーザーID、メールアドレス、JSONペイロード)
Q2: 期待される出力は何ですか?
(例: 認証トークン、ユーザー情報、HTTPステータス)
Q3: 成功の条件を具体的に教えてください
(例: 「有効な認証情報で200 + JWT返却」)
Q4: 制約や前提条件はありますか?
(例: PostgreSQL使用、既存API互換性必須)
Step 3: ネガティブチェック(認知バイアス除去)(10-15分)
3-1. 失敗シナリオ分析
=== Step 3-1: 失敗シナリオ分析 ===
Progress: ▓▓▓▓░░░░░░ (4/10)
確証バイアスを排除するため、「どこで壊れるか」を先に考えます。
Q: この機能が失敗する可能性があるケースを選択してください(複数選択可)
1. 入力が不正(型違い、範囲外、フォーマット不正)
2. 依存リソースが存在しない(ファイル、DB、API)
3. 権限不足・認証失敗
4. タイムアウト・ネットワークエラー
5. リソース枯渇(メモリ、ディスク、CPU)
6. 並行実行による競合
7. その他(自由記述)
選択: 1,2,3
→ 選択された各ケースについて詳細を質問
3-2. エッジケース網羅
=== Step 3-2: エッジケース網羅 ===
正常系偏重を避けるため、境界値での振る舞いを確認します。
以下のケースで期待される動作を確認してください(該当するものにチェック):
□ 空文字列 / 空配列 / 空オブジェクト
→ どう処理すべきですか? (1. エラー / 2. デフォルト値 / 3. そのまま通す)
□ null / undefined / NaN
→ どう処理すべきですか? (1. エラー / 2. 無視 / 3. デフォルト値)
□ 最小値・最大値(数値、文字数、配列長)
→ 境界値は? (例: 0-255文字、1-100件)
□ 0, -1, Infinity
→ 許可しますか? 許可する場合の意味は?
□ 特殊文字(<>"'&;など)
→ エスケープ必要? どのレベルで?
□ 非ASCII文字(絵文字、全角、Unicode)
→ サポートしますか? 制限は?
□ 巨大なデータ(1MB超の文字列、10万件の配列)
→ 制限値は? 超えた場合の処理は?
3-3. セキュリティリスク分析
=== Step 3-3: セキュリティリスク分析 ===
楽観バイアスを排除し、攻撃シナリオを想定します。
該当する脅威を選択してください(複数選択可):
1. XSS(クロスサイトスクリプティング)
- ユーザー入力を画面表示する箇所がある
2. SQLインジェクション
- SQL文を動的生成している
3. CSRF(クロスサイトリクエストフォージェリ)
- 状態変更操作(POST/PUT/DELETE)がある
4. 権限昇格
- 他ユーザーのデータにアクセスする可能性
5. DoS(サービス拒否)
- 大量リクエストで停止する可能性
6. 情報漏洩
- エラーメッセージに秘密情報が含まれる可能性
選択: 1,3,4
→ 各脅威に対する対策を質問
3-4. 認知バイアスチェック
=== Step 3-4: 認知バイアスチェック ===
以下のバイアスを意識的に排除したか確認します:
✓ 確証バイアス
「うまくいくはず」ではなく「どこで壊れるか」を先に考えた
✓ 正常系偏重
正常系:異常系 = 1:3 の比率でテストケースを設計した
✓ 楽観バイアス
「たぶん大丈夫」を「証明されるまで信用しない」に変換した
✓ 可用性バイアス
「よくあるケース」だけでなく「レアだが致命的なケース」も網羅した
全てチェック完了後、次へ進みます。
Step 4: 失敗するテスト生成(5分)
=== Step 4: 失敗するテスト生成 ===
確定した仕様から、Red状態のテストコードを自動生成します。
テスト比率:
- 正常系テスト(20%): 2件
- 異常系テスト(50%): 5件
- エッジケーステスト(30%): 3件
合計: 10件のテストケース
生成されたテストは tasks/pbi-{id}/tests/ に保存されます。
Phase 2: タスク分解(既存Group 1-3 + ネガティブレビュー)
Group 1: 要件・制約の確定(5-8分)
- 処理方式の選択
- 機能範囲の決定
- セキュリティレベルの設定
- 非機能要件の確認
Group 1.5: ネガティブケース・レビュー(5分)
=== Group 1.5: ネガティブケース・レビュー ===
Phase 1で抽出したネガティブケースを確認します:
【失敗シナリオ】
1. 入力不正(空文字列、型違い) - Priority: High
2. DB接続失敗 - Priority: Critical
3. 権限不足 - Priority: High
【エッジケース】
1. 最大長超過(255文字) - Priority: Medium
2. 特殊文字(XSSペイロード) - Priority: Critical
3. 並行実行 - Priority: Low
Q: 追加で考慮すべき失敗シナリオはありますか?
(あれば記述、なければEnter)
→ ユーザー入力を反映してspecs.mdを更新
Group 2: 技術・アーキテクチャ設計(8-12分)
- 技術スタックの選択
- データ設計・モデル構造
- API設計・インターフェース
- UI/UX設計方針
Group 3: 実装・タスク構成(5-8分)
- タスク分解粒度の決定(ネガティブケース考慮)
- 実装優先順位の設定
- 依存関係の整理
- 最終タスクリストの確認
生成されるファイル構造
tasks/pbi-{timestamp or custom-id}/
├── specs.md # 網羅的仕様書(正常系+異常系+エッジケース)
├── tests/
│ ├── spec-test-positive-1.md # 正常系テスト(Red状態)
│ ├── spec-test-negative-1.md # 異常系テスト(Red状態)
│ ├── spec-test-edge-1.md # エッジケーステスト(Red状態)
│ └── tdd-log.md # Red→Green遷移記録
├── README.md # リファインメント履歴・タスク一覧
├── todo-{category}-N.md # 実装タスク(ネガティブケース含む)
└── .refine-progress.json # 進捗管理
specs.md フォーマット
---
created: 2024-01-01T10:00:00Z
updated: 2024-01-01T10:30:00Z
status: confirmed
coverage_score: 85 # ネガティブチェック網羅率
---
# 仕様: ユーザー認証機能
## 要望(オリジナルプロンプト)
ユーザー認証機能を実装したい
## 確定した仕様
### 機能概要
メールアドレスとパスワードでユーザー認証を行い、JWTトークンを返却する
### 入力
- email: string(必須、メール形式、最大255文字)
- password: string(必須、最小8文字、最大128文字)
### 出力
- 成功時: 200 OK + { token: string, userId: string }
- 失敗時: 適切なHTTPステータス + エラーメッセージ
### 制約
- JWT有効期限: 24時間
- パスワードハッシュ: bcrypt
- データベース: PostgreSQL
### 成功条件(正常系)
- [ ] 有効な認証情報で200 + JWT返却
- [ ] トークンでユーザー情報取得可能
## ネガティブケース分析
### 失敗シナリオ
#### 入力不正
- [ ] 空文字列のemail → 400 + "email is required"
- [ ] 無効なメール形式 → 400 + "invalid email format"
- [ ] パスワード7文字 → 400 + "password must be at least 8 characters"
- [ ] 型違い(数値) → 400 + "email must be a string"
#### 依存リソース欠如
- [ ] DB接続失敗 → 503 + "service temporarily unavailable" + リトライ
- [ ] DBクエリタイムアウト → 504 + "gateway timeout"
#### 権限・認証
- [ ] 存在しないユーザー → 401 + "invalid credentials"
- [ ] パスワード不一致 → 401 + "invalid credentials"
- [ ] アカウント無効化済み → 403 + "account disabled"
- [ ] ログイン試行回数超過 → 429 + "too many attempts"
#### 並行実行
- [ ] 同一ユーザーの多重ログイン → 許可(トークン複数発行)
### エッジケース
| ケース | 入力例 | 期待される振る舞い |
|--------|--------|-------------------|
| 空文字列 | `email=""` | 400 + ValidationError |
| null | `email=null` | 400 + ValidationError |
| 最大長 | 256文字のemail | 400 + "email too long" |
| 最大長境界 | 255文字のemail | 正常処理 |
| 特殊文字 | `email="<script>"` | エスケープ処理 + 通常検証 |
| 絵文字 | `password="👍pass"` | 正常処理(UTF-8対応) |
| SQL注入試行 | `email="' OR '1'='1"` | プレースホルダーで無害化 |
### セキュリティ考慮事項
- [ ] パスワードは平文ログ出力禁止
- [ ] エラーメッセージで存在ユーザーを推測不可(401で統一)
- [ ] ブルートフォース対策: 5回失敗で15分ロック
- [ ] HTTPS必須(平文通信禁止)
- [ ] CSRF対策: 状態変更なしのため不要
- [ ] レート制限: 1IP 10req/min
### 想定される失敗モード(FMEA的分析)
| 失敗モード | 発生頻度 | 影響度 | 検出容易性 | 対策 |
|-----------|---------|--------|-----------|------|
| DB接続断 | 低 | 高 | 容易 | コネクションプール + リトライ |
| パスワード平文ログ出力 | 低 | 致命的 | 困難 | ログフィルター + コードレビュー |
| ブルートフォース | 高 | 中 | 容易 | レート制限 + アカウントロック |
| タイミング攻撃 | 低 | 中 | 困難 | 固定時間比較 |
## 対話履歴
### Q1: 入力は何ですか?
A: メールアドレスとパスワード
### Q2: 失敗シナリオ - 入力不正
Q: 空文字列が渡された場合の振る舞いは?
A: 400 BadRequestでValidationErrorを返す
### Q3: エッジケース - 最大長
Q: メールアドレスの最大長は?
A: 255文字。超過時は400エラー
### Q4: セキュリティ - ブルートフォース
Q: 連続失敗時の対策は?
A: 5回失敗で15分間アカウントロック
## テスト戦略
### 正常系テスト(20%)
- test_001: 有効な認証情報で200 + JWT
- test_002: トークンでユーザー情報取得成功
### 異常系テスト(50%)
- test_101: 空文字列emailで400
- test_102: 無効なメール形式で400
- test_103: 短いパスワードで400
- test_104: 存在しないユーザーで401
- test_105: パスワード不一致で401
- test_106: DB接続失敗で503
- test_107: ログイン試行超過で429
### エッジケーステスト(30%)
- test_201: 最大長境界値(255文字)
- test_202: 最大長超過(256文字)
- test_203: XSSペイロード試行
- test_204: SQL注入試行
- test_205: パスワードにUnicode文字
### カバレッジ目標
- 行カバレッジ: 90%以上
- 分岐カバレッジ: 85%以上
- 異常系カバレッジ: 100%
todo-{category}-N.md フォーマット(拡張版)
---
parent: auth-feature
category: services
priority: high
estimated_hours: 6
negative_cases: 7 # このタスクがカバーすべき異常系の数
edge_cases: 5 # エッジケースの数
test_ratio: "2:7:5" # 正常:異常:エッジ
---
# ユーザー認証API実装
## やること
specs.mdに基づき、ユーザー認証エンドポイントを実装
## 成功条件(正常系)
- [ ] POST /api/auth/login で200 + JWT返却
- [ ] 有効なトークンでユーザー情報取得可能
## 失敗条件(異常系)
- [ ] 空email → 400 + ValidationError
- [ ] 無効なメール形式 → 400 + validation message
- [ ] パスワード7文字 → 400 + length requirement
- [ ] 存在しないユーザー → 401 + generic message
- [ ] パスワード不一致 → 401 + generic message
- [ ] DB接続失敗 → 503 + retry logic
- [ ] ログイン試行5回超過 → 429 + lockout period
## エッジケース
- [ ] メール255文字(境界値) → 正常処理
- [ ] メール256文字 → 400 error
- [ ] XSSペイロード → エスケープして検証
- [ ] SQL注入試行 → prepared statementで無害化
- [ ] Unicode文字パスワード → 正常処理
## 技術仕様
- パスワードハッシュ: bcrypt(salt rounds: 10)
- JWT署名: HS256 + 環境変数シークレット
- DB: prepared statement必須
- エラーログ: パスワード除外
## 制約
- specs.md#セキュリティ考慮事項 を全て遵守
- 認証失敗はタイミング攻撃対策で固定時間応答
- エラーメッセージでユーザー存在を推測不可
## 実装メモ
(TDD Red→Green→Refactorサイクルを記録)
実行後の出力
✅ 仕様策定完了
【生成ファイル】
- tasks/pbi-auth-feature/specs.md
- tasks/pbi-auth-feature/tests/spec-test-positive-1.md
- tasks/pbi-auth-feature/tests/spec-test-negative-1.md
- tasks/pbi-auth-feature/tests/spec-test-negative-2.md
- tasks/pbi-auth-feature/tests/spec-test-negative-3.md
- tasks/pbi-auth-feature/tests/spec-test-negative-4.md
- tasks/pbi-auth-feature/tests/spec-test-negative-5.md
- tasks/pbi-auth-feature/tests/spec-test-edge-1.md
- tasks/pbi-auth-feature/tests/spec-test-edge-2.md
- tasks/pbi-auth-feature/tests/spec-test-edge-3.md
- tasks/pbi-auth-feature/README.md
【ネガティブチェック網羅率】
- 失敗シナリオ: 7件
- エッジケース: 5件
- セキュリティ: 6項目
- カバレッジスコア: 85/100
【タスク数】
- Setup: 1タスク
- Models: 1タスク
- Services: 1タスク(正常2 + 異常7 + エッジ5 = 14テストケース)
- UI: 1タスク
- Tests: 1タスク
次のステップ:
1. /task-next で最初のタスクを実行
2. /task-status auth-feature で進捗確認
エラーハンドリング
実行前チェック
- tasksディレクトリの存在確認
- プロンプトの最小文字数確認(10文字以上)
- カスタムIDの重複チェック
進行中のエラー処理
- 不正な選択肢入力時の再プロンプト
- ネットワークエラー時の状態保存
- 強制終了時の進捗復旧(.refine-progress.json)
完了条件
- Phase 1, 2の全ステップが正常完了
- specs.mdにネガティブケース分析が記録されている
- テストファイルが正常系:異常系:エッジ = 2:5:3の比率で生成されている
- 各タスクに異常系・エッジケースが割り当てられている
- カバレッジスコアが80以上