melech-debug-mode について
コーディングエージェント向けに、ローカルブラウザー UI での再現を起点とするデバッグ手順を定めたスキルです。ブラウザーで得た E2E の証拠と、補助的なテストや直接呼び出しを区別します。
主な機能
- 01ローカル UI での再現を優先
- 02一時コレクターでプローブイベントを収集
- 03実行環境でのプローブ読み込みを確認
- 04観測した証拠に基づいて対応
- 05プローブを除去してセッションを終了
活用シーン
- 01ローカル Web アプリの操作障害を調査
- 02コード変更後のブラウザー動作を検証
- 03E2E 証拠と補助診断を区別
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ adird/ agent-shell-hamelech --skill melech-debug-modeインストール後、Claude Code で/melech-debug-modeを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.mdassets/collector.pyscripts/debug_session.pydm.shinstall-dm.shtests/test_debug_session.py詳細
デバッグモード
ユーザーが依頼したワークフローでは、次のプロトコルに従います。
choose browser driver → attach if autopilot → define one complete attempt
→ start collector → add probes → prove probes loaded → run E2E → read evidence
→ act on evidence → rerun E2E if code changed → clean up
E2E の境界は、ブラウザー内のローカル UI です。ユニットテスト、インテグレーションテスト、AI テスト、テストハーネスの実行は、実際のモデル、ツール、サンドボックス、ファイルシステム、バックエンドを使用していても、E2E には該当しません。直接の呼び出し、スクリプト、合成リクエスト、分離されたエンドポイントも同様です。
最初にブラウザーで試す前に、テストハーネスを作成したり実行したりしないでください。テストと直接の呼び出しは、ブラウザーで再現した後に行う補足的な診断に限ります。依頼された動作をローカル UI から実行できない場合は、このスキルでは E2E の手順を提供していないと伝え、テストハーネスを E2E として扱わないでください。
1. ドライバーを選択する
- ローカル UI のワークフローでは、デフォルトで autopilot を使用します。
- ユーザーが自分で操作する、主導権を握る、または
proceedを使うと明示した場合 → manual。 - ユーザーがブラウザーの操作を拒否した場合、対象のタブが曖昧または安全でない場合、対象が本番環境と思われる場合、または再試行してもアタッチできない場合 → manual。
通常のローカル UI について、どちらを使うかユーザーに尋ねないでください。
autopilot では、診断の近道を使う前に、インストール済みの melech-live-browser/SKILL.md を読み、その Chrome の同意通知を表示して、アタッチフローを開始します。見つからない場合は、次の選択肢を提示します。
npx skills add https://github.com/AdirD/agent-shell-hamelech --skill melech-live-browser
インストールするか、manual に切り替えるかを尋ねます。別のブラウザーやプロファイルで代用しないでください。
autopilot は必ず、ユーザーに chrome://inspect/#remote-debugging でリモートデバッグを有効にし、Chrome のプロンプトが表示されたら Allow をクリックするよう依頼するところから開始します。アタッチに失敗した場合は、その依頼をもう一度行い、1 回だけ再試行します。manual は、その再試行に失敗した場合に限り、フォールバックとして使用します。
manual でも、実行中のローカル UI と同じプローブを使用します。ユーザーにリセット手順、操作手順、結果を判定する条件を伝え、1 回再現した後に正確に proceed と返信するよう依頼してから、そこで止めて返答を待ちます。その返信を受け取ってから、証拠を読み取ります。
2. 1 回の試行を定義する
次の内容を明示します。
- リセット方法と開始状態
- 正確な操作手順
- ユーザーの依頼に応じて結果を判定するための、観測可能な内容
- 結果を見分けるために必要なプローブ(最大 5 つ)
3. コレクターを起動する
このスキルのインストール先ディレクトリを特定し、python3 と portless が存在することを確認します。Portless が見つからない場合は、停止して次の内容を依頼します。
npm install -g portless
初回セットアップが必要な場合は portless doctor を実行し、その後、次を実行します。
source <skill-dir>/scripts/dm.sh
dm start
dm は python3 <skill-dir>/scripts/debug_session.py を実行するソース済みシェル関数です。後続の手順で dm が未定義と報告された場合は、dm.sh を再度 source するか、そのパスを直接呼び出してください。
| コマンド | 用途 |
|---|---|
dm start | 一時コレクターを 1 つ起動します |
dm status <session-dir> | そのセッションのメタデータとプロセスの稼働状況を確認します |
dm logs <session-dir> [--run ID] [--after-seq N] [--tail N] | コンパクトな JSONL を読み取ります。1 行につき完全なイベントが 1 件あります |
dm logs <session-dir> --pretty | 読みやすい複数行形式のイベントを表示します |
dm stop <session-dir> | そのセッションを終了します |
dm doctor --once | すべての稼働中セッションの JSON スナップショットを取得します |
doctor には必ず --once を付けてください。引数なしの dm doctor(および引数なしの dm)は、ユーザー自身のターミナルで curses TUI を起動するため、非対話型シェルがハングまたはクラッシュします。
dm start は、以降の各手順で必要となる session_id、session_dir、log_endpoint、health_url、events_file、backend_host/backend_port を出力します。これらを保存し、アプリケーションコードを編集する前にコレクターが応答することを確認します。
curl -s "<health_url>" # {"ok":true,"entries":0}
health_url と log_endpoint は Portless 経由でルーティングされます。プローブを実行するランタイムからそのルートに到達できない場合も、同じコレクターが http://<backend_host>:<backend_port> で応答します。その場合はオリジンのみを置き換え、log_endpoint の /log/<token> パスは維持してください。
コレクターはローカルに保ちます。LAN モード、トンネル、Tailscale、Funnel、ngrok、その他のリモート公開は決して有効にしないでください。
4. プローブを追加する
実行するべきか、しないべきかを決める条件、変換の直前の値、境界の入力と出力、エラーパスを手掛かりに、設置場所を決めます。対象の問いを扱うレイヤーに計測を追加します。ブラウザーワークフローの場合、レンダリングと操作にはページまたはコンポーネントの状態を、永続化、検証、連携にはサーバーハンドラーを使います。
すでに実行中の各対象について、そのライフサイクルに合った利用可能な鮮度の基準点を記録します。プロセスの起動時点、ビルド ID、またはビルド/再読み込みログのカーソルです。編集後に実行する、ソースを読み込むワンショットのコマンドには事前の基準点は必要ありません。
セッション トークンが埋め込まれた log_endpoint に、観測ごとに小さな JSON オブジェクトを 1 つずつ、返されたとおりに POST します。
{
"run": "run-1",
"probe": "checkout-before-submit",
"hypothesis": "save commits exactly once",
"data": { "isDisabled": true, "itemCount": 2 }
}
失敗しても製品の動作に影響しないよう、送信後は結果を待たずに処理します。
// DEBUG_MODE:<session-id>:checkout-before-submit
void fetch("<log-endpoint>", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
run: "run-1",
probe: "checkout-before-submit",
hypothesis: "save commits exactly once",
data: { isDisabled, itemCount: items.length },
}),
}).catch(() => {});
ペイロードの形、マーカーコメント、限定的なフィールド選択、失敗を無視する処理を維持しながら、対象言語に合わせて書き換えます。送信するのは、ブール値、カウント、列挙値、開発環境で安全な ID、短い要約だけです。認証情報、トークン、Cookie、認可ヘッダー、個人データ、完全な本文、無関係な状態は絶対に送信しないでください。
結果を待たずに送信するプローブでは拒否を検知できないため、試行前に実際のペイロード形式を使って、コレクターへの送信が一度成功することを確認してください。
curl -s -X POST "<log_endpoint>" -H 'content-type: application/json' \
-d '{"run":"run-0","probe":"delivery-check","data":{"ok":true}}'
# {"accepted":true,"seq":1}
それ以外の応答は、コードパスが実行されなかったのではなく、コレクターがイベントを拒否したことを意味します。原因には、content-type の欠落、オブジェクト以外または不正な形式の本文、64 KB を超えるペイロード、URL またはトークンの誤り、sensitive_field_rejected などがあります。最後のケースでは、キーが(大文字小文字とハイフンを無視して)どの階層でも token、secret、password、cookie、authorization、api_key、access_token などの認証情報名と完全一致するイベントが破棄されます。観測を削除するのではなく、フィールド名を hasSessionToken のように内容が分かる名前に変更してください。
一時的な編集にはすべて DEBUG_MODE:<session-id>:<probe-id> を付け、変更したファイルを記録します。計測が有効であることを証明するために必要な、最も低コストのコンパイル、型チェック、構文チェックだけを実行します。そのチェックで生成されたプローブイベントは E2E の証拠にはなりません。プローブを読み込むテストファイルやハーネスは作成しないでください。ブラウザーワークフローを提供しているものと同じ開発サービスでプローブを読み込みます。
E2E の前に、長時間実行される各対象または事前ビルド済みの各対象がプローブを読み込んだことを証明してください。プローブの編集後に生成され、そのソースまたはアーティファクトに結び付いた証拠が必要です。編集対象の新しいビルド/HMR/再起動マーカー、編集後に起動したソース読み込みプロセス、またはプローブ固有の読み込みイベントが該当します。事前ビルド済みのランタイムでは、アーティファクトが編集後にビルドされたことと、プロセスがそれを読み込んだことの両方を確認してください。ターミナルの mtime が変わったことや、古い再起動ログは鮮度の証明になりません。Jest、Vitest、AI ハーネス、その他のテストプロセスでは、ブラウザーを提供するランタイムがプローブを読み込んだ証明にはなりません。
ランタイムが古い場合、既存のトレース、永続化された入力、監査記録、またはその他の信頼できる境界記録は、同じ決定要因を記録している場合に限り、プローブの代わりに使用できます。該当する記録を正確に示してください。アプリの説明文や UI の動作からの推測は認められません。
それ以外の場合は、安全なときに限り、対象サービスだけを再起動します。そのプロセスをユーザーが管理している場合、または再起動によって進行中の作業が中断される可能性がある場合は、そこで中断して次のように確認してください。
<service>はプローブ追加前のコードでまだ実行中です。再ビルドまたは再起動してから、続行できるようにお知らせください。
シェルでの送信確認によって証明できるのは、コレクターが動作することだけです。
5. ブラウザーで試行する
最初は run-1 を使い、再試行、補足診断、変更後の検証ごとに実行 ID を増やします。試行を完了するたびに、次を読み取ります。
dm logs <session-dir> --run <run-id>
各行はエンベロープです。payload にオブジェクトが入り、seq と received_at が付加されます。既定の出力形式は JSONL です。各行は完全な JSON オブジェクト 1 つで、個別に解析できます。最新の試行で追加された内容だけを見るには --after-seq、実行ログが多い場合は --tail を使います。--pretty は人が読む場合に限って使用してください。
自動実行
melech-live-browser を使って既存のアプリのタブを選択し、スナップショットを取得してから、完全な試行をちょうど 1 回実行し、その実行結果を読み取ります。明示された結果の確認に必要な場合に限り、ライブブラウザーを通じてコンソールまたはネットワークの証拠を関連付けます。スナップショットだけから結論を出してはいけません。proceed を求めてはいけません。アタッチまたはタブの選択に失敗した場合は、手動モードに切り替えます。
手動
手動モードが有効であることをユーザーに伝え、定義済みのリセット手順、操作、判定結果を示し、1 回試行した後に正確に proceed と返信するよう求めます。その後は停止します。proceed を受け取った後に限り、その実行結果を読み取ります。
6. 証拠に基づいて対応する
結果を裏付けるイベントの順序と値を示します。相関関係から原因を推測してはいけません。
- 証拠を使って、ユーザーが求めた次のアクションを範囲を広げずに実行します。
- 証拠が不完全 → 最小限のプローブを見直し、同じ E2E ドライバーを使って新しい実行 ID で再実行します。
- 証拠計画に含まれるプローブから予期せずイベントが記録されない → まず、プローブを編集した後に計測対象のランタイムが再ビルドまたは再起動されたことを確認します。次に、
health_urlの curl またはdm doctor --onceでコレクターが稼働していることを確認し(dm statusが報告するのはプロセスの生存状態のみです)、配信確認を再実行します。コレクターはすでにクロスオリジンの POST を許可しているため、ページ側のプローブではアプリの CSPconnect-srcまたは到達不能なルートを疑います。修正してから E2E を再実行します。 - コードを変更した → 関連するプローブを維持し、クリーンアップの前に同じ E2E ワークフローを再実行します。
補足診断
最初のブラウザー E2E 試行の後に限り、焦点を絞ったテスト、直接呼び出し、その場限りの診断スクリプト、エンドポイントリクエスト、または合成リクエストを使って、より限定的な疑問を切り分けてもかまいません。これらには別の実行 ID を付けて補足として明示します。E2E のゲートや変更後の検証を満たすものとして扱ってはいけません。
7. クリーンアップ
結論が出た E2E 結果でコード変更がない場合、変更後の E2E 検証が成功した場合、または中止した場合は、次の手順を実行します。
DEBUG_MODE:<session-id>:のプローブとデバッグ専用の変更をすべて削除します。- 変更したファイルを検索して
DEBUG_MODE:を確認し、差分を調べます。 - ユーザー所有のタブを閉じずに、ブラウザー操作を停止します。
dm stop <session-dir>を実行し、removed: trueを確認します。
ティアダウンに失敗した場合は、セッションディレクトリと PID を報告します。プロセスを広範囲に終了したり、Portless の広範なクリーンアップを実行したりしてはいけません。処理が中断された場合は、dm status、dm logs、または dm doctor --once で保存済みの session_dir を復旧し、このクリーンアップを最後まで実行するか、中止します。