harness-eval について
Harness Evalは、リポジトリ内のエージェントハーネスを評価するスキルです。正確性、冗長性、有用性のレポートを作成し、負荷の高い評価には事前承認を求めます。既定ではファイルを自動編集しません。
主な機能
- 01リポジトリの目録と主張を抽出
- 02スクリプトで参照パスとコマンドを確認
- 03任意の二重判定による冗長性評価
- 04任意の二重判定による有用性評価
- 05簡素化候補の参照元を確認
活用シーン
- 01エージェント向け説明のパスやコマンドを検証
- 02スキル内容の冗長性や有用性を評価
- 03ハーネスの簡素化前に評価レポートを確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tech-leads-club/ agent-skills --skill harness-evalインストール後、Claude Code で/harness-evalを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/claims.schema.jsonGLOSSARY.mdjudge-prompts.mdPROTOCOL.mdscripts/doc_scope.pyinventory_extract.pymerge_agreement.pymerge_usefulness.pyslim_fanin.pysurfaces_extract.pytrack_a_correctness.py詳細
ハーネス評価
スタックに依存しないハーネス評価を一通り実行し、レポートの作成までで停止します。ユーザーが Ship/Slim を確認したうえで明示的に依頼しない限り、AGENTS.md やスキルを自動編集しないでください。
ユーザーへの質問(最優先)
続行する前に停止して質問してください。 これらの確認手順を省略しないでください。任意のドキュメントを黙って含めたり、B/C の審査担当者を起動したりしないでください。
インベントリの後は、Q1(必要な場合)→ Q2 → Track A の順に進めます(A は必ず実行)。B/C は承認された場合のみ実行します。
Q1 — 任意のプロジェクトドキュメント(インベントリの後)
optional-docs-candidates.md に任意の種類が記載されている場合、Q2 / Track A の前に質問します。
Inventory found cited project docs outside the agent skill trees.
- **Always in scope:** skill-tree files (`.agents/skills`, `.cursor/skills`, `.claude/skills`)
- **Always excluded:** ADRs / RFCs / decision-record trees (never scored as T2)
- **Optional (default: omit):** see types/paths in `optional-docs-candidates.md`
Include any optional doc types or paths in this run?
Reply with: `none` (default), type ids (e.g. `docs`), and/or specific paths.
ユーザーの回答後に限り、--include-doc-type / --include-doc を指定してインベントリを再実行します。任意の種類がない場合は Q1 を省略します。
Q2 — Track B と C(Track A の前 — 予算)
ユーザーがあらかじめ費用を設定できるよう、Track A の前に質問します。次に実行する Track A は必須です(決定的で、モデルのトークンを約 0 消費します)。B/C は承認された場合のみ実行します。
Choose eval scope for this run (before Track A).
| Track | Question | Certainty | Token consumption |
|-------|----------|-----------|-------------------|
| **A — Correctness** | Cited path/command exists? | **Highest** — script only, no LLM. Prefers false negatives over false BROKEN. | **~0 model tokens** (always runs next) |
| **B — Redundancy** | Would an agent rediscover this cheaply without the harness? | **Medium** — dual LLM + plants; Ship only if trap PASS and both agree. Disagree → Hold. Less model-sensitive than C. | **High** — 2 judges × every claim (~N in this inventory). Each may spot-check the repo. |
| **C — Usefulness** | Does this surface change behavior vs theory/demo/overlap? | **Lowest / most subjective** — dual LLM + plants + fan-in; **model-sensitive**. Slim/Mixed need gates; prefer second-model check before large deletes. | **Highest** — 2 judges × every surface (whole files; often dominates the run). |
Notes: Ship (B) ≠ Slim (C). Rediscoverable ≠ useless. A always runs; B/C are optional.
Reply with one of: `A only`, `B`, `C`, or `B+C`.
判明している場合は、claims.md からクレーム数を記入します。抽出後の T0+T1+T2 の Markdown のおおよその数を提示するか、まだ実行していない場合は「surfaces_extract の実行後」と伝えます。
A only: Track A を実行し、04を提示して停止します(B/C の審査担当者は起動しません)。B: Track A を実行後、手順 4~6 を実行します。C: Track A を実行後、手順 7~10 を実行します(C に B は不要です)。B+C: Track A を実行後、手順 4~11 を実行します。
トリガーとなったメッセージでユーザーがすでに B/C/full eval を依頼している場合は、承認済みとして扱います。それでも費用がわかるよう、Q2 の表は一度提示してください。
このスキルのファイルを読み込む
このスキルは自己完結型です。プロトコル、スクリプト、審査用プロンプトは、このスキルのディレクトリ(SKILL.md を含むフォルダー)にあります。SKILL_DIR はそのディレクトリとして解決し、別のインストール先を決めつけないでください。
- 最初の実行前に(スクリプトが失敗した場合は再度)references/PROTOCOL.md をすべて読んでください。
- Track B または Track C の審査担当者を起動する際は、references/judge-prompts.md を読んでください。
- 平易な用語の説明は references/GLOSSARY.md を参照してください(
04/07/10のレポート冒頭にも記載されています)。 - クレーム記録の形式は references/claims.schema.json を参照してください(ツール用です。エージェントは毎回読み込む必要はありません)。
- スクリプトは
python3 "$SKILL_DIR/scripts/<name>.py" ...として実行してください。
実行結果(プロトコルを除く)は、対象リポジトリの .harness-eval/runs/<run-id>/ に保存します。
重要なルール
- デフォルトは報告のみです。 判定は修正ではありません。
- README は対象外です。 ハーネスの対象としても、再発見可能性/有用性の根拠としても扱いません。
- スタックに依存しません。 プロンプトやプラントで、パッケージマネージャー、DB、フレームワーク、フォルダー構成をハードコードしないでください。存在するマニフェスト(JS、Python、Make/Task、Rust、Go、PHP、Ruby/Rails、Java/Gradle/Maven、および
bin/*)を検出してください。 - ドキュメントの対象範囲。 T2 には常にエージェントのスキルツリー参照(
.agents/skills、.cursor/skills、.claude/skills)が含まれます。ADR / RFC(意思決定記録ツリー)は常に T2 の対象から除外します。その他の引用されたプロジェクト文書は任意です。デフォルトでは省略し、このスキルの先頭にある Q1 で確認してから、--include-doc-type/--include-docを指定して再実行してください。 - 棚卸しの後は、常にトラック A を実行します(決定論的で高精度)。誤った BROKEN 判定よりも偽陰性を優先してください。プレースホルダー(
SPEC_FOLDER、{x}、[feature])は決して BROKEN ではありません。str.lstrip('./')でパスを正規化しないでください。 - トラック B と C は、トラック A の前に Q2 を通じてユーザーの承認が必要です。 ユーザーが明示的に選択するまで、B/C の判定担当を起動しないでください。ユーザーは B のみ、C のみ、両方、または A のみを承認できます。
- トラック B には、二重判定担当とプラントが必要です。 Judge2 はブラインドであり、Judge1 のスコアや
trap-key.jsonを読んではいけません。トラップゲートが PASS で、二重判定が REDUNDANT、かつ Judge2 のコストが 1 以下の場合にのみ Ship します。 - トラック C には、二重判定担当とプラントが必要です。 ブラインドの Judge2 は
08-usefulness-j1.mdまたはusefulness-trap-key.jsonを読んではいけません。トラップが PASS で、二重判定が SLIM/ROUTING-ONLY、かつファンインが PASS の場合にのみ Slim します(他のハーネス対象がそのパスを SoT としてハードロードしていないこと。マージでは--seedだけでなく、スキルツリー全体に対して検証されます)。有用性はモデルに左右されます。両方のスコアファイルにmodel: <id>を記録してください。実行中は同じモデルを使うのが望ましく、大規模な Slim 削除の前には、2 つ目のモデルで再判定してください。 - KEEP / KEEP-CORE プラントは、デッキ内にすでにある主張/対象の逐語的なコピーにしてはいけません。
- サブエージェント: 許可リストにある非 fast モデルを使用してください(ポリシーが許す場合は、親と同じファミリーを優先)。
*-fastモデルは使用しないでください。 - トラックを同一視しないでください。 トラック B の Ship はトラック C の Slim と同じではありません。再発見可能だからといって役に立たないとは限らず、役に立つからといって冗長でないとは限りません。
- Slim の適用/ファンイン。 「Slim fan-in blocked」に記載された Slim パス、または
python3 "$SKILL_DIR/scripts/slim_fanin.py" --path <P>が参照元を報告する Slim パスは、同じ変更内でそれらの利用側を更新しない限り、スタブ化も削除もしないでください。 - Mixed/Slim の適用は自己完結させます。 REPO-DEMONSTRATED / THEORY を削除する場合は、ハーネス対象内の該当箇所を削除または圧縮してください。フェンス付きの説明用スニペット(または、それが担っていた契約)を
See app/.../lib/.../test/...に置き換えてはいけません。これは SoT をコードツリーへのポインターに置き換えることになります。判定の根拠となるパスはスコア表にのみ記載してください。動作を変える契約を残す必要がある場合は、スキル内に短いルールまたはスニペットを残してください。 - Mixed の適用は機械的に行います。 二重判定が MIXED であるだけでは不十分です。マージ処理は、ID ごとに Keep-core 列から KEEP、Slim 列から CUT を記載した
11-mixed-apply.mdを出力します。適用担当はそのファイルの指示にのみ従ってください。再判定、再設計、KEEP とは異なるパターンの考案はしないでください。Keep-core/Slim のセルが空の場合は、そのパスをスキップします(Hold)。
手順
ステップ 1:SKILL_DIR を解決する
SKILL_DIR を、この SKILL.md があるディレクトリに設定します。以下を確認してください。
$SKILL_DIR/references/PROTOCOL.md$SKILL_DIR/scripts/inventory_extract.py$SKILL_DIR/scripts/track_a_correctness.py$SKILL_DIR/scripts/merge_agreement.py$SKILL_DIR/scripts/surfaces_extract.py$SKILL_DIR/scripts/merge_usefulness.py$SKILL_DIR/scripts/slim_fanin.py$SKILL_DIR/scripts/doc_scope.py
存在しない場合、スキルのインストールが壊れているため、停止してください。
ステップ 2:棚卸しと主張デッキ
対象リポジトリのルートから実行します。
RUN_ID=$(date -u +%Y-%m-%d)-full
python3 "$SKILL_DIR/scripts/inventory_extract.py" --root . --run-id "$RUN_ID"
# Optional scope: AGENTS.md + one-hop related skills only
# python3 "$SKILL_DIR/scripts/inventory_extract.py" --root . --run-id "$RUN_ID" --seed AGENTS.md
.harness-eval/runs/$RUN_ID/ に以下が生成される想定です:inventory.json、claims.jsonl、claims.md、trap-key.json、optional-docs-candidates.md(および .json)。
Step 2b: 任意のドキュメント — Q1(冒頭を参照)
optional-docs-candidates.md を読みます。任意のタイプが存在する場合は、ユーザーへの質問の Q1 を実行します。承認後にのみインベントリを再実行します。
python3 "$SKILL_DIR/scripts/inventory_extract.py" --root . --run-id "$RUN_ID" \
--include-doc-type docs # and/or --include-doc path
Step 2c: 予算を確認 — Q2(冒頭を参照)
Track A の前に、ユーザーへの質問の Q2 を実行します。回答(A only / B / C / B+C)を記録します。B および/または C が承認されていない限り、Step 4 以降を開始しないでください。
Step 3: Track A(決定論的)— 必ず実行
python3 "$SKILL_DIR/scripts/track_a_correctness.py" --root . --run-id "$RUN_ID"
想定される成果物:04-correctness.md(冒頭に用語の定義を含む)。.agents/... の参照先が解決されること(agents/... ではないこと)を抜き取り確認します。
Track A を要約します(問題の件数と注目すべきクラスター)。Q2 の回答が A only の場合は、ここで終了します。それ以外の場合は、承認された B および/または C のステップに進みます。
Step 4: Track B — Judge1
references/judge-prompts.md(Track B Judge1)を読みます。許可リストに登録されたモデルを使用し、独立したサブエージェントを起動します。.harness-eval/runs/$RUN_ID/claims.md を指定します。05-redundancy-j1.md(model: <id> を含む)を作成します。
Judge1 は inventory.json を読んでもかまいません。trap-key.json は読んではいけません。
Step 5: Track B — Judge2(ブラインド)
references/judge-prompts.md(Track B Judge2)を読みます。2 つ目のサブエージェントを起動します。06-blind-scores.md を作成します。
Judge2 が読むことを禁止するファイル:trap-key.json、05-redundancy-j1.md、07-agreement.md、過去の合意レポート。
Step 4 と Step 5 は並行して実行することを推奨します。
Step 6: Track B の合意を統合
python3 "$SKILL_DIR/scripts/merge_agreement.py" --run-dir .harness-eval/runs/$RUN_ID
想定される成果物:07-agreement.md(Ship/Review/Hold と これらの用語の意味)。トラップが FAIL の場合は、PROTOCOL に従って仕掛けを修正し、P00x を再採点して再統合します。Ship にしてはいけません。
Step 7: Track C — サーフェスデッキ
python3 "$SKILL_DIR/scripts/surfaces_extract.py" --root . --run-id "$RUN_ID"
想定される成果物:surfaces.md、surfaces.json、usefulness-trap-key.json。
Step 8: Track C — Usefulness Judge1
references/judge-prompts.md(Usefulness Judge1)を読みます。許可リストに登録されたモデルを使用してサブエージェントを起動します(ヘッダーに同じ ID を記録)。08-usefulness-j1.md を作成します。
usefulness-trap-key.json は読んではいけません。
Step 9: Track C — Usefulness Judge2(ブラインド)
Usefulness Judge2 のプロンプトを読みます。合意の安定性を高めるため、Step 8 と 同じモデル を使うことを推奨します。09-usefulness-j2.md を作成します。
読むことを禁止するもの:usefulness-trap-key.json、08-usefulness-j1.md、10-usefulness-agreement.md。また、有用性クラスの判断に Track B の 05/06/07 を使用してはいけません。
Step 8 と Step 9 は並行して実行することを推奨します。
Step 10: Track C の合意を統合
python3 "$SKILL_DIR/scripts/merge_usefulness.py" --run-dir .harness-eval/runs/$RUN_ID
想定される成果物:10-usefulness-agreement.md(Slim/Keep-core/Mixed/Hold と これらの用語の意味)、11-mixed-apply.md(各 Mixed ID の KEEP/CUT)、および slim-fanin.json。トラップが FAIL の場合は Slim にしてはいけません。slim-fanin-blocked のサーフェスは Hold です。Slim の適用候補ではありません。
Step 11: 結果を提示
合意レポート(それぞれ冒頭に用語の定義があります)に基づいて要約します。
- Track A の問題件数 →
04-correctness.md - Track B のトラップと Ship/Review/Hold →
07-agreement.md - Track C のトラップ、ファンイン、および Slim/Keep-core/Mixed/Hold →
10-usefulness-agreement.md - Mixed の件数が 0 より大きい場合は
11-mixed-apply.mdを明示します(Mixed の適用経路はこれだけです) - Track C で使用したモデル ID と、Slim がモデルに依存することを明示します
- Slim のファンインがブロックされている行を明示します(seed の外にある利用側が含まれる場合があります)
ユーザーから Ship/Slim/Mixed の適用を依頼されない限り、ここで終了します。適用する場合:
- Slim: Slim テーブルに記載されたパス(ファンインが PASS のもの)のみを対象とします。利用側を先に更新せずに、ファンインでブロックされたパスをスタブ化してはいけません。
- Mixed:
11-mixed-apply.mdを開き、ID ごとに KEEP/CUT のみを実行します(ルール 12)。Mixed のパス一覧だけを基に再判定してはいけません。カットしたデモの代わりに、コードツリーのパスポインターを追加してはいけません(ルール 11)。
例
例 1:ハーネス評価を完全に実行
ユーザーの依頼:「このリポジトリでハーネス評価を実行して」
実行内容:インベントリ → 必要に応じて Q1 → Q2(B/C の予算表)→ Track A → 承認された場合は Step 4〜11。B の判定者を並行して実行し、続いて C の判定者を実行します。合意結果を提示します(用語は各ファイルに記載されています)。
例 2:既存の実行結果で有用性のみを評価
ユーザーの依頼:「最後に実行した harness-eval の実行結果で Track C の有用性評価を実行して」
実行内容:その RUN_ID に対して Step 7〜11 を実行します(インベントリはすでに存在している必要があります)。
例 3: 誤ったスキル
ユーザーが「setup harness」/「init harness」と言った場合 → harness setup(このスキルではありません)。ユーザーが「specify feature」と言った場合 → tlc-spec-driven です。
トラブルシューティング
Trap ゲート FAIL(トラック B または C)
原因: KEEP/KEEP-CORE のプラントがデッキの重複であった、またはブラインドジャッジがファミリーを誤判定した。解決策: スキルの固定プラントテンプレートを使用し、プラントを再スコアリングし、再マージします。
トラック A で .agents/... が誤って欠落する
原因: パス正規化の不具合。解決策: スキルスクリプトは normalize_cite(./ のみを除去)を使用する必要があります。$SKILL_DIR/scripts/ からトラック A を再実行します。
サブエージェントがブロックされる
原因: モデルが欠落しているか許可リストにない、または *-fast がブロックされている。解決策: 許可リストにある非 fast モデルで再起動します。
モデル変更後にトラック C の Slim がおかしく見える
想定事項: 有用性はモデルに依存します。2 つ目のモデルで C1+C2 を再実行し、Slim 帯域の積集合が安全に削除できる集合です。
Mixed apply が規約を書き換えた / モジュールを削除した
原因: apply エージェントが KEEP/CUT に従わず、Mixed パスリストから再判定した。解決策: 11-mixed-apply.md 経由でのみ apply します。そのファイルが存在しない場合は merge_usefulness.py を再実行します。Keep-core/Slim のセルが曖昧な場合は、apply の前にそれらの ID を再スコアリングします。
T2 が空 / スキルの references/ がインベントリにない
原因: パス正規化が lstrip("./") を使用し、.agents/… を agents/… に変換した。解決策: doc_scope.normalize_rel は ./ プレフィックスのみを除去する必要があります(トラック A と同じルール)。
トラック C に ADR が出現した
原因: 古いインベントリがすべての 1 ホップの docs/** を T2 として扱っていた。解決策: v1.7+ では意思決定記録のツリーを除外します。ユーザーが承認したオプションのドキュメント種別(ADR/RFC は決して含まない)のみが T2 に入ることができます。
Slim スタブがそのファイルを読み込む別のスキルを壊した
原因: fan-in なしのコンテンツ OVERLAP/Slim — 古い実行、または apply がゲートをスキップした。解決策: チェックリスト本体を復元し、merge_usefulness.py で再マージします(fan-in はスキルツリー全体をスキャンします)。slim_fanin.py --path <P> で確認します。
スクリプトが見つからない
原因: スキルフォルダが不完全。解決策: $SKILL_DIR/scripts/ と references/ を復元します。