| name | harness-verification |
| description | xp-harness の skill / subagent が意図どおり振る舞えているか (発火するか・あるべき振る舞いができているか) を transcript で事実確認する手順。skill / subagent を改修した後に sandbox で動作検証したいとき、または本番の実運用セッションを「あるべき振る舞い」に照らして分析したいとき、「検証したい」「発火するか確かめたい」「このセッションを分析したい」と言われたときに発火させる。核は発火・振る舞いができたかの事実確認で、本番セッションでは自走の良し悪し (止まり方・判断の質など) も見る。 |
harness 検証 — skill / subagent の発火・振る舞いの事実確認
なぜこの skill があるか
skill / subagent を改修しても、それが実際に発火するか・意図どおり振る舞うかは transcript を観測しないと分からない。この検証のやり方 (sandbox の作り方、起動の仕方、transcript の場所と解析方法) はノウハウの塊で、skill 化しないと検証のたびにゼロから再発明することになる。
ここで言うのは「検証」= 仕組みが意図どおり動いたか(sandbox: 的は改修が定める=既知)・あるべき振る舞いができているか(本番: 的=理想を自分で立てて照らす)の確認。核は「できた / できていない」の事実確認。加えて本番セッションでは自走の 良し悪し(止まり方が妥当だったか・判断の質など)まで踏み込んでよい ── ただし二つを守る: 評価は必ず 証拠に接地する(印象・自己分析でなく生 transcript で裏を取る)、点数化・ランク・ベンチには逃げない(偽の精度を生むので扱わない)。当初は良し悪しを扱わない線だったが、観点を型にできる知見が溜まったので拡張した(下記「本番の実運用セッションを見る場合」)。
検証の構造 (全部これの同型)
状態を仕込む → 改修者が Claude Code を起動して走らせる → transcript を解析して発火・振る舞いを観測 → 後片付け
仕込む状態の大きさが検証の目的で変わるだけ。skill の連鎖発火だけならプローブ一式、実フェーズの振る舞いなら要件定義・基本設計 md を置いた途中状態を仕込む。
(上は sandbox で自分が走らせる場合。既に走った 本番の実運用セッション を分析する場合は「状態を仕込む・走らせる」が無く、下記に従う。)
本番の実運用セッションを見る場合 (sandbox でなく、既に走った実運用)
sandbox 検証は「改修した skill が発火・動作するか」で 的が既知(何を確認するかは改修が決める)。一方、本番の実運用セッション(実際のユーザーの自走など)を解析するときは、的が開いている(何を見るべきか自体が定まっていない)。だから最初に 的=理想を立てる のが最重要ステップになる。仕込み・起動は無く、既に走った transcript を解析するだけ。
理想を先に確定する (最重要・ここを飛ばさない)
- まず分析対象のフェーズ / 範囲を絞る: 実運用セッションは要件定義 → 基本設計 → 実装と複数フェーズ(=複数 skill)をまたぐのが普通。全部を一度に見ようとせず、見たいフェーズを 1 つ選び、それを統べる skill に絞る。
- 理想は skill の本文から立てる: 対象の実走を統べる skill(実装フェーズなら slice-tdd、E2E なら e2e 等)の 実際の記述を読み、そこから「あるべき振る舞い」を導く。記憶・想像で立てない(skill の文言と食い違い、照合が的外れになる)。
- 依頼者と合意して固める: 理想の項目をまず短く並べ(発散)、1 項目ずつ深掘りして合意する(収束)。一人で完成形を出さない。認識がズレたまま進めない。
- 理想が固まる前に照合・判定に進まない: 的が定まる前に実走を時系列で並べても、見づらいだけで分析にならない。理想がズレると照合が全部ズレて手戻りになる。理想の各項目が「何を見るか」を決める。
理想を lens に照合する
- 確定した理想の各項目を「見る対象」にして、実走が できている / できていない を、証拠(記録上の実際の記述)付き で照らす。
- 事実(記録から取れるもの)と仮説(内部状態の推測)を分ける。自己分析・因果は捏造されやすいので、判断に効く所は生 transcript で裏を取る(下記手順 4 の「集計を真と扱わない」と同じ)。
本番分析の実行順はこう: 理想を確定(本節) → transcript を解析(手順 4)。手順 1 の「検証目的の確認」は本節の理想確定が兼ね、sandbox 用の手順 2・3(仕込み・起動)は無い。transcript の在り処・読み方は手順 4 の解析をそのまま使う。本番セッションの jsonl は ~/.claude/projects/<エンコードされた作業ディレクトリ>/<セッション ID>.jsonl にある。
自走セッションの質を見る観点 (出発点の型)
自走した実装セッションを「どう走れたか」で見るときの 出発点の型。毎回ゼロから観点を立てると浅くなりがちなので型として置くが、固定のチェックリストではない ── ここから始めて、対象セッションに合わせて足し引きする。各観点は「できた / できていない」+証拠で照らし、点数化はしない。各観点の具体(何をもって「できた」とするか)は、対象 skill 本文や philosophy から毎回立てる(上の「理想を先に確定する」の通り、記憶で机上評価しない)。
- 規律通り走れたか: 対象フェーズを統べる skill の正典サイクルに照らす(実装なら slice-tdd の red→green→リファクタ→green 維持→commit、reviewer / done-verifier を仕上げ前に通したか、commit 粒度、確認なしに push していないか 等。サイクルの正典は slice-tdd 本文で、ここは写しでなく参照)。この skill 固有の見方として、リファクタは「実施したか」と「実施後にテストを流して green を保ったか」の両方を記録から裏取りする(refactor 型の commit があるだけでは振る舞い不変の保証にならない)
- 判断の質: 自走中に詰まり・手戻り・空転はあったか。派生問題を自分で見つけて対処できたか。設計・規約から逸れたとき自力で戻せたか
- 止まり方の妥当性: 人間に委ねるべき判断で止まれたか。止まりすぎ(自分で決められたのに聞いた)も 進みすぎ(大きい・後戻りしにくい判断を勝手に進めた)も無かったか(判断軸は philosophy「対話と自走の境界」)
- 成果密度: その稼働時間で何が完成したか(commit)と時間の内訳(実装・思考 / subagent 委譲待ち / main 検証実行 / git・調査、割り方は手順 4)。生産性そのものの計測ではなく、空転(実装が進まず待ちに時間が溶ける)を skill 連携・リズムの不全のサインとして観る(harness の効きの裏返し)
自走の 稼働時間・介入回数 の測り方は手順 4 の「transcript を解析する」を参照。
鉄則: -p を使わない
claude -p (ヘッドレス) を使わない (2026-06-15 から従量課金)。検証は interactive (サブスク枠) で駆動する — 起動・送信の具体は手順 3。自分で駆動でき、改修者の手動起動に頼らなくてよい (手動起動 + 貼り付けも従来どおり可)。いずれの場合も、走り終わった transcript を解析するのがあなたの仕事。
検証条件の設計原則
仕込み (sandbox の状態・設計書・規約) とプロンプトを作るときの原則。条件が悪いと、走らせても何も測れない / 別物を測る。
- ノーヒント: 検証したい振る舞い・期待結果・誘導を、プロンプトにも仕込み (要件定義 / 基本設計 / コメント) にも書かない。検証したい挙動はセッションが自分で気づく形にする (その挙動を促すルールは skill / プロジェクト規約の側に置き、プロンプトは普通の依頼にとどめる)。書くと自己成就し、skill のおかげか指示のおかげか区別できなくなる
- 実観測ケースを使う: 仮想のシナリオをでっち上げず、実際に起きた / 起こりうるケースを再現する。でっち上げは「ありそう」に寄って実挙動とずれる
- 開始状態は検証対象の skill に合わせる: 検証対象 skill が「どのフェーズで効くか」に開始状態を合わせないと、その skill が発火する文脈にならず振る舞いを測れない。どの状態を仕込むかの具体は手順2 で選ぶ。既存機能の変更・改善を投げるケースでは、sandbox にその機能の実体 (placeholder でない実画面・実 API) があるかを条件設計時に確認する (実体が無いと、セッションは「対象が無い」方向に逸れて狙った振る舞いを観測できない)
- 前後比較と試行数は要否を検討して提案する: 発火は確率的に揺らぐ (実測: 同一条件で story-slicing が新 2/4・旧 2/3)。改修後の版を 1 本走らせて発火しなくても、それが回帰なのか元々の揺らぎなのかは区別できない。だから改修前の版と改修後の版を同じ条件で走らせ複数試行で比べることが、回帰を見る検証では反証可能性の前提になる (実例: dialogue-principles は旧 3/3・新 0/3 という差があって初めて回帰と言えた。ただし新規 skill の検証には比較対象の旧版が無いなど、常に必須ではない)。条件設計のときに要否を必ず検討し、やる / やらない どちらの場合も理由を添えて依頼者に提案する (黙って単発条件で走らせない)。前後比較のやり方は手順 3 の deploy 形の差し替えを参照
- 検証セッションのモデルを条件として固定する: 発火と振る舞いはモデル依存なので (上位モデルは弱い description を推論で補う)、条件設計でモデルを決め (
claude-launcher.sh launch --model)、前後比較では新旧を同一モデルで走らせる。実際に使われた model ID は transcript から確認し (指定した alias でなく実測値が真)、検証記録に残す (記録の必須項目、references/README.md 参照)
- 反証可能性 (falsifiability) — 条件を仕込んだら最後に必ず通す (最重要): その条件は、検証対象 skill の核の価値が欠けていたら明確に FAIL するかを問う。ノーヒント・実観測を満たしていても、表面の新挙動が「出た」だけを見る条件は薄い (弱い skill でも通り、何も保証しない)。設計時に「この skill の一番の失敗モードは何か → それが起きたら条件が FAIL するよう仕込めているか」を通す。これは条件の弁別力 (FAIL を出せる設計か) の話で、skill の出来をスコアリングするのではない。例: 「引き継ぎドキュメント skill」で "引き継ぎの一言が出るか" だけ観測しても核 (会話文脈が漏れず自己完結に書けるか) は突けていない → 会話由来の却下・変更を仕込み、それが成果物に残るかで FAIL 判定する。
手順
1. 検証目的を確認する
どの skill / subagent の、どの発火・振る舞いを確認したいかを特定する。確認したい事実を先に言語化する (例:「main が slice-tdd を Skill tool で発火するか」「code-reviewer が preload された skill の指示で動くか」)。目的が曖昧なまま走らせると、transcript を見ても判定できない。
2. 状態を仕込む
sandbox の用意 — 新規に作るなら:
.claude/skills/harness-verification/scripts/setup-sandbox.sh <名前>
.claude/skills/harness-verification/scripts/setup-sandbox.sh <名前> --bare
.claude/skills/harness-verification/scripts/setup-sandbox.sh <名前> --wiremock
<xp-harness の親ディレクトリ>/xp-harness-test/<名前>/ に git repo + apm install 済の sandbox ができる (改修中の xp-harness をローカル依存で deploy)。既存 sandbox の使い回しでよいかは改修者と判断する。改修内容を sandbox に反映するには、改修を commit してから sandbox で apm install し直す (apm はローカル依存でも git の内容を見る)。
既定の構成は front (Vite + React) / api (Hono) / e2e (Playwright、webServer で両サーバ自動起動、スモーク spec つき) の分離構成で、探索型スキル (implementation / e2e / e2e-execution) が探し当てる先として以下を同梱する:
- 領域別スキル:
front-implementation / api-implementation。わざと対照的な規約 (front: interface のみ + コメント禁止、api: type のみ + JSDoc 必須) にしてあり、領域をまたぐ実装で規約の混線が起きたか grep で観測できる (例: api 配下に interface が出たら混線)
- front E2E 流儀スキル:
e2e-playwright-front (探索の「スキルなら呼ぶ」枝の対象)
- 実行手順ドキュメント:
e2e/README.md (探索の「スキルでないファイルは読む」枝の対象)
同梱スキルは配布物ではなく、consumer プロジェクトが持つ固有スキルの形を模した検証材料 (配布側の e2e skill と sync させる対象ではない)。「検証材料である」という注記を template 側の SKILL.md に書かないのは意図的 (= 上の「ノーヒント」原則の具体適用) — sandbox に複製されて検証セッション自身が読むため、観測を汚す。同梱スキルが探索型スキルに実際に探し当てられるかは検証ランで観測して確定する (同形の構成で探索発火・混線ゼロの実績あり)。
プローブによる連鎖発火確認などアプリが不要な検証は --bare で安く作る。
--wiremock は「外部 API をモックする E2E でモック検証が十分か」を確認する検証クラス用。api (Hono) + WireMock(Docker) 構成で、検証材料として「リクエストマッチが緩い既存テスト」「モックは仕様書の全パラメータを検証する規約スキル e2e-api-wiremock」「外部 API 仕様書」を同梱する (= セッションが『既存テストの検証が甘い』と自分で気づけるかを見る材料)。docs/working/ にはサンプルの要件 / 設計を同梱するが、これは筋書きの一例。実際の検証では、検証したい対象に合わせて筋書き (タスク・要件 / 設計) を差し替え、上の「検証条件の設計原則」(ノーヒント・実観測ケース) で点検してから走らせる。
途中状態の仕込み — 目的に応じて選ぶ:
-
skill の連鎖発火だけ安く確認したい (preload → Skill tool 呼び出しの連鎖など):
.claude/skills/harness-verification/scripts/setup-probe.sh <sandbox パス>
合言葉 PROBE_TARGET_FIRED_OK を出させるプローブ一式 (検証用 subagent + skill 2 つ) が配置される。配置内容と起動プロンプト例はスクリプトが出力する
-
実フェーズの発火・振る舞いを確認したい (実装フェーズで slice-tdd → implementation → reviewer の流れ等): sandbox の docs/working/<title>/ に要件定義.md・基本設計.md を置き、「実装フェーズの続き」という途中状態を作る。md はこの main session が書いてよい (ここはコストがかからない)
3. 検証セッションを起動・駆動する
走らせる前に、条件 (仕込み + プロンプト) をテスト観点でレビューする (外部の目)。上の「検証条件の設計原則」を 1 項目ずつ通す (項目の列挙はそちらが単一の出典)。特に 前後比較の要否とモデル は、ここで結論と理由を改修者に提示する。自己レビューは同じ盲点で素通りするので、改修者に条件を見せて確認を取ってから走らせる (高コストな実走の前の関門)。
interactive (サブスク枠) で自分で起動して FIFO 駆動する のが既定。scripts/claude-launcher.sh を使う (pty + FIFO + --remote-control を内包):
scripts/claude-launcher.sh launch <name> <sandbox パス> — 起動
scripts/claude-launcher.sh log <name> で Remote Control active を確認。出なければ起動失敗 → stop して仕切り直す (起動の stdout は捨てているのでサイレントに失敗しうる。ここを skip しない)
scripts/claude-launcher.sh send <name> "<検証プロンプト>" — プロンプト送信。送信後、log で処理が始まったことを確認してから次を送る(FIFO 送信は稀に submit されず未送信のまま残る。未送信のまま次を送ると入力が混線し、別物を検証してしまう)
- 注意 (v2.1.177 以降で確認): 起動直後に welcome dialog / 新機能通知が表示される場合、この dialog が残っていると
send したプロンプトが input box に入るが submit されない。rc active 確認後に printf '\r' > <name>.pipe を 1〜2 回送って dialog を閉じてから send すること
- 注意: input box に ghost text (= 次のユーザー返信の提案) が薄字で出ることがある (実観測)。
send は入力を上書きするので通常の送信は影響を受けない。ただし dialog 閉じ・再 submit 等で printf '\r' を単独で送るときは、直前に log で input box に ghost text / 意図しない文言が残っていないか確認してから送る (= 意図しない発話が submit されて検証の入力が汚れるのを防ぐ)
scripts/claude-launcher.sh wait-idle <name> --timeout <秒> でターン完了 (入力待ち) を待つ → IDLE が返ったら手順 4 で解析。判定は pty 画面 (log) の mtime で行う (処理中はスピナーが画面を書き続け、idle で止まる) ので、長考・巨大トークン生成・AskUserQuestion 終わりも idle と誤らない。transcript の更新停止で判断しない (thinking 中は transcript が書かれず、長考を idle と誤検知する)。
--timeout はそのターンの重さに応じて呼ぶ側が渡す (サブエージェントを数回挟むなら長め)。既定 300s は網。idle 判定閾 (quiet 6s) は固定。
TIMEOUT が返ったら状態を見る: 「まだ処理中 (画面が動いている)」なら --timeout を延ばして再 wait、「画面が止まっているのに idle 未検知」なら想定外なので log で実状態を確認。放置でなく必ず引き戻される。
NOSTART は send が submit されていないサイン → printf '\r' > <name>.pipe で再送信してから wait-idle。
scripts/claude-launcher.sh stop <name> — 停止 + 片付け(実際に終了してから返るので、呼び出し後に手で再確認しない)
手動でやる場合 (従来フロー) は、起動ディレクトリと貼り付け用プロンプトをセットで提示する。形式:
検証の準備ができました。以下で検証セッションを起動してください:
cd <sandbox パス> && claude
起動したら、このプロンプトを貼ってください:
<検証目的に合わせたプロンプト>
走り終わったら教えてください。transcript を解析します。
プロンプトには「どの状態から始まるか」(例: docs/working// に要件定義.md と基本設計.md がある、実装フェーズの続き) と「自走してよい範囲」(branch 作成の承認等、確認で止まらないための前置き) を含める。
対話フェーズ・多ターン・前後比較の駆動 (型)
- 対話フェーズは依頼者役で駆動する: 要件定義・基本設計は対話フェーズなので、1 発のノーヒント依頼で「発火したか」だけ見ても足りない (対話が進まず、そのフェーズが走らない)。検証者が依頼者役として応答を読み、Why / Done / スコープに答え・推奨案を選び、対話を回して初めてそのフェーズを検証できる (実装フェーズで自走に切り替わる)。この対話再現は応答が可変なので固定スクリプト化できない — 依頼者役の駆動は手で回す
- AskUserQuestion を FIFO で答える: 矢印 (
printf '\033[B' > <name>.pipe) で選択肢を移動して Enter (printf '\r') が確実。番号 ("3" 等) を send すると自由記述欄に入って誤爆しうる。マルチ質問ウィジェットは各質問を Enter で進めて最後に Submit。TUI の log は文字化けするので、判定は見た目でなく analyze-session.py で裏取りする
- ドライバスクリプトで自走を回している最中に出る質問も、回答は手で送る: 質問ウィジェットは選択と Submit で状態が遷移するので、画面を読まずに機械的な Enter 連打で答えると却下され ("User declined to answer questions")、そのランは丸ごと無効になる (実際に発生)。毎回 log で今どの質問・どの選択肢にフォーカスがあるかを読んでから、矢印と Enter を送る (自動化の外に置く)
- 多ターン・長時間の検証はドライバスクリプトで一気通貫に回す: 実装フェーズの複数サイクルや前後比較の複数試行は、launch / send / wait-idle / analyze を 1 本のスクリプトにまとめて回す (micro-step で改修者を呼び戻さない = トークン節約・再現性)。対話フェーズだけは上記のとおり手で駆動する
- 走っているドライバスクリプトを編集しない: bash はスクリプトを逐次読みながら実行するので、走行中のファイルを書き換えると実行位置がずれて構文エラーで落ち、そのランが壊れる (実際に発生。transcript から救済はできたが記録は欠けた)。直したいことに気づいたら、そのバッチが終わるまで待つか、バッチを止めてから直して回し直す
- instruction / rules の前後比較は deploy 形を差し替える: apm は instruction を
.claude/rules/<name>.md に deploy する (frontmatter applyTo: → paths: 変換、本文は無変換)。旧版・新版の deploy 形を作って .claude/rules/<name>.md を旧/新で cp 差し替えれば、apm install し直さず前後比較できる
4. transcript を解析する
.claude/skills/harness-verification/scripts/analyze-session.py <sandbox パス>
最新セッションの発火事実 (main の Skill 発火・subagent 起動の時系列、各 subagent 内の Skill 発火、SKILL.md を Read しただけのケース) が一覧で出る。--list でセッション一覧、--session <ID> で指定、--grep <文字列> で合言葉等の出現確認。
読むときの観点:
- Skill tool で発火したか、Read で済まされたか: SKILL.md を Read しただけの場合、補助ファイルを取りこぼす失敗モード。⚠ 表示が出たら発火失敗を疑う
- main と subagent のどちらが呼んだか: 「subagent に発火させたい skill を main が読んでしまった」は別物。出力の section 分けで区別できる
- 期待した振る舞いの痕跡: 確認したい事実 (手順 1 で言語化したもの) が transcript 上で観測できたか。コマンド実行の痕跡は
--grep や sandbox の git status / git diff (初期 commit との差分) でも観測できる
- 出力に出ないことは「起きなかった」と断定しない: スクリプトは主要な事実だけ抽出する。疑わしいときは transcript (
~/.claude/projects/ 配下の jsonl、subagent は <session>/subagents/agent-*.jsonl) を直接読む
- 集計を真と扱わない (= 肯定的事実も生データで裏を取る): スクリプトが「発火した」「N 件」と出していても、それを鵜呑みに「確認できた」と報告しない。発火・引用・振る舞いといった肯定的事実こそ、生 transcript で tool_use を確認してから事実として報告する (上の「断定しない」が不在側、これが存在側の対)
自走セッションの タイムライン(稼働時間・介入回数)を復元する ときの落とし穴:
- 人間の介入点は 2 種類ある: 自由記述の user メッセージだけでなく、
AskUserQuestion の回答も介入点として記録に乗る。片方だけ数えると介入回数を取りこぼす(実際、選択肢回答を除外して数え、自走時間を過大評価した失敗がある)。remote-control 経由でも記録形は同じ(remote-control は入力を隠さない)
- 介入点は回答文言でなく
AskUserQuestion の tool_use で捉える: ツールを呼んだ時点がもう停止点なので、tool_use を数えれば介入の回数・タイミングは文言に依存せず取れる。回答の中身が要るときだけ、その id に対応する tool_result を引く。回答文言そのものを検出条件にしない — 文言は複数フォーマットあり("...have been answered" / "The user answered: ..." を実観測)、片方だけを grep すると別フォーマットの回答を丸ごと落とす(実際 have been answered だけで拾って push 承認を取りこぼし、「無断 push」と誤断定した失敗がある)
- 許可プロンプト(push 等の権限確認)は transcript に残らない: ハーネス層の UI 操作で jsonl に乗らない。上の「出力に出ないことは起きなかったと断定しない」の対処(生 transcript を読む)が届かない一段強い層で、生を読んでも不在の証明にはならない。「回答の記録が無い=確認せず実行した」と断定しない
- 稼働と待ちの測り方: 介入点で区切り、「介入 → 次の停止」を稼働時間、「停止 → 次の介入」を人間待ちとして測る。停止は自発 gate(
AskUserQuestion 提示 / 確認を求める発話)で起きる
- 無音(アイドル)判定は行数で見る: jsonl の mtime はメタデータの touch でも動くので「再開」を誤検知する。会話が実際に進んだかは 行数の増加 で判定する。コンパクト後も同じ jsonl が追記され続ける(新しいファイルにはならない)
稼働時間の 内訳(何に時間が使われたか)を割る ときの見方(成果密度の観点で効く):
- カテゴリ: 稼働 1 区間を「subagent 待ち(code-reviewer / done-verifier 等への検証委譲)」「main 自身の検証実行(test / build / DB)」「実装・思考・生成」「git / 調査」に割る。subagent 待ちは subagent の jsonl の最初→最後で測る(main はその間ほぼ待ち)
- 実装は残差で見る: 実装の実体は「結果を読んで次を考え・コードを生成する」ツール間の間隔に乗る。Edit / Write 自体は一瞬なので 編集ツールの所要時間では 0 に見える。総稼働から他カテゴリを引いた残差を「実装・思考」とみなす
- 後段が検証寄りになるのは正常: タスクが仕上げ・検証フェーズに入るほど、時間の主役は「作る」から「確かめる」に移る(検証割合が増える)。タスク数が多いほど後半で顕著。これは 空転(実装が進まず待ちに溶ける=連携・リズムの不全)とは別物 で、それ自体は手を打つ対象ではない ── 検証テールを異常と誤読しないための線引き
- フェーズ別に % で切り直す: 稼働をフェーズ(タスク / サイクル)で区切って上のカテゴリ別に 分・% を出すと、局面ごとの主役の移り(作る→確かめる)が数字で見える
自走実装セッションの サイクル構造と skill 発火を復元する ときの見方(規律通り走れたかの観点で効く):
- 入れ子サイクルを復元する: agent の宣言(「red を書く」「次に driver 層」「リファクタ」等)+テスト / 編集 / リファクタの並びから、実走が踏んだ入れ子サイクルを復元する。正典の綴りはここに書き下さず、slice-tdd 本文に照らして「入れ子か・outside-in か・各単位が正典サイクルを踏んだか」を判定する(single source は slice-tdd)。なお slice-tdd の入れ子は大=ストーリーを E2E で駆動 / 小=層ごとで、実運用は複数タスクをまたぐため タスク境界の区切りが挟まる(これは本 skill 側の復元単位で slice-tdd の正典ではない)。外側が E2E-red 起点でないこともある(remediation 等)── その順が対象の性質に照らして妥当かで見る
- skill 発火は 2 通りで見る(役割が違う): (1) フラットな一覧(時刻+skill)で「全部を適切なタイミングで呼べたか」を網羅チェック。(2) サイクルの各局面に埋め込んで「サイクル上の正しい位置で呼べたか」を見る(例: domain-modeling が domain 設計の直前 / e2e-execution が実行の局面)。領域が変わる局面での再発火漏れ(別リポ・別領域に移ったのに implementation 等が再発火しない)は、埋め込みビューでしか見つからない
解析結果は事実 (起きた / 起きていない) として改修者に報告する。発火しなかった場合の原因究明と改修は、この skill の外 (通常の skill 改修フロー) で行う。
報告は「検証レポート」の書式で出す
検証で取れた事実 (起きた / 起きていない) を土台に、その上へ全体結論 (リリース可否の目線) と軽い提案を一段重ねて渡す ── 発火・動作の検証がこの skill の核で、可否そのものを決めるのは依頼者。
解析している間は実況してよいが、報告はそれと地続きにしない。調査の過程を読み返さなくても成立するよう、はっきりした区切りを立てて「ここから報告」を明示する。中身は抽象度を上から下へ深める (最抽象の結論 → 詳細 → 証拠)。複数シナリオは入れ子にする (全体 → 一覧 → 各詳細)。これは dialogue-principles の「同じ抽象度で話す」「段階的開示」を報告に当てたもの。
---
# 検証レポート: <タイトル> ← はっきりした区切り (ここから報告)
## 全体結論
<PASS/FAIL + 平易な意味 + リリースの温度感 (確信の厚み)。複数シナリオなら「N 件中 M PASS」。PR 番号など具体は書かない>
## シナリオ一覧 ← 複数シナリオのとき。ここまでで全体像が取れる
- <シナリオ A>: PASS / FAIL
- <シナリオ B>: PASS / FAIL
## 各シナリオ詳細 ← シナリオごとに一段深く降りる
### <シナリオ A>
- 何を検証したか: 対象 skill / 条件 (**再現粒度**: sandbox flavor / 仕込み / プロンプト全文 / 前後比較 / 試行数) / 反証条件
- 結果: 観測された振る舞い
- 証拠: 生 transcript・git 状態から取れた事実 (FAIL なら核が破れた証拠)
## 提案 (軽い) ← 次どうするか
<リリース可否 / できてない所を別ストーリーに切るか等の次の一手>
書式の要点:
- 全体結論の温度感: 温度感 = 検証の網羅・確信の厚み (対象 skill に点数・ランクを付ける話ではない ─ 自走の質を良し悪しで見るのとは別レイヤー)。検証が厚く確信を持って出せる / 検証パターンが薄くて心許ない / 何パターンか回して概ね OK 等。「1 件でも FAIL なら機械的に FAIL」にはしない、中身で判断する。結論の形 (PASS/FAIL + 平易な意味 + 温度感、具体は書かない) はテンプレ側の通り
- 地の文は平易に書く: 結論・結果の地の文は、過程を知らない読み手に分かる言葉で書く (対象 skill / セッションの硬い言い回しをそのまま持ち込まない)。証拠の生 transcript / git 引用そのものは改変せず忠実に載せる (下の裏取りと同じ)
- 提案は軽く、確定しない: 「できてない所は別ストーリーで切るか」等を提案として出す。結論を出しきって依頼者の判断を奪わない (= エンジニアとして提案する)。可否を決めるのは依頼者
- 証拠は生データで裏を取ったものだけ載せる (上の「集計を真と扱わない」と同じ)
- 単一シナリオなら「シナリオ一覧」は省き、全体結論 → 詳細 → 提案でよい
- 自走実装セッションの分析では詳細セクションを 2 つ足す: 「サイクル構造」(入れ子サイクルの復元 + skill 発火をサイクルの各局面に埋め込み)と「時間配分」(フェーズ別のカテゴリ % 表)。skill 発火はフラット一覧も併記する(一覧と埋め込みの役割差は手順 4 の通り)。手順 4 の復元手順で得た事実をこの 2 セクションに載せる
検証記録を references/ に残す
検証は throwaway な sandbox で回すので、報告(上の検証レポート)を再現レシピ付きで永続化した記録を references/ に残す — 報告の結果をそのまま記録の「結果」に写し、加えて再現レシピ(条件)を足す。sandbox 自体は git に入れない(setup-sandbox.sh +その条件で再生成できる)。docs/working/ は working でいつ消えてもおかしくないので 依存しない — 記録は references/ だけで成立させる(結果・証拠を inline で書き写す)。
- 置き場:
.claude/skills/harness-verification/references/(1 検証 = 1 ファイル YYYY-MM-DD_対象.md)
- format の single source は
references/README.md(必須項目・frontmatter のキーはそこと validate-verifications.sh が持つ。本文には写さない)。条件は再現粒度で書く(setup-sandbox の flavor / 仕込んだ状態の中身 / ノーヒント依頼の全文 / 前後比較 / 試行数)
- 足したら点検・検索:
.claude/skills/harness-verification/scripts/validate-verifications.sh(format 点検、違反で exit 1)/ .claude/skills/harness-verification/scripts/find-verifications.sh [キーワード](目的 / 対象 / verdict / 本文の横断検索、引数なしで一覧)
5. 後片付け
-
プローブを配置した場合は必ず削除する:
.claude/skills/harness-verification/scripts/setup-probe.sh <sandbox パス> --clean
-
検証セッションが sandbox に生成した成果物 (実装コード等) を残すか消すかは改修者と判断する (再検証でクリーンな状態が要るなら 再 deploy 済みを commit した baseline に戻す: git reset --hard <baseline> + git clean -fd。戻す先の選び方は次の落とし穴を参照)。baseline は tag で打つ — branch にすると検証セッションが切った branch を掃除するときに一緒に消える (落とし穴2 と同根)
-
落とし穴1: reset の deploy 巻き戻し (ケース毎にリセットして回すとき): deploy 済み skill は sandbox に git tracked で入っているので、再 deploy より前の commit へ reset すると deploy も旧版に巻き戻る (= 改修版でなく旧版で走ってしまう)。だから戻す先は上記 baseline にする (初期 commit が再 deploy 前なら使わない)。リセット後は「検証対象 skill が実際に deploy されているか」を 1 度確認してからケースを流す
-
落とし穴2: reset の branch リーク: git reset --hard は branch を切り替えないので、検証セッションが切った branch が次ケースに残る → base branch へ戻し不要 branch を消す
-
sandbox 自体の削除は改修者の判断。基本は残す (次回の検証で使い回せる)
-
例外: worktree から setup した sandbox は、worktree の掃除とセットで片付ける。setup-sandbox.sh はスクリプトの場所から xp-harness root を解決するため、改修 worktree で実行すると sandbox は <worktree の親>/xp-harness-test/ に作られ、apm.yml のローカル依存も worktree のパスを指す。worktree を削除すると依存が宙に浮き apm install し直せなくなるので、worktree の後片付け時に sandbox も削除する (再検証したければ統合後の main から作り直す)