mcpField
P
pasteurize

pasteurize

github.com/paulnsorensen開発19652 回インストール6 日前に更新
リポジトリ

pasteurize について

pasteurize は再現が難しいソフトウェアの不具合を調査するための、手順化されたデバッグスキルです。仮説を立てる前に再現ループを構築・検証し、計測、回帰テスト、修正、後片付けを導きます。

主な機能

  1. 01再現性のある不具合ループの構築
  2. 02複数回実行による想定症状の確認
  3. 03検証可能な仮説の順位付け
  4. 04対象を絞った計測と修正の案内
  5. 05一時的なデバッグタグの検査

活用シーン

  1. 01不安定またはタイミング依存の不具合調査
  2. 02本番コードの変更前にリグレッションを追跡
  3. 03回帰テストと元のループによる修正確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/paulnsorensen/easy-cheese --skill pasteurize

インストール後、Claude Code で/pasteurizeを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

wedge.toml
references/
commands.md
feedback-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からの調査依頼を受け付けます。

調査依頼では、次のフィールドを使用します。

フィールド型必須意味
sourcestringはい依頼元のスキル。例:affinage。
source_refstringいいえプルリクエストのコメントまたは指摘の識別子。
symptomstringはい1文で示した報告済みの失敗。
expect_exitintegerいいえ失敗を示す終了コード。
expect_outputstringいいえ失敗時の出力に対する正規表現。
modestringいいえ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 つだけにします。

ツールは次の順序で使用します。

  1. 環境が対応している場合は、デバッガーまたは REPL を使用します。
  2. 仮説を見分けられる境界に、対象を絞ったログを追加します。
  3. すべてのデータをログに記録して、後から検索することは避けてください。

この調査用に、a4f2 などのセッションタグを 1 つ選びます。 一時ログの先頭に、正確なトークン [DEBUG-a4f2] を付けます。 セッションタグをハンドオフスラッグに記録します。 セッションタグを使って、クリーンアップ時にすべての一時ログを検索します。

パフォーマンスのリグレッションでは、コードを変更する前にベースラインを計測します。 計測ハーネス、プロファイラー、またはクエリプランを使用します。 次に、失敗した範囲を二分探索します。

フェーズ 5:バグを修正する

修正前に回帰テストを追加します。 正しいテストシームが存在する場合にのみ、テストを追加します。

正しいシームでは、実際の呼び出し箇所で実際のバグを検証します。 実際のデータ経路と障害モードを使用します。 浅いシームやモックを使ったシームでは、誤った安心感が生じます。

シームがない場合は、アーキテクチャ上の問題として扱います。 引き継ぎスラッグに記録します。 該当する早期停止ステータスを記述します。 next: mold を設定します。 不適切なシームではテストを追加しないでください。

正しいシームが存在する場合は、次の手順を完了します。

  1. 最小再現を、そのシームで失敗するテストに変換します。
  2. テストを実行し、失敗を確認します。
  3. 失敗を修正できる最小限の本番コード変更を適用します。
  4. テストを実行し、成功を確認します。
  5. 元のフェーズ 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 が変更を出荷すると主張しないでください。
  • 次の完了表明を使用してください:「原因を特定、回帰テストは成功、修正はツリー内、チェーンに進む準備完了」。
  • スラッグにアーキテクチャ上のギャップを記録してください。

参考資料

コメント