# v1.16 タスク実装チェックリスト機能
Release Date: TBD
## 背景・課題
LLM が「10個の実装項目のうち3個しか実装しない」問題が頻発している。
**原因:**
- タスク完了報告時に、個別の実装項目の完了状態を検証していない
- LLM が「タスク完了」と報告すれば、中身の検証なしで次に進む
- モックだけ作って中身なし、`pass` だけ、`// TODO` だけでも「done」と報告可能
---
## 解決策
### タスク構造の拡張
タスクに `checklist`(実装すべきこと一覧)を追加し、各項目の完了状態を追跡する。
```
タスク1 (description: "認証機能を実装")
└─ checklist:
- ログインメソッド追加
- ログアウトメソッド追加
- セッション管理追加
- パスワード検証追加
```
### 2段階の検証
| 検証 | タイミング | 内容 |
|------|-----------|------|
| **実装項目レベル** | Step 13 (タスク完了時) | checklist の全項目が done/skipped か |
| **タスクレベル** | Step 15 (POST_IMPL_VERIFY) | 機能全体が動作するか |
---
## 設計
### タスク登録時 (READY_PLAN)
```python
submit_phase(data={
"tasks": [
{
"id": "task_1",
"description": "認証機能を実装",
"status": "pending",
"checklist": [
{"item": "ログインメソッド追加", "status": "pending"},
{"item": "ログアウトメソッド追加", "status": "pending"},
{"item": "セッション管理追加", "status": "pending"},
{"item": "パスワード検証追加", "status": "pending"}
]
}
]
})
```
### タスク完了報告時 (READY_IMPL)
```python
complete_task(task_id="task_1", data={
"summary": "認証機能実装完了",
"checklist": [
{"item": "ログインメソッド追加", "status": "done", "evidence": "auth.py:42-58"},
{"item": "ログアウトメソッド追加", "status": "done", "evidence": "auth.py:60-75"},
{"item": "セッション管理追加", "status": "skipped", "reason": "既存SessionManagerを再利用するため"},
{"item": "パスワード検証追加", "status": "done", "evidence": "auth.py:77-95"}
]
})
```
### checklist item の構造
| status | evidence | reason | 説明 |
|--------|----------|--------|------|
| `pending` | - | - | 初期状態 |
| `done` | **必須** | - | 実装完了(file:line で証拠を示す) |
| `skipped` | - | **必須** | 実装しない(理由を明記) |
---
## 検証ロジック (オーケストレーター側)
### evidence フォーマット仕様
```
<file_path>:<line>[-<end_line>]
```
**有効:**
```
auth.py:42
auth.py:42-58
src/services/auth.py:42
src/services/auth.py:42-58
```
**無効:**
```
auth.py の 42行目 # 日本語
auth.py:42〜58 # 全角
auth.py line 42 # 英語表記
42-58 in auth.py # 順序逆
```
### 正規表現
```python
import re
EVIDENCE_PATTERN = re.compile(r'^[\w./\-]+\.\w+:\d+(-\d+)?$')
```
### タスク完了時のチェック
```python
def validate_task_completion(task, reported_checklist):
errors = []
# 1. 全項目が報告されているか
original_items = {c["item"] for c in task["checklist"]}
reported_items = {c["item"] for c in reported_checklist}
if original_items != reported_items:
errors.append("checklist items mismatch")
# 2. 各項目の検証
for item in reported_checklist:
if item["status"] == "pending":
errors.append(f"Item '{item['item']}' is still pending")
elif item["status"] == "done":
if "evidence" not in item or not item["evidence"]:
errors.append(f"Item '{item['item']}' requires evidence")
else:
# evidence フォーマット検証
if not EVIDENCE_PATTERN.match(item["evidence"]):
errors.append(
f"Invalid evidence format for '{item['item']}': '{item['evidence']}'. "
f"Use 'file.py:42' or 'file.py:42-58'"
)
else:
# ファイル存在・中身検証
file_error = validate_evidence_content(item["evidence"])
if file_error:
errors.append(f"Evidence error for '{item['item']}': {file_error}")
elif item["status"] == "skipped":
if "reason" not in item or len(item.get("reason", "")) < 10:
errors.append(f"Item '{item['item']}' requires reason (min 10 chars)")
return errors
```
### evidence 内容の検証
```python
def validate_evidence_content(evidence):
"""
evidence の指す場所に実際にコードがあるか検証
Returns: error message or None
"""
# パース: "file.py:42-58" → file="file.py", start=42, end=58
match = re.match(r'^(.+):(\d+)(?:-(\d+))?$', evidence)
file_path, start_line, end_line = match.groups()
start_line = int(start_line)
end_line = int(end_line) if end_line else start_line
# 1. ファイル存在チェック
if not os.path.exists(file_path):
return f"File not found: {file_path}"
# 2. 行範囲チェック
with open(file_path) as f:
lines = f.readlines()
if start_line > len(lines):
return f"Line {start_line} exceeds file length ({len(lines)} lines)"
# 3. 空実装チェック
code_lines = lines[start_line-1:end_line]
code = ''.join(code_lines).strip()
# 空関数/pass/TODO のみの検出
empty_patterns = [
r'^\s*pass\s*$',
r'^\s*\.\.\.\s*$',
r'^\s*#\s*TODO',
r'^\s*//\s*TODO',
r'^\s*raise\s+NotImplementedError',
]
for pattern in empty_patterns:
if re.match(pattern, code, re.MULTILINE):
return f"Empty implementation detected (matches '{pattern}')"
return None
```
---
## phase_contract.yml 変更
### READY_PLAN expected_payload 更新
```yaml
READY_PLAN:
expected_payload:
tasks: list[{id, description, status, checklist: list[{item, status}]}]
# checklist を追加
instruction: >-
If .code-intel/task_planning.md exists, read it and create a task list following the guidelines.
Each task MUST include a checklist of specific implementation items.
Submit via submit_phase.
```
### READY_IMPL instruction 更新
```yaml
READY_IMPL:
expected_payload:
task_id: str
checklist: list[{item, status, evidence?, reason?}]
# checklist 報告を追加
instruction: >-
Run check_write_target before modifying files.
After implementation, report task completion with checklist status:
- For each checklist item, set status to "done" or "skipped"
- "done" requires evidence in strict format: <file_path>:<line> or <file_path>:<start>-<end>
Examples: "auth.py:42", "src/services/auth.py:42-58"
Invalid: "auth.py の 42行目", "line 42 in auth.py"
- "skipped" requires reason (min 10 characters explaining why not needed)
Submit via complete_task(task_id, data={summary, checklist}).
```
### 新規エラーメッセージ
```yaml
failures:
READY:
checklist_items_mismatch:
error: payload_mismatch
message: "Reported checklist items don't match registered items. Include all items from the original checklist."
checklist_item_pending:
error: payload_mismatch
message: "Checklist item '{item}' is still pending. Set status to 'done' (with evidence) or 'skipped' (with reason)."
checklist_evidence_required:
error: payload_mismatch
message: "Checklist item '{item}' with status 'done' requires evidence. Format: 'file.py:42' or 'file.py:42-58'."
checklist_evidence_format_invalid:
error: payload_mismatch
message: "Evidence '{evidence}' has invalid format. Required format: <file_path>:<line> or <file_path>:<start>-<end>. Examples: 'auth.py:42', 'src/auth.py:42-58'."
checklist_evidence_file_not_found:
error: payload_mismatch
message: "Evidence file not found: {file_path}. Verify the file path is correct and the file exists."
checklist_evidence_line_out_of_range:
error: payload_mismatch
message: "Evidence line {line} exceeds file length ({total} lines). Use a valid line number within 1-{total}."
checklist_evidence_empty_impl:
error: payload_mismatch
message: "Empty implementation detected at '{evidence}'. Contains only pass/TODO/NotImplementedError. Add actual implementation code."
checklist_reason_required:
error: payload_mismatch
message: "Checklist item '{item}' with status 'skipped' requires reason (min 10 chars). Explain why this item is not needed."
```
---
## task_planning.md 更新
```markdown
# Task Planning Guide
- Create tasks for all modification targets identified during exploration phase
- The purpose is to prevent implementation omissions; granularity is flexible
- Do not include post-implementation verification (tests, etc.) in tasks
- Identify dependencies between tasks
- Order by dependencies (independent tasks first)
- Note risk level (High/Medium/Low) for tasks requiring extra caution
## Checklist Requirements
Each task MUST include a `checklist` of specific implementation items.
### How to Write Checklist Items
**Good examples** (concrete, verifiable):
- "auth.py に login() メソッドを追加"
- "UserService クラスに validate_password() を実装"
- "config.yml に新しい認証設定セクションを追加"
- "AuthController の /login エンドポイントを実装"
**Bad examples** (vague, unverifiable):
- "認証を実装"(どのファイル?何を?)
- "ログイン機能"(メソッド?UI?API?)
- "セキュリティ対応"(具体的に何?)
### Checklist Item Format
```
[ファイル/クラス/モジュール] に [具体的な変更内容] を [動詞]
```
Examples:
- `auth.py` に `login()` メソッドを追加
- `UserModel` に `is_active` フィールドを追加
- `routes/auth.ts` に `/logout` エンドポイントを実装
- `styles.css` に `.btn-primary` のホバースタイルを追加
### Deriving Checklist from EXPLORATION
EXPLORATION で特定した変更対象を漏れなく checklist に含める:
```
EXPLORATION findings:
- auth.py: 認証ロジックの追加が必要
- models/user.py: is_active フィールドの追加が必要
- routes/auth.ts: /login, /logout エンドポイントが必要
- tests/: テストファイルの追加が必要
↓ 変換
Task: 認証機能を実装
checklist:
- auth.py に login() メソッドを追加
- auth.py に logout() メソッドを追加
- models/user.py に is_active フィールドを追加
- routes/auth.ts に /login エンドポイントを実装
- routes/auth.ts に /logout エンドポイントを実装
```
### When Completing a Task
- `done`: Provide evidence as file:line reference (e.g., "auth.py:42-58")
- `skipped`: Provide reason (min 10 characters) explaining why not needed
```
---
## 実装タスク
### 1. phase_contract.yml
- [x] `READY_PLAN.expected_payload.tasks` に `checklist: list[{item, status}]` を追加
- [x] `READY_PLAN.instruction` を更新(checklist 必須の旨を追加)
- [x] `READY_IMPL.expected_payload` に `checklist: list[{item, status, evidence?, reason?}]` を追加
- [x] `READY_IMPL.instruction` を更新(evidence フォーマット、skipped reason を明記)
- [x] `failures.READY` に以下のエラーメッセージを追加:
- [x] `checklist_items_mismatch`
- [x] `checklist_item_pending`
- [x] `checklist_evidence_required`
- [x] `checklist_evidence_format_invalid`
- [x] `checklist_evidence_file_not_found`
- [x] `checklist_evidence_line_out_of_range`
- [x] `checklist_evidence_empty_impl`
- [x] `checklist_reason_required`
### 2. session.py
- [x] `ChecklistItem` データクラスを追加:
```python
@dataclass
class ChecklistItem:
item: str
status: str # "pending" | "done" | "skipped"
evidence: str | None = None
reason: str | None = None
```
- [x] `Task` データクラスに `checklist: list[ChecklistItem]` フィールドを追加
- [x] `Task.to_dict()` で checklist をシリアライズ
- [x] `Task.from_dict()` で checklist をデシリアライズ
### 3. code_intel_server.py
- [x] `EVIDENCE_PATTERN` 正規表現を定義: `r'^[\w./\-]+\.\w+:\d+(-\d+)?$'`
- [x] `validate_evidence_format(evidence)` 関数を追加
- [x] `validate_evidence_content(evidence)` 関数を追加:
- [x] ファイル存在チェック
- [x] 行番号範囲チェック
- [x] 空実装検出(pass/TODO/NotImplementedError)
- [x] `validate_task_completion(task, reported_checklist)` 関数を追加:
- [x] 全項目報告チェック
- [x] status が pending でないことチェック
- [x] done の場合 evidence 必須チェック
- [x] done の場合 evidence フォーマットチェック
- [x] done の場合 evidence 内容チェック
- [x] skipped の場合 reason 必須チェック(10文字以上)
- [x] `_handle_ready()` で READY_PLAN 時に checklist 付きタスク登録をサポート
- [x] `complete_task()` で checklist 検証ロジックを呼び出し
- [x] エラー時は `_get_message()` で phase_contract.yml からメッセージ取得
### 4. templates/code-intel/task_planning.md
- [x] `## Checklist Requirements` セクションを追加
- [x] `### How to Write Checklist Items` を追加(Good/Bad examples)
- [x] `### Checklist Item Format` を追加
- [x] `### Deriving Checklist from EXPLORATION` を追加
- [x] `### When Completing a Task` を追加(evidence/reason の書き方)
### 5. .code-intel/ へのコピー
- [x] `templates/code-intel/task_planning.md` → `.code-intel/task_planning.md`
- [x] `templates/code-intel/phase_contract.yml` → `.code-intel/phase_contract.yml`
- [x] `sample/.code-intel/` にも同様にコピー
### 6. テスト
- [x] `test_checklist_registration` - checklist 付きタスク登録が成功する
- [x] `test_checklist_missing` - checklist なしタスク登録(後方互換性のため許可)
- [x] `test_checklist_items_mismatch` - 報告項目が登録項目と一致しない場合エラー
- [x] `test_checklist_item_pending` - pending のまま報告するとエラー
- [x] `test_checklist_evidence_required` - done で evidence なしがエラー
- [x] `test_checklist_evidence_format_valid` - 正しいフォーマットが通る
- [x] `test_checklist_evidence_format_invalid` - 不正フォーマットがエラー
- [x] `test_checklist_evidence_file_not_found` - 存在しないファイルがエラー
- [x] `test_checklist_evidence_line_out_of_range` - 行番号範囲外がエラー
- [x] `test_checklist_evidence_empty_impl` - 空実装(pass/TODO)がエラー
- [x] `test_checklist_reason_required` - skipped で reason なしがエラー
- [x] `test_checklist_reason_min_length` - reason が10文字未満でエラー
- [x] `test_checklist_complete_success` - 正しい報告で完了
### 7. ドキュメント
- [x] `README_ja.md` にチェックリスト機能の概要を追加
- [x] `docs/DESIGN_ja.md` に READY フェーズの変更を反映
---
## 期待される効果
### 防げるケース
- **うっかり忘れ**: checklist に全項目あるので報告時に気づく
- **なんとなくスキップ**: reason 必須で理由を考えざるを得ない
- **モックだけ実装**: evidence 検証で空関数/TODO を検出
- **項目の見落とし**: サーバーが「全項目報告されてない」を検出
### 定量的効果(予測)
| 指標 | Before | After (予測) |
|------|--------|-------------|
| 実装漏れ率 | 70% (3/10) | 10% 以下 |
| skipped 理由の質 | - | 10文字以上の説明必須 |
| 空実装検出 | 0% | 90%+ |
---
## 注意事項
- checklist の粒度は LLM の判断に依存するため、EXPLORATION で特定した変更対象を漏れなく含める指示が重要
- evidence 検証は完璧ではない(複雑なロジックの正しさまでは検証できない)
- POST_IMPL_VERIFY(verifier 実行)との組み合わせで効果を発揮