pasteurize について
pasteurize は再現が難しいソフトウェアの不具合を調査するための、手順化されたデバッグスキルです。仮説を立てる前に再現ループを構築・検証し、計測、回帰テスト、修正、後片付けを導きます。
主な機能
- 01再現性のある不具合ループの構築
- 02複数回実行による想定症状の確認
- 03検証可能な仮説の順位付け
- 04対象を絞った計測と修正の案内
- 05一時的なデバッグタグの検査
活用シーン
- 01不安定またはタイミング依存の不具合調査
- 02本番コードの変更前にリグレッションを追跡
- 03回帰テストと元のループによる修正確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ paulnsorensen/ easy-cheese --skill pasteurizeインストール後、Claude Code で/pasteurizeを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
wedge.tomlreferences/commands.mdfeedback-loops.md詳細
/pasteurize
難しいバグには、このプロセスを使用します。
規律
ルール: 仮説を立てる前に、信頼できるフィードバックループを構築します。
次の危険信号が現れたら、その時点で止めてください。
- ループで失敗を再現する前に、原因を特定する。
- 無関係な失敗を再現として受け入れる。
- 実際の境界が難しいという理由で、モックした境界にテストを追加する。
- 同じ仮説リストに対して、4回目の修正を試みる。
- セッションタグの一括確認をせずに、作業ツリーがクリーンだと報告する。
| もっともらしい理由 | 回答 |
|---|---|
| 「原因は明らかです。」 | まずループを構築します。原因が明らかなら、1回の実行で確認できます。 |
| 「ループを書くのに時間がかかりすぎます。」 | 時間がかかるループでも、誤った修正よりはましです。 |
| 「どんな失敗でもバグの証明になります。」 | 想定される終了コードまたは出力と一致させます。 |
| 「モックした境界でも十分近いです。」 | 欠けている境界を記録し、Moldに引き継ぎます。 |
| 「あと1回試せばうまくいきます。」 | まず新しい仮説リストを書きます。 |
コードを調べる際は、code-intelligence-routing.md に従ってください。
artifact-path specs を使用して仕様ストアを解決します。
解決したディレクトリから、失敗した境界に関するメモを読みます。
移植性のあるツールの使用については、harness-portability.md を読んでください。
${CLAUDE_SKILL_DIR} より先に、バンドル済みまたはリポジトリのヘルパーを使用します。
${CLAUDE_SKILL_DIR} は任意のホスト側フォールバックとして扱います。
ハンドオフブロックを移植性のある契約として使用します。
スラッシュコマンドはホスト側の表示形式であり、制御モデルではないことに留意してください。
入力
<input> は報告された症状です。
バグ報告、スタックトレース、失敗したテストの出力、またはアーティファクトのパスを受け付けます。
Affinage、Cheese、Cookからの調査依頼を受け付けます。
調査依頼では、次のフィールドを使用します。
| フィールド | 型 | 必須 | 意味 |
|---|---|---|---|
source | string | はい | 依頼元のスキル。例:affinage。 |
source_ref | string | いいえ | プルリクエストのコメントまたは指摘の識別子。 |
symptom | string | はい | 1文で示した報告済みの失敗。 |
expect_exit | integer | いいえ | 失敗を示す終了コード。 |
expect_output | string | いいえ | 失敗時の出力に対する正規表現。 |
mode | string | いいえ | investigate または fix。既定値は fix です。 |
次のフラグを受け付けます。
--autoは、2つの質問を省略して各フェーズを実行します。--open-prは、Cook経由でPlateに進みます。--hardは、Cook経由で最終的なHard-cheeseゲートに進みます。
--open-pr と --hard は、すべての /cook および /mold コマンドに引き継いでください。
呼び出し元が指定したフラグを削除しないでください。
Cheeseは handoff_context.wiki_hits を渡すことがあります。
各ヒットには、page、line、why フィールドがあります。
フェーズ1の前に、各ヒットを読んでください。
仮説の優先順位を変えるヒットがあれば、その名前を示してください。
mode: investigate の依頼は、フェーズ2の後で終了します。
依頼元のスキルに reproduced、not-reproduced、または inconclusive を返してください。
調査依頼ではフェーズ4を開始しないでください。
フェーズ1:フィードバックループを構築する
バグを診断する前に、高速で信頼できる合否判定用のフィードバックループを構築します。 このフィードバックループは、以降のすべてのフェーズを制御します。
ループの選択肢と順序については、references/feedback-loops.md を読んでください。
失敗した境界に到達する最初の選択肢を選びます。
続行する前に、ループを改善します。
- セットアップと無関係な初期化を減らします。
- 症状そのものを確認します。
- 時間、乱数値、ファイル、ネットワークアクセスを制御します。
非決定的なバグ
再現率を50%より高くします。 トリガーを繰り返します。 負荷を追加します。 タイミングウィンドウを狭めます。 制御された遅延を追加します。
使用可能なループがない場合
使用可能なループを構築できない場合は停止します。
試した方法をそれぞれ列挙します。
再現環境へのアクセスをリクエストします。
または、キャプチャしたアーティファクト、あるいは一時的な本番環境の計測を行う許可をリクエストします。
status: needs-context: <the access you need> というハンドオフスラッグを記述します。
アクセスが提供されると、オーケストレーターがこの実行を再試行します。
ループなしで仮説を立てないでください。
Phase 2 に進む前に、次の条件を確認してください。
- ループを実行するたびに同じ結果になります。
- 不安定なループでは、50 パーセントを超える確率でバグが再現します。
- 人の操作なしに、1 つのコマンドでループを実行できます。
- ループで、報告された症状そのものを確認できます。
- ループが 30 秒未満で完了します。
5 秒未満で完了するループを目指してください。
Phase 2:バグを再現する
ループを 5 回実行します。
python3 skills/pasteurize/scripts/pasteurize.pyz repro-rerun \
--cmd "<repro-command>" --runs 5 \
--expect-output "<expected failure text>" --threshold 0.5 --timeout 30
予想される失敗モードを必ず指定してください。
出力が既知の失敗には --expect-output を使用します。
終了コードが既知の失敗には --expect-exit を使用します。
結果に reproduced: true が含まれていることを確認します。
決定論的なバグでは、matches が runs と等しいことを確認します。
results リストを読み、各実行で一致していることを確認します。
不安定なバグが 5 回の実行で再現しない場合は、--runs を増やします。
ループで予想される失敗が再現するまで、先に進まないでください。
無関係な失敗を再現として受け入れないでください。
症状の判定
仮説を立てる前に、症状を分類してください。
- スタックトレースが明確で、ループが安定している場合は、現在のモデルティアのまま続行します。
- 競合状態、モジュール間の障害、パフォーマンスのリグレッション、またはハイゼンバグの場合は、モデルティアを上げます。
モデルをアップグレードするには、ハーネスのコマンドを使用します。
Claude の場合は、/model opus を使用します。
続けて /effort を使用します。
Codex または OMP では、指定された同等のコマンドを使用します。
その他のホストでは、一般的なモデルアップグレードを使用します。
Phase 3:仮説を立てる
1 つを検証する前に、優先順位を付けた仮説を 3~5 個記述します。 各仮説について、検証可能な予測を示します。 予測を示せない仮説は破棄します。
次の形式を使用します。
<X>がバグの原因なら、<Y>を変更するとバグが解消し、<Z>を変更すると悪化します。
優先順位を付けたリストを handoff-gate.md で提示します。
ドメイン知識に基づいて順位を変更できます。
ユーザーが不在の場合、または --auto を使用している場合は、付けた順位のまま続行します。
Phase 4:計測を追加する
各プローブを Phase 3 の予測に対応付けます。 一度に変更する変数は 1 つだけにします。
ツールは次の順序で使用します。
- 環境が対応している場合は、デバッガーまたは REPL を使用します。
- 仮説を見分けられる境界に、対象を絞ったログを追加します。
- すべてのデータをログに記録して、後から検索することは避けてください。
この調査用に、a4f2 などのセッションタグを 1 つ選びます。
一時ログの先頭に、正確なトークン [DEBUG-a4f2] を付けます。
セッションタグをハンドオフスラッグに記録します。
セッションタグを使って、クリーンアップ時にすべての一時ログを検索します。
パフォーマンスのリグレッションでは、コードを変更する前にベースラインを計測します。 計測ハーネス、プロファイラー、またはクエリプランを使用します。 次に、失敗した範囲を二分探索します。
フェーズ 5:バグを修正する
修正前に回帰テストを追加します。 正しいテストシームが存在する場合にのみ、テストを追加します。
正しいシームでは、実際の呼び出し箇所で実際のバグを検証します。 実際のデータ経路と障害モードを使用します。 浅いシームやモックを使ったシームでは、誤った安心感が生じます。
シームがない場合は、アーキテクチャ上の問題として扱います。
引き継ぎスラッグに記録します。
該当する早期停止ステータスを記述します。
next: mold を設定します。
不適切なシームではテストを追加しないでください。
正しいシームが存在する場合は、次の手順を完了します。
- 最小再現を、そのシームで失敗するテストに変換します。
- テストを実行し、失敗を確認します。
- 失敗を修正できる最小限の本番コード変更を適用します。
- テストを実行し、成功を確認します。
- 元のフェーズ 1 のループを実行し、症状がないことを確認します。
修正に失敗した場合は、次の試行の前に変更を元に戻します。 修正の試行は、3 回失敗した時点で停止します。 フェーズ 3 に戻ります。 仮説を新たに順位付けしてリストを作成します。 新たな仮説がない限り、4 回目の試行は行わないでください。
新しい仮説が見つかった場合は、フェーズ 4 から再開します。
それ以外の場合は、修正試行の上限到達ステータスを記述します。
その後、next: mold を設定します。
より広範な変更は /cook に任せます。
それらの変更を引き継ぎスラッグに記録します。
フェーズ 6:ワークツリーを整理する
引き継ぎスラッグを記述する前に、このチェックリストを完了します。
- 元のループを実行し、バグがないことを確認します。
- 回帰テストを実行し、成功を確認します。
- 正しいシームがない場合は、テストシームがないことを記録します。
-
[DEBUG-...]の計測コードをすべて削除します。 - 一時的なハーネスとプロトタイプを削除します。
- 残したデバッグファイルがあれば、スラッグに記録します。
- 確認済みの仮説をスラッグに記録します。
セッションタグを指定して、計測コードのスイープを実行します。
python3 skills/pasteurize/scripts/pasteurize.pyz debug-tag-sweep \
--session-tag a4f2 --changed-only --root .
--session-tag は、トークン [DEBUG-a4f2] に完全一致します。
--changed-only は、このワークツリーで変更されたファイルをスキャンします。
このスイープでは、.cheese/、キャッシュ、実行ログなどのツール出力は除外されます。
スイープは files と total を含む JSON オブジェクトを 1 つ出力し、完了すると 0 で終了します。
total が 0 の場合、スイープでタグは見つかりませんでした。
total が 0 以外の場合、files に列挙されたタグが見つかっています。
続行する前に、列挙されたタグをそれぞれ削除してください。
終了ステータスが 0 以外の場合は入力エラーです。stderr の行は error と exit_code を含む JSON です。
クリーンなワークツリーの証明には、広範囲を対象とする --tags スキャンを使用しないでください。
このバグを防ぐためにできることを特定します。 必要なアーキテクチャ作業をスラッグに記録します。 この推奨事項は修正を適用した後に提示します。
完了したスラッグを /cook <slug> --auto に渡します。
Cook は差分を確認し、cook (⇄ press) -> age -> cure を実行します。
Pasteurize は変更をコミットせず、プルリクエストも作成しません。
ファンアウトの規模設定
/pasteurize は現在、エージェントを起動しません。
size_pasteurize_fanout() は、src/easy_cheese/shared/fanout/pasteurize_route.py で将来のポリシーを定義しています。
このポリシーは、疑わしい範囲、つまり最後に正常だったリビジョンから HEAD までの review_surface を降順で読み取ります。
証拠スコアが低いほど探索空間が広いことを示すため、エージェント数が増えます。
| バグの形状 | 範囲 | 再現性 | エージェント数 |
|---|---|---|---|
| リグレッション | 狭い、スコア < 250 | 決定的 | 1 |
| リグレッション | 狭い、スコア < 250 | 非決定的 | 2 |
| リグレッション | 広い、スコア > 250 | 決定的 | 2 |
| リグレッション | 広い、スコア > 250 | 非決定的 | 3 |
| リグレッション | スコアなし | 決定的 | 3 |
| リグレッション | スコアなし | 非決定的 | 5 |
| 競合状態、ヒーゼンバグ、またはパフォーマンスのリグレッション | 任意 | 任意 | 3 |
| コールドバグ | スコアなし | 決定的 | 3 |
| コールドバグ | スコアなし | 非決定的 | 5 |
スコア 250 が、狭い範囲の基準です。
レビュー担当者がこれらの定数を検討しました。実行時の測定は行われていません。 レビュー担当者が使用するしきい値は、リポジトリのコミット 30 件を基準にしています。 これらの定数には実行履歴がありません。 名前付き定数は調整可能なままにしてください。 実際の実行データが得られたら見直してください。
バンドルのみを使うホストは、次のコマンドでポリシーを呼び出せます。
python3 skills/pasteurize/scripts/pasteurize.pyz pasteurize-route <request.json>
このコマンドは JSON を読み込み、JSON を出力します。
age-route のバンドル規約に従います。
優先ツール
| 必要な作業 | 優先ツール | フォールバック |
|---|---|---|
| コード検索と影響範囲の調査 | セマンティックな呼び出し元・依存関係検索 | 精度に関する警告を付けた範囲指定テキスト検索 |
| コードの読み取り | 書き込みバックエンドからの新しい範囲指定読み取り | 安定した行アンカーを使った範囲指定読み取り |
| 計測コードの編集 | 古い内容を安全に検出するアンカー付き編集 | 古い書き込みを検出する LSP またはスナップショット編集 |
| GitHub のコンテキスト | gh | ローカルの Git 履歴またはユーザーのリンク |
| 外部確認 | /briesearch | 明確に仮定と明記した内容 |
オプションのツールが利用できない場合も、診断を続けてください。
出力
次の項目を含む短いレポートを返してください。
- 特定した原因と、その確信度。
- ループコマンドと、確認された結果。
- 検討した仮説と、確認された仮説。
- 回帰テストのパス。
- 変更した本番コードの行。
- 計測コードと一時ファイルのクリーンアップ状況。
- 次のコマンド
/cook <slug> --auto。
確信度には <certain>、<speculating>、または <don't know> を使ってください。
ハンドオフのスラッグ
ハンドオフのスラッグを .cheese/pasteurize/<slug>.md に書き込んでください。
次の最小形式を使ってください。
status: <canonical status field>
next: cook | mold | done
artifact: <path-to-richer-report-if-any>
<one-line orientation: what pasteurize confirmed>
cause: <one-sentence named cause>
loop: <command or repro path>
session_tag: <the Phase 4 session tag, or "none">
seam: <regression-test path:line, or "none — architectural follow-up">
fix: <production diff footprint, e.g. "src/foo.ts:42">
follow_up: <architectural follow-up note, or "none">
4 行目にはオリエンテーションを記載してください。
パーサーはオリエンテーションより前に status、next、artifact を読み取ります。
プリアンブルでは、これ以外のキー付き行を読み取りません。
すべての診断フィールドは、1 行の空行を挟んで本文に記載してください。
詳細なレポートには artifact を使い、診断には使わないでください。
ハンドバック契約に従ってください。
次のステータスを使ってください。
| ステータス | 判定 | 用途 |
|---|---|---|
ok | 続行 | テスト、再現、クリーンアップの確認が成功した場合。 |
ok-with-concerns: <reason> | 続行 | 診断は完了していますが、作業に Mold が必要な場合。 |
needs-context: <reason> | 再試行 | 実行に再現アクセスまたは取得済みの成果物が必要な場合。 |
halt: <reason> | 停止 | 実行を続けられず、後続のルートもない場合。 |
オーケストレーターは halt の後の next: を無視します。
halt のスラッグではルートを指定しないでください。
標準チェーンでは next: cook を設定してください。
診断にアーキテクチャ仕様が必要な場合は next: mold を設定してください。
リポジトリの変更が不要な外部要因が原因の場合は next: done を設定してください。
ハンドオフ
パイプライン: cheese -> pasteurize -> cook --auto (⇄ press) -> age -> cure -> plate
レポートとスラッグを書き込んだら、handoff-gate.md を通じて次の選択肢を提示してください。
- 検証して続行:
/cook <slug> --auto。 - 自動チェーンを使わずに検証:
/cook <slug>。 - アーキテクチャ作業を仕様化:
/mold <slug>。 - 停止: 修正をワークツリーに残します。
status: ok の場合は、最初の選択肢を推奨してください。
ユーザーが選択するまで、どの選択肢も開始しないでください。
--auto モードではこの質問を省略してください。
自動モード
--auto では Phase 3 の順位付けに関する質問を省略します。
Phase 6 のハンドオフに関する質問も省略します。
クリーンアップの後に /cook <slug> --auto を開始します。
Phase 4 と Phase 5 は省略しません。
早期停止条件
次のいずれかに該当する場合は停止してください。
- Phase 1 で使用可能なループを作成できない。
- Phase 3 を 2 ラウンド実施して、すべての仮説が否定される。
- Phase 5 で適切な回帰テストの接点が見つからない。
- 最小限の修正によって、pasteurize の対象範囲外にある無関係なテストが失敗する。
- 修正に 3 回失敗し、すべての仮説を検証し尽くす。
適切な接点が見つからない場合は、status: ok-with-concerns: no correct regression-test seam と記載してください。
修正を試し尽くした場合は、status: ok-with-concerns: fix attempts exhausted — architectural re-examination needed と記載してください。
どちらの場合も next: mold を設定してください。
再現に必要なアクセスがない場合は、status: needs-context: <the access you need> と記載してください。
必ずスラッグを書き、レポートを提示してください。
証拠を推測で置き換えないでください。
ルール
- フェーズ 1 を省略しないでください。
- 再現ループを実行せずに仮説を立てないでください。
- フェーズ 5 では、回帰テストと最小限の本番コードのみを変更してください。
- 引き渡し前に、すべての
[DEBUG-...]タグを削除してください。 - Pasteurize が変更を出荷すると主張しないでください。
- 次の完了表明を使用してください:「原因を特定、回帰テストは成功、修正はツリー内、チェーンに進む準備完了」。
- スラッグにアーキテクチャ上のギャップを記録してください。
参考資料
- 生成されたバンドルのコマンド:
references/commands.md。