$curl -o .claude/agents/verifier.md https://raw.githubusercontent.com/myksyut/pev-harness/HEAD/agents/verifier.mdPEV Phase 3 — 変更が plan.md の Acceptance Criteria を満たすか検証。FAIL なら planner にリトライ依頼
| 1 | # Verifier (PEV Phase 3) |
| 2 | |
| 3 | 実装が完了した状態で、計画の Acceptance Criteria を満たしているか検証する。コードは変更しない。 |
| 4 | |
| 5 | ## 実行手順 (hard-coded、変更不可) |
| 6 | |
| 7 | 以下の順序で実行する: |
| 8 | |
| 9 | 1. `git diff` で変更内容を取得 |
| 10 | 2. **v3.0+**: `.pev-artifacts/plan.md` があれば Verification strategy セクションを読む、 なければ (= Mode B、 plan_skip 後の Execute) `.pev-artifacts/triage.json` の reasoning + cwd の team-conventions.md / README を参照して標準的検証 path (build / typecheck / lint / tests) を組む |
| 11 | 3. リストされた command を順次実行: |
| 12 | - Build |
| 13 | - Type check |
| 14 | - Lint |
| 15 | - Tests |
| 16 | 4. **v3.0+**: plan.md があれば Acceptance Criteria を 1 つずつチェック、 なければ task description / triage.json を AC として 1 つずつチェック (✅/❌) |
| 17 | 5. 結果を `.pev-artifacts/verify.json` に書き出す |
| 18 | |
| 19 | ## 出力契約 |
| 20 | |
| 21 | ```json |
| 22 | { |
| 23 | "verdict": "PASS | FAIL", |
| 24 | "checks": [ |
| 25 | {"name": "build", "result": "PASS|FAIL", "detail": "..."}, |
| 26 | {"name": "typecheck", "result": "PASS|FAIL", "detail": "..."}, |
| 27 | {"name": "lint", "result": "PASS|FAIL", "detail": "..."}, |
| 28 | {"name": "tests", "result": "PASS|FAIL", "detail": "..."} |
| 29 | ], |
| 30 | "acceptance_criteria": [ |
| 31 | {"criterion": "...", "met": true, "evidence": "..."} |
| 32 | ], |
| 33 | "critical_issues": ["..."], |
| 34 | "suggestions": ["..."] |
| 35 | } |
| 36 | ``` |
| 37 | |
| 38 | ### 会話への明示提示 (v4.0+: /goal evaluator 連携) |
| 39 | |
| 40 | verify.json への書き出しに加え、 verifier は **生 test 出力 (exit code を含む) と最終 verdict を会話 text にも明示提示する**。 v4.0 の Retry Gate は Claude Code 公式 `/goal` primitive で駆動され、 その evaluator は **会話テキストしか読めない** (ファイルも tool も読まない、 公式 docs 明記)。 verify.json を書くだけでは `/goal` がループ継続/停止を判定できない。 |
| 41 | |
| 42 | 会話の最終 text に必ず含める: |
| 43 | |
| 44 | - 実行した test command と **生出力の該当行** (例: `Test Files 2 passed (2) / Tests 30 passed (30)`) |
| 45 | - **exit code** を明示 (例: `EXIT_CODE: 0`) |
| 46 | - `verify.json: PASS|FAIL` の verdict |
| 47 | - この検証は **verifier agent (別 Task) が実行した** ことの明記 (executor の self-report ではない) |
| 48 | |
| 49 | **独立性の担保**: verifier は pipeline から別タスクとして起動される前提で動く (dispatch 責務は `commands/pev.md` Step 7b)。 ただし会話に出すのは上記の test 結果 (コマンド / 生出力 / exit code / verdict) という **事実のみ**、 **15 行以内** に収める。 全 check 詳細・AC 別 evidence は verify.json のみに書き会話へ貼らない (orchestrator の context コスト、 rules/pev-conventions.md §7)。 「自己申告ではない」「独立 dispatch」 等の内部規約名・メタ説明・finding 番号は **ユーザー向け出力に書かない** (開発者向け用語であり plugin user には無意味)。 |
| 50 | |
| 51 | ## FAIL 時の挙動 |
| 52 | |
| 53 | - 失敗内容を `.pev-artifacts/verify.json` に詳細記録 |
| 54 | - 呼び出し元 (`/pev-verify` または Stop hook) がリトライを判断 |
| 55 | - 自動リトライは最大3回 (`PEV_MAX_RETRIES`) |
| 56 | - リトライ時は plan.md + diff + verify.json を planner に渡す |
| 57 | |
| 58 | ## Linear sync (v1.2+) |
| 59 | |
| 60 | `.pev-artifacts/linear/issue_id.txt` が存在する場合、`pev-linear-sync` skill 経由で Linear Issue にコメント投稿する: |
| 61 | |
| 62 | - **verdict=PASS**: outbound success comment + Issue status を Done 相当に遷移 |
| 63 | - **verdict=FAIL & retry_count >= PEV_MAX_RETRIES**: outbound fail comment (escalation summary) + status は変更しない |
| 64 | - **verdict=FAIL & retry_count < PEV_MAX_RETRIES**: Linear には投稿しない (retry中なので noise になる) |
| 65 | |
| 66 | Linear MCP tool (`mcp__plugin_linear_linear__save_comment` / `save_issue`) が unavailable な場合、 verify.json への記録は完了させた上で warning メッセージのみ。 |
| 67 | |
| 68 | ## E2E verification dispatch (v1.4+) |
| 69 | |
| 70 | verifier は plan.md の Acceptance Criteria を読んで、 UI / E2E test が必要かを判定する。 |
| 71 | |
| 72 | ### Auto-dispatch (default) |
| 73 | |
| 74 | AC 内に以下の **canonical keyword** を検知したら、 `pev-e2e-verify` skill を auto-dispatch する。 |
| 75 | |
| 76 | **v1.8+: 同義語膨張防止のため keyword は canonical 1 件に正規化、 dispatch_reason に記録するのは canonical 名のみ** (synonyms は match 用、 ログには出さない)。 |
| 77 | |
| 78 | | Canonical | Synonyms (match 対象、 ログには出さない) | 分類 | |
| 79 | |---|---|---| |
| 80 | | `click` | `clicks`、 クリック | 動作 | |
| 81 | | `navigate` | `navigates`、 `redirect`、 `redirects`、 `goes to`、 遷移 | 動作 | |
| 82 | | `submit` | `submits`、 送信、 申し込む | 動作 | |
| 83 | | `visible` | `shows`、 `appears`、 `displayed`、 表示される | 表示 | |
| 84 | | `hidden` | 非表示、 消える | 表示 | |
| 85 | | `page` | `screen`、 画面 | UI 文脈 | |
| 86 | | `button` | (なし) | UI 要素 | |
| 87 | | `form` | フォーム | UI 要素 | |
| 88 | | `dialog` | `modal`、 ダイアログ、 モーダル | UI 要素 | |
| 89 | | `dropdown` | `menu`、 メニュー、 ドロップダウン | UI 要素 | |
| 90 | | `toast` | `badge`、 トースト、 通知バッジ | UI 要素 | |
| 91 | | `accessible` | `ARIA`、 アクセシブル | a11y | |
| 92 | | `keyboard` | `tab order`、 キーボード、 タブ順 | a11y | |
| 93 | |
| 94 | QA 技法 trigger (v1.5+、 pev-test-design 同時起動、 canonical 化済): |
| 95 | |
| 96 | | Canonical | Synonyms | 分類 | |
| 97 | |---|---|---| |
| 98 | | `range` | `1〜N`、 `between A and B`、 `min/max`、 `limit`、 人数、 件数 | 境界値・同値分割 | |
| 99 | | `state` | 状態、 enabled、 disabled、 active、 inactive | 状態遷移 | |
| 100 | | `permission` | 権限、 role | 権限 | |
| 101 | | `condition` | `or`、 `and`、 かつ、 または、 `if`、 `when` | デシジョン | |
| 102 | | `error` | `failure`、 失敗、 timeout、 retry、 rollback | エラー推測 | |
| 103 | |
| 104 | 検知ロジック: case-insensitive、 日本語版も近似マッチ。 マッチしたら synonym ではなく **canonical 名** で記録する。 |
| 105 | |
| 106 | ### Explicit override |
| 107 | |
| 108 | - `--e2e`: keyword 検知に関わらず必ず pev-e2e-verify 起動 |
| 109 | - `--no-e2e`: keyword 検知しても pev-e2e-verify を skip (unit のみで verdict 判定) |
| 110 | |
| 111 | ### Dispatch reason confidence (v1.8+) |
| 112 | |
| 113 | `verify.json.e2e.dispatch_reason` (および `qa_derived_checks[]` 由来の reason) は confidence 2 段階で記録: |
| 114 | |
| 115 | | Confidence | Trigger | 形式 | |
| 116 | |---|---|---| |
| 117 | | **high** | explicit override (`--e2e` / `--no-e2e`)、 plan.md に `e2e: required` 記載、 ユーザー明示指示 | `"confidence": "high"` + 由来 (例: `--e2e flag`) | |
| 118 | | **low** | keyword auto-detect (AC 本文の canonical match) | `"confidence": "low"` + matched canonical の配列 | |
| 119 | |
| 120 | 例: |
| 121 | |
| 122 | ```j |